From 7194acbf028bcd14172fd3e95c970ccde0d16cea Mon Sep 17 00:00:00 2001 From: Kohei Date: Sat, 21 Feb 2026 23:39:45 +0900 Subject: [PATCH] fix: preserve assistant message in chat history when TTS is interrupted Move chatHistory update into try-finally in speakAndDrain so the response is committed even when the user cancels mid-speech. Co-Authored-By: Claude Opus 4.6 --- .../chat/assistant/AssistantManager.kt | 21 +++++++++++-------- 1 file changed, 12 insertions(+), 9 deletions(-) diff --git a/android/feature/chat/src/main/java/io/picoclaw/android/feature/chat/assistant/AssistantManager.kt b/android/feature/chat/src/main/java/io/picoclaw/android/feature/chat/assistant/AssistantManager.kt index 3048c3554..a0d321784 100644 --- a/android/feature/chat/src/main/java/io/picoclaw/android/feature/chat/assistant/AssistantManager.kt +++ b/android/feature/chat/src/main/java/io/picoclaw/android/feature/chat/assistant/AssistantManager.kt @@ -208,17 +208,20 @@ class AssistantManager( } private suspend fun speakAndDrain(firstContent: String, speechQueue: Channel) { - _state.update { it.copy(phase = VoicePhase.SPEAKING, responseText = firstContent) } - ttsWrapper.speak(firstContent) val chunks = mutableListOf(firstContent) - while (true) { - val next = speechQueue.tryReceive().getOrNull() ?: break - _state.update { it.copy(responseText = next) } - ttsWrapper.speak(next) - chunks.add(next) + try { + _state.update { it.copy(phase = VoicePhase.SPEAKING, responseText = firstContent) } + ttsWrapper.speak(firstContent) + while (true) { + val next = speechQueue.tryReceive().getOrNull() ?: break + chunks.add(next) + _state.update { it.copy(responseText = next) } + ttsWrapper.speak(next) + } + } finally { + val fullResponse = chunks.joinToString("\n") + _state.update { it.copy(chatHistory = it.chatHistory + ChatTurn("assistant", fullResponse)) } } - val fullResponse = chunks.joinToString("\n") - _state.update { it.copy(chatHistory = it.chatHistory + ChatTurn("assistant", fullResponse)) } } private suspend fun drainSpeechQueue(speechQueue: Channel) {