fixes for test paths
This commit is contained in:
@@ -72,6 +72,7 @@ The current .NET pass covers only a narrow, explicitly synthetic subset of obser
|
||||
- `CLIENT_NLU` turn completion using remembered listen/session metadata
|
||||
- `CLIENT_ASR` turn completion, including a synthetic STT seam for buffered-audio replay
|
||||
- `EOS` emission after completed turns
|
||||
- delayed `SKILL_ACTION` emission after `EOS` on completed turn flows to better match the Node oracle timing
|
||||
- first richer vertical slice for joke/chat `SKILL_ACTION` playback
|
||||
|
||||
This does not yet mean parity for:
|
||||
|
||||
@@ -76,6 +76,7 @@ Current websocket scope is still intentionally narrow:
|
||||
- structured websocket telemetry and live-run fixture export
|
||||
- `CONTEXT` capture and follow-up turn state
|
||||
- `EOS` completion
|
||||
- delayed `SKILL_ACTION` emission after `EOS` to preserve the current Node-observed turn sequence
|
||||
- first skill vertical for joke/chat `SKILL_ACTION` playback
|
||||
- repo-root live-run capture support for both `captures/http/` and `captures/websocket/`
|
||||
|
||||
|
||||
@@ -86,6 +86,11 @@ app.Use(async (context, next) =>
|
||||
continue;
|
||||
}
|
||||
|
||||
if (reply.DelayMs > 0)
|
||||
{
|
||||
await Task.Delay(reply.DelayMs, context.RequestAborted);
|
||||
}
|
||||
|
||||
var payload = Encoding.UTF8.GetBytes(reply.Text);
|
||||
await socket.SendAsync(payload, WebSocketMessageType.Text, true, context.RequestAborted);
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ namespace Jibo.Cloud.Application.Services;
|
||||
|
||||
public sealed class ResponsePlanToSocketMessagesMapper
|
||||
{
|
||||
public IReadOnlyList<string> Map(ResponsePlan plan, TurnContext turn, CloudSession session, bool emitSkillActions)
|
||||
public IReadOnlyList<SocketReplyPlan> Map(ResponsePlan plan, TurnContext turn, CloudSession session, bool emitSkillActions)
|
||||
{
|
||||
var speak = plan.Actions.OfType<SpeakAction>().FirstOrDefault();
|
||||
var skill = plan.Actions.OfType<InvokeNativeSkillAction>().FirstOrDefault();
|
||||
@@ -15,9 +15,9 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
: session.LastTransId ?? string.Empty;
|
||||
var transcript = turn.NormalizedTranscript ?? turn.RawTranscript ?? string.Empty;
|
||||
var rules = ReadRules(turn);
|
||||
var messages = new List<string>();
|
||||
var messages = new List<SocketReplyPlan>();
|
||||
|
||||
messages.Add(JsonSerializer.Serialize(new
|
||||
messages.Add(new SocketReplyPlan(JsonSerializer.Serialize(new
|
||||
{
|
||||
type = "LISTEN",
|
||||
transID = transId,
|
||||
@@ -43,9 +43,9 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
score = 0.95
|
||||
}
|
||||
}
|
||||
}));
|
||||
})));
|
||||
|
||||
messages.Add(JsonSerializer.Serialize(new
|
||||
messages.Add(new SocketReplyPlan(JsonSerializer.Serialize(new
|
||||
{
|
||||
type = "EOS",
|
||||
data = new
|
||||
@@ -53,21 +53,23 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
sessionId = plan.SessionId,
|
||||
transID = transId
|
||||
}
|
||||
}));
|
||||
})));
|
||||
|
||||
if (emitSkillActions && speak is not null)
|
||||
{
|
||||
messages.Add(JsonSerializer.Serialize(BuildSkillPayload(plan, turn, transId, speak, skill)));
|
||||
messages.Add(new SocketReplyPlan(
|
||||
JsonSerializer.Serialize(BuildSkillPayload(plan, turn, transId, speak, skill)),
|
||||
DelayMs: 75));
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
public IReadOnlyList<string> MapFallback(CloudSession session, string transId, IReadOnlyList<string> rules)
|
||||
public IReadOnlyList<SocketReplyPlan> MapFallback(CloudSession session, string transId, IReadOnlyList<string> rules)
|
||||
{
|
||||
return
|
||||
[
|
||||
JsonSerializer.Serialize(new
|
||||
new SocketReplyPlan(JsonSerializer.Serialize(new
|
||||
{
|
||||
type = "LISTEN",
|
||||
transID = transId,
|
||||
@@ -93,8 +95,8 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
score = 0.95
|
||||
}
|
||||
}
|
||||
}),
|
||||
JsonSerializer.Serialize(new
|
||||
})),
|
||||
new SocketReplyPlan(JsonSerializer.Serialize(new
|
||||
{
|
||||
type = "EOS",
|
||||
data = new
|
||||
@@ -102,8 +104,8 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
sessionId = session.SessionId,
|
||||
transID = transId
|
||||
}
|
||||
}),
|
||||
JsonSerializer.Serialize(BuildGenericFallbackSkillPayload(transId))
|
||||
})),
|
||||
new SocketReplyPlan(JsonSerializer.Serialize(BuildGenericFallbackSkillPayload(transId)), DelayMs: 75)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -231,4 +233,6 @@ public sealed class ResponsePlanToSocketMessagesMapper
|
||||
.Replace("\"", """, StringComparison.Ordinal)
|
||||
.Replace("'", "'", StringComparison.Ordinal);
|
||||
}
|
||||
|
||||
public sealed record SocketReplyPlan(string Text, int DelayMs = 0);
|
||||
}
|
||||
|
||||
@@ -269,7 +269,7 @@ public sealed class WebSocketTurnFinalizationService(
|
||||
session.LastIntent = "heyJibo";
|
||||
session.LastListenType = "fallback";
|
||||
var fallbackReplies = replyMapper.MapFallback(session, turnState.TransId ?? session.LastTransId ?? string.Empty, turnState.ListenRules)
|
||||
.Select(text => new WebSocketReply { Text = text })
|
||||
.Select(map => new WebSocketReply { Text = map.Text, DelayMs = map.DelayMs })
|
||||
.ToArray();
|
||||
ResetBufferedAudio(session);
|
||||
return fallbackReplies;
|
||||
@@ -308,9 +308,10 @@ public sealed class WebSocketTurnFinalizationService(
|
||||
turnState.AwaitingTurnCompletion = false;
|
||||
|
||||
var emitSkillActions = messageType != "CLIENT_NLU";
|
||||
var replies = replyMapper.Map(plan, finalizedTurn, session, emitSkillActions).Select(text => new WebSocketReply
|
||||
var replies = replyMapper.Map(plan, finalizedTurn, session, emitSkillActions).Select(map => new WebSocketReply
|
||||
{
|
||||
Text = text
|
||||
Text = map.Text,
|
||||
DelayMs = map.DelayMs
|
||||
}).ToArray();
|
||||
|
||||
ResetBufferedAudio(session);
|
||||
|
||||
@@ -3,5 +3,6 @@ namespace Jibo.Cloud.Domain.Models;
|
||||
public sealed class WebSocketReply
|
||||
{
|
||||
public string? Text { get; init; }
|
||||
public int DelayMs { get; init; }
|
||||
public bool Close { get; init; }
|
||||
}
|
||||
|
||||
@@ -49,6 +49,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
Assert.Equal("SKILL_ACTION", ReadReplyType(replies[2]));
|
||||
Assert.Equal(75, replies[2].DelayMs);
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal("hello jibo", listenPayload.RootElement.GetProperty("data").GetProperty("asr").GetProperty("text").GetString());
|
||||
@@ -124,6 +125,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
Assert.Equal("SKILL_ACTION", ReadReplyType(replies[2]));
|
||||
Assert.Equal(75, replies[2].DelayMs);
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal("tell me a joke", listenPayload.RootElement.GetProperty("data").GetProperty("asr").GetProperty("text").GetString());
|
||||
@@ -180,6 +182,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.Equal("LISTEN", ReadReplyType(replies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(replies[1]));
|
||||
Assert.Equal("SKILL_ACTION", ReadReplyType(replies[2]));
|
||||
Assert.Equal(75, replies[2].DelayMs);
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(replies[0].Text!);
|
||||
Assert.Equal("heyJibo", listenPayload.RootElement.GetProperty("data").GetProperty("nlu").GetProperty("intent").GetString());
|
||||
@@ -324,6 +327,7 @@ public sealed class JiboWebSocketServiceTests
|
||||
Assert.Equal("LISTEN", ReadReplyType(finalizeReplies[0]));
|
||||
Assert.Equal("EOS", ReadReplyType(finalizeReplies[1]));
|
||||
Assert.Equal("SKILL_ACTION", ReadReplyType(finalizeReplies[2]));
|
||||
Assert.Equal(75, finalizeReplies[2].DelayMs);
|
||||
|
||||
using var listenPayload = JsonDocument.Parse(finalizeReplies[0].Text!);
|
||||
Assert.Equal("tell me a joke", listenPayload.RootElement.GetProperty("data").GetProperty("asr").GetProperty("text").GetString());
|
||||
|
||||
Reference in New Issue
Block a user