resident_projection_test.go RawHistoryFolder
1package subagents
2
3import (
4 "encoding/json"
5 "strings"
6 "testing"
7
8 "github.com/bnema/zut/packages/core"
9 "github.com/bnema/zut/packages/provider"
10)
11
12func TestResidentLiveProjectionPublishesCopiesAndFinalizesLiveItems(t *testing.T) {
13 projection := newResidentLiveProjection()
14 projection.Start("turn-1")
15 projection.Apply(core.EvTextDelta{Delta: "draft"})
16 projection.Apply(core.EvToolUseStart{ID: "call-1", Name: "bash"})
17 projection.Apply(core.EvToolUseArgs{ID: "call-1", Delta: `{"command":"pwd"}`})
18 projection.Apply(core.EvToolExecutionStarted{ID: "call-1", Name: "bash"})
19
20 live := projection.Snapshot()
21 if live.TurnID != "turn-1" || live.State != ResidentRunning || live.AssistantText != "draft" || len(live.Tools) != 1 || live.Tools[0].State != ResidentLiveToolRunning || string(live.Tools[0].Args) != `{"command":"pwd"}` || live.Revision == 0 {
22 t.Fatalf("live projection = %#v", live)
23 }
24 live.Tools[0].Args[0] = 'x'
25 if got := projection.Snapshot(); string(got.Tools[0].Args) != `{"command":"pwd"}` {
26 t.Fatalf("snapshot mutated projection: %#v", got)
27 }
28
29 projection.Apply(core.EvToolResult{ID: "call-1", Result: core.ToolResult{Content: []provider.Content{provider.TextBlock{Text: "done"}}}})
30 projection.Apply(core.EvRequestStarted{})
31 if !projection.Snapshot().WaitingForModel {
32 t.Fatal("provider request did not mark the resident as waiting for the model")
33 }
34 projection.Apply(core.EvAssistantMessage{Message: provider.Message{Role: provider.RoleAssistant, Content: []provider.Content{provider.TextBlock{Text: "final"}}}})
35 projection.Finish(ResidentIdle)
36 final := projection.Snapshot()
37 if final.AssistantText != "" || len(final.Tools) != 0 || final.State != ResidentIdle || final.Revision <= live.Revision {
38 t.Fatalf("final projection = %#v", final)
39 }
40}
41
42func TestResidentLiveProjectionBoundsToolArguments(t *testing.T) {
43 projection := newResidentLiveProjection()
44 projection.Start("turn-1")
45 projection.Apply(core.EvToolCall{ID: "call-1", Name: "bash", Args: json.RawMessage(`{"command":"pwd"}`)})
46 if got := projection.Snapshot(); len(got.Tools) != 1 || string(got.Tools[0].Args) != `{"command":"pwd"}` {
47 t.Fatalf("live tool = %#v", got)
48 }
49 projection.Apply(core.EvToolCall{ID: "call-2", Name: "bash", Args: json.RawMessage(strings.Repeat("a", residentLiveArgumentBytes+1024))})
50 if got := projection.Snapshot(); len(got.Tools) != 2 || len(got.Tools[1].Args) != residentLiveArgumentBytes {
51 t.Fatalf("oversized tool args = %d bytes", len(got.Tools[1].Args))
52 }
53}