feat: session busy indicator — daemon tracks mid-turn state (agent_start/settled), busy field on session rows + live broadcast; pulsing pip in sidebar and cards (265 web tests, daemon 95.4%)

This commit is contained in:
Raphael Westphal
2026-08-19 10:41:40 +02:00
parent c8ad68aaea
commit 957ea03aa1
11 changed files with 137 additions and 3 deletions
+31
View File
@@ -714,3 +714,34 @@ func TestWebResubscribeSplitsEventBatches(t *testing.T) {
_ = agent2.WriteJSON(map[string]any{"v": 1, "type": evMessageUpdate, "sessionId": "s2", "seq": 1, "ts": 11, "delta": "two"})
readBatch("s2") // event B must arrive as its own frame, never mixed with A's
}
func TestHubBusyFlagLifecycle(t *testing.T) {
ts, _, hub := newTestServerHub(t)
ws := dialAgent(t, ts)
defer ws.Close()
_ = ws.WriteJSON(helloFrame("busy-1"))
_ = readFrame(t, ws)
sendEv := func(typ string, seq int64) {
_ = ws.WriteJSON(map[string]any{
"v": 1, "sessionId": "busy-1", "seq": seq, "ts": 1, "type": typ,
})
}
sendEv("agent_start", 1)
waitFor(t, 3*time.Second, func() bool {
for _, s := range hub.SessionsView() {
if s.ID == "busy-1" {
return s.Busy
}
}
return false
})
sendEv("agent_settled", 2)
waitFor(t, 3*time.Second, func() bool {
for _, s := range hub.SessionsView() {
if s.ID == "busy-1" {
return !s.Busy
}
}
return false
})
}