From f94d1784d43d0229790755b43ec71d2b5ee46413 Mon Sep 17 00:00:00 2001 From: M57 <41645758+Hy4ri@users.noreply.github.com> Date: Wed, 16 Sep 2026 10:48:08 +0300 Subject: [PATCH] fix(chat): reject stale dispatch after session switch --- .../com/m57/hermescontrol/ui/chat/ChatViewModel.kt | 2 ++ .../com/m57/hermescontrol/ui/chat/ChatViewModelTest.kt | 10 ++-------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatViewModel.kt b/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatViewModel.kt index 44534ca5..7a69978b 100644 --- a/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatViewModel.kt +++ b/app/src/main/java/com/m57/hermescontrol/ui/chat/ChatViewModel.kt @@ -1807,6 +1807,8 @@ class ChatViewModel( if (text.isNotBlank()) "\n\n$text" else "" } + if (dispatchGeneration != sessionGeneration) return@launch + // While a turn is actively streaming and this is a plain text prompt // (no attachments — session.redirect carries text only), steer the // in-flight turn via session.redirect instead of queueing a fresh diff --git a/app/src/test/java/com/m57/hermescontrol/ui/chat/ChatViewModelTest.kt b/app/src/test/java/com/m57/hermescontrol/ui/chat/ChatViewModelTest.kt index df49b884..289de8a0 100644 --- a/app/src/test/java/com/m57/hermescontrol/ui/chat/ChatViewModelTest.kt +++ b/app/src/test/java/com/m57/hermescontrol/ui/chat/ChatViewModelTest.kt @@ -2110,7 +2110,7 @@ class ChatViewModelTest { viewModel.sendMessage("Send in the old session") advanceUntilIdle() - verify { + verify(exactly = 0) { HermesWsClient.sendMessage( oldSessionId, match { it.contains("Send in the old session") }, @@ -2118,13 +2118,7 @@ class ChatViewModelTest { any(), ) } - mockEventsFlow.emit( - WsEvent.RpcError( - promptRequestId, - JsonRpcError(code = 4001, message = "old session rejected prompt"), - ), - ) - advanceUntilIdle() + assertFalse(viewModel.streamingState.value.turnUsageBaselineCaptured) val state = viewModel.uiState.value assertEquals("session-456", state.currentSessionId)