fix(chat): preserve usage baseline across local aborts

This commit is contained in:
M57 committed 2026-09-16 10:14:48 +03:00
1 parent d16a2ea35c
commit 22b948f671
4 files changed
+80 -13

No files matched your search

@@ -1883,7 +1883,7 @@ class ChatViewModelTest {
@Test
fun sendMessage_oversizedDuringSnapshotLeavesNoPersistedGhostMessage() =
runTest {
val (viewModel, _) = createViewModelWithSession()
val (viewModel, sessionId) = createViewModelWithSession()
val persistedBeforeSend = fakeRepo.dao.count()
val uriString = "content://unknown/growing-file"
val mockUri = mockk<Uri>()
@@ -1920,6 +1920,7 @@ class ChatViewModelTest {
viewModel.sendMessage("Inspect changing file")
advanceUntilIdle()
assertFalse(viewModel.streamingState.value.turnUsageBaselineCaptured)
assertEquals(persistedBeforeSend, fakeRepo.dao.count())
assertFalse(
fakeRepo.dao
@@ -1931,6 +1932,24 @@ class ChatViewModelTest {
viewModel.uiState.value.messages
.any { it.content == "Inspect changing file" },
)
mockEventsFlow.emit(
WsEvent.SessionUsage(
data = mapOf("usage" to mapOf("output" to 1300L)),
sessionId = sessionId,
),
)
advanceUntilIdle()
viewModel.removeAttachment(0)
viewModel.sendMessage("Retry without attachment")
advanceUntilIdle()
assertEquals(
1300L,
viewModel.streamingState.value.turnUsageBaseline
?.outputTokens,
)
assertTrue(viewModel.streamingState.value.turnUsageBaselineCaptured)
}
@Test
@@ -4191,6 +4210,7 @@ class ChatViewModelTest {
advanceUntilIdle()
viewModel.sendMessage("prompt")
advanceUntilIdle()
assertEquals(
1000L,
@@ -4,6 +4,7 @@ import com.m57.hermescontrol.data.model.UsageSnapshotResponse
import com.m57.hermescontrol.data.ws.WsEvent
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test
@@ -1185,6 +1186,46 @@ class ChatWsEventReducerTest {
assertTrue(!result.streamingState.turnUsageBaselineCaptured)
}
@Test
fun testMessageComplete_invalidFinalTpsFallsBackToLatestValidTps() {
fun complete(
finalTps: Double?,
latestTps: Double?,
): Double? {
val state =
ChatUiState(
currentSessionId = "session-1",
latestTps = latestTps,
sessionUsage = UsageSnapshotResponse(outputTokens = 1000),
)
val start =
ChatWsEventReducer.reduce(
state,
StreamingState(),
WsEvent.MessageStart("session-1"),
"session-1",
)
val usage = mutableMapOf<String, Any?>("output" to 1250L)
if (finalTps != null) usage["avg_tps"] = finalTps
return ChatWsEventReducer
.reduce(
state,
start.streamingState,
WsEvent.MessageComplete("reply", "session-1", rawPayload = mapOf("usage" to usage)),
"session-1",
).state.messages
.single()
.tps
}
assertEquals(42.5, complete(42.5, 30.0) ?: 0.0, 0.001)
assertEquals(37.5, complete(0.0, 37.5) ?: 0.0, 0.001)
assertEquals(37.5, complete(-2.0, 37.5) ?: 0.0, 0.001)
assertEquals(37.5, complete(null, 37.5) ?: 0.0, 0.001)
assertNull(complete(-2.0, null))
assertNull(complete(0.0, -1.0))
}
@Test
fun testMessageComplete_withoutBaselineFallsBackToVisibleTextEstimate() {
val result =