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 <noreply@anthropic.com>
This commit is contained in:
Kohei 2026-02-21 23:39:45 +09:00
parent 64e7a42f9a
commit 7194acbf02

View file

@ -208,17 +208,20 @@ class AssistantManager(
} }
private suspend fun speakAndDrain(firstContent: String, speechQueue: Channel<String>) { private suspend fun speakAndDrain(firstContent: String, speechQueue: Channel<String>) {
_state.update { it.copy(phase = VoicePhase.SPEAKING, responseText = firstContent) }
ttsWrapper.speak(firstContent)
val chunks = mutableListOf(firstContent) val chunks = mutableListOf(firstContent)
while (true) { try {
val next = speechQueue.tryReceive().getOrNull() ?: break _state.update { it.copy(phase = VoicePhase.SPEAKING, responseText = firstContent) }
_state.update { it.copy(responseText = next) } ttsWrapper.speak(firstContent)
ttsWrapper.speak(next) while (true) {
chunks.add(next) 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<String>) { private suspend fun drainSpeechQueue(speechQueue: Channel<String>) {