feat(#525): render reasoning.delta / reasoning.available stream (#543)

* feat(#525): add ReasoningDelta + ReasoningAvailable WsEvent types

* feat(#525): parse reasoning.delta + reasoning.available; route through reducer + StreamingState

* feat(#525): add reasoning streaming buffer to ChatStreamingController

* feat(#525): dispatch ReasoningDelta/ReasoningAvailable in ChatViewModel

* feat(#525): render collapsible ReasoningIndicator in chat list

* fix(#525): address review — icons+semantics, LocalHermesStatusColors, drop redundant ReasoningAvailable branch

* feat(#525): persist reasoningText on model, entity, mapper + Room migration 3->4

* feat(#525): reducer + streaming carry reasoningText onto message

* feat(#525): render persisted reasoning above each assistant bubble, drop global indicator

* nix: flake

* nix: flake

---------

Co-authored-by: M57 <m57@hermes-control.app>
This commit is contained in:
M57andM57 authored and GitHub committed 2026-07-10 23:41:53 +03:00
1 parent d04b74ee0a
commit 53b3966931
17 files changed
+441 -33

No files matched your search

@@ -166,6 +166,48 @@ class EventParserTest {
assertEquals("session-2", deltaEvent.sessionId)
}
@Test
fun testParseReasoningDelta_returnsReasoningDeltaEvent() {
val response =
createJsonRpcResponse(
jsonrpc = "2.0",
id = null,
result = null,
error = null,
method = "event",
params =
mapOf(
"type" to "reasoning.delta",
"payload" to mapOf("text" to "reasoning token", "session_id" to "session-r1"),
),
)
val event = EventParser.parse(response)
assertTrue(event is WsEvent.ReasoningDelta)
val deltaEvent = event as WsEvent.ReasoningDelta
assertEquals("reasoning token", deltaEvent.token)
assertEquals("session-r1", deltaEvent.sessionId)
}
@Test
fun testParseReasoningAvailable_returnsReasoningAvailableEvent() {
val response =
createJsonRpcResponse(
jsonrpc = "2.0",
id = null,
result = null,
error = null,
method = "event",
params =
mapOf(
"type" to "reasoning.available",
"payload" to mapOf("session_id" to "session-r1"),
),
)
val event = EventParser.parse(response)
assertTrue(event is WsEvent.ReasoningAvailable)
assertEquals("session-r1", (event as WsEvent.ReasoningAvailable).sessionId)
}
@Test
fun testParseClarifyRequest_returnsClarifyRequestEvent() {
val response =