From 6c62e48495b7091590663d4f641ba2a6cd886eca Mon Sep 17 00:00:00 2001 From: Jacob Dubin Date: Tue, 21 Apr 2026 23:27:18 -0500 Subject: [PATCH] more fixes --- .../Services/JiboInteractionService.cs | 8 +++-- .../WebSockets/JiboInteractionServiceTests.cs | 32 +++++++++++++++++++ .../WebSockets/JiboWebSocketServiceTests.cs | 28 ++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs index 479be19..9e097a9 100644 --- a/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs +++ b/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/JiboInteractionService.cs @@ -839,7 +839,9 @@ public sealed class JiboInteractionService( private static string ResolveAmPm(string token) { - return token.StartsWith("p", StringComparison.OrdinalIgnoreCase) ? "pm" : "am"; + var normalized = token.Replace(" ", string.Empty, StringComparison.Ordinal) + .Replace(".", string.Empty, StringComparison.Ordinal); + return normalized.StartsWith("p", StringComparison.OrdinalIgnoreCase) ? "pm" : "am"; } private static bool IsTimerRequest(string loweredTranscript) @@ -971,11 +973,11 @@ public sealed class JiboInteractionService( private sealed record ClockAlarmValue(string Time, string AmPm); private static readonly Regex SplitAlarmPattern = new( - @"\b(?\d{1,2}|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)(?:[:\s-](?\d{2}|[a-z\-]+(?:\s+[a-z\-]+)?))?\s*(?a\.?m\.?|p\.?m\.?)?\b", + @"\b(?\d{1,2}|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)(?:[:\s-](?\d{2}|[a-z\-]+(?:\s+[a-z\-]+)?))?\s*(?a[\s\.]*m\.?|p[\s\.]*m\.?)?\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled); private static readonly Regex CompactAlarmPattern = new( - @"\b(?\d{3,4})\s*(?a\.?m\.?|p\.?m\.?)?\b", + @"\b(?\d{3,4})\s*(?a[\s\.]*m\.?|p[\s\.]*m\.?)?\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled); private static readonly (string Phrase, string Station)[] RadioGenreAliases = diff --git a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs index 8d4b0d9..4c39c9e 100644 --- a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs +++ b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboInteractionServiceTests.cs @@ -336,6 +336,38 @@ public sealed class JiboInteractionServiceTests Assert.Equal("am", decision.SkillPayload["ampm"]); } + [Fact] + public async Task BuildDecisionAsync_SetAlarmForTenTwentyFivePm_ParsesPmSuffix() + { + var service = CreateService(); + + var decision = await service.BuildDecisionAsync(new TurnContext + { + RawTranscript = "set an alarm for 10:25 pm", + NormalizedTranscript = "set an alarm for 10:25 pm" + }); + + Assert.Equal("alarm_value", decision.IntentName); + Assert.Equal("10:25", decision.SkillPayload!["time"]); + Assert.Equal("pm", decision.SkillPayload["ampm"]); + } + + [Fact] + public async Task BuildDecisionAsync_SetAlarmForTenTwentyFiveSpacedPm_ParsesPmSuffix() + { + var service = CreateService(); + + var decision = await service.BuildDecisionAsync(new TurnContext + { + RawTranscript = "set an alarm for 10 25 p m", + NormalizedTranscript = "set an alarm for 10 25 p m" + }); + + Assert.Equal("alarm_value", decision.IntentName); + Assert.Equal("10:25", decision.SkillPayload!["time"]); + Assert.Equal("pm", decision.SkillPayload["ampm"]); + } + [Fact] public async Task BuildDecisionAsync_TimerValueFollowUp_ParsesBareDuration() { diff --git a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboWebSocketServiceTests.cs b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboWebSocketServiceTests.cs index 09f6a05..050ef0c 100644 --- a/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboWebSocketServiceTests.cs +++ b/OpenJibo/tests/Jibo.Cloud.Tests/WebSockets/JiboWebSocketServiceTests.cs @@ -533,6 +533,34 @@ public sealed class JiboWebSocketServiceTests Assert.Equal("am", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("ampm").GetString()); } + [Fact] + public async Task ClientAsr_SetAlarmForTenTwentyFivePm_ParsesAlarmTimeWithPm() + { + await _service.HandleMessageAsync(new WebSocketMessageEnvelope + { + HostName = "neo-hub.jibo.com", + Path = "/listen", + Kind = "neo-hub-listen", + Token = "hub-clock-pm-alarm-token", + Text = """{"type":"LISTEN","transID":"trans-clock-pm-alarm","data":{"rules":["globals/global_commands_launch"]}}""" + }); + + var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope + { + HostName = "neo-hub.jibo.com", + Path = "/listen", + Kind = "neo-hub-listen", + Token = "hub-clock-pm-alarm-token", + Text = """{"type":"CLIENT_ASR","transID":"trans-clock-pm-alarm","data":{"text":"set an alarm for 10:25 pm"}}""" + }); + + Assert.Equal(4, replies.Count); + + using var listenPayload = JsonDocument.Parse(replies[0].Text!); + Assert.Equal("10:25", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("time").GetString()); + Assert.Equal("pm", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("ampm").GetString()); + } + [Fact] public async Task ClientAsr_TimerValueFollowUp_ParsesBareDurationIntoClockStartIntent() {