try and make skill launch mimic source code better

This commit is contained in:
Jacob Dubin
2026-04-19 08:17:28 -05:00
parent 17583e3cdc
commit bacaa6f2ca
16 changed files with 6071 additions and 81 deletions

View File

@@ -230,9 +230,8 @@ public sealed class JiboInteractionService(
"@be/word-of-the-day",
SkillPayload: new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["destination"] = "word-of-the-day",
["skillId"] = "@be/word-of-the-day",
["cloudResponseMode"] = "completion_only"
["domain"] = "word-of-the-day",
["skillId"] = "@be/word-of-the-day"
});
}

View File

@@ -26,7 +26,7 @@ public sealed class ResponsePlanToSocketMessagesMapper
var nluGuess = ReadClientEntity(turn, "guess");
var wordOfDayGuess = ResolveWordOfDayGuess(turn, transcript, nluGuess);
var outboundIntent = isWordOfDayLaunch
? "loadMenu"
? "menu"
: isWordOfDayGuess
? "guess"
: string.Equals(messageType, "CLIENT_NLU", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(clientIntent)
@@ -34,6 +34,8 @@ public sealed class ResponsePlanToSocketMessagesMapper
: plan.IntentName ?? "unknown";
var outboundAsrText = isWordOfDayGuess && !string.IsNullOrWhiteSpace(wordOfDayGuess)
? wordOfDayGuess
: isWordOfDayLaunch
? string.Empty
: string.Equals(clientIntent, "guess", StringComparison.OrdinalIgnoreCase) && !string.IsNullOrWhiteSpace(nluGuess)
? nluGuess
: isYesNoTurn && isYesNoIntent
@@ -42,72 +44,30 @@ public sealed class ResponsePlanToSocketMessagesMapper
? clientIntent
: transcript;
var outboundRules = isWordOfDayLaunch
? ["main-menu/execute_fun_stuff"]
? ["word-of-the-day/menu"]
: isYesNoTurn && isYesNoIntent ? [yesNoCreateRule!] : rules;
var entities = ReadEntities(turn, messageType, isYesNoTurn && isYesNoIntent, isWordOfDayLaunch, isWordOfDayGuess, wordOfDayGuess);
object listenMessage;
if (isWordOfDayLaunch)
var listenMessage = new
{
listenMessage = new
type = "LISTEN",
transID = transId,
data = new
{
type = "LISTEN",
transID = transId,
skillID = "@be/word-of-the-day",
onRobot = true,
data = new
asr = new
{
asr = new
{
confidence = 0.95,
final = true,
text = outboundAsrText
},
nlu = new
{
confidence = 0.95,
intent = outboundIntent,
rules = outboundRules,
entities
},
match = new
{
intent = outboundIntent,
rule = outboundRules.FirstOrDefault() ?? string.Empty,
score = 0.95
}
}
};
}
else
{
listenMessage = new
{
type = "LISTEN",
transID = transId,
data = new
confidence = 0.95,
final = true,
text = outboundAsrText
},
nlu = BuildNluPayload(outboundIntent, outboundRules, entities, isWordOfDayLaunch ? "@be/word-of-the-day" : null),
match = new
{
asr = new
{
confidence = 0.95,
final = true,
text = outboundAsrText
},
nlu = new
{
confidence = 0.95,
intent = outboundIntent,
rules = outboundRules,
entities
},
match = new
{
intent = outboundIntent,
rule = outboundRules.FirstOrDefault() ?? string.Empty,
score = 0.95
}
intent = outboundIntent,
rule = outboundRules.FirstOrDefault() ?? string.Empty,
score = 0.95
}
};
}
}
};
var messages = new List<SocketReplyPlan>
{
@@ -222,7 +182,7 @@ public sealed class ResponsePlanToSocketMessagesMapper
{
return new Dictionary<string, object?>
{
["destination"] = "word-of-the-day"
["domain"] = "word-of-the-day"
};
}
@@ -410,6 +370,28 @@ public sealed class ResponsePlanToSocketMessagesMapper
};
}
private static IReadOnlyDictionary<string, object?> BuildNluPayload(
string outboundIntent,
IReadOnlyList<string> outboundRules,
object entities,
string? skillId)
{
var payload = new Dictionary<string, object?>(StringComparer.OrdinalIgnoreCase)
{
["confidence"] = 0.95,
["intent"] = outboundIntent,
["rules"] = outboundRules,
["entities"] = entities
};
if (!string.IsNullOrWhiteSpace(skillId))
{
payload["skill"] = skillId;
}
return payload;
}
private static object BuildGenericFallbackSkillPayload(string transId)
{
return new

View File

@@ -44,6 +44,14 @@ public sealed class WebSocketTurnFinalizationService(
return [];
}
if (!turnState.AwaitingTurnCompletion &&
!session.FollowUpOpen &&
!turnState.SawListen &&
!string.IsNullOrWhiteSpace(turnState.TransId))
{
return [];
}
session.LastMessageType = "BINARY_AUDIO";
turnState.FirstAudioReceivedUtc ??= DateTimeOffset.UtcNow;
turnState.BufferedAudioChunkCount += 1;
@@ -140,6 +148,8 @@ public sealed class WebSocketTurnFinalizationService(
session.TurnState.IgnoreAdditionalAudioUntilUtc = DateTimeOffset.UtcNow.Add(WebSocketTurnState.DefaultLateAudioIgnoreWindow);
session.FollowUpExpiresUtc = null;
ResetBufferedAudio(session);
session.TurnState.SawListen = false;
session.TurnState.SawContext = false;
return ResponsePlanToSocketMessagesMapper.MapCompletionOnly(
session.TurnState.TransId ?? session.LastTransId ?? string.Empty,
"@be/word-of-the-day")
@@ -421,6 +431,8 @@ public sealed class WebSocketTurnFinalizationService(
turnState.IgnoreAdditionalAudioUntilUtc = DateTimeOffset.UtcNow.Add(WebSocketTurnState.DefaultLateAudioIgnoreWindow);
session.FollowUpExpiresUtc = null;
ResetBufferedAudio(session);
turnState.SawListen = false;
turnState.SawContext = false;
return [];
}
@@ -521,9 +533,9 @@ public sealed class WebSocketTurnFinalizationService(
? null
: DateTimeOffset.UtcNow.Add(WebSocketTurnState.DefaultLateAudioIgnoreWindow);
var emitSkillActions = messageType != "CLIENT_NLU" ||
string.Equals(plan.IntentName, "word_of_the_day", StringComparison.OrdinalIgnoreCase) ||
string.Equals(plan.IntentName, "word_of_the_day_guess", StringComparison.OrdinalIgnoreCase);
var emitSkillActions = !string.Equals(plan.IntentName, "word_of_the_day", StringComparison.OrdinalIgnoreCase) &&
(messageType != "CLIENT_NLU" ||
string.Equals(plan.IntentName, "word_of_the_day_guess", StringComparison.OrdinalIgnoreCase));
var replies = ResponsePlanToSocketMessagesMapper.Map(plan, finalizedTurn, session, emitSkillActions).Select(map => new WebSocketReply
{
Text = map.Text,
@@ -531,6 +543,8 @@ public sealed class WebSocketTurnFinalizationService(
}).ToArray();
ResetBufferedAudio(session);
turnState.SawListen = false;
turnState.SawContext = false;
return replies;
}