version 18 fixes from testing and some documentation around leaks and untested paths, future prep
This commit is contained in:
@@ -21,15 +21,14 @@ Release `1.0.18` is now in feature-hardening. Its main bug-fix theme is alarm an
|
||||
|
||||
## Latest Live Evidence
|
||||
|
||||
`jibo test 23` was captured after the `jibo test 22` alarm/photo hardening pass.
|
||||
`jibo test 24` was captured after the `jibo test 23` alarm/photo fixes.
|
||||
|
||||
- Radio remained live-valid.
|
||||
- News live validation passed. The robot spoke the current synthetic quick brief: `technology companies are still racing on AI...`. This proves the Nimbus-shaped path, not provider-backed headline expansion.
|
||||
- Backup/update remains unresolved. The user observed backup-in-progress sluggishness and the update menu could not proceed while backups were active; the spoken "start backups" style command is not currently a wired OpenJibo voice path.
|
||||
- The first alarm path succeeded: `set an alarm for 743` scheduled a local `7:43 AM` alarm and the alarm fired. A later clarification answer was logged by the robot as `- Time. - 7, 14.` and local NLU interpreted it as `7:00 PM`, causing the confusing replacement prompt.
|
||||
- Current source now accepts short clock value answers during `clock/alarm_set_value` / `clock/timer_set_value`, parses comma-separated alarm digits such as `7, 44`, and maps stock alarm yes/no prompt rules `clock/alarm_timer_change` and `clock/alarm_timer_none_set`.
|
||||
- Photo/gallery still needs a clean live pass. The gallery path opened, but several `shared/yes_no` turns had empty ASR text, so there was no positive `yes` transcript for the cloud to map.
|
||||
- No `ffmpeg` / `whisper.cpp` error was evident in the `jibo test 23` turn timeline, unlike `jibo test 22`. Treat any future decode errors separately from the gallery yes/no payload path.
|
||||
- Basic news remained live-proven from `jibo test 23`; `jibo test 24` focused on alarm and photo/gallery regression.
|
||||
- Alarm replacement yes/no improved: `Yes.` on `clock/alarm_timer_change` was recognized locally. The persistent `7:00 PM` alarm from the previous session still caused repeated replacement prompts until menu cleanup.
|
||||
- Alarm still struggled around value-entry cleanup. Empty ASR under `clock/alarm_set_value` fell into generic Nimbus speech (`I heard you.`), and `CLIENT_NLU intent=cancel` under `clock/alarm_set_value` mapped back to alarm clarification instead of closing the clock value prompt. Current source now treats clock value empty turns as local no-input and maps value-prompt cancel to local clock `cancel`.
|
||||
- Photo/gallery cleanup improved: the blue-ring/listening state appeared to settle, create keeper yes/no could complete, and robot logs showed photo adoption/upload plus `it's a keeper`.
|
||||
- Photo/gallery still has spotty speech recognition. Empty ASR under `gallery/gallery_preview` caused the other observed `I heard you.` after gallery opened. Current source now treats gallery preview empty turns as local no-input instead of relaunching Nimbus fallback speech.
|
||||
- No `ffmpeg` / `whisper.cpp` error was evident in the `jibo test 24` websocket timeline. Remaining alarm/gallery failures are now mostly local no-input handling and STT/recognition quality, not decode failures.
|
||||
|
||||
## Release Rhythm
|
||||
|
||||
@@ -73,7 +72,7 @@ Current websocket scope:
|
||||
- local whisper only attempts external decoding when buffered audio contains an Opus identification header
|
||||
- auto-finalize thresholds for buffered audio after a real listen phase
|
||||
- late-audio ignore windows after completed turns
|
||||
- no-input local completion for constrained prompts
|
||||
- no-input local completion for constrained prompts, clock value prompts, and gallery preview prompts
|
||||
- unknown inbound websocket types dropped silently instead of echoing stock-OS-unknown OpenJibo events
|
||||
- file telemetry and fixture export for HTTP, websocket, and turn captures
|
||||
|
||||
@@ -98,12 +97,14 @@ The following behavior is present in source and covered by focused tests:
|
||||
- short clock value follow-up transcripts are accepted under `clock/alarm_set_value` and `clock/timer_set_value` instead of being dropped before parsing
|
||||
- `CLIENT_NLU intent=set` with only `domain=alarm` stays on the local clock clarification path instead of defaulting to a fabricated time
|
||||
- `CLIENT_NLU intent=cancel` on `clock/alarm_timer_query_menu` can reuse the last active clock domain
|
||||
- `CLIENT_NLU intent=cancel` on `clock/alarm_set_value` / `clock/timer_set_value` maps to local clock `cancel` instead of re-asking for a value
|
||||
- photo flows route `open photo gallery` to `@be/gallery`, `snap a picture` to `@be/create/createOnePhoto`, and `open photobooth` to `@be/create/createSomePhotos`
|
||||
- passive gallery/create context does not reopen a stale cloud turn
|
||||
- media metadata persists across store recreation and `/media/{path}` can serve the current text-body placeholder payload
|
||||
- constrained yes/no handling covers `clock/alarm_timer_change`, `clock/alarm_timer_none_set`, `create/is_it_a_keeper`, `shared/yes_no`, `settings/download_now_later`, `surprises-date/offer_date_fact`, `surprises-ota/want_to_download_now`, and `$YESNO` hints
|
||||
- outbound constrained yes/no responses strip unrelated `globals/*` rules so stock OS stays local
|
||||
- no-input fallback for constrained yes/no prompts emits local `LISTEN`/`EOS` instead of relaunching generic Nimbus speech, including `shared/yes_no` after STT failure
|
||||
- no-input fallback for clock value prompts and `gallery/gallery_preview` emits local `LISTEN`/`EOS` instead of generic `I heard you` Nimbus speech
|
||||
- repeated empty `create/is_it_a_keeper` replies redirect to `@be/idle` after the second miss so the photo/create flow can settle instead of leaving a stale listening state
|
||||
- local whisper skips buffered audio turns that do not contain `OpusHead`, preventing a known `ffmpeg` failure path from becoming the noisy failure mode
|
||||
- Word of the Day launch, spoken guesses, structured `CLIENT_NLU` guesses, hint-order guesses, fuzzy hint matching, right-word cleanup, and late audio cleanup are covered in the websocket layer
|
||||
@@ -125,6 +126,14 @@ The Pegasus tree is especially useful for cloud service intent: `packages/hub` d
|
||||
|
||||
The JiboOS trees are especially useful for local skill ownership and payload shape: `@be/clock`, `@be/gallery`, `@be/create`, `@be/radio`, `@be/nimbus`, `@be/settings`, `@be/surprises*`, `@be/restore`, `@be/who-am-i`, and `@be/idle`.
|
||||
|
||||
The original test suites are useful as behavior contracts before more live-device trial and error:
|
||||
|
||||
- `..\jibo\sdk\skills\clock\tests\AlarmTimer` documents alarm/timer state expectations. Cancel at the alarm value prompt exits without scheduling; no-alarm query `yes` redirects to the value prompt while `no` exits without touching KB/scheduler; existing-alarm `keep` preserves KB/scheduler while `delete`, `change`, and `cancel` clear it; cross-domain cancel uses the `OtherSet` yes/no branch before deleting the other clock domain.
|
||||
- `..\jibo\sdk\skills\gallery\tests` documents gallery ownership. Empty gallery `yes` redirects to `@be/create`, empty gallery `no` exits, media-load failure exits, gallery/item views lifecycle out around two minutes, and delete confirmation only deletes on a positive `yes`.
|
||||
- `..\jibo\sdk\skills\surprises-ota\tests\OTASurprise.test.js` shows OTA/backup surprise priority is robot-local and rate-limited by status plus last-notification timestamps. Backup-in-progress sluggishness should be investigated as local scheduler/status behavior before assuming a cloud backup API issue.
|
||||
- `..\jibo\sdk\skills\nimbus\tests` and `..\jibo\pegasus\packages\integration-tests-int\src\listen*.test.ts` show the cloud/Nimbus contract: listen transactions emit `SOS`, `EOS`, and `LISTEN`, with optional `SKILL_ACTION`; matched responses preserve `match.skillID` or `match.cloudSkill`; `CLIENT_ASR` and `CLIENT_NLU` should both be first-class test inputs.
|
||||
- `..\jibo\pegasus\packages\report-skill\tests\subskills\News.test.js` is the best source-backed guide for news expansion: use category preferences, filter unusable or duplicate items, gate adult headlines for children or unidentified speakers, and provide image metadata alongside spoken headlines.
|
||||
|
||||
When sources disagree, prefer the newest live stock-OS capture for runtime behavior, then stock robot source for local ownership, then Pegasus for original cloud intent, then Node for known working compatibility behavior.
|
||||
|
||||
## `1.0.18` Closeout Gates
|
||||
@@ -133,8 +142,8 @@ Before calling `1.0.18` complete, prove or explicitly defer these:
|
||||
|
||||
- Run the focused `.NET` cloud test suite after the last feature slice.
|
||||
- Confirm the running robot build reports cloud version `1.0.18`.
|
||||
- Regression test alarm flows again after the `jibo test 23` fixes: set with explicit time, set with compact/spoken/comma-separated time, clarify missing time, replace an existing alarm, cancel/delete by voice, and verify the menu agrees.
|
||||
- Regression test photo/gallery flows again after the `jibo test 23` fixes: open gallery, answer the stock `shared/yes_no` prompt with a transcript-bearing `yes`, hand into create, take one photo, and avoid blue-ring stale turns.
|
||||
- Regression test alarm flows again after the `jibo test 24` fixes: set with explicit time, set with compact/spoken/comma-separated time, clarify missing time, replace an existing alarm, cancel/delete by voice, cancel out of a value prompt, and verify the menu agrees.
|
||||
- Regression test photo/gallery flows again after the `jibo test 24` fixes: open gallery, answer the stock `shared/yes_no` prompt with a transcript-bearing `yes`, hand into create, take one photo, keep it, and avoid blue-ring or `I heard you` stale turns.
|
||||
- Live-test radio launch: `open the radio` passed in `jibo test 22`; re-run `play country music` if that exact phrase was not captured.
|
||||
- Treat basic news as live-proven by `jibo test 23`; defer provider-backed or category-expanded news unless it is chosen as an optional feature slice.
|
||||
- Recheck constrained yes/no prompts for update/backup/share/gallery/alarm replacement without leaking global rules.
|
||||
|
||||
@@ -39,6 +39,7 @@ Current release theme:
|
||||
- radio, ESML apostrophe cleanup, and first news are implemented in source/tests; radio and basic news are live-proven as of `jibo test 23`
|
||||
- `jibo test 22` validated radio, exposed backup/load interference, exposed a shared yes/no no-input gap, exposed repeated create keeper prompts after photo handoff, and showed local whisper `ffmpeg` failures on unusable buffered audio
|
||||
- `jibo test 23` validated basic news, proved one alarm set/fire path at `7:43 AM`, exposed comma-separated/short alarm follow-up parsing risk, showed stock alarm replacement yes/no rules that needed cloud handling, and showed photo gallery still failing when `shared/yes_no` ASR came back empty
|
||||
- `jibo test 24` showed alarm replacement yes/no working, but exposed empty `clock/alarm_set_value` and `gallery/gallery_preview` turns falling into generic `I heard you` fallback speech; it also showed `CLIENT_NLU cancel` inside `clock/alarm_set_value` re-asking for an alarm value instead of closing the prompt
|
||||
|
||||
## Immediate `1.0.18` Queue
|
||||
|
||||
@@ -75,6 +76,7 @@ Current release theme:
|
||||
- JiboOS Nimbus checks `match.cloudSkill === "news"` and waits for a cloud response
|
||||
- `jibo test 22` captured the phrase `So, play the news.` reaching the `news` intent, but live behavior was not cleanly confirmed
|
||||
- `jibo test 23` successfully played the synthetic quick brief
|
||||
- original Pegasus `report-skill` news tests cover the next expansion shape: category preferences, default categories, duplicate filtering, missing-summary filtering, child/unidentified-speaker content filtering, and headline image metadata
|
||||
- Exit criteria:
|
||||
- live `tell me the news` reaches the Nimbus-shaped path
|
||||
- the robot behavior feels like a cloud skill response, not generic chat playback
|
||||
@@ -96,6 +98,7 @@ Current release theme:
|
||||
- Latest evidence:
|
||||
- `jibo test 22` did not show `Backup_*` HTTP traffic during the backup complaint
|
||||
- stock `@be/surprises-ota` drives the backup notification from robot-local `jibo.scheduler.backupStatus`
|
||||
- original `surprises-ota` tests make backup and OTA notifications contextual-priority prompts, with repeat suppression through last-notification timestamps
|
||||
- a spoken `take a backup` command currently routes as generic chat and is not the same as proving the local backup scheduler path
|
||||
- `jibo test 23` again showed backup-in-progress sluggishness and update-menu blockage while backups were active; explicit backup voice launch remains unwired
|
||||
- Exit criteria:
|
||||
@@ -113,10 +116,13 @@ Current release theme:
|
||||
- Current code:
|
||||
- alarm values parse explicit, compact, spaced, comma-separated, hyphenated, and local-context ambiguous times
|
||||
- short alarm/timer value replies are accepted during clock value follow-up rules instead of being filtered out before parsing
|
||||
- empty alarm/timer value turns complete locally as no-input instead of falling through to generic Nimbus speech
|
||||
- missing alarm times stay in local `@be/clock` clarification
|
||||
- alarm cancel can reuse the last active clock domain
|
||||
- cancel inside a clock value prompt maps to local clock `cancel`
|
||||
- stock alarm replacement/no-alarm prompts use the constrained yes/no path
|
||||
- gallery opens as `@be/gallery`; snapshot and photobooth open through `@be/create`
|
||||
- empty `gallery/gallery_preview` turns complete locally as no-input instead of relaunching Nimbus fallback speech
|
||||
- passive gallery/create context no longer reopens stale cloud turns
|
||||
- `shared/yes_no` no-input fallback and repeated create keeper cleanup were added after `jibo test 22`
|
||||
- Latest evidence:
|
||||
@@ -125,9 +131,14 @@ Current release theme:
|
||||
- `ffmpeg` failures were present during the same test window, so alarm/gallery retest should separate transcript quality from payload shape
|
||||
- `jibo test 23` set and fired a `7:43 AM` alarm, then failed a later clarify/replacement path when the robot heard `- Time. - 7, 14.` and stock NLU converted that to `7:00 PM`
|
||||
- `jibo test 23` photo gallery got stuck on `shared/yes_no` turns with empty ASR, not on a transcript-bearing `yes` that the cloud mapped incorrectly
|
||||
- `jibo test 24` recognized `Yes.` for `clock/alarm_timer_change`, but empty `clock/alarm_set_value` produced `I heard you`; current source now keeps that as local no-input
|
||||
- `jibo test 24` showed photo/gallery blue-ring cleanup improved and create keeper completion working, but empty `gallery/gallery_preview` produced `I heard you`; current source now keeps that as local no-input
|
||||
- original clock tests confirm cancel inside the alarm value prompt must close without scheduling, existing-alarm `keep` must preserve KB/scheduler state, and existing-alarm `delete` or `cancel` must clear it
|
||||
- original gallery tests confirm empty-gallery `yes` redirects to `@be/create`, empty-gallery `no` exits, media-load failure exits, and delete confirmation only deletes on a positive `yes`
|
||||
- Exit criteria:
|
||||
- gallery opens, offers to take a picture if empty, accepts `yes`, and hands into create
|
||||
- alarm set, clarify, replacement yes/no, and cancel/delete flows behave locally and agree with the menu state
|
||||
- alarm set, clarify, replacement yes/no, cancel from value prompt, and cancel/delete flows behave locally and agree with the menu state
|
||||
- alarm replacement and deletion regression checks verify both websocket payload shape and persistent robot menu state where possible
|
||||
- failures caused by collapsed STT transcripts are logged as STT issues rather than misdiagnosed as payload bugs
|
||||
- Next action:
|
||||
- re-run a stock OS `1.9` regression bundle before declaring `1.0.18` complete
|
||||
@@ -187,10 +198,13 @@ Current release theme:
|
||||
- timer/alarm menu, value, clarify, and delete are implemented
|
||||
- compact, spoken, comma-separated, and local-context alarm parsing has focused tests
|
||||
- short clock value replies under `clock/alarm_set_value` and `clock/timer_set_value` are not filtered out by websocket finalization
|
||||
- empty clock value turns produce local no-input instead of generic Nimbus fallback speech
|
||||
- `CLIENT_NLU cancel` inside a clock value prompt maps to local clock `cancel`
|
||||
- alarm replacement/no-alarm yes/no prompts are mapped as constrained local prompts
|
||||
- client NLU alarm clarify/cancel cases from `jibo test 20` and `jibo test 21` are reflected in source
|
||||
- client NLU alarm clarify/cancel cases from `jibo test 20`, `jibo test 21`, and `jibo test 24` are reflected in source
|
||||
- Follow-up:
|
||||
- live regression remains in the immediate queue
|
||||
- add fixture coverage for original clock-test branches that are not yet mirrored in `.NET`: no-alarm query `yes`/`no`, existing-alarm `keep` versus `delete`, and cross-domain `OtherSet` behavior
|
||||
|
||||
### Photo / Gallery / Create Family
|
||||
|
||||
@@ -200,9 +214,11 @@ Current release theme:
|
||||
- gallery, snapshot, and photobooth voice paths route to the correct local skills
|
||||
- media metadata persists locally
|
||||
- `/media/{path}` serves the current text-body placeholder payload
|
||||
- empty `gallery/gallery_preview` turns produce local no-input instead of generic Nimbus fallback speech
|
||||
- repeated empty `create/is_it_a_keeper` turns redirect to `@be/idle` after the second miss
|
||||
- Follow-up:
|
||||
- live regression remains in the immediate queue
|
||||
- add fixture coverage for original gallery-test branches that are not yet mirrored in `.NET`: empty-gallery `yes` redirect to create, empty-gallery `no` exit, media-load failure exit, and delete confirmation `yes`/`no`
|
||||
- binary-safe media storage remains future work
|
||||
|
||||
### Constrained Yes-No Cleanup
|
||||
@@ -294,6 +310,7 @@ Current release theme:
|
||||
- Current evidence:
|
||||
- `@be/settings` contains update and backup flows
|
||||
- `@be/restore` waits for a UGC key, runs restore, and reboots
|
||||
- original OTA surprise tests treat backup/download status as robot-local scheduler state, not as a direct cloud backup command path
|
||||
- no-op update fabrication has been removed from `.NET`
|
||||
- Exit criteria:
|
||||
- no phantom "always has updates" behavior
|
||||
@@ -310,6 +327,7 @@ Current release theme:
|
||||
- Current evidence:
|
||||
- `jibo test 22` showed `ffmpeg` and `whisper.cpp` failures
|
||||
- `jibo test 23` did not show the same decode failure pattern, but gallery yes/no turns still produced empty ASR
|
||||
- `jibo test 24` still had collapsed or empty transcripts in alarm/gallery paths, including `Sudden alarm.`, `I'm setting alarm for seven.`, empty clock value input, and empty gallery preview input
|
||||
- current source now skips local whisper when buffered audio does not contain an Opus identification header
|
||||
- yes/no and alarm flows are especially sensitive to short or collapsed transcripts
|
||||
- Implementation notes:
|
||||
@@ -362,6 +380,11 @@ Current release theme:
|
||||
- which source should provide headlines for hosted OpenJibo
|
||||
- whether news belongs under a broader Lasso-style aggregation service
|
||||
- how to keep content short and Jibo-native
|
||||
- Source-backed implementation notes:
|
||||
- original report-skill news tests expect default general, technology, sports, and business headlines for unidentified users
|
||||
- category counts are preference-dependent: one active category gets multiple headlines, two categories get two each, and three or more get one each
|
||||
- filter items without summaries, corrections, duplicate headlines, banned words, and adult headlines for children or unidentified speakers
|
||||
- include image view metadata with unique IDs, category labels, source image URLs, and sane scaling
|
||||
|
||||
### 14. Proactivity Selector And Surprise Offers
|
||||
|
||||
|
||||
@@ -57,6 +57,8 @@ public sealed class JiboInteractionService(
|
||||
"alarm_menu" => BuildClockLaunchDecision("alarm", "Opening the alarm."),
|
||||
"timer_delete" => BuildClockLaunchDecision("timer_delete", "timer", "delete", "Canceling the timer."),
|
||||
"alarm_delete" => BuildClockLaunchDecision("alarm_delete", "alarm", "delete", "Canceling the alarm."),
|
||||
"timer_cancel" => BuildClockLaunchDecision("timer_cancel", "timer", "cancel", "Canceling the timer."),
|
||||
"alarm_cancel" => BuildClockLaunchDecision("alarm_cancel", "alarm", "cancel", "Canceling the alarm."),
|
||||
"timer_value" => BuildTimerValueDecision(lowered, isTimerValueTurn, clientEntities),
|
||||
"alarm_value" => BuildAlarmValueDecision(lowered, isAlarmValueTurn, referenceLocalTime, clientEntities),
|
||||
"timer_clarify" => BuildClockClarifyDecision("timer_clarify", "timer", "How long should I set the timer for?"),
|
||||
@@ -218,6 +220,19 @@ public sealed class JiboInteractionService(
|
||||
return "alarm_value";
|
||||
}
|
||||
|
||||
if (IsCancelRequest(clientIntent, loweredTranscript))
|
||||
{
|
||||
if (isAlarmValueTurn)
|
||||
{
|
||||
return "alarm_cancel";
|
||||
}
|
||||
|
||||
if (isTimerValueTurn)
|
||||
{
|
||||
return "timer_cancel";
|
||||
}
|
||||
}
|
||||
|
||||
if ((string.Equals(clientIntent, "start", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(clientIntent, "set", StringComparison.OrdinalIgnoreCase)) &&
|
||||
clientEntities.TryGetValue("domain", out var startDomain))
|
||||
@@ -1098,6 +1113,13 @@ public sealed class JiboInteractionService(
|
||||
"alarm for");
|
||||
}
|
||||
|
||||
private static bool IsCancelRequest(string? clientIntent, string loweredTranscript)
|
||||
{
|
||||
return string.Equals(clientIntent, "cancel", StringComparison.OrdinalIgnoreCase) ||
|
||||
string.Equals(clientIntent, "stop", StringComparison.OrdinalIgnoreCase) ||
|
||||
loweredTranscript is "cancel" or "stop" or "never mind" or "nevermind";
|
||||
}
|
||||
|
||||
private static bool IsClockTimerValueTurn(
|
||||
IReadOnlyList<string> clientRules,
|
||||
IReadOnlyList<string> listenRules)
|
||||
|
||||
@@ -511,6 +511,8 @@ public sealed class WebSocketTurnFinalizationService(
|
||||
!string.Equals(plan.IntentName, "clock_menu", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(plan.IntentName, "timer_menu", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(plan.IntentName, "alarm_menu", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(plan.IntentName, "timer_cancel", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(plan.IntentName, "alarm_cancel", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(plan.IntentName, "timer_clarify", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(plan.IntentName, "alarm_clarify", StringComparison.OrdinalIgnoreCase) &&
|
||||
!string.Equals(plan.IntentName, "timer_value", StringComparison.OrdinalIgnoreCase) &&
|
||||
@@ -794,6 +796,8 @@ public sealed class WebSocketTurnFinalizationService(
|
||||
private static bool IsLocalNoInputRule(string rule)
|
||||
{
|
||||
return string.Equals(rule, "clock/alarm_timer_okay", StringComparison.OrdinalIgnoreCase) ||
|
||||
IsClockValueRule(rule) ||
|
||||
IsGalleryPreviewRule(rule) ||
|
||||
IsConstrainedYesNoRule(rule);
|
||||
}
|
||||
|
||||
@@ -803,6 +807,11 @@ public sealed class WebSocketTurnFinalizationService(
|
||||
string.Equals(rule, "clock/timer_set_value", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool IsGalleryPreviewRule(string rule)
|
||||
{
|
||||
return string.Equals(rule, "gallery/gallery_preview", StringComparison.OrdinalIgnoreCase);
|
||||
}
|
||||
|
||||
private static bool IsConstrainedYesNoRule(string rule)
|
||||
{
|
||||
return string.Equals(rule, "clock/alarm_timer_change", StringComparison.OrdinalIgnoreCase) ||
|
||||
|
||||
@@ -633,6 +633,28 @@ public sealed class JiboInteractionServiceTests
|
||||
Assert.Equal("delete", decision.SkillPayload["clockIntent"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildDecisionAsync_ClientNluCancelFromAlarmValuePrompt_MapsToClockCancelIntent()
|
||||
{
|
||||
var service = CreateService();
|
||||
|
||||
var decision = await service.BuildDecisionAsync(new TurnContext
|
||||
{
|
||||
RawTranscript = "cancel",
|
||||
NormalizedTranscript = "cancel",
|
||||
Attributes = new Dictionary<string, object?>
|
||||
{
|
||||
["clientIntent"] = "cancel",
|
||||
["clientRules"] = new[] { "clock/alarm_set_value" }
|
||||
}
|
||||
});
|
||||
|
||||
Assert.Equal("alarm_cancel", decision.IntentName);
|
||||
Assert.Equal("@be/clock", decision.SkillName);
|
||||
Assert.Equal("alarm", decision.SkillPayload!["domain"]);
|
||||
Assert.Equal("cancel", decision.SkillPayload["clockIntent"]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task BuildDecisionAsync_SetTimerWithoutDuration_AsksForClarification()
|
||||
{
|
||||
|
||||
@@ -777,6 +777,37 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.False(listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").TryGetProperty("time", out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClientNlu_CancelFromAlarmValuePrompt_PassesClockCancelInsteadOfClarifyingAgain()
|
||||
{
|
||||
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||
{
|
||||
HostName = "neo-hub.jibo.com",
|
||||
Path = "/listen",
|
||||
Kind = "neo-hub-listen",
|
||||
Token = "hub-clock-cancel-alarm-value-token",
|
||||
Text = """{"type":"LISTEN","transID":"trans-clock-cancel-alarm-value","data":{"rules":["clock/alarm_set_value","globals/gui_nav","globals/global_commands_launch"],"mode":"CLIENT_NLU"}}"""
|
||||
});
|
||||
|
||||
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||
{
|
||||
HostName = "neo-hub.jibo.com",
|
||||
Path = "/listen",
|
||||
Kind = "neo-hub-listen",
|
||||
Token = "hub-clock-cancel-alarm-value-token",
|
||||
Text = """{"type":"CLIENT_NLU","transID":"trans-clock-cancel-alarm-value","data":{"entities":{},"intent":"cancel","rules":["clock/alarm_set_value"]}}"""
|
||||
});
|
||||
|
||||
Assert.Equal(2, replies.Count);
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal("cancel", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||
Assert.Equal("clock/alarm_set_value", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules")[0].GetString());
|
||||
Assert.Equal("alarm", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClientNlu_CancelFromAlarmQueryMenu_UsesLastClockDomainAndDeletesAlarm()
|
||||
{
|
||||
@@ -936,6 +967,66 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.Equal("clock/alarm_timer_okay", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules")[0].GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClientAsr_AlarmValuePromptEmptyReply_MapsToLocalNoInputInsteadOfFallback()
|
||||
{
|
||||
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||
{
|
||||
HostName = "neo-hub.jibo.com",
|
||||
Path = "/listen",
|
||||
Kind = "neo-hub-listen",
|
||||
Token = "hub-clock-alarm-value-noinput-token",
|
||||
Text = """{"type":"LISTEN","transID":"trans-clock-alarm-value-noinput","data":{"rules":["clock/alarm_set_value","globals/gui_nav","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-alarm-value-noinput-token",
|
||||
Text = """{"type":"CLIENT_ASR","transID":"trans-clock-alarm-value-noinput","data":{}}"""
|
||||
});
|
||||
|
||||
Assert.Equal(2, replies.Count);
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal(string.Empty, listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||
Assert.Equal("clock/alarm_set_value", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules")[0].GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClientAsr_GalleryPreviewEmptyReply_MapsToLocalNoInputInsteadOfFallback()
|
||||
{
|
||||
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||
{
|
||||
HostName = "neo-hub.jibo.com",
|
||||
Path = "/listen",
|
||||
Kind = "neo-hub-listen",
|
||||
Token = "hub-gallery-preview-noinput-token",
|
||||
Text = """{"type":"LISTEN","transID":"trans-gallery-preview-noinput","data":{"rules":["gallery/gallery_preview","globals/gui_nav","globals/mim_repeat","globals/mim_thanks","globals/global_commands_launch"]}}"""
|
||||
});
|
||||
|
||||
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||
{
|
||||
HostName = "neo-hub.jibo.com",
|
||||
Path = "/listen",
|
||||
Kind = "neo-hub-listen",
|
||||
Token = "hub-gallery-preview-noinput-token",
|
||||
Text = """{"type":"CLIENT_ASR","transID":"trans-gallery-preview-noinput","data":{}}"""
|
||||
});
|
||||
|
||||
Assert.Equal(2, replies.Count);
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal(string.Empty, listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||
Assert.Equal("gallery/gallery_preview", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules")[0].GetString());
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClientAsr_SnapAPicture_RedirectsIntoCreateSkill()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user