fix(#1163): avoid streaming JSON tree copies
This commit is contained in:
1 parent
8007bd529d
commit
613d01c1b6
5 files changed
+145
-7
No files matched your search
@@ -2,6 +2,7 @@ package com.m57.hermescontrol.data.ws
|
||||
|
||||
import android.util.Log
|
||||
import com.m57.hermescontrol.ui.chat.extractTodosFromMap
|
||||
import kotlinx.serialization.json.JsonObject
|
||||
|
||||
/**
|
||||
* Converts raw [JsonRpcResponse] objects into typed [WsEvent] instances.
|
||||
@@ -38,8 +39,22 @@ object EventParser {
|
||||
}
|
||||
|
||||
// ── Notification / event (no id, has method) ─────────────────────
|
||||
val jsonParams = response.params ?: return WsEvent.Unknown(rawJson)
|
||||
// Issue #1163: token events need only scalar lookups, never recursive map/list copies.
|
||||
val eventType = jsonParams["type"].eventStringOrNull()
|
||||
if (eventType == "message.token" || eventType == "message.delta" ||
|
||||
eventType == "thinking.delta" || eventType == "reasoning.delta"
|
||||
) {
|
||||
val sessionId = jsonParams.eventSessionId()
|
||||
val token = (jsonParams["payload"] as? JsonObject)?.get("text").eventStringOrNull() ?: ""
|
||||
return when (eventType) {
|
||||
"thinking.delta" -> WsEvent.ThinkingDelta(token, sessionId)
|
||||
"reasoning.delta" -> WsEvent.ReasoningDelta(token, sessionId)
|
||||
else -> WsEvent.MessageToken(token, sessionId)
|
||||
}
|
||||
}
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val params = response.params?.toAny() as? Map<String, Any?> ?: return WsEvent.Unknown(rawJson)
|
||||
val params = jsonParams.toAny() as Map<String, Any?>
|
||||
return parseParams(params, rawJson)
|
||||
}
|
||||
|
||||
|
||||
@@ -1316,12 +1316,9 @@ object HermesWsClient {
|
||||
}
|
||||
|
||||
if (rpc.id == null) {
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
val params = rpc.params?.toAny() as? Map<String, Any?>
|
||||
val sid =
|
||||
(params?.get("session_id") as? String)
|
||||
?: ((params?.get("payload") as? Map<*, *>)?.get("session_id") as? String)
|
||||
val seq = (params?.get("seq") as? Number)?.toInt()
|
||||
// Issue #1163: inspect scalars, not a throwaway copy of the whole params tree.
|
||||
val sid = rpc.params?.eventSessionId()
|
||||
val seq = ((rpc.params?.get("seq") as? JsonPrimitive)?.toAny() as? Number)?.toInt()
|
||||
|
||||
if (!sid.isNullOrBlank() && seq != null) {
|
||||
val prev = lastSeenSeq[sid] ?: 0
|
||||
|
||||
@@ -102,6 +102,13 @@ fun Any?.toJsonElement(): JsonElement =
|
||||
}
|
||||
}
|
||||
|
||||
// Issue #1163: scalar conversion preserves toAny() type semantics without copying JSON containers.
|
||||
internal fun JsonElement?.eventStringOrNull(): String? = (this as? JsonPrimitive)?.toAny() as? String
|
||||
|
||||
internal fun JsonObject.eventSessionId(): String? =
|
||||
get("session_id").eventStringOrNull()
|
||||
?: (get("payload") as? JsonObject)?.get("session_id").eventStringOrNull()
|
||||
|
||||
fun JsonElement.toAny(): Any? =
|
||||
when (this) {
|
||||
is JsonNull -> {
|
||||
|
||||
Reference in new issue
Block a user