feat(events): add RouterNarrationEvent with polymorphic registration and round-trip test

This commit is contained in:
2026-06-03 15:43:48 +04:00
parent 80a72d370e
commit 432226c544
3 changed files with 60 additions and 0 deletions
@@ -50,3 +50,16 @@ data class ContextTruncatedEvent(
val truncatedLayers: List<String>,
val timestampMs: Long,
) : EventPayload
@Serializable
@SerialName("RouterNarration")
data class RouterNarrationEvent(
val sessionId: SessionId,
val narrationId: String,
val trigger: String,
val stageId: String? = null,
val content: String,
val latencyMs: Long? = null,
val tokensUsed: TokenUsage? = null,
val timestampMs: Long,
) : EventPayload
@@ -9,6 +9,7 @@ import com.correx.core.events.events.ArtifactValidatedEvent
import com.correx.core.events.events.ArtifactValidatingEvent
import com.correx.core.events.events.ChatSessionStartedEvent
import com.correx.core.events.events.ChatTurnEvent
import com.correx.core.events.events.RouterNarrationEvent
import com.correx.core.events.events.SessionWorkspaceBoundEvent
import com.correx.core.events.events.ContextTruncatedEvent
import com.correx.core.events.events.EventPayload
@@ -80,6 +81,7 @@ val eventModule = SerializersModule {
subclass(RiskAssessedEvent::class)
subclass(ChatSessionStartedEvent::class)
subclass(ChatTurnEvent::class)
subclass(RouterNarrationEvent::class)
subclass(SessionWorkspaceBoundEvent::class)
subclass(L3MemoryRetrievedEvent::class)
subclass(ContextTruncatedEvent::class)
@@ -0,0 +1,45 @@
package com.correx.core.events.serialization
import com.correx.core.events.events.EventPayload
import com.correx.core.events.events.RouterNarrationEvent
import com.correx.core.events.types.SessionId
import com.correx.core.inference.TokenUsage
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue
class RouterNarrationEventSerializationTest {
private val sample = RouterNarrationEvent(
sessionId = SessionId("sess-1"),
narrationId = "narr-42",
trigger = "stage_start",
stageId = "stage-1",
content = "Router chose the default path.",
latencyMs = 123L,
tokensUsed = TokenUsage(promptTokens = 10, completionTokens = 5),
timestampMs = 1_700_000_000_000L,
)
@Test
fun `round-trips as polymorphic EventPayload`() {
val encoded = eventJson.encodeToString(EventPayload.serializer(), sample)
assertTrue(encoded.contains("\"type\":\"RouterNarration\""), "SerialName must be present: $encoded")
val decoded = eventJson.decodeFromString(EventPayload.serializer(), encoded)
assertEquals(sample, decoded)
}
@Test
fun `round-trips with optional fields absent`() {
val minimal = RouterNarrationEvent(
sessionId = SessionId("sess-2"),
narrationId = "narr-0",
trigger = "manual",
content = "Minimal narration.",
timestampMs = 1_000L,
)
val encoded = eventJson.encodeToString(EventPayload.serializer(), minimal)
val decoded = eventJson.decodeFromString(EventPayload.serializer(), encoded)
assertEquals(minimal, decoded)
}
}