github.com/anthropics/anthropic-sdk-go@v1.70.1/betasessionutil_test.go (about) 1 package anthropic 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "testing" 7 ) 8 9 func sseEvent(t *testing.T, raw string) BetaManagedAgentsStreamSessionEventsUnion { 10 t.Helper() 11 var ev BetaManagedAgentsStreamSessionEventsUnion 12 if err := json.Unmarshal([]byte(raw), &ev); err != nil { 13 t.Fatalf("unmarshal: %v", err) 14 } 15 return ev 16 } 17 18 func eventStart(t *testing.T, eventID string) BetaManagedAgentsStreamSessionEventsUnion { 19 return sseEvent(t, fmt.Sprintf(`{"type":"event_start","event":{"type":"agent.message","id":%q}}`, eventID)) 20 } 21 22 func eventDelta(t *testing.T, eventID, text string, index int) BetaManagedAgentsStreamSessionEventsUnion { 23 return sseEvent(t, fmt.Sprintf(`{"type":"event_delta","event_id":%q,"delta":{"type":"content_delta","index":%d,"content":{"type":"text","text":%q}}}`, eventID, index, text)) 24 } 25 26 func feed(acc *BetaManagedAgentsEventAccumulator, evs ...BetaManagedAgentsStreamSessionEventsUnion) { 27 for _, ev := range evs { 28 acc.Accumulate(ev) 29 } 30 } 31 32 func TestBetaManagedAgentsEventAccumulator_StartOpensEmptyPreview(t *testing.T) { 33 var acc BetaManagedAgentsEventAccumulator 34 feed(&acc, eventStart(t, "evt_1")) 35 msg, ok := acc.AgentMessages["evt_1"] 36 if !ok { 37 t.Fatal("expected preview") 38 } 39 if msg.ID != "evt_1" || msg.Type != "agent.message" || len(msg.Content) != 0 { 40 t.Fatalf("unexpected seed: %+v", msg) 41 } 42 } 43 44 func TestBetaManagedAgentsEventAccumulator_StartIgnoresNonAgentMessage(t *testing.T) { 45 var acc BetaManagedAgentsEventAccumulator 46 feed(&acc, sseEvent(t, `{"type":"event_start","event":{"type":"agent.thinking","id":"evt_1"}}`)) 47 if _, ok := acc.AgentMessages["evt_1"]; ok { 48 t.Fatal("expected no preview for agent.thinking start") 49 } 50 } 51 52 func TestBetaManagedAgentsEventAccumulator_DeltaForIgnoredPreviewIsNoOp(t *testing.T) { 53 var acc BetaManagedAgentsEventAccumulator 54 feed(&acc, 55 sseEvent(t, `{"type":"event_start","event":{"type":"agent.thinking","id":"evt_1"}}`), 56 eventDelta(t, "evt_1", "x", 0), 57 ) 58 if _, ok := acc.AgentMessages["evt_1"]; ok { 59 t.Fatal("expected no preview for ignored type") 60 } 61 } 62 63 func TestBetaManagedAgentsEventAccumulator_DeltaAppendsAndInserts(t *testing.T) { 64 var acc BetaManagedAgentsEventAccumulator 65 feed(&acc, 66 eventStart(t, "evt_1"), 67 eventDelta(t, "evt_1", "Hel", 0), 68 eventDelta(t, "evt_1", "lo", 0), 69 eventDelta(t, "evt_1", "World", 1), 70 ) 71 msg := acc.AgentMessages["evt_1"] 72 if len(msg.Content) != 2 || msg.Content[0].Text != "Hello" || msg.Content[1].Text != "World" { 73 t.Fatalf("unexpected content: %+v", msg.Content) 74 } 75 if text := acc.AgentMessageText("evt_1"); text != "HelloWorld" { 76 t.Fatalf("unexpected joined text: %q", text) 77 } 78 } 79 80 func TestBetaManagedAgentsEventAccumulator_DeltaDefaultsIndexZero(t *testing.T) { 81 var acc BetaManagedAgentsEventAccumulator 82 feed(&acc, 83 eventStart(t, "evt_1"), 84 sseEvent(t, `{"type":"event_delta","event_id":"evt_1","delta":{"type":"content_delta","content":{"type":"text","text":"a"}}}`), 85 sseEvent(t, `{"type":"event_delta","event_id":"evt_1","delta":{"type":"content_delta","content":{"type":"text","text":"b"}}}`), 86 ) 87 if text := acc.AgentMessageText("evt_1"); text != "ab" { 88 t.Fatalf("unexpected joined text: %q", text) 89 } 90 } 91 92 func TestBetaManagedAgentsEventAccumulator_DeltaSeedsTheUnionVariant(t *testing.T) { 93 var acc BetaManagedAgentsEventAccumulator 94 feed(&acc, 95 eventStart(t, "evt_1"), 96 eventDelta(t, "evt_1", "Hel", 0), 97 ) 98 block := acc.AgentMessages["evt_1"].Content[0] 99 if _, ok := block.AsAny().(BetaManagedAgentsTextBlock); !ok { 100 t.Fatalf("expected preview block to report the text variant, got %T", block.AsAny()) 101 } 102 } 103 104 func TestBetaManagedAgentsEventAccumulator_ContentlessDeltaKeepsIndexAlignment(t *testing.T) { 105 // Deltas address entries by index, so a fragment carrying no content still 106 // has to occupy its slot or every later fragment falls out of range. 107 var acc BetaManagedAgentsEventAccumulator 108 feed(&acc, 109 eventStart(t, "evt_1"), 110 sseEvent(t, `{"type":"event_delta","event_id":"evt_1","delta":{"type":"content_delta","index":0}}`), 111 eventDelta(t, "evt_1", "World", 1), 112 ) 113 msg := acc.AgentMessages["evt_1"] 114 if len(msg.Content) != 2 || msg.Content[1].Text != "World" { 115 t.Fatalf("unexpected content: %+v", msg.Content) 116 } 117 } 118 119 func TestBetaManagedAgentsEventAccumulator_DeltaBeforeStartIsNoOp(t *testing.T) { 120 var acc BetaManagedAgentsEventAccumulator 121 feed(&acc, eventDelta(t, "evt_1", "x", 0)) 122 if _, ok := acc.AgentMessages["evt_1"]; ok { 123 t.Fatal("expected no preview without event_start") 124 } 125 } 126 127 func TestBetaManagedAgentsEventAccumulator_OutOfRangeIndexIsNoOp(t *testing.T) { 128 var acc BetaManagedAgentsEventAccumulator 129 feed(&acc, 130 eventStart(t, "evt_1"), 131 eventDelta(t, "evt_1", "x", 2), 132 eventDelta(t, "evt_1", "y", -1), 133 ) 134 if len(acc.AgentMessages["evt_1"].Content) != 0 { 135 t.Fatalf("expected out-of-range deltas to be dropped, got %+v", acc.AgentMessages["evt_1"].Content) 136 } 137 } 138 139 func TestBetaManagedAgentsEventAccumulator_BufferedEventReplacesPreview(t *testing.T) { 140 var acc BetaManagedAgentsEventAccumulator 141 feed(&acc, 142 eventStart(t, "evt_1"), 143 eventDelta(t, "evt_1", "partial", 0), 144 sseEvent(t, `{"type":"agent.message","id":"evt_1","processed_at":"2024-01-01T00:00:00Z","content":[{"type":"text","text":"complete"}]}`), 145 ) 146 if text := acc.AgentMessageText("evt_1"); text != "complete" { 147 t.Fatalf("expected final event to replace preview, got %q", text) 148 } 149 } 150 151 func TestBetaManagedAgentsEventAccumulator_StragglerDeltaAfterBufferedEventIsDropped(t *testing.T) { 152 var acc BetaManagedAgentsEventAccumulator 153 feed(&acc, 154 eventStart(t, "evt_1"), 155 eventDelta(t, "evt_1", "partial", 0), 156 sseEvent(t, `{"type":"agent.message","id":"evt_1","processed_at":"2024-01-01T00:00:00Z","content":[{"type":"text","text":"complete"}]}`), 157 eventDelta(t, "evt_1", "straggler", 0), 158 ) 159 if text := acc.AgentMessageText("evt_1"); text != "complete" { 160 t.Fatalf("expected straggler delta after the canonical event to be dropped, got %q", text) 161 } 162 } 163 164 func TestBetaManagedAgentsEventAccumulator_ModelRequestEndClearsPreviews(t *testing.T) { 165 var acc BetaManagedAgentsEventAccumulator 166 feed(&acc, 167 eventStart(t, "evt_1"), 168 eventDelta(t, "evt_1", "x", 0), 169 sseEvent(t, `{"type":"span.model_request_end","id":"sevt_2","model_request_start_id":"sevt_1","is_error":true,"processed_at":"2024-01-01T00:00:00Z"}`), 170 ) 171 if len(acc.AgentMessages) != 0 { 172 t.Fatal("expected previews to be cleared by span.model_request_end") 173 } 174 } 175 176 func TestBetaManagedAgentsEventAccumulator_ModelRequestEndKeepsCanonicalMessages(t *testing.T) { 177 var acc BetaManagedAgentsEventAccumulator 178 feed(&acc, 179 eventStart(t, "evt_1"), 180 eventDelta(t, "evt_1", "partial", 0), 181 sseEvent(t, `{"type":"agent.message","id":"evt_1","processed_at":"2024-01-01T00:00:00Z","content":[{"type":"text","text":"complete"}]}`), 182 eventStart(t, "evt_2"), 183 eventDelta(t, "evt_2", "open", 0), 184 sseEvent(t, `{"type":"span.model_request_end","id":"sevt_2","model_request_start_id":"sevt_1","is_error":true,"processed_at":"2024-01-01T00:00:00Z"}`), 185 ) 186 if text := acc.AgentMessageText("evt_1"); text != "complete" { 187 t.Fatalf("expected canonical message to survive span.model_request_end, got %q", text) 188 } 189 if _, ok := acc.AgentMessages["evt_2"]; ok { 190 t.Fatal("expected open preview to be discarded by span.model_request_end") 191 } 192 } 193 194 func TestBetaManagedAgentsEventAccumulator_OtherEventsAreNoOps(t *testing.T) { 195 var acc BetaManagedAgentsEventAccumulator 196 feed(&acc, sseEvent(t, `{"type":"session.status_running","id":"sevt_1","processed_at":"2024-01-01T00:00:00Z"}`)) 197 if _, ok := acc.AgentMessages["sevt_1"]; ok { 198 t.Fatal("expected no preview") 199 } 200 } 201 202 func TestBetaManagedAgentsEventAccumulator_UnrecognizedEventTypeIsNoOp(t *testing.T) { 203 var acc BetaManagedAgentsEventAccumulator 204 feed(&acc, 205 eventStart(t, "evt_1"), 206 eventDelta(t, "evt_1", "Hi", 0), 207 sseEvent(t, `{"type":"session.some_future_event","id":"evt_1","result":{"type":"object"}}`), 208 ) 209 if text := acc.AgentMessageText("evt_1"); text != "Hi" { 210 t.Fatalf("expected preview to be untouched by an unrecognized event type, got %q", text) 211 } 212 } 213 214 func TestBetaManagedAgentsEventAccumulator_MultiplePreviews(t *testing.T) { 215 var acc BetaManagedAgentsEventAccumulator 216 feed(&acc, 217 eventStart(t, "evt_a"), 218 eventDelta(t, "evt_a", "alpha", 0), 219 eventStart(t, "evt_b"), 220 eventDelta(t, "evt_b", "beta", 0), 221 sseEvent(t, `{"type":"event_start","event":{"type":"agent.thinking","id":"evt_c"}}`), 222 ) 223 if len(acc.AgentMessages) != 2 { 224 t.Fatalf("expected 2 previews, got %d", len(acc.AgentMessages)) 225 } 226 if acc.AgentMessageText("evt_a") != "alpha" || acc.AgentMessageText("evt_b") != "beta" { 227 t.Fatalf("unexpected: a=%q b=%q", acc.AgentMessageText("evt_a"), acc.AgentMessageText("evt_b")) 228 } 229 } 230 231 func TestBetaManagedAgentsEventAccumulator_ZeroValue(t *testing.T) { 232 var acc BetaManagedAgentsEventAccumulator 233 if acc.AgentMessageText("evt_1") != "" { 234 t.Fatal("expected empty text from zero value") 235 } 236 if len(acc.AgentMessages) != 0 { 237 t.Fatal("expected empty map from zero value") 238 } 239 }