Compare commits
4 Commits
b595766ac9
...
6c62e48495
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6c62e48495 | ||
|
|
1f4adc8292 | ||
|
|
c74da1955b | ||
|
|
685d1515f6 |
@@ -181,7 +181,8 @@ Latest clock discovery findings:
|
|||||||
|
|
||||||
- `@be/clock` is a real local skill with `clock`, `timer`, and `alarm` domains.
|
- `@be/clock` is a real local skill with `clock`, `timer`, and `alarm` domains.
|
||||||
- Menu launches use `intent = "menu"` with `entities.domain` set to the target sub-area.
|
- Menu launches use `intent = "menu"` with `entities.domain` set to the target sub-area.
|
||||||
- Direct timer and alarm actions use `timerValue` and `alarmValue` utterances, not a generic chat path.
|
- The `jibo test 15` bundle shows stock OS 1.9 rejecting our older top-level `timerValue` launch with `found no matching transition`, so the safer cloud contract is a stock-style `start` intent with the timer/alarm entities attached.
|
||||||
|
- The same bundle also shows local follow-up rules like `clock/timer_set_value`, so bare replies such as `five minutes` or `ten twenty five` need to be parsed when the robot is already collecting a timer/alarm value.
|
||||||
- The newest `.NET` pass now routes `open the clock` into the direct `askForTime` clock-view path, moves plain time/date/day questions onto stock-shaped local `@be/clock` handoffs, and keeps malformed timer/alarm requests on a clarification reply path instead of generic chat echo.
|
- The newest `.NET` pass now routes `open the clock` into the direct `askForTime` clock-view path, moves plain time/date/day questions onto stock-shaped local `@be/clock` handoffs, and keeps malformed timer/alarm requests on a clarification reply path instead of generic chat echo.
|
||||||
|
|
||||||
Latest photo discovery findings:
|
Latest photo discovery findings:
|
||||||
|
|||||||
@@ -127,9 +127,11 @@ Parallel tags:
|
|||||||
- Current evidence:
|
- Current evidence:
|
||||||
- [protocol-inventory.md](C:/Projects/JiboExperiments/OpenJibo/docs/protocol-inventory.md) already tracks menu intents for `askForTime`, `askForDate`, `timerValue`, and `alarmValue`
|
- [protocol-inventory.md](C:/Projects/JiboExperiments/OpenJibo/docs/protocol-inventory.md) already tracks menu intents for `askForTime`, `askForDate`, `timerValue`, and `alarmValue`
|
||||||
- `@be/clock` exists in the robot skill inventory
|
- `@be/clock` exists in the robot skill inventory
|
||||||
- `JiboOs` shows `@be/clock` branches on `entities.domain = clock | timer | alarm`, uses `intent = menu` for menu launches, and accepts direct `timerValue` / `alarmValue` utterances with structured entities
|
- `JiboOs` shows `@be/clock` branches on `entities.domain = clock | timer | alarm`, uses `intent = menu` for menu launches, and has distinct local value-collection rules such as `clock/timer_set_value`
|
||||||
- Implementation notes:
|
- [artifact-output/jibo-test-15](C:/Projects/JiboExperiments/artifact-output/jibo-test-15) shows stock OS 1.9 rejecting our older `timerValue` top-level launch with `found no matching transition`, which points to a stock-style `start` flow plus local follow-up value rules instead
|
||||||
- compare our custom time/date path against actual menu payloads
|
- Implementation notes:
|
||||||
|
- compare our custom time/date path against actual menu payloads
|
||||||
|
- keep direct clock/date/day local, but treat timer and alarm as a two-part flow: stock start intent plus bare follow-up parsing on `clock/*_set_value`
|
||||||
- decide whether timer and alarm should stay robot-local with cloud acknowledgement, or whether cloud needs to shape the launch and follow-up turns
|
- decide whether timer and alarm should stay robot-local with cloud acknowledgement, or whether cloud needs to shape the launch and follow-up turns
|
||||||
- Progress so far:
|
- Progress so far:
|
||||||
- voice `open the clock` now routes to the direct local `askForTime` clock-view path instead of the broader clock menu
|
- voice `open the clock` now routes to the direct local `askForTime` clock-view path instead of the broader clock menu
|
||||||
|
|||||||
@@ -23,7 +23,17 @@ public sealed class JiboInteractionService(
|
|||||||
var clientEntities = ReadEntities(turn);
|
var clientEntities = ReadEntities(turn);
|
||||||
var isYesNoTurn = IsYesNoTurn(turn);
|
var isYesNoTurn = IsYesNoTurn(turn);
|
||||||
|
|
||||||
var semanticIntent = ResolveSemanticIntent(lowered, clientIntent, clientRules, listenRules, clientEntities, isYesNoTurn);
|
var isTimerValueTurn = IsClockTimerValueTurn(clientRules, listenRules);
|
||||||
|
var isAlarmValueTurn = IsClockAlarmValueTurn(clientRules, listenRules);
|
||||||
|
var semanticIntent = ResolveSemanticIntent(
|
||||||
|
lowered,
|
||||||
|
clientIntent,
|
||||||
|
clientRules,
|
||||||
|
listenRules,
|
||||||
|
clientEntities,
|
||||||
|
isYesNoTurn,
|
||||||
|
isTimerValueTurn,
|
||||||
|
isAlarmValueTurn);
|
||||||
return semanticIntent switch
|
return semanticIntent switch
|
||||||
{
|
{
|
||||||
"joke" => BuildJokeDecision(catalog),
|
"joke" => BuildJokeDecision(catalog),
|
||||||
@@ -39,8 +49,8 @@ public sealed class JiboInteractionService(
|
|||||||
"clock_menu" => BuildClockLaunchDecision("clock_menu", "clock", "menu", "Opening the clock menu."),
|
"clock_menu" => BuildClockLaunchDecision("clock_menu", "clock", "menu", "Opening the clock menu."),
|
||||||
"timer_menu" => BuildClockLaunchDecision("timer", "Opening the timer."),
|
"timer_menu" => BuildClockLaunchDecision("timer", "Opening the timer."),
|
||||||
"alarm_menu" => BuildClockLaunchDecision("alarm", "Opening the alarm."),
|
"alarm_menu" => BuildClockLaunchDecision("alarm", "Opening the alarm."),
|
||||||
"timer_value" => BuildTimerValueDecision(lowered),
|
"timer_value" => BuildTimerValueDecision(lowered, isTimerValueTurn),
|
||||||
"alarm_value" => BuildAlarmValueDecision(lowered),
|
"alarm_value" => BuildAlarmValueDecision(lowered, isAlarmValueTurn),
|
||||||
"timer_clarify" => new JiboInteractionDecision("timer_clarify", "How long should I set the timer for?"),
|
"timer_clarify" => new JiboInteractionDecision("timer_clarify", "How long should I set the timer for?"),
|
||||||
"alarm_clarify" => new JiboInteractionDecision("alarm_clarify", "What time should I set the alarm for?"),
|
"alarm_clarify" => new JiboInteractionDecision("alarm_clarify", "What time should I set the alarm for?"),
|
||||||
"photo_gallery" => BuildPhotoGalleryLaunchDecision(),
|
"photo_gallery" => BuildPhotoGalleryLaunchDecision(),
|
||||||
@@ -141,7 +151,9 @@ public sealed class JiboInteractionService(
|
|||||||
IReadOnlyList<string> clientRules,
|
IReadOnlyList<string> clientRules,
|
||||||
IReadOnlyList<string> listenRules,
|
IReadOnlyList<string> listenRules,
|
||||||
IReadOnlyDictionary<string, string> clientEntities,
|
IReadOnlyDictionary<string, string> clientEntities,
|
||||||
bool isYesNoTurn)
|
bool isYesNoTurn,
|
||||||
|
bool isTimerValueTurn,
|
||||||
|
bool isAlarmValueTurn)
|
||||||
{
|
{
|
||||||
var wordOfDayPuzzleTurn = clientRules.Concat(listenRules)
|
var wordOfDayPuzzleTurn = clientRules.Concat(listenRules)
|
||||||
.Any(rule => string.Equals(rule, "word-of-the-day/puzzle", StringComparison.OrdinalIgnoreCase));
|
.Any(rule => string.Equals(rule, "word-of-the-day/puzzle", StringComparison.OrdinalIgnoreCase));
|
||||||
@@ -196,6 +208,18 @@ public sealed class JiboInteractionService(
|
|||||||
return "alarm_value";
|
return "alarm_value";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((string.Equals(clientIntent, "start", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(clientIntent, "set", StringComparison.OrdinalIgnoreCase)) &&
|
||||||
|
clientEntities.TryGetValue("domain", out var startDomain))
|
||||||
|
{
|
||||||
|
return startDomain.ToLowerInvariant() switch
|
||||||
|
{
|
||||||
|
"timer" => "timer_value",
|
||||||
|
"alarm" => "alarm_value",
|
||||||
|
_ => "chat"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
if (string.Equals(clientIntent, "menu", StringComparison.OrdinalIgnoreCase) &&
|
if (string.Equals(clientIntent, "menu", StringComparison.OrdinalIgnoreCase) &&
|
||||||
clientEntities.TryGetValue("domain", out var clockDomain))
|
clientEntities.TryGetValue("domain", out var clockDomain))
|
||||||
{
|
{
|
||||||
@@ -261,22 +285,22 @@ public sealed class JiboInteractionService(
|
|||||||
return "alarm_menu";
|
return "alarm_menu";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryParseAlarmValue(loweredTranscript) is not null)
|
if (TryParseAlarmValue(loweredTranscript, isAlarmValueTurn) is not null)
|
||||||
{
|
{
|
||||||
return "alarm_value";
|
return "alarm_value";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (TryParseTimerValue(loweredTranscript) is not null)
|
if (TryParseTimerValue(loweredTranscript, isTimerValueTurn) is not null)
|
||||||
{
|
{
|
||||||
return "timer_value";
|
return "timer_value";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsAlarmRequest(loweredTranscript))
|
if (IsAlarmRequest(loweredTranscript) || isAlarmValueTurn)
|
||||||
{
|
{
|
||||||
return "alarm_clarify";
|
return "alarm_clarify";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (IsTimerRequest(loweredTranscript))
|
if (IsTimerRequest(loweredTranscript) || isTimerValueTurn)
|
||||||
{
|
{
|
||||||
return "timer_clarify";
|
return "timer_clarify";
|
||||||
}
|
}
|
||||||
@@ -469,9 +493,9 @@ public sealed class JiboInteractionService(
|
|||||||
return BuildClockLaunchDecision($"{domain}_menu", domain, "menu", replyText);
|
return BuildClockLaunchDecision($"{domain}_menu", domain, "menu", replyText);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildTimerValueDecision(string loweredTranscript)
|
private static JiboInteractionDecision BuildTimerValueDecision(string loweredTranscript, bool allowImplicit)
|
||||||
{
|
{
|
||||||
var timer = TryParseTimerValue(loweredTranscript) ?? new ClockTimerValue("0", "1", "null");
|
var timer = TryParseTimerValue(loweredTranscript, allowImplicit) ?? new ClockTimerValue("0", "1", "null");
|
||||||
|
|
||||||
return new JiboInteractionDecision(
|
return new JiboInteractionDecision(
|
||||||
"timer_value",
|
"timer_value",
|
||||||
@@ -481,16 +505,16 @@ public sealed class JiboInteractionService(
|
|||||||
{
|
{
|
||||||
["skillId"] = "@be/clock",
|
["skillId"] = "@be/clock",
|
||||||
["domain"] = "timer",
|
["domain"] = "timer",
|
||||||
["clockIntent"] = "timerValue",
|
["clockIntent"] = "start",
|
||||||
["hours"] = timer.Hours,
|
["hours"] = timer.Hours,
|
||||||
["minutes"] = timer.Minutes,
|
["minutes"] = timer.Minutes,
|
||||||
["seconds"] = timer.Seconds
|
["seconds"] = timer.Seconds
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private static JiboInteractionDecision BuildAlarmValueDecision(string loweredTranscript)
|
private static JiboInteractionDecision BuildAlarmValueDecision(string loweredTranscript, bool allowImplicit)
|
||||||
{
|
{
|
||||||
var alarm = TryParseAlarmValue(loweredTranscript) ?? new ClockAlarmValue("7:00", "am");
|
var alarm = TryParseAlarmValue(loweredTranscript, allowImplicit) ?? new ClockAlarmValue("7:00", "am");
|
||||||
|
|
||||||
return new JiboInteractionDecision(
|
return new JiboInteractionDecision(
|
||||||
"alarm_value",
|
"alarm_value",
|
||||||
@@ -500,7 +524,7 @@ public sealed class JiboInteractionService(
|
|||||||
{
|
{
|
||||||
["skillId"] = "@be/clock",
|
["skillId"] = "@be/clock",
|
||||||
["domain"] = "alarm",
|
["domain"] = "alarm",
|
||||||
["clockIntent"] = "alarmValue",
|
["clockIntent"] = "start",
|
||||||
["time"] = alarm.Time,
|
["time"] = alarm.Time,
|
||||||
["ampm"] = alarm.AmPm
|
["ampm"] = alarm.AmPm
|
||||||
});
|
});
|
||||||
@@ -734,9 +758,9 @@ public sealed class JiboInteractionService(
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClockTimerValue? TryParseTimerValue(string loweredTranscript)
|
private static ClockTimerValue? TryParseTimerValue(string loweredTranscript, bool allowImplicit = false)
|
||||||
{
|
{
|
||||||
if (!loweredTranscript.Contains("timer", StringComparison.Ordinal))
|
if (!allowImplicit && !loweredTranscript.Contains("timer", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -756,9 +780,9 @@ public sealed class JiboInteractionService(
|
|||||||
seconds is null ? "null" : seconds.Value.ToString());
|
seconds is null ? "null" : seconds.Value.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static ClockAlarmValue? TryParseAlarmValue(string loweredTranscript)
|
private static ClockAlarmValue? TryParseAlarmValue(string loweredTranscript, bool allowImplicit = false)
|
||||||
{
|
{
|
||||||
if (!loweredTranscript.Contains("alarm", StringComparison.Ordinal))
|
if (!allowImplicit && !loweredTranscript.Contains("alarm", StringComparison.Ordinal))
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -803,7 +827,8 @@ public sealed class JiboInteractionService(
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!int.TryParse(minuteToken, out var minute) || minute is < 0 or > 59)
|
var minute = ParseNumberToken(minuteToken);
|
||||||
|
if (minute is null || minute is < 0 or > 59)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -814,7 +839,9 @@ public sealed class JiboInteractionService(
|
|||||||
|
|
||||||
private static string ResolveAmPm(string token)
|
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)
|
private static bool IsTimerRequest(string loweredTranscript)
|
||||||
@@ -838,26 +865,79 @@ public sealed class JiboInteractionService(
|
|||||||
"alarm for");
|
"alarm for");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool IsClockTimerValueTurn(
|
||||||
|
IReadOnlyList<string> clientRules,
|
||||||
|
IReadOnlyList<string> listenRules)
|
||||||
|
{
|
||||||
|
return clientRules.Concat(listenRules).Any(static rule =>
|
||||||
|
rule.Contains("clock/", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
rule.Contains("timer", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
rule.Contains("value", StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
|
private static bool IsClockAlarmValueTurn(
|
||||||
|
IReadOnlyList<string> clientRules,
|
||||||
|
IReadOnlyList<string> listenRules)
|
||||||
|
{
|
||||||
|
return clientRules.Concat(listenRules).Any(static rule =>
|
||||||
|
rule.Contains("clock/", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
rule.Contains("alarm", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
rule.Contains("value", StringComparison.OrdinalIgnoreCase));
|
||||||
|
}
|
||||||
|
|
||||||
private static int? ExtractDurationValue(string loweredTranscript, string unitStem)
|
private static int? ExtractDurationValue(string loweredTranscript, string unitStem)
|
||||||
{
|
{
|
||||||
var pattern = new Regex($@"\b(?<value>\d+|[a-z\-]+)\s+{unitStem}s?\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
var pattern = new Regex($@"\b(?<value>\d+|[a-z\-]+(?:\s+[a-z\-]+)?)\s+{unitStem}s?\b", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||||
var match = pattern.Match(loweredTranscript);
|
var match = pattern.Match(loweredTranscript);
|
||||||
if (!match.Success)
|
if (!match.Success)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ParseNumberToken(match.Groups["value"].Value);
|
var valueToken = match.Groups["value"].Value.Trim();
|
||||||
|
var parsed = ParseNumberToken(valueToken);
|
||||||
|
if (parsed is not null)
|
||||||
|
{
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
|
||||||
|
var parts = valueToken.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
if (parts.Length >= 2)
|
||||||
|
{
|
||||||
|
parsed = ParseNumberToken(string.Join(' ', parts.TakeLast(2)));
|
||||||
|
if (parsed is not null)
|
||||||
|
{
|
||||||
|
return parsed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return parts.Length > 0
|
||||||
|
? ParseNumberToken(parts[^1])
|
||||||
|
: null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int? ParseNumberToken(string token)
|
private static int? ParseNumberToken(string token)
|
||||||
{
|
{
|
||||||
var normalized = token.Trim().ToLowerInvariant();
|
var normalized = token.Trim().ToLowerInvariant().Replace("-", " ", StringComparison.Ordinal);
|
||||||
if (int.TryParse(normalized, out var numeric))
|
if (int.TryParse(normalized, out var numeric))
|
||||||
{
|
{
|
||||||
return numeric;
|
return numeric;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (normalized.Contains(' '))
|
||||||
|
{
|
||||||
|
var parts = normalized.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
|
||||||
|
if (parts.Length == 2)
|
||||||
|
{
|
||||||
|
var first = ParseNumberToken(parts[0]);
|
||||||
|
var second = ParseNumberToken(parts[1]);
|
||||||
|
if (first is >= 20 && second is >= 0 and < 10)
|
||||||
|
{
|
||||||
|
return first + second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return normalized switch
|
return normalized switch
|
||||||
{
|
{
|
||||||
"a" or "an" => 1,
|
"a" or "an" => 1,
|
||||||
@@ -893,11 +973,11 @@ public sealed class JiboInteractionService(
|
|||||||
private sealed record ClockAlarmValue(string Time, string AmPm);
|
private sealed record ClockAlarmValue(string Time, string AmPm);
|
||||||
|
|
||||||
private static readonly Regex SplitAlarmPattern = new(
|
private static readonly Regex SplitAlarmPattern = new(
|
||||||
@"\b(?<hour>\d{1,2}|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)(?:[:\s](?<minute>\d{2}))?\s*(?<ampm>a\.?m\.?|p\.?m\.?)?\b",
|
@"\b(?<hour>\d{1,2}|one|two|three|four|five|six|seven|eight|nine|ten|eleven|twelve)(?:[:\s-](?<minute>\d{2}|[a-z\-]+(?:\s+[a-z\-]+)?))?\s*(?<ampm>a[\s\.]*m\.?|p[\s\.]*m\.?)?\b",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly Regex CompactAlarmPattern = new(
|
private static readonly Regex CompactAlarmPattern = new(
|
||||||
@"\b(?<compact>\d{3,4})\s*(?<ampm>a\.?m\.?|p\.?m\.?)?\b",
|
@"\b(?<compact>\d{3,4})\s*(?<ampm>a[\s\.]*m\.?|p[\s\.]*m\.?)?\b",
|
||||||
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
|
RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled);
|
||||||
|
|
||||||
private static readonly (string Phrase, string Station)[] RadioGenreAliases =
|
private static readonly (string Phrase, string Station)[] RadioGenreAliases =
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ namespace Jibo.Cloud.Application.Services;
|
|||||||
|
|
||||||
public static class OpenJiboCloudBuildInfo
|
public static class OpenJiboCloudBuildInfo
|
||||||
{
|
{
|
||||||
public const string Version = "1.0.12";
|
public const string Version = "1.0.13";
|
||||||
|
|
||||||
public static string VersionWords => Version.Replace(".", " dot ");
|
public static string VersionWords => Version.Replace(".", " dot ");
|
||||||
|
|
||||||
|
|||||||
@@ -408,14 +408,16 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
|||||||
entities["domain"] = clockDomain;
|
entities["domain"] = clockDomain;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(clockIntent, "timerValue", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(clockDomain, "timer", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
!string.IsNullOrWhiteSpace(timerHours + timerMinutes + timerSeconds))
|
||||||
{
|
{
|
||||||
entities["hours"] = timerHours ?? "0";
|
entities["hours"] = timerHours ?? "0";
|
||||||
entities["minutes"] = timerMinutes ?? "0";
|
entities["minutes"] = timerMinutes ?? "0";
|
||||||
entities["seconds"] = timerSeconds ?? "null";
|
entities["seconds"] = timerSeconds ?? "null";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (string.Equals(clockIntent, "alarmValue", StringComparison.OrdinalIgnoreCase))
|
if (string.Equals(clockDomain, "alarm", StringComparison.OrdinalIgnoreCase) &&
|
||||||
|
(!string.IsNullOrWhiteSpace(alarmTime) || !string.IsNullOrWhiteSpace(alarmAmPm)))
|
||||||
{
|
{
|
||||||
entities["time"] = alarmTime ?? string.Empty;
|
entities["time"] = alarmTime ?? string.Empty;
|
||||||
entities["ampm"] = alarmAmPm ?? string.Empty;
|
entities["ampm"] = alarmAmPm ?? string.Empty;
|
||||||
|
|||||||
@@ -105,6 +105,29 @@ public sealed class WebSocketTurnFinalizationService(
|
|||||||
session.Metadata["audioTranscriptHint"] = transcriptHint;
|
session.Metadata["audioTranscriptHint"] = transcriptHint;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ShouldIgnorePassiveLocalSkillContext(session, envelope.Text))
|
||||||
|
{
|
||||||
|
turnState.AwaitingTurnCompletion = false;
|
||||||
|
turnState.IgnoreAdditionalAudioUntilUtc = DateTimeOffset.UtcNow.Add(WebSocketTurnState.DefaultLateAudioIgnoreWindow);
|
||||||
|
ResetBufferedAudio(session);
|
||||||
|
turnState.SawContext = false;
|
||||||
|
return
|
||||||
|
[
|
||||||
|
new WebSocketReply
|
||||||
|
{
|
||||||
|
Text = JsonSerializer.Serialize(new
|
||||||
|
{
|
||||||
|
type = "OPENJIBO_CONTEXT_ACK",
|
||||||
|
data = new
|
||||||
|
{
|
||||||
|
sessionId = session.SessionId,
|
||||||
|
transID = session.LastTransId
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
if (ShouldAutoFinalize(session))
|
if (ShouldAutoFinalize(session))
|
||||||
{
|
{
|
||||||
return await FinalizeTurnAsync(session, envelope, "AUTO_FINALIZE", allowFallbackOnMissingTranscript: true, cancellationToken);
|
return await FinalizeTurnAsync(session, envelope, "AUTO_FINALIZE", allowFallbackOnMissingTranscript: true, cancellationToken);
|
||||||
@@ -614,6 +637,18 @@ public sealed class WebSocketTurnFinalizationService(
|
|||||||
ignoreUntilUtc.Value > DateTimeOffset.UtcNow;
|
ignoreUntilUtc.Value > DateTimeOffset.UtcNow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static bool ShouldIgnorePassiveLocalSkillContext(CloudSession session, string? text)
|
||||||
|
{
|
||||||
|
if (session.FollowUpOpen || session.TurnState.SawListen)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
var skillId = TryReadContextSkillId(text);
|
||||||
|
return string.Equals(skillId, "@be/gallery", StringComparison.OrdinalIgnoreCase) ||
|
||||||
|
string.Equals(skillId, "@be/create", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
private static string? ExtractDataPayload(string? text)
|
private static string? ExtractDataPayload(string? text)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrWhiteSpace(text))
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
@@ -664,6 +699,32 @@ public sealed class WebSocketTurnFinalizationService(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string? TryReadContextSkillId(string? text)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrWhiteSpace(text))
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var document = JsonDocument.Parse(text);
|
||||||
|
if (!document.RootElement.TryGetProperty("data", out var data) ||
|
||||||
|
!data.TryGetProperty("skill", out var skill) ||
|
||||||
|
!skill.TryGetProperty("id", out var id) ||
|
||||||
|
id.ValueKind != JsonValueKind.String)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return id.GetString();
|
||||||
|
}
|
||||||
|
catch (JsonException)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static bool TryReadTransId(string? text, out string? transId)
|
private static bool TryReadTransId(string? text, out string? transId)
|
||||||
{
|
{
|
||||||
transId = null;
|
transId = null;
|
||||||
|
|||||||
@@ -250,7 +250,7 @@ public sealed class JiboInteractionServiceTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task BuildDecisionAsync_SetTimerForFiveMinutes_MapsToTimerValue()
|
public async Task BuildDecisionAsync_SetTimerForFiveMinutes_MapsToClockStartIntent()
|
||||||
{
|
{
|
||||||
var service = CreateService();
|
var service = CreateService();
|
||||||
|
|
||||||
@@ -263,14 +263,14 @@ public sealed class JiboInteractionServiceTests
|
|||||||
Assert.Equal("timer_value", decision.IntentName);
|
Assert.Equal("timer_value", decision.IntentName);
|
||||||
Assert.Equal("@be/clock", decision.SkillName);
|
Assert.Equal("@be/clock", decision.SkillName);
|
||||||
Assert.Equal("timer", decision.SkillPayload!["domain"]);
|
Assert.Equal("timer", decision.SkillPayload!["domain"]);
|
||||||
Assert.Equal("timerValue", decision.SkillPayload["clockIntent"]);
|
Assert.Equal("start", decision.SkillPayload["clockIntent"]);
|
||||||
Assert.Equal("0", decision.SkillPayload["hours"]);
|
Assert.Equal("0", decision.SkillPayload["hours"]);
|
||||||
Assert.Equal("5", decision.SkillPayload["minutes"]);
|
Assert.Equal("5", decision.SkillPayload["minutes"]);
|
||||||
Assert.Equal("null", decision.SkillPayload["seconds"]);
|
Assert.Equal("null", decision.SkillPayload["seconds"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task BuildDecisionAsync_SetAlarmForSevenThirtyAm_MapsToAlarmValue()
|
public async Task BuildDecisionAsync_SetAlarmForSevenThirtyAm_MapsToClockStartIntent()
|
||||||
{
|
{
|
||||||
var service = CreateService();
|
var service = CreateService();
|
||||||
|
|
||||||
@@ -283,7 +283,7 @@ public sealed class JiboInteractionServiceTests
|
|||||||
Assert.Equal("alarm_value", decision.IntentName);
|
Assert.Equal("alarm_value", decision.IntentName);
|
||||||
Assert.Equal("@be/clock", decision.SkillName);
|
Assert.Equal("@be/clock", decision.SkillName);
|
||||||
Assert.Equal("alarm", decision.SkillPayload!["domain"]);
|
Assert.Equal("alarm", decision.SkillPayload!["domain"]);
|
||||||
Assert.Equal("alarmValue", decision.SkillPayload["clockIntent"]);
|
Assert.Equal("start", decision.SkillPayload["clockIntent"]);
|
||||||
Assert.Equal("7:30", decision.SkillPayload["time"]);
|
Assert.Equal("7:30", decision.SkillPayload["time"]);
|
||||||
Assert.Equal("am", decision.SkillPayload["ampm"]);
|
Assert.Equal("am", decision.SkillPayload["ampm"]);
|
||||||
}
|
}
|
||||||
@@ -320,6 +320,97 @@ public sealed class JiboInteractionServiceTests
|
|||||||
Assert.Equal("am", decision.SkillPayload["ampm"]);
|
Assert.Equal("am", decision.SkillPayload["ampm"]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task BuildDecisionAsync_SetAlarmForTenTwentyFiveWithHyphen_ParsesSplitTime()
|
||||||
|
{
|
||||||
|
var service = CreateService();
|
||||||
|
|
||||||
|
var decision = await service.BuildDecisionAsync(new TurnContext
|
||||||
|
{
|
||||||
|
RawTranscript = "set an alarm for 10-25",
|
||||||
|
NormalizedTranscript = "set an alarm for 10-25"
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal("alarm_value", decision.IntentName);
|
||||||
|
Assert.Equal("10:25", decision.SkillPayload!["time"]);
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
var service = CreateService();
|
||||||
|
|
||||||
|
var decision = await service.BuildDecisionAsync(new TurnContext
|
||||||
|
{
|
||||||
|
RawTranscript = "twenty five minutes",
|
||||||
|
NormalizedTranscript = "twenty five minutes",
|
||||||
|
Attributes = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["listenRules"] = new[] { "clock/timer_set_value" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal("timer_value", decision.IntentName);
|
||||||
|
Assert.Equal("@be/clock", decision.SkillName);
|
||||||
|
Assert.Equal("start", decision.SkillPayload!["clockIntent"]);
|
||||||
|
Assert.Equal("25", decision.SkillPayload["minutes"]);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task BuildDecisionAsync_AlarmValueFollowUp_ParsesBareSpokenTime()
|
||||||
|
{
|
||||||
|
var service = CreateService();
|
||||||
|
|
||||||
|
var decision = await service.BuildDecisionAsync(new TurnContext
|
||||||
|
{
|
||||||
|
RawTranscript = "ten twenty five",
|
||||||
|
NormalizedTranscript = "ten twenty five",
|
||||||
|
Attributes = new Dictionary<string, object?>
|
||||||
|
{
|
||||||
|
["listenRules"] = new[] { "clock/alarm_set_value" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal("alarm_value", decision.IntentName);
|
||||||
|
Assert.Equal("@be/clock", decision.SkillName);
|
||||||
|
Assert.Equal("start", decision.SkillPayload!["clockIntent"]);
|
||||||
|
Assert.Equal("10:25", decision.SkillPayload["time"]);
|
||||||
|
Assert.Equal("am", decision.SkillPayload["ampm"]);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task BuildDecisionAsync_SetAlarmWithoutTime_AsksForClarification()
|
public async Task BuildDecisionAsync_SetAlarmWithoutTime_AsksForClarification()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -371,7 +371,7 @@ public sealed class JiboWebSocketServiceTests
|
|||||||
Assert.Equal("SKILL_ACTION", ReadReplyType(replies[3]));
|
Assert.Equal("SKILL_ACTION", ReadReplyType(replies[3]));
|
||||||
|
|
||||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||||
Assert.Equal("timerValue", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
Assert.Equal("start", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||||
Assert.Equal("@be/clock", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("skill").GetString());
|
Assert.Equal("@be/clock", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("skill").GetString());
|
||||||
Assert.Equal("timer", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
Assert.Equal("timer", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
||||||
Assert.Equal("0", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("hours").GetString());
|
Assert.Equal("0", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("hours").GetString());
|
||||||
@@ -380,7 +380,7 @@ public sealed class JiboWebSocketServiceTests
|
|||||||
|
|
||||||
using var redirectPayload = JsonDocument.Parse(replies[2].Text!);
|
using var redirectPayload = JsonDocument.Parse(replies[2].Text!);
|
||||||
Assert.Equal("@be/clock", redirectPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("skillID").GetString());
|
Assert.Equal("@be/clock", redirectPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("skillID").GetString());
|
||||||
Assert.Equal("timerValue", redirectPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
Assert.Equal("start", redirectPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -468,7 +468,7 @@ public sealed class JiboWebSocketServiceTests
|
|||||||
Assert.Equal(4, replies.Count);
|
Assert.Equal(4, replies.Count);
|
||||||
|
|
||||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||||
Assert.Equal("alarmValue", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
Assert.Equal("start", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||||
Assert.Equal("@be/clock", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("skill").GetString());
|
Assert.Equal("@be/clock", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("skill").GetString());
|
||||||
Assert.Equal("alarm", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
Assert.Equal("alarm", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
||||||
Assert.Equal("7:30", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("time").GetString());
|
Assert.Equal("7:30", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("time").GetString());
|
||||||
@@ -503,6 +503,123 @@ public sealed class JiboWebSocketServiceTests
|
|||||||
Assert.Equal("am", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("ampm").GetString());
|
Assert.Equal("am", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("ampm").GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ClientAsr_SetAlarmForTenTwentyFiveWithHyphen_ParsesAlarmTime()
|
||||||
|
{
|
||||||
|
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-clock-hyphen-alarm-token",
|
||||||
|
Text = """{"type":"LISTEN","transID":"trans-clock-hyphen-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-hyphen-alarm-token",
|
||||||
|
Text = """{"type":"CLIENT_ASR","transID":"trans-clock-hyphen-alarm","data":{"text":"set an alarm for 10-25"}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal(4, replies.Count);
|
||||||
|
|
||||||
|
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||||
|
Assert.Equal("start", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||||
|
Assert.Equal("alarm", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
||||||
|
Assert.Equal("10:25", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("time").GetString());
|
||||||
|
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()
|
||||||
|
{
|
||||||
|
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-clock-timer-followup-token",
|
||||||
|
Text = """{"type":"LISTEN","transID":"trans-clock-timer-followup","data":{"rules":["clock/timer_set_value"]}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-clock-timer-followup-token",
|
||||||
|
Text = """{"type":"CLIENT_ASR","transID":"trans-clock-timer-followup","data":{"text":"twenty five minutes"}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal(4, replies.Count);
|
||||||
|
|
||||||
|
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||||
|
Assert.Equal("start", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||||
|
Assert.Equal("timer", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
||||||
|
Assert.Equal("25", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("minutes").GetString());
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task ClientAsr_AlarmValueFollowUp_ParsesBareSpokenTimeIntoClockStartIntent()
|
||||||
|
{
|
||||||
|
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-clock-alarm-followup-token",
|
||||||
|
Text = """{"type":"LISTEN","transID":"trans-clock-alarm-followup","data":{"rules":["clock/alarm_set_value"]}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-clock-alarm-followup-token",
|
||||||
|
Text = """{"type":"CLIENT_ASR","transID":"trans-clock-alarm-followup","data":{"text":"ten twenty five"}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Equal(4, replies.Count);
|
||||||
|
|
||||||
|
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||||
|
Assert.Equal("start", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||||
|
Assert.Equal("alarm", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
||||||
|
Assert.Equal("10:25", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("time").GetString());
|
||||||
|
Assert.Equal("am", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("ampm").GetString());
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ClientAsr_SetAlarmWithoutTime_UsesClarificationSpeechInsteadOfClockRedirect()
|
public async Task ClientAsr_SetAlarmWithoutTime_UsesClarificationSpeechInsteadOfClockRedirect()
|
||||||
{
|
{
|
||||||
@@ -573,6 +690,55 @@ public sealed class JiboWebSocketServiceTests
|
|||||||
Assert.Equal("menu", redirectPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
Assert.Equal("menu", redirectPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task Context_FromGalleryOpen_DoesNotReopenPendingTurnOrLeaveBufferedAudioArmed()
|
||||||
|
{
|
||||||
|
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-photo-gallery-context-token",
|
||||||
|
Text = """{"type":"LISTEN","transID":"trans-photo-gallery-context","data":{"rules":["globals/global_commands_launch"]}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-photo-gallery-context-token",
|
||||||
|
Text = """{"type":"CLIENT_ASR","transID":"trans-photo-gallery-context","data":{"text":"open photo gallery"}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-photo-gallery-context-token",
|
||||||
|
Binary = [1, 2, 3, 4, 5]
|
||||||
|
});
|
||||||
|
|
||||||
|
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||||
|
{
|
||||||
|
HostName = "neo-hub.jibo.com",
|
||||||
|
Path = "/listen",
|
||||||
|
Kind = "neo-hub-listen",
|
||||||
|
Token = "hub-photo-gallery-context-token",
|
||||||
|
Text = """{"type":"CONTEXT","transID":"trans-photo-gallery-context","data":{"skill":{"id":"@be/gallery"}}}"""
|
||||||
|
});
|
||||||
|
|
||||||
|
Assert.Single(replies);
|
||||||
|
Assert.Equal("OPENJIBO_CONTEXT_ACK", ReadReplyType(replies[0]));
|
||||||
|
|
||||||
|
var session = _store.FindSessionByToken("hub-photo-gallery-context-token");
|
||||||
|
Assert.NotNull(session);
|
||||||
|
Assert.False(session.TurnState.AwaitingTurnCompletion);
|
||||||
|
Assert.Equal(0, session.TurnState.BufferedAudioBytes);
|
||||||
|
Assert.Equal(0, session.TurnState.BufferedAudioChunkCount);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task ClientAsr_SnapAPicture_RedirectsIntoCreateSkill()
|
public async Task ClientAsr_SnapAPicture_RedirectsIntoCreateSkill()
|
||||||
{
|
{
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"exception": "System.InvalidOperationException: whisper.cpp returned no transcript for the buffered audio turn.\n at Jibo.Cloud.Infrastructure.Audio.LocalWhisperCppBufferedAudioSttStrategy.TranscribeAsync(TurnContext turn, CancellationToken cancellationToken) in /home/jake-dubin/JiboExperiments/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Audio/LocalWhisperCppBufferedAudioSttStrategy.cs:line 58\n at Jibo.Cloud.Application.Services.WebSocketTurnFinalizationService.ResolveTranscriptAsync(TurnContext turn, CloudSession session, CancellationToken cancellationToken) in /home/jake-dubin/JiboExperiments/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/WebSocketTurnFinalizationService.cs:line 219",
|
||||||
|
"message": "Error during STT processing"
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"name": "neohubjibocom-neohublisten-tid52b6f46e3b6a11f191515cf821ea55ae",
|
||||||
|
"session": {
|
||||||
|
"hostName": "neo-hub.jibo.com",
|
||||||
|
"path": "/v1/listen",
|
||||||
|
"kind": "neo-hub-listen",
|
||||||
|
"token": "hub-usr_openjibo_owner-1776545569192"
|
||||||
|
},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "LISTEN",
|
||||||
|
"ts": 1776546327052,
|
||||||
|
"msgID": "mid-5303b5f6-3b6a-11f1-adc4-5cf821ea55ae",
|
||||||
|
"transID": "tid-52b6f46e-3b6a-11f1-9151-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"lang": "en-US",
|
||||||
|
"hotphrase": true,
|
||||||
|
"rules": [
|
||||||
|
"launch",
|
||||||
|
"globals/global_commands_launch"
|
||||||
|
],
|
||||||
|
"mode": "CLIENT_ASR",
|
||||||
|
"asr": {
|
||||||
|
"hints": [],
|
||||||
|
"earlyEOS": [],
|
||||||
|
"encoding": "OGG_OPUS",
|
||||||
|
"sampleRate": 16000,
|
||||||
|
"sosTimeout": 7000,
|
||||||
|
"maxSpeechTimeout": 20000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_TURN_PENDING"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "CLIENT_ASR",
|
||||||
|
"ts": 1776546327052,
|
||||||
|
"msgID": "mid-5303bd76-3b6a-11f1-81d4-5cf821ea55ae",
|
||||||
|
"transID": "tid-52b6f46e-3b6a-11f1-9151-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"text": "tell me about the news"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"LISTEN",
|
||||||
|
"EOS",
|
||||||
|
"SKILL_ACTION"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "CONTEXT",
|
||||||
|
"ts": 1776546327177,
|
||||||
|
"msgID": "mid-5316cf2e-3b6a-11f1-8aa7-5cf821ea55ae",
|
||||||
|
"transID": "tid-52b6f46e-3b6a-11f1-9151-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"runtime": {
|
||||||
|
"character": {
|
||||||
|
"emotion": {
|
||||||
|
"name": "NEUTRAL",
|
||||||
|
"valence": 0.45,
|
||||||
|
"confidence": 0.2
|
||||||
|
},
|
||||||
|
"motivation": {
|
||||||
|
"social": 1,
|
||||||
|
"playful": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"perception": {
|
||||||
|
"speaker": null,
|
||||||
|
"peoplePresent": []
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"city": "Pleasant Hill",
|
||||||
|
"state": "Missouri",
|
||||||
|
"stateAbbr": "MO",
|
||||||
|
"country": "United States",
|
||||||
|
"countryCode": "US",
|
||||||
|
"lat": 38.8358494,
|
||||||
|
"lng": -94.1427229,
|
||||||
|
"iso": "2026-04-18T16:05:27.073-05:00"
|
||||||
|
},
|
||||||
|
"loop": {
|
||||||
|
"loopId": "5c0b221fdf9d450019c5e253",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"firstName": "Erin",
|
||||||
|
"lastName": "Picone",
|
||||||
|
"phoneticName": "Erin",
|
||||||
|
"gender": "female",
|
||||||
|
"birthdate": 649209600000,
|
||||||
|
"id": "5c0b221fdf9d450019c5e255",
|
||||||
|
"accountId": "5c0b20547c46170019235759"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"jibo": {
|
||||||
|
"color": "WHITE",
|
||||||
|
"birthdate": 1544234645598,
|
||||||
|
"id": "5c0b221fdf9d450019c5e254"
|
||||||
|
},
|
||||||
|
"owner": "5c0b221fdf9d450019c5e255"
|
||||||
|
},
|
||||||
|
"dialog": {
|
||||||
|
"referent": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"skill": {
|
||||||
|
"id": null
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"release": "1.9.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_CONTEXT_ACK"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
{
|
||||||
|
"name": "neohubjibocom-neohublisten-tida8165b823b9411f195545cf821ea55ae",
|
||||||
|
"session": {
|
||||||
|
"hostName": "neo-hub.jibo.com",
|
||||||
|
"path": "/v1/listen",
|
||||||
|
"kind": "neo-hub-listen",
|
||||||
|
"token": "hub-usr_openjibo_owner-1776563295273"
|
||||||
|
},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "LISTEN",
|
||||||
|
"ts": 1776564508900,
|
||||||
|
"msgID": "mid-a83d9076-3b94-11f1-978d-5cf821ea55ae",
|
||||||
|
"transID": "tid-a8165b82-3b94-11f1-9554-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"lang": "en-US",
|
||||||
|
"hotphrase": true,
|
||||||
|
"rules": [
|
||||||
|
"launch",
|
||||||
|
"globals/global_commands_launch"
|
||||||
|
],
|
||||||
|
"mode": "",
|
||||||
|
"asr": {
|
||||||
|
"hints": [],
|
||||||
|
"earlyEOS": [],
|
||||||
|
"encoding": "OGG_OPUS",
|
||||||
|
"sampleRate": 16000,
|
||||||
|
"sosTimeout": 7000,
|
||||||
|
"maxSpeechTimeout": 20000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"LISTEN",
|
||||||
|
"EOS",
|
||||||
|
"SKILL_ACTION"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": null,
|
||||||
|
"binary": [
|
||||||
|
79,
|
||||||
|
103,
|
||||||
|
103,
|
||||||
|
83,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
62,
|
||||||
|
200,
|
||||||
|
6,
|
||||||
|
48,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
146,
|
||||||
|
142,
|
||||||
|
146,
|
||||||
|
101,
|
||||||
|
1,
|
||||||
|
19,
|
||||||
|
79,
|
||||||
|
112,
|
||||||
|
117,
|
||||||
|
115,
|
||||||
|
72,
|
||||||
|
101,
|
||||||
|
97,
|
||||||
|
100,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
128,
|
||||||
|
62,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_AUDIO_RECEIVED"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "CONTEXT",
|
||||||
|
"ts": 1776564510009,
|
||||||
|
"msgID": "mid-a8e6d640-3b94-11f1-b2b0-5cf821ea55ae",
|
||||||
|
"transID": "tid-a8165b82-3b94-11f1-9554-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"runtime": {
|
||||||
|
"character": {
|
||||||
|
"emotion": {
|
||||||
|
"name": "NEUTRAL",
|
||||||
|
"valence": 0.45,
|
||||||
|
"confidence": 0.2
|
||||||
|
},
|
||||||
|
"motivation": {
|
||||||
|
"social": 1,
|
||||||
|
"playful": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"perception": {
|
||||||
|
"speaker": null,
|
||||||
|
"peoplePresent": [
|
||||||
|
{
|
||||||
|
"id": "NOT_TRAINED",
|
||||||
|
"entityId": 1282,
|
||||||
|
"type": "fused",
|
||||||
|
"confidence": 0.25
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"city": "Pleasant Hill",
|
||||||
|
"state": "Missouri",
|
||||||
|
"stateAbbr": "MO",
|
||||||
|
"country": "United States",
|
||||||
|
"countryCode": "US",
|
||||||
|
"lat": 38.8358494,
|
||||||
|
"lng": -94.1427229,
|
||||||
|
"iso": "2026-04-18T21:08:29.921-05:00"
|
||||||
|
},
|
||||||
|
"loop": {
|
||||||
|
"loopId": "5c0b221fdf9d450019c5e253",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"firstName": "Erin",
|
||||||
|
"lastName": "Picone",
|
||||||
|
"phoneticName": "Erin",
|
||||||
|
"gender": "female",
|
||||||
|
"birthdate": 649209600000,
|
||||||
|
"id": "5c0b221fdf9d450019c5e255",
|
||||||
|
"accountId": "5c0b20547c46170019235759"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"jibo": {
|
||||||
|
"color": "WHITE",
|
||||||
|
"birthdate": 1544234645598,
|
||||||
|
"id": "5c0b221fdf9d450019c5e254"
|
||||||
|
},
|
||||||
|
"owner": "5c0b221fdf9d450019c5e255"
|
||||||
|
},
|
||||||
|
"dialog": {
|
||||||
|
"referent": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"skill": {
|
||||||
|
"id": null
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"release": "1.9.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_CONTEXT_ACK"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
"name": "neohubjibocom-neohublisten-tidd2b591403b6811f1a5735cf821ea55ae",
|
||||||
|
"session": {
|
||||||
|
"hostName": "neo-hub.jibo.com",
|
||||||
|
"path": "/v1/listen",
|
||||||
|
"kind": "neo-hub-listen",
|
||||||
|
"token": "hub-usr_openjibo_owner-1776545569192"
|
||||||
|
},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "LISTEN",
|
||||||
|
"ts": 1776545682509,
|
||||||
|
"msgID": "mid-d2d657ea-3b68-11f1-985b-5cf821ea55ae",
|
||||||
|
"transID": "tid-d2b59140-3b68-11f1-a573-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"lang": "en-US",
|
||||||
|
"hotphrase": true,
|
||||||
|
"rules": [
|
||||||
|
"launch",
|
||||||
|
"globals/global_commands_launch"
|
||||||
|
],
|
||||||
|
"mode": "",
|
||||||
|
"asr": {
|
||||||
|
"hints": [],
|
||||||
|
"earlyEOS": [],
|
||||||
|
"encoding": "OGG_OPUS",
|
||||||
|
"sampleRate": 16000,
|
||||||
|
"sosTimeout": 7000,
|
||||||
|
"maxSpeechTimeout": 20000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_TURN_PENDING"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": null,
|
||||||
|
"binary": [
|
||||||
|
79,
|
||||||
|
103,
|
||||||
|
103,
|
||||||
|
83,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
94,
|
||||||
|
132,
|
||||||
|
99,
|
||||||
|
103,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
234,
|
||||||
|
141,
|
||||||
|
12,
|
||||||
|
246,
|
||||||
|
1,
|
||||||
|
19,
|
||||||
|
79,
|
||||||
|
112,
|
||||||
|
117,
|
||||||
|
115,
|
||||||
|
72,
|
||||||
|
101,
|
||||||
|
97,
|
||||||
|
100,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
128,
|
||||||
|
62,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_AUDIO_RECEIVED"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1492
artifact-output/jibo-test-15/jibo test 15.txt
Normal file
1492
artifact-output/jibo-test-15/jibo test 15.txt
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
@@ -0,0 +1,4 @@
|
|||||||
|
{
|
||||||
|
"exception": "System.InvalidOperationException: whisper.cpp returned no transcript for the buffered audio turn.\n at Jibo.Cloud.Infrastructure.Audio.LocalWhisperCppBufferedAudioSttStrategy.TranscribeAsync(TurnContext turn, CancellationToken cancellationToken) in /home/jake-dubin/JiboExperiments/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Infrastructure/Audio/LocalWhisperCppBufferedAudioSttStrategy.cs:line 58\n at Jibo.Cloud.Application.Services.WebSocketTurnFinalizationService.ResolveTranscriptAsync(TurnContext turn, CloudSession session, CancellationToken cancellationToken) in /home/jake-dubin/JiboExperiments/OpenJibo/src/Jibo.Cloud/dotnet/src/Jibo.Cloud.Application/Services/WebSocketTurnFinalizationService.cs:line 219",
|
||||||
|
"message": "Error during STT processing"
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,127 @@
|
|||||||
|
{
|
||||||
|
"name": "neohubjibocom-neohublisten-tid52b6f46e3b6a11f191515cf821ea55ae",
|
||||||
|
"session": {
|
||||||
|
"hostName": "neo-hub.jibo.com",
|
||||||
|
"path": "/v1/listen",
|
||||||
|
"kind": "neo-hub-listen",
|
||||||
|
"token": "hub-usr_openjibo_owner-1776545569192"
|
||||||
|
},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "LISTEN",
|
||||||
|
"ts": 1776546327052,
|
||||||
|
"msgID": "mid-5303b5f6-3b6a-11f1-adc4-5cf821ea55ae",
|
||||||
|
"transID": "tid-52b6f46e-3b6a-11f1-9151-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"lang": "en-US",
|
||||||
|
"hotphrase": true,
|
||||||
|
"rules": [
|
||||||
|
"launch",
|
||||||
|
"globals/global_commands_launch"
|
||||||
|
],
|
||||||
|
"mode": "CLIENT_ASR",
|
||||||
|
"asr": {
|
||||||
|
"hints": [],
|
||||||
|
"earlyEOS": [],
|
||||||
|
"encoding": "OGG_OPUS",
|
||||||
|
"sampleRate": 16000,
|
||||||
|
"sosTimeout": 7000,
|
||||||
|
"maxSpeechTimeout": 20000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_TURN_PENDING"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "CLIENT_ASR",
|
||||||
|
"ts": 1776546327052,
|
||||||
|
"msgID": "mid-5303bd76-3b6a-11f1-81d4-5cf821ea55ae",
|
||||||
|
"transID": "tid-52b6f46e-3b6a-11f1-9151-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"text": "tell me about the news"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"LISTEN",
|
||||||
|
"EOS",
|
||||||
|
"SKILL_ACTION"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "CONTEXT",
|
||||||
|
"ts": 1776546327177,
|
||||||
|
"msgID": "mid-5316cf2e-3b6a-11f1-8aa7-5cf821ea55ae",
|
||||||
|
"transID": "tid-52b6f46e-3b6a-11f1-9151-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"runtime": {
|
||||||
|
"character": {
|
||||||
|
"emotion": {
|
||||||
|
"name": "NEUTRAL",
|
||||||
|
"valence": 0.45,
|
||||||
|
"confidence": 0.2
|
||||||
|
},
|
||||||
|
"motivation": {
|
||||||
|
"social": 1,
|
||||||
|
"playful": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"perception": {
|
||||||
|
"speaker": null,
|
||||||
|
"peoplePresent": []
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"city": "Pleasant Hill",
|
||||||
|
"state": "Missouri",
|
||||||
|
"stateAbbr": "MO",
|
||||||
|
"country": "United States",
|
||||||
|
"countryCode": "US",
|
||||||
|
"lat": 38.8358494,
|
||||||
|
"lng": -94.1427229,
|
||||||
|
"iso": "2026-04-18T16:05:27.073-05:00"
|
||||||
|
},
|
||||||
|
"loop": {
|
||||||
|
"loopId": "5c0b221fdf9d450019c5e253",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"firstName": "Erin",
|
||||||
|
"lastName": "Picone",
|
||||||
|
"phoneticName": "Erin",
|
||||||
|
"gender": "female",
|
||||||
|
"birthdate": 649209600000,
|
||||||
|
"id": "5c0b221fdf9d450019c5e255",
|
||||||
|
"accountId": "5c0b20547c46170019235759"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"jibo": {
|
||||||
|
"color": "WHITE",
|
||||||
|
"birthdate": 1544234645598,
|
||||||
|
"id": "5c0b221fdf9d450019c5e254"
|
||||||
|
},
|
||||||
|
"owner": "5c0b221fdf9d450019c5e255"
|
||||||
|
},
|
||||||
|
"dialog": {
|
||||||
|
"referent": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"skill": {
|
||||||
|
"id": null
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"release": "1.9.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_CONTEXT_ACK"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,174 @@
|
|||||||
|
{
|
||||||
|
"name": "neohubjibocom-neohublisten-tida8165b823b9411f195545cf821ea55ae",
|
||||||
|
"session": {
|
||||||
|
"hostName": "neo-hub.jibo.com",
|
||||||
|
"path": "/v1/listen",
|
||||||
|
"kind": "neo-hub-listen",
|
||||||
|
"token": "hub-usr_openjibo_owner-1776563295273"
|
||||||
|
},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "LISTEN",
|
||||||
|
"ts": 1776564508900,
|
||||||
|
"msgID": "mid-a83d9076-3b94-11f1-978d-5cf821ea55ae",
|
||||||
|
"transID": "tid-a8165b82-3b94-11f1-9554-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"lang": "en-US",
|
||||||
|
"hotphrase": true,
|
||||||
|
"rules": [
|
||||||
|
"launch",
|
||||||
|
"globals/global_commands_launch"
|
||||||
|
],
|
||||||
|
"mode": "",
|
||||||
|
"asr": {
|
||||||
|
"hints": [],
|
||||||
|
"earlyEOS": [],
|
||||||
|
"encoding": "OGG_OPUS",
|
||||||
|
"sampleRate": 16000,
|
||||||
|
"sosTimeout": 7000,
|
||||||
|
"maxSpeechTimeout": 20000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"LISTEN",
|
||||||
|
"EOS",
|
||||||
|
"SKILL_ACTION"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": null,
|
||||||
|
"binary": [
|
||||||
|
79,
|
||||||
|
103,
|
||||||
|
103,
|
||||||
|
83,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
62,
|
||||||
|
200,
|
||||||
|
6,
|
||||||
|
48,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
146,
|
||||||
|
142,
|
||||||
|
146,
|
||||||
|
101,
|
||||||
|
1,
|
||||||
|
19,
|
||||||
|
79,
|
||||||
|
112,
|
||||||
|
117,
|
||||||
|
115,
|
||||||
|
72,
|
||||||
|
101,
|
||||||
|
97,
|
||||||
|
100,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
128,
|
||||||
|
62,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_AUDIO_RECEIVED"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "CONTEXT",
|
||||||
|
"ts": 1776564510009,
|
||||||
|
"msgID": "mid-a8e6d640-3b94-11f1-b2b0-5cf821ea55ae",
|
||||||
|
"transID": "tid-a8165b82-3b94-11f1-9554-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"runtime": {
|
||||||
|
"character": {
|
||||||
|
"emotion": {
|
||||||
|
"name": "NEUTRAL",
|
||||||
|
"valence": 0.45,
|
||||||
|
"confidence": 0.2
|
||||||
|
},
|
||||||
|
"motivation": {
|
||||||
|
"social": 1,
|
||||||
|
"playful": 1
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"perception": {
|
||||||
|
"speaker": null,
|
||||||
|
"peoplePresent": [
|
||||||
|
{
|
||||||
|
"id": "NOT_TRAINED",
|
||||||
|
"entityId": 1282,
|
||||||
|
"type": "fused",
|
||||||
|
"confidence": 0.25
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"location": {
|
||||||
|
"city": "Pleasant Hill",
|
||||||
|
"state": "Missouri",
|
||||||
|
"stateAbbr": "MO",
|
||||||
|
"country": "United States",
|
||||||
|
"countryCode": "US",
|
||||||
|
"lat": 38.8358494,
|
||||||
|
"lng": -94.1427229,
|
||||||
|
"iso": "2026-04-18T21:08:29.921-05:00"
|
||||||
|
},
|
||||||
|
"loop": {
|
||||||
|
"loopId": "5c0b221fdf9d450019c5e253",
|
||||||
|
"users": [
|
||||||
|
{
|
||||||
|
"firstName": "Erin",
|
||||||
|
"lastName": "Picone",
|
||||||
|
"phoneticName": "Erin",
|
||||||
|
"gender": "female",
|
||||||
|
"birthdate": 649209600000,
|
||||||
|
"id": "5c0b221fdf9d450019c5e255",
|
||||||
|
"accountId": "5c0b20547c46170019235759"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"jibo": {
|
||||||
|
"color": "WHITE",
|
||||||
|
"birthdate": 1544234645598,
|
||||||
|
"id": "5c0b221fdf9d450019c5e254"
|
||||||
|
},
|
||||||
|
"owner": "5c0b221fdf9d450019c5e255"
|
||||||
|
},
|
||||||
|
"dialog": {
|
||||||
|
"referent": null
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"skill": {
|
||||||
|
"id": null
|
||||||
|
},
|
||||||
|
"general": {
|
||||||
|
"release": "1.9.2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_CONTEXT_ACK"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -0,0 +1,95 @@
|
|||||||
|
{
|
||||||
|
"name": "neohubjibocom-neohublisten-tidd2b591403b6811f1a5735cf821ea55ae",
|
||||||
|
"session": {
|
||||||
|
"hostName": "neo-hub.jibo.com",
|
||||||
|
"path": "/v1/listen",
|
||||||
|
"kind": "neo-hub-listen",
|
||||||
|
"token": "hub-usr_openjibo_owner-1776545569192"
|
||||||
|
},
|
||||||
|
"steps": [
|
||||||
|
{
|
||||||
|
"text": {
|
||||||
|
"type": "LISTEN",
|
||||||
|
"ts": 1776545682509,
|
||||||
|
"msgID": "mid-d2d657ea-3b68-11f1-985b-5cf821ea55ae",
|
||||||
|
"transID": "tid-d2b59140-3b68-11f1-a573-5cf821ea55ae",
|
||||||
|
"data": {
|
||||||
|
"lang": "en-US",
|
||||||
|
"hotphrase": true,
|
||||||
|
"rules": [
|
||||||
|
"launch",
|
||||||
|
"globals/global_commands_launch"
|
||||||
|
],
|
||||||
|
"mode": "",
|
||||||
|
"asr": {
|
||||||
|
"hints": [],
|
||||||
|
"earlyEOS": [],
|
||||||
|
"encoding": "OGG_OPUS",
|
||||||
|
"sampleRate": 16000,
|
||||||
|
"sosTimeout": 7000,
|
||||||
|
"maxSpeechTimeout": 20000
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"binary": null,
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_TURN_PENDING"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"text": null,
|
||||||
|
"binary": [
|
||||||
|
79,
|
||||||
|
103,
|
||||||
|
103,
|
||||||
|
83,
|
||||||
|
0,
|
||||||
|
2,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
94,
|
||||||
|
132,
|
||||||
|
99,
|
||||||
|
103,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
234,
|
||||||
|
141,
|
||||||
|
12,
|
||||||
|
246,
|
||||||
|
1,
|
||||||
|
19,
|
||||||
|
79,
|
||||||
|
112,
|
||||||
|
117,
|
||||||
|
115,
|
||||||
|
72,
|
||||||
|
101,
|
||||||
|
97,
|
||||||
|
100,
|
||||||
|
1,
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
128,
|
||||||
|
62,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
0
|
||||||
|
],
|
||||||
|
"expectedReplyTypes": [
|
||||||
|
"OPENJIBO_AUDIO_RECEIVED"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
1134
artifact-output/jibo-test-16/jibo test 16.txt
Normal file
1134
artifact-output/jibo-test-16/jibo test 16.txt
Normal file
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user