diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.PersonalityDecisions.cs b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.PersonalityDecisions.cs index a455c7f..d85a5b9 100644 --- a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.PersonalityDecisions.cs +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.PersonalityDecisions.cs @@ -169,14 +169,24 @@ public sealed partial class JiboInteractionService var tenantRememberedName = personalMemoryStore.GetName(ResolveTenantScope(turn)); if (!string.IsNullOrWhiteSpace(tenantRememberedName)) return ToDisplayName(tenantRememberedName); - if (!string.IsNullOrWhiteSpace(presence.PrimaryPersonId) && - presence.LoopUserFirstNames.TryGetValue(presence.PrimaryPersonId, out var firstName) && + var primaryPersonId = presence.PrimaryPersonId; + if (CanUseLoopFirstNameFallback(presence) && + !string.IsNullOrWhiteSpace(primaryPersonId) && + presence.LoopUserFirstNames.TryGetValue(primaryPersonId, out var firstName) && !string.IsNullOrWhiteSpace(firstName)) return ToDisplayName(firstName); return null; } + private static bool CanUseLoopFirstNameFallback(GreetingPresenceProfile presence) + { + if (string.IsNullOrWhiteSpace(presence.PrimaryPersonId)) return false; + if (presence.PeoplePresentIds.Count > 1) return false; + + return true; + } + private static string ToDisplayName(string value) { var trimmed = value.Trim(); diff --git a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs index 87d1b74..53b4e8d 100644 --- a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs +++ b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs @@ -349,6 +349,31 @@ public sealed class JiboInteractionServiceTests greeting.LastGreetingIntent == "proactive_greeting"); } + [Fact] + public async Task BuildDecisionAsync_TriggerWithMultiplePeople_DoesNotBorrowLoopFirstName() + { + var cloudStateStore = new InMemoryCloudStateStore(); + var service = CreateService(cloudStateStore: cloudStateStore); + + var decision = await service.BuildDecisionAsync(new TurnContext + { + RawTranscript = string.Empty, + NormalizedTranscript = string.Empty, + Attributes = new Dictionary + { + ["messageType"] = "TRIGGER", + ["triggerSource"] = "PRESENCE", + ["context"] = + """{"runtime":{"perception":{"speaker":"person-1","peoplePresent":[{"id":"person-1"},{"id":"person-2"}]},"loop":{"users":[{"id":"person-1","firstName":"jake"},{"id":"person-2","firstName":"sam"}]}}}""" + } + }); + + Assert.Equal("proactive_greeting", decision.IntentName); + Assert.DoesNotContain("Jake", decision.ReplyText, StringComparison.Ordinal); + Assert.DoesNotContain("Sam", decision.ReplyText, StringComparison.Ordinal); + Assert.Contains("I am glad to see you", decision.ReplyText, StringComparison.OrdinalIgnoreCase); + } + [Fact] public async Task BuildDecisionAsync_TriggerInTheMorning_UsesGoodMorningProactiveTone() {