more messaging updates
This commit is contained in:
@@ -146,6 +146,11 @@ The current evidence in captures, fixtures, and Node behavior supports three mai
|
||||
|
||||
Those are the right primary buckets for now. Additional side channels may still emerge later, especially around proactive traffic, direct skill/service sockets, or future on-device OS changes, but they should be treated as extensions to this model until captures prove otherwise.
|
||||
|
||||
Latest stock-OS WOD findings:
|
||||
|
||||
- `word-of-the-day/right_word` closeout should not emit a synthetic `match`; otherwise Jetstream promotes it into `globalTurnResult` and Global Service relaunches Nimbus a few seconds later with a `Cloud Skill Response Timeout`.
|
||||
- Voice `play word of the day` hotphrase launch still enters Global Service first, so a synthetic `LISTEN` result alone is not enough. The next-most-correct transport hint is a direct `SKILL_REDIRECT` event aimed at `@be/word-of-the-day`, alongside the menu-shaped `LISTEN` payload.
|
||||
|
||||
## Speech, Animation, And ESML
|
||||
|
||||
The current joke flow is only a small foothold into Jibo expressiveness.
|
||||
|
||||
@@ -82,6 +82,19 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
}))
|
||||
};
|
||||
|
||||
if (isWordOfDayLaunch)
|
||||
{
|
||||
messages.Add(new SocketReplyPlan(
|
||||
JsonSerializer.Serialize(BuildSkillRedirectPayload(
|
||||
transId,
|
||||
"@be/word-of-the-day",
|
||||
outboundIntent,
|
||||
outboundAsrText,
|
||||
outboundRules,
|
||||
entities)),
|
||||
DelayMs: 75));
|
||||
}
|
||||
|
||||
if (emitSkillActions && speak is not null)
|
||||
{
|
||||
messages.Add(new SocketReplyPlan(
|
||||
@@ -165,12 +178,6 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
intent = string.Empty,
|
||||
rules,
|
||||
entities = new Dictionary<string, object?>()
|
||||
},
|
||||
match = new
|
||||
{
|
||||
intent = string.Empty,
|
||||
rule = rules.FirstOrDefault() ?? string.Empty,
|
||||
score = 0.95
|
||||
}
|
||||
}
|
||||
})),
|
||||
@@ -522,6 +529,44 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
};
|
||||
}
|
||||
|
||||
private static object BuildSkillRedirectPayload(
|
||||
string transId,
|
||||
string skillId,
|
||||
string outboundIntent,
|
||||
string outboundAsrText,
|
||||
IReadOnlyList<string> outboundRules,
|
||||
object entities)
|
||||
{
|
||||
return new
|
||||
{
|
||||
type = "SKILL_REDIRECT",
|
||||
ts = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
|
||||
msgID = CreateHubMessageId(),
|
||||
transID = transId,
|
||||
data = new
|
||||
{
|
||||
match = new
|
||||
{
|
||||
skillID = skillId,
|
||||
onRobot = true,
|
||||
launch = true
|
||||
},
|
||||
asr = new
|
||||
{
|
||||
text = outboundAsrText,
|
||||
confidence = 0.95
|
||||
},
|
||||
nlu = new
|
||||
{
|
||||
confidence = 0.95,
|
||||
intent = outboundIntent,
|
||||
rules = outboundRules,
|
||||
entities
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private static string EscapeXml(string value)
|
||||
{
|
||||
return value
|
||||
|
||||
@@ -469,7 +469,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task ClientAsr_WordOfDayLaunch_EmitsMenuStyleLoadMenuWithSkillAction()
|
||||
public async Task ClientAsr_WordOfDayLaunch_EmitsMenuStyleLoadMenuAndRedirect()
|
||||
{
|
||||
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||
{
|
||||
@@ -489,13 +489,19 @@ public sealed class JiboWebSocketServiceTests
|
||||
Text = """{"type":"CLIENT_ASR","transID":"trans-wod-launch","data":{"text":"Play word of the day."}}"""
|
||||
});
|
||||
|
||||
Assert.Equal(2, replies.Count);
|
||||
Assert.Equal(3, replies.Count);
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal("menu", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||
Assert.Equal(string.Empty, listenPayload.RootElement.GetProperty("data").GetProperty("asr").GetProperty("text").GetString());
|
||||
Assert.Equal("word-of-the-day", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("entities").GetProperty("domain").GetString());
|
||||
Assert.Equal("@be/word-of-the-day", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("skill").GetString());
|
||||
Assert.Equal("word-of-the-day/menu", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
|
||||
Assert.Equal("SKILL_REDIRECT", ReadReplyType(replies[2]));
|
||||
|
||||
using var redirectPayload = JsonDocument.Parse(replies[2].Text!);
|
||||
Assert.Equal("@be/word-of-the-day", redirectPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("skillID").GetString());
|
||||
Assert.True(redirectPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("onRobot").GetBoolean());
|
||||
Assert.True(redirectPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("launch").GetBoolean());
|
||||
|
||||
var session = _store.FindSessionByToken("hub-wod-launch-token");
|
||||
Assert.NotNull(session);
|
||||
@@ -551,9 +557,10 @@ public sealed class JiboWebSocketServiceTests
|
||||
Binary = new byte[3000]
|
||||
});
|
||||
|
||||
Assert.Equal(2, replies.Count);
|
||||
Assert.Equal(3, replies.Count);
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
Assert.Equal("SKILL_REDIRECT", ReadReplyType(replies[2]));
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal("menu", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||
@@ -632,6 +639,9 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.Equal(2, replies.Count);
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.False(listenPayload.RootElement.GetProperty("data").TryGetProperty("match", out _));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -682,7 +692,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal(string.Empty, listenPayload.RootElement.GetProperty("data").GetProperty("asr").GetProperty("text").GetString());
|
||||
Assert.Equal("word-of-the-day/right_word", listenPayload.RootElement.GetProperty("data").GetProperty("match").GetProperty("rule").GetString());
|
||||
Assert.False(listenPayload.RootElement.GetProperty("data").TryGetProperty("match", out _));
|
||||
|
||||
var binaryReplies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user