Skip to content

Commit 5e6ab93

Browse files
ochafikclaude
andcommitted
debug(say-server): add logging to track queue lifecycle
Add console logging to debug why end_tts_queue might not be called: Widget-side: - Log queueId in ontoolinputpartial, ontoolinput, ontoolresult - Log when new session is detected (queue reset) - Log when initTTSQueue fails - Log when end_tts_queue is called/not called Server-side: - Log when end_tts_queue is called - Log warnings for unknown queues - Log info for already-ended queues This will help identify if the issue is: - User interruption (ontoolresult never called) - Session reset (queueId becomes null) - Host bug (callback dropped) 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 90fe8f5 commit 5e6ab93

1 file changed

Lines changed: 22 additions & 7 deletions

File tree

examples/say-server/server.py

Lines changed: 22 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -271,8 +271,10 @@ def end_tts_queue(queue_id: str) -> list[types.TextContent]:
271271
"""
272272
state = tts_queues.get(queue_id)
273273
if not state:
274+
logger.warning(f"end_tts_queue called for unknown queue: {queue_id}")
274275
return [types.TextContent(type="text", text='{"error": "Queue not found"}')]
275276
if state.end_signaled:
277+
logger.info(f"end_tts_queue called for already-ended queue: {queue_id}")
276278
return [types.TextContent(type="text", text='{"already_ended": true}')]
277279

278280
state.end_signaled = True
@@ -282,6 +284,7 @@ def end_tts_queue(queue_id: str) -> list[types.TextContent]:
282284
except asyncio.QueueFull:
283285
pass
284286

287+
logger.info(f"end_tts_queue called for queue: {queue_id}")
285288
return [types.TextContent(type="text", text='{"ended": true}')]
286289

287290

@@ -1104,23 +1107,26 @@ def generate_sync():
11041107
onAppCreated: (app) => {
11051108
appRef.current = app;
11061109
app.ontoolinputpartial = async (params) => {
1107-
console.log('[TTS] ontoolinputpartial called');
1110+
console.log('[TTS] ontoolinputpartial called, queueId:', queueIdRef.current);
11081111
const newText = params.arguments?.text;
11091112
if (!newText) return;
11101113
// Detect new session: text doesn't continue from where we left off
11111114
const isNewSession = lastTextRef.current.length > 0 && !newText.startsWith(lastTextRef.current);
1112-
if (isNewSession) console.log('[TTS] new session detected in partial');
11131115
if (isNewSession) {
1116+
console.log('[TTS] new session detected in partial - resetting queue');
11141117
// Reset for new session
11151118
queueIdRef.current = null;
11161119
lastTextRef.current = "";
11171120
}
11181121
setDisplayText(newText);
1119-
if (!queueIdRef.current && !(await initTTSQueue())) return;
1122+
if (!queueIdRef.current && !(await initTTSQueue())) {
1123+
console.log('[TTS] initTTSQueue failed in partial');
1124+
return;
1125+
}
11201126
await sendTextToTTS(newText);
11211127
};
11221128
app.ontoolinput = async (params) => {
1123-
console.log('[TTS] ontoolinput called');
1129+
console.log('[TTS] ontoolinput called, queueId:', queueIdRef.current);
11241130
const text = params.arguments?.text;
11251131
if (!text) return;
11261132
// Read voice setting (defaults to cosette)
@@ -1131,16 +1137,20 @@ def generate_sync():
11311137
setAutoPlay(shouldAutoPlay);
11321138
// Detect new session: text doesn't continue from where we left off
11331139
const isNewSession = lastTextRef.current.length > 0 && !text.startsWith(lastTextRef.current);
1134-
if (isNewSession) console.log('[TTS] new session detected in input');
11351140
if (isNewSession) {
1141+
console.log('[TTS] new session detected in input - resetting queue');
11361142
queueIdRef.current = null;
11371143
lastTextRef.current = "";
11381144
}
11391145
setDisplayText(text);
1140-
if (!queueIdRef.current && !(await initTTSQueue())) return;
1146+
if (!queueIdRef.current && !(await initTTSQueue())) {
1147+
console.log('[TTS] initTTSQueue failed in input');
1148+
return;
1149+
}
11411150
await sendTextToTTS(text);
11421151
};
11431152
app.ontoolresult = async (params) => {
1153+
console.log('[TTS] ontoolresult called, queueId:', queueIdRef.current);
11441154
fullTextRef.current = lastTextRef.current;
11451155
// Read widget UUID from tool result _meta for speak lock coordination
11461156
const resultUuid = params.content?.[0]?._meta?.widgetUUID;
@@ -1149,8 +1159,13 @@ def generate_sync():
11491159
console.log('[TTS] Widget UUID:', resultUuid);
11501160
}
11511161
if (queueIdRef.current) {
1162+
console.log('[TTS] Calling end_tts_queue for:', queueIdRef.current);
11521163
try { await app.callServerTool({ name: "end_tts_queue", arguments: { queue_id: queueIdRef.current } }); }
1153-
catch (err) {}
1164+
catch (err) {
1165+
console.log('[TTS] end_tts_queue error:', err);
1166+
}
1167+
} else {
1168+
console.log('[TTS] No queueId to end in ontoolresult');
11541169
}
11551170
// DON'T reset here - let audio continue playing
11561171
// New session detection happens in ontoolinputpartial via text comparison

0 commit comments

Comments
 (0)