feat(tui): Task 3.5 — decode + render router.narration as bright narration_llm lines

Add TypeRouterNarration constant, mark it event-bearing, decode golden test,
applyServer case appending RouterEntry{Role:"narration_llm"} with metrics, and
routerRows render branch showing bright ◆ prefix with FgStrong content + metrics suffix.
This commit is contained in:
2026-06-03 19:09:28 +04:00
parent da1aca411a
commit 2bef4b96a5
4 changed files with 33 additions and 1 deletions
+6
View File
@@ -92,6 +92,12 @@ func (m *Model) applyServer(msg protocol.ServerMessage) {
switch msg.Type {
case protocol.TypeSessionAnnounced:
m.onSessionAnnounced(msg)
case protocol.TypeRouterNarration:
entry := RouterEntry{Role: "narration_llm", Content: msg.Content}
if msg.LatencyMs != nil && msg.TotalTokens != nil {
entry.Metrics = &TurnMetrics{LatencyMs: *msg.LatencyMs, TotalTokens: *msg.TotalTokens}
}
m.appendRouter(msg.SessionID, entry)
case protocol.TypeChatTurn:
m.routerConnected = true
role := "router"
+13
View File
@@ -358,6 +358,19 @@ func (m Model) routerRows(w, h int) []string {
}
case "tool":
rows = append(rows, t.span("· tool output ("+itoaLen(e.Content)+" chars) — ^x to view", t.P.Dim))
case "narration_llm":
diamond := lipgloss.NewStyle().Foreground(t.P.Accent).Background(t.P.Bg).Bold(true).Render("◆")
lines := wrap(e.Content, w-2)
for i, ln := range lines {
if i == 0 {
rows = append(rows, diamond+" "+t.span(ln, t.P.FgStrong))
} else {
rows = append(rows, " "+t.span(ln, t.P.FgStrong))
}
}
if s := metricsSuffix(e.Metrics); s != "" {
rows = append(rows, t.span(s, t.P.Faint))
}
case "narration", "stage":
rows = append(rows, t.span(e.Content, t.P.Dim))
}