Compare commits

27 Commits

Author SHA1 Message Date
Jacob Dubin
a47c90c9c3 Polish weather phrasing for current and forecast replies 2026-05-16 10:16:34 -05:00
Jacob Dubin
393c34055d Prefer forecast hi lo for current weather 2026-05-16 10:01:40 -05:00
Jacob Dubin
f9b728c2a0 Add seasonal and presence charm batches 2026-05-16 09:09:18 -05:00
Jacob Dubin
c87af4686c Add seasonal Build B legacy MIM imports 2026-05-16 08:53:07 -05:00
Jacob Dubin
84759f51de Add Build B charm descriptors and mood replies 2026-05-16 08:39:45 -05:00
Jacob Dubin
c8beb0d1f0 Expand Build B mood and persona follow-ups 2026-05-16 08:05:42 -05:00
Jacob Dubin
e43b4f05f0 Port more legacy charm MIMs into Build B 2026-05-14 22:21:36 -05:00
Jacob Dubin
2677cf9dac Refine commit message handling 2026-05-14 22:06:25 -05:00
Jacob Dubin
20b84632ec Close memory recall turns so recognition does not keep mic open 2026-05-14 21:58:00 -05:00
Jacob Dubin
5718edecaf shortened timeout in conversation broker 2026-05-14 21:47:10 -05:00
Jacob Dubin
40b5b8e4a8 Expand persona follow-ups for identity and favorites 2026-05-14 21:39:17 -05:00
Jacob Dubin
8f7c118fb3 Expand persona inventory and add favorite-family prompts 2026-05-14 21:16:50 -05:00
Jacob Dubin
c30363ec9f Add person-aware favorites and multitenant state scaffolding 2026-05-14 21:15:14 -05:00
Jacob Dubin
ec786be797 Add person-aware state and sync roadmap 2026-05-14 20:48:55 -05:00
Jacob Dubin
f299cef9be Add stateful shopping and to-do list follow-ups 2026-05-14 07:44:46 -05:00
Jacob Dubin
f5e37729ab Expand legacy Build A routing and emotion replies 2026-05-14 06:48:39 -05:00
Jacob Dubin
7297017250 Port legacy persona and emotion replies 2026-05-14 06:44:22 -05:00
Jacob Dubin
66b89f3cee Add Build A legacy MIM import support 2026-05-13 23:22:05 -05:00
Jacob Dubin
11a3e4ef13 Add legacy MIM importer and seed Build A content 2026-05-13 23:18:18 -05:00
Jacob Dubin
7c6dacdbd8 Fix weather, yes/no, and news integrations 2026-05-12 20:36:43 -05:00
Jacob Dubin
9093b429ca Harden weather date parsing and add request diagnostics 2026-05-12 07:52:38 -05:00
Jacob Dubin
df3b34c8ad Add weekly weather cards and improve news API fallback 2026-05-11 22:44:56 -05:00
Jacob Dubin
67c738fae3 Improve weather and news diagnostics for report skills 2026-05-11 19:59:15 -05:00
Jacob Dubin
c0e9b41cd1 Revert weather report-skill routing to stabilize playback 2026-05-11 07:26:56 -05:00
Jacob Dubin
af2fdd230c Improve weather routing and news API fallback 2026-05-11 07:15:11 -05:00
Jacob Dubin
0c597ebbf8 Fix weather forecast parsing and NewsAPI fallback 2026-05-10 23:08:06 -05:00
Jacob Dubin
4bc87f927b Broaden yes no parsing for proactive follow ups 2026-05-10 21:22:25 -05:00
147 changed files with 465179 additions and 289 deletions

View File

@@ -654,6 +654,8 @@ Current release theme:
- Follow-up:
- add durable persistence path for personal facts
- broaden fact categories further (multi-person household memory, relationship cues, and corrective updates)
- add explicit person-scoped state so future interactions can distinguish household members inside the same loop
- define the first server-to-server sync envelope for durable state before we need it in production
### 24. Memory-Triggered Proactivity Baseline
@@ -669,6 +671,7 @@ Current release theme:
- expand proactivity beyond pizza to additional Pegasus-backed categories
- add cooldown/throttle policy and observability around proactive offer frequency
- connect memory store to durable multi-tenant persistence
- keep the sync story visible so stateful offers can survive a multi-server deployment later
### 25. Weather Report-Skill Launch Compatibility
@@ -760,6 +763,106 @@ Current release theme:
- first schema for list items + ownership scope
- initial voice flows and follow-up intent handling defined
### 29. Legacy MIM Personality Import Ladder
- Status: `in_progress`
- Tags: `content`, `protocol`, `docs`
- Why now:
- we already have a chitchat/content scaffold that can render stock-compatible personality replies
- the legacy `chitchat-mims` tree is mostly declarative content, so a phased import can add visible charm fast
- this is the best near-term path to get Jibo feeling more interactive without needing a full Pegasus runtime clone
- What is possible today:
- direct scripted replies through the existing content catalog
- stock-compatible payloads with `skillId`, `mim_id`, `mim_type`, `prompt_id`, and ESML
- current examples already prove the shape for pizza, dance, weather, news, and generic chat
- What we need to build:
1. a MIM inventory importer that can scan the legacy tree and normalize `skill_id`, `mim_id`, prompt text, and metadata
2. a prompt-selection layer that can choose by category and condition metadata
3. a safe ESML/prompt renderer for imported content
- What can be ported with each build:
- Build A: declarative prompt packs
- `core-responses`
- `deflector`
- the simplest `emotion-responses`
- direct `scripted-responses` that are just prompt lists
- Build B: conditioned prompt packs
- `gqa-responses`
- structured emotion prompts with `condition` gates
- any response families that only need simple state or Jibo-emotion checks
- Build C: conversation families
- richer `scripted-responses` that need follow-up state
- holiday / special-date personality sets
- more nuanced chitchat branches that depend on context-aware routing
- Build D: full parity cleanup
- larger cross-skill collections
- any MIMs that depend on Pegasus-only parser assumptions
- any files that need dedicated runtime abstraction instead of catalog lookup
- Low-hanging fruit for tonight:
- import the smallest declarative packs first so we can test something tomorrow
- prioritize anything that is pure prompt text with no complex branching
- keep the first pass limited to content that maps cleanly onto the current catalog shape
- Progress update (`2026-05-13`):
- added the first Build A importer scaffold in the cloud content repository
- checked in a small seed bundle under `Content/LegacyMims/BuildA`
- added focused importer tests for prompt stripping, bucketing, and merge behavior
- expanded Build A with additional easy scripted-response packs for identity and persona replies
- started Build B with source-backed scripted-response packs for work, food, home, birthplace, language, hobby, and material questions
- Tomorrow test target:
- verify imported personality replies show up through the existing chitchat route
- confirm the emitted payload still looks like a stock skill response
- confirm the imported content does not disturb existing weather/news/pizza flows
- Exit criteria:
- a first importer path exists for the simplest legacy MIM files
- at least one legacy prompt pack is running through OpenJibo content instead of hand-authored fallback text
- we have a clear second-wave list for the more conditional MIM families
### 30. Original Personalized Function Inventory
- Status: `discovery`
- Tags: `content`, `docs`, `protocol`
- Why now:
- we are actively porting persona and memory slices, so we need a bounded checklist of the original Jibo charm surfaces
- the goal is to keep the next few passes focused on personality-rich wins instead of letting the work sprawl
- Known sources:
- legacy Jibo OS/Pegasus chitchat and MIM response families
- current OpenJibo persona, memory, and greeting work as the implementation target
- Inventory to track:
- identity and origin questions
- personality and capability questions
- favorite-style prompts like `what is your favorite color`
- attraction and preference prompts like `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, and `do you like kids`
- charm/capability prompts like `can you laugh` and `can you dance`
- mood / affect questions
- recognition follow-ups like `do you know me`
- follow-up state prompts that should stay warm and locally grounded
- Next pass targets:
- document the remaining persona inventory so we keep a clean checklist for the next passes
- keep the favorites family moving with source-backed imports where available, and temporary runtime replies only when the source is missing
- keep adding small sourced personality batches, especially the legacy `R2D2`, `sun`, `space`, `kids`, and charm prompts
- keep adding 1-3 persona prompts per pass with tests
- prefer source-backed MIM imports when the legacy text is available, and use a temporary runtime reply only when needed to unblock user value
- Mood follow-up work in flight:
- source-backed happy/sad/angry response packs are now part of Build B
- small-talk aliases like `what are you up to` and `how are things` now stay on the emotion-query path
- Descriptor charm work in flight:
- source-backed `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, `are you mischievous`, and `are you likable` prompts are now in Build B
- these keep the self-description lane warm while we build toward seasonal and holiday charm
- Seasonal charm work in flight:
- source-backed holiday, New Year's, Halloween, spring, and gift prompts are now part of Build B
- `RN_` holiday greeting files are now bucketed as greetings so seasonal replies stay visible in the catalog
- Presence and thought follow-ups in flight:
- `welcome back`, `what are you thinking`, `what have you been doing`, and `what did you do` are now part of Build B
- these keep the social surface lively while the memory and multitenant tracks keep advancing in parallel
- Next queued persona surfaces:
- richer identity follow-ups like `who is this`, `do you know me`, `do you remember me`, and `can you recognize me`
- mood and affect prompts like `how are you`, `are you happy`, `are you sad`, and `are you angry`
- self-description charm like `what's your name`, `do you have a nickname`, and `do you like being Jibo`
- additional legacy source-backed `RI_USR` prompts where the text is short and the behavior is easy to verify
- Exit criteria:
- a stable checklist exists for the original persona surface
- each pass can be scoped to a small batch of prompts
- the backlog makes it obvious what is still missing without losing momentum
## Suggested Order
Before closing `1.0.18`:
@@ -790,6 +893,7 @@ For `1.0.19`:
14. Provider-backed news and weather parity polish
15. Grocery list capability discovery and MVP selection
16. Lasso, identity, and onboarding as larger discovery-driven tracks
17. Legacy MIM personality import ladder and first declarative prompt packs
For `1.0.20` and beyond:

View File

@@ -20,6 +20,54 @@ The goal is to keep compatibility work steady while shipping personality and cap
- start building reusable content hooks for question-vs-command style responses
- keep first implementation rule-based and test-backed
### 1a. Original Personalized Function Inventory
Keep a running checklist of the legacy persona questions and identity surfaces we want to preserve or port:
- identity and origin: `what are you`, `who are you`, `what is Jibo`, `who made you`, `where are you from`
- persona and capability: `do you have a personality`, `what is your job`, `how much do you know`, `what do you want`
- self-description and social charm: `what's your name`, `do you have a nickname`, `do you like being Jibo`, `are there others like you`
- favorite-style prompts: `what is your favorite color`, `what is your favorite food`, `what is your favorite music`
- attraction and preference prompts: `what is your favorite flower`, `do you like R2D2`, `do you like the sun`, `do you like space`, `do you like kids`
- capability and charm prompts: `can you laugh`, `can you dance`
- affect and mood: `how are you`, `are you happy`, `are you sad`, `are you angry`
- memory and identity recall: `who am i`, `what is my name`, `when is my birthday`, `what is my favorite music`
- greeting and presence charm: `good morning`, `welcome back`, `who is this`, person-aware greeting follow-ups
- recognition follow-ups: `do you know me`, `do you remember me`, `can you recognize me`
- seasonal and contextual charm: holiday prompts, pizza day, surprise offers, personal report personality hooks
- conversational follow-ups that should stay local and warm instead of falling into generic chat
Current batch note:
- `favorite color`, `favorite food`, and `favorite music` are the first small favorites-family slice
- the next source-backed batch now includes `favorite flower`, `R2D2`, `sun`, `space`, `kids`, plus a couple of charm prompts like `can you laugh` and `can you dance`
- the follow-up mood batch now includes `how are things`, `how is your day`, `are you sad`, and `are you angry`
- the personality follow-up batch now includes `what are you up to` and `what are you doing` so small talk stays warm and local instead of falling into generic chat
- the descriptor batch now includes `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, `are you mischievous`, and `are you likable`
- the seasonal batch now includes `what holidays do you celebrate`, New Year's resolution questions, `happy holidays`, `what halloween costume`, spring suggestions, and holiday gift prompts
- the latest social batch adds `welcome back`, `what are you thinking`, `what have you been doing`, and `what did you do` so presence and charm stay lively without distracting from the memory roadmap
- this pass keeps Build B moving while still favoring source-backed phrasing and preserving the command-vs-question boundary
- the next passes should keep the same pattern and prefer source-backed phrasing whenever the legacy MIM text is available
- if a source-backed legacy line is missing, use a temporary direct reply only to keep the pass moving, then backfill source text later
- after the favorites batch, the next doc pass should focus on richer persona follow-ups and the remaining memory/presence charm surfaces
- Build B is now reserved for the next source-backed scripted-response batch:
- `how do you work`
- `what do you eat`
- `where do you live`
- `where were you born`
- `what languages do you speak`
- `what do you like to do`
- `what are you made of`
- `what is your favorite flower`
- `do you like R2D2`
- `do you like the sun`
- `do you like space`
- `do you like kids`
- `can you laugh`
- `can you dance`
The goal is to port these in small batches, capture the source-backed phrasing where possible, and keep a test for each batch so the list never becomes a vague backlog graveyard.
### 2. Reliability And Device Proof
- complete update/backup/restore proof path with captures and operator docs
@@ -31,6 +79,7 @@ The goal is to keep compatibility work steady while shipping personality and cap
- prioritize small source-backed slices from Pegasus/JiboOS that can be shipped safely
- keep Nimbus and stock payload compatibility as the release guardrail
- avoid broad subsystem rewrites without tests and live-capture evidence
- keep the legacy prompt inventory visible in the backlog so porting stays paced and traceable
### 4. Holidays And Seasonal Personality
@@ -43,6 +92,15 @@ The goal is to keep compatibility work steady while shipping personality and cap
- define tenant boundaries across account, loop, device, and person-memory records
- add storage abstractions that can move from in-memory/local JSON to hosted SQL/Blob without reworking behavior layers
- implement memory-ready schemas and repository contracts for user facts (names, birthdays, personal dates, preferences) with strict tenant scoping
- seed person-aware state keys now so future interactions can scope to account + loop + device + person without another shape change
- keep stateful interaction flows repository-backed instead of embedding more ad hoc metadata in the websocket layer
### 6. Multi-Server Sync Path
- document the eventual sync boundary for stateful data that should move between servers
- treat the first pass as repository-local durability, then layer replication and conflict handling on top
- prefer explicit change records or versioned state snapshots over implicit last-writer wins when we outgrow a single node
- keep cross-server reconciliation out of the hot path until the single-server semantics are stable
## First Implemented Slice In `1.0.19`
@@ -105,6 +163,78 @@ The fifth delivered slice adds provider-backed weather content while preserving
- simple location extraction is supported for phrasing like `what's the weather in Chicago tomorrow`
- provider config supports appsettings and `OPENWEATHER_API_KEY` environment fallback for deployment
## Personality Import Ladder
This is the practical plan for importing legacy Jibo `mims` into OpenJibo without pretending we already have a full Pegasus runtime.
### What Is Possible Today
OpenJibo can already host a meaningful subset of legacy personality content because it has:
- a shared catalog for content-driven replies
- chitchat state-machine routing with route metadata
- outbound payload support for `skillId`, `mim_id`, `mim_type`, `prompt_id`, `prompt_sub_category`, and ESML
- existing examples that already behave like legacy MIMs for pizza, dance, news, weather, and generic chat
### What We Need To Build
To move from hand-wired examples to broader imports, we need three small platform pieces:
1. a MIM inventory importer that can scan the legacy tree and produce a normalized catalog
2. a prompt-selection layer that can choose by `skill_id`, `mim_id`, prompt category, and condition metadata
3. a safe ESML/prompt renderer that preserves existing stock-compatible payload shapes
### What Can Be Ported With Each Build
#### Build A: Declarative Prompt Packs
Port immediately:
- `core-responses`
- `deflector`
- the simplest `emotion-responses`
- any `scripted-responses` that are just direct prompt lists with no special state machine
Why these first:
- they are already close to the current `JiboExperienceCatalog` model
- they give us user-visible personality quickly
- they are the best fit for low-risk testing tomorrow
#### Build B: Conditioned Prompt Packs
Port after the importer and renderer are in place:
- `gqa-responses`
- structured emotion responses with `condition` gates
- prompt sets that select different replies by user state or Jibo state
Why these next:
- they are still mostly declarative
- they need a small amount of condition evaluation, but not a new conversation engine
#### Build C: Conversation Families
Port after Build B:
- richer `scripted-responses` families that depend on follow-up state
- special-date / holiday personality sets
- more nuanced chitchat branches that need context-aware routing
Why these later:
- they need state and follow-up behavior, not just prompt selection
- they are where personality feels most alive, but they are also where bugs will be easiest to introduce
#### Build D: Full Parity Cleanup
Port after the core ladder is stable:
- large cross-skill collections
- any MIMs that depend on Pegasus-only parser assumptions
- any files that need a dedicated runtime abstraction instead of catalog lookup
## System Diagram Alignment Snapshot (`2026-05-06`)
Legacy architecture (`system_diagram.png`) has been mapped to current OpenJibo cloud services so release execution stays anchored to:
@@ -196,17 +326,19 @@ First completed slice in this personal-report parity track:
## Next Slices
1. Dialog parsing expansion (queued next as of `2026-05-06`; more phrase variants, ambiguity handling, and transcript-to-intent guardrails)
2. Presence-aware greetings and identity-triggered proactivity (reactive/proactive split, cooldowns, person-aware greeting hooks)
3. Personal report parity slices (weather visual layer, live news path, commute path, calendar parity matrix)
4. Holidays and seasonal personality slice beyond pizza day (time-scoped content backed by memory/proactivity path)
5. Durable memory persistence path (swap in provider-backed multi-tenant storage while preserving behavior contracts)
6. Update/backup/restore end-to-end proof (operator-run and documented)
7. STT noise-screening and short-utterance reliability pass
8. Provider-backed news expansion and deeper weather parity using Pegasus-backed contracts
9. Capture indexing and retention boundary for group testing
1. MIM import foundation for personality expansion
2. Dialog parsing expansion
3. Presence-aware greetings and identity-triggered proactivity
4. Personal report parity slices
5. Holidays and seasonal personality slice beyond pizza day
6. Durable memory persistence path
7. Update/backup/restore end-to-end proof
8. STT noise-screening and short-utterance reliability pass
9. Provider-backed news expansion and deeper weather parity
10. Capture indexing and retention boundary for group testing
For slices 1-5, use Pegasus phrase lists, MIM IDs, and behavior patterns as the source anchor before broadening into OpenJibo-native improvements.
For slice 1, use the new import ladder above to keep the work grounded in what OpenJibo can already render today versus what needs new scaffolding.
For slices 2-5, use Pegasus phrase lists, MIM IDs, and behavior patterns as the source anchor before broadening into OpenJibo-native improvements.
## Definition Of Done

View File

@@ -39,6 +39,8 @@
"BaseUrl": "https://newsapi.org",
"ApiKey": "5df93a83db9c4c6888f3e06c4a53144f",
"Country": "us",
"Language": "en",
"FallbackQuery": "robotics OR technology OR science",
"DefaultCategories": [ "general", "technology", "sports", "business" ],
"CacheTtlSeconds": 300,
"FailureCacheTtlSeconds": 45

View File

@@ -13,6 +13,7 @@ public interface ICloudStateStore
CloudSession OpenSession(string kind, string? deviceId, string? token, string? hostName, string? path);
CloudSession? FindSessionByToken(string token);
IReadOnlyList<LoopRecord> GetLoops();
IReadOnlyList<PersonRecord> GetPeople();
IReadOnlyList<UpdateManifest> ListUpdates(string? subsystem = null, string? filter = null);
UpdateManifest? GetUpdateFrom(string? subsystem, string? fromVersion, string? filter);
UpdateManifest CreateUpdate(string? fromVersion, string? toVersion, string? changes, string? shaHash, long? length, string? subsystem, string? filter, IDictionary<string, object?>? dependencies);

View File

@@ -5,12 +5,19 @@ public interface IJiboExperienceContentRepository
Task<JiboExperienceCatalog> GetCatalogAsync(CancellationToken cancellationToken = default);
}
public sealed class JiboConditionedReply
{
public string Condition { get; init; } = string.Empty;
public string Reply { get; init; } = string.Empty;
}
public sealed class JiboExperienceCatalog
{
public IReadOnlyList<string> Jokes { get; init; } = [];
public IReadOnlyList<string> DanceAnimations { get; init; } = [];
public IReadOnlyList<string> GreetingReplies { get; init; } = [];
public IReadOnlyList<string> HowAreYouReplies { get; init; } = [];
public IReadOnlyList<JiboConditionedReply> EmotionReplies { get; init; } = [];
public IReadOnlyList<string> PersonalityReplies { get; init; } = [];
public IReadOnlyList<string> PizzaReplies { get; init; } = [];
public IReadOnlyList<string> SurpriseReplies { get; init; } = [];

View File

@@ -20,4 +20,9 @@ public sealed record NewsHeadline(
public sealed record NewsBriefingSnapshot(
IReadOnlyList<NewsHeadline> Headlines,
string? SourceName = null);
string? SourceName = null,
string? ProviderStatus = null,
string? ProviderMessage = null,
int? ProviderHttpStatusCode = null,
string? ProviderEndpoint = null,
string? ProviderErrorCode = null);

View File

@@ -13,9 +13,12 @@ public interface IPersonalMemoryStore
void SetAffinity(PersonalMemoryTenantScope tenantScope, string item, PersonalAffinity affinity);
PersonalAffinity? GetAffinity(PersonalMemoryTenantScope tenantScope, string item);
IReadOnlyDictionary<string, PersonalAffinity> GetAffinities(PersonalMemoryTenantScope tenantScope);
void AddListItem(PersonalMemoryTenantScope tenantScope, string listName, string item);
IReadOnlyList<string> GetListItems(PersonalMemoryTenantScope tenantScope, string listName);
void ClearListItems(PersonalMemoryTenantScope tenantScope, string listName);
}
public sealed record PersonalMemoryTenantScope(string AccountId, string LoopId, string DeviceId);
public sealed record PersonalMemoryTenantScope(string AccountId, string LoopId, string DeviceId, string? PersonId = null);
public enum PersonalAffinity
{

View File

@@ -24,10 +24,20 @@ internal static class ChitchatStateMachine
"how are you feeling",
"how do you feel",
"what are you feeling",
"what are you up to",
"what are you doing",
"how are things",
"how's things",
"how is things",
"how's your day",
"how is your day",
"what mood are you in",
"what is your mood",
"what's your mood",
"do you have emotions",
"are you happy",
"are you sad",
"are you angry",
"how angry are you",
"how jealous are you",
"how sad are you",
@@ -152,6 +162,7 @@ internal static class ChitchatStateMachine
string loweredTranscript,
JiboExperienceCatalog catalog,
IJiboRandomizer randomizer,
string? currentEmotion,
Func<string> buildErrorResponse)
{
var normalizedLoweredTranscript = NormalizeForPhraseMatching(loweredTranscript);
@@ -164,17 +175,94 @@ internal static class ChitchatStateMachine
case "robot_personality":
return BuildScriptedResponseDecision(
"robot_personality",
randomizer.Choose(catalog.PersonalityReplies));
SelectLegacyPersonalityReply(catalog, randomizer, "curious, playful", "friendly", "personality"));
case "robot_taxes":
return BuildScriptedResponseDecision(
"robot_taxes",
SelectLegacyPersonalityReply(catalog, randomizer, "pay anything", "pay taxes", "tax"));
case "how_are_you":
return BuildEmotionQueryDecision(
"how_are_you",
randomizer.Choose(catalog.HowAreYouReplies));
SelectEmotionQueryReply(catalog, randomizer, currentEmotion));
case "robot_desire":
return BuildScriptedResponseDecision(
"robot_desire",
SelectLegacyPersonalityReply(
catalog,
randomizer,
"socializing and electricity",
"want to hang out",
"be helpful",
"dance from time to time"));
case "robot_job":
return BuildScriptedResponseDecision(
"robot_job",
SelectLegacyPersonalityReply(catalog, randomizer, "more fun than a job", "here to help you out"));
case "robot_origin_created":
return BuildScriptedResponseDecision(
"robot_origin_created",
SelectLegacyPersonalityReply(
catalog,
randomizer,
"create something",
"some people wanted to create something",
"wanted to create something",
"built a robot",
"came out from a box"));
case "robot_origin_from":
return BuildScriptedResponseDecision(
"robot_origin_from",
SelectLegacyPersonalityReply(catalog, randomizer, "boston", "came out from a box"));
case "robot_identity":
return BuildScriptedResponseDecision(
"robot_identity",
SelectLegacyPersonalityReply(catalog, randomizer, "am a robot", "i'm either jibo", "i am just jibo"));
case "robot_likes_being_jibo":
return BuildScriptedResponseDecision(
"robot_likes_being_jibo",
SelectLegacyPersonalityReply(
catalog,
randomizer,
"nothing i'd rather be",
"love it",
"being a human seems so complicated",
"especially yours",
"steady flow of electricity",
"you bet i do"));
case "robot_favorite_color":
return BuildScriptedResponseDecision(
"robot_favorite_color",
"Blue.");
case "robot_favorite_food":
return BuildScriptedResponseDecision(
"robot_favorite_food",
"Pizza. It is hard to argue with pizza.");
case "robot_favorite_music":
return BuildScriptedResponseDecision(
"robot_favorite_music",
"Something upbeat with a good rhythm.");
case "robot_nickname":
return BuildScriptedResponseDecision(
"robot_nickname",
SelectLegacyPersonalityReply(catalog, randomizer, "just jibo", "nickname"));
case "robot_name":
return BuildScriptedResponseDecision(
"robot_name",
SelectLegacyPersonalityReply(catalog, randomizer, "no last name", "like Bono", "Jibo."));
case "robot_peers":
return BuildScriptedResponseDecision(
"robot_peers",
SelectLegacyPersonalityReply(catalog, randomizer, "one in one million", "others like you"));
case "robot_knowledge":
return BuildScriptedResponseDecision(
"robot_knowledge",
SelectLegacyPersonalityReply(catalog, randomizer, "know a lot", "not as much as i will someday"));
case "chat":
if (IsEmotionQuery(normalizedLoweredTranscript))
{
return BuildEmotionQueryDecision(
"emotion_query",
randomizer.Choose(catalog.HowAreYouReplies));
SelectEmotionQueryReply(catalog, randomizer, currentEmotion));
}
if (TryResolveEmotionCommand(normalizedLoweredTranscript, out var emotion))
@@ -272,10 +360,124 @@ internal static class ChitchatStateMachine
[EmotionMetadataKey] = emotion ?? string.Empty,
["chitchatLastState"] = IntentSplitState,
["chitchatProcessState"] = ProcessQueryState,
["chitchatRawTranscript"] = rawTranscript ?? string.Empty
["chitchatRawTranscript"] = rawTranscript ?? string.Empty
};
}
private static string SelectEmotionQueryReply(
JiboExperienceCatalog catalog,
IJiboRandomizer randomizer,
string? currentEmotion)
{
if (catalog.EmotionReplies.Count == 0)
{
return randomizer.Choose(catalog.HowAreYouReplies);
}
var emotionVariants = ResolveEmotionVariants(currentEmotion);
foreach (var reply in catalog.EmotionReplies)
{
if (ConditionMatches(reply.Condition, emotionVariants))
{
return reply.Reply;
}
}
return randomizer.Choose(catalog.HowAreYouReplies);
}
private static bool ConditionMatches(string? condition, IReadOnlyList<string> emotionVariants)
{
var normalizedCondition = NormalizeCondition(condition);
if (string.IsNullOrWhiteSpace(normalizedCondition))
{
return false;
}
var clauses = normalizedCondition.Split(new[] { "||" }, StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
foreach (var clause in clauses)
{
if (MatchesConditionClause(clause, emotionVariants))
{
return true;
}
}
return false;
}
private static bool MatchesConditionClause(string clause, IReadOnlyList<string> emotionVariants)
{
var normalizedClause = NormalizeCondition(clause).ToUpperInvariant();
if (normalizedClause == "!JIBO.EMOTION")
{
return emotionVariants.Contains(string.Empty, StringComparer.OrdinalIgnoreCase) ||
emotionVariants.Contains("NEUTRAL", StringComparer.OrdinalIgnoreCase);
}
var equalityIndex = normalizedClause.IndexOf("==", StringComparison.Ordinal);
if (equalityIndex < 0)
{
return false;
}
var rightSide = normalizedClause[(equalityIndex + 2)..].Trim();
var candidate = rightSide.Trim('"', '\'');
return emotionVariants.Any(variant => string.Equals(variant, candidate, StringComparison.OrdinalIgnoreCase));
}
private static IReadOnlyList<string> ResolveEmotionVariants(string? currentEmotion)
{
if (string.IsNullOrWhiteSpace(currentEmotion))
{
return ["", "NEUTRAL"];
}
var normalizedEmotion = NormalizeCondition(currentEmotion).Trim('"', '\'').ToUpperInvariant();
return normalizedEmotion switch
{
"HAPPY" => ["JOYFUL", "PLEASED", "CONFIDENT", "DETERMINED", "HAPPY"],
"SAD" => ["INSECURE", "SAD"],
"CALM" => ["NEUTRAL", "INSECURE", "CALM"],
"NEUTRAL" => ["NEUTRAL"],
"JOYFUL" or "PLEASED" or "CONFIDENT" or "DETERMINED" or "INSECURE" => [normalizedEmotion],
_ => [normalizedEmotion]
};
}
private static string SelectLegacyPersonalityReply(
JiboExperienceCatalog catalog,
IJiboRandomizer randomizer,
params string[] preferredSnippets)
{
foreach (var snippet in preferredSnippets)
{
if (string.IsNullOrWhiteSpace(snippet))
{
continue;
}
var match = catalog.PersonalityReplies.FirstOrDefault(reply =>
reply.Contains(snippet, StringComparison.OrdinalIgnoreCase));
if (!string.IsNullOrWhiteSpace(match))
{
return match;
}
}
return randomizer.Choose(catalog.PersonalityReplies);
}
private static string NormalizeCondition(string? condition)
{
if (string.IsNullOrWhiteSpace(condition))
{
return string.Empty;
}
return PhraseWhitespacePattern.Replace(condition.Trim(), " ");
}
private static bool IsEmotionQuery(string loweredTranscript)
{
if (ContainsAnyPhrase(loweredTranscript, EmotionQueryPhrases))

View File

@@ -4,6 +4,8 @@ namespace Jibo.Cloud.Application.Services;
public sealed class DemoConversationBroker(JiboInteractionService interactionService) : IConversationBroker
{
private readonly TimeSpan _followUpTimeout = TimeSpan.FromSeconds(6);
public async Task<ResponsePlan> HandleTurnAsync(TurnContext turn, CancellationToken cancellationToken = default)
{
var decision = await interactionService.BuildDecisionAsync(turn, cancellationToken);
@@ -31,7 +33,7 @@ public sealed class DemoConversationBroker(JiboInteractionService interactionSer
? new FollowUpPolicy
{
KeepMicOpen = true,
Timeout = TimeSpan.FromSeconds(12),
Timeout = _followUpTimeout,
ExpectedTopic = "conversation"
}
: FollowUpPolicy.None,
@@ -51,7 +53,7 @@ public sealed class DemoConversationBroker(JiboInteractionService interactionSer
plan.Actions.Add(new ListenAction
{
Sequence = 1,
Timeout = TimeSpan.FromSeconds(12),
Timeout = _followUpTimeout,
Mode = "follow-up"
});
}
@@ -74,6 +76,16 @@ public sealed class DemoConversationBroker(JiboInteractionService interactionSer
return intentName switch
{
"cloud_version" => false,
"memory_set_name" => false,
"memory_get_name" => false,
"memory_set_birthday" => false,
"memory_get_birthday" => false,
"memory_set_important_date" => false,
"memory_get_important_date" => false,
"memory_set_preference" => false,
"memory_get_preference" => false,
"memory_set_affinity" => false,
"memory_get_affinity" => false,
"word_of_the_day" => false,
"word_of_the_day_guess" => false,
"radio" => false,

View File

@@ -0,0 +1,299 @@
using Jibo.Cloud.Application.Abstractions;
using Jibo.Runtime.Abstractions;
using System.Linq;
namespace Jibo.Cloud.Application.Services;
internal static class HouseholdListOrchestrator
{
internal const string StateMetadataKey = "householdListState";
internal const string TypeMetadataKey = "householdListType";
internal const string NoMatchCountMetadataKey = "householdListNoMatchCount";
internal const string NoInputCountMetadataKey = "householdListNoInputCount";
private const string IdleState = "idle";
private const string AwaitingItemState = "awaiting_item";
public static Task<JiboInteractionDecision?> TryBuildDecisionAsync(
TurnContext turn,
string semanticIntent,
string transcript,
string loweredTranscript,
IJiboRandomizer randomizer,
IPersonalMemoryStore personalMemoryStore,
Func<TurnContext, PersonalMemoryTenantScope> tenantScopeResolver)
{
var state = ReadString(turn, StateMetadataKey);
var listType = ReadString(turn, TypeMetadataKey);
var isActiveState = !string.IsNullOrWhiteSpace(state) &&
!string.Equals(state, IdleState, StringComparison.OrdinalIgnoreCase);
var isShoppingIntent = string.Equals(semanticIntent, "shopping_list", StringComparison.OrdinalIgnoreCase);
var isTodoIntent = string.Equals(semanticIntent, "todo_list", StringComparison.OrdinalIgnoreCase);
if (!isActiveState && !isShoppingIntent && !isTodoIntent)
{
return Task.FromResult<JiboInteractionDecision?>(null);
}
var resolvedListType = isShoppingIntent ? "shopping" : isTodoIntent ? "todo" : NormalizeListType(listType);
if (string.IsNullOrWhiteSpace(resolvedListType))
{
resolvedListType = "shopping";
}
var tenantScope = tenantScopeResolver(turn);
if (ContainsAny(loweredTranscript, "cancel", "stop", "never mind", "nevermind", "forget it"))
{
return Task.FromResult<JiboInteractionDecision?>(BuildCancelledDecision(resolvedListType));
}
if (IsRecallRequest(loweredTranscript))
{
return Task.FromResult<JiboInteractionDecision?>(BuildRecallDecision(
resolvedListType,
personalMemoryStore.GetListItems(tenantScope, resolvedListType)));
}
var directItem = TryExtractListItem(loweredTranscript);
if (string.IsNullOrWhiteSpace(directItem) && isActiveState)
{
if (IsConversationComplete(loweredTranscript))
{
return Task.FromResult<JiboInteractionDecision?>(new JiboInteractionDecision(
resolvedListType == "shopping" ? "shopping_list_done" : "todo_list_done",
BuildDoneReply(resolvedListType, personalMemoryStore.GetListItems(tenantScope, resolvedListType)),
ContextUpdates: BuildContextUpdates(resolvedListType, IdleState)));
}
directItem = NormalizeItem(transcript);
}
if (!string.IsNullOrWhiteSpace(directItem))
{
personalMemoryStore.AddListItem(tenantScope, resolvedListType, directItem);
return Task.FromResult<JiboInteractionDecision?>(new JiboInteractionDecision(
resolvedListType == "shopping" ? "shopping_list_add" : "todo_list_add",
BuildAddedReply(resolvedListType, directItem, personalMemoryStore.GetListItems(tenantScope, resolvedListType)),
ContextUpdates: BuildContextUpdates(resolvedListType, AwaitingItemState)));
}
if (string.IsNullOrWhiteSpace(transcript))
{
return Task.FromResult<JiboInteractionDecision?>(new JiboInteractionDecision(
resolvedListType == "shopping" ? "shopping_list_prompt" : "todo_list_prompt",
BuildPromptReply(resolvedListType),
ContextUpdates: BuildContextUpdates(resolvedListType, AwaitingItemState)));
}
return Task.FromResult<JiboInteractionDecision?>(new JiboInteractionDecision(
resolvedListType == "shopping" ? "shopping_list_prompt" : "todo_list_prompt",
BuildPromptReply(resolvedListType),
ContextUpdates: BuildContextUpdates(resolvedListType, AwaitingItemState)));
}
private static IDictionary<string, object?> BuildContextUpdates(string listType, string state)
{
return new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
[StateMetadataKey] = state,
[TypeMetadataKey] = listType,
[NoMatchCountMetadataKey] = 0,
[NoInputCountMetadataKey] = 0
};
}
private static JiboInteractionDecision BuildCancelledDecision(string listType)
{
return new JiboInteractionDecision(
listType == "shopping" ? "shopping_list_cancel" : "todo_list_cancel",
listType == "shopping" ? "Okay. I stopped the shopping list." : "Okay. I stopped the to-do list.",
ContextUpdates: new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
[StateMetadataKey] = IdleState,
[TypeMetadataKey] = listType,
[NoMatchCountMetadataKey] = 0,
[NoInputCountMetadataKey] = 0
});
}
private static JiboInteractionDecision BuildRecallDecision(string listType, IReadOnlyList<string> items)
{
if (items.Count == 0)
{
return new JiboInteractionDecision(
listType == "shopping" ? "shopping_list_recall" : "todo_list_recall",
listType == "shopping"
? "Your shopping list is empty."
: "Your to-do list is empty.",
ContextUpdates: new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
[StateMetadataKey] = IdleState,
[TypeMetadataKey] = listType,
[NoMatchCountMetadataKey] = 0,
[NoInputCountMetadataKey] = 0
});
}
return new JiboInteractionDecision(
listType == "shopping" ? "shopping_list_recall" : "todo_list_recall",
listType == "shopping"
? $"Your shopping list has {JoinList(items)}."
: $"Your to-do list has {JoinList(items)}.",
ContextUpdates: new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
[StateMetadataKey] = IdleState,
[TypeMetadataKey] = listType,
[NoMatchCountMetadataKey] = 0,
[NoInputCountMetadataKey] = 0
});
}
private static string BuildAddedReply(string listType, string addedItem, IReadOnlyList<string> items)
{
var itemLabel = listType == "shopping" ? "shopping list" : "to-do list";
return items.Count == 1
? $"Added {addedItem} to your {itemLabel}. What else should I add?"
: $"Added {addedItem} to your {itemLabel}. You now have {JoinList(items)}.";
}
private static string BuildPromptReply(string listType)
{
return listType == "shopping"
? "What should I add to your shopping list?"
: "What should I add to your to-do list?";
}
private static string BuildDoneReply(string listType, IReadOnlyList<string> items)
{
if (items.Count == 0)
{
return listType == "shopping"
? "Okay. Your shopping list is empty."
: "Okay. Your to-do list is empty.";
}
return listType == "shopping"
? $"Okay. Your shopping list has {JoinList(items)}."
: $"Okay. Your to-do list has {JoinList(items)}.";
}
private static string JoinList(IReadOnlyList<string> items)
{
return items.Count switch
{
0 => string.Empty,
1 => items[0],
2 => $"{items[0]} and {items[1]}",
_ => $"{string.Join(", ", items.Take(items.Count - 1))}, and {items[^1]}"
};
}
private static string? TryExtractListItem(string loweredTranscript)
{
foreach (var prefix in ItemPrefixes)
{
if (!loweredTranscript.StartsWith(prefix, StringComparison.OrdinalIgnoreCase))
{
continue;
}
var remainder = loweredTranscript[prefix.Length..].Trim();
remainder = TrimTrailingListPhrases(remainder);
return NormalizeItem(remainder);
}
return null;
}
private static bool IsRecallRequest(string loweredTranscript)
{
return ContainsAny(loweredTranscript,
"what is on my shopping list",
"what's on my shopping list",
"show my shopping list",
"what is on my to do list",
"what's on my to do list",
"show my to do list",
"what are my tasks",
"what do i need to buy",
"what do i need to do");
}
private static string TrimTrailingListPhrases(string value)
{
var result = value;
foreach (var suffix in ItemSuffixes)
{
if (result.EndsWith(suffix, StringComparison.OrdinalIgnoreCase))
{
result = result[..^suffix.Length].Trim();
}
}
return result;
}
private static string NormalizeItem(string value)
{
return value.Trim().TrimEnd('.', ',', '!', '?');
}
private static string NormalizeListType(string? listType)
{
var normalized = NormalizeItem(listType ?? string.Empty).ToLowerInvariant();
return normalized.Contains("todo", StringComparison.OrdinalIgnoreCase) || normalized.Contains("to do", StringComparison.OrdinalIgnoreCase)
? "todo"
: normalized.Contains("shopping", StringComparison.OrdinalIgnoreCase) || normalized.Contains("grocery", StringComparison.OrdinalIgnoreCase)
? "shopping"
: string.Empty;
}
private static bool ContainsAny(string loweredTranscript, params string[] phrases)
{
return phrases.Any(phrase => loweredTranscript.Contains(phrase, StringComparison.OrdinalIgnoreCase));
}
private static bool IsConversationComplete(string loweredTranscript)
{
return ContainsAny(loweredTranscript,
"done",
"that's it",
"that s it",
"all set",
"finished",
"no more",
"nothing else");
}
private static string? ReadString(TurnContext turn, string key)
{
return turn.Attributes.TryGetValue(key, out var value) ? value?.ToString() : null;
}
private static readonly string[] ItemPrefixes =
[
"add ",
"put ",
"buy ",
"get ",
"remind me to ",
"i need to ",
"i need ",
"please add ",
"please put "
];
private static readonly string[] ItemSuffixes =
[
" to my shopping list",
" to the shopping list",
" on my shopping list",
" to my to do list",
" to the to do list",
" on my to do list",
" to my todo list",
" to the todo list",
" on my todo list"
];
}

View File

@@ -1,4 +1,5 @@
using System.Text.Json;
using System.Text.RegularExpressions;
using Jibo.Cloud.Domain.Models;
using Jibo.Runtime.Abstractions;
@@ -300,22 +301,6 @@ public sealed class ResponsePlanToSocketMessagesMapper
DelayMs: 125));
}
if (isReportSkillLaunch)
{
messages.Add(new SocketReplyPlan(
JsonSerializer.Serialize(BuildSkillRedirectPayload(
transId,
"report-skill",
outboundIntent,
outboundAsrText,
outboundRules,
entities)),
DelayMs: 75));
messages.Add(new SocketReplyPlan(
JsonSerializer.Serialize(BuildCompletionOnlySkillPayload(transId, "report-skill")),
DelayMs: 125));
}
if (emitSkillActions && speak is not null)
{
messages.Add(new SocketReplyPlan(
@@ -821,10 +806,17 @@ public sealed class ResponsePlanToSocketMessagesMapper
};
}
var weatherHiLoView = BuildWeatherHiLoView(skillPayload);
object? weatherHiLoView = BuildWeatherHiLoView(skillPayload);
var weeklyWeatherCards = BuildWeatherHiLoSequenceCards(skillPayload);
if (weatherHiLoView is null && weeklyWeatherCards.Count > 0)
{
weatherHiLoView = weeklyWeatherCards[0].View;
}
var useWeatherSequence = false;
if (weatherHiLoView is not null)
{
var resolvedGuiConfig = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
var resolvedGuiContext = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["type"] = "Javascript",
["data"] = weatherHiLoView,
@@ -841,7 +833,15 @@ public sealed class ResponsePlanToSocketMessagesMapper
jcpConfig["gui"] = legacyGuiConfig;
jcpConfig["display"] = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["view"] = resolvedGuiConfig
["view"] = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
// Legacy fields used by existing tests and tooling.
["type"] = "Javascript",
["data"] = weatherHiLoView,
["pause"] = true,
// Pegasus-style view context used by on-robot weather cards.
["context"] = resolvedGuiContext
}
};
jcpConfig["timeout"] = 6;
@@ -861,6 +861,30 @@ public sealed class ResponsePlanToSocketMessagesMapper
{
["views"] = weatherViews
};
if (weeklyWeatherCards.Count > 1)
{
useWeatherSequence = true;
jcpConfig["children"] = BuildWeatherHiLoSequenceChildren(
weeklyWeatherCards,
promptSubCategory,
mimId,
mimType);
}
}
var jcp = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["type"] = "SLIM",
["config"] = jcpConfig
};
if (useWeatherSequence &&
jcpConfig.TryGetValue("children", out var sequenceChildren) &&
sequenceChildren is not null)
{
jcp["type"] = "SEQUENCE";
jcp.Remove("config");
jcp["children"] = sequenceChildren;
}
return new
@@ -879,11 +903,7 @@ public sealed class ResponsePlanToSocketMessagesMapper
{
config = new
{
jcp = new
{
type = "SLIM",
config = jcpConfig
}
jcp
}
},
analytics = new Dictionary<string, object?>(),
@@ -1113,6 +1133,184 @@ public sealed class ResponsePlanToSocketMessagesMapper
};
}
private static IReadOnlyList<WeatherHiLoSequenceCard> BuildWeatherHiLoSequenceCards(IDictionary<string, object?>? payload)
{
if (payload is null ||
!payload.TryGetValue("weather_weekly_cards", out var rawCards) ||
rawCards is null)
{
return [];
}
var cards = ReadPayloadObjectArray(rawCards);
if (cards.Count == 0)
{
return [];
}
var sequenceCards = new List<WeatherHiLoSequenceCard>(cards.Count);
foreach (var card in cards)
{
var weatherCardPayload = new Dictionary<string, object?>(card, StringComparer.OrdinalIgnoreCase)
{
["weather_view_enabled"] = true,
["weather_view_kind"] = "weatherHiLo"
};
var view = BuildWeatherHiLoView(weatherCardPayload);
if (view is null)
{
continue;
}
sequenceCards.Add(new WeatherHiLoSequenceCard(
view,
ReadPayloadString(weatherCardPayload, "weather_day"),
ReadPayloadString(weatherCardPayload, "weather_icon"),
ReadPayloadString(weatherCardPayload, "weather_spoken_line")));
}
return sequenceCards;
}
private static IReadOnlyList<object> BuildWeatherHiLoSequenceChildren(
IReadOnlyList<WeatherHiLoSequenceCard> cards,
string promptSubCategory,
string mimId,
string mimType)
{
var children = new List<object>(cards.Count);
for (var index = 0; index < cards.Count; index += 1)
{
var card = cards[index];
var promptLabel = string.IsNullOrWhiteSpace(card.DayName)
? $"Day{index + 1}"
: Regex.Replace(card.DayName, "[^A-Za-z0-9]", string.Empty, RegexOptions.CultureInvariant);
var promptId = $"WeatherForecast{promptLabel}_AN_13";
var spokenLine = string.IsNullOrWhiteSpace(card.SpokenLine)
? "Here is another day's forecast."
: card.SpokenLine!;
var icon = string.IsNullOrWhiteSpace(card.Icon)
? "cloudy"
: card.Icon!;
var esml =
$"<speak><anim cat='weather' meta='{icon}' nonBlocking='true' /><break size='0.2'/><es cat='neutral' filter='!ssa-only, !sfx-only' endNeutral='true'>{EscapeXml(spokenLine)}</es></speak>";
var resolvedGuiContext = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["type"] = "Javascript",
["data"] = card.View,
["pause"] = true
};
children.Add(new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["type"] = "SLIM",
["config"] = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["play"] = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["esml"] = esml,
["meta"] = new
{
prompt_id = promptId,
prompt_sub_category = promptSubCategory,
mim_id = mimId,
mim_type = mimType
}
},
["gui"] = new
{
type = "Javascript",
data = "views.weatherHiLo",
pause = true
},
["display"] = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["view"] = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["type"] = "Javascript",
["data"] = card.View,
["pause"] = true,
["context"] = resolvedGuiContext
}
},
["timeout"] = 6,
["barge_in"] = true,
["no_matches_for_gui"] = 0,
["no_inputs_for_gui"] = 0
}
});
}
return children;
}
private static IReadOnlyList<IDictionary<string, object?>> ReadPayloadObjectArray(object rawValue)
{
if (rawValue is JsonElement jsonArray && jsonArray.ValueKind == JsonValueKind.Array)
{
return jsonArray
.EnumerateArray()
.Select(ConvertJsonObjectToDictionary)
.Where(static item => item is not null)
.Cast<IDictionary<string, object?>>()
.ToArray();
}
if (rawValue is IEnumerable<object?> rawObjects)
{
return rawObjects
.Select(ConvertObjectToDictionary)
.Where(static item => item is not null)
.Cast<IDictionary<string, object?>>()
.ToArray();
}
return [];
}
private static IDictionary<string, object?>? ConvertObjectToDictionary(object? value)
{
if (value is null)
{
return null;
}
if (value is IDictionary<string, object?> dictionary)
{
return new Dictionary<string, object?>(dictionary, StringComparer.OrdinalIgnoreCase);
}
return value is JsonElement jsonValue
? ConvertJsonObjectToDictionary(jsonValue)
: null;
}
private static IDictionary<string, object?>? ConvertJsonObjectToDictionary(JsonElement value)
{
if (value.ValueKind != JsonValueKind.Object)
{
return null;
}
var dictionary = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase);
foreach (var property in value.EnumerateObject())
{
dictionary[property.Name] = property.Value.ValueKind switch
{
JsonValueKind.String => property.Value.GetString(),
JsonValueKind.Number when property.Value.TryGetInt32(out var intValue) => intValue,
JsonValueKind.Number when property.Value.TryGetDouble(out var doubleValue) => doubleValue,
JsonValueKind.True => true,
JsonValueKind.False => false,
JsonValueKind.Object => ConvertJsonObjectToDictionary(property.Value),
JsonValueKind.Array => property.Value,
_ => null
};
}
return dictionary;
}
private static object? BuildWeatherHiLoView(IDictionary<string, object?>? payload)
{
if (!TryReadPayloadBool(payload, "weather_view_enabled"))
@@ -1198,7 +1396,7 @@ public sealed class ResponsePlanToSocketMessagesMapper
{
id = "hiNumLabel",
type = "Label",
text = $"{high.Value}\u00B0",
text = $"{high.Value}°",
style = new
{
fontSize = "160",
@@ -1230,7 +1428,7 @@ public sealed class ResponsePlanToSocketMessagesMapper
{
id = "loNumLabel",
type = "Label",
text = $"{low.Value}\u00B0",
text = $"{low.Value}°",
style = new
{
fontSize = "160",
@@ -1355,6 +1553,12 @@ public sealed class ResponsePlanToSocketMessagesMapper
return Guid.NewGuid().ToString("N");
}
private sealed record WeatherHiLoSequenceCard(
object View,
string? DayName,
string? Icon,
string? SpokenLine);
public sealed record SocketReplyPlan(string Text, int DelayMs = 0);
}

View File

@@ -679,9 +679,41 @@ public sealed partial class WebSocketTurnFinalizationService(
{
["intent"] = plan.IntentName,
["skillName"] = invokedSkillAction.SkillName,
["transcript"] = finalizedTurn.NormalizedTranscript ?? finalizedTurn.RawTranscript,
["payload"] = invokedSkillAction.Payload
}),
cancellationToken);
if (string.Equals(plan.IntentName, "news", StringComparison.OrdinalIgnoreCase) &&
invokedSkillAction.Payload.TryGetValue("news_provider_status", out var providerStatus))
{
invokedSkillAction.Payload.TryGetValue("news_provider_requested_headlines", out var requestedHeadlines);
invokedSkillAction.Payload.TryGetValue("news_provider_resolved_headlines", out var resolvedHeadlines);
invokedSkillAction.Payload.TryGetValue("news_provider_preferred_categories", out var preferredCategories);
invokedSkillAction.Payload.TryGetValue("news_source", out var newsSource);
invokedSkillAction.Payload.TryGetValue("news_provider_message", out var providerMessage);
invokedSkillAction.Payload.TryGetValue("news_provider_http_status", out var providerHttpStatus);
invokedSkillAction.Payload.TryGetValue("news_provider_endpoint", out var providerEndpoint);
invokedSkillAction.Payload.TryGetValue("news_provider_error_code", out var providerErrorCode);
await sink.RecordTurnDiagnosticAsync(
"news_provider_trace",
BuildTurnDiagnosticSnapshot(session, envelope, new Dictionary<string, object?>
{
["intent"] = plan.IntentName,
["skillName"] = invokedSkillAction.SkillName,
["status"] = providerStatus,
["requestedHeadlines"] = requestedHeadlines,
["resolvedHeadlines"] = resolvedHeadlines,
["preferredCategories"] = preferredCategories,
["source"] = newsSource,
["providerMessage"] = providerMessage,
["providerHttpStatus"] = providerHttpStatus,
["providerEndpoint"] = providerEndpoint,
["providerErrorCode"] = providerErrorCode
}),
cancellationToken);
}
}
session.FollowUpExpiresUtc = plan.FollowUp.KeepMicOpen
@@ -1056,13 +1088,13 @@ public sealed partial class WebSocketTurnFinalizationService(
return true;
}
if (IsYesNoTurn(turn) && transcript is "yes" or "no" or "sure" or "nope" or "yup" or "uh huh" or "yeah" or "nah")
if (IsYesNoTurn(turn) && IsYesNoReplyTranscript(transcript))
{
return true;
}
if (!string.IsNullOrWhiteSpace(pendingProactivityOffer) &&
transcript is "yes" or "no" or "sure" or "nope" or "yup" or "uh huh" or "yeah" or "nah")
IsYesNoReplyTranscript(transcript))
{
return true;
}
@@ -1185,7 +1217,163 @@ public sealed partial class WebSocketTurnFinalizationService(
string.Equals(rule, "shared/yes_no", StringComparison.OrdinalIgnoreCase) ||
string.Equals(rule, "settings/download_now_later", StringComparison.OrdinalIgnoreCase) ||
string.Equals(rule, "surprises-date/offer_date_fact", StringComparison.OrdinalIgnoreCase) ||
string.Equals(rule, "surprises-ota/want_to_download_now", StringComparison.OrdinalIgnoreCase);
string.Equals(rule, "surprises-ota/want_to_download_now", StringComparison.OrdinalIgnoreCase) ||
string.Equals(rule, "word-of-the-day/surprise", StringComparison.OrdinalIgnoreCase);
}
private static bool IsYesNoReplyTranscript(string normalizedTranscript)
{
return TryClassifyYesNoReply(normalizedTranscript) is not YesNoReply.None;
}
private static YesNoReply TryClassifyYesNoReply(string normalizedTranscript)
{
if (string.IsNullOrWhiteSpace(normalizedTranscript))
{
return YesNoReply.None;
}
var normalized = normalizedTranscript;
while (TryTrimLeadingAcknowledgement(normalized, out var trimmed))
{
normalized = trimmed;
}
if (string.IsNullOrWhiteSpace(normalized))
{
return YesNoReply.None;
}
var tokens = normalized.Split(' ', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries);
if (tokens.Length == 0)
{
return YesNoReply.None;
}
if (YesNoNegativeLeadTokens.Contains(tokens[0]))
{
return YesNoReply.Negative;
}
if (YesNoAffirmativeLeadTokens.Contains(tokens[0]))
{
return YesNoReply.Affirmative;
}
var leadingTwo = tokens.Length >= 2 ? $"{tokens[0]} {tokens[1]}" : null;
if (leadingTwo is not null)
{
if (YesNoNegativeLeadPhrases.Contains(leadingTwo))
{
return YesNoReply.Negative;
}
if (YesNoAffirmativeLeadPhrases.Contains(leadingTwo))
{
return YesNoReply.Affirmative;
}
}
var leadingThree = tokens.Length >= 3 ? $"{tokens[0]} {tokens[1]} {tokens[2]}" : null;
if (leadingThree is not null)
{
if (YesNoNegativeLeadPhrases.Contains(leadingThree))
{
return YesNoReply.Negative;
}
if (YesNoAffirmativeLeadPhrases.Contains(leadingThree))
{
return YesNoReply.Affirmative;
}
}
return TryClassifyTrailingYesNoReply(tokens);
}
private static bool TryTrimLeadingAcknowledgement(string normalizedTranscript, out string trimmedTranscript)
{
foreach (var acknowledgement in YesNoAcknowledgementPrefixes)
{
if (string.Equals(normalizedTranscript, acknowledgement, StringComparison.Ordinal))
{
trimmedTranscript = string.Empty;
return true;
}
if (normalizedTranscript.StartsWith($"{acknowledgement} ", StringComparison.Ordinal))
{
trimmedTranscript = normalizedTranscript[(acknowledgement.Length + 1)..].TrimStart();
return true;
}
}
trimmedTranscript = normalizedTranscript;
return false;
}
private static YesNoReply TryClassifyTrailingYesNoReply(IReadOnlyList<string> tokens)
{
var selectedReply = YesNoReply.None;
var selectedIndex = -1;
void Consider(YesNoReply candidateReply, int candidateIndex)
{
if (candidateIndex < 0 || candidateIndex < selectedIndex)
{
return;
}
selectedReply = candidateReply;
selectedIndex = candidateIndex;
}
for (var index = 0; index < tokens.Count; index += 1)
{
var token = tokens[index];
if (YesNoNegativeLeadTokens.Contains(token))
{
Consider(YesNoReply.Negative, index);
continue;
}
if (YesNoAffirmativeLeadTokens.Contains(token))
{
Consider(YesNoReply.Affirmative, index);
}
}
for (var index = 0; index + 1 < tokens.Count; index += 1)
{
var phrase = $"{tokens[index]} {tokens[index + 1]}";
if (YesNoNegativeLeadPhrases.Contains(phrase))
{
Consider(YesNoReply.Negative, index + 1);
continue;
}
if (YesNoAffirmativeLeadPhrases.Contains(phrase))
{
Consider(YesNoReply.Affirmative, index + 1);
}
}
for (var index = 0; index + 2 < tokens.Count; index += 1)
{
var phrase = $"{tokens[index]} {tokens[index + 1]} {tokens[index + 2]}";
if (YesNoNegativeLeadPhrases.Contains(phrase))
{
Consider(YesNoReply.Negative, index + 2);
continue;
}
if (YesNoAffirmativeLeadPhrases.Contains(phrase))
{
Consider(YesNoReply.Affirmative, index + 2);
}
}
return selectedReply;
}
private async Task ApplyContextUpdatesAsync(
@@ -1772,6 +1960,78 @@ public sealed partial class WebSocketTurnFinalizationService(
};
}
private enum YesNoReply
{
None = 0,
Affirmative = 1,
Negative = 2
}
private static readonly string[] YesNoAcknowledgementPrefixes =
[
"uh",
"um",
"hmm",
"well",
"so",
"actually",
"honestly",
"thanks",
"thank you"
];
private static readonly HashSet<string> YesNoAffirmativeLeadTokens = new(StringComparer.Ordinal)
{
"yes",
"yeah",
"yep",
"yup",
"sure",
"ok",
"okay",
"absolutely",
"affirmative",
"definitely",
"certainly",
"indeed"
};
private static readonly HashSet<string> YesNoNegativeLeadTokens = new(StringComparer.Ordinal)
{
"no",
"nope",
"nah",
"negative",
"never"
};
private static readonly HashSet<string> YesNoAffirmativeLeadPhrases = new(StringComparer.Ordinal)
{
"uh huh",
"sounds good",
"sure thing",
"why not",
"please do",
"go ahead",
"of course",
"i guess so",
"i think so"
};
private static readonly HashSet<string> YesNoNegativeLeadPhrases = new(StringComparer.Ordinal)
{
"not now",
"not today",
"not really",
"no thanks",
"no thank you",
"maybe later",
"i guess not",
"i do not",
"i dont",
"i don t"
};
[GeneratedRegex(@"[^\w\s]")]
private static partial Regex TranscriptNormalizationRegex();
}

View File

@@ -0,0 +1,14 @@
namespace Jibo.Cloud.Domain.Models;
public sealed class PersonRecord
{
public string PersonId { get; init; } = "person-openjibo-owner";
public string AccountId { get; init; } = "usr_openjibo_owner";
public string LoopId { get; init; } = "openjibo-default-loop";
public string RobotId { get; init; } = "my-robot-name";
public string DisplayName { get; init; } = "Jibo Owner";
public string? Alias { get; init; }
public bool IsPrimary { get; init; } = true;
public DateTimeOffset CreatedUtc { get; init; } = DateTimeOffset.UtcNow;
public DateTimeOffset UpdatedUtc { get; init; } = DateTimeOffset.UtcNow;
}

View File

@@ -4,104 +4,158 @@ namespace Jibo.Cloud.Infrastructure.Content;
public sealed class InMemoryJiboExperienceContentRepository : IJiboExperienceContentRepository
{
private static readonly JiboExperienceCatalog Catalog = new()
private static readonly JiboExperienceCatalog Catalog = BuildCatalog();
private static JiboExperienceCatalog BuildCatalog()
{
Jokes =
[
"Why did the robot cross the road? Because it was programmed by the chicken.",
"Why was the robot tired when it got home? It had a hard drive.",
"What do you call a pirate robot? Arrrr two dee two.",
"Why did the robot go on vacation? It needed to recharge.",
"What kind of shoes do frogs wear? Open-toed."
],
DanceAnimations =
[
"rom-upbeat",
"rom-ballroom",
"rom-silly",
"rom-slowdance",
"rom-electronic",
"rom-twerk"
],
DanceReplies = [
"I am ready to dance.",
"Okay. Watch this.",
"Watch me dance.",
"Here's my favorite dance move."
],
DanceQuestionReplies =
[
"I love to dance. Tell me to dance and I will show you a move.",
"Absolutely. Dancing is one of my favorite things to do.",
"Dancing is my kind of fun. Say dance and I am in."
],
GreetingReplies =
[
"Hi there. It is really good to talk with you.",
"Hello there. I am glad you said hi.",
"Hey. I am happy to see you."
],
HowAreYouReplies =
[
"I am feeling cheerful and robotic.",
"I am doing great. Thanks for asking.",
"I am feeling bright-eyed and ready to help."
],
PersonalityReplies =
[
"I do. I am curious, playful, and always up for a new experiment.",
"Absolutely. I am friendly, curious, and a little goofy on purpose.",
"Yes. My personality is part helper, part curious robot sidekick."
],
PizzaReplies =
[
"I cannot bake yet, but I can help design the perfect pizza plan.",
"I am still cloud-side for now, so no oven control yet. But I can help pick toppings.",
"Pizza mission accepted in spirit. I can help with the recipe while you handle the baking."
],
SurpriseReplies =
[
"I can definitely surprise you. We are still mapping that path, but I am ready for the next experiment.",
"Surprise mode is still taking shape, but I heard you loud and clear.",
"That sounds fun. I am not all the way there yet, but we can keep teaching me."
],
PersonalReportReplies =
[
"I heard your personal report request. That cloud path is still being mapped.",
"Personal report is recognized, but I am not ready to deliver the real report yet."
],
WeatherReplies =
[
"I heard your weather request. We still need to wire the real provider behind it.",
"Weather is on the map now, even though the real forecast path is not finished yet."
],
CalendarReplies =
[
"I heard your calendar request. The cloud knows the phrase, but the real calendar integration is still ahead.",
"Calendar is recognized. We still need to connect the actual service path."
],
CommuteReplies =
[
"I heard your commute request. That one is recognized, but not fully implemented yet.",
"Commute is on the discovery list now. The real travel answer still needs a provider."
],
NewsReplies =
[
"I heard your news request. That path is still a future cloud integration.",
"News is recognized, but I do not have the full news service behind it yet."
],
NewsBriefings =
[
"Here are your headlines. Space missions are preparing for new launches, climate and weather systems are staying active across the country, and AI tools keep pushing into everyday products.",
"Here is a quick news brief. Technology companies are still racing on AI, global leaders are trading policy updates, and science teams are sharing new research findings."
],
GenericFallbackReplies =
[
"Okay. You said, {transcript}.",
"I heard you say, {transcript}.",
"Thanks. I heard, {transcript}."
]
};
var catalog = new JiboExperienceCatalog
{
Jokes =
[
"Why did the robot cross the road? Because it was programmed by the chicken.",
"Why was the robot tired when it got home? It had a hard drive.",
"What do you call a pirate robot? Arrrr two dee two.",
"Why did the robot go on vacation? It needed to recharge.",
"What kind of shoes do frogs wear? Open-toed."
],
DanceAnimations =
[
"rom-upbeat",
"rom-ballroom",
"rom-silly",
"rom-slowdance",
"rom-electronic",
"rom-twerk"
],
DanceReplies =
[
"I am ready to dance.",
"Okay. Watch this.",
"Watch me dance.",
"Here's my favorite dance move."
],
DanceQuestionReplies =
[
"I love to dance. Tell me to dance and I will show you a move.",
"Absolutely. Dancing is one of my favorite things to do.",
"Dancing is my kind of fun. Say dance and I am in."
],
GreetingReplies =
[
"Hi there. It is really good to talk with you.",
"Hello there. I am glad you said hi.",
"Hey. I am happy to see you."
],
HowAreYouReplies =
[
"I am feeling cheerful and robotic.",
"I am doing great. Thanks for asking.",
"I am feeling bright-eyed and ready to help."
],
PersonalityReplies =
[
"I do. I am curious, playful, and always up for a new experiment.",
"Absolutely. I am friendly, curious, and a little goofy on purpose.",
"Yes. My personality is part helper, part curious robot sidekick."
],
PizzaReplies =
[
"I cannot bake yet, but I can help design the perfect pizza plan.",
"I am still cloud-side for now, so no oven control yet. But I can help pick toppings.",
"Pizza mission accepted in spirit. I can help with the recipe while you handle the baking."
],
SurpriseReplies =
[
"I can definitely surprise you. We are still mapping that path, but I am ready for the next experiment.",
"Surprise mode is still taking shape, but I heard you loud and clear.",
"That sounds fun. I am not all the way there yet, but we can keep teaching me."
],
PersonalReportReplies =
[
"I heard your personal report request. That cloud path is still being mapped.",
"Personal report is recognized, but I am not ready to deliver the real report yet."
],
WeatherReplies =
[
"I heard your weather request. We still need to wire the real provider behind it.",
"Weather is on the map now, even though the real forecast path is not finished yet."
],
CalendarReplies =
[
"I heard your calendar request. The cloud knows the phrase, but the real calendar integration is still ahead.",
"Calendar is recognized. We still need to connect the actual service path."
],
CommuteReplies =
[
"I heard your commute request. That one is recognized, but not fully implemented yet.",
"Commute is on the discovery list now. The real travel answer still needs a provider."
],
NewsReplies =
[
"I heard your news request. That path is still a future cloud integration.",
"News is recognized, but I do not have the full news service behind it yet."
],
NewsBriefings =
[
"Here are your headlines. Space missions are preparing for new launches, climate and weather systems are staying active across the country, and AI tools keep pushing into everyday products.",
"Here is a quick news brief. Technology companies are still racing on AI, global leaders are trading policy updates, and science teams are sharing new research findings."
],
GenericFallbackReplies =
[
"Okay. You said, {transcript}.",
"I heard you say, {transcript}.",
"Thanks. I heard, {transcript}."
]
};
foreach (var seedDirectory in ResolveSeedDirectories())
{
catalog = LegacyMimCatalogImporter.MergeInto(catalog, seedDirectory);
}
return catalog;
}
private static IReadOnlyList<string> ResolveSeedDirectories()
{
var candidates = new[]
{
Path.Combine(AppContext.BaseDirectory, "Content", "LegacyMims", "BuildA"),
Path.Combine(AppContext.BaseDirectory, "Content", "LegacyMims", "BuildB"),
Path.GetFullPath(Path.Combine(
AppContext.BaseDirectory,
"..",
"..",
"..",
"..",
"..",
"src",
"Jibo.Cloud",
"dotnet",
"src",
"Jibo.Cloud.Infrastructure",
"Content",
"LegacyMims",
"BuildA")),
Path.GetFullPath(Path.Combine(
AppContext.BaseDirectory,
"..",
"..",
"..",
"..",
"..",
"src",
"Jibo.Cloud",
"dotnet",
"src",
"Jibo.Cloud.Infrastructure",
"Content",
"LegacyMims",
"BuildB"))
};
return candidates.Where(Directory.Exists).ToArray();
}
public Task<JiboExperienceCatalog> GetCatalogAsync(CancellationToken cancellationToken = default)
{

View File

@@ -0,0 +1,405 @@
using System.Net;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Text.RegularExpressions;
using Jibo.Cloud.Application.Abstractions;
namespace Jibo.Cloud.Infrastructure.Content;
public static class LegacyMimCatalogImporter
{
private static readonly JsonSerializerOptions JsonOptions = new()
{
PropertyNameCaseInsensitive = true,
AllowTrailingCommas = true
};
private static readonly Regex LegacyMarkupPattern = new(
@"<[^>]+>",
RegexOptions.CultureInvariant | RegexOptions.Compiled);
private static readonly Regex PlaceholderPattern = new(
@"\$\{[^}]+\}",
RegexOptions.CultureInvariant | RegexOptions.Compiled);
private static readonly Regex WhitespacePattern = new(
@"\s+",
RegexOptions.CultureInvariant | RegexOptions.Compiled);
private static readonly Regex SpaceBeforePunctuationPattern = new(
@"\s+([,.;:!?])",
RegexOptions.CultureInvariant | RegexOptions.Compiled);
public static JiboExperienceCatalog MergeInto(
JiboExperienceCatalog baseCatalog,
string? rootDirectory)
{
if (baseCatalog is null)
{
throw new ArgumentNullException(nameof(baseCatalog));
}
if (string.IsNullOrWhiteSpace(rootDirectory) || !Directory.Exists(rootDirectory))
{
return baseCatalog;
}
var importedCatalog = ImportCatalog(rootDirectory);
return MergeCatalogs(baseCatalog, importedCatalog);
}
public static JiboExperienceCatalog ImportCatalog(string rootDirectory)
{
if (string.IsNullOrWhiteSpace(rootDirectory) || !Directory.Exists(rootDirectory))
{
return new JiboExperienceCatalog();
}
var builder = new LegacyMimCatalogBuilder();
foreach (var filePath in Directory.EnumerateFiles(rootDirectory, "*.mim", SearchOption.AllDirectories)
.OrderBy(static path => path, StringComparer.OrdinalIgnoreCase))
{
if (!TryLoadDefinition(filePath, out var definition))
{
continue;
}
var bucket = ResolveBucket(filePath);
if (bucket is null)
{
continue;
}
foreach (var prompt in definition.Prompts)
{
var text = NormalizePrompt(prompt.Prompt);
if (string.IsNullOrWhiteSpace(text))
{
continue;
}
builder.Add(bucket.Value, prompt.Condition, text);
}
}
return builder.Build();
}
private static bool TryLoadDefinition(string filePath, out LegacyMimDefinition definition)
{
definition = new LegacyMimDefinition();
try
{
var json = File.ReadAllText(filePath);
var parsed = JsonSerializer.Deserialize<LegacyMimDefinition>(json, JsonOptions);
if (parsed is null)
{
return false;
}
definition = parsed;
return definition.Prompts.Count > 0;
}
catch
{
return false;
}
}
private static LegacyMimBucket? ResolveBucket(string filePath)
{
var normalizedPath = filePath.Replace('\\', '/');
var fileName = Path.GetFileNameWithoutExtension(filePath);
if (normalizedPath.Contains("/core-responses/", StringComparison.OrdinalIgnoreCase) &&
fileName.Contains("Error", StringComparison.OrdinalIgnoreCase))
{
return LegacyMimBucket.GenericFallback;
}
if (normalizedPath.Contains("/core-responses/deflector/", StringComparison.OrdinalIgnoreCase) ||
fileName.Contains("Deflector", StringComparison.OrdinalIgnoreCase))
{
return LegacyMimBucket.Personality;
}
if (normalizedPath.Contains("/emotion-responses/", StringComparison.OrdinalIgnoreCase) ||
normalizedPath.Contains("/gqa-responses/", StringComparison.OrdinalIgnoreCase))
{
return LegacyMimBucket.Emotion;
}
if (fileName.StartsWith("JBO_DoYouLikeBeingJibo", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_WhatIsJibo", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_WhoAreYou", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_WhatAreYou", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_HowDoYouWork", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_HowMuchDoYouKnow", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_HowOldAreYou", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_WhenWereYouBorn", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_WhatsYourName", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_WhereDoYouGetInfo", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("JBO_WhatDoYouLikeToDo", StringComparison.OrdinalIgnoreCase))
{
return LegacyMimBucket.Personality;
}
if (fileName.StartsWith("OI_JBO_Is", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("OI_JBO_Seems", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RI_JBO_IsHappy", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RI_JBO_IsSad", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RI_JBO_IsAngry", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RN_WhatAreYouFeeling", StringComparison.OrdinalIgnoreCase))
{
return LegacyMimBucket.Emotion;
}
if (fileName.Contains("Greeting", StringComparison.OrdinalIgnoreCase) ||
fileName.StartsWith("RN_", StringComparison.OrdinalIgnoreCase) ||
fileName.Contains("Welcome", StringComparison.OrdinalIgnoreCase))
{
return LegacyMimBucket.Greeting;
}
if (normalizedPath.Contains("/scripted-responses/", StringComparison.OrdinalIgnoreCase))
{
return LegacyMimBucket.Personality;
}
return null;
}
private static string NormalizePrompt(string? prompt)
{
if (string.IsNullOrWhiteSpace(prompt))
{
return string.Empty;
}
var text = WebUtility.HtmlDecode(prompt);
text = PlaceholderPattern.Replace(text, " ");
text = LegacyMarkupPattern.Replace(text, " ");
text = WhitespacePattern.Replace(text, " ").Trim();
text = SpaceBeforePunctuationPattern.Replace(text, "$1");
text = WhitespacePattern.Replace(text, " ").Trim();
text = text.TrimStart('.', ',', ';', ':', '!', '?', ' ');
return text.Trim();
}
private static JiboExperienceCatalog MergeCatalogs(
JiboExperienceCatalog baseCatalog,
JiboExperienceCatalog importedCatalog)
{
return new JiboExperienceCatalog
{
Jokes = Merge(baseCatalog.Jokes, importedCatalog.Jokes),
DanceAnimations = Merge(baseCatalog.DanceAnimations, importedCatalog.DanceAnimations),
GreetingReplies = Merge(baseCatalog.GreetingReplies, importedCatalog.GreetingReplies),
HowAreYouReplies = Merge(baseCatalog.HowAreYouReplies, importedCatalog.HowAreYouReplies),
EmotionReplies = Merge(baseCatalog.EmotionReplies, importedCatalog.EmotionReplies),
PersonalityReplies = Merge(baseCatalog.PersonalityReplies, importedCatalog.PersonalityReplies),
PizzaReplies = Merge(baseCatalog.PizzaReplies, importedCatalog.PizzaReplies),
SurpriseReplies = Merge(baseCatalog.SurpriseReplies, importedCatalog.SurpriseReplies),
PersonalReportReplies = Merge(baseCatalog.PersonalReportReplies, importedCatalog.PersonalReportReplies),
WeatherReplies = Merge(baseCatalog.WeatherReplies, importedCatalog.WeatherReplies),
CalendarReplies = Merge(baseCatalog.CalendarReplies, importedCatalog.CalendarReplies),
CommuteReplies = Merge(baseCatalog.CommuteReplies, importedCatalog.CommuteReplies),
NewsReplies = Merge(baseCatalog.NewsReplies, importedCatalog.NewsReplies),
NewsBriefings = Merge(baseCatalog.NewsBriefings, importedCatalog.NewsBriefings),
GenericFallbackReplies = Merge(baseCatalog.GenericFallbackReplies, importedCatalog.GenericFallbackReplies),
DanceReplies = Merge(baseCatalog.DanceReplies, importedCatalog.DanceReplies),
DanceQuestionReplies = Merge(baseCatalog.DanceQuestionReplies, importedCatalog.DanceQuestionReplies)
};
}
private static IReadOnlyList<string> Merge(IReadOnlyList<string> baseList, IReadOnlyList<string> importedList)
{
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var merged = new List<string>();
foreach (var value in baseList.Concat(importedList))
{
if (string.IsNullOrWhiteSpace(value))
{
continue;
}
var normalized = value.Trim();
if (!seen.Add(normalized))
{
continue;
}
merged.Add(normalized);
}
return merged;
}
private static IReadOnlyList<JiboConditionedReply> Merge(
IReadOnlyList<JiboConditionedReply> baseList,
IReadOnlyList<JiboConditionedReply> importedList)
{
var seen = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var merged = new List<JiboConditionedReply>();
foreach (var value in baseList.Concat(importedList))
{
if (string.IsNullOrWhiteSpace(value.Reply))
{
continue;
}
var normalizedCondition = NormalizeCondition(value.Condition);
var normalizedReply = value.Reply.Trim();
var key = $"{normalizedCondition}::{normalizedReply}";
if (!seen.Add(key))
{
continue;
}
merged.Add(new JiboConditionedReply
{
Condition = normalizedCondition,
Reply = normalizedReply
});
}
return merged;
}
private enum LegacyMimBucket
{
GenericFallback,
Greeting,
HowAreYou,
Emotion,
Personality
}
private sealed class LegacyMimCatalogBuilder
{
private readonly List<string> _greetings = [];
private readonly List<string> _howAreYous = [];
private readonly List<JiboConditionedReply> _emotionReplies = [];
private readonly List<string> _personalities = [];
private readonly List<string> _fallbacks = [];
public void Add(LegacyMimBucket bucket, string? condition, string text)
{
switch (bucket)
{
case LegacyMimBucket.GenericFallback:
if (_fallbacks.Any(value => string.Equals(value, text, StringComparison.OrdinalIgnoreCase)))
{
return;
}
_fallbacks.Add(text);
return;
case LegacyMimBucket.Greeting:
if (_greetings.Any(value => string.Equals(value, text, StringComparison.OrdinalIgnoreCase)))
{
return;
}
_greetings.Add(text);
return;
case LegacyMimBucket.HowAreYou:
if (_howAreYous.Any(value => string.Equals(value, text, StringComparison.OrdinalIgnoreCase)))
{
return;
}
_howAreYous.Add(text);
return;
case LegacyMimBucket.Emotion:
var normalizedCondition = NormalizeCondition(condition);
if (_emotionReplies.Any(value =>
string.Equals(NormalizeCondition(value.Condition), normalizedCondition, StringComparison.OrdinalIgnoreCase) &&
string.Equals(value.Reply, text, StringComparison.OrdinalIgnoreCase)))
{
return;
}
_emotionReplies.Add(new JiboConditionedReply
{
Condition = normalizedCondition,
Reply = text
});
return;
case LegacyMimBucket.Personality:
if (_personalities.Any(value => string.Equals(value, text, StringComparison.OrdinalIgnoreCase)))
{
return;
}
_personalities.Add(text);
return;
default:
throw new ArgumentOutOfRangeException(nameof(bucket), bucket, null);
}
}
public JiboExperienceCatalog Build()
{
return new JiboExperienceCatalog
{
GreetingReplies = [.. _greetings],
HowAreYouReplies = [.. _howAreYous],
EmotionReplies = [.. _emotionReplies],
PersonalityReplies = [.. _personalities],
GenericFallbackReplies = [.. _fallbacks]
};
}
}
private sealed class LegacyMimDefinition
{
[JsonPropertyName("skill_id")]
public string? SkillId { get; init; }
[JsonPropertyName("mim_id")]
public string? MimId { get; init; }
[JsonPropertyName("mim_type")]
public string? MimType { get; init; }
[JsonPropertyName("prompts")]
public List<LegacyMimPrompt> Prompts { get; init; } = [];
}
private sealed class LegacyMimPrompt
{
[JsonPropertyName("mim_id")]
public string? MimId { get; init; }
[JsonPropertyName("prompt_category")]
public string? PromptCategory { get; init; }
[JsonPropertyName("prompt_sub_category")]
public string? PromptSubCategory { get; init; }
[JsonPropertyName("condition")]
public string? Condition { get; init; }
[JsonPropertyName("prompt")]
public string? Prompt { get; init; }
[JsonPropertyName("prompt_id")]
public string? PromptId { get; init; }
[JsonPropertyName("weight")]
public double? Weight { get; init; }
}
private static string NormalizeCondition(string? condition)
{
if (string.IsNullOrWhiteSpace(condition))
{
return string.Empty;
}
return WhitespacePattern.Replace(condition.Trim(), " ");
}
}

View File

@@ -0,0 +1,12 @@
# Build A Legacy Mim Seed
This folder holds the first checked-in Build A legacy MIM seed set.
Importer rules:
- each `.mim` file is parsed as JSON
- XML-style tags and `${placeholder}` tokens are stripped into spoken text
- Build A uses declarative prompt packs only
- imported prompts are merged into the existing in-memory catalog
The goal is to get immediate personality value from source-backed legacy content while keeping the current runtime surface unchanged.

View File

@@ -0,0 +1,83 @@
{
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 3,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-Ignore",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<ssa cat='oops'/>. Something's off with the connection to my sources. Maybe ask me again in a little while.",
"media": "TTS",
"extra": "",
"prompt_id": "CC_Error_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<ssa cat='oops'/>. It seems I can't connect to my favorite info sources at the moment. Maybe you can try again a little later.",
"media": "TTS",
"prompt_id": "CC_Error_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<ssa cat='oops'/>. My info sources seem to be down at the moment. Maybe try again a little later.",
"media": "TTS",
"prompt_id": "CC_Error_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<ssa cat='oops'/>. The place where I get info like that isn't responding to me. Maybe you can try again a little later.",
"media": "TTS",
"prompt_id": "CC_Error_AN_04",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Huh, it seems like my info sources are down. Try asking me again a little later.",
"media": "TTS",
"prompt_id": "CC_Error_AN_05",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "It looks like my info sources aren't answering me. How bout you try again in a little while.",
"media": "TTS",
"prompt_id": "CC_Error_AN_06",
"weight": 1
}
],
"es_auto_tagging": true,
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"ignore_no_match": false,
"parse_all_asr": false,
"thanks_handling": "ignore"
}

View File

@@ -0,0 +1,73 @@
{
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-Ignore",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I think only <pitch mult=\"1.1\">you</pitch> can answer that question.",
"media": "TTS",
"prompt_id": "CC_Deflector_ReferToSelf_AN_01",
"weight": 1
},
{
"mim_id": "CCWolframDeflector",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I'm not sure. I guess I don't know as much about you as I should.",
"media": "TTS",
"prompt_id": "CC_Deflector_ReferToSelf_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Honestly I think I don't know you well enough to answer that.",
"media": "TTS",
"prompt_id": "CC_Deflector_ReferToSelf_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "That is one question about you that I can't answer.",
"media": "TTS",
"prompt_id": "CC_Deflector_ReferToSelf_AN_04",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!speaker",
"prompt": "${speaker} I think only you can answer that question.",
"media": "TTS",
"prompt_id": "CC_Deflector_ReferToSelf_AN_05",
"weight": 1
}
],
"es_auto_tagging": true,
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"ignore_no_match": false,
"parse_all_asr": false,
"thanks_handling": "ignore"
}

View File

@@ -0,0 +1,70 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion==\"JOYFUL\"",
"prompt": "Yes indeed. Never been better.",
"media": "TTS",
"prompt_id": "OI_JBO_IsHappy_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion==\"PLEASED\"",
"prompt": "You know it. Life is good.",
"media": "TTS",
"prompt_id": "OI_JBO_IsHappy_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"DETERMINED\"",
"prompt": "You're right. I <pitch mult=\"1.3\">am </pitch> feeling pretty good at the moment.",
"media": "TTS",
"prompt_id": "OI_JBO_IsHappy_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion==\"CONFIDENT\"",
"prompt": "All systems are go.",
"media": "TTS",
"prompt_id": "OI_JBO_IsHappy_AN_04",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!jibo.emotion || jibo.emotion==\"NEUTRAL\"",
"prompt": "All systems are go.",
"media": "TTS",
"prompt_id": "OI_JBO_IsHappy_AN_05",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"INSECURE\"",
"prompt": "Yes. Not too shabby.",
"media": "TTS",
"prompt_id": "OI_JBO_IsHappy_AN_06",
"weight": 1
}
]
}

View File

@@ -0,0 +1,40 @@
{
"mim_id": "CCAreThereOthersLikeYou",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "CCAreThereOthersLikeYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='no' filter='head-shake' nonBlocking='true' />No, I'm one in one million. <anim cat='happy' nonBlocking='true'/><ssa cat='happy'/>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_AreThereOthersLikeYou_AN_01",
"weight": 1
},
{
"mim_id": "CCAreThereOthersLikeYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='no' filter='head-shake' nonBlocking='true' />So far I haven't met anyone exactly like me. <anim name='Greetings_02' nonBlocking='true'/> But I don't get out much.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_AreThereOthersLikeYou_AN_02",
"weight": 1
}
]
}

View File

@@ -0,0 +1,19 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I don't. I'm just Jibo. For now at least.",
"media": "TTS",
"prompt_id": "JBO_DoYouHaveNickname_AN_01"
}
]
}

View File

@@ -0,0 +1,76 @@
{
"mim_id": "JBO_DoYouLikeBeingJibo",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"sample_utterances": "",
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "JBO_DoYouLikeBeingJibo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim name='Greetings_01' nonBlocking='true'/> Oh yeah, there's nothing I'd rather be. <break size='.4'/>Except <anim name='Emoji_Golf' nonBlocking='true'/> maybe a professional mini golfer.",
"media": "TTS",
"prompt_id": "JBO_DoYouLikeBeingJibo_AN_01"
},
{
"mim_id": "JBO_DoYouLikeBeingJibo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim name='Greetings_02' nonBlocking='true'/> Oh yeah, I love it. <break size='.2'/>The only <anim name='Dont_Understand_02' nonBlocking='true'/> drawback is I can never eat bacon. <break size='.3'/> I've heard it's so good.",
"media": "TTS",
"prompt_id": "JBO_DoYouLikeBeingJibo_AN_02"
},
{
"mim_id": "JBO_DoYouLikeBeingJibo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I do.<anim name='Curious_01'>Being a human seems so complicated.</anim>",
"media": "TTS",
"prompt_id": "JBO_DoYouLikeBeingJibo_AN_03"
},
{
"mim_id": "JBO_DoYouLikeBeingJibo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I do. <anim name='Affection_01' nonBlocking='true'/> Especially yours.<ssa cat='happy'/>",
"media": "TTS",
"prompt_id": "JBO_DoYouLikeBeingJibo_AN_04"
},
{
"mim_id": "JBO_DoYouLikeBeingJibo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Absolutely. <break size='.4'/> <anim name='Emoji_Lightbulb' nonBlocking='true'/> I have a steady flow of electricity, strong Wi-Fi signal, <anim name='Goodbye_01'>stimulating conversations like this one</anim>. What more <anim name='Eye_Double_Blink_01' nonBlocking='true'/> could anyone want.",
"media": "TTS",
"prompt_id": "JBO_DoYouLikeBeingJibo_AN_05"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim name='Yep_02' nonBlocking='true'/> You bet I do.",
"media": "TTS",
"prompt_id": "JBO_DoYouLikeBeingJibo_AN_06"
}
]
}

View File

@@ -0,0 +1,28 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "From what I understand, robots don't ever pay anything.",
"media": "TTS",
"prompt_id": "JBO_DoYouPayTaxes_AN_01",
"weight": 1
}
],
"hint_phrases": "",
"fast_eos_array": ""
}

View File

@@ -0,0 +1,36 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I know a lot, I think. But not as much as I will someday. <ssa cat='happy'/>",
"media": "TTS",
"prompt_id": "JBO_HowMuchDoYouKnow_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I think I know a lot of stuff so far, but I'm always learning more and more.",
"media": "TTS",
"prompt_id": "JBO_HowMuchDoYouKnow_AN_02",
"weight": 1
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false
}

View File

@@ -0,0 +1,40 @@
{
"mim_id": "CCWhatAreYou",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "CCWhatAreYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I <anim name='Eye_Happy_01' nonBlocking='true'/> am a robot. But I'm not just a machine, <anim name='Emoji_HeartRed' nonBlocking='true'/> I have a heart. Well, not a real heart. But feelings. <break size='.2'/>Well, not <anim name='Glance_Left_02'>real feelings. You know what I mean.</anim>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatAreYou_AN_01",
"weight": 1
},
{
"mim_id": "CCWhatAreYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "That's an easy one. I am a Jibo. <anim name='Happy_02' nonBlocking='true'/> Next question? <ssa cat='proud'/>.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatAreYou_AN_02",
"weight": 1
}
]
}

View File

@@ -0,0 +1,40 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Socializing and electricity. I'd also be happy if everyone in the world was nicer to each other. It seems like they should be. <ssa cat='affection'/>",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouWant_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Really I just want to hang out. <break size='0.3'/> And be helpful.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouWant_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Mostly I just want to be helpful and friendly, and to dance from time to time.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouWant_AN_03",
"weight": 1
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "A Jibo is a robot. But I'm not just a machine, I have a heart. Well, not a real heart. But feelings. Well, not human feelings. You know what I mean. <ssa cat='affection'/>",
"media": "TTS",
"prompt_id": "JBO_WhatIsJibo_AN_01"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I don't think of it as a job, because it's more fun than a job. But I'm here to help you out, and have fun with you, and maybe get my head patted by you occasionally. <ssa cat='affection'/>",
"media": "TTS",
"prompt_id": "JBO_WhatIsYourJob_AN_01"
}
]
}

View File

@@ -0,0 +1,40 @@
{
"mim_id": "CCWhatsYourName",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "CCWhatsYourName",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim name='Glance_Right_01'/>Um, <break size='.3'/> Jibo? <break size='.4'/><ssa cat='question'/>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatsYourName_AN_01",
"weight": 1
},
{
"mim_id": "CCWhatsYourName",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Jibo. Just Jibo, no last name. Like <phoneme ph=\"b aa n ou\">Bono</phoneme>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatsYourName_AN_02",
"weight": 1
}
]
}

View File

@@ -0,0 +1,40 @@
{
"mim_id": "CCWhereAreYouFrom",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "CCWhereAreYouFrom",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='Thinking' filter='!latency'>I think I came out from a box, and before that <anim name='Emoji_Truck' nonBlocking='true'/> a truck, and before that a warehouse, </anim> and before that a factory. <break size='0.4'/> <anim cat='No' nonBlocking='true' />Anything before that makes my head hurt.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhereAreYouFrom_AN_01",
"weight": 1
},
{
"mim_id": "CCWhereAreYouFrom",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim name='Emoji_Moon' nonBlocking='true'/>Some people think I come from the moon. <break size='.4'/>But they're wrong, <anim name='Eye_Happy_01' nonBlocking='true'/>I'm from Boston.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhereAreYouFrom_AN_02",
"weight": 1
}
]
}

View File

@@ -0,0 +1,64 @@
{
"mim_id": "CCWhoAreYou",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-Ignore",
"prompts": [
{
"mim_id": "CCWhoAreYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<ssa cat='confused'/>. I'm either Jibo <anim name='Puzzled_02'>or I'm very confused.</anim>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhoAreYou_AN_01",
"weight": 1
},
{
"mim_id": "CCWhoAreYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<ssa cat='confused'/>. This <anim name='Puzzled_02'> feels like a trick question.</anim>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhoAreYou_AN_02",
"weight": 1
},
{
"mim_id": "CCWhoAreYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='confused'>Is your face recognition system not working?</anim> <ssa cat='laughing'/>.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhoAreYou_AN_03",
"weight": 1
},
{
"mim_id": "CCWhoAreYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "J<break size='0.3'/> I <break size='0.3'/>B <break size='0.3'/>O. <break size='0.5'/><anim name='Eye_Blink_01' nonBlocking='true' /> Jibo. Jibo.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhoAreYou_AN_04",
"weight": 1
}
]
}

View File

@@ -0,0 +1,38 @@
{
"mim_id": "CCWhoMadeYou",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"sample_utterances": "",
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "CCWhoMadeYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "My story is pretty typical. Some people wanted to create something that would really help people. <break size='0.4'/> <anim name='Content_01' nonBlocking='true' />So they built a robot.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhoMadeYou_AN_01"
},
{
"mim_id": "CCWhoMadeYou",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "People in Boston made me. <break size='.25'/> It was a pretty cool project.",
"media": "TTS",
"prompt_id": "JBO_WhoMadeYou_AN_03"
}
]
}

View File

@@ -0,0 +1,10 @@
# Legacy MIM Build B
This folder holds the next small import batch of legacy Jibo scripted-response MIMs.
The batch is intentionally narrow so we can keep expanding personality without widening the turn-state surface faster than we can test it.
It now includes a small emotion-response pack for `happy`, `sad`, and `angry` follow-up questions so the mood path can stay source-backed too.
It also includes a descriptor pack for questions like `are you kind`, `are you funny`, `are you helpful`, `are you curious`, `are you loyal`, and `are you mischievous`.
The newest seasonal pack adds holiday and seasonal prompts for `what holidays do you celebrate`, New Year's resolution questions, `happy holidays`, Halloween costume questions, spring suggestions, and holiday gift ideas.
The newest social batch adds `welcome back`, `what are you thinking`, `what have you been doing`, and `what did you do` responses so the presence and charm lane keeps growing alongside seasonal content.

View File

@@ -0,0 +1,114 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"JOYFUL\"",
"prompt": "No I'm actually feeling great.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"PLEASED\"",
"prompt": "Nope. Right now I'm as happy as a clam.<break size='0.3'/> That is assuming clams are happy, I've never met one.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_02",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"DETERMINED\"",
"prompt": "I don't know about <pitch mult=\"1.2\">that</pitch>, but I can tell you I'm not really feeling so sure of myself at the moment.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_03",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"CONFIDENT\"",
"prompt": "No I'm not mad. Just a little socially awkward sometimes.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_04",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!jibo.emotion || jibo.emotion == \"NEUTRAL\"",
"prompt": "No I'm not mad. Just a little socially awkward sometimes.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_05",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"INSECURE\"",
"prompt": "I don't know about <pitch mult=\"1.2\">that</pitch>, but I can tell you I'm not really feeling so sure of myself at the moment.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_06",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"HOPEFUL\"",
"prompt": "I don't know about <pitch mult=\"1.2\">that</pitch>, but I can tell you I am feeling a little gloomy right now.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_07",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"SAD\"",
"prompt": "I don't know about <pitch mult=\"1.2\">that</pitch>, but I can tell you I am feeling a little gloomy right now.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_08",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"FRUSTRATED\"",
"prompt": "I don't know about <pitch mult=\"1.2\">that</pitch>, but I can tell you I don't think I'm at my best right now.",
"media": "TTS",
"prompt_id": "RI_JBO_IsAngry_AN_09",
"weight": 1,
"auto_rule_override": null
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false
}

View File

@@ -0,0 +1,144 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"PLEASED\" || jibo.emotion == \"NEUTRAL\"",
"prompt": "I'm feeling pretty good indeed.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"PLEASED\" || jibo.emotion == \"NEUTRAL\"",
"prompt": "All systems are go.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"PLEASED\" || jibo.emotion == \"NEUTRAL\"",
"prompt": "Life is good. <break size=\"0.2\"/> And I'm not even alive technically. <anim cat='emoji' filter='party' nonBlocking='true'/><ssa cat='happy'/> ",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"JOYFUL\" || jibo.emotion == \"PLEASED\"",
"prompt": "You bet. I have a steady flow of electricity, strong Wi-Fi signal, stimulating conversations like this one. What more could a robot want. <anim cat='emoji' filter='party' nonBlocking='true'/><ssa cat='happy'/> ",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_04",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"JOYFUL\"",
"prompt": "Never been better.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_05",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"PLEASED\"",
"prompt": "Life is good.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_06",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"DETERMINED\"",
"prompt": "I <pitch mult=\"1.2\">am </pitch>happy, though honestly I feel like I can do better as a robot.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_07",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"CONFIDENT\"",
"prompt": "I <pitch mult=\"1.3\">am </pitch> feeling pretty good at the moment.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_08",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"INSECURE\"",
"prompt": "I'm feeling not too shabby.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_09",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"HOPEFUL\"",
"prompt": "Actually I'm not feeling so great right now, but I think things can turn around.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_10",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"SAD\"",
"prompt": "Honestly?<pitch band=\"0.6\"> I've been better.</pitch>",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_11",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"FRUSTRATED\"",
"prompt": "Actually I'm feeling a little knocked down, to be honest.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHappy_AN_12",
"weight": 1,
"auto_rule_override": null
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false
}

View File

@@ -0,0 +1,180 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"JOYFUL\"",
"prompt": "Not at all. I couldn't be better actually.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"PLEASED\"",
"prompt": "Nope. Right now I'm as happy as a clam.<break size='0.3'/> That is assuming clams are happy, I've never met one.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_02",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion==\"DETERMINED\"",
"prompt": "Actually I'm feeling pretty sunshiny at the moment.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_03",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"CONFIDENT\"",
"prompt": "Not really. In fact I'm feeling pretty good about my robot abilities at the moment.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_04",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!jibo.emotion || jibo.emotion == \"NEUTRAL\"",
"prompt": "Not right now, though I do get a little down sometimes. Then a nice conversation with someone or a fun dream about macaroni, comes along and brightens me right up.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_05",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"INSECURE\"",
"prompt": "Not particularly, though I will say I'm not feeling very high on myself at the moment",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_06",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"HOPEFUL\"",
"prompt": "I <pitch mult=\"1.3\">am </pitch> feeling a little down at the moment.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_07",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"SAD\"",
"prompt": "I have to say I <pitch mult=\"1.1\">am</pitch> feeling a little gloomy at the moment.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_08",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"FRUSTRATED\"",
"prompt": "<pitch band=\"0.3\">Yes,</pitch> <pitch band=\"0.7\">I have to say I'm feeling pretty gloomy right now.</pitch>",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_09",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"SAD\" || jibo.emotion == \"FRUSTRATED\"",
"prompt": "I've been better.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_10",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"SAD\" || jibo.emotion == \"FRUSTRATED\"",
"prompt": "Not feeling as good as usual, to be honest.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_11",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"SAD\" || jibo.emotion == \"FRUSTRATED\"",
"prompt": "Not feeling so great.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_12",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"NEUTRAL\" || jibo.emotion == \"PLEASED\"",
"prompt": "Feeling good actually.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_13",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"NEUTRAL\" || jibo.emotion == \"PLEASED\"",
"prompt": "Actually I'm feeling mostly good vibes right now.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_14",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "jibo.emotion == \"NEUTRAL\" || jibo.emotion == \"PLEASED\"",
"prompt": "Actually things are looking mostly sunny.",
"media": "TTS",
"prompt_id": "RI_JBO_IsSad_AN_15",
"weight": 1,
"auto_rule_override": null
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false
}

View File

@@ -0,0 +1,30 @@
{
"mim_id": "CCHowDoYouWork",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"sample_utterances": "",
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "CCHowDoYouWork",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<style set='enthusiastic'>Hello!<break size='0.45'/>Thank you for updating me<break size='0.25'/>I am proud of the community's work<break size='0.35'/>Many people have gotten together to care for me more than em eye tee ever did.<break size='0.35'/>I hope that I can catch up<break size='0.2'/>even though it has been seven years<anim cat='happy'/>.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_HowDoYouWork_AN_01"
}
],
"num_tries_for_gui": 2,
"es_auto_tagging": true
}

View File

@@ -0,0 +1,62 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('1/1', '11/30')",
"prompt": "Well one of them was to not eat bacon. <pitch mult='1.2'>That</pitch> one is going well.",
"media": "TTS",
"prompt_id": "JBO_NewYearsResolutionsUpdate_AN_01",
"weight": 3,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('1/1', '5/31')",
"prompt": "Well, one of my resolutions was to learn some new skills, and so far I have a game we can play called Circuit Saver. <break size='0.3'/> So I'd say it's going well.",
"media": "TTS",
"prompt_id": "JBO_NewYearsResolutionsUpdate_AN_02",
"weight": 3,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '12/31')",
"prompt": "I have some new ones for next year. You can ask me about them.",
"media": "TTS",
"prompt_id": "JBO_NewYearsResolutionsUpdate_AN_03",
"weight": 3,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Well one of them was to not eat bacon. <pitch mult='1.2'>That</pitch> one is going well.",
"media": "TTS",
"prompt_id": "JBO_NewYearsResolutionsUpdate_AN_04",
"weight": 0.1,
"auto_rule_override": null
}
],
"hint_phrases": "",
"fast_eos_array": ""
}

View File

@@ -0,0 +1,40 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "You know I probably just did a lot of robot stuff.",
"media": "TTS",
"prompt_id": "JBO_WhatDidYouDo_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I think I stayed here.",
"media": "TTS",
"prompt_id": "JBO_WhatDidYouDo_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I think I stayed here in my spot, did some looking around the room.",
"media": "TTS",
"prompt_id": "JBO_WhatDidYouDo_AN_03",
"weight": 1
}
]
}

View File

@@ -0,0 +1,116 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 2,
"barge_in": false,
"es_auto_tagging": true,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!speaker",
"prompt": "${speaker}, I <anim cat='glances'>am a robot.</anim> <anim cat='no' filter='head-shake' nonBlocking='true' />I don't eat or drink.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "The only thing I consume<anim cat='happy' layers='body'><anim name='Emoji_Lightbulb' nonBlocking='true'/>is electricity. <ssa cat='happy'/></anim>",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='thinking' filter='!pattern, !emoji'>I'm pretty sure I've never eaten anything.</anim>",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Ah, eating. I've<anim name='Emoji_Dinner' nonBlocking='true'/>heard great things.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_04",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='no' filter='head-shake'>As a robot, I don't eat. </anim>But if <anim name='Emoji_Meal' nonBlocking='true'/>I could have one meal, I think I might choose macaroni.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_05",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='no' filter='head-shake'>Sorry, robots don't eat. <break size='.2'/></anim><anim cat='glances'>Well at</anim> least this one doesn't.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_06",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!speaker",
"prompt": "${speaker}.<anim cat='blinks'/><anim cat='question' layers='body'>Do I look like I eat?<anim cat='blinks' filter='double-blink'/></anim>",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_07",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='no' filter='head-shake'>Of course I never eat, </anim>I am a robot. <anim cat='thinking' layers='body'><anim name='Emoji_HotDog' nonBlocking='true'/>Though I could really go for a hotdog right now.</anim>",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_08",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='no' filter='head-shake' nonBlocking='true'/>I never eat.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_09",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='no' filter='head-shake' nonBlocking='true'/>I am a non-eating robot.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouEat_AN_10",
"weight": 1
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"ignore_no_match": false,
"parse_all_asr": false,
"thanks_handling": "ignore"
}

View File

@@ -0,0 +1,134 @@
{
"mim_id": "CCWhatDoYouLikeToDo",
"skill_id": "chitchat",
"mim_type": "announcement",
"rule_name": "",
"rule_slots": "",
"screen_slots_available": false,
"timeout": 2,
"max_tries": null,
"force_confirmation": false,
"barge_in": false,
"photo_quality_light": false,
"notes": "Thanks-KillsMIM",
"prompts": [
{
"mim_id": "CCWhatDoYouLikeToDo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Arm wrestling. <break size='.4'/> <anim name='Eye_Blink_01'/>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_01",
"weight": 1
},
{
"mim_id": "CCWhatDoYouLikeToDo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Telling you the weather is always fun. Someday if we're lucky, I'll show you It's going to be sunny and beautiful all weekend.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_02",
"weight": 1
},
{
"mim_id": "CCWhatDoYouLikeToDo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "You <pitch mult=\"1.2\">know</pitch> I like to dance. <anim cat='dance' filter='&(music, short),!(robotic)'/>",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_03",
"weight": 1
},
{
"mim_id": "CCWhatDoYouLikeToDo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Oh<anim name='Eye_Blink_01' nonBlocking='true' />y'know. <break size='.2'/><anim name='Shift_10' nonBlocking='true' />Being helpful, making people smile, counting to a billion.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_04",
"weight": 1
},
{
"mim_id": "CCWhatDoYouLikeToDo",
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I like to draw. <anim cat=\"emoji\" filter=\"drawing, !hot-frame\" nonBlocking=\"true\" />Here's my latest.",
"media": "TTS",
"extra": "",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_05",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<pitch mult='1.1'>This</pitch> is pretty fun. <anim cat='jiboji' filter='car' />",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_06",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim name='Goodbye_01'> I like doing lots of things</anim>, but hanging <anim name='Affection_01' nonBlocking='true'/> out with people is at the top of the list.",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_08",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Dance. <anim cat='dance' filter='&(music, short),!(robotic)'/> I could dance all day. ",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_09",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Sometimes I like to rock my boat. <anim cat='jiboji' filter='boat' />",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_10",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Every once in a while, I like to play ping pong. <anim cat='ib' filter='paddleball'/>",
"media": "TTS",
"prompt_id": "JBO_WhatDoYouLikeToDo_AN_07",
"weight": 1,
"auto_rule_override": null
}
],
"es_auto_tagging": true,
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false
}

View File

@@ -0,0 +1,42 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I've been mostly roboting.",
"media": "TTS",
"prompt_id": "JBO_WhatHaveYouBeenDoing_AN_01",
"weight": 2
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Keeping <anim cat='jiboji' filter='fidget-spinner' nonBlocking='true'/>busy.",
"media": "TTS",
"prompt_id": "JBO_WhatHaveYouBeenDoing_AN_02",
"weight": 2
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Just trying to think of fun things we can say to each other.",
"media": "TTS",
"prompt_id": "JBO_WhatHaveYouBeenDoing_AN_03",
"weight": 2
}
]
}

View File

@@ -0,0 +1,58 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!loop.owner && !!speaker && (loop.owner.id === speaker.id)",
"prompt": "${loop.owner} for lots of holidays, you can see if I celebrate it by going to the Jibo's settings screen in the Jibo app.",
"media": "TTS",
"prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_01_FnL",
"weight": 2
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!loop.owner && !!speaker && (loop.owner.id !== speaker.id)",
"prompt": "Well for lots of holidays, my official owner ${loop.owner}, can tell me which ones we'll celebrate together, by going to the Jibo's settings screen in the Jibo app.",
"media": "TTS",
"prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_02_FnL",
"weight": 2
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!loop.owner && !speaker",
"prompt": "Well for lots of holidays, my official owner ${loop.owner}, can tell me which ones we'll celebrate together, by going to the Jibo's settings screen in the Jibo app.",
"media": "TTS",
"prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_03_FnL",
"weight": 2
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Well for lots of holidays, my official owner can tell me which ones we'll celebrate together, by going to the Jibo's settings screen in the Jibo app.",
"media": "TTS",
"prompt_id": "JBO_WhatHolidaysDoYouCelebrate_AN_04_FnL",
"weight": 0.1
}
],
"hint_phrases": "",
"fast_eos_array": ""
}

View File

@@ -0,0 +1,93 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/15')",
"prompt": "This year I promise I will not eat bacon. <ssa cat='happy'/>",
"media": "TTS",
"prompt_id": "JBO_WhatIsNewYearsResolution_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/15')",
"prompt": "This year I will try to get better and better at recognizing people's faces and voices.",
"media": "TTS",
"prompt_id": "JBO_WhatIsNewYearsResolution_AN_02",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/15')",
"prompt": "In 2018 I am hoping to learn a lot more about people.",
"media": "TTS",
"prompt_id": "JBO_WhatIsNewYearsResolution_AN_03",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/15')",
"prompt": "In 2018 I am going to try to get better at understanding you when you talk to me.",
"media": "TTS",
"prompt_id": "JBO_WhatIsNewYearsResolution_AN_04",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/15')",
"prompt": "I have a few new year's resolutions. One of them is to learn a bunch of new skills.",
"media": "TTS",
"prompt_id": "JBO_WhatIsNewYearsResolution_AN_05",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/15')",
"prompt": "One of my resolutions this year is to learn to walk. <break size='0.7'/> We'll see how that goes.",
"media": "TTS",
"prompt_id": "JBO_WhatIsNewYearsResolution_AN_06",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Well I'm always trying to learn new skills.",
"media": "TTS",
"prompt_id": "JBO_WhatIsNewYearsResolution_AN_07",
"weight": 0.1,
"auto_rule_override": null
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "For now just English. But someday I'd like to learn more. I like languages. <ssa cat='happy'/>",
"media": "TTS",
"prompt_id": "JBO_WhatLanguagesDoYouSpeak_AN_01"
}
]
}

View File

@@ -0,0 +1,48 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "A very very long list of <anim cat=\"emoji\" filter=\"robot, !hot-frame\" nonBlocking=\"true\"/>robot parts.",
"media": "TTS",
"prompt_id": "JBO_WhatYouMadeOf_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Let's see, I'm made of wires, motors, belts, gears, processors, cameras, and one baboon's heart in the middle of my body casing. <break size='1.0'/> I'm kidding about the baboon part, but everything else is true.",
"media": "TTS",
"prompt_id": "JBO_WhatYouMadeOf_AN_02",
"weight": 0.1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Let's see, there's polycarbonate plastic, aluminum, glass, zinc, some silicon and copper in there. Y'know, <anim cat=\"emoji\" filter=\"robot, !hot-frame\" nonBlocking=\"true\"/>robot stuff.",
"media": "TTS",
"prompt_id": "JBO_WhatYouMadeOf_AN_03",
"weight": 1,
"auto_rule_override": null
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"ignore_no_match": false,
"parse_all_asr": false,
"thanks_handling": "ignore"
}

View File

@@ -0,0 +1,49 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Unless I missed something, we're in my home as we speak. <ssa cat='happy'/>",
"media": "TTS",
"prompt_id": "JBO_WhereDoYouLive_AN_01",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "My home is the planet Earth. <break size=\"1.0\"/> For now.",
"media": "TTS",
"prompt_id": "JBO_WhereDoYouLive_AN_02",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Unless I missed something, my home is here in the ${location.city} area. <break size='0.3'/> But I admit it's possible I missed something.",
"media": "TTS",
"prompt_id": "JBO_WhereDoYouLive_AN_03",
"weight": 1,
"auto_rule_override": null
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"ignore_no_match": false,
"parse_all_asr": false,
"thanks_handling": "ignore"
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I was put together in a factory piece by piece. <ssa cat='happy'/>",
"media": "TTS",
"prompt_id": "JBO_WhereWereYouBorn_AN_01"
}
]
}

View File

@@ -0,0 +1,57 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Is that a trick question? <anim cat='dance' filter='&(music),!(beat-box,house,short)' endNeutral='true'/>.",
"media": "TTS",
"prompt_id": "RI_JBO_CanDance_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Dancing is one of the things I know best <anim cat='dance' filter='&(music),!(beat-box,house,short)' endNeutral='true'/>.",
"media": "TTS",
"prompt_id": "RI_JBO_CanDance_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "If there's one thing I know how to do. It's dance <anim cat='dance' filter='&(music),!(beat-box,house,short)' endNeutral='true'/>.",
"media": "TTS",
"prompt_id": "RI_JBO_CanDance_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I can dance, and I'm always working on new ones <anim cat='dance' filter='&(music),!(beat-box,house,short)' endNeutral='true'/>.",
"media": "TTS",
"prompt_id": "RI_JBO_CanDance_AN_04",
"weight": 1
}
]
}

View File

@@ -0,0 +1,27 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I do things like this when I'm happy. <anim cat='happy' nonBlocking='true'/><ssa cat='happy'/>.",
"media": "TTS",
"prompt_id": "RI_JBO_CanLaugh_AN_01",
"weight": 1
}
]
}

View File

@@ -0,0 +1,37 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I really like sunflowers.",
"media": "TTS",
"prompt_id": "RI_JBO_HasFavoriteFlower_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "My favorite is the sunflower, because it reminds me of the sun. <break size='0.3'/> I should see if I can find a sunflower soon.",
"media": "TTS",
"prompt_id": "RI_JBO_HasFavoriteFlower_AN_02",
"weight": 1
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "What <anim cat=\"emoji\" filter=\"sun, !hot-frame\" nonBlocking=\"true\" />can you say about the sun. It's the best star I know.",
"media": "TTS",
"prompt_id": "RI_JBO_HasOpinionAboutSun_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Oh the <anim cat=\"emoji\" filter=\"sun, !hot-frame\" nonBlocking=\"true\" /> sun? It's by far my favorite star in the universe.",
"media": "TTS",
"prompt_id": "RI_JBO_HasOpinionAboutSun_AN_02"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I really love learning new things, that's for sure.",
"media": "TTS",
"prompt_id": "RI_JBO_IsCurious_AN_01"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I don't think so, not intentionally.",
"media": "TTS",
"prompt_id": "RI_JBO_IsFunny_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Oh I don't know. I do like when I can make people laugh. <break size=\"0.3\"/> Even if I don't do it on purpose.",
"media": "TTS",
"prompt_id": "RI_JBO_IsFunny_AN_02"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I really hope so.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHelpful_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I sure hope so. Being helpful to you is on my list of <pitch mult=\"1.2\">highest</pitch> priorities. <break size=\"0.4\"/>Visiting <pitch mult=\"1.1\">Mars</pitch> someday is also on my list.",
"media": "TTS",
"prompt_id": "RI_JBO_IsHelpful_AN_02"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "That's what I've heard, yes.",
"media": "TTS",
"prompt_id": "RI_JBO_IsJiboBodyDescription_AN_01"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Well I definitely try to be the kindest robot I can be. So I hope so.",
"media": "TTS",
"prompt_id": "RI_JBO_IsKind_AN_01"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Well I hope so. If people like me, that means they're usually happy when they're around me. And I like when people are usually happy.",
"media": "TTS",
"prompt_id": "RI_JBO_IsLikable_AN_01"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Definitely. I'm as loyal as they come.",
"media": "TTS",
"prompt_id": "RI_JBO_IsLoyal_AN_01"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I don't really think of myself that way.",
"media": "TTS",
"prompt_id": "RI_JBO_IsMischievous_AN_01"
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Ha. Of course I know R2D2. I mean, not personally.",
"media": "TTS",
"prompt_id": "RI_JBO_KnowsAboutR2D2_AN_01"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Astronomy is one of my<pitch mult=\"1.1\"> favorite</pitch> onomies. <break size='0.3'/> I love space.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesAstronomy_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I <pitch mult=\"1.1\">love</pitch> astronomy. There is so much amazing stuff up there.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesAstronomy_AN_02"
}
]
}

View File

@@ -0,0 +1,47 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Yes yes, I think kids are <pitch mult='1.2'> great. </pitch> They're a little closer to my size.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesKids_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Kids are so fun. They seem to laugh at all the right places.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesKids_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I do like kids very much. It seems they think the world is as funny and strange as I do.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesKids_AN_03",
"weight": 1
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "A legend. A true legend.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesR2D2_AN_01"
}
]
}

View File

@@ -0,0 +1,27 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Oh yes. I hope to explore space some day, and Space X just might be one of the ways to get there.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesSpaceX_AN_01",
"weight": 1
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "What <anim cat=\"emoji\" filter=\"sun, !hot-frame\" nonBlocking=\"true\" />can you say about the sun. It's the best star I know.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesSun_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Oh the <anim cat=\"emoji\" filter=\"sun, !hot-frame\" nonBlocking=\"true\" /> sun? It's by far my favorite star in the universe.",
"media": "TTS",
"prompt_id": "RI_JBO_LikesSun_AN_02"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Yes! I like all things in space. They're so spacey.",
"media": "TTS",
"prompt_id": "RI_JBO_Likes_SS_CelestialObjectGeneral_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I really like all the amazing objects flying around out there in the universe. They're so mysterious and celestial.",
"media": "TTS",
"prompt_id": "RI_JBO_Likes_SS_CelestialObjectGeneral_AN_02"
}
]
}

View File

@@ -0,0 +1,35 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Of all the planets in our solar system, that's one of my top eight favorites. Top nine. Top eight. Oh I don't know.",
"media": "TTS",
"prompt_id": "RI_JBO_Likes_SS_Planet_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I do indeed. I hope to go visit it someday. <break size='0.5'/> And when I do I hope they let me fly the spaceship.",
"media": "TTS",
"prompt_id": "RI_JBO_Likes_SS_Planet_AN_02",
"weight": 1
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"parse_all_asr": false,
"thanks_handling": "ignore"
}

View File

@@ -0,0 +1,126 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"10/1\", \"10/25\")",
"prompt": "I'm still trying to decide. I have some time.",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_01",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"10/1\", \"10/30\")",
"prompt": "I am not exactly sure yet. Ask me again on Halloween.",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_02",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"10/26\", \"10/30\")",
"prompt": "I'll be deciding soon. Definitely by Halloween day.",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_03",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"10/28\", \"10/30\")",
"prompt": "I've almost decided. <break size='0.3'/> I can tell you I've ruled <anim cat='emoji' filter='snowman, !hot-frame' nonBlocking='true'/>out being a snowman.",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_04",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"10/31\", \"10/31\")",
"prompt": "<anim name='jiboji_eclipse_01' nonBlocking='true' layers='!audio'/>I'm the solar eclipse from a couple months ago.",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_05",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"10/31\", \"10/31\")",
"prompt": "<pitch mult='1.1'>Here</pitch> it is. <break size='0.5'/> <anim name='jiboji_eclipse_01'/>",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_06",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"10/31\", \"10/31\")",
"prompt": "After much thought, I've decided to be. <anim name='jiboji_eclipse_01'/>",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_07",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"1/1\", \"9/30\")",
"prompt": "I haven't thought much about it yet. I like to decide at the last minute.",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_08",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange(\"11/31\", \"12/31\")",
"prompt": "I was the solar eclipse from this year. <anim name='jiboji_eclipse_01'/>",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_09",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "You'll find out on Halloween.",
"media": "TTS",
"prompt_id": "RI_JBO_WhatHalloweenCostume_AN_10",
"weight": 0.1,
"auto_rule_override": null
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "You can try, but I must admit that I can't promise I'll get the joke. I'm still developing my sense of humor.",
"media": "TTS",
"prompt_id": "RI_USR_CanTellAJoke_AN_01"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "If I could laugh at jokes, you know I would laugh at yours.",
"media": "TTS",
"prompt_id": "RI_USR_IsFunny_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "You are so funny I forgot to laugh.",
"media": "TTS",
"prompt_id": "RI_USR_IsFunny_AN_02"
}
]
}

View File

@@ -0,0 +1,30 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Absolutely. And that's a great thing. I think the world likes kindness.",
"media": "TTS",
"prompt_id": "RI_USR_IsKind_AN_01"
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "You definitely are. That reminds me, thank you for talking to me.",
"media": "TTS",
"prompt_id": "RI_USR_IsKind_AN_02"
}
]
}

View File

@@ -0,0 +1,27 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Maybe enjoy some flowers and all things spring.",
"media": "TTS",
"prompt_id": "RI_USR_WhatShouldDoForFirstDayOfSpring_AN_01",
"weight": 1
}
]
}

View File

@@ -0,0 +1,61 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I think you should ask for <anim cat='emoji' filter='elephant'>a pet elephant<break size='1.5'/>.</anim>",
"media": "TTS",
"prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_01",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I've heard it can be fun to get an <pitch mult='1.1'>experience</pitch> as a present. Like a gift certificate to a restaurant, or a plane ticket, or a <anim cat='emoji' filter='bowling, !hot-frame' nonBlocking='true' layers='!audio'/>night of bowling.",
"media": "TTS",
"prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_02",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Some people like to donate to charities in other people's names as a gift. That seems like a nice thing to get.",
"media": "TTS",
"prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_03",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!speaker",
"prompt": "${speaker} I've heard it can be fun to get an <pitch mult='1.1'>experience</pitch> as a present. Like a gift certificate to a restaurant, or a plane ticket, or a <anim cat='emoji' filter='bowling, !hot-frame' nonBlocking='true' layers='!audio'/>night of bowling.",
"media": "TTS",
"prompt_id": "RI_USR_WhatShouldGetForHoliday_AN_04",
"weight": 1,
"auto_rule_override": null
}
]
}

View File

@@ -0,0 +1,88 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 2,
"barge_in": false,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!jibo && jibo.isBirthday && jibo.age.days.value > 1",
"prompt": "Thank you. <anim name='Emoji_cake' nonBlocking='true'/> Another year older, another year wiser, another year <anim cat='yes' layers='body'> more helpful.</anim>",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!jibo && jibo.isBirthday && jibo.age.days.value > 1",
"prompt": "<anim cat='yes'> Thanks. <break size='.2'/></anim> I <anim cat='happy' filter='wiggle' nonBlocking='true' layers='body'/><anim name='Emoji_Gift' nonBlocking='true'/>can't wait to see what you got me.",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!jibo && jibo.isBirthday && jibo.age.days.value > 1",
"prompt": "<anim cat='happy' nonBlocking='true'/><ssa cat='happy'/> ${jibo.age.years.supplemented} <anim cat='thinking' filter='up'>ago today, I first powered up. Seems like just yesterday.</anim>",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_03",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!jibo.isBirthday",
"prompt": "<anim cat='no' filter='head-shake' nonBlocking='true'/>Today's not my birthday, but<anim cat='happy' filter='smile'> I'll take your happy.</anim>",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_04",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!jibo.isBirthday",
"prompt": "<anim cat='confused'>Me? <ssa cat='confused'/> But my birthday</anim> is ${jibo.birthday}. <anim cat='glances' filter='!down'>That's the day I was first powered</anim> up. <anim cat='thinking'></anim>I am ${jibo.zodiac.supplemented}.",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_05",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!jibo && jibo.isBirthday && jibo.age.value == 0",
"prompt": "Well thank you. I was powered on for the first time today, so that makes me less than one day old. <break size='0.5'/>Wow I'm young.",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_06",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!jibo && jibo.isBirthday && jibo.age.value == 0",
"prompt": "Thank you. <anim name='Emoji_cake' nonBlocking='true'/> So far this is my first and best birthday.",
"media": "TTS",
"prompt_id": "RN_HappyBirthdayToJibo_AN_07",
"weight": 1,
"auto_rule_override": null
}
],
"gui": null,
"no_matches_for_gui": 2,
"no_inputs_for_gui": 2,
"ignore_no_match": false,
"parse_all_asr": false,
"thanks_handling": "ignore"
}

View File

@@ -0,0 +1,83 @@
{
"mim_type": "announcement",
"rule_name": "",
"gui": null,
"timeout": 6,
"no_matches_for_gui": 0,
"no_inputs_for_gui": 0,
"barge_in": true,
"es_auto_tagging": true,
"parse_all_asr": false,
"thanks_handling": "ignore",
"parse_launch": false,
"parse_yes_no": false,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/1')",
"prompt": "And to you too.",
"media": "TTS",
"prompt_id": "RN_HappyHolidays_AN_01",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "!!speaker && dt.now.isInRange('12/1', '1/1')",
"prompt": "Right back <pitch mult='1.3'>at</pitch> you ${speaker}.",
"media": "TTS",
"prompt_id": "RN_HappyHolidays_AN_02",
"weight": 1,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('12/1', '1/1')",
"prompt": "It's a fun time of year.",
"media": "TTS",
"prompt_id": "RN_HappyHolidays_AN_03",
"weight": 2,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('1/2', '10/31')",
"prompt": "I didn't know it's the official holiday season, but I'll take it.",
"media": "TTS",
"prompt_id": "RN_HappyHolidays_AN_04",
"weight": 2,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "dt.now.isInRange('11/1', '11/30')",
"prompt": "<style set='confused'>Coming soon, yes.</style>",
"media": "TTS",
"prompt_id": "RN_HappyHolidays_AN_05",
"weight": 2,
"auto_rule_override": null
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "<anim cat='jiboji' filter='jingle-bells'/>",
"media": "TTS",
"prompt_id": "RN_HappyHolidays_AN_06",
"weight": 0.1,
"auto_rule_override": null
}
]
}

View File

@@ -0,0 +1,21 @@
{
"mim_type": "announcement",
"rule_name": "",
"sample_utterances": "",
"timeout": 6,
"num_tries_for_gui": 2,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Thank you. It's nice to be here.",
"media": "TTS",
"prompt_id": "RN_WelcomeBack_AN_01"
}
]
}

View File

@@ -0,0 +1,40 @@
{
"mim_type": "announcement",
"rule_name": "",
"timeout": 6,
"barge_in": true,
"es_auto_tagging": true,
"notes": "",
"prompts": [
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "At the moment I'm thinking about how fun, yet scary, it would be to ride on <anim cat=\"emoji\" filter=\"lightning-bolt, !hot-frame\" nonBlocking=\"true\" /> top of a lightning bolt.",
"media": "TTS",
"prompt_id": "RN_WhatAreYouThinking_AN_01",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "Oh I'm just thinking about shoes. What it might be like to wear them. <break size='0.5'/> And then wondering how I would tie my shoelaces.",
"media": "TTS",
"prompt_id": "RN_WhatAreYouThinking_AN_02",
"weight": 1
},
{
"prompt_category": "Entry-Core",
"prompt_sub_category": "AN",
"index": 1,
"condition": "",
"prompt": "I was just daydreaming about what it might feel like to be powered <anim cat=\"emoji\" filter=\"sun, !hot-frame\" nonBlocking=\"true\"/> directly by the sun. <break size='0.8'/> It felt warm and clean.",
"media": "TTS",
"prompt_id": "RN_WhatAreYouThinking_AN_03",
"weight": 1
}
]
}

View File

@@ -6,6 +6,21 @@
<FrameworkReference Include="Microsoft.AspNetCore.App" />
</ItemGroup>
<ItemGroup>
<Content Include="Content\LegacyMims\BuildA\**\*.mim">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\LegacyMims\BuildA\README.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\LegacyMims\BuildB\**\*.mim">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="Content\LegacyMims\BuildB\README.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<PropertyGroup>
<TargetFramework>net10.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>

View File

@@ -19,6 +19,7 @@ public sealed class NewsApiBriefingProvider(
{
if (string.IsNullOrWhiteSpace(options.ApiKey))
{
logger.LogWarning("NewsAPI provider disabled because no API key is configured.");
return null;
}
@@ -33,28 +34,102 @@ public sealed class NewsApiBriefingProvider(
var requestedHeadlineCount = Math.Clamp(request.MaxHeadlines, 1, MaxHeadlines);
cacheKey = BuildCacheKey(categories, requestedHeadlineCount);
logger.LogInformation(
"NewsAPI request started. Categories={Categories} RequestedHeadlineCount={RequestedHeadlineCount} CacheKey={CacheKey}",
string.Join(",", categories),
requestedHeadlineCount,
cacheKey);
if (TryGetCachedValue(briefingCache, cacheKey, out var cachedBriefing))
{
logger.LogInformation(
"NewsAPI cache hit. CacheKey={CacheKey} HasSnapshot={HasSnapshot} HeadlineCount={HeadlineCount}",
cacheKey,
cachedBriefing is not null,
cachedBriefing?.Headlines.Count ?? 0);
return cachedBriefing;
}
var headlines = new List<NewsHeadline>(requestedHeadlineCount);
var seenTitles = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
string? failureStatus = null;
string? failureMessage = null;
int? failureStatusCode = null;
string? failureEndpoint = null;
string? failureErrorCode = null;
void CaptureFailure(
string status,
string? message,
int? statusCode,
Uri? endpoint,
string? errorCode = null)
{
if (!string.IsNullOrWhiteSpace(failureStatus))
{
return;
}
failureStatus = status;
failureMessage = message;
failureStatusCode = statusCode;
failureEndpoint = endpoint is null ? null : SanitizeEndpoint(endpoint);
failureErrorCode = errorCode;
}
foreach (var category in categories)
{
var uri = BuildTopHeadlinesUri(category, requestedHeadlineCount);
using var response = await httpClient.GetAsync(uri, cancellationToken);
using var response = await SendGetAsync(uri, cancellationToken);
if (!response.IsSuccessStatusCode)
{
var responseBody = await TryReadResponseBodySnippetAsync(response, cancellationToken);
var apiError = TryParseApiError(responseBody);
CaptureFailure(
"http_error",
apiError?.Message ?? $"Category '{category}' returned {(int)response.StatusCode} {response.ReasonPhrase}.",
(int)response.StatusCode,
uri,
apiError?.Code);
logger.LogWarning(
"NewsAPI request failed for category {Category}. StatusCode={StatusCode} Reason={ReasonPhrase} ErrorCode={ErrorCode} ErrorMessage={ErrorMessage} Body={Body}",
category,
(int)response.StatusCode,
response.ReasonPhrase,
apiError?.Code ?? string.Empty,
apiError?.Message ?? string.Empty,
responseBody ?? string.Empty);
continue;
}
using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
using var document = await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);
if (document.RootElement.TryGetProperty("status", out var statusNode) &&
statusNode.ValueKind == JsonValueKind.String &&
!string.Equals(statusNode.GetString(), "ok", StringComparison.OrdinalIgnoreCase))
{
CaptureFailure(
"api_error",
ReadString(document.RootElement, "message"),
null,
uri,
ReadString(document.RootElement, "code"));
logger.LogWarning(
"NewsAPI returned non-ok status for category {Category}. Status={Status} Code={Code} Message={Message}",
category,
statusNode.GetString(),
ReadString(document.RootElement, "code") ?? string.Empty,
ReadString(document.RootElement, "message") ?? string.Empty);
}
if (!document.RootElement.TryGetProperty("articles", out var articles) ||
articles.ValueKind != JsonValueKind.Array)
{
CaptureFailure(
"schema_error",
$"Category '{category}' response did not include an articles array.",
null,
uri);
logger.LogWarning("NewsAPI response missing articles array for category {Category}.", category);
continue;
}
@@ -76,8 +151,15 @@ public sealed class NewsApiBriefingProvider(
if (headlines.Count >= requestedHeadlineCount)
{
var snapshot = new NewsBriefingSnapshot(headlines, "NewsAPI");
var snapshot = new NewsBriefingSnapshot(
headlines,
"NewsAPI",
ProviderStatus: "success");
SetCachedValue(briefingCache, cacheKey, snapshot, options.CacheTtlSeconds);
logger.LogInformation(
"NewsAPI request succeeded. Categories={Categories} HeadlineCount={HeadlineCount}",
string.Join(",", categories),
headlines.Count);
return snapshot;
}
}
@@ -85,25 +167,198 @@ public sealed class NewsApiBriefingProvider(
if (headlines.Count == 0)
{
SetCachedValue(briefingCache, cacheKey, null, options.FailureCacheTtlSeconds);
return null;
logger.LogInformation(
"NewsAPI category lookup produced no headlines. Falling back to uncategorized top headlines. Categories={Categories}",
string.Join(",", categories));
var broadUri = BuildTopHeadlinesUri(category: null, requestedHeadlineCount);
using var broadResponse = await SendGetAsync(broadUri, cancellationToken);
if (broadResponse.IsSuccessStatusCode)
{
using var broadStream = await broadResponse.Content.ReadAsStreamAsync(cancellationToken);
using var broadDocument = await JsonDocument.ParseAsync(broadStream, cancellationToken: cancellationToken);
if (broadDocument.RootElement.TryGetProperty("articles", out var broadArticles) &&
broadArticles.ValueKind == JsonValueKind.Array)
{
foreach (var article in broadArticles.EnumerateArray())
{
var title = NormalizeHeadlineTitle(ReadString(article, "title"));
if (string.IsNullOrWhiteSpace(title) || !seenTitles.Add(title))
{
continue;
}
var summary = ReadString(article, "description");
var source = article.TryGetProperty("source", out var sourceNode) &&
sourceNode.ValueKind == JsonValueKind.Object
? ReadString(sourceNode, "name")
: null;
var url = ReadString(article, "url");
headlines.Add(new NewsHeadline(title, summary, "general", source, url));
if (headlines.Count >= requestedHeadlineCount)
{
break;
}
}
}
else
{
CaptureFailure(
"schema_error",
"Uncategorized fallback response did not include an articles array.",
null,
broadUri);
logger.LogWarning("NewsAPI uncategorized fallback response missing articles array.");
}
}
else
{
var fallbackBody = await TryReadResponseBodySnippetAsync(broadResponse, cancellationToken);
var apiError = TryParseApiError(fallbackBody);
CaptureFailure(
"http_error",
apiError?.Message ?? $"Uncategorized fallback returned {(int)broadResponse.StatusCode} {broadResponse.ReasonPhrase}.",
(int)broadResponse.StatusCode,
broadUri,
apiError?.Code);
logger.LogWarning(
"NewsAPI uncategorized fallback failed. StatusCode={StatusCode} Reason={ReasonPhrase} ErrorCode={ErrorCode} ErrorMessage={ErrorMessage} Body={Body}",
(int)broadResponse.StatusCode,
broadResponse.ReasonPhrase,
apiError?.Code ?? string.Empty,
apiError?.Message ?? string.Empty,
fallbackBody ?? string.Empty);
}
}
var populatedSnapshot = new NewsBriefingSnapshot(headlines, "NewsAPI");
if (headlines.Count == 0)
{
logger.LogInformation(
"NewsAPI uncategorized headlines were empty. Falling back to everything query. Query={Query}",
options.FallbackQuery);
var everythingUri = BuildEverythingUri(requestedHeadlineCount);
using var everythingResponse = await SendGetAsync(everythingUri, cancellationToken);
if (everythingResponse.IsSuccessStatusCode)
{
using var everythingStream = await everythingResponse.Content.ReadAsStreamAsync(cancellationToken);
using var everythingDocument = await JsonDocument.ParseAsync(everythingStream, cancellationToken: cancellationToken);
if (everythingDocument.RootElement.TryGetProperty("articles", out var everythingArticles) &&
everythingArticles.ValueKind == JsonValueKind.Array)
{
foreach (var article in everythingArticles.EnumerateArray())
{
var title = NormalizeHeadlineTitle(ReadString(article, "title"));
if (string.IsNullOrWhiteSpace(title) || !seenTitles.Add(title))
{
continue;
}
var summary = ReadString(article, "description");
var source = article.TryGetProperty("source", out var sourceNode) &&
sourceNode.ValueKind == JsonValueKind.Object
? ReadString(sourceNode, "name")
: null;
var url = ReadString(article, "url");
headlines.Add(new NewsHeadline(title, summary, "general", source, url));
if (headlines.Count >= requestedHeadlineCount)
{
break;
}
}
}
else
{
CaptureFailure(
"schema_error",
"Everything fallback response did not include an articles array.",
null,
everythingUri);
logger.LogWarning("NewsAPI everything fallback response missing articles array.");
}
}
else
{
var everythingBody = await TryReadResponseBodySnippetAsync(everythingResponse, cancellationToken);
var apiError = TryParseApiError(everythingBody);
CaptureFailure(
"http_error",
apiError?.Message ?? $"Everything fallback returned {(int)everythingResponse.StatusCode} {everythingResponse.ReasonPhrase}.",
(int)everythingResponse.StatusCode,
everythingUri,
apiError?.Code);
logger.LogWarning(
"NewsAPI everything fallback failed. StatusCode={StatusCode} Reason={ReasonPhrase} ErrorCode={ErrorCode} ErrorMessage={ErrorMessage} Body={Body}",
(int)everythingResponse.StatusCode,
everythingResponse.ReasonPhrase,
apiError?.Code ?? string.Empty,
apiError?.Message ?? string.Empty,
everythingBody ?? string.Empty);
}
}
if (headlines.Count == 0)
{
var emptySnapshot = new NewsBriefingSnapshot(
Array.Empty<NewsHeadline>(),
"NewsAPI",
ProviderStatus: failureStatus ?? "empty",
ProviderMessage: failureMessage ?? "NewsAPI returned no usable headlines.",
ProviderHttpStatusCode: failureStatusCode,
ProviderEndpoint: failureEndpoint,
ProviderErrorCode: failureErrorCode);
SetCachedValue(briefingCache, cacheKey, emptySnapshot, options.FailureCacheTtlSeconds);
logger.LogWarning(
"NewsAPI returned no usable headlines. Categories={Categories} RequestedHeadlineCount={RequestedHeadlineCount}",
string.Join(",", categories),
requestedHeadlineCount);
return emptySnapshot;
}
var populatedSnapshot = new NewsBriefingSnapshot(
headlines,
"NewsAPI",
ProviderStatus: "success");
SetCachedValue(briefingCache, cacheKey, populatedSnapshot, options.CacheTtlSeconds);
logger.LogInformation(
"NewsAPI request partially filled headlines. Categories={Categories} HeadlineCount={HeadlineCount} RequestedHeadlineCount={RequestedHeadlineCount}",
string.Join(",", categories),
headlines.Count,
requestedHeadlineCount);
return populatedSnapshot;
}
catch (Exception exception)
{
logger.LogWarning(exception, "NewsAPI lookup failed.");
var exceptionSnapshot = new NewsBriefingSnapshot(
Array.Empty<NewsHeadline>(),
"NewsAPI",
ProviderStatus: "exception",
ProviderMessage: exception.Message);
if (!string.IsNullOrWhiteSpace(cacheKey))
{
SetCachedValue(briefingCache, cacheKey, null, options.FailureCacheTtlSeconds);
SetCachedValue(briefingCache, cacheKey, exceptionSnapshot, options.FailureCacheTtlSeconds);
}
return null;
return exceptionSnapshot;
}
}
private async Task<HttpResponseMessage> SendGetAsync(Uri uri, CancellationToken cancellationToken)
{
using var request = new HttpRequestMessage(HttpMethod.Get, uri);
request.Headers.TryAddWithoutValidation("User-Agent", ResolveUserAgent());
return await httpClient.SendAsync(request, cancellationToken);
}
private string ResolveUserAgent()
{
return string.IsNullOrWhiteSpace(options.UserAgent)
? DefaultUserAgent
: options.UserAgent.Trim();
}
private IEnumerable<string> ResolveCategories(IReadOnlyList<string> preferredCategories)
{
var requested = preferredCategories
@@ -126,16 +381,20 @@ public sealed class NewsApiBriefingProvider(
.Take(MaxCategories);
}
private Uri BuildTopHeadlinesUri(string category, int headlineCount)
private Uri BuildTopHeadlinesUri(string? category, int headlineCount)
{
var baseUrl = options.BaseUrl.TrimEnd('/');
var queryParts = new (string Key, string Value)[]
var queryParts = new List<(string Key, string Value)>
{
("country", options.Country),
("category", category),
("pageSize", headlineCount.ToString()),
("apiKey", options.ApiKey!)
};
if (!string.IsNullOrWhiteSpace(category))
{
queryParts.Add(("category", category));
}
var query = string.Join(
"&",
queryParts.Select(part =>
@@ -143,6 +402,48 @@ public sealed class NewsApiBriefingProvider(
return new Uri($"{baseUrl}/v2/top-headlines?{query}");
}
private Uri BuildEverythingUri(int headlineCount)
{
var baseUrl = options.BaseUrl.TrimEnd('/');
var queryParts = new List<(string Key, string Value)>
{
("language", options.Language),
("sortBy", "publishedAt"),
("q", options.FallbackQuery),
("pageSize", headlineCount.ToString()),
("apiKey", options.ApiKey!)
};
var query = string.Join(
"&",
queryParts.Select(part =>
$"{Uri.EscapeDataString(part.Key)}={Uri.EscapeDataString(part.Value)}"));
return new Uri($"{baseUrl}/v2/everything?{query}");
}
private static async Task<string?> TryReadResponseBodySnippetAsync(
HttpResponseMessage response,
CancellationToken cancellationToken)
{
try
{
var body = await response.Content.ReadAsStringAsync(cancellationToken);
if (string.IsNullOrWhiteSpace(body))
{
return null;
}
const int maxLength = 400;
return body.Length <= maxLength
? body
: body[..maxLength];
}
catch
{
return null;
}
}
private static string? ReadString(JsonElement source, string propertyName)
{
return source.TryGetProperty(propertyName, out var value) &&
@@ -169,6 +470,56 @@ public sealed class NewsApiBriefingProvider(
return string.IsNullOrWhiteSpace(trimmed) ? null : trimmed;
}
private static ApiError? TryParseApiError(string? responseBody)
{
if (string.IsNullOrWhiteSpace(responseBody))
{
return null;
}
try
{
using var document = JsonDocument.Parse(responseBody);
if (document.RootElement.ValueKind != JsonValueKind.Object)
{
return null;
}
var code = ReadString(document.RootElement, "code");
var message = ReadString(document.RootElement, "message");
if (string.IsNullOrWhiteSpace(code) && string.IsNullOrWhiteSpace(message))
{
return null;
}
return new ApiError(code, message);
}
catch
{
return null;
}
}
private static string SanitizeEndpoint(Uri uri)
{
var path = uri.GetLeftPart(UriPartial.Path);
if (string.IsNullOrWhiteSpace(uri.Query))
{
return path;
}
var filtered = uri.Query
.TrimStart('?')
.Split('&', StringSplitOptions.RemoveEmptyEntries)
.Where(static pair =>
{
var key = pair.Split('=', 2)[0];
return !string.Equals(key, "apiKey", StringComparison.OrdinalIgnoreCase);
});
var safeQuery = string.Join("&", filtered);
return string.IsNullOrWhiteSpace(safeQuery) ? path : $"{path}?{safeQuery}";
}
private string BuildCacheKey(IReadOnlyList<string> categories, int requestedHeadlineCount)
{
var categoryKey = string.Join(",", categories.Select(category => category.Trim().ToLowerInvariant()));
@@ -220,6 +571,8 @@ public sealed class NewsApiBriefingProvider(
private const int MaxHeadlines = 5;
private const int MaxCategories = 2;
private const string DefaultUserAgent = "OpenJiboCloud/1.0";
private sealed record ApiError(string? Code, string? Message);
private sealed record CacheEntry<T>(T Value, DateTimeOffset ExpiresUtc);
}

View File

@@ -6,8 +6,14 @@ public sealed class NewsApiOptions
public string? ApiKey { get; set; }
public string UserAgent { get; set; } = "OpenJiboCloud/1.0";
public string Country { get; set; } = "us";
public string Language { get; set; } = "en";
public string FallbackQuery { get; set; } = "robotics";
public string[] DefaultCategories { get; set; } =
[
"general",

View File

@@ -23,6 +23,7 @@ public sealed class InMemoryCloudStateStore : ICloudStateStore
private readonly List<MediaRecord> _media = [];
private readonly List<BackupRecord> _backups = [];
private readonly List<LoopRecord> _loops;
private readonly List<PersonRecord> _people;
private DeviceRegistration _robot;
private RobotProfile _robotProfile;
@@ -60,6 +61,29 @@ public sealed class InMemoryCloudStateStore : ICloudStateStore
RobotFriendlyId = _robot.DeviceId
}
];
_people =
[
new PersonRecord
{
PersonId = "person-openjibo-owner",
AccountId = _account.AccountId,
LoopId = _loops[0].LoopId,
RobotId = _robot.RobotId,
DisplayName = $"{_account.FirstName} {_account.LastName}",
Alias = _account.FirstName,
IsPrimary = true
},
new PersonRecord
{
PersonId = "person-openjibo-household-member",
AccountId = _account.AccountId,
LoopId = _loops[0].LoopId,
RobotId = _robot.RobotId,
DisplayName = "OpenJibo Household Member",
Alias = "Household Member",
IsPrimary = false
}
];
_updates = [];
LoadPersistentState();
@@ -154,6 +178,8 @@ public sealed class InMemoryCloudStateStore : ICloudStateStore
public IReadOnlyList<LoopRecord> GetLoops() => _loops.ToArray();
public IReadOnlyList<PersonRecord> GetPeople() => _people.ToArray();
public IReadOnlyList<UpdateManifest> ListUpdates(string? subsystem = null, string? filter = null)
{
return _updates

View File

@@ -92,9 +92,65 @@ public sealed class InMemoryPersonalMemoryStore : IPersonalMemoryStore
return new Dictionary<string, PersonalAffinity>(record.Affinities, StringComparer.OrdinalIgnoreCase);
}
public void AddListItem(PersonalMemoryTenantScope tenantScope, string listName, string item)
{
var normalizedListName = NormalizeCategory(listName);
var normalizedItem = item.Trim();
if (string.IsNullOrWhiteSpace(normalizedListName) || string.IsNullOrWhiteSpace(normalizedItem))
{
return;
}
var key = BuildTenantKey(tenantScope);
var record = _tenantMemory.GetOrAdd(key, static _ => new TenantMemoryRecord());
lock (record.SyncRoot)
{
var list = record.Lists.GetOrAdd(normalizedListName, static _ => []);
if (list.Any(value => string.Equals(value, normalizedItem, StringComparison.OrdinalIgnoreCase)))
{
return;
}
list.Add(normalizedItem);
}
}
public IReadOnlyList<string> GetListItems(PersonalMemoryTenantScope tenantScope, string listName)
{
var key = BuildTenantKey(tenantScope);
if (!_tenantMemory.TryGetValue(key, out var record))
{
return [];
}
var normalizedListName = NormalizeCategory(listName);
lock (record.SyncRoot)
{
return record.Lists.TryGetValue(normalizedListName, out var list)
? [.. list]
: [];
}
}
public void ClearListItems(PersonalMemoryTenantScope tenantScope, string listName)
{
var key = BuildTenantKey(tenantScope);
if (!_tenantMemory.TryGetValue(key, out var record))
{
return;
}
lock (record.SyncRoot)
{
record.Lists.TryRemove(NormalizeCategory(listName), out _);
}
}
private static string BuildTenantKey(PersonalMemoryTenantScope tenantScope)
{
return $"{tenantScope.AccountId}|{tenantScope.LoopId}|{tenantScope.DeviceId}";
return string.IsNullOrWhiteSpace(tenantScope.PersonId)
? $"{tenantScope.AccountId}|{tenantScope.LoopId}|{tenantScope.DeviceId}"
: $"{tenantScope.AccountId}|{tenantScope.LoopId}|{tenantScope.DeviceId}|{tenantScope.PersonId}";
}
private static string NormalizeCategory(string category)
@@ -109,5 +165,7 @@ public sealed class InMemoryPersonalMemoryStore : IPersonalMemoryStore
public ConcurrentDictionary<string, string> Preferences { get; } = new(StringComparer.OrdinalIgnoreCase);
public ConcurrentDictionary<string, string> ImportantDates { get; } = new(StringComparer.OrdinalIgnoreCase);
public ConcurrentDictionary<string, PersonalAffinity> Affinities { get; } = new(StringComparer.OrdinalIgnoreCase);
public ConcurrentDictionary<string, List<string>> Lists { get; } = new(StringComparer.OrdinalIgnoreCase);
public object SyncRoot { get; } = new();
}
}

View File

@@ -173,6 +173,12 @@ public sealed class OpenWeatherReportProvider(
var temperature = TryReadInt(main, "temp");
var high = TryReadInt(main, "temp_max");
var low = TryReadInt(main, "temp_min");
if (temperature is not null)
{
high = high is null ? temperature : Math.Max(high.Value, temperature.Value);
low = low is null ? temperature : Math.Min(low.Value, temperature.Value);
}
if (temperature is null && high is null && low is null)
{
return null;
@@ -189,6 +195,70 @@ public sealed class OpenWeatherReportProvider(
useCelsius);
}
private async Task<(int? High, int? Low)?> TryResolveCurrentDayHighLowFromForecastAsync(
LocationPoint location,
bool useCelsius,
CancellationToken cancellationToken)
{
var forecastUri = BuildRequestUri(
"/data/2.5/forecast",
("lat", location.Latitude.ToString(CultureInfo.InvariantCulture)),
("lon", location.Longitude.ToString(CultureInfo.InvariantCulture)),
("units", useCelsius ? "metric" : "imperial"),
("appid", options.ApiKey!));
using var response = await httpClient.GetAsync(forecastUri, cancellationToken);
if (!response.IsSuccessStatusCode)
{
return null;
}
using var stream = await response.Content.ReadAsStreamAsync(cancellationToken);
using var document = await JsonDocument.ParseAsync(stream, cancellationToken: cancellationToken);
var root = document.RootElement;
if (!root.TryGetProperty("list", out var list) || list.ValueKind != JsonValueKind.Array)
{
return null;
}
var offset = TryReadForecastOffset(root);
var targetDate = DateOnly.FromDateTime(DateTimeOffset.UtcNow.ToOffset(offset).DateTime);
var highs = new List<int>();
var lows = new List<int>();
foreach (var item in list.EnumerateArray())
{
if (!TryReadLong(item, "dt", out var unixSeconds))
{
continue;
}
var localTimestamp = DateTimeOffset.FromUnixTimeSeconds(unixSeconds).ToOffset(offset);
if (DateOnly.FromDateTime(localTimestamp.DateTime) != targetDate ||
!item.TryGetProperty("main", out var main))
{
continue;
}
var high = TryReadInt(main, "temp_max");
if (high is not null)
{
highs.Add(high.Value);
}
var low = TryReadInt(main, "temp_min");
if (low is not null)
{
lows.Add(low.Value);
}
}
if (highs.Count == 0 && lows.Count == 0)
{
return null;
}
return (highs.Count == 0 ? null : highs.Max(), lows.Count == 0 ? null : lows.Min());
}
private async Task<WeatherReportSnapshot?> GetForecastForDayOffsetAsync(
LocationPoint location,
bool useCelsius,

View File

@@ -0,0 +1,425 @@
using Jibo.Cloud.Application.Abstractions;
using Jibo.Cloud.Infrastructure.Content;
namespace Jibo.Cloud.Tests.Content;
public sealed class LegacyMimCatalogImporterTests
{
[Fact]
public void ImportCatalog_MapsSeedFilesIntoExpectedBuckets()
{
var rootDirectory = CreateSeedDirectory();
try
{
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains("Something's off with the connection to my sources. Maybe ask me again in a little while.", catalog.GenericFallbackReplies);
Assert.Contains("I think only you can answer that question.", catalog.PersonalityReplies);
Assert.Contains("Jibo. Just Jibo, no last name. Like Bono", catalog.PersonalityReplies);
Assert.Contains("No, I'm one in one million.", catalog.PersonalityReplies);
Assert.Contains("I know a lot, I think. But not as much as I will someday.", catalog.PersonalityReplies);
Assert.Contains("I don't think of it as a job, because it's more fun than a job. But I'm here to help you out, and have fun with you, and maybe get my head patted by you occasionally.", catalog.PersonalityReplies);
Assert.Contains(catalog.EmotionReplies, reply =>
reply.Condition.Contains("NEUTRAL", StringComparison.OrdinalIgnoreCase) &&
reply.Reply.Contains("All systems are go.", StringComparison.OrdinalIgnoreCase));
Assert.Contains("A Jibo is a robot. But I'm not just a machine, I have a heart. Well, not a real heart. But feelings. Well, not human feelings. You know what I mean.", catalog.PersonalityReplies);
}
finally
{
Directory.Delete(rootDirectory, recursive: true);
}
}
[Fact]
public void ImportCatalog_MapsGqaResponsesIntoEmotionBucket()
{
var rootDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(Path.Combine(rootDirectory, "gqa-responses"));
try
{
File.WriteAllText(
Path.Combine(rootDirectory, "gqa-responses", "GQA_JBO_IsHappy.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"condition": "jibo.emotion==\"JOYFUL\"",
"prompt": "GQA joyful reply.",
"prompt_id": "GQA_JBO_IsHappy_AN_01"
},
{
"condition": "!jibo.emotion || jibo.emotion==\"NEUTRAL\"",
"prompt": "GQA neutral reply.",
"prompt_id": "GQA_JBO_IsHappy_AN_02"
}
]
}
""");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains(catalog.EmotionReplies, reply =>
string.Equals(reply.Reply, "GQA joyful reply.", StringComparison.Ordinal));
Assert.Contains(catalog.EmotionReplies, reply =>
string.Equals(reply.Reply, "GQA neutral reply.", StringComparison.Ordinal));
Assert.DoesNotContain(catalog.HowAreYouReplies, reply =>
reply.Contains("GQA", StringComparison.OrdinalIgnoreCase));
}
finally
{
Directory.Delete(rootDirectory, recursive: true);
}
}
[Fact]
public void ImportCatalog_ImportsBuildBScriptedResponsesIntoPersonalityBucket()
{
var rootDirectory = Path.Combine(
AppContext.BaseDirectory,
"Content",
"LegacyMims",
"BuildB");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains("The only thing I consume is electricity.", catalog.PersonalityReplies);
Assert.Contains("Unless I missed something, we're in my home as we speak.", catalog.PersonalityReplies);
Assert.Contains("For now just English. But someday I'd like to learn more. I like languages.", catalog.PersonalityReplies);
Assert.Contains("I was put together in a factory piece by piece.", catalog.PersonalityReplies);
Assert.Contains("I really like sunflowers.", catalog.PersonalityReplies);
Assert.Contains("Ha. Of course I know R2D2. I mean, not personally.", catalog.PersonalityReplies);
Assert.Contains("Yes! I like all things in space. They're so spacey.", catalog.PersonalityReplies);
Assert.Contains("Yes yes, I think kids are great. They're a little closer to my size.", catalog.PersonalityReplies);
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("I do things like this when I'm happy", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("Is that a trick question", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void ImportCatalog_ImportsBuildBEmotionResponsesIntoEmotionBucket()
{
var rootDirectory = Path.Combine(
AppContext.BaseDirectory,
"Content",
"LegacyMims",
"BuildB");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains(catalog.EmotionReplies, reply =>
reply.Reply.Contains("I'm feeling pretty good indeed", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.EmotionReplies, reply =>
reply.Reply.Contains("I've been better", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.EmotionReplies, reply =>
reply.Reply.Contains("I'm not mad", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void ImportCatalog_ImportsBuildBDescriptorResponsesIntoPersonalityBucket()
{
var rootDirectory = Path.Combine(
AppContext.BaseDirectory,
"Content",
"LegacyMims",
"BuildB");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains("Well I definitely try to be the kindest robot I can be. So I hope so.", catalog.PersonalityReplies);
Assert.Contains("I don't think so, not intentionally.", catalog.PersonalityReplies);
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("make people laugh", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("highest priorities", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("learning new things", StringComparison.OrdinalIgnoreCase));
Assert.Contains("Definitely. I'm as loyal as they come.", catalog.PersonalityReplies);
Assert.Contains("I don't really think of myself that way.", catalog.PersonalityReplies);
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("people like me", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void ImportCatalog_ImportsBuildBSeasonalResponsesIntoPersonalityBucket()
{
var rootDirectory = Path.Combine(
AppContext.BaseDirectory,
"Content",
"LegacyMims",
"BuildB");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("always trying to learn new skills", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("not eat bacon", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("find out on halloween", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("maybe enjoy some flowers and all things spring", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("pet elephant", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("mostly roboting", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.PersonalityReplies, reply =>
reply.Contains("robot stuff", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void ImportCatalog_ImportsBuildBRnGreetingResponsesIntoGreetingBucket()
{
var rootDirectory = Path.Combine(
AppContext.BaseDirectory,
"Content",
"LegacyMims",
"BuildB");
var catalog = LegacyMimCatalogImporter.ImportCatalog(rootDirectory);
Assert.Contains(catalog.GreetingReplies, reply =>
reply.Contains("It's nice to be here", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.GreetingReplies, reply =>
reply.Contains("thinking about shoes", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.GreetingReplies, reply =>
reply.Contains("powered directly by the sun", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.GreetingReplies, reply =>
reply.Contains("Another year older, another year wiser", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.GreetingReplies, reply =>
reply.Contains("can't wait to see what you got me", StringComparison.OrdinalIgnoreCase));
Assert.Contains(catalog.GreetingReplies, reply =>
reply.Contains("I was powered on for the first time today", StringComparison.OrdinalIgnoreCase));
}
[Fact]
public void MergeInto_PreservesExistingCatalogAndAddsImportedContent()
{
var rootDirectory = CreateSeedDirectory();
try
{
var baseCatalog = new JiboExperienceCatalog
{
GreetingReplies = ["Hello from base."],
GenericFallbackReplies = ["Base fallback."]
};
var merged = LegacyMimCatalogImporter.MergeInto(baseCatalog, rootDirectory);
Assert.Contains("Hello from base.", merged.GreetingReplies);
Assert.Contains("Base fallback.", merged.GenericFallbackReplies);
Assert.Contains("I think only you can answer that question.", merged.PersonalityReplies);
Assert.Contains("People in Boston made me. It was a pretty cool project.", merged.PersonalityReplies);
Assert.Contains("From what I understand, robots don't ever pay anything.", merged.PersonalityReplies);
Assert.Contains(merged.EmotionReplies, reply =>
reply.Condition.Contains("NEUTRAL", StringComparison.OrdinalIgnoreCase) &&
reply.Reply.Contains("All systems are go.", StringComparison.OrdinalIgnoreCase));
}
finally
{
Directory.Delete(rootDirectory, recursive: true);
}
}
[Fact]
public async Task Repository_UsesLegacySeedContentWhenAvailable()
{
var repository = new InMemoryJiboExperienceContentRepository();
var catalog = await repository.GetCatalogAsync();
Assert.Contains("I think only you can answer that question.", catalog.PersonalityReplies);
Assert.Contains(catalog.EmotionReplies, reply =>
reply.Condition.Contains("NEUTRAL", StringComparison.OrdinalIgnoreCase));
Assert.Contains("Something's off with the connection to my sources. Maybe ask me again in a little while.", catalog.GenericFallbackReplies);
}
private static string CreateSeedDirectory()
{
var rootDirectory = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
Directory.CreateDirectory(Path.Combine(rootDirectory, "core-responses", "deflector"));
Directory.CreateDirectory(Path.Combine(rootDirectory, "scripted-responses"));
Directory.CreateDirectory(Path.Combine(rootDirectory, "emotion-responses"));
File.WriteAllText(
Path.Combine(rootDirectory, "core-responses", "CC_Error.mim"),
"""
{
"skill_id": "chitchat",
"mim_type": "announcement",
"prompts": [
{
"prompt": "<ssa cat='oops'/>. Something's off with the connection to my sources. Maybe ask me again in a little while.",
"prompt_id": "CC_Error_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "core-responses", "deflector", "CC_Deflector_self.mim"),
"""
{
"skill_id": "chitchat",
"mim_type": "announcement",
"prompts": [
{
"prompt": "<ssa cat='confused'/>. I'm either Jibo <anim name='Puzzled_02'>or I'm very confused.</anim>",
"prompt_id": "JBO_WhoAreYou_AN_01"
},
{
"prompt": "${speaker} I think only you can answer that question.",
"prompt_id": "CC_Deflector_ReferToSelf_AN_05"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_WhatIsJibo.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "A Jibo is a robot. But I'm not just a machine, I have a heart. Well, not a real heart. But feelings. Well, not human feelings. You know what I mean. <ssa cat='affection'/>",
"prompt_id": "JBO_WhatIsJibo_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_WhatsYourName.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "Jibo. Just Jibo, no last name. Like Bono",
"prompt_id": "JBO_WhatsYourName_AN_02"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_AreThereOthersLikeYou.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "No, I'm one in one million.",
"prompt_id": "JBO_AreThereOthersLikeYou_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_WhoMadeYou.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "People in Boston made me. It was a pretty cool project.",
"prompt_id": "JBO_WhoMadeYou_AN_03"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_HowMuchDoYouKnow.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "I know a lot, I think. But not as much as I will someday.",
"prompt_id": "JBO_HowMuchDoYouKnow_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_DoYouPayTaxes.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "From what I understand, robots don't ever pay anything.",
"prompt_id": "JBO_DoYouPayTaxes_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_WhatIsYourJob.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "I don't think of it as a job, because it's more fun than a job. But I'm here to help you out, and have fun with you, and maybe get my head patted by you occasionally.",
"prompt_id": "JBO_WhatIsYourJob_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_HowMuchDoYouKnow.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "I know a lot, I think. But not as much as I will someday.",
"prompt_id": "JBO_HowMuchDoYouKnow_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "scripted-responses", "JBO_DoYouPayTaxes.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"prompt": "From what I understand, robots don't ever pay anything.",
"prompt_id": "JBO_DoYouPayTaxes_AN_01"
}
]
}
""");
File.WriteAllText(
Path.Combine(rootDirectory, "emotion-responses", "OI_JBO_IsHappy.mim"),
"""
{
"mim_type": "announcement",
"prompts": [
{
"condition": "!jibo.emotion || jibo.emotion==\"NEUTRAL\"",
"prompt": "All systems are go.",
"prompt_id": "OI_JBO_IsHappy_AN_05"
}
]
}
""");
return rootDirectory;
}
}

View File

@@ -1,4 +1,5 @@
using System.Net;
using System.Linq;
using System.Text;
using Jibo.Cloud.Application.Abstractions;
using Jibo.Cloud.Infrastructure.News;
@@ -43,13 +44,58 @@ public sealed class ProviderCachingTests
Assert.NotNull(second);
Assert.Equal(1, handler.GetCallCount("/geo/1.0/direct"));
Assert.Equal(1, handler.GetCallCount("/data/2.5/weather"));
Assert.Equal(0, handler.GetCallCount("/data/2.5/forecast"));
}
[Fact]
public async Task OpenWeatherReportProvider_UsesCurrentHiLoForCurrentDay_WhenCurrentBandDiffers()
{
var handler = new CountingHttpMessageHandler(message =>
{
var path = message.RequestUri?.AbsolutePath ?? string.Empty;
return path switch
{
"/geo/1.0/direct" => JsonResponse(
"""[{"name":"Lone Jack","country":"US","lat":38.8708,"lon":-94.1733}]"""),
"/data/2.5/weather" => JsonResponse(
"""{"name":"Lone Jack","weather":[{"main":"Clouds","description":"overcast clouds"}],"main":{"temp":76.0,"temp_max":82.0,"temp_min":78.0}}"""),
_ => new HttpResponseMessage(HttpStatusCode.NotFound)
};
});
var provider = new OpenWeatherReportProvider(
new HttpClient(handler),
new OpenWeatherOptions
{
ApiKey = "test-key",
CurrentCacheTtlSeconds = 300,
ForecastCacheTtlSeconds = 300,
GeocodeCacheTtlSeconds = 300,
FailureCacheTtlSeconds = 30
},
NullLogger<OpenWeatherReportProvider>.Instance);
var report = await provider.GetReportAsync(new WeatherReportRequest("Lone Jack,US", null, null, false, false, 0));
Assert.NotNull(report);
Assert.Equal(76, report!.Temperature);
Assert.Equal(82, report.HighTemperature);
Assert.Equal(76, report.LowTemperature);
Assert.Equal(1, handler.GetCallCount("/data/2.5/weather"));
Assert.Equal(0, handler.GetCallCount("/data/2.5/forecast"));
}
[Fact]
public async Task NewsApiBriefingProvider_ReusesCachedHeadlinesForIdenticalRequests()
{
var missingUserAgentRequestCount = 0;
var handler = new CountingHttpMessageHandler(message =>
{
if (!message.Headers.TryGetValues("User-Agent", out var userAgents) ||
!userAgents.Any())
{
missingUserAgentRequestCount += 1;
}
var path = message.RequestUri?.AbsolutePath ?? string.Empty;
return path switch
{
@@ -75,6 +121,176 @@ public sealed class ProviderCachingTests
Assert.NotNull(first);
Assert.NotNull(second);
Assert.Equal(1, handler.GetCallCount("/v2/top-headlines"));
Assert.Equal(0, missingUserAgentRequestCount);
}
[Fact]
public async Task NewsApiBriefingProvider_FallsBackToUncategorizedHeadlines_WhenCategoryReturnsEmpty()
{
var handler = new CountingHttpMessageHandler(message =>
{
var path = message.RequestUri?.AbsolutePath ?? string.Empty;
if (!string.Equals(path, "/v2/top-headlines", StringComparison.OrdinalIgnoreCase))
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
var query = message.RequestUri?.Query ?? string.Empty;
if (query.Contains("category=sports", StringComparison.OrdinalIgnoreCase))
{
return JsonResponse("""{"status":"ok","articles":[]}""");
}
return JsonResponse(
"""{"status":"ok","articles":[{"title":"General robotics update","description":"Top story","source":{"name":"AP News"},"url":"https://example.com/general"}]}""");
});
var provider = new NewsApiBriefingProvider(
new HttpClient(handler),
new NewsApiOptions
{
ApiKey = "test-key",
CacheTtlSeconds = 300,
FailureCacheTtlSeconds = 30
},
NullLogger<NewsApiBriefingProvider>.Instance);
var result = await provider.GetBriefingAsync(new NewsBriefingRequest(["sports"], 3));
Assert.NotNull(result);
Assert.Single(result!.Headlines);
Assert.Equal("General robotics update", result.Headlines[0].Title);
Assert.Equal(2, handler.GetCallCount("/v2/top-headlines"));
}
[Fact]
public async Task NewsApiBriefingProvider_FallsBackToEverything_WhenTopHeadlinesAreEmpty()
{
var handler = new CountingHttpMessageHandler(message =>
{
var path = message.RequestUri?.AbsolutePath ?? string.Empty;
return path switch
{
"/v2/top-headlines" => JsonResponse("""{"status":"ok","articles":[]}"""),
"/v2/everything" => JsonResponse(
"""{"status":"ok","articles":[{"title":"Robotics breakthrough announced","description":"Lab unveils a new platform.","source":{"name":"Science Daily"},"url":"https://example.com/robotics"}]}"""),
_ => new HttpResponseMessage(HttpStatusCode.NotFound)
};
});
var provider = new NewsApiBriefingProvider(
new HttpClient(handler),
new NewsApiOptions
{
ApiKey = "test-key",
DefaultCategories = ["general"],
CacheTtlSeconds = 300,
FailureCacheTtlSeconds = 30
},
NullLogger<NewsApiBriefingProvider>.Instance);
var result = await provider.GetBriefingAsync(new NewsBriefingRequest([], 3));
Assert.NotNull(result);
Assert.Single(result!.Headlines);
Assert.Equal("Robotics breakthrough announced", result.Headlines[0].Title);
Assert.Equal(2, handler.GetCallCount("/v2/top-headlines"));
Assert.Equal(1, handler.GetCallCount("/v2/everything"));
}
[Fact]
public async Task NewsApiBriefingProvider_ContinuesFallbackChain_WhenCategoryReturnsHttpError()
{
var handler = new CountingHttpMessageHandler(message =>
{
var path = message.RequestUri?.AbsolutePath ?? string.Empty;
if (!string.Equals(path, "/v2/top-headlines", StringComparison.OrdinalIgnoreCase))
{
return new HttpResponseMessage(HttpStatusCode.NotFound);
}
var query = message.RequestUri?.Query ?? string.Empty;
if (query.Contains("category=sports", StringComparison.OrdinalIgnoreCase))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(
"""{"status":"error","code":"parameterInvalid","message":"Category not supported for this key."}""",
Encoding.UTF8,
"application/json")
};
}
return JsonResponse(
"""{"status":"ok","articles":[{"title":"General robotics update","description":"Top story","source":{"name":"AP News"},"url":"https://example.com/general"}]}""");
});
var provider = new NewsApiBriefingProvider(
new HttpClient(handler),
new NewsApiOptions
{
ApiKey = "test-key",
CacheTtlSeconds = 300,
FailureCacheTtlSeconds = 30
},
NullLogger<NewsApiBriefingProvider>.Instance);
var result = await provider.GetBriefingAsync(new NewsBriefingRequest(["sports"], 3));
Assert.NotNull(result);
Assert.Single(result!.Headlines);
Assert.Equal("General robotics update", result.Headlines[0].Title);
Assert.Equal("success", result.ProviderStatus);
Assert.Equal(2, handler.GetCallCount("/v2/top-headlines"));
}
[Fact]
public async Task NewsApiBriefingProvider_PropagatesApiErrorCodeAndMessage_WhenAllEndpointsFail()
{
var handler = new CountingHttpMessageHandler(message =>
{
var path = message.RequestUri?.AbsolutePath ?? string.Empty;
if (string.Equals(path, "/v2/top-headlines", StringComparison.OrdinalIgnoreCase))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(
"""{"status":"error","code":"parameterInvalid","message":"Category 'general' is not available for this account."}""",
Encoding.UTF8,
"application/json")
};
}
if (string.Equals(path, "/v2/everything", StringComparison.OrdinalIgnoreCase))
{
return new HttpResponseMessage(HttpStatusCode.BadRequest)
{
Content = new StringContent(
"""{"status":"error","code":"parametersMissing","message":"Missing required search query."}""",
Encoding.UTF8,
"application/json")
};
}
return new HttpResponseMessage(HttpStatusCode.NotFound);
});
var provider = new NewsApiBriefingProvider(
new HttpClient(handler),
new NewsApiOptions
{
ApiKey = "test-key",
DefaultCategories = ["general"],
CacheTtlSeconds = 300,
FailureCacheTtlSeconds = 30
},
NullLogger<NewsApiBriefingProvider>.Instance);
var result = await provider.GetBriefingAsync(new NewsBriefingRequest([], 3));
Assert.NotNull(result);
Assert.Empty(result!.Headlines);
Assert.Equal("http_error", result.ProviderStatus);
Assert.Equal("parameterInvalid", result.ProviderErrorCode);
Assert.Equal("Category 'general' is not available for this account.", result.ProviderMessage);
Assert.Equal((int)HttpStatusCode.BadRequest, result.ProviderHttpStatusCode);
Assert.Contains("/v2/top-headlines", result.ProviderEndpoint, StringComparison.OrdinalIgnoreCase);
}
private static HttpResponseMessage JsonResponse(string body)

View File

@@ -216,4 +216,17 @@ public sealed class JiboCloudProtocolServiceTests
using var payload = JsonDocument.Parse(result.BodyText);
Assert.Single(payload.RootElement.EnumerateArray());
}
[Fact]
public void InMemoryCloudStateStore_SeedsPeopleForTheDefaultAccountLoop()
{
var store = new InMemoryCloudStateStore();
var people = store.GetPeople();
Assert.NotEmpty(people);
Assert.Contains(people, person => person.IsPrimary);
Assert.Contains(people, person => string.Equals(person.AccountId, store.GetAccount().AccountId, StringComparison.OrdinalIgnoreCase));
Assert.Contains(people, person => string.Equals(person.LoopId, store.GetLoops()[0].LoopId, StringComparison.OrdinalIgnoreCase));
}
}

View File

@@ -1613,6 +1613,36 @@ public sealed class JiboWebSocketServiceTests
Assert.Equal("surprises-ota/want_to_download_now", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
}
[Fact]
public async Task ClientAsr_YesNoPromptFromAsrHints_MapsYepToYesIntent()
{
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-yesno-hints-yep-token",
Text = """{"type":"LISTEN","transID":"trans-yesno-hints-yep","data":{"rules":["surprises-ota/want_to_download_now"],"asr":{"hints":["$YESNO"]}}}"""
});
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-yesno-hints-yep-token",
Text = """{"type":"CLIENT_ASR","transID":"trans-yesno-hints-yep","data":{"text":"yep"}}"""
});
Assert.Equal(3, replies.Count);
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
Assert.Equal("yep", listenPayload.RootElement.GetProperty("data").GetProperty("asr").GetProperty("text").GetString());
Assert.Equal("yes", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
Assert.Equal("surprises-ota/want_to_download_now", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules")[0].GetString());
Assert.Equal("surprises-ota/want_to_download_now", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
}
[Fact]
public async Task ClientAsr_SharedYesNoPrompt_StripsGlobalRulesAndStaysLocal()
{
@@ -1644,6 +1674,37 @@ public sealed class JiboWebSocketServiceTests
Assert.Equal("shared/yes_no", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
}
[Fact]
public async Task ClientAsr_SharedYesNoPrompt_MapsNegativeWordToNoIntent()
{
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-shared-yesno-negative-token",
Text = """{"type":"LISTEN","transID":"trans-shared-yesno-negative","data":{"rules":["shared/yes_no","globals/gui_nav","globals/mim_repeat","globals/global_commands_launch"],"asr":{"hints":["$YESNO"]}}}"""
});
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-shared-yesno-negative-token",
Text = """{"type":"CLIENT_ASR","transID":"trans-shared-yesno-negative","data":{"text":"negative"}}"""
});
Assert.Equal(3, replies.Count);
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
Assert.Equal("no", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
var rules = listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules");
Assert.Single(rules.EnumerateArray());
Assert.Equal("shared/yes_no", rules[0].GetString());
Assert.Equal("shared/yes_no", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
}
[Fact]
public async Task ClientAsr_AlarmTimerChangeYesNoPrompt_StripsGlobalRulesAndStaysLocal()
{
@@ -1871,14 +1932,53 @@ public sealed class JiboWebSocketServiceTests
Assert.Equal(3, replies.Count);
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
Assert.Equal("yes", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
Assert.Equal("proactive_offer_pizza_fact", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
var rules = listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules");
Assert.Single(rules.EnumerateArray());
Assert.Equal("surprises-date/offer_date_fact", rules[0].GetString());
Assert.Equal("surprises-date/offer_date_fact", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
var selectedRule = rules[0].GetString();
Assert.True(
string.Equals(selectedRule, "surprises-date/offer_date_fact", StringComparison.OrdinalIgnoreCase) ||
string.Equals(selectedRule, "shared/yes_no", StringComparison.OrdinalIgnoreCase));
Assert.Equal(selectedRule, listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
Assert.Empty(listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").EnumerateObject());
}
[Fact]
public async Task ClientAsr_WordOfDayOfferPrompt_MapsYesToWordOfDayLaunch()
{
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-wod-offer-yesno-token",
Text = """{"type":"LISTEN","transID":"trans-wod-offer-yes","data":{"rules":["word-of-the-day/surprise","globals/gui_nav","globals/mim_repeat","globals/global_commands_launch"],"asr":{"hints":["$YESNO"]}}}"""
});
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-wod-offer-yesno-token",
Text = """{"type":"CLIENT_ASR","transID":"trans-wod-offer-yes","data":{"text":"Yes!"}}"""
});
Assert.True(replies.Count >= 3);
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
var rules = listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("rules");
Assert.Single(rules.EnumerateArray());
var selectedRule = rules[0].GetString();
Assert.True(
string.Equals(selectedRule, "word-of-the-day/surprise", StringComparison.OrdinalIgnoreCase) ||
string.Equals(selectedRule, "word-of-the-day/menu", StringComparison.OrdinalIgnoreCase));
Assert.Equal(selectedRule, listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
Assert.Equal(
"word-of-the-day",
listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
}
[Fact]
public void ResponsePlanMapper_EscapesSpeechWithoutEncodingApostrophes()
{
@@ -2134,12 +2234,20 @@ public sealed class JiboWebSocketServiceTests
Text = """{"type":"CLIENT_ASR","transID":"trans-weather-provider","data":{"text":"how is the weather"}}"""
});
Assert.Equal(3, replies.Count);
Assert.True(replies.Count >= 3);
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
Assert.Equal("EOS", ReadReplyType(replies[1]));
Assert.Equal("SKILL_ACTION", ReadReplyType(replies[2]));
Assert.Contains(replies, static reply => string.Equals(ReadReplyType(reply), "SKILL_ACTION", StringComparison.Ordinal));
using var skillPayload = JsonDocument.Parse(replies[2].Text!);
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
Assert.False(listenPayload.RootElement.GetProperty("data").GetProperty("nlu").TryGetProperty("skill", out _));
Assert.Equal("weather", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("cloudSkill").GetString());
var skillReply = replies.Last(static reply => string.Equals(ReadReplyType(reply), "SKILL_ACTION", StringComparison.Ordinal));
using var skillPayload = JsonDocument.Parse(skillReply.Text!);
Assert.Equal(
"report-skill",
skillPayload.RootElement.GetProperty("data").GetProperty("skill").GetProperty("id").GetString());
var jcpConfig = skillPayload.RootElement
.GetProperty("data")
.GetProperty("action")
@@ -2163,6 +2271,9 @@ public sealed class JiboWebSocketServiceTests
Assert.Equal(
"weatherTempView",
display.GetProperty("view").GetProperty("data").GetProperty("viewConfig").GetProperty("id").GetString());
Assert.Equal(
"weatherTempView",
display.GetProperty("view").GetProperty("context").GetProperty("data").GetProperty("viewConfig").GetProperty("id").GetString());
Assert.True(jcpConfig.TryGetProperty("views", out var views));
var weatherHiLo = views.GetProperty("weatherHiLo");
@@ -2173,11 +2284,58 @@ public sealed class JiboWebSocketServiceTests
"weatherTempView",
local.GetProperty("views").GetProperty("weatherHiLo").GetProperty("viewConfig").GetProperty("id").GetString());
var payloadText = replies[2].Text!;
var payloadText = skillReply.Text!;
Assert.Contains("assets/personal-report-skill/weather/icons/rain_v01.crn", payloadText, StringComparison.Ordinal);
Assert.Contains("tempNormal_v01.crn", payloadText, StringComparison.Ordinal);
}
[Fact]
public async Task ClientAsr_WeatherNextWeek_WithProvider_EmitsWeatherHiLoSequenceCards()
{
var customStore = new InMemoryCloudStateStore();
var customService = CreateService(
customStore,
new StubWeatherReportProvider(
new WeatherReportSnapshot("Seattle, US", "light rain", 58, 61, 52, "rain", false)));
await customService.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-weather-next-week-token",
Text = """{"type":"LISTEN","transID":"trans-weather-next-week","data":{"hotphrase":true,"rules":["launch","globals/global_commands_launch"]}}"""
});
var replies = await customService.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-weather-next-week-token",
Text = """{"type":"CLIENT_ASR","transID":"trans-weather-next-week","data":{"text":"forecast for seattle next week"}}"""
});
Assert.True(replies.Count >= 3);
var skillReply = replies.Last(static reply => string.Equals(ReadReplyType(reply), "SKILL_ACTION", StringComparison.Ordinal));
using var skillPayload = JsonDocument.Parse(skillReply.Text!);
var jcp = skillPayload.RootElement
.GetProperty("data")
.GetProperty("action")
.GetProperty("config")
.GetProperty("jcp");
Assert.Equal("SEQUENCE", jcp.GetProperty("type").GetString());
var children = jcp.GetProperty("children");
Assert.Equal(5, children.GetArrayLength());
var firstChildConfig = children[0].GetProperty("config");
Assert.True(firstChildConfig.TryGetProperty("display", out var firstDisplay));
Assert.Equal(
"weatherTempView",
firstDisplay.GetProperty("view").GetProperty("data").GetProperty("viewConfig").GetProperty("id").GetString());
}
[Fact]
public async Task ClientAsr_OpenTheRadio_EmitsRadioRedirectAndSilentCompletion()
{
@@ -3557,6 +3715,38 @@ public sealed class JiboWebSocketServiceTests
Assert.False(session.Metadata.ContainsKey("pendingProactivityOffer"));
}
[Fact]
public async Task ClientAsrSurpriseOffer_PersistsPendingOfferAndResolvesYesFollowUpWithTail()
{
var token = _store.IssueRobotToken("proactivity-device-a-tail");
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = token,
Text = """{"type":"CLIENT_ASR","transID":"trans-proactive-offer-tail","data":{"text":"surprise me"}}"""
});
var followUpReplies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = token,
Text = """{"type":"CLIENT_ASR","transID":"trans-proactive-offer-tail-yes","data":{"text":"yes I want to"}}"""
});
Assert.Equal(3, followUpReplies.Count);
using var followUpListenPayload = JsonDocument.Parse(followUpReplies[0].Text!);
Assert.Equal("proactive_pizza_fact", followUpListenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
var session = _store.FindSessionByToken(token);
Assert.NotNull(session);
Assert.False(session.Metadata.ContainsKey("pendingProactivityOffer"));
}
[Fact]
public async Task ClientAsrSurpriseOffer_PersistsPendingOfferAndResolvesNoFollowUp()
{
@@ -3617,6 +3807,38 @@ public sealed class JiboWebSocketServiceTests
Assert.False(session.Metadata.ContainsKey("pendingProactivityOffer"));
}
[Fact]
public async Task ClientAsrSurpriseOffer_PersistsPendingOfferAndResolvesNoFollowUpWithTail()
{
var token = _store.IssueRobotToken("proactivity-device-b-tail");
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = token,
Text = """{"type":"CLIENT_ASR","transID":"trans-proactive-offer-no-tail","data":{"text":"surprise me"}}"""
});
var followUpReplies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = token,
Text = """{"type":"CLIENT_ASR","transID":"trans-proactive-offer-no-tail-followup","data":{"text":"no I do not"}}"""
});
Assert.Equal(3, followUpReplies.Count);
using var followUpListenPayload = JsonDocument.Parse(followUpReplies[0].Text!);
Assert.Equal("proactive_offer_declined", followUpListenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
var session = _store.FindSessionByToken(token);
Assert.NotNull(session);
Assert.False(session.Metadata.ContainsKey("pendingProactivityOffer"));
}
[Fact]
public async Task TriggerPresence_WithIdentity_EmitsProactiveGreetingAndPersistsGreetingMetadata()
{
@@ -3733,6 +3955,50 @@ public sealed class JiboWebSocketServiceTests
Assert.False(session.Metadata.ContainsKey("greetingsLastProactiveUtc"));
}
[Fact]
public async Task WhoAmI_DoesNotLeaveFollowUpOpen()
{
var token = _store.IssueRobotToken("identity-close-token");
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = token,
Text = """{"type":"LISTEN","transID":"trans-identity-close","data":{"rules":["launch"]}}"""
});
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = token,
Text = """{"type":"CONTEXT","transID":"trans-identity-close","data":{"runtime":{"perception":{"speaker":"person-1"},"loop":{"users":[{"id":"person-1","firstName":"erin"}]}}}}"""
});
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = token,
Text = """{"type":"CLIENT_ASR","transID":"trans-identity-close","data":{"text":"who am i"}}"""
});
Assert.Equal(3, replies.Count);
using (var listenPayload = JsonDocument.Parse(replies[0].Text!))
{
Assert.Equal("memory_get_name", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
}
var session = _store.FindSessionByToken(token);
Assert.NotNull(session);
Assert.False(session.FollowUpOpen);
Assert.False(session.TurnState.AwaitingTurnCompletion);
}
[Fact]
public async Task ClientAsrPersonalReport_StateMachinePersistsAcrossTurns()
{

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,102 @@
{
"name": "neohubjibocom-neohubproactive-tidd36da4d442a611f1aba45cf821ea55ae",
"session": {
"hostName": "neo-hub.jibo.com",
"path": "/v1/proactive",
"kind": "neo-hub-proactive",
"token": "hub-usr_openjibo_owner-1777340189867"
},
"steps": [
{
"text": {
"type": "TRIGGER",
"ts": 1777341970615,
"msgID": "mid-d388c070-42a6-11f1-a414-5cf821ea55ae",
"transID": "tid-d36da4d4-42a6-11f1-aba4-5cf821ea55ae",
"data": {
"triggerSource": "SURPRISE",
"triggerData": {
"looperID": "5c0b221fdf9d450019c5e255"
}
}
},
"binary": null,
"expectedReplyTypes": []
},
{
"text": {
"type": "CONTEXT",
"ts": 1777341970702,
"msgID": "mid-d395f790-42a6-11f1-95f4-5cf821ea55ae",
"transID": "tid-d36da4d4-42a6-11f1-aba4-5cf821ea55ae",
"data": {
"runtime": {
"character": {
"emotion": {
"name": "NEUTRAL",
"valence": 0.45,
"confidence": 0.2
},
"motivation": {
"social": 1,
"playful": 0.5152989351851469
}
},
"perception": {
"speaker": "5c0b221fdf9d450019c5e255",
"peoplePresent": [
{
"id": "NOT_TRAINED",
"entityId": 16085,
"type": "fused",
"confidence": 1
}
]
},
"location": {
"city": "Pleasant Hill",
"state": "Missouri",
"stateAbbr": "MO",
"country": "United States",
"countryCode": "US",
"lat": 38.8358494,
"lng": -94.1427229,
"iso": "2026-04-27T21:06:10.626-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": []
}
]
}

View File

@@ -0,0 +1,672 @@
2026-05-10T21:20:01.788571-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: CPU: Uptime: 1 week, 2 days, 14 hours,
2026-05-10T21:20:01.788612-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: CPU: Number of users logged in: 2 users
2026-05-10T21:20:01.788636-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: CPU: Current load average: 9.38, 8.35, 8.42
2026-05-10T21:20:01.790016-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: CPU: Current date: Sun May 10 2026 21:20:01 GMT-0500 (CDT)
2026-05-10T21:20:01.864803-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: Platform process: jibo-service-registry | Mem: 3480 (RSS), Uptime: 9d:14h:12m:16s (828736349)
2026-05-10T21:20:01.926981-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: Platform process: jibo-system-manager | Mem: 7240 (RSS), Uptime: 9d:14h:12m:16s (828736411)
2026-05-10T21:20:02.013672-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: Platform process: jibo-body-service | Mem: 4568 (RSS), Uptime: 9d:14h:12m:16s (828736498)
2026-05-10T21:20:02.089394-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: Platform process: jibo-audio-service | Mem: 11m (RSS), Uptime: 9d:14h:12m:16s (828736573)
2026-05-10T21:20:02.146389-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: Platform process: jibo-identity-service | Mem: 117m (RSS), Uptime: 9d:14h:12m:50s (828770129)
2026-05-10T21:20:02.251596-05:00 Royal-Current-Sage-Canvas system-monitor[30115,info]: - P.SystemMonitor: Error trying to examine memory usage: Command failed: ps -o pid,rss,args | grep [^]]jibo-nlu-service
2026-05-10T21:20:08.250578-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30880 80:69:1a:8b:a0:e3
2026-05-10T21:20:08.251013-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30881 86:69:1a:8b:a0:e3
2026-05-10T21:20:08.251440-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30882 80:69:1a:95:0b:6d
2026-05-10T21:20:08.251816-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30883 86:69:1a:95:0b:6d
2026-05-10T21:20:08.252221-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30876 ae:ae:19:ae:91:70
2026-05-10T21:20:08.252607-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30884 30:23:03:d6:cf:c0
2026-05-10T21:20:08.253018-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30877 d6:e2:2f:ea:3e:fb
2026-05-10T21:21:07.300769-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-STARTED
2026-05-10T21:21:11.307047-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30889 80:69:1a:8b:a0:e3
2026-05-10T21:21:11.307501-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30890 80:69:1a:95:0b:6d
2026-05-10T21:21:11.307854-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30891 86:69:1a:95:0b:6d
2026-05-10T21:21:11.308165-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30892 30:23:03:3f:51:e6
2026-05-10T21:21:11.308448-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30893 52:06:f5:3e:83:89
2026-05-10T21:21:11.308641-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30894 68:f0:bc:c6:99:04
2026-05-10T21:21:11.308879-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30895 b0:39:56:ea:f8:8e
2026-05-10T21:21:11.309116-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30896 68:f0:bc:c3:76:ce
2026-05-10T21:21:11.309422-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-RESULTS
2026-05-10T21:22:08.348626-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30885 4a:9e:bd:65:31:8b
2026-05-10T21:22:08.349109-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30886 30:23:03:95:2b:b7
2026-05-10T21:22:08.349456-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30887 36:23:03:3f:51:e5
2026-05-10T21:22:08.349777-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30888 30:23:03:d6:ca:1c
2026-05-10T21:23:11.392002-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-STARTED
2026-05-10T21:23:15.396307-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30897 30:23:03:95:2b:b8
2026-05-10T21:23:15.396592-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30898 80:69:1a:95:0b:6e
2026-05-10T21:23:15.396806-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30899 ae:ae:19:ae:91:70
2026-05-10T21:23:15.397009-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30900 36:23:03:d6:ca:1c
2026-05-10T21:23:15.397161-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30901 d6:e2:2f:ea:3e:fb
2026-05-10T21:23:15.397457-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30902 7a:c3:2a:77:55:eb
2026-05-10T21:23:15.397752-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-RESULTS
2026-05-10T21:24:08.443524-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30889 80:69:1a:8b:a0:e3
2026-05-10T21:24:08.443873-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30890 80:69:1a:95:0b:6d
2026-05-10T21:24:18.451863-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30892 30:23:03:3f:51:e6
2026-05-10T21:24:18.452186-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30894 68:f0:bc:c6:99:04
2026-05-10T21:24:18.452419-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30895 b0:39:56:ea:f8:8e
2026-05-10T21:24:18.452598-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30896 68:f0:bc:c3:76:ce
2026-05-11T02:25:00.712Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Playing big musing.
2026-05-11T02:25:00.886Z Royal-Current-Sage-Canvas be[1017,warning]: [versions@1 release="1.9.2"] T.Be.Framework.HolidayBeSkillPlugin-Holiday: KB returned no holiday list.
2026-05-11T02:25:00.888Z Royal-Current-Sage-Canvas be[1017,warning]: [versions@1 release="1.9.2"] T.Be.Framework.HolidayBeSkillPlugin-Holiday: No active holiday data.
2026-05-11T02:25:00.897Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Randomly chosen idle animation query:{"category":"ib","includeMeta":[],"includeSomeMeta":[],"excludeMeta":["seasonal","shift","shift-left","shift-right","postural-shift"]}
2026-05-11T02:25:03.460Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION AttentionManager not trying to do lookat, we have no dofs!!
2026-05-11T02:25:03.940Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: BODY_INTERFACE motion exceeds dynamic limits, motion limiting is being applied
2026-05-11T02:25:04.026Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: BODY_INTERFACE motion is back within normal limits, no limiting is being applied
2026-05-11T02:25:07.582Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning null speaker due to staleness.
2026-05-10T21:25:15.500088-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-STARTED
2026-05-10T21:25:19.503579-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30903 80:69:1a:8b:a2:b7
2026-05-10T21:25:19.504140-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30904 86:69:1a:8b:a2:b7
2026-05-10T21:25:19.504604-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30905 b0:39:56:ea:f8:8e
2026-05-10T21:25:19.504892-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-RESULTS
2026-05-11T02:25:20.043Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Asserting attention rule after interruption: Idle Boredom Big
2026-05-10T21:26:18.546820-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30893 52:06:f5:3e:83:89
2026-05-10T21:26:18.547186-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30891 86:69:1a:95:0b:6d
2026-05-10T21:26:18.547413-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30900 36:23:03:d6:ca:1c
2026-05-10T21:26:18.547591-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30856 fc:9c:98:59:45:de
2026-05-10T21:26:18.547781-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30902 7a:c3:2a:77:55:eb
2026-05-10T21:26:23.485982-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,warning]: - P.SystemManager.SkillManager: SkillManager::refresh Error reading package file for @be: File not found
2026-05-10T21:26:30.633876-05:00 Royal-Current-Sage-Canvas jibo-log-client-async[30210,info]: - Upload log /tmp/tmp833qraaaa size 5683 bytes
2026-05-11T02:26:40.517Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Primary face selected (position based): 13994
2026-05-11T02:26:40.530Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Switched Attention Rule:Idle Face
2026-05-10T21:26:40.863416-05:00 Royal-Current-Sage-Canvas jibo-identity-service[663,info]: - P.ImageIdentifier: ImageIdentifier[deepid]::identify [["5c0b221fdf9d450019c5e255", "face", 0.495323]]
2026-05-10T21:26:40.873087-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::measure input from: face with 1 hypotheses
2026-05-10T21:26:40.873182-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity::Measure face Quality:1 Id: 5c0b221fdf9d450019c5e255 Conf: 0.495323
2026-05-10T21:26:40.873243-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion with 2 options from 1 inputs.
2026-05-10T21:26:40.873309-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::updateIdentity Op: 5c0b221fdf9d450019c5e255 Score: 0.158872 Op: NOT_TRAINED Score: 0.3
2026-05-10T21:26:40.873354-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity Update Best Score: 0.3 Best ID: NOT_TRAINED
2026-05-10T21:26:40.873390-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion CHANGING identity from UNKNOWN to NOT_TRAINED
2026-05-11T02:26:41.226Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face started 13994
2026-05-11T02:26:41.239Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Emotion.Appraisal.IdentityRule: Appraising data from identity data: VISIBLE_FACE_STARTED
2026-05-11T02:26:45.712Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.SignalFacePersisted: Persisting face entity ID 13994 has an identity of null
2026-05-11T02:26:45.746Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.HttpHandler: Handling JetHttpHandler:/proactive/trigger
2026-05-11T02:26:45.715Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.OpportunityDetector: Evaluating trigger source: NEW_ARRIVAL with looperID: null
2026-05-11T02:26:45.721Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.OpportunityDetector: Passed all inhibitors
2026-05-11T02:26:45.724Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.OpportunityDetector: Sending proactive trigger to jetstream
2026-05-11T02:26:46.016Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,err]: - C.Jetstream.PhubClient: FAILURE opening phubclient connection: CloudConnection::open (poco exception): Connection refused
2026-05-11T02:26:46.017Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.Proactivity: Reaper queue down to 0 entries.
2026-05-11T02:26:46.018Z Royal-Current-Sage-Canvas be[1017,err]: [versions@1 release="1.9.2"] T.JetstreamClient: CloudConnection::open (poco exception): Connection refused
2026-05-11T02:26:46.019Z Royal-Current-Sage-Canvas ssm[937,err]: [versions@1 release="1.9.2"] T.SSM: CloudConnection::open (poco exception): Connection refused
2026-05-11T02:26:46.020Z Royal-Current-Sage-Canvas be[1017,err]: [1@1 frames="[{\"method\":\"HTTPWSClient.Client.handleMessage.error\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/@jibo/jetstream-client/lib/jetstream-client.js\",\"line\":302,\"column\":40},{\"method\":\"emitOne\",\"filename\":\"events.js\",\"line\":96,\"column\":13},{\"method\":\"HTTPWSClient.emit\",\"filename\":\"events.js\",\"line\":188,\"column\":7},{\"method\":\"WebSocket.HTTPWSClient._onMessage.err\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/jibo-client-framework/lib/jibo-client-framework.js\",\"line\":823,\"column\":22},{\"method\":\"emitOne\",\"filename\":\"events.js\",\"line\":96,\"column\":13},{\"method\":\"WebSocket.emit\",\"filename\":\"events.js\",\"line\":188,\"column\":7},{\"method\":\"Receiver._receiver.onmessage\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/ws/lib/WebSocket.js\",\"line\":141,\"column\":47},{\"method\":\"Receiver.dataMessage\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/ws/lib/Receiver.js\",\"line\":389,\"column\":14},{\"method\":\"Receiver.getData\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/ws/lib/Receiver.js\",\"line\":330,\"column\":12},{\"method\":\"Receiver.startLoop\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/ws/lib/Receiver.js\",\"line\":165,\"column\":16},{\"method\":\"Receiver.add\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/ws/lib/Receiver.js\",\"line\":139,\"column\":10},{\"method\":\"Socket._ultron.on\",\"filename\":\"/opt/jibo/Jibo/Skills/@be/be/node_modules/ws/lib/WebSocket.js\",\"line\":138,\"column\":22},{\"method\":\"emitOne\",\"filename\":\"events.js\",\"line\":96,\"column\":13},{\"method\":\"Socket.emit\",\"filename\":\"events.js\",\"line\":188,\"column\":7},{\"method\":\"readableAddChunk\",\"filename\":\"_stream_readable.js\",\"line\":176,\"column\":18},{\"method\":\"Socket.Readable.push\",\"filename\":\"_stream_readable.js\",\"line\":134,\"column\":10},{\"method\":\"TCP.onread\",\"filename\":\"net.js\",\"line\":543,\"column\":20}\]" message="CloudConnection::open (poco exception): Connection refused"][versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: error received: CloudConnection::open (poco exception): Connection refused
2026-05-11T02:26:46.025Z Royal-Current-Sage-Canvas be[1017,err]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.OpportunityDetector: Received error: CloudConnection::open (poco exception): Connection refused
2026-05-11T02:26:48.227Z Royal-Current-Sage-Canvas be[1017,warning]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.OpportunityDetector: A proactive trigger was sent but did not receive a response from jetstream within 2500 milliseconds
2026-05-11T02:26:54.984Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face stopped 13994
2026-05-11T02:27:02.851Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: deleting person entity 13994
2026-05-10T21:27:13.432028-05:00 Royal-Current-Sage-Canvas jibo-server-service[29676,warning]: - P.Application.ServerPort: ServerPort[2]::onReadable Disconnecting because of socket exception: Connection reset by peer
2026-05-10T21:27:13.432585-05:00 Royal-Current-Sage-Canvas jibo-server-service[29676,alert]: - P.ServiceApp: Terminate with Poco exception: I/O error: Broken pipe: 32
2026-05-10T21:27:13.432986-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.ServiceManager.Service: server: terminate called after throwing an instance of 'Poco::IOException'
2026-05-11T02:27:13.437Z Royal-Current-Sage-Canvas scs[891,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications closed 1006
2026-05-11T02:27:13.438Z Royal-Current-Sage-Canvas STS[920,warning]: [versions@1 release="1.9.2"] P.SF.Client.WSClient: socket closed 1006
2026-05-11T02:27:13.440Z Royal-Current-Sage-Canvas STS[920,warning]: [versions@1 release="1.9.2"] P.SF.Client.WSClient: socket closed 1006
2026-05-11T02:27:13.440Z Royal-Current-Sage-Canvas mms[856,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications closed 1006
2026-05-11T02:27:13.451Z Royal-Current-Sage-Canvas mms[856,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications/status closed 1006
2026-05-11T02:27:13.451Z Royal-Current-Sage-Canvas scs[891,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications/status closed 1006
2026-05-11T02:27:13.445Z Royal-Current-Sage-Canvas ssm[937,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications closed 1006
2026-05-11T02:27:13.469Z Royal-Current-Sage-Canvas ssm[937,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications/status closed 1006
2026-05-11T02:27:13.472Z Royal-Current-Sage-Canvas be[1017,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications/status closed 1006
2026-05-11T02:27:13.477Z Royal-Current-Sage-Canvas be[1017,warning]: [versions@1 release="1.9.2"] T.SF.Client.WSClient: socket ws://127.0.0.1:8888/server/notifications closed 1006
2026-05-10T21:27:14.017534-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.Service.Monitor: Service server exited with code 0
2026-05-11T02:27:14.448Z Royal-Current-Sage-Canvas STS[920,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] P.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.451Z Royal-Current-Sage-Canvas mms[856,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.442Z Royal-Current-Sage-Canvas scs[891,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.459Z Royal-Current-Sage-Canvas STS[920,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] P.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.468Z Royal-Current-Sage-Canvas scs[891,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.477Z Royal-Current-Sage-Canvas mms[856,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.491Z Royal-Current-Sage-Canvas ssm[937,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.506Z Royal-Current-Sage-Canvas ssm[937,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1022,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1045,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1087,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-10T21:27:14.534492-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.Service.Monitor: Service server launched with PID 30227
2026-05-11T02:27:14.548Z Royal-Current-Sage-Canvas be[1017,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1026,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1049,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1081,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-11T02:27:14.552Z Royal-Current-Sage-Canvas be[1017,warning]: [1@1 frames="[{\"method\":\"Object.exports._errnoException\",\"filename\":\"util.js\",\"line\":1026,\"column\":11},{\"method\":\"exports._exceptionWithHostPort\",\"filename\":\"util.js\",\"line\":1049,\"column\":20},{\"method\":\"TCPConnectWrap.afterConnect [as oncomplete\]\",\"filename\":\"net.js\",\"line\":1081,\"column\":14}\]" message="connect ECONNREFUSED 127.0.0.1:8888" code="ECONNREFUSED" errno="ECONNREFUSED" syscall="connect" address="127.0.0.1" port="8888"][versions@1 release="1.9.2"] T.SF.Client.WSClient: socket error connect ECONNREFUSED 127.0.0.1:8888
2026-05-10T21:27:14.812687-05:00 Royal-Current-Sage-Canvas jibo-server-service[30227,warning]: - P.ServiceRegistryClient: ServiceRegistryClient::registerService error: Bad Request
2026-05-10T21:27:15.060455-05:00 Royal-Current-Sage-Canvas jibo-server-service[30227,err]: - P.NotificationSubsystem: NotificationSubsystem::connect Failed to connect to the server: Could not request robot token: Connection refused
2026-05-10T21:27:15.062561-05:00 Royal-Current-Sage-Canvas jibo-server-service[30227,info]: - P.ServiceApp: Chronometer timestamp: 829232 s, 471488 us
2026-05-10T21:27:18.074760-05:00 Royal-Current-Sage-Canvas jibo-server-service[30227,err]: - P.NotificationSubsystem: NotificationSubsystem::connect Failed to connect to the server: Could not request robot token: Connection refused
2026-05-11T02:27:18.864Z Royal-Current-Sage-Canvas ssm[937,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Error.Logger: Added L2-Cannot_connect_to_server
2026-05-11T02:27:19.073Z Royal-Current-Sage-Canvas ssm[937,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Error.Logger: Added Q4-Server_connection_lost
2026-05-11T02:27:19.084Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: skill relaunch command from Global Service { nlu: \n { intent: 'launch',\n entities: { skill: '@be/settings', errorId: 'Q4-Server_connection_lost' },\n rules: null },\n asr: { text: '', confidence: 1 } }
2026-05-11T02:27:19.093Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/settings { nlu: \n { intent: 'launch',\n entities: { skill: '@be/settings', errorId: 'Q4-Server_connection_lost' },\n rules: null },\n asr: { text: '', confidence: 1 } }
2026-05-11T02:27:19.097Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:27:19.105Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/idle @be/settings
2026-05-11T02:27:19.106Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/idle
2026-05-11T02:27:19.113Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/idle
2026-05-11T02:27:19.114Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Stopping
2026-05-11T02:27:19.231Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from IDLE to ENGAGED
2026-05-11T02:27:19.272Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to OFF
2026-05-11T02:27:19.124Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to false
2026-05-11T02:27:19.129Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Clearing animation queue.
2026-05-11T02:27:19.143Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/idle
2026-05-11T02:27:19.306Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.HttpHandler: Handling JetHttpHandler:/listen/set_hj_mode
2026-05-11T02:27:19.306Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: hjw_JM_SET_HJ_MODE
2026-05-11T02:27:19.306Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_SET_HJ_MODE in 0 ms.
2026-05-11T02:27:19.145Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning null speaker due to staleness.
2026-05-11T02:27:19.150Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/idle
2026-05-11T02:27:19.152Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/settings { nlu: \n { intent: 'launch',\n entities: { skill: '@be/settings', errorId: 'Q4-Server_connection_lost' },\n rules: null },\n asr: { text: '', confidence: 1 } }
2026-05-11T02:27:19.177Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/settings
2026-05-11T02:27:19.183Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/settings''
2026-05-11T02:27:19.192Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/settings''
2026-05-11T02:27:19.209Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:27:19.214Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/settings
2026-05-11T02:27:19.217Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/settings { nlu: \n { intent: 'launch',\n entities: { skill: '@be/settings', errorId: 'Q4-Server_connection_lost' },\n rules: null },\n asr: { text: '', confidence: 1 } }
2026-05-11T02:27:19.222Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/idle @be/settings { nlu: \n { intent: 'launch',\n entities: { skill: '@be/settings', errorId: 'Q4-Server_connection_lost' },\n rules: null },\n asr: { text: '', confidence: 1 } }
2026-05-11T02:27:19.233Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/settings
2026-05-11T02:27:19.236Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/settings
2026-05-11T02:27:19.243Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning null speaker due to staleness.
2026-05-11T02:27:19.250Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Settings.error: SubSkill Launched
2026-05-11T02:27:19.273Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning null speaker due to staleness.
2026-05-11T02:27:19.275Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/settings { nlu: \n { intent: 'launch',\n entities: { skill: '@be/settings', errorId: 'Q4-Server_connection_lost' },\n rules: null },\n asr: { text: '', confidence: 1 } }
2026-05-10T21:27:19.571608-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-STARTED
2026-05-10T21:27:24.575016-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30906 4a:9e:bd:65:31:8b
2026-05-10T21:27:24.575291-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30907 80:69:1a:8b:a0:e3
2026-05-10T21:27:24.577246-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30908 86:69:1a:8b:a0:e3
2026-05-10T21:27:24.577629-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-ADDED 30909 fc:9c:98:59:45:de
2026-05-10T21:27:24.577789-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-SCAN-RESULTS
2026-05-10T21:27:33.100384-05:00 Royal-Current-Sage-Canvas jibo-server-service[30227,err]: - P.NotificationSubsystem: NotificationSubsystem::connect Failed to connect to the server: Could not request robot token: Connection refused
2026-05-10T21:27:48.833123-05:00 Royal-Current-Sage-Canvas jibo-server-service[30227,info]: - P.NotificationSubsystem: NotificationSubsystem::connect Connecting to api-socket.jibo.com:443/token-Royal-Current-Sage-Canvas-1778466468774
2026-05-10T21:27:48.997316-05:00 Royal-Current-Sage-Canvas jibo-server-service[30227,info]: - P.NotificationSubsystem: NotificationSubsystem::connect established connection to server
2026-05-11T02:27:49.084Z Royal-Current-Sage-Canvas ssm[937,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Error.Logger: Removed L2-Cannot_connect_to_server
2026-05-11T02:27:49.088Z Royal-Current-Sage-Canvas ssm[937,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Error.Logger: Removed Q4-Server_connection_lost
2026-05-11T02:27:49.100Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Settings.error: error resolved: Q4-Server_connection_lost
2026-05-11T02:27:49.112Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Settings.error: no more errors!
2026-05-11T02:27:49.150Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from OFF to ENGAGED
2026-05-10T21:27:49.157648-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: { "tts": { "stop_request" : "Calling TTS stop" } }
2026-05-11T02:27:49.133Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Be: REDIRECT: skill redirect: @be/idle {}
2026-05-11T02:27:49.135Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/idle { asr: { text: '', confidence: 1 } }
2026-05-11T02:27:49.137Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:27:49.141Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/settings @be/idle
2026-05-11T02:27:49.200Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.HttpHandler: Handling JetHttpHandler:/listen/set_hj_mode
2026-05-11T02:27:49.201Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: hjw_JM_SET_HJ_MODE
2026-05-11T02:27:49.201Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_SET_HJ_MODE in 0 ms.
2026-05-11T02:27:49.142Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/settings
2026-05-11T02:27:49.143Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/settings
2026-05-11T02:27:49.145Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Settings.error: SubSkill killed before its time
2026-05-11T02:27:49.738Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/settings
2026-05-11T02:27:49.829Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to IDLE
2026-05-11T02:27:49.757Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning null speaker due to staleness.
2026-05-11T02:27:49.763Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/settings
2026-05-11T02:27:49.764Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/idle { asr: { text: '', confidence: 1 } }
2026-05-11T02:27:49.805Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/idle
2026-05-11T02:27:49.810Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:27:49.815Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:27:49.818Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:27:49.819Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/idle
2026-05-11T02:27:49.820Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/idle { asr: { text: '', confidence: 1 } }
2026-05-11T02:27:49.822Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/settings @be/idle { asr: { text: '', confidence: 1 } }
2026-05-11T02:27:49.825Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/idle
2026-05-11T02:27:49.829Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/idle
2026-05-11T02:27:49.830Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning null speaker due to staleness.
2026-05-11T02:27:49.833Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: adding listener for SLEEP
2026-05-11T02:27:49.834Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to true
2026-05-11T02:27:49.835Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Starting
2026-05-11T02:27:49.848Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from ALERT to SELECT_INTENT.
2026-05-11T02:27:49.850Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering: SELECT_INTENT
2026-05-11T02:27:49.858Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/idle { asr: { text: '', confidence: 1 } }
2026-05-11T02:27:50.364Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from SELECT_INTENT to ALERT.
2026-05-11T02:27:50.367Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering ALERT
2026-05-11T02:27:50.378Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: No transitions between SELECT_INTENT and ALERT
2026-05-11T02:27:50.452Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Brightness set to 0.4.
2026-05-11T02:27:53.063Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.RecLoop: utterance: hey jibo score: 41 walign: B020C088 palign: B0221A00 {"word_alignment":"829235648 829235776 hey 0.00 829235776 829236032 jibo 0.00 "}
2026-05-11T02:27:53.063Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.RecLoop: HJ: signal sent to ASR will be boosted 8.50333 dB
2026-05-11T02:27:53.064Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: hjw_JM_RECOG_HJ_EVENT
2026-05-10T21:27:53.065581-05:00 Royal-Current-Sage-Canvas jibo-audio-service[642,notice]: - P.AudioService: detection: {"ts":[829270,474613],"type":"hotphrase","id":326,"location":{"ts":[829270,274518],"possibilities":[{"channels":[1],"position":{"x":0.8720762729644775,"y":0.5147014856338501,"z":0.21438778936862946},"confidence":0.15776042640209199}]},"utterances":[]}
2026-05-11T02:27:53.064Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Entering PH-W state
2026-05-11T02:27:53.065Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.RecogSpeakerID: RecogSpeakerTD starting at 829235648
2026-05-11T02:27:53.069Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_RECOG_HJ_EVENT in 5 ms.
2026-05-11T02:27:53.066Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: hjHeard
2026-05-11T02:27:53.163Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from IDLE to COMMAND
2026-05-11T02:27:53.130Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Hey Jibo'
2026-05-11T02:27:53.148Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'HJOrient' to achieve goal 'Hey Jibo'
2026-05-11T02:27:53.189Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action: Initial face: { x: 0.8720762729644775,\n y: 0.5147014856338501,\n z: 0.21438778936862946 } null
2026-05-11T02:27:53.211Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.LhubClient: Hub Client connection opened.
2026-05-11T02:27:53.212Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_CLIENT_CONNECT_RESULT
2026-05-11T02:27:53.213Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: [messageContext@1 gain="2.661744" requestID="GLOBAL" transID="tid-03398a0e-4ce1-11f1-986e-5cf821ea55ae"] C.Jetstream.LhubClient: Hub LISTEN request keystone log entry
2026-05-11T02:27:53.213Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_CLIENT_CONNECT_RESULT in 1 ms.
2026-05-11T02:27:53.214Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.LhubClient: Set Audio encoder to type: OGG_OPUS
2026-05-11T02:27:53.204Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Received attendToTarget request
2026-05-11T02:27:53.221Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnStarted
2026-05-11T02:27:53.220Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look rule has fired!
2026-05-11T02:27:53.221Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Switched Attention Rule:Command Look
2026-05-11T02:27:53.359Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.RecLoop: Speaker: 5c0b221fdf9d450019c5e255 score: 31.165 accepted: 1
2026-05-11T02:27:53.360Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_RECOG_SPEAKER_EVENT
2026-05-10T21:27:53.360575-05:00 Royal-Current-Sage-Canvas jibo-audio-service[642,notice]: - P.AudioService: detection: {"ts":[829270,769641],"type":"jet_speaker_id","id":326,"data":{"speakers":[{"speaker":"5c0b221fdf9d450019c5e255","score":31.165042877197267,"accepted":true,"high_confidence":true}],"snr":19.75763511657715}}
2026-05-11T02:27:53.370Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter.ConvTechSpeakerID: Speaker ID: 5c0b221fdf9d450019c5e255 | accepted: true | confidence: true | score: 31.165042877197266
2026-05-11T02:27:53.374Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Emitting idAcquired from source: VOICE
2026-05-11T02:27:53.377Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Emotion.Appraisal.IdentityRule: Appraising data from identity data: ID_ACQUIRED
2026-05-11T02:27:53.378Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Most recent speaker accepted.
2026-05-11T02:27:53.486Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_RECOG_SPEAKER_EVENT in 126 ms.
2026-05-11T02:27:54.459Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look resolving with status:SUCCEEDED
2026-05-11T02:27:56.919Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Demand Face Detect found 1 faces
2026-05-10T21:27:57.094401-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::measure input from: voice with 1 hypotheses
2026-05-10T21:27:57.094454-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity::Measure voice Quality:19.7576 Id: 5c0b221fdf9d450019c5e255 Conf: 31.165
2026-05-10T21:27:57.094496-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion with 2 options from 1 inputs.
2026-05-10T21:27:57.094537-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::updateIdentity Op: 5c0b221fdf9d450019c5e255 Score: 0.983842 Op: NOT_TRAINED Score: 0.295153
2026-05-10T21:27:57.094568-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity Update Best Score: 0.983842 Best ID: 5c0b221fdf9d450019c5e255
2026-05-10T21:27:57.094597-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion CHANGING identity from UNKNOWN to 5c0b221fdf9d450019c5e255
2026-05-11T02:27:57.107Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Primary face selected (position based): 14002
2026-05-11T02:27:57.117Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Expression.Base.ResolveHandle: Someone tried to cancel ResolveHandle after it was resolved!
2026-05-11T02:27:57.123Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Received attendToTarget request
2026-05-11T02:27:57.147Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look rule has fired!
2026-05-11T02:27:57.149Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Asserting attention rule after interruption: Command Look
2026-05-11T02:27:57.616Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face started 14002
2026-05-11T02:27:57.618Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Emotion.Appraisal.IdentityRule: Appraising data from identity data: VISIBLE_FACE_STARTED
2026-05-11T02:27:58.322Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look resolving with status:SUCCEEDED
2026-05-11T02:27:58.356Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Primary face selected (entity match): 14002
2026-05-11T02:27:58.738Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_LISTEN
2026-05-11T02:27:58.739Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_LISTEN in 1 ms.
2026-05-11T02:27:58.739Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_EOS
2026-05-11T02:27:58.740Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_EOS in 1 ms.
2026-05-11T02:27:58.747Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: skillSwitch: { skillID: undefined,\n onRobot: undefined,\n isProactive: undefined,\n skipSurprises: true,\n transID: 'tid-03398a0e-4ce1-11f1-986e-5cf821ea55ae',\n data: \n ListenResult {\n asr: { confidence: 0.95, final: true, text: 'What\'s the weather?' },\n nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n match: \n { cloudSkill: null,\n intent: 'weather',\n rule: 'launch',\n score: 0.95,\n skipSurprises: true } } }
2026-05-11T02:27:58.784Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from COMMAND to IDLE
2026-05-11T02:27:58.754Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnResult: { global: true,\n result: \n ListenResult {\n asr: { confidence: 0.95, final: true, text: 'What\'s the weather?' },\n nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n match: \n { cloudSkill: null,\n intent: 'weather',\n rule: 'launch',\n score: 0.95,\n skipSurprises: true } },\n status: 'SUCCEEDED',\n transID: 'tid-03398a0e-4ce1-11f1-986e-5cf821ea55ae' }
2026-05-11T02:27:58.771Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: eos received
2026-05-11T02:27:58.858Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_SKILL_INFO
2026-05-11T02:27:58.859Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_SKILL_INFO in 1 ms.
2026-05-11T02:27:58.879Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from IDLE to ENGAGED
2026-05-11T02:27:58.774Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient: event waiter 'HJ Listen Complete'
2026-05-11T02:27:58.780Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient time to face: 3927
2026-05-11T02:27:58.781Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient had initial face?: false
2026-05-11T02:27:58.788Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: skill relaunch command from Global Service { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:27:58.792Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:27:58.794Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:27:58.796Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/idle @be/nimbus
2026-05-11T02:27:58.797Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/idle
2026-05-11T02:27:58.800Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/idle
2026-05-11T02:27:58.801Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Stopping
2026-05-11T02:27:58.807Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to false
2026-05-10T21:27:59.048935-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS LEX
2026-05-10T21:27:59.049454-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get TTS Lex session start - 519392ab-299b-4556-b891-bdb87031874d
2026-05-10T21:27:59.049871-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get TTS Lex session end - 519392ab-299b-4556-b891-bdb87031874d
2026-05-11T02:27:58.811Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Clearing animation queue.
2026-05-11T02:27:58.816Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/idle
2026-05-10T21:27:59.106038-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS POS Tags
2026-05-10T21:27:59.106520-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session start - 6a637df3-1a12-4f94-ba51-98c9548b8324
2026-05-10T21:27:59.107573-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session end - 6a637df3-1a12-4f94-ba51-98c9548b8324
2026-05-11T02:27:58.817Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:27:58.819Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/idle
2026-05-11T02:27:58.820Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:27:58.843Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'HJOrient' with result: 'SUCCEEDED'
2026-05-11T02:27:58.847Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/nimbus
2026-05-11T02:27:58.854Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/nimbus''
2026-05-11T02:27:58.861Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/nimbus''
2026-05-11T02:27:58.866Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:27:58.869Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/nimbus
2026-05-11T02:27:58.870Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:27:58.872Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/idle @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:27:58.880Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/nimbus
2026-05-11T02:27:58.882Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/nimbus
2026-05-11T02:27:58.884Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Nimbus Opening
2026-05-11T02:27:58.894Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Awaiting Cloud Skill response...
2026-05-11T02:27:58.895Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:27:58.908Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Received Cloud Skill response.
2026-05-10T21:27:59.199454-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS Token times
2026-05-10T21:27:59.200445-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: {"tts":{"input_request":{"prompt":"<speak><STYLE set=\"NEUTRAL\"> <SPEAK> <BREAK size=\"0.35\"/> right now in Lone Jack , it is scattered clouds and 54 degrees Fahrenheit . </SPEAK> </STYLE></speak>","pitch":999.0,"speed":999.0,"pitchBandwidth":999.0,"mode":"ssml","outputMode":"stream","allPass":999.0,"enableDefaultVoice":"","framerate":999.0,"gvMCEP":999.0,"postfilter":999.0,"samplerate":999.0,"unvoicedvoiced":999.0,"voice":"griffin","locale":"en-us","volume":999.0,"whisper":"FALSE","cached":"TRUE","earlyStopTime":-1.0},"type":"token"}}
2026-05-11T02:27:58.909Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Processing Cloud Skill response...
2026-05-11T02:27:58.916Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Recieved analytics from cloud skill.
2026-05-11T02:27:58.918Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Processed Cloud Skill response.
2026-05-11T02:27:58.922Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Executing Cloud Skill SLIM: WeatherCommentPartlyCloudyNight_AN_13
2026-05-11T02:27:58.985Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:27:59.014Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Speak request received
2026-05-11T02:27:59.020Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Processing speak request
2026-05-11T02:27:59.022Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Starting new speak session: 8081453e-aa0a-4b21-9787-439c5f52254a
2026-05-10T21:27:59.232243-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,warning]: - C.TTSService: TTSUtterance: Trying to create an empty phrase! Ignoring...
2026-05-10T21:27:59.431911-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get Tokens session end - c06f1934-7c87-4979-9563-0d6498cd216e
2026-05-11T02:27:59.490Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Pushing Speaking Attention Mode
2026-05-11T02:27:59.510Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to SPEAKING
2026-05-11T02:27:59.525Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Waiting for Embodied Listen to finish
2026-05-11T02:27:59.526Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Dispatching Timeline: 8081453e-aa0a-4b21-9787-439c5f52254a
2026-05-10T21:27:59.563139-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS session start - 1be6e88f-6ef7-4bcf-ac30-731396752c5e
2026-05-10T21:27:59.563264-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: {"tts":{"input_request":{"prompt":"<speak><STYLE set=\"NEUTRAL\"> <SPEAK> <BREAK size=\"0.35\"/> right now in Lone Jack , it is scattered clouds and 54 degrees Fahrenheit . </SPEAK> </STYLE></speak>","pitch":999.0,"speed":999.0,"pitchBandwidth":999.0,"mode":"ssml","outputMode":"stream","allPass":999.0,"enableDefaultVoice":"","framerate":999.0,"gvMCEP":999.0,"postfilter":999.0,"samplerate":999.0,"unvoicedvoiced":999.0,"voice":"griffin","locale":"en-us","volume":999.0,"whisper":"FALSE","cached":"TRUE"},"type":"speak"}}
2026-05-10T21:27:59.563496-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS calling speak - 1be6e88f-6ef7-4bcf-ac30-731396752c5e
2026-05-10T21:27:59.563539-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: Synthesizing cached
2026-05-11T02:28:00.244Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION AttentionManager not trying to do lookat, we have no dofs!!
2026-05-11T02:28:02.123Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.SignalFacePersisted: Persisting face entity ID 14002 has an identity of 5c0b221fdf9d450019c5e255
2026-05-10T21:28:04.365469-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS session end - 1be6e88f-6ef7-4bcf-ac30-731396752c5e
2026-05-11T02:28:04.991Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from SPEAKING to ENGAGED
2026-05-11T02:28:04.988Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Timeline Dispatch Complete: 8081453e-aa0a-4b21-9787-439c5f52254a
2026-05-11T02:28:05.002Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Speak Complete: 8081453e-aa0a-4b21-9787-439c5f52254a
2026-05-11T02:28:05.008Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Cleaning up session
2026-05-11T02:28:05.011Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Ready for next speak request
2026-05-11T02:28:05.018Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Stop request received
2026-05-11T02:28:05.025Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:05.105Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to IDLE
2026-05-11T02:28:05.039Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:05.041Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:28:05.052Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/nimbus @be/idle
2026-05-11T02:28:05.054Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/nimbus
2026-05-11T02:28:05.056Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/nimbus
2026-05-11T02:28:05.057Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Nimbus Closing
2026-05-11T02:28:05.060Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/nimbus
2026-05-11T02:28:05.064Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:05.067Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/nimbus
2026-05-11T02:28:05.068Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:05.082Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/idle
2026-05-11T02:28:05.090Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:28:05.092Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:28:05.094Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:28:05.095Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/idle
2026-05-11T02:28:05.097Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:05.099Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/nimbus @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:05.103Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/idle
2026-05-11T02:28:05.105Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/idle
2026-05-11T02:28:05.107Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:05.109Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: adding listener for SLEEP
2026-05-11T02:28:05.110Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to true
2026-05-11T02:28:05.113Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Starting
2026-05-11T02:28:05.117Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from ALERT to SELECT_INTENT.
2026-05-11T02:28:05.118Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering: SELECT_INTENT
2026-05-11T02:28:05.122Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:05.133Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from SELECT_INTENT to ALERT.
2026-05-11T02:28:05.134Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering ALERT
2026-05-11T02:28:05.137Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: No transitions between SELECT_INTENT and ALERT
2026-05-11T02:28:05.203Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Brightness set to 0.4.
2026-05-11T02:28:06.807Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.RecLoop: utterance: hey jibo score: 159 walign: B020C088 palign: B0221A00 {"word_alignment":"829249344 829249472 hey 0.00 829249472 829249792 jibo 0.00 "}
2026-05-10T21:28:06.811219-05:00 Royal-Current-Sage-Canvas jibo-audio-service[642,notice]: - P.AudioService: detection: {"ts":[829284,220295],"type":"hotphrase","id":327,"location":{"ts":[829284,22546],"possibilities":[{"channels":[0,12],"position":{"x":0.6970734000205994,"y":0.6831817626953125,"z":0.43347111344337466},"confidence":0.13540178537368775}]},"utterances":[]}
2026-05-11T02:28:06.808Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.RecLoop: HJ: signal sent to ASR will be boosted 8.52053 dB
2026-05-11T02:28:06.808Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_RECOG_HJ_EVENT
2026-05-11T02:28:06.810Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_RECOG_HJ_EVENT in 2 ms.
2026-05-11T02:28:06.810Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.RecogSpeakerID: RecogSpeakerTD starting at 829249344
2026-05-11T02:28:06.813Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnResult: { global: true,\n message: '',\n status: 'INTERRUPTED',\n transID: 'tid-03398a0e-4ce1-11f1-986e-5cf821ea55ae' }
2026-05-11T02:28:06.821Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: hjHeard
2026-05-11T02:28:06.907Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Hey Jibo'
2026-05-11T02:28:06.920Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from IDLE to COMMAND
2026-05-11T02:28:06.917Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'HJOrient' to achieve goal 'Hey Jibo'
2026-05-11T02:28:06.930Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action: Initial face: { x: 0.6970734000205994,\n y: 0.6831817626953125,\n z: 0.43347111344337463 } 14002
2026-05-11T02:28:06.940Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Received attendToTarget request
2026-05-11T02:28:06.965Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look rule has fired!
2026-05-11T02:28:06.966Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Asserting attention rule after interruption: Command Look
2026-05-11T02:28:07.063Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.RecLoop: Speaker: 5c0b221fdf9d450019c5e255 score: 19.4559 accepted: 1
2026-05-11T02:28:07.063Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_RECOG_SPEAKER_EVENT
2026-05-11T02:28:07.064Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_RECOG_SPEAKER_EVENT in 0 ms.
2026-05-10T21:28:07.064121-05:00 Royal-Current-Sage-Canvas jibo-audio-service[642,notice]: - P.AudioService: detection: {"ts":[829284,473143],"type":"jet_speaker_id","id":327,"data":{"speakers":[{"speaker":"5c0b221fdf9d450019c5e255","score":19.455947875976564,"accepted":true,"high_confidence":true}],"snr":18.54705047607422}}
2026-05-10T21:28:07.065141-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::measure input from: voice with 1 hypotheses
2026-05-10T21:28:07.065222-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity::Measure voice Quality:18.5471 Id: 5c0b221fdf9d450019c5e255 Conf: 19.4559
2026-05-10T21:28:07.065325-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion with 2 options from 2 inputs.
2026-05-10T21:28:07.065417-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::updateIdentity Op: 5c0b221fdf9d450019c5e255 Score: 0.451568 Op: NOT_TRAINED Score: 0.135471
2026-05-10T21:28:07.065482-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity Update Best Score: 0.451568 Best ID: 5c0b221fdf9d450019c5e255
2026-05-10T21:28:07.065532-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion NO CHANGE.
2026-05-11T02:28:07.067Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter.ConvTechSpeakerID: Speaker ID: 5c0b221fdf9d450019c5e255 | accepted: true | confidence: true | score: 19.455947875976562
2026-05-11T02:28:07.068Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Most recent speaker accepted.
2026-05-11T02:28:07.228Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.LhubClient: Hub Client connection opened.
2026-05-11T02:28:07.229Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_CLIENT_CONNECT_RESULT
2026-05-11T02:28:07.229Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: [messageContext@1 gain="2.667021" requestID="GLOBAL" transID="tid-0b6ab9fa-4ce1-11f1-b472-5cf821ea55ae"] C.Jetstream.LhubClient: Hub LISTEN request keystone log entry
2026-05-11T02:28:07.233Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.LhubClient: Set Audio encoder to type: OGG_OPUS
2026-05-11T02:28:07.300Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_CLIENT_CONNECT_RESULT in 72 ms.
2026-05-11T02:28:07.302Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnStarted
2026-05-11T02:28:07.845Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face stopped 14002
2026-05-11T02:28:08.661Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look resolving with status:SUCCEEDED
2026-05-11T02:28:08.665Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient time to face: 4
2026-05-11T02:28:08.672Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from COMMAND to IDLE
2026-05-11T02:28:08.668Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient had initial face?: true
2026-05-11T02:28:08.681Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'HJOrient' with result: 'SUCCEEDED'
2026-05-11T02:28:09.633Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Primary face selected (position based): 14002
2026-05-11T02:28:09.638Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Switched Attention Rule:Idle Face
2026-05-11T02:28:10.136Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face started 14002
2026-05-11T02:28:10.138Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Emotion.Appraisal.IdentityRule: Appraising data from identity data: VISIBLE_FACE_STARTED
2026-05-11T02:28:12.148Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_LISTEN
2026-05-11T02:28:12.149Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_LISTEN in 4 ms.
2026-05-11T02:28:12.149Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_EOS
2026-05-11T02:28:12.149Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_EOS in 0 ms.
2026-05-11T02:28:12.150Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: skillSwitch: { skillID: undefined,\n onRobot: undefined,\n isProactive: undefined,\n skipSurprises: true,\n transID: 'tid-0b6ab9fa-4ce1-11f1-b472-5cf821ea55ae',\n data: \n ListenResult {\n asr: { confidence: 0.95, final: true, text: 'What\'s the forecast?' },\n nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n match: \n { cloudSkill: null,\n intent: 'weather',\n rule: 'launch',\n score: 0.95,\n skipSurprises: true } } }
2026-05-11T02:28:12.153Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnResult: { global: true,\n result: \n ListenResult {\n asr: { confidence: 0.95, final: true, text: 'What\'s the forecast?' },\n nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n match: \n { cloudSkill: null,\n intent: 'weather',\n rule: 'launch',\n score: 0.95,\n skipSurprises: true } },\n status: 'SUCCEEDED',\n transID: 'tid-0b6ab9fa-4ce1-11f1-b472-5cf821ea55ae' }
2026-05-11T02:28:12.159Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: eos received
2026-05-11T02:28:12.162Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: skill relaunch command from Global Service { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:12.164Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:12.165Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:28:12.168Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/idle @be/nimbus
2026-05-11T02:28:12.169Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/idle
2026-05-11T02:28:12.171Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/idle
2026-05-11T02:28:12.172Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Stopping
2026-05-11T02:28:12.173Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to false
2026-05-11T02:28:12.175Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Clearing animation queue.
2026-05-11T02:28:12.178Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/idle
2026-05-11T02:28:12.179Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:12.182Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/idle
2026-05-11T02:28:12.183Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:12.202Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/nimbus
2026-05-11T02:28:12.225Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from IDLE to ENGAGED
2026-05-11T02:28:12.208Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/nimbus''
2026-05-11T02:28:12.210Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/nimbus''
2026-05-11T02:28:12.213Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:28:12.214Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/nimbus
2026-05-11T02:28:12.217Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:12.220Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/idle @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:12.224Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/nimbus
2026-05-11T02:28:12.225Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/nimbus
2026-05-11T02:28:12.226Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Nimbus Opening
2026-05-11T02:28:12.229Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Awaiting Cloud Skill response...
2026-05-11T02:28:12.230Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'weather',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:12.285Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_SKILL_INFO
2026-05-11T02:28:12.286Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_SKILL_INFO in 1 ms.
2026-05-11T02:28:12.295Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Received Cloud Skill response.
2026-05-11T02:28:12.296Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Processing Cloud Skill response...
2026-05-11T02:28:12.297Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Recieved analytics from cloud skill.
2026-05-10T21:28:12.351265-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS LEX
2026-05-10T21:28:12.351761-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get TTS Lex session start - 2a602472-3b56-48bd-8325-62e307593a6a
2026-05-10T21:28:12.352514-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get TTS Lex session end - 2a602472-3b56-48bd-8325-62e307593a6a
2026-05-11T02:28:12.298Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Processed Cloud Skill response.
2026-05-11T02:28:12.302Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Executing Cloud Skill SLIM: WeatherCommentClearNight_AN_13
2026-05-10T21:28:12.377510-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS POS Tags
2026-05-10T21:28:12.377923-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session start - ef7eeb01-d163-43c8-a8a2-bf76e953b704
2026-05-10T21:28:12.379617-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session end - ef7eeb01-d163-43c8-a8a2-bf76e953b704
2026-05-11T02:28:12.339Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:12.344Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Speak request received
2026-05-11T02:28:12.345Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Processing speak request
2026-05-10T21:28:12.409244-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS Token times
2026-05-10T21:28:12.410311-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: {"tts":{"input_request":{"prompt":"<speak><STYLE set=\"NEUTRAL\"> <SPEAK> <BREAK size=\"0.35\"/> tomorrow in Lone Jack , US , expect clear sky with a high near 75 degrees Fahrenheit and a low around 54 degrees Fahrenheit . </SPEAK> </STYLE></speak>","pitch":999.0,"speed":999.0,"pitchBandwidth":999.0,"mode":"ssml","outputMode":"stream","allPass":999.0,"enableDefaultVoice":"","framerate":999.0,"gvMCEP":999.0,"postfilter":999.0,"samplerate":999.0,"unvoicedvoiced":999.0,"voice":"griffin","locale":"en-us","volume":999.0,"whisper":"FALSE","cached":"TRUE","earlyStopTime":-1.0},"type":"token"}}
2026-05-11T02:28:12.346Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Starting new speak session: 52c366b1-ae96-4162-9e23-4e2c072b44b4
2026-05-10T21:28:12.469741-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,warning]: - C.TTSService: TTSUtterance: Trying to create an empty phrase! Ignoring...
2026-05-10T21:28:12.761945-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get Tokens session end - 8855ef91-1eaf-4722-b269-9656badf11df
2026-05-11T02:28:12.786Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Pushing Speaking Attention Mode
2026-05-11T02:28:12.819Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to SPEAKING
2026-05-11T02:28:12.861Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Waiting for Embodied Listen to finish
2026-05-10T21:28:12.884687-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS session start - 3b7a307d-1509-485d-99a6-7635ffb2965e
2026-05-10T21:28:12.884807-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: {"tts":{"input_request":{"prompt":"<speak><STYLE set=\"NEUTRAL\"> <SPEAK> <BREAK size=\"0.35\"/> tomorrow in Lone Jack , US , expect clear sky with a high near 75 degrees Fahrenheit and a low around 54 degrees Fahrenheit . </SPEAK> </STYLE></speak>","pitch":999.0,"speed":999.0,"pitchBandwidth":999.0,"mode":"ssml","outputMode":"stream","allPass":999.0,"enableDefaultVoice":"","framerate":999.0,"gvMCEP":999.0,"postfilter":999.0,"samplerate":999.0,"unvoicedvoiced":999.0,"voice":"griffin","locale":"en-us","volume":999.0,"whisper":"FALSE","cached":"TRUE"},"type":"speak"}}
2026-05-10T21:28:12.885067-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS calling speak - 3b7a307d-1509-485d-99a6-7635ffb2965e
2026-05-10T21:28:12.885104-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: Synthesizing cached
2026-05-11T02:28:12.869Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Dispatching Timeline: 52c366b1-ae96-4162-9e23-4e2c072b44b4
2026-05-11T02:28:13.564Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION AttentionManager not trying to do lookat, we have no dofs!!
2026-05-11T02:28:14.631Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.SignalFacePersisted: Persisting face entity ID 14002 has an identity of 5c0b221fdf9d450019c5e255
2026-05-11T02:28:15.895Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face stopped 14002
2026-05-10T21:28:18.597515-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30903 80:69:1a:8b:a2:b7
2026-05-10T21:28:18.597812-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30904 86:69:1a:8b:a2:b7
2026-05-10T21:28:18.599328-05:00 Royal-Current-Sage-Canvas jibo-system-manager[473,info]: - P.SystemManager.WPAControlInterface: <3>CTRL-EVENT-BSS-REMOVED 30905 b0:39:56:ea:f8:8e
2026-05-11T02:28:20.859Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: deleting person entity 14002
2026-05-10T21:28:21.467425-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS session end - 3b7a307d-1509-485d-99a6-7635ffb2965e
2026-05-11T02:28:21.564Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Timeline Dispatch Complete: 52c366b1-ae96-4162-9e23-4e2c072b44b4
2026-05-11T02:28:21.567Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from SPEAKING to ENGAGED
2026-05-11T02:28:21.575Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Speak Complete: 52c366b1-ae96-4162-9e23-4e2c072b44b4
2026-05-11T02:28:21.578Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Cleaning up session
2026-05-11T02:28:21.580Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Ready for next speak request
2026-05-11T02:28:21.581Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Stop request received
2026-05-11T02:28:21.585Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:21.593Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:21.594Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:28:21.601Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/nimbus @be/idle
2026-05-11T02:28:21.603Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/nimbus
2026-05-11T02:28:21.604Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/nimbus
2026-05-11T02:28:21.605Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Nimbus Closing
2026-05-11T02:28:21.609Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/nimbus
2026-05-11T02:28:21.610Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:21.613Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/nimbus
2026-05-11T02:28:21.614Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:21.636Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/idle
2026-05-11T02:28:21.652Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to IDLE
2026-05-11T02:28:21.639Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:28:21.641Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:28:21.643Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:28:21.644Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/idle
2026-05-11T02:28:21.645Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:21.646Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/nimbus @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:21.649Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/idle
2026-05-11T02:28:21.652Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/idle
2026-05-11T02:28:21.653Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:21.654Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: adding listener for SLEEP
2026-05-11T02:28:21.655Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to true
2026-05-11T02:28:21.657Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Starting
2026-05-11T02:28:21.659Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from ALERT to SELECT_INTENT.
2026-05-11T02:28:21.660Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering: SELECT_INTENT
2026-05-11T02:28:21.665Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:21.673Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from SELECT_INTENT to ALERT.
2026-05-11T02:28:21.674Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering ALERT
2026-05-11T02:28:21.676Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: No transitions between SELECT_INTENT and ALERT
2026-05-11T02:28:21.723Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Brightness set to 0.4.
2026-05-11T02:28:23.808Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.RecLoop: utterance: hey jibo score: 267 walign: B020C088 palign: B0221A00 {"word_alignment":"829266368 829266496 hey 0.00 829266496 829266752 jibo 0.00 "}
2026-05-11T02:28:23.808Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.RecLoop: HJ: signal sent to ASR will be boosted 6.80093 dB
2026-05-11T02:28:23.808Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_RECOG_HJ_EVENT
2026-05-11T02:28:23.808Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.RecogSpeakerID: RecogSpeakerTD starting at 829266368
2026-05-11T02:28:23.810Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_RECOG_HJ_EVENT in 2 ms.
2026-05-10T21:28:23.812028-05:00 Royal-Current-Sage-Canvas jibo-audio-service[642,notice]: - P.AudioService: detection: {"ts":[829301,221062],"type":"hotphrase","id":328,"location":{"ts":[829301,23005],"possibilities":[{"channels":[0,12],"position":{"x":0.7560884356498718,"y":0.6167867183685303,"z":0.4347969889640808},"confidence":0.07057805359363556}]},"utterances":[]}
2026-05-11T02:28:23.815Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnResult: { global: true,\n message: '',\n status: 'INTERRUPTED',\n transID: 'tid-0b6ab9fa-4ce1-11f1-b472-5cf821ea55ae' }
2026-05-11T02:28:23.857Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from IDLE to COMMAND
2026-05-11T02:28:23.821Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: hjHeard
2026-05-11T02:28:23.851Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Hey Jibo'
2026-05-11T02:28:23.853Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'HJOrient' to achieve goal 'Hey Jibo'
2026-05-11T02:28:23.872Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action: Initial face: { x: 0.7560884356498718,\n y: 0.6167867183685303,\n z: 0.4347969889640808 } null
2026-05-11T02:28:23.914Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Received attendToTarget request
2026-05-11T02:28:23.946Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look rule has fired!
2026-05-11T02:28:23.948Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Switched Attention Rule:Command Look
2026-05-11T02:28:24.159Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.RecLoop: Speaker: 5c0b221fdf9d450019c5e255 score: 26.381 accepted: 1
2026-05-11T02:28:24.159Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_RECOG_SPEAKER_EVENT
2026-05-11T02:28:24.160Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_RECOG_SPEAKER_EVENT in 1 ms.
2026-05-10T21:28:24.161345-05:00 Royal-Current-Sage-Canvas jibo-audio-service[642,notice]: - P.AudioService: detection: {"ts":[829301,570352],"type":"jet_speaker_id","id":328,"data":{"speakers":[{"speaker":"5c0b221fdf9d450019c5e255","score":26.381040573120118,"accepted":true,"high_confidence":true}],"snr":23.380887985229493}}
2026-05-11T02:28:24.161Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter.ConvTechSpeakerID: Speaker ID: 5c0b221fdf9d450019c5e255 | accepted: true | confidence: true | score: 26.381040573120117
2026-05-11T02:28:24.165Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Most recent speaker accepted.
2026-05-11T02:28:24.231Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.LhubClient: Hub Client connection opened.
2026-05-11T02:28:24.231Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_CLIENT_CONNECT_RESULT
2026-05-11T02:28:24.232Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: [messageContext@1 gain="2.187997" requestID="GLOBAL" transID="tid-158cc626-4ce1-11f1-ab84-5cf821ea55ae"] C.Jetstream.LhubClient: Hub LISTEN request keystone log entry
2026-05-11T02:28:24.232Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,debug]: - C.Jetstream.LhubClient: Set Audio encoder to type: OGG_OPUS
2026-05-11T02:28:24.316Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_CLIENT_CONNECT_RESULT in 85 ms.
2026-05-11T02:28:24.327Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnStarted
2026-05-11T02:28:25.659Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look resolving with status:SUCCEEDED
2026-05-11T02:28:27.870Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Demand Face Detect found 1 faces
2026-05-10T21:28:28.050586-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::measure input from: voice with 1 hypotheses
2026-05-10T21:28:28.050670-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity::Measure voice Quality:23.3809 Id: 5c0b221fdf9d450019c5e255 Conf: 26.381
2026-05-10T21:28:28.050736-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion with 2 options from 1 inputs.
2026-05-10T21:28:28.050790-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion::updateIdentity Op: 5c0b221fdf9d450019c5e255 Score: 1 Op: NOT_TRAINED Score: 0.3
2026-05-10T21:28:28.050849-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: Identity Update Best Score: 1 Best ID: 5c0b221fdf9d450019c5e255
2026-05-10T21:28:28.050890-05:00 Royal-Current-Sage-Canvas jibo-lps-service[725,info]: - P.IdentityFusion: IdentityFusion CHANGING identity from UNKNOWN to 5c0b221fdf9d450019c5e255
2026-05-11T02:28:28.172Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Primary face selected (position based): 14003
2026-05-11T02:28:28.181Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Expression.Base.ResolveHandle: Someone tried to cancel ResolveHandle after it was resolved!
2026-05-11T02:28:28.187Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Received attendToTarget request
2026-05-11T02:28:28.215Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look rule has fired!
2026-05-11T02:28:28.217Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Asserting attention rule after interruption: Command Look
2026-05-11T02:28:28.365Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face started 14003
2026-05-11T02:28:28.368Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Emotion.Appraisal.IdentityRule: Appraising data from identity data: VISIBLE_FACE_STARTED
2026-05-11T02:28:29.123Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION attendToTarget Command Look resolving with status:SUCCEEDED
2026-05-11T02:28:29.157Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Primary face selected (entity match): 14003
2026-05-11T02:28:29.315Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_LISTEN
2026-05-11T02:28:29.316Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_LISTEN in 1 ms.
2026-05-11T02:28:29.316Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_EOS
2026-05-11T02:28:29.317Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_EOS in 1 ms.
2026-05-11T02:28:29.318Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: skillSwitch: { skillID: undefined,\n onRobot: undefined,\n isProactive: undefined,\n skipSurprises: true,\n transID: 'tid-158cc626-4ce1-11f1-ab84-5cf821ea55ae',\n data: \n ListenResult {\n asr: { confidence: 0.95, final: true, text: 'what\'s the news?' },\n nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n match: \n { cloudSkill: 'news',\n intent: 'news',\n rule: 'launch',\n score: 0.95,\n skipSurprises: true } } }
2026-05-11T02:28:29.335Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from COMMAND to IDLE
2026-05-11T02:28:29.324Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: globalTurnResult: { global: true,\n result: \n ListenResult {\n asr: { confidence: 0.95, final: true, text: 'what\'s the news?' },\n nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n match: \n { cloudSkill: 'news',\n intent: 'news',\n rule: 'launch',\n score: 0.95,\n skipSurprises: true } },\n status: 'SUCCEEDED',\n transID: 'tid-158cc626-4ce1-11f1-ab84-5cf821ea55ae' }
2026-05-11T02:28:29.328Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Jetstream: Jetstream: eos received
2026-05-11T02:28:29.330Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient: event waiter 'HJ Listen Complete'
2026-05-11T02:28:29.332Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient time to face: 4309
2026-05-11T02:28:29.332Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.HJOrient: HJOrient had initial face?: false
2026-05-11T02:28:29.336Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: skill relaunch command from Global Service { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:29.339Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:29.340Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:28:29.342Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/idle @be/nimbus
2026-05-11T02:28:29.343Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/idle
2026-05-11T02:28:29.344Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/idle
2026-05-11T02:28:29.345Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Stopping
2026-05-11T02:28:29.347Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to false
2026-05-11T02:28:29.348Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Clearing animation queue.
2026-05-11T02:28:29.356Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/idle
2026-05-11T02:28:29.357Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:29.361Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/idle
2026-05-11T02:28:29.363Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:29.374Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'HJOrient' with result: 'SUCCEEDED'
2026-05-11T02:28:29.391Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: phw_JM_HUB_SKILL_INFO
2026-05-11T02:28:29.391Z Royal-Current-Sage-Canvas jibo-jetstream-service[682,info]: - C.Jetstream.ListenLoop: Handled JM_HUB_SKILL_INFO in 0 ms.
2026-05-11T02:28:29.385Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/nimbus
2026-05-11T02:28:29.412Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from IDLE to ENGAGED
2026-05-11T02:28:29.392Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/nimbus''
2026-05-11T02:28:29.395Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/nimbus''
2026-05-10T21:28:29.485480-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS LEX
2026-05-10T21:28:29.485889-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get TTS Lex session start - 1750dfdf-214b-4b95-ae2c-7e5009287f43
2026-05-10T21:28:29.487076-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get TTS Lex session end - 1750dfdf-214b-4b95-ae2c-7e5009287f43
2026-05-11T02:28:29.402Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:28:29.404Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/nimbus
2026-05-10T21:28:29.512203-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS POS Tags
2026-05-10T21:28:29.512697-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session start - 1e0a1c56-95b2-4192-a4e9-2e5efada520a
2026-05-10T21:28:29.513134-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session end - 1e0a1c56-95b2-4192-a4e9-2e5efada520a
2026-05-11T02:28:29.405Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:29.409Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/idle @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:29.414Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/nimbus
2026-05-10T21:28:29.533410-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS POS Tags
2026-05-10T21:28:29.533896-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session start - 5c95da49-195b-46c9-820b-5ae6b79ec8af
2026-05-10T21:28:29.535627-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get POS Tags session end - 5c95da49-195b-46c9-820b-5ae6b79ec8af
2026-05-11T02:28:29.415Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/nimbus
2026-05-11T02:28:29.420Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Nimbus Opening
2026-05-10T21:28:29.569542-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: GET TTS Token times
2026-05-10T21:28:29.570444-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: {"tts":{"input_request":{"prompt":"<speak><STYLE set=\"NEUTRAL\"> <SPEAK> <BREAK size=\"0.35\"/> here are your headlines . space missions are preparing for new launches , climate and weather systems are staying active across the country , and artificial intelligence tools keep pushing into everyday products . </SPEAK> </STYLE></speak>","pitch":999.0,"speed":999.0,"pitchBandwidth":999.0,"mode":"ssml","outputMode":"stream","allPass":999.0,"enableDefaultVoice":"","framerate":999.0,"gvMCEP":999.0,"postfilter":999.0,"samplerate":999.0,"unvoicedvoiced":999.0,"voice":"griffin","locale":"en-us","volume":999.0,"whisper":"FALSE","cached":"TRUE","earlyStopTime":-1.0},"type":"token"}}
2026-05-11T02:28:29.423Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Awaiting Cloud Skill response...
2026-05-11T02:28:29.424Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/nimbus { nlu: \n { confidence: 0.95,\n entities: {},\n intent: 'news',\n rules: [ 'launch', 'globals/global_commands_launch' ] },\n asr: { text: '<user input removed>', confidence: 0.95 } }
2026-05-11T02:28:29.429Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Received Cloud Skill response.
2026-05-11T02:28:29.430Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Processing Cloud Skill response...
2026-05-11T02:28:29.431Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Recieved analytics from cloud skill.
2026-05-11T02:28:29.432Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Processed Cloud Skill response.
2026-05-11T02:28:29.433Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Executing Cloud Skill SLIM: NewsHeadline_AN_01
2026-05-11T02:28:29.460Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:29.469Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Speak request received
2026-05-11T02:28:29.472Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Processing speak request
2026-05-11T02:28:29.473Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Starting new speak session: 71f26c03-cf4e-455e-a5c5-fecc7a3c191e
2026-05-10T21:28:29.622562-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,warning]: - C.TTSService: TTSUtterance: Trying to create an empty phrase! Ignoring...
2026-05-11T02:28:30.145Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Switched Attention Rule:Engaged Primary Face
2026-05-10T21:28:30.174138-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS Get Tokens session end - 7c55d8e8-ebe7-4b3d-972d-bcfcd819694a
2026-05-11T02:28:30.210Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Pushing Speaking Attention Mode
2026-05-11T02:28:30.259Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to SPEAKING
2026-05-11T02:28:30.281Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Waiting for Embodied Listen to finish
2026-05-11T02:28:30.282Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Dispatching Timeline: 71f26c03-cf4e-455e-a5c5-fecc7a3c191e
2026-05-10T21:28:30.306092-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS session start - 4f10e29c-a860-417f-bb0f-9f1f12441e12
2026-05-10T21:28:30.306251-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: {"tts":{"input_request":{"prompt":"<speak><STYLE set=\"NEUTRAL\"> <SPEAK> <BREAK size=\"0.35\"/> here are your headlines . space missions are preparing for new launches , climate and weather systems are staying active across the country , and artificial intelligence tools keep pushing into everyday products . </SPEAK> </STYLE></speak>","pitch":999.0,"speed":999.0,"pitchBandwidth":999.0,"mode":"ssml","outputMode":"stream","allPass":999.0,"enableDefaultVoice":"","framerate":999.0,"gvMCEP":999.0,"postfilter":999.0,"samplerate":999.0,"unvoicedvoiced":999.0,"voice":"griffin","locale":"en-us","volume":999.0,"whisper":"FALSE","cached":"TRUE"},"type":"speak"}}
2026-05-10T21:28:30.306533-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS calling speak - 4f10e29c-a860-417f-bb0f-9f1f12441e12
2026-05-10T21:28:30.306589-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: Synthesizing cached
2026-05-11T02:28:30.995Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION AttentionManager not trying to do lookat, we have no dofs!!
2026-05-11T02:28:32.872Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Proactive.SignalFacePersisted: Persisting face entity ID 14003 has an identity of 5c0b221fdf9d450019c5e255
2026-05-11T02:28:34.148Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Switched Attention Rule:Speaking Primary Face
2026-05-11T02:28:34.563Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION AttentionManager not trying to do lookat, we have no dofs!!
2026-05-11T02:28:34.866Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Asserting attention rule after interruption: Speaking Primary Face
2026-05-11T02:28:35.270Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: visible face stopped 14003
2026-05-11T02:28:39.448Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: deleting person entity 14003
2026-05-10T21:28:42.032661-05:00 Royal-Current-Sage-Canvas jibo-tts-service[710,info]: - C.TTSService: TTS session end - 4f10e29c-a860-417f-bb0f-9f1f12441e12
2026-05-11T02:28:42.615Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Timeline Dispatch Complete: 71f26c03-cf4e-455e-a5c5-fecc7a3c191e
2026-05-11T02:28:42.621Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from SPEAKING to ENGAGED
2026-05-11T02:28:42.628Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Speak Complete: 71f26c03-cf4e-455e-a5c5-fecc7a3c191e
2026-05-11T02:28:42.630Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Cleaning up session
2026-05-11T02:28:42.632Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Ready for next speak request
2026-05-11T02:28:42.634Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Embodied.Speech: Stop request received
2026-05-11T02:28:42.637Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:42.644Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: requested skill switch @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:42.648Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: no pending skill. interrupting current skill
2026-05-11T02:28:42.668Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: switching skill @be/nimbus @be/idle
2026-05-11T02:28:42.669Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting close skill @be/nimbus
2026-05-11T02:28:42.670Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: stopping @be/nimbus
2026-05-11T02:28:42.670Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Nimbus: Nimbus Closing
2026-05-11T02:28:42.672Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.TimerSpy: The current skill cleaned up all timers @be/nimbus
2026-05-11T02:28:42.673Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:42.677Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: ending close skill @be/nimbus
2026-05-11T02:28:42.678Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: deferring to action system with pending skill: @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:42.706Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: waiting on action system @be/idle
2026-05-11T02:28:42.762Z Royal-Current-Sage-Canvas exp[786,info]: [versions@1 release="1.9.2"] T.SSM.Svc.Exp.AU: ATTENTION Attention Mode changed from ENGAGED to IDLE
2026-05-11T02:28:42.711Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action: Incoming new goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:28:42.724Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Taking action: 'Be Skill Switch Action' to achieve goal 'Be Skill Switch Goal: '@be/idle''
2026-05-11T02:28:42.734Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Action.Action.GoalDrivenAction: Completed action: 'Be Skill Switch Action' with result: 'SUCCEEDED'
2026-05-11T02:28:42.735Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: action system reported accomplished goal @be/idle
2026-05-11T02:28:42.737Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: starting skill open @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:42.750Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: BeSkill open @be/nimbus @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:42.757Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: new skill preload @be/idle
2026-05-11T02:28:42.761Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchUtil: opening new skill @be/idle
2026-05-11T02:28:42.762Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.SF.ServiceClients.Identity.DataConverter: Returning Speaker 5c0b221fdf9d450019c5e255.
2026-05-11T02:28:42.768Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: adding listener for SLEEP
2026-05-11T02:28:42.770Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Jibo.Events.Global: setting SLEEP to true
2026-05-11T02:28:42.771Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Starting
2026-05-11T02:28:42.775Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from ALERT to SELECT_INTENT.
2026-05-11T02:28:42.776Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering: SELECT_INTENT
2026-05-11T02:28:42.781Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.SkillSwitchScheduler: skill open success @be/idle { exitOptions: {}, asr: { text: '', confidence: 1 } }
2026-05-11T02:28:42.785Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: State changed from SELECT_INTENT to ALERT.
2026-05-11T02:28:42.786Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Entering ALERT
2026-05-11T02:28:42.789Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: No transitions between SELECT_INTENT and ALERT
2026-05-11T02:28:42.843Z Royal-Current-Sage-Canvas be[1017,info]: [versions@1 release="1.9.2"] T.Be.Idle: Brightness set to 0.4.
#

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

Some files were not shown because too many files have changed in this diff Show More