From eda88f83f3f6c81116f1be95219ff9b75f913d0b Mon Sep 17 00:00:00 2001 From: hailin Date: Mon, 6 Apr 2026 09:30:55 -0700 Subject: [PATCH] =?UTF-8?q?fix:=20send=20system=20idle=20instead=20of=20tt?= =?UTF-8?q?s=20stop=20to=20avoid=20Speaking=E2=86=92Listening=20race?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause: tts stop triggers Speaking→Listening, which calls SendStartListening in HandleStateChangedEvent. idle arrives too late and gets overridden. Fix: skip tts stop when idle is needed, go Speaking→Idle directly. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../xiaozhi-server/core/handle/sendAudioHandle.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/backend/main/xiaozhi-server/core/handle/sendAudioHandle.py b/backend/main/xiaozhi-server/core/handle/sendAudioHandle.py index 2870e67..53c53ad 100644 --- a/backend/main/xiaozhi-server/core/handle/sendAudioHandle.py +++ b/backend/main/xiaozhi-server/core/handle/sendAudioHandle.py @@ -44,15 +44,18 @@ async def sendAudioMessage(conn: "ConnectionHandler", sentenceType, audios, text # 发送结束消息(如果是最后一个文本) if sentenceType == SentenceType.LAST: - await send_tts_message(conn, "stop", None) - conn.client_is_speaking = False - # Send system idle command if LLM requested it (e.g. antaf bridge unavailable) if getattr(conn, 'send_idle_after_tts', False): + # Send system idle instead of tts stop — goes Speaking→Idle directly, + # avoids Speaking→Listening which triggers SendStartListening conn.send_idle_after_tts = False + conn.client_is_speaking = False await conn.websocket.send( json.dumps({"type": "system", "command": "idle"}) ) - conn.logger.bind(tag=TAG).info("Sent system idle to device") + conn.logger.bind(tag=TAG).info("Sent system idle to device (skip tts stop)") + else: + await send_tts_message(conn, "stop", None) + conn.client_is_speaking = False if conn.close_after_chat: await conn.close()