feat(server): carry latencyMs + totalTokens through ServerMessage.ChatTurn
ChatTurn wire frame now includes latencyMs: Long? and totalTokens: Int?. DomainEventMapper reads them from ChatTurnEvent.latencyMs and tokensUsed?.totalTokens. Positional call site in DomainEventMapperTest converted to named args. Two new serialization tests cover the ROUTER (metrics present) and USER (metrics absent) paths.
This commit is contained in:
@@ -82,6 +82,8 @@ suspend fun domainEventToServerMessage(
|
||||
turnId = p.turnId,
|
||||
role = p.role.name,
|
||||
content = p.content,
|
||||
latencyMs = p.latencyMs,
|
||||
totalTokens = p.tokensUsed?.totalTokens,
|
||||
sequence = seq,
|
||||
sessionSequence = sessionSequence,
|
||||
)
|
||||
|
||||
@@ -67,6 +67,8 @@ sealed interface ServerMessage {
|
||||
val turnId: String,
|
||||
val role: String,
|
||||
val content: String,
|
||||
val latencyMs: Long? = null,
|
||||
val totalTokens: Int? = null,
|
||||
override val sequence: Long,
|
||||
override val sessionSequence: Long,
|
||||
) : ServerMessage, SessionMessage
|
||||
|
||||
@@ -113,7 +113,14 @@ class DomainEventMapperTest {
|
||||
)
|
||||
val result = domainEventToServerMessage(event, noopStore, sessionSequence = 3L)
|
||||
assertEquals(
|
||||
ServerMessage.ChatTurn(sessionId, "turn-1", "ROUTER", "hello", event.sequence, 3L),
|
||||
ServerMessage.ChatTurn(
|
||||
sessionId = sessionId,
|
||||
turnId = "turn-1",
|
||||
role = "ROUTER",
|
||||
content = "hello",
|
||||
sequence = event.sequence,
|
||||
sessionSequence = 3L,
|
||||
),
|
||||
result,
|
||||
)
|
||||
}
|
||||
|
||||
+34
@@ -45,6 +45,40 @@ class ServerMessageSerializationTest {
|
||||
assert(jsonStr.contains("\"content\":\"hi there\"")) { "expected content" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ChatTurn with metrics encodes latencyMs and totalTokens`() {
|
||||
val msg = ServerMessage.ChatTurn(
|
||||
sessionId = SessionId("sess-1"),
|
||||
turnId = "t9",
|
||||
role = "ROUTER",
|
||||
content = "hi",
|
||||
latencyMs = 3000,
|
||||
totalTokens = 943,
|
||||
sequence = 7,
|
||||
sessionSequence = 2,
|
||||
)
|
||||
val jsonStr = ProtocolSerializer.encodeServerMessage(msg)
|
||||
assert(jsonStr.contains("\"type\":\"chat.turn\"")) { "expected type=chat.turn" }
|
||||
assert(jsonStr.contains("\"latencyMs\":3000")) { "expected latencyMs=3000" }
|
||||
assert(jsonStr.contains("\"totalTokens\":943")) { "expected totalTokens=943" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `ChatTurn without metrics encodes latencyMs and totalTokens as absent or null`() {
|
||||
val msg = ServerMessage.ChatTurn(
|
||||
sessionId = SessionId("sess-1"),
|
||||
turnId = "t10",
|
||||
role = "USER",
|
||||
content = "hello",
|
||||
sequence = 8,
|
||||
sessionSequence = 3,
|
||||
)
|
||||
val jsonStr = ProtocolSerializer.encodeServerMessage(msg)
|
||||
assert(jsonStr.contains("\"type\":\"chat.turn\"")) { "expected type=chat.turn" }
|
||||
assert(!jsonStr.contains("\"latencyMs\":3000")) { "latencyMs should not be 3000" }
|
||||
assert(!jsonStr.contains("\"totalTokens\":943")) { "totalTokens should not be 943" }
|
||||
}
|
||||
|
||||
@Test
|
||||
fun `SnapshotComplete encodes with only type field`() {
|
||||
val msg = ServerMessage.SnapshotComplete
|
||||
|
||||
Reference in New Issue
Block a user