fixes for hey jibo

This commit is contained in:
Jacob Dubin
2026-04-18 21:13:45 -05:00
parent 5dbe16a0e1
commit 25d5ab1e43
3 changed files with 69 additions and 1 deletions

View File

@@ -260,6 +260,7 @@ public sealed class WebSocketTurnFinalizationService(
(hotphrase.ValueKind == JsonValueKind.True || hotphrase.ValueKind == JsonValueKind.False))
{
turnState.ListenHotphrase = hotphrase.GetBoolean();
turnState.HotphraseEmptyTurnCount = 0;
}
if (data.TryGetProperty("intent", out var intent) && intent.ValueKind == JsonValueKind.String)
@@ -310,6 +311,7 @@ public sealed class WebSocketTurnFinalizationService(
turnState.SawListen = false;
turnState.SawContext = false;
turnState.ListenHotphrase = false;
turnState.HotphraseEmptyTurnCount = 0;
turnState.ListenRules = [];
turnState.ListenAsrHints = [];
}
@@ -364,6 +366,32 @@ public sealed class WebSocketTurnFinalizationService(
return [];
}
if (ShouldIgnoreInitialEmptyHotphraseTurn(finalizedTurn, turnState))
{
turnState.HotphraseEmptyTurnCount += 1;
turnState.AwaitingTurnCompletion = true;
return
[
new WebSocketReply
{
Text = JsonSerializer.Serialize(new
{
type = "OPENJIBO_TURN_PENDING",
data = new
{
sessionId = session.SessionId,
transID = session.LastTransId,
bufferedAudioBytes = turnState.BufferedAudioBytes,
bufferedAudioChunks = turnState.BufferedAudioChunkCount,
awaitingAudio = turnState.BufferedAudioBytes == 0,
awaitingTranscriptHint = turnState.BufferedAudioBytes > 0 && string.IsNullOrWhiteSpace(turnState.AudioTranscriptHint),
finalizeAttempts = turnState.FinalizeAttemptCount
}
})
}
];
}
if (ShouldTreatEmptyHotphraseTurnAsGreeting(finalizedTurn))
{
finalizedTurn = WithSyntheticTranscript(finalizedTurn, "hello");
@@ -689,6 +717,33 @@ public sealed class WebSocketTurnFinalizationService(
.Any(static rule => string.Equals(rule, "launch", StringComparison.OrdinalIgnoreCase));
}
private static bool ShouldIgnoreInitialEmptyHotphraseTurn(TurnContext turn, WebSocketTurnState turnState)
{
if (!string.IsNullOrWhiteSpace(turn.NormalizedTranscript) || !string.IsNullOrWhiteSpace(turn.RawTranscript))
{
return false;
}
var messageType = ReadMessageType(turn);
if (messageType is not ("CLIENT_ASR" or "CLIENT_NLU"))
{
return false;
}
if (!ReadBoolAttribute(turn, "listenHotphrase"))
{
return false;
}
if (turnState.HotphraseEmptyTurnCount > 0)
{
return false;
}
return ReadRules(turn, "listenRules")
.Any(static rule => string.Equals(rule, "launch", StringComparison.OrdinalIgnoreCase));
}
private static TurnContext WithSyntheticTranscript(TurnContext turn, string transcript)
{
var attributes = new Dictionary<string, object?>(turn.Attributes, StringComparer.OrdinalIgnoreCase)

View File

@@ -5,6 +5,7 @@ public sealed class WebSocketTurnState
public string? TransId { get; set; }
public string? ContextPayload { get; set; }
public bool ListenHotphrase { get; set; }
public int HotphraseEmptyTurnCount { get; set; }
public string? AudioTranscriptHint { get; set; }
public string? LastSttError { get; set; }
public DateTimeOffset? LastSttErrorUtc { get; set; }

View File

@@ -573,7 +573,7 @@ public sealed class JiboWebSocketServiceTests
}
[Fact]
public async Task EmptyHotphraseTurn_BecomesGreetingAndKeepsFollowUpOpen()
public async Task SecondEmptyHotphraseTurn_BecomesGreetingAndKeepsFollowUpOpen()
{
await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
@@ -584,6 +584,18 @@ public sealed class JiboWebSocketServiceTests
Text = """{"type":"LISTEN","transID":"trans-empty-hotphrase","data":{"hotphrase":true,"rules":["launch","globals/global_commands_launch"]}}"""
});
var firstReplies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",
Path = "/listen",
Kind = "neo-hub-listen",
Token = "hub-empty-hotphrase-token",
Text = """{"type":"CLIENT_ASR","transID":"trans-empty-hotphrase","data":{}}"""
});
Assert.Single(firstReplies);
Assert.Equal("OPENJIBO_TURN_PENDING", ReadReplyType(firstReplies[0]));
var replies = await _service.HandleMessageAsync(new WebSocketMessageEnvelope
{
HostName = "neo-hub.jibo.com",