@m8tes/sdk 0.1.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,295 @@
1
+ // src/protocol/fixtures.ts
2
+ var FIXTURES = {
3
+ /** Happy-path text run: preamble (comment + 2 metadata + json keepalive), one
4
+ * streamed text block, terminal snapshot, run_metrics -> done. */
5
+ "text-run": `: keep-alive
6
+
7
+ data: {"type": "metadata", "run_id": 123, "mode": "chat", "run_uuid": "run-abc", "agent_name": "PPC Manager", "status": "running"}
8
+
9
+ data: {"type": "keep-alive", "message": "Connection established"}
10
+
11
+ data: {"type": "metadata", "run_id": 123, "mode": "chat", "run_uuid": "run-abc"}
12
+
13
+ data: {"type": "message_start", "message": {"id": "msg_1", "role": "assistant", "content": [], "usage": {"input_tokens": 100, "output_tokens": 0}}}
14
+
15
+ data: {"type": "content_block_start", "id": "block_1", "block_type": "text"}
16
+
17
+ data: {"type": "content_block_delta", "id": "block_1", "delta": {"type": "text_delta", "text": "Hello"}}
18
+
19
+ data: {"type": "content_block_delta", "id": "block_1", "delta": {"type": "text_delta", "text": " world"}}
20
+
21
+ data: {"type": "content_block_stop", "id": "block_1"}
22
+
23
+ data: {"type": "message_snapshot", "message_id": "msg_1", "role": "assistant", "content_blocks": [{"type": "text", "text": "Hello world"}], "usage": {"input_tokens": 100, "output_tokens": 5}}
24
+
25
+ data: {"type": "message_stop", "message_id": "msg_1"}
26
+
27
+ data: {"type": "run_metrics", "model": "claude-opus-4-8", "execution_time_ms": 1840, "input_tokens_used": 100, "output_tokens_used": 5, "claude_token_cost_usd": 0.004, "stop_reason": "end_turn", "completion_state": "complete", "unresolved_tool_use_ids": [], "terminal_completion_seen": true, "sdk_total_cost_usd": 0.0045, "code_version": "v2-46", "message_count": 1, "last_event_type": "message_complete", "retry_count": 0}
28
+
29
+ data: {"type": "done", "message_count": 1, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
30
+
31
+ `,
32
+ /** Computer-use screenshot: tool_result whose content is an array holding a
33
+ * base64 image block (the desktop MCP server's `_png_to_image_block` shape).
34
+ * Platform renders these inline (BubbleTimeline tool_result case). */
35
+ "screenshot-run": `data: {"type": "message_start", "message": {"id": "msg_s1", "role": "assistant", "content": [], "usage": {"input_tokens": 100, "output_tokens": 0}}}
36
+
37
+ data: {"type": "tool_use", "id": "toolu_pre1", "name": "bash", "input": {"command": "ls"}}
38
+
39
+ data: {"type": "tool_result", "tool_use_id": "toolu_pre1", "content": "ok", "result": "ok"}
40
+
41
+ data: {"type": "tool_use", "id": "toolu_pre2", "name": "bash", "input": {"command": "pwd"}}
42
+
43
+ data: {"type": "tool_result", "tool_use_id": "toolu_pre2", "content": "/", "result": "/"}
44
+
45
+ data: {"type": "tool_use", "id": "toolu_shot", "name": "computer", "input": {"action": "screenshot"}}
46
+
47
+ data: {"type": "tool_result", "tool_use_id": "toolu_shot", "content": [{"type": "image", "source": {"type": "base64", "media_type": "image/png", "data": "iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg=="}}]}
48
+
49
+ data: {"type": "done", "message_count": 2, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
50
+
51
+ `,
52
+ /** Full tool chain: block-start(tool_use) -> input_json_delta streaming ->
53
+ * block-stop -> standalone tool_use (resolved input, SAME id) -> tool_result. */
54
+ "tool-call-lifecycle": `data: {"type": "message_start", "message": {"id": "msg_2", "role": "assistant", "content": [], "usage": {"input_tokens": 200, "output_tokens": 0}}}
55
+
56
+ data: {"type": "content_block_start", "id": "toolu_1", "block_type": "tool_use", "name": "get_weather"}
57
+
58
+ data: {"type": "content_block_delta", "id": "toolu_1", "delta": {"type": "input_json_delta", "partial_json": "{\\"location\\": \\"San"}}
59
+
60
+ data: {"type": "content_block_delta", "id": "toolu_1", "delta": {"type": "input_json_delta", "partial_json": " Francisco\\"}"}}
61
+
62
+ data: {"type": "content_block_stop", "id": "toolu_1"}
63
+
64
+ data: {"type": "tool_use", "id": "toolu_1", "name": "get_weather", "input": {"location": "San Francisco"}}
65
+
66
+ data: {"type": "message_snapshot", "message_id": "msg_2", "role": "assistant", "content_blocks": [{"id": "toolu_1", "type": "tool_use", "name": "get_weather", "input": {"location": "San Francisco"}}], "usage": {"input_tokens": 200, "output_tokens": 20}}
67
+
68
+ data: {"type": "message_stop", "message_id": "msg_2"}
69
+
70
+ data: {"type": "tool_result", "tool_use_id": "toolu_1", "content": "Sunny, 72\xB0F", "result": "Sunny, 72\xB0F"}
71
+
72
+ data: {"type": "message_snapshot", "message_id": "msg_3", "role": "user", "content_blocks": [{"type": "tool_result", "tool_use_id": "toolu_1", "content": "Sunny, 72\xB0F"}]}
73
+
74
+ data: {"type": "done", "message_count": 3, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
75
+
76
+ `,
77
+ /** HITL tool approval. Segment 1 ends on awaiting_approval (no done). Segment 2
78
+ * (post-approve resume stream) delivers the tool_result -> done. */
79
+ "permission-approve": `data: {"type": "metadata", "run_id": 124, "mode": "chat", "run_uuid": "run-def"}
80
+
81
+ data: {"type": "message_start", "message": {"id": "msg_4", "role": "assistant", "content": [], "usage": {"input_tokens": 150, "output_tokens": 0}}}
82
+
83
+ data: {"type": "content_block_start", "id": "toolu_2", "block_type": "tool_use", "name": "Bash"}
84
+
85
+ data: {"type": "content_block_delta", "id": "toolu_2", "delta": {"type": "input_json_delta", "partial_json": "{\\"command\\": \\"rm -rf build\\"}"}}
86
+
87
+ data: {"type": "content_block_stop", "id": "toolu_2"}
88
+
89
+ data: {"type": "awaiting_approval", "request_id": "r1", "tool_name": "Bash", "tool_input": {"command": "rm -rf build"}, "timeout_seconds": 55}
90
+
91
+ : resume after approval
92
+
93
+ data: {"type": "metadata", "run_id": 124, "mode": "chat", "run_uuid": "run-def"}
94
+
95
+ data: {"type": "tool_result", "tool_use_id": "toolu_2", "content": "", "result": ""}
96
+
97
+ data: {"type": "done", "message_count": 5, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
98
+
99
+ `,
100
+ /** AskUserQuestion HITL: awaiting_approval(tool_name=AskUserQuestion) must
101
+ * normalize to a `question`, not `approval-request`. Resume delivers the
102
+ * answer as a tool_result for the AskUserQuestion id. */
103
+ "question-answer": `data: {"type": "metadata", "run_id": 125, "mode": "chat", "run_uuid": "run-ghi"}
104
+
105
+ data: {"type": "message_start", "message": {"id": "msg_6", "role": "assistant", "content": [], "usage": {"input_tokens": 120, "output_tokens": 0}}}
106
+
107
+ data: {"type": "content_block_start", "id": "toolu_3", "block_type": "tool_use", "name": "AskUserQuestion"}
108
+
109
+ data: {"type": "content_block_stop", "id": "toolu_3"}
110
+
111
+ data: {"type": "awaiting_approval", "request_id": "q1", "tool_name": "AskUserQuestion", "tool_input": {"questions": [{"question": "Which budget?", "options": [{"label": "$5k", "description": "Conservative start"}, {"label": "$10k"}]}]}, "timeout_seconds": 0}
112
+
113
+ : resume after answer
114
+
115
+ data: {"type": "metadata", "run_id": 125, "mode": "chat", "run_uuid": "run-ghi"}
116
+
117
+ data: {"type": "tool_result", "tool_use_id": "toolu_3", "content": "$10k", "result": "$10k"}
118
+
119
+ data: {"type": "done", "message_count": 4, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
120
+
121
+ `,
122
+ /** Terminal error: partial text then `error` ends the stream with NO done. */
123
+ "error-before-done": `data: {"type": "metadata", "run_id": 126, "mode": "chat", "run_uuid": "run-jkl"}
124
+
125
+ data: {"type": "content_block_start", "id": "block_2", "block_type": "text"}
126
+
127
+ data: {"type": "content_block_delta", "id": "block_2", "delta": {"type": "text_delta", "text": "Working on it"}}
128
+
129
+ data: {"type": "error", "error": "Connection reset", "message": "Agent execution failed"}
130
+
131
+ `,
132
+ /** Terminal-but-unsuccessful: `done` with completion_state !== complete and a
133
+ * pending tool. run_metrics carries the diagnostics block. */
134
+ "done-with-error": `data: {"type": "metadata", "run_id": 127, "mode": "chat", "run_uuid": "run-mno"}
135
+
136
+ data: {"type": "content_block_start", "id": "toolu_4", "block_type": "tool_use", "name": "Bash"}
137
+
138
+ data: {"type": "content_block_stop", "id": "toolu_4"}
139
+
140
+ data: {"type": "run_metrics", "model": "claude-opus-4-8", "execution_time_ms": 60000, "input_tokens_used": 90, "output_tokens_used": 12, "claude_token_cost_usd": 0.006, "stop_reason": null, "completion_state": "incomplete_tool_loop", "unresolved_tool_use_ids": ["toolu_4"], "terminal_completion_seen": false, "sdk_total_cost_usd": 0.0065, "code_version": "v2-46", "message_count": 1, "last_event_type": "content_block_stop", "retry_count": 0, "diagnostics": {"pending_tool_ids": ["toolu_4"]}}
141
+
142
+ data: {"type": "done", "message_count": 1, "completion_state": "incomplete_tool_loop", "unresolved_tool_use_ids": ["toolu_4"], "stop_reason": null, "terminal_completion_seen": false}
143
+
144
+ `,
145
+ /** Backend-injected cancellation: partial text then `cancelled` ends the stream. */
146
+ cancelled: `data: {"type": "metadata", "run_id": 128, "mode": "chat", "run_uuid": "run-pqr"}
147
+
148
+ data: {"type": "content_block_start", "id": "block_3", "block_type": "text"}
149
+
150
+ data: {"type": "content_block_delta", "id": "block_3", "delta": {"type": "text_delta", "text": "Analyzing"}}
151
+
152
+ data: {"type": "cancelled", "run_id": 128}
153
+
154
+ `,
155
+ /** GET /stream rejoin of run 123: re-synthesized metadata + user_message (no id),
156
+ * the SAME block_1 streamed again, a snapshot re-covering block_1 (duplicate),
157
+ * and the SAME permission_request request_id TWICE. Client must render block_1
158
+ * ONCE and show ONE approval. */
159
+ "reconnect-replay-with-duplicates": `: keep-alive
160
+
161
+ data: {"type": "metadata", "run_id": 123, "mode": "chat", "run_uuid": "run-abc"}
162
+
163
+ data: {"type": "user_message", "content": "What is the weather?"}
164
+
165
+ data: {"type": "content_block_start", "id": "block_1", "block_type": "text"}
166
+
167
+ data: {"type": "content_block_delta", "id": "block_1", "delta": {"type": "text_delta", "text": "Hello"}}
168
+
169
+ data: {"type": "content_block_delta", "id": "block_1", "delta": {"type": "text_delta", "text": " world"}}
170
+
171
+ data: {"type": "content_block_stop", "id": "block_1"}
172
+
173
+ data: {"type": "message_snapshot", "message_id": "msg_1", "role": "assistant", "content_blocks": [{"type": "text", "text": "Hello world"}], "usage": {"input_tokens": 100, "output_tokens": 5}}
174
+
175
+ data: {"type": "permission_request", "request_id": "r1", "tool_name": "Bash", "tool_input": {"command": "rm -rf build"}, "timeout_seconds": 55}
176
+
177
+ data: {"type": "permission_request", "request_id": "r1", "tool_name": "Bash", "tool_input": {"command": "rm -rf build"}, "timeout_seconds": 55}
178
+
179
+ data: {"type": "done", "message_count": 1, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
180
+
181
+ `,
182
+ /** Parser robustness: a glued concatenated-JSON frame (two objects), an
183
+ * invalid/unterminated JSON frame that must be dropped without crashing, then
184
+ * valid frames so the stream recovers to done. */
185
+ "malformed-frame": `data: {"type": "metadata", "run_id": 129, "mode": "chat", "run_uuid": "run-stu"}
186
+
187
+ data: {"type": "content_block_start", "id": "block_4", "block_type": "text"}
188
+
189
+ data: {"type": "content_block_delta", "id": "block_4", "delta": {"type": "text_delta", "text": "ok"}}{"type": "content_block_delta", "id": "block_4", "delta": {"type": "text_delta", "text": " glued"}}
190
+
191
+ data: {"type": "message_delta", "delta": {"text": "broken
192
+
193
+ data: {"type": "content_block_stop", "id": "block_4"}
194
+
195
+ data: {"type": "done", "message_count": 1, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
196
+
197
+ `,
198
+ /** Empty/whitespace payloads: an empty text_delta, a real delta, an empty
199
+ * top-level message_delta. Final text must equal just the real content. */
200
+ "empty-deltas": `data: {"type": "metadata", "run_id": 130, "mode": "chat", "run_uuid": "run-vwx"}
201
+
202
+ data: {"type": "content_block_start", "id": "block_5", "block_type": "text"}
203
+
204
+ data: {"type": "content_block_delta", "id": "block_5", "delta": {"type": "text_delta", "text": ""}}
205
+
206
+ data: {"type": "content_block_delta", "id": "block_5", "delta": {"type": "text_delta", "text": "real"}}
207
+
208
+ data: {"type": "message_delta", "delta": {"text": ""}}
209
+
210
+ data: {"type": "content_block_stop", "id": "block_5"}
211
+
212
+ data: {"type": "done", "message_count": 1, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
213
+
214
+ `,
215
+ /** Keepalive/no-op handling via both layers: `: keep-alive` comment, JSON
216
+ * keep-alive, `: ping` comment, JSON ping — all dropped — around a real text block. */
217
+ keepalive: `: keep-alive
218
+
219
+ data: {"type": "keep-alive", "message": "Connection established"}
220
+
221
+ : ping
222
+
223
+ data: {"type": "ping"}
224
+
225
+ data: {"type": "metadata", "run_id": 131, "mode": "chat", "run_uuid": "run-yz"}
226
+
227
+ data: {"type": "content_block_start", "id": "block_6", "block_type": "text"}
228
+
229
+ data: {"type": "content_block_delta", "id": "block_6", "delta": {"type": "text_delta", "text": "Hi"}}
230
+
231
+ data: {"type": "content_block_stop", "id": "block_6"}
232
+
233
+ data: {"type": "done", "message_count": 1, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
234
+
235
+ `,
236
+ /** Extended thinking: thinking deltas carry `delta.thinking` (NOT `text`),
237
+ * signature_delta is ignored, and the snapshot copy of the thinking block is
238
+ * `{"type": "thinking", "thinking": ...}` with NO id (runtime accumulator
239
+ * shape) — it must dedupe against the streamed content, not re-render. */
240
+ "thinking-run": `data: {"type": "metadata", "run_id": 132, "mode": "chat", "run_uuid": "run-think"}
241
+
242
+ data: {"type": "message_start", "message": {"id": "msg_7", "role": "assistant", "content": [], "usage": {"input_tokens": 80, "output_tokens": 0}}}
243
+
244
+ data: {"type": "content_block_start", "id": "block_7", "block_type": "thinking"}
245
+
246
+ data: {"type": "content_block_delta", "id": "block_7", "delta": {"type": "thinking_delta", "thinking": "Let me check"}}
247
+
248
+ data: {"type": "content_block_delta", "id": "block_7", "delta": {"type": "thinking_delta", "thinking": " the budget"}}
249
+
250
+ data: {"type": "content_block_delta", "id": "block_7", "delta": {"type": "signature_delta", "signature": "sig_abc"}}
251
+
252
+ data: {"type": "content_block_stop", "id": "block_7"}
253
+
254
+ data: {"type": "content_block_start", "id": "block_8", "block_type": "text"}
255
+
256
+ data: {"type": "content_block_delta", "id": "block_8", "delta": {"type": "text_delta", "text": "Done"}}
257
+
258
+ data: {"type": "content_block_stop", "id": "block_8"}
259
+
260
+ data: {"type": "message_snapshot", "message_id": "msg_7", "role": "assistant", "content_blocks": [{"type": "thinking", "thinking": "Let me check the budget", "signature": "sig_abc"}, {"type": "text", "text": "Done"}], "usage": {"input_tokens": 80, "output_tokens": 9}}
261
+
262
+ data: {"type": "message_stop", "message_id": "msg_7"}
263
+
264
+ data: {"type": "done", "message_count": 1, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
265
+
266
+ `,
267
+ /** Snapshot-only output: the CLI-handled-API-error path streams NO content
268
+ * blocks — the synthetic final message_snapshot (id-less text block) is the
269
+ * ONLY carrier of the assistant's output and must render. A replayed copy of
270
+ * the same snapshot must dedupe. */
271
+ "snapshot-only-output": `data: {"type": "metadata", "run_id": 133, "mode": "chat", "run_uuid": "run-snap"}
272
+
273
+ data: {"type": "message_snapshot", "message_id": "msg_8", "role": "assistant", "content_blocks": [{"type": "text", "text": "Final answer via snapshot"}]}
274
+
275
+ data: {"type": "message_snapshot", "message_id": "msg_8", "role": "assistant", "content_blocks": [{"type": "text", "text": "Final answer via snapshot"}]}
276
+
277
+ data: {"type": "done", "message_count": 1, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": "end_turn", "terminal_completion_seen": true}
278
+
279
+ `,
280
+ /** Anthropic-side failure: the SDK ResultMessage arrives with is_error=true
281
+ * but the wire STILL ends `done` + completion_state "complete" (the backend
282
+ * marks the run failed from is_error). The client must surface the error and
283
+ * suppress the misleading done. */
284
+ "sdk-error-result": `data: {"type": "metadata", "run_id": 134, "mode": "chat", "run_uuid": "run-sdkerr"}
285
+
286
+ data: {"type": "sdk_success", "subtype": "error_during_execution", "is_error": true, "result": "Credit balance is too low", "duration_ms": 1200, "num_turns": 1}
287
+
288
+ data: {"type": "done", "message_count": 0, "completion_state": "complete", "unresolved_tool_use_ids": [], "stop_reason": null, "terminal_completion_seen": true}
289
+
290
+ `
291
+ };
292
+
293
+ export { FIXTURES };
294
+ //# sourceMappingURL=fixtures.js.map
295
+ //# sourceMappingURL=fixtures.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/protocol/fixtures.ts"],"names":[],"mappings":";AAuBO,IAAM,QAAA,GAAW;AAAA;AAAA;AAAA,EAGtB,UAAA,EAAY,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA;AAAA,EA+BZ,gBAAA,EAAkB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA,EAoBlB,qBAAA,EAAuB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA,EA0BvB,oBAAA,EAAsB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA;AAAA,EAyBtB,iBAAA,EAAmB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA,EAqBnB,mBAAA,EAAqB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA,EAYrB,iBAAA,EAAmB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA,EAanB,SAAA,EAAW,CAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAcX,kCAAA,EAAoC,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA;AAAA,EA2BpC,iBAAA,EAAmB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA,EAgBnB,cAAA,EAAgB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA,EAkBhB,SAAA,EAAW,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAuBX,cAAA,EAAgB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAgChB,sBAAA,EAAwB,CAAA;;AAAA;;AAAA;;AAAA;;AAAA,CAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAaxB,kBAAA,EAAoB,CAAA;;AAAA;;AAAA;;AAAA;AAOtB","file":"fixtures.js","sourcesContent":["/**\n * Recorded-style wire fixtures for the SSE parser + normalizer.\n *\n * PUBLIC, via `@m8tes/sdk/fixtures`. It is exported rather than kept private for\n * two reasons: it is the single test oracle for the wire protocol (both\n * `@m8tes/sdk` and `@m8tes/react` assert against THIS file, so there is no\n * second copy to drift), and anyone writing tests for their own protocol\n * consumer — a custom `ToolCall` renderer, a bespoke client — needs realistic\n * streams to feed it. It has its own bundle entry, so it never ships inside the\n * runtime bundles.\n *\n * Each value is the RAW SSE text the m8tes V2 backend sends — frames separated\n * by a blank line, including `: comment` keepalive lines. Derived from the\n * canonical streaming contract (workflow embed-stream-contract). These are the\n * test oracle; they match the documented flat Claude-native wire format.\n *\n * NOTE: a few scenarios encode reality the client must tolerate but that we\n * could not 100% confirm without a live stack (see the plan's \"open contracts\"\n * + the package TODOs): the exact `done-with-error` path, AskUserQuestion\n * rediscovery on rejoin, and concatenated-JSON prevalence. The normalizer is\n * built to handle all of them defensively regardless.\n */\n\nexport const FIXTURES = {\n /** Happy-path text run: preamble (comment + 2 metadata + json keepalive), one\n * streamed text block, terminal snapshot, run_metrics -> done. */\n \"text-run\": `: keep-alive\n\ndata: {\"type\": \"metadata\", \"run_id\": 123, \"mode\": \"chat\", \"run_uuid\": \"run-abc\", \"agent_name\": \"PPC Manager\", \"status\": \"running\"}\n\ndata: {\"type\": \"keep-alive\", \"message\": \"Connection established\"}\n\ndata: {\"type\": \"metadata\", \"run_id\": 123, \"mode\": \"chat\", \"run_uuid\": \"run-abc\"}\n\ndata: {\"type\": \"message_start\", \"message\": {\"id\": \"msg_1\", \"role\": \"assistant\", \"content\": [], \"usage\": {\"input_tokens\": 100, \"output_tokens\": 0}}}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_1\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_1\", \"delta\": {\"type\": \"text_delta\", \"text\": \"Hello\"}}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_1\", \"delta\": {\"type\": \"text_delta\", \"text\": \" world\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"block_1\"}\n\ndata: {\"type\": \"message_snapshot\", \"message_id\": \"msg_1\", \"role\": \"assistant\", \"content_blocks\": [{\"type\": \"text\", \"text\": \"Hello world\"}], \"usage\": {\"input_tokens\": 100, \"output_tokens\": 5}}\n\ndata: {\"type\": \"message_stop\", \"message_id\": \"msg_1\"}\n\ndata: {\"type\": \"run_metrics\", \"model\": \"claude-opus-4-8\", \"execution_time_ms\": 1840, \"input_tokens_used\": 100, \"output_tokens_used\": 5, \"claude_token_cost_usd\": 0.004, \"stop_reason\": \"end_turn\", \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"terminal_completion_seen\": true, \"sdk_total_cost_usd\": 0.0045, \"code_version\": \"v2-46\", \"message_count\": 1, \"last_event_type\": \"message_complete\", \"retry_count\": 0}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** Computer-use screenshot: tool_result whose content is an array holding a\n * base64 image block (the desktop MCP server's `_png_to_image_block` shape).\n * Platform renders these inline (BubbleTimeline tool_result case). */\n \"screenshot-run\": `data: {\"type\": \"message_start\", \"message\": {\"id\": \"msg_s1\", \"role\": \"assistant\", \"content\": [], \"usage\": {\"input_tokens\": 100, \"output_tokens\": 0}}}\n\ndata: {\"type\": \"tool_use\", \"id\": \"toolu_pre1\", \"name\": \"bash\", \"input\": {\"command\": \"ls\"}}\n\ndata: {\"type\": \"tool_result\", \"tool_use_id\": \"toolu_pre1\", \"content\": \"ok\", \"result\": \"ok\"}\n\ndata: {\"type\": \"tool_use\", \"id\": \"toolu_pre2\", \"name\": \"bash\", \"input\": {\"command\": \"pwd\"}}\n\ndata: {\"type\": \"tool_result\", \"tool_use_id\": \"toolu_pre2\", \"content\": \"/\", \"result\": \"/\"}\n\ndata: {\"type\": \"tool_use\", \"id\": \"toolu_shot\", \"name\": \"computer\", \"input\": {\"action\": \"screenshot\"}}\n\ndata: {\"type\": \"tool_result\", \"tool_use_id\": \"toolu_shot\", \"content\": [{\"type\": \"image\", \"source\": {\"type\": \"base64\", \"media_type\": \"image/png\", \"data\": \"iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mP8z8BQDwAEhQGAhKmMIQAAAABJRU5ErkJggg==\"}}]}\n\ndata: {\"type\": \"done\", \"message_count\": 2, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** Full tool chain: block-start(tool_use) -> input_json_delta streaming ->\n * block-stop -> standalone tool_use (resolved input, SAME id) -> tool_result. */\n \"tool-call-lifecycle\": `data: {\"type\": \"message_start\", \"message\": {\"id\": \"msg_2\", \"role\": \"assistant\", \"content\": [], \"usage\": {\"input_tokens\": 200, \"output_tokens\": 0}}}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"toolu_1\", \"block_type\": \"tool_use\", \"name\": \"get_weather\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"toolu_1\", \"delta\": {\"type\": \"input_json_delta\", \"partial_json\": \"{\\\\\"location\\\\\": \\\\\"San\"}}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"toolu_1\", \"delta\": {\"type\": \"input_json_delta\", \"partial_json\": \" Francisco\\\\\"}\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"toolu_1\"}\n\ndata: {\"type\": \"tool_use\", \"id\": \"toolu_1\", \"name\": \"get_weather\", \"input\": {\"location\": \"San Francisco\"}}\n\ndata: {\"type\": \"message_snapshot\", \"message_id\": \"msg_2\", \"role\": \"assistant\", \"content_blocks\": [{\"id\": \"toolu_1\", \"type\": \"tool_use\", \"name\": \"get_weather\", \"input\": {\"location\": \"San Francisco\"}}], \"usage\": {\"input_tokens\": 200, \"output_tokens\": 20}}\n\ndata: {\"type\": \"message_stop\", \"message_id\": \"msg_2\"}\n\ndata: {\"type\": \"tool_result\", \"tool_use_id\": \"toolu_1\", \"content\": \"Sunny, 72°F\", \"result\": \"Sunny, 72°F\"}\n\ndata: {\"type\": \"message_snapshot\", \"message_id\": \"msg_3\", \"role\": \"user\", \"content_blocks\": [{\"type\": \"tool_result\", \"tool_use_id\": \"toolu_1\", \"content\": \"Sunny, 72°F\"}]}\n\ndata: {\"type\": \"done\", \"message_count\": 3, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** HITL tool approval. Segment 1 ends on awaiting_approval (no done). Segment 2\n * (post-approve resume stream) delivers the tool_result -> done. */\n \"permission-approve\": `data: {\"type\": \"metadata\", \"run_id\": 124, \"mode\": \"chat\", \"run_uuid\": \"run-def\"}\n\ndata: {\"type\": \"message_start\", \"message\": {\"id\": \"msg_4\", \"role\": \"assistant\", \"content\": [], \"usage\": {\"input_tokens\": 150, \"output_tokens\": 0}}}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"toolu_2\", \"block_type\": \"tool_use\", \"name\": \"Bash\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"toolu_2\", \"delta\": {\"type\": \"input_json_delta\", \"partial_json\": \"{\\\\\"command\\\\\": \\\\\"rm -rf build\\\\\"}\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"toolu_2\"}\n\ndata: {\"type\": \"awaiting_approval\", \"request_id\": \"r1\", \"tool_name\": \"Bash\", \"tool_input\": {\"command\": \"rm -rf build\"}, \"timeout_seconds\": 55}\n\n: resume after approval\n\ndata: {\"type\": \"metadata\", \"run_id\": 124, \"mode\": \"chat\", \"run_uuid\": \"run-def\"}\n\ndata: {\"type\": \"tool_result\", \"tool_use_id\": \"toolu_2\", \"content\": \"\", \"result\": \"\"}\n\ndata: {\"type\": \"done\", \"message_count\": 5, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** AskUserQuestion HITL: awaiting_approval(tool_name=AskUserQuestion) must\n * normalize to a `question`, not `approval-request`. Resume delivers the\n * answer as a tool_result for the AskUserQuestion id. */\n \"question-answer\": `data: {\"type\": \"metadata\", \"run_id\": 125, \"mode\": \"chat\", \"run_uuid\": \"run-ghi\"}\n\ndata: {\"type\": \"message_start\", \"message\": {\"id\": \"msg_6\", \"role\": \"assistant\", \"content\": [], \"usage\": {\"input_tokens\": 120, \"output_tokens\": 0}}}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"toolu_3\", \"block_type\": \"tool_use\", \"name\": \"AskUserQuestion\"}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"toolu_3\"}\n\ndata: {\"type\": \"awaiting_approval\", \"request_id\": \"q1\", \"tool_name\": \"AskUserQuestion\", \"tool_input\": {\"questions\": [{\"question\": \"Which budget?\", \"options\": [{\"label\": \"$5k\", \"description\": \"Conservative start\"}, {\"label\": \"$10k\"}]}]}, \"timeout_seconds\": 0}\n\n: resume after answer\n\ndata: {\"type\": \"metadata\", \"run_id\": 125, \"mode\": \"chat\", \"run_uuid\": \"run-ghi\"}\n\ndata: {\"type\": \"tool_result\", \"tool_use_id\": \"toolu_3\", \"content\": \"$10k\", \"result\": \"$10k\"}\n\ndata: {\"type\": \"done\", \"message_count\": 4, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** Terminal error: partial text then `error` ends the stream with NO done. */\n \"error-before-done\": `data: {\"type\": \"metadata\", \"run_id\": 126, \"mode\": \"chat\", \"run_uuid\": \"run-jkl\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_2\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_2\", \"delta\": {\"type\": \"text_delta\", \"text\": \"Working on it\"}}\n\ndata: {\"type\": \"error\", \"error\": \"Connection reset\", \"message\": \"Agent execution failed\"}\n\n`,\n\n /** Terminal-but-unsuccessful: `done` with completion_state !== complete and a\n * pending tool. run_metrics carries the diagnostics block. */\n \"done-with-error\": `data: {\"type\": \"metadata\", \"run_id\": 127, \"mode\": \"chat\", \"run_uuid\": \"run-mno\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"toolu_4\", \"block_type\": \"tool_use\", \"name\": \"Bash\"}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"toolu_4\"}\n\ndata: {\"type\": \"run_metrics\", \"model\": \"claude-opus-4-8\", \"execution_time_ms\": 60000, \"input_tokens_used\": 90, \"output_tokens_used\": 12, \"claude_token_cost_usd\": 0.006, \"stop_reason\": null, \"completion_state\": \"incomplete_tool_loop\", \"unresolved_tool_use_ids\": [\"toolu_4\"], \"terminal_completion_seen\": false, \"sdk_total_cost_usd\": 0.0065, \"code_version\": \"v2-46\", \"message_count\": 1, \"last_event_type\": \"content_block_stop\", \"retry_count\": 0, \"diagnostics\": {\"pending_tool_ids\": [\"toolu_4\"]}}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"incomplete_tool_loop\", \"unresolved_tool_use_ids\": [\"toolu_4\"], \"stop_reason\": null, \"terminal_completion_seen\": false}\n\n`,\n\n /** Backend-injected cancellation: partial text then `cancelled` ends the stream. */\n cancelled: `data: {\"type\": \"metadata\", \"run_id\": 128, \"mode\": \"chat\", \"run_uuid\": \"run-pqr\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_3\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_3\", \"delta\": {\"type\": \"text_delta\", \"text\": \"Analyzing\"}}\n\ndata: {\"type\": \"cancelled\", \"run_id\": 128}\n\n`,\n\n /** GET /stream rejoin of run 123: re-synthesized metadata + user_message (no id),\n * the SAME block_1 streamed again, a snapshot re-covering block_1 (duplicate),\n * and the SAME permission_request request_id TWICE. Client must render block_1\n * ONCE and show ONE approval. */\n \"reconnect-replay-with-duplicates\": `: keep-alive\n\ndata: {\"type\": \"metadata\", \"run_id\": 123, \"mode\": \"chat\", \"run_uuid\": \"run-abc\"}\n\ndata: {\"type\": \"user_message\", \"content\": \"What is the weather?\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_1\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_1\", \"delta\": {\"type\": \"text_delta\", \"text\": \"Hello\"}}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_1\", \"delta\": {\"type\": \"text_delta\", \"text\": \" world\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"block_1\"}\n\ndata: {\"type\": \"message_snapshot\", \"message_id\": \"msg_1\", \"role\": \"assistant\", \"content_blocks\": [{\"type\": \"text\", \"text\": \"Hello world\"}], \"usage\": {\"input_tokens\": 100, \"output_tokens\": 5}}\n\ndata: {\"type\": \"permission_request\", \"request_id\": \"r1\", \"tool_name\": \"Bash\", \"tool_input\": {\"command\": \"rm -rf build\"}, \"timeout_seconds\": 55}\n\ndata: {\"type\": \"permission_request\", \"request_id\": \"r1\", \"tool_name\": \"Bash\", \"tool_input\": {\"command\": \"rm -rf build\"}, \"timeout_seconds\": 55}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** Parser robustness: a glued concatenated-JSON frame (two objects), an\n * invalid/unterminated JSON frame that must be dropped without crashing, then\n * valid frames so the stream recovers to done. */\n \"malformed-frame\": `data: {\"type\": \"metadata\", \"run_id\": 129, \"mode\": \"chat\", \"run_uuid\": \"run-stu\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_4\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_4\", \"delta\": {\"type\": \"text_delta\", \"text\": \"ok\"}}{\"type\": \"content_block_delta\", \"id\": \"block_4\", \"delta\": {\"type\": \"text_delta\", \"text\": \" glued\"}}\n\ndata: {\"type\": \"message_delta\", \"delta\": {\"text\": \"broken\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"block_4\"}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** Empty/whitespace payloads: an empty text_delta, a real delta, an empty\n * top-level message_delta. Final text must equal just the real content. */\n \"empty-deltas\": `data: {\"type\": \"metadata\", \"run_id\": 130, \"mode\": \"chat\", \"run_uuid\": \"run-vwx\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_5\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_5\", \"delta\": {\"type\": \"text_delta\", \"text\": \"\"}}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_5\", \"delta\": {\"type\": \"text_delta\", \"text\": \"real\"}}\n\ndata: {\"type\": \"message_delta\", \"delta\": {\"text\": \"\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"block_5\"}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** Keepalive/no-op handling via both layers: `: keep-alive` comment, JSON\n * keep-alive, `: ping` comment, JSON ping — all dropped — around a real text block. */\n keepalive: `: keep-alive\n\ndata: {\"type\": \"keep-alive\", \"message\": \"Connection established\"}\n\n: ping\n\ndata: {\"type\": \"ping\"}\n\ndata: {\"type\": \"metadata\", \"run_id\": 131, \"mode\": \"chat\", \"run_uuid\": \"run-yz\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_6\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_6\", \"delta\": {\"type\": \"text_delta\", \"text\": \"Hi\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"block_6\"}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n /** Extended thinking: thinking deltas carry `delta.thinking` (NOT `text`),\n * signature_delta is ignored, and the snapshot copy of the thinking block is\n * `{\"type\": \"thinking\", \"thinking\": ...}` with NO id (runtime accumulator\n * shape) — it must dedupe against the streamed content, not re-render. */\n \"thinking-run\": `data: {\"type\": \"metadata\", \"run_id\": 132, \"mode\": \"chat\", \"run_uuid\": \"run-think\"}\n\ndata: {\"type\": \"message_start\", \"message\": {\"id\": \"msg_7\", \"role\": \"assistant\", \"content\": [], \"usage\": {\"input_tokens\": 80, \"output_tokens\": 0}}}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_7\", \"block_type\": \"thinking\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_7\", \"delta\": {\"type\": \"thinking_delta\", \"thinking\": \"Let me check\"}}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_7\", \"delta\": {\"type\": \"thinking_delta\", \"thinking\": \" the budget\"}}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_7\", \"delta\": {\"type\": \"signature_delta\", \"signature\": \"sig_abc\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"block_7\"}\n\ndata: {\"type\": \"content_block_start\", \"id\": \"block_8\", \"block_type\": \"text\"}\n\ndata: {\"type\": \"content_block_delta\", \"id\": \"block_8\", \"delta\": {\"type\": \"text_delta\", \"text\": \"Done\"}}\n\ndata: {\"type\": \"content_block_stop\", \"id\": \"block_8\"}\n\ndata: {\"type\": \"message_snapshot\", \"message_id\": \"msg_7\", \"role\": \"assistant\", \"content_blocks\": [{\"type\": \"thinking\", \"thinking\": \"Let me check the budget\", \"signature\": \"sig_abc\"}, {\"type\": \"text\", \"text\": \"Done\"}], \"usage\": {\"input_tokens\": 80, \"output_tokens\": 9}}\n\ndata: {\"type\": \"message_stop\", \"message_id\": \"msg_7\"}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n\n /** Snapshot-only output: the CLI-handled-API-error path streams NO content\n * blocks — the synthetic final message_snapshot (id-less text block) is the\n * ONLY carrier of the assistant's output and must render. A replayed copy of\n * the same snapshot must dedupe. */\n \"snapshot-only-output\": `data: {\"type\": \"metadata\", \"run_id\": 133, \"mode\": \"chat\", \"run_uuid\": \"run-snap\"}\n\ndata: {\"type\": \"message_snapshot\", \"message_id\": \"msg_8\", \"role\": \"assistant\", \"content_blocks\": [{\"type\": \"text\", \"text\": \"Final answer via snapshot\"}]}\n\ndata: {\"type\": \"message_snapshot\", \"message_id\": \"msg_8\", \"role\": \"assistant\", \"content_blocks\": [{\"type\": \"text\", \"text\": \"Final answer via snapshot\"}]}\n\ndata: {\"type\": \"done\", \"message_count\": 1, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": \"end_turn\", \"terminal_completion_seen\": true}\n\n`,\n /** Anthropic-side failure: the SDK ResultMessage arrives with is_error=true\n * but the wire STILL ends `done` + completion_state \"complete\" (the backend\n * marks the run failed from is_error). The client must surface the error and\n * suppress the misleading done. */\n \"sdk-error-result\": `data: {\"type\": \"metadata\", \"run_id\": 134, \"mode\": \"chat\", \"run_uuid\": \"run-sdkerr\"}\n\ndata: {\"type\": \"sdk_success\", \"subtype\": \"error_during_execution\", \"is_error\": true, \"result\": \"Credit balance is too low\", \"duration_ms\": 1200, \"num_turns\": 1}\n\ndata: {\"type\": \"done\", \"message_count\": 0, \"completion_state\": \"complete\", \"unresolved_tool_use_ids\": [], \"stop_reason\": null, \"terminal_completion_seen\": true}\n\n`,\n} as const;\n\nexport type FixtureName = keyof typeof FIXTURES;\n"]}