@anvia/client 1.0.0-rc.10

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.
package/dist/index.js ADDED
@@ -0,0 +1,2522 @@
1
+ import {
2
+ createFetchEventTransport
3
+ } from "./chunk-2KGXQZWA.js";
4
+
5
+ // src/adapters.ts
6
+ import {
7
+ isJsonValue as isJsonValue3
8
+ } from "@anvia/core/completion";
9
+
10
+ // src/messages.ts
11
+ import { isJsonValue } from "@anvia/core/completion";
12
+ function uiMessagesToMessages(messages) {
13
+ const result = [];
14
+ for (const message of messages) {
15
+ assertMetadata(message.metadata);
16
+ if (message.role === "system") {
17
+ assertOnlyParts(message, ["text", "data", "error"]);
18
+ result.push({
19
+ role: "system",
20
+ content: textFromParts(message.parts),
21
+ ...metadataField(message.metadata)
22
+ });
23
+ continue;
24
+ }
25
+ if (message.role === "user") {
26
+ assertOnlyParts(message, ["text", "attachment", "data", "error"]);
27
+ const content2 = [];
28
+ for (const part of message.parts) {
29
+ if (part.type === "text") {
30
+ content2.push(textContent(part.text, part.signature));
31
+ } else if (part.type === "attachment") {
32
+ content2.push(attachmentToUserContent(part.attachment));
33
+ }
34
+ }
35
+ result.push({ role: "user", content: content2, ...metadataField(message.metadata) });
36
+ continue;
37
+ }
38
+ if (message.role === "assistant") {
39
+ assertOnlyParts(message, [
40
+ "text",
41
+ "reasoning",
42
+ "tool",
43
+ "attachment",
44
+ "source",
45
+ "data",
46
+ "error"
47
+ ]);
48
+ const content2 = [];
49
+ const toolResults = [];
50
+ for (const part of message.parts) {
51
+ if (part.type === "text") {
52
+ content2.push(textContent(part.text, part.signature));
53
+ } else if (part.type === "reasoning") {
54
+ let reasoning = {
55
+ type: "reasoning",
56
+ text: part.text
57
+ };
58
+ if (part.reasoningId !== void 0) reasoning = { ...reasoning, id: part.reasoningId };
59
+ if (part.content !== void 0) reasoning = { ...reasoning, details: part.content };
60
+ content2.push(reasoning);
61
+ } else if (part.type === "tool") {
62
+ assertReplayableToolPart(part);
63
+ let toolCall = {
64
+ type: "tool-call",
65
+ toolCallId: part.toolCallId,
66
+ toolName: part.toolName,
67
+ input: part.input
68
+ };
69
+ if (part.callId !== void 0) toolCall = { ...toolCall, callId: part.callId };
70
+ if (part.signature !== void 0) toolCall = { ...toolCall, signature: part.signature };
71
+ content2.push(toolCall);
72
+ if (part.state === "output-available" || part.state === "error") {
73
+ toolResults.push(toolResultFromPart(part));
74
+ }
75
+ } else if (part.type === "attachment") {
76
+ content2.push(attachmentToAssistantContent(part.attachment));
77
+ }
78
+ }
79
+ let assistant = {
80
+ role: "assistant",
81
+ content: content2,
82
+ ...metadataField(message.metadata)
83
+ };
84
+ if (message.modelMessageId !== void 0) {
85
+ assistant = { ...assistant, id: message.modelMessageId };
86
+ }
87
+ result.push(assistant);
88
+ if (toolResults.length > 0) {
89
+ result.push({ role: "tool", content: toolResults });
90
+ }
91
+ continue;
92
+ }
93
+ assertOnlyParts(message, ["tool", "data", "error"]);
94
+ const content = [];
95
+ for (const part of message.parts) {
96
+ if (part.type !== "tool") continue;
97
+ assertToolResultPart(part);
98
+ content.push(toolResultFromPart(part));
99
+ }
100
+ result.push({ role: "tool", content, ...metadataField(message.metadata) });
101
+ }
102
+ return result;
103
+ }
104
+ function messagesToUIMessages(messages) {
105
+ const result = [];
106
+ const byToolCallId = /* @__PURE__ */ new Map();
107
+ const byCallId = /* @__PURE__ */ new Map();
108
+ for (const message of messages) {
109
+ assertMetadata(message.metadata);
110
+ if (message.role === "system") {
111
+ result.push({
112
+ id: createId("msg"),
113
+ role: "system",
114
+ parts: [{ id: createId("part"), type: "text", text: message.content }],
115
+ ...metadataField(message.metadata)
116
+ });
117
+ continue;
118
+ }
119
+ if (message.role === "user") {
120
+ const content = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
121
+ const parts = content.map((part) => contentToUIMessagePart(part));
122
+ result.push({
123
+ id: createId("msg"),
124
+ role: "user",
125
+ parts,
126
+ ...metadataField(message.metadata)
127
+ });
128
+ continue;
129
+ }
130
+ if (message.role === "assistant") {
131
+ const content = typeof message.content === "string" ? [{ type: "text", text: message.content }] : message.content;
132
+ const parts = content.map(assistantContentToUIMessagePart);
133
+ let uiMessage = {
134
+ id: createId("msg"),
135
+ role: "assistant",
136
+ parts,
137
+ ...metadataField(message.metadata)
138
+ };
139
+ if (message.id !== void 0) uiMessage = { ...uiMessage, modelMessageId: message.id };
140
+ const messageIndex = result.length;
141
+ result.push(uiMessage);
142
+ for (const [partIndex, part] of parts.entries()) {
143
+ if (part.type !== "tool") continue;
144
+ const location = { messageIndex, partIndex };
145
+ byToolCallId.set(part.toolCallId, location);
146
+ if (part.callId !== void 0) byCallId.set(part.callId, location);
147
+ }
148
+ continue;
149
+ }
150
+ const unmerged = [];
151
+ for (const content of message.content) {
152
+ if (content.type !== "tool-result") continue;
153
+ const location = (content.callId === void 0 ? void 0 : byCallId.get(content.callId)) ?? byToolCallId.get(content.toolCallId);
154
+ const ownerPart = toolPartAt(result, location);
155
+ if (ownerPart === void 0 || ownerPart.state === "input-streaming") {
156
+ throw new TypeError(
157
+ `Tool result "${content.toolCallId}" requires a matching completed tool call.`
158
+ );
159
+ }
160
+ const part = toolResultToUIMessagePart(content, ownerPart.toolName, ownerPart.input);
161
+ if (message.metadata === void 0 && location !== void 0) {
162
+ const owner = result[location.messageIndex];
163
+ const existing = owner?.parts[location.partIndex];
164
+ if (owner !== void 0 && existing?.type === "tool") {
165
+ const parts = [...owner.parts];
166
+ parts[location.partIndex] = { ...existing, ...part, id: existing.id };
167
+ result[location.messageIndex] = { ...owner, parts };
168
+ continue;
169
+ }
170
+ }
171
+ unmerged.push(part);
172
+ }
173
+ if (unmerged.length > 0 || message.metadata !== void 0) {
174
+ result.push({
175
+ id: createId("msg"),
176
+ role: "tool",
177
+ parts: unmerged,
178
+ ...metadataField(message.metadata)
179
+ });
180
+ }
181
+ }
182
+ return result;
183
+ }
184
+ function contentToUIMessagePart(content) {
185
+ if (content.type === "text") {
186
+ const part = {
187
+ id: createId("part"),
188
+ type: "text",
189
+ text: content.text
190
+ };
191
+ if (content.signature !== void 0) part.signature = content.signature;
192
+ return part;
193
+ }
194
+ return {
195
+ id: createId("part"),
196
+ type: "attachment",
197
+ attachment: contentToAttachment(content)
198
+ };
199
+ }
200
+ function assistantContentToUIMessagePart(content) {
201
+ if (content.type === "text") return contentToUIMessagePart(content);
202
+ if (content.type === "reasoning") {
203
+ const part = {
204
+ id: createId("part"),
205
+ type: "reasoning",
206
+ text: content.text
207
+ };
208
+ if (content.id !== void 0) part.reasoningId = content.id;
209
+ if (content.details !== void 0) part.content = content.details;
210
+ return part;
211
+ }
212
+ if (content.type === "tool-call") {
213
+ const part = {
214
+ id: toolPartId(content.toolCallId),
215
+ type: "tool",
216
+ toolName: content.toolName,
217
+ toolCallId: content.toolCallId,
218
+ state: "input-available",
219
+ input: content.input
220
+ };
221
+ if (content.callId !== void 0) part.callId = content.callId;
222
+ if (content.signature !== void 0) part.signature = content.signature;
223
+ return part;
224
+ }
225
+ return {
226
+ id: createId("part"),
227
+ type: "attachment",
228
+ attachment: contentToAttachment(content)
229
+ };
230
+ }
231
+ function textContent(text, signature) {
232
+ return signature === void 0 ? { type: "text", text } : { type: "text", text, signature };
233
+ }
234
+ function toolResultFromPart(part) {
235
+ let result = {
236
+ type: "tool-result",
237
+ toolCallId: part.toolCallId,
238
+ toolName: part.toolName,
239
+ output: toolOutputFromPart(part)
240
+ };
241
+ if (part.callId !== void 0) result = { ...result, callId: part.callId };
242
+ return result;
243
+ }
244
+ function toolOutputFromPart(part) {
245
+ if (part.state === "error") {
246
+ return { type: "error-text", value: part.error.message };
247
+ }
248
+ if (part.resultContent !== void 0) {
249
+ return { type: "content", value: part.resultContent };
250
+ }
251
+ const output = part.output;
252
+ return typeof output === "string" ? { type: "text", value: output } : { type: "json", value: output };
253
+ }
254
+ function attachmentToUserContent(attachment) {
255
+ if (attachment.type === "image" || attachment.mediaType?.startsWith("image/") === true) {
256
+ return attachmentToImageContent(attachment);
257
+ }
258
+ return attachmentToFileContent(attachment);
259
+ }
260
+ function attachmentToAssistantContent(attachment) {
261
+ return attachment.type === "image" || attachment.mediaType?.startsWith("image/") === true ? attachmentToImageContent(attachment) : attachmentToFileContent(attachment);
262
+ }
263
+ function attachmentToImageContent(attachment) {
264
+ const image = attachment.url !== void 0 ? { type: "url", url: attachment.url } : attachment.data !== void 0 ? { type: "data", data: attachment.data } : (() => {
265
+ throw new TypeError("Image attachments require a URL or base64 data.");
266
+ })();
267
+ let content = {
268
+ type: "image",
269
+ image
270
+ };
271
+ if (attachment.mediaType !== void 0) content = { ...content, mediaType: attachment.mediaType };
272
+ if (attachment.detail !== void 0) content = { ...content, detail: attachment.detail };
273
+ return content;
274
+ }
275
+ function attachmentToFileContent(attachment) {
276
+ const data = attachment.url !== void 0 ? { type: "url", url: attachment.url } : attachment.data !== void 0 ? { type: "data", data: attachment.data } : attachment.text !== void 0 ? { type: "text", text: attachment.text } : (() => {
277
+ throw new TypeError("File attachments require a URL, base64 data, or text.");
278
+ })();
279
+ let content = {
280
+ type: "file",
281
+ data,
282
+ mediaType: attachment.mediaType ?? "application/octet-stream"
283
+ };
284
+ if (attachment.name !== void 0) content = { ...content, filename: attachment.name };
285
+ return content;
286
+ }
287
+ function contentToAttachment(content) {
288
+ const attachment = {
289
+ id: createId("attachment"),
290
+ type: content.type === "image" ? "image" : "file"
291
+ };
292
+ if (content.type === "image") {
293
+ if (content.detail !== void 0) attachment.detail = content.detail;
294
+ if (content.mediaType !== void 0) attachment.mediaType = content.mediaType;
295
+ if (content.image.type === "url") attachment.url = content.image.url;
296
+ else attachment.data = content.image.data;
297
+ return attachment;
298
+ }
299
+ attachment.mediaType = content.mediaType;
300
+ if (content.filename !== void 0) attachment.name = content.filename;
301
+ if (content.data.type === "url") attachment.url = content.data.url;
302
+ else if (content.data.type === "data") attachment.data = content.data.data;
303
+ else attachment.text = content.data.text;
304
+ return attachment;
305
+ }
306
+ function toolResultToUIMessagePart(content, fallbackToolName, input) {
307
+ const output = content.output;
308
+ const common = {
309
+ id: toolPartId(content.toolCallId),
310
+ type: "tool",
311
+ toolName: content.toolName || fallbackToolName,
312
+ toolCallId: content.toolCallId,
313
+ input
314
+ };
315
+ if (content.callId !== void 0) Object.assign(common, { callId: content.callId });
316
+ if (output.type === "error-text" || output.type === "error-json") {
317
+ return {
318
+ ...common,
319
+ state: "error",
320
+ error: {
321
+ message: output.type === "error-text" ? output.value : JSON.stringify(output.value)
322
+ }
323
+ };
324
+ }
325
+ if (output.type === "execution-denied") {
326
+ return {
327
+ ...common,
328
+ state: "error",
329
+ error: { message: output.reason ?? "Tool execution was denied." }
330
+ };
331
+ }
332
+ const part = {
333
+ ...common,
334
+ state: "output-available",
335
+ output: toolResultOutput(output)
336
+ };
337
+ if (output.type === "content") part.resultContent = output.value;
338
+ return part;
339
+ }
340
+ function toolResultOutput(output) {
341
+ if (output.type === "text" || output.type === "error-text") return output.value;
342
+ if (output.type === "json" || output.type === "error-json") return output.value;
343
+ if (output.type === "execution-denied") return output.reason ?? "Tool execution was denied.";
344
+ return output.value.length === 1 && output.value[0]?.type === "text" ? output.value[0].text : output.value.map(
345
+ (part) => part.type === "text" ? { ...part } : { ...part, data: { ...part.data } }
346
+ );
347
+ }
348
+ function toolPartAt(messages, location) {
349
+ if (location === void 0) return void 0;
350
+ const part = messages[location.messageIndex]?.parts[location.partIndex];
351
+ return part?.type === "tool" ? part : void 0;
352
+ }
353
+ function assertReplayableToolPart(part) {
354
+ if (part.state === "input-streaming") {
355
+ throw new TypeError(
356
+ `Tool call "${part.toolCallId}" is still streaming and cannot be converted to a model message.`
357
+ );
358
+ }
359
+ if (!isJsonValue(part.input)) {
360
+ throw new TypeError(`Tool call "${part.toolCallId}" input must be a strict JSON value.`);
361
+ }
362
+ }
363
+ function assertToolResultPart(part) {
364
+ assertReplayableToolPart(part);
365
+ if (part.state === "input-available") {
366
+ throw new TypeError(
367
+ `Tool message part "${part.toolCallId}" requires an output or execution error.`
368
+ );
369
+ }
370
+ }
371
+ function textFromParts(parts) {
372
+ return parts.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
373
+ }
374
+ function assertOnlyParts(message, allowed) {
375
+ for (const part of message.parts) {
376
+ if (!allowed.includes(part.type)) {
377
+ throw new TypeError(`${message.role} UI messages cannot contain ${part.type} parts.`);
378
+ }
379
+ }
380
+ }
381
+ function assertMetadata(metadata) {
382
+ if (metadata !== void 0 && (!isJsonValue(metadata) || Array.isArray(metadata))) {
383
+ throw new TypeError("Message metadata must be a strict JSON object.");
384
+ }
385
+ }
386
+ function metadataField(metadata) {
387
+ return metadata === void 0 ? {} : { metadata };
388
+ }
389
+ function toolPartId(toolCallId) {
390
+ return `tool_${toolCallId}`;
391
+ }
392
+ var nextId = 0;
393
+ function createClientId(prefix) {
394
+ const random = globalThis.crypto?.randomUUID?.();
395
+ if (random !== void 0) return `${prefix}_${random}`;
396
+ nextId += 1;
397
+ return `${prefix}_${nextId.toString(36)}`;
398
+ }
399
+ function createId(prefix) {
400
+ return createClientId(prefix);
401
+ }
402
+
403
+ // src/protocol.ts
404
+ import {
405
+ parseAgentInteractionRequest,
406
+ parseAgentInteractionResponse
407
+ } from "@anvia/core/agent/interactions";
408
+ import { isJsonValue as isJsonValue2, parseMessages } from "@anvia/core/completion";
409
+
410
+ // src/types.ts
411
+ var CLIENT_STREAM_PROTOCOL = "anvia.client.v3";
412
+
413
+ // src/protocol.ts
414
+ var ClientProtocolError = class extends Error {
415
+ constructor(message, value) {
416
+ super(message);
417
+ this.value = value;
418
+ this.name = "ClientProtocolError";
419
+ }
420
+ value;
421
+ };
422
+ function parseUIMessage(value, options = {}) {
423
+ const message = requireRecord(value, "UI message");
424
+ if (!isJsonValue2(message)) {
425
+ throw new ClientProtocolError("UI messages must be strict JSON values.", value);
426
+ }
427
+ requireOnlyKeys(
428
+ message,
429
+ ["id", "role", "parts", "modelMessageId", "metadata", "generation"],
430
+ "UI message"
431
+ );
432
+ if (typeof message.id !== "string") invalid("UI message.id", value);
433
+ requireOneOf(message.role, ["system", "user", "assistant", "tool"], "UI message.role", value);
434
+ if (!Array.isArray(message.parts)) invalid("UI message.parts", value);
435
+ const parts = message.parts.map((part) => parseUIMessagePart(part, options.dataSchemas, value));
436
+ if (message.modelMessageId !== void 0 && typeof message.modelMessageId !== "string") {
437
+ invalid("UI message.modelMessageId", value);
438
+ }
439
+ const metadata = message.metadata === void 0 ? void 0 : parseMetadata(message.metadata, options.metadataSchema, value);
440
+ if (message.generation !== void 0 && !isUIMessageGeneration(message.generation)) {
441
+ invalid("UI message.generation", value);
442
+ }
443
+ let parsed = {
444
+ id: message.id,
445
+ role: message.role,
446
+ parts
447
+ };
448
+ if (message.modelMessageId !== void 0) {
449
+ parsed = { ...parsed, modelMessageId: message.modelMessageId };
450
+ }
451
+ if (metadata !== void 0) parsed = { ...parsed, metadata };
452
+ if (message.generation !== void 0) {
453
+ parsed = { ...parsed, generation: message.generation };
454
+ }
455
+ return parsed;
456
+ }
457
+ function parseUIMessages(value, options = {}) {
458
+ if (!Array.isArray(value)) {
459
+ throw new ClientProtocolError("UI messages must be an array.", value);
460
+ }
461
+ return value.map((message) => parseUIMessage(message, options));
462
+ }
463
+ function parseClientStreamRequest(value) {
464
+ const input = requireRecord(value, "Client stream request");
465
+ requireOnlyKeys(
466
+ input,
467
+ ["type", "messages", "interactionId", "response", "metadata", "resume"],
468
+ "Client stream request"
469
+ );
470
+ requireOneOf(
471
+ input.type,
472
+ ["messages", "interaction_response"],
473
+ "Client stream request.type",
474
+ value
475
+ );
476
+ if (input.metadata !== void 0 && !isJsonObject(input.metadata)) {
477
+ throw new ClientProtocolError("Client stream request.metadata must be a JSON object.", value);
478
+ }
479
+ let request;
480
+ if (input.type === "messages") {
481
+ if (input.interactionId !== void 0 || input.response !== void 0) {
482
+ throw new ClientProtocolError(
483
+ "Messages requests cannot include interaction response fields.",
484
+ value
485
+ );
486
+ }
487
+ let messages;
488
+ try {
489
+ messages = parseMessages(input.messages);
490
+ } catch {
491
+ throw new ClientProtocolError("Client stream request.messages must be Message[].", value);
492
+ }
493
+ request = { type: "messages", messages };
494
+ } else {
495
+ if (input.messages !== void 0 || typeof input.interactionId !== "string") {
496
+ throw new ClientProtocolError(
497
+ "Interaction response requests require interactionId and cannot include messages.",
498
+ value
499
+ );
500
+ }
501
+ try {
502
+ request = {
503
+ type: "interaction_response",
504
+ interactionId: input.interactionId,
505
+ response: parseAgentInteractionResponse(input.response)
506
+ };
507
+ } catch {
508
+ throw new ClientProtocolError("Client interaction response is invalid.", value);
509
+ }
510
+ }
511
+ if (input.metadata !== void 0) request.metadata = input.metadata;
512
+ if (input.resume !== void 0) {
513
+ const resume = requireRecord(input.resume, "Client stream request.resume");
514
+ requireOnlyKeys(resume, ["streamId", "after"], "Client stream request.resume");
515
+ if (typeof resume.streamId !== "string" || !isEventId(resume.after)) {
516
+ throw new ClientProtocolError(
517
+ "Client stream resume cursor requires streamId and a nonnegative safe integer after.",
518
+ value
519
+ );
520
+ }
521
+ request.resume = { streamId: resume.streamId, after: resume.after };
522
+ }
523
+ return request;
524
+ }
525
+ function parseClientStreamEvent(value, options = {}) {
526
+ const event = requireRecord(value, "Client stream event");
527
+ if (!isJsonValue2(event)) {
528
+ throw new ClientProtocolError("Client stream events must be strict JSON values.", value);
529
+ }
530
+ if (typeof event.type !== "string" || typeof event.runId !== "string") {
531
+ throw new ClientProtocolError("Client stream events require type and runId.", value);
532
+ }
533
+ if (event.turn !== void 0 && !isPositiveEventId(event.turn)) {
534
+ throw new ClientProtocolError(
535
+ "Client stream event.turn must be a positive safe integer.",
536
+ value
537
+ );
538
+ }
539
+ if (event.scope !== void 0 && !isScope(event.scope)) {
540
+ throw new ClientProtocolError("Client stream event.scope is invalid.", value);
541
+ }
542
+ switch (event.type) {
543
+ case "run_start":
544
+ requireEventKeys(event, ["source", "metadata"]);
545
+ requireOneOf(event.source, ["completion", "agent"], "run_start.source", value);
546
+ break;
547
+ case "turn_start":
548
+ requireEventKeys(event, []);
549
+ if (!isPositiveEventId(event.turn)) invalid("turn_start.turn", value);
550
+ break;
551
+ case "generation_start":
552
+ requireEventKeys(event, ["model"]);
553
+ if (event.model !== void 0 && (!isRecord(event.model) || !hasOnlyKeys(event.model, ["provider", "modelId"]) || typeof event.model.provider !== "string" || typeof event.model.modelId !== "string")) {
554
+ invalid("generation_start.model", value);
555
+ }
556
+ break;
557
+ case "message_start":
558
+ requireEventKeys(event, ["messageId", "role", "metadata"]);
559
+ requireStrings(event, ["messageId"], value);
560
+ if (event.role !== "assistant") invalid("message_start.role", value);
561
+ break;
562
+ case "text_start":
563
+ requireEventKeys(event, ["messageId", "partId"]);
564
+ requireStrings(event, ["messageId", "partId"], value);
565
+ break;
566
+ case "text_delta":
567
+ requireEventKeys(event, ["messageId", "partId", "delta"]);
568
+ requireStrings(event, ["messageId", "partId", "delta"], value);
569
+ break;
570
+ case "reasoning_delta":
571
+ requireEventKeys(event, ["messageId", "partId", "delta", "contentType", "signature"]);
572
+ requireStrings(event, ["messageId", "partId", "delta"], value);
573
+ requireOptionalStrings(event, ["signature"], value);
574
+ if (event.contentType !== void 0 && !["text", "summary", "encrypted", "redacted"].includes(event.contentType)) {
575
+ invalid("reasoning_delta.contentType", value);
576
+ }
577
+ break;
578
+ case "text_end":
579
+ requireEventKeys(event, ["messageId", "partId", "text", "signature"]);
580
+ requireStrings(event, ["messageId", "partId"], value);
581
+ requireOptionalStrings(event, ["text", "signature"], value);
582
+ break;
583
+ case "reasoning_start":
584
+ requireEventKeys(event, ["messageId", "partId", "reasoningId"]);
585
+ requireStrings(event, ["messageId", "partId"], value);
586
+ requireOptionalStrings(event, ["reasoningId"], value);
587
+ break;
588
+ case "reasoning_end":
589
+ requireEventKeys(event, ["messageId", "partId", "text", "content"]);
590
+ requireStrings(event, ["messageId", "partId"], value);
591
+ requireOptionalStrings(event, ["text"], value);
592
+ if (event.content !== void 0 && (!Array.isArray(event.content) || !event.content.every(isReasoningContent))) {
593
+ invalid("reasoning_end.content", value);
594
+ }
595
+ break;
596
+ case "tool_call_start":
597
+ requireEventKeys(event, ["messageId", "partId", "toolCallId", "callId", "toolName"]);
598
+ requireStrings(event, ["messageId", "partId", "toolCallId"], value);
599
+ requireOptionalStrings(event, ["callId", "toolName"], value);
600
+ break;
601
+ case "tool_call_delta":
602
+ requireEventKeys(event, [
603
+ "messageId",
604
+ "partId",
605
+ "toolCallId",
606
+ "callId",
607
+ "toolName",
608
+ "delta",
609
+ "mode",
610
+ "signature"
611
+ ]);
612
+ requireStrings(event, ["messageId", "partId", "toolCallId", "delta"], value);
613
+ requireOptionalStrings(event, ["callId", "toolName"], value);
614
+ requireOptionalStrings(event, ["signature"], value);
615
+ requireOneOf(event.mode, ["append", "replace"], "tool_call_delta.mode", value);
616
+ break;
617
+ case "tool_call_end":
618
+ requireEventKeys(event, [
619
+ "messageId",
620
+ "partId",
621
+ "toolCallId",
622
+ "callId",
623
+ "toolName",
624
+ "input",
625
+ "signature"
626
+ ]);
627
+ requireStrings(event, ["messageId", "partId", "toolCallId", "toolName"], value);
628
+ requireOptionalStrings(event, ["callId", "signature"], value);
629
+ if (!isJsonValue2(event.input)) invalid("tool_call_end.input", value);
630
+ break;
631
+ case "tool_result":
632
+ requireEventKeys(event, [
633
+ "messageId",
634
+ "partId",
635
+ "toolCallId",
636
+ "callId",
637
+ "internalCallId",
638
+ "toolName",
639
+ "input",
640
+ "result"
641
+ ]);
642
+ requireStrings(event, ["messageId", "partId", "toolCallId", "toolName"], value);
643
+ requireOptionalStrings(event, ["callId", "internalCallId"], value);
644
+ if (!isJsonValue2(event.input)) invalid("tool_result.input", value);
645
+ if (!isRecord(event.result)) invalid("tool_result.result", value);
646
+ if (event.result.status === "success") {
647
+ if (!hasOnlyKeys(event.result, ["status", "output", "content"]) || !isJsonValue2(event.result.output) || event.result.content !== void 0 && (!Array.isArray(event.result.content) || !event.result.content.every(isToolResultContent))) {
648
+ invalid("tool_result.result", value);
649
+ }
650
+ } else if (event.result.status === "error") {
651
+ if (!hasOnlyKeys(event.result, ["status", "error"]) || !isClientStreamError(event.result.error)) {
652
+ invalid("tool_result.result", value);
653
+ }
654
+ } else {
655
+ invalid("tool_result.result.status", value);
656
+ }
657
+ break;
658
+ case "source":
659
+ requireEventKeys(event, ["messageId", "partId", "source"]);
660
+ requireStrings(event, ["messageId", "partId"], value);
661
+ if (!isCompletionSource(event.source)) invalid("source.source", value);
662
+ break;
663
+ case "attachment":
664
+ requireEventKeys(event, ["messageId", "partId", "attachment"]);
665
+ requireStrings(event, ["messageId", "partId"], value);
666
+ if (!isAttachment(event.attachment)) invalid("attachment.attachment", value);
667
+ break;
668
+ case "provider_tool_call":
669
+ requireEventKeys(event, ["toolCall"]);
670
+ if (!isProviderToolCall(event.toolCall)) invalid("provider_tool_call.toolCall", value);
671
+ break;
672
+ case "interaction":
673
+ requireEventKeys(event, ["interaction"]);
674
+ try {
675
+ parseAgentInteractionRequest(event.interaction);
676
+ } catch {
677
+ invalid("interaction.interaction", value);
678
+ }
679
+ break;
680
+ case "guardrail_decision":
681
+ requireEventKeys(event, ["decision"]);
682
+ if (!isGuardrailDecision(event.decision)) invalid("guardrail_decision.decision", value);
683
+ break;
684
+ case "data":
685
+ requireEventKeys(event, ["name", "data", "transient"]);
686
+ requireStrings(event, ["name"], value);
687
+ if (!isJsonValue2(event.data)) invalid("data.data", value);
688
+ if (event.transient !== void 0 && typeof event.transient !== "boolean") {
689
+ invalid("data.transient", value);
690
+ }
691
+ return {
692
+ ...event,
693
+ data: parseDataEvent(event.name, event.data, options.dataSchemas, value)
694
+ };
695
+ case "message_end":
696
+ requireEventKeys(event, [
697
+ "messageId",
698
+ "modelMessageId",
699
+ "parts",
700
+ "usage",
701
+ "contextUsage",
702
+ "metadata"
703
+ ]);
704
+ requireStrings(event, ["messageId"], value);
705
+ requireOptionalStrings(event, ["modelMessageId"], value);
706
+ if (event.parts !== void 0) {
707
+ if (!Array.isArray(event.parts)) invalid("message_end.parts", value);
708
+ const parts = event.parts.map(
709
+ (part) => parseUIMessagePart(part, options.dataSchemas, value)
710
+ );
711
+ validateUsageAndContext(event, value);
712
+ return parseEventMetadata(
713
+ { ...event, parts },
714
+ options.metadataSchema,
715
+ value
716
+ );
717
+ }
718
+ validateUsageAndContext(event, value);
719
+ break;
720
+ case "turn_end":
721
+ requireEventKeys(event, ["usage", "contextUsage", "firstDeltaMs"]);
722
+ if (!isPositiveEventId(event.turn)) invalid("turn_end.turn", value);
723
+ if (event.firstDeltaMs !== void 0 && !isNonnegativeNumber(event.firstDeltaMs)) {
724
+ invalid("turn_end.firstDeltaMs", value);
725
+ }
726
+ validateUsageAndContext(event, value);
727
+ break;
728
+ case "memory_compaction":
729
+ requireEventKeys(event, [
730
+ "originalMessageCount",
731
+ "compactedMessageCount",
732
+ "retainedMessageCount",
733
+ "attempts",
734
+ "usage"
735
+ ]);
736
+ validateMemoryCompactionInfo(event, value);
737
+ break;
738
+ case "run_end":
739
+ requireEventKeys(event, [
740
+ "status",
741
+ "text",
742
+ "output",
743
+ "usage",
744
+ "contextUsage",
745
+ "trace",
746
+ "memoryCompaction",
747
+ "metadata"
748
+ ]);
749
+ requireOneOf(
750
+ event.status,
751
+ ["completed", "blocked", "suspended", "cancelled", "error"],
752
+ "run_end.status",
753
+ value
754
+ );
755
+ requireOptionalStrings(event, ["text"], value);
756
+ validateUsageAndContext(event, value);
757
+ if (event.trace !== void 0 && !isTrace(event.trace)) invalid("run_end.trace", value);
758
+ if (event.memoryCompaction !== void 0) {
759
+ if (!isRecord(event.memoryCompaction)) invalid("run_end.memoryCompaction", value);
760
+ requireOnlyKeys(
761
+ event.memoryCompaction,
762
+ [
763
+ "originalMessageCount",
764
+ "compactedMessageCount",
765
+ "retainedMessageCount",
766
+ "attempts",
767
+ "usage"
768
+ ],
769
+ "run_end.memoryCompaction"
770
+ );
771
+ validateMemoryCompactionInfo(event.memoryCompaction, value);
772
+ }
773
+ break;
774
+ case "error":
775
+ requireEventKeys(event, ["error", "usage"]);
776
+ if (!isClientStreamError(event.error)) invalid("error.error", value);
777
+ if (event.usage !== void 0 && !isUsage(event.usage)) invalid("error.usage", value);
778
+ break;
779
+ default:
780
+ throw new ClientProtocolError(`Unknown client stream event type "${event.type}".`, value);
781
+ }
782
+ return parseEventMetadata(event, options.metadataSchema, value);
783
+ }
784
+ function parseClientStreamFrame(value, options = {}) {
785
+ const frame = requireRecord(value, "Client stream frame");
786
+ if (!isJsonValue2(frame)) {
787
+ throw new ClientProtocolError("Client stream frames must be strict JSON values.", value);
788
+ }
789
+ if (typeof frame.type !== "string") {
790
+ throw new ClientProtocolError("Client stream frames require type.", value);
791
+ }
792
+ if (frame.type === "stream_start") {
793
+ requireOnlyKeys(
794
+ frame,
795
+ ["type", "protocol", "streamId", "eventId", "resumable"],
796
+ "stream_start frame"
797
+ );
798
+ if (frame.protocol === "anvia.client.v1" || frame.protocol === "anvia.client.v2") {
799
+ throw new ClientProtocolError(
800
+ `Client stream protocol ${frame.protocol.slice(-2)} is not supported.`,
801
+ value
802
+ );
803
+ }
804
+ if (frame.protocol !== CLIENT_STREAM_PROTOCOL || typeof frame.streamId !== "string" || frame.eventId !== 0 || typeof frame.resumable !== "boolean") {
805
+ throw new ClientProtocolError("Invalid client stream_start frame.", value);
806
+ }
807
+ return frame;
808
+ }
809
+ if (frame.type === "stream_event") {
810
+ requireOnlyKeys(frame, ["type", "streamId", "eventId", "event"], "stream_event frame");
811
+ if (typeof frame.streamId !== "string" || !isPositiveEventId(frame.eventId)) {
812
+ throw new ClientProtocolError("Invalid client stream_event frame.", value);
813
+ }
814
+ const event = parseClientStreamEvent(frame.event, options);
815
+ return { ...frame, event };
816
+ }
817
+ if (frame.type === "stream_end") {
818
+ requireOnlyKeys(frame, ["type", "streamId", "eventId", "status"], "stream_end frame");
819
+ if (typeof frame.streamId !== "string" || !isEventId(frame.eventId)) {
820
+ throw new ClientProtocolError("Invalid client stream_end frame.", value);
821
+ }
822
+ requireOneOf(frame.status, ["completed", "error", "missing"], "stream_end.status", value);
823
+ return frame;
824
+ }
825
+ throw new ClientProtocolError(`Unknown client stream frame type "${frame.type}".`, value);
826
+ }
827
+ function maskedClientError() {
828
+ return { message: "An unexpected error occurred." };
829
+ }
830
+ function normalizeClientError(value) {
831
+ if (value instanceof Error) return value;
832
+ if (isClientStreamError(value)) {
833
+ const error = new Error(value.message);
834
+ if (value.name !== void 0) error.name = value.name;
835
+ return error;
836
+ }
837
+ return new Error(typeof value === "string" ? value : "An unexpected error occurred.");
838
+ }
839
+ function parseDataEvent(name, data, schemas, value) {
840
+ if (schemas === void 0) return data;
841
+ const schema = schemas[name];
842
+ if (schema === void 0) {
843
+ throw new ClientProtocolError(`Invalid data event "${name}".`, value);
844
+ }
845
+ const parsed = schema.safeParse(data);
846
+ if (parsed.success !== true || !isJsonValue2(parsed.data)) {
847
+ throw new ClientProtocolError(`Invalid data event "${name}".`, value);
848
+ }
849
+ return parsed.data;
850
+ }
851
+ function parseUIMessagePart(value, schemas, root) {
852
+ if (!isUIMessagePart(value)) {
853
+ throw new ClientProtocolError("UI message contains an invalid part.", root);
854
+ }
855
+ if (value.type !== "data") {
856
+ return value;
857
+ }
858
+ return {
859
+ ...value,
860
+ data: parseDataEvent(value.name, value.data, schemas, root)
861
+ };
862
+ }
863
+ function parseMetadata(value, schema, root) {
864
+ if (schema === void 0) {
865
+ if (!isJsonObject(value)) {
866
+ throw new ClientProtocolError("Client metadata must be a JSON object.", root);
867
+ }
868
+ return value;
869
+ }
870
+ const parsed = schema.safeParse(value);
871
+ if (parsed.success !== true || !isJsonObject(parsed.data)) {
872
+ throw new ClientProtocolError("Invalid client metadata.", root);
873
+ }
874
+ return parsed.data;
875
+ }
876
+ function parseEventMetadata(event, schema, root) {
877
+ if (event.metadata === void 0) return event;
878
+ return { ...event, metadata: parseMetadata(event.metadata, schema, root) };
879
+ }
880
+ function isUIMessageGeneration(value) {
881
+ if (!isRecord(value)) return false;
882
+ if (!hasOnlyKeys(value, ["runId", "status", "usage", "contextUsage", "trace", "memoryCompaction"])) {
883
+ return false;
884
+ }
885
+ return (value.runId === void 0 || typeof value.runId === "string") && (value.status === void 0 || ["completed", "blocked", "suspended", "cancelled", "error"].includes(
886
+ value.status
887
+ )) && (value.usage === void 0 || isUsage(value.usage)) && (value.contextUsage === void 0 || isContextUsage(value.contextUsage)) && (value.trace === void 0 || isTrace(value.trace)) && (value.memoryCompaction === void 0 || isRecord(value.memoryCompaction) && validateMemoryCompactionForGuard(value.memoryCompaction));
888
+ }
889
+ function validateMemoryCompactionForGuard(value) {
890
+ try {
891
+ requireOnlyKeys(
892
+ value,
893
+ [
894
+ "originalMessageCount",
895
+ "compactedMessageCount",
896
+ "retainedMessageCount",
897
+ "attempts",
898
+ "usage"
899
+ ],
900
+ "memory compaction"
901
+ );
902
+ validateMemoryCompactionInfo(value, value);
903
+ return true;
904
+ } catch {
905
+ return false;
906
+ }
907
+ }
908
+ function isJsonObject(value) {
909
+ return isRecord(value) && isJsonValue2(value);
910
+ }
911
+ function isClientStreamError(value) {
912
+ return isRecord(value) && hasOnlyKeys(value, ["name", "message", "code", "retryable", "details"]) && typeof value.message === "string" && (value.name === void 0 || typeof value.name === "string") && (value.code === void 0 || typeof value.code === "string") && (value.retryable === void 0 || typeof value.retryable === "boolean") && (value.details === void 0 || isJsonValue2(value.details));
913
+ }
914
+ function isScope(value) {
915
+ if (!isRecord(value)) return false;
916
+ const keys = [
917
+ "agentId",
918
+ "agentName",
919
+ "parentRunId",
920
+ "parentToolName",
921
+ "parentToolCallId",
922
+ "parentInternalToolCallId"
923
+ ];
924
+ return hasOnlyKeys(value, keys) && keys.every((key) => value[key] === void 0 || typeof value[key] === "string");
925
+ }
926
+ function isAttachment(value) {
927
+ if (!isRecord(value) || typeof value.id !== "string") return false;
928
+ if (value.type !== "image" && value.type !== "document" && value.type !== "file") return false;
929
+ return hasOnlyKeys(value, [
930
+ "id",
931
+ "type",
932
+ "name",
933
+ "mediaType",
934
+ "url",
935
+ "data",
936
+ "text",
937
+ "detail",
938
+ "metadata"
939
+ ]) && (value.name === void 0 || typeof value.name === "string") && (value.mediaType === void 0 || typeof value.mediaType === "string") && (value.url === void 0 || typeof value.url === "string") && (value.data === void 0 || typeof value.data === "string") && (value.text === void 0 || typeof value.text === "string") && (value.detail === void 0 || ["auto", "low", "high"].includes(value.detail)) && (value.metadata === void 0 || isJsonValue2(value.metadata));
940
+ }
941
+ function isUIMessagePart(value) {
942
+ if (!isRecord(value) || typeof value.id !== "string" || typeof value.type !== "string") {
943
+ return false;
944
+ }
945
+ if (value.type === "text") {
946
+ return hasOnlyKeys(value, ["id", "type", "text", "signature"]) && typeof value.text === "string" && (value.signature === void 0 || typeof value.signature === "string");
947
+ }
948
+ if (value.type === "reasoning") {
949
+ return hasOnlyKeys(value, ["id", "type", "text", "reasoningId", "content"]) && typeof value.text === "string" && (value.reasoningId === void 0 || typeof value.reasoningId === "string") && (value.content === void 0 || Array.isArray(value.content) && value.content.every(isReasoningContent));
950
+ }
951
+ if (value.type === "source") {
952
+ return hasOnlyKeys(value, ["id", "type", "source"]) && isCompletionSource(value.source);
953
+ }
954
+ if (value.type === "data") {
955
+ return hasOnlyKeys(value, ["id", "type", "name", "data"]) && typeof value.name === "string" && isJsonValue2(value.data);
956
+ }
957
+ if (value.type === "attachment") {
958
+ return hasOnlyKeys(value, ["id", "type", "attachment"]) && isAttachment(value.attachment);
959
+ }
960
+ if (value.type === "error") {
961
+ return hasOnlyKeys(value, ["id", "type", "error"]) && isClientStreamError(value.error);
962
+ }
963
+ if (value.type !== "tool" || !hasOnlyKeys(value, [
964
+ "id",
965
+ "type",
966
+ "toolName",
967
+ "toolCallId",
968
+ "callId",
969
+ "internalCallId",
970
+ "turn",
971
+ "state",
972
+ "input",
973
+ "output",
974
+ "resultContent",
975
+ "signature",
976
+ "error"
977
+ ]) || typeof value.toolName !== "string" || typeof value.toolCallId !== "string" || value.callId !== void 0 && typeof value.callId !== "string" || value.internalCallId !== void 0 && typeof value.internalCallId !== "string" || value.turn !== void 0 && !isPositiveEventId(value.turn) || value.signature !== void 0 && typeof value.signature !== "string") {
978
+ return false;
979
+ }
980
+ if (value.state === "input-streaming") {
981
+ return typeof value.input === "string" && value.output === void 0 && value.resultContent === void 0 && value.error === void 0;
982
+ }
983
+ if (value.state === "input-available") {
984
+ return isJsonValue2(value.input) && value.output === void 0 && value.resultContent === void 0 && value.error === void 0;
985
+ }
986
+ if (value.state === "output-available") {
987
+ return isJsonValue2(value.input) && isJsonValue2(value.output) && (value.resultContent === void 0 || Array.isArray(value.resultContent) && value.resultContent.every(isToolResultContent)) && value.error === void 0;
988
+ }
989
+ return value.state === "error" && isJsonValue2(value.input) && value.output === void 0 && value.resultContent === void 0 && isClientStreamError(value.error);
990
+ }
991
+ function isReasoningContent(value) {
992
+ if (!isRecord(value) || typeof value.type !== "string") return false;
993
+ if (value.type === "text") {
994
+ return hasOnlyKeys(value, ["type", "text", "signature"]) && typeof value.text === "string" && (value.signature === void 0 || typeof value.signature === "string");
995
+ }
996
+ if (value.type === "summary") {
997
+ return hasOnlyKeys(value, ["type", "text"]) && typeof value.text === "string";
998
+ }
999
+ if (value.type === "encrypted" || value.type === "redacted") {
1000
+ return hasOnlyKeys(value, ["type", "data"]) && typeof value.data === "string";
1001
+ }
1002
+ return false;
1003
+ }
1004
+ function isToolResultContent(value) {
1005
+ if (!isRecord(value)) return false;
1006
+ if (value.type === "text") {
1007
+ return hasOnlyKeys(value, ["type", "text", "signature"]) && typeof value.text === "string" && (value.signature === void 0 || typeof value.signature === "string");
1008
+ }
1009
+ return value.type === "file" && hasOnlyKeys(value, ["type", "data", "mediaType", "filename"]) && isFileData(value.data) && typeof value.mediaType === "string" && (value.filename === void 0 || typeof value.filename === "string");
1010
+ }
1011
+ function isFileData(value) {
1012
+ if (!isRecord(value)) return false;
1013
+ if (value.type === "url") {
1014
+ return hasOnlyKeys(value, ["type", "url"]) && typeof value.url === "string";
1015
+ }
1016
+ if (value.type === "data") {
1017
+ return hasOnlyKeys(value, ["type", "data"]) && typeof value.data === "string";
1018
+ }
1019
+ return value.type === "text" && hasOnlyKeys(value, ["type", "text"]) && typeof value.text === "string";
1020
+ }
1021
+ function isCompletionSource(value) {
1022
+ return isRecord(value) && value.type === "url" && hasOnlyKeys(value, ["type", "url", "title", "id", "startIndex", "endIndex"]) && typeof value.url === "string" && (value.title === void 0 || typeof value.title === "string") && (value.id === void 0 || typeof value.id === "string") && (value.startIndex === void 0 || isNonnegativeNumber(value.startIndex)) && (value.endIndex === void 0 || isNonnegativeNumber(value.endIndex));
1023
+ }
1024
+ function isProviderToolCall(value) {
1025
+ return isRecord(value) && hasOnlyKeys(value, ["id", "name", "status", "details"]) && typeof value.id === "string" && typeof value.name === "string" && (value.status === void 0 || typeof value.status === "string") && (value.details === void 0 || isRecord(value.details) && isJsonValue2(value.details));
1026
+ }
1027
+ function isGuardrailDecision(value) {
1028
+ return isRecord(value) && hasOnlyKeys(value, [
1029
+ "policyId",
1030
+ "guardrailId",
1031
+ "boundary",
1032
+ "mode",
1033
+ "action",
1034
+ "applied",
1035
+ "reason",
1036
+ "message",
1037
+ "metadata",
1038
+ "latencyMs"
1039
+ ]) && typeof value.policyId === "string" && typeof value.guardrailId === "string" && (value.boundary === "input" || value.boundary === "output") && (value.mode === "enforce" || value.mode === "observe") && typeof value.action === "string" && ["allow", "block", "rewrite", "error"].includes(value.action) && typeof value.applied === "boolean" && (value.reason === void 0 || typeof value.reason === "string") && (value.message === void 0 || typeof value.message === "string") && (value.metadata === void 0 || isRecord(value.metadata) && isJsonValue2(value.metadata)) && isNonnegativeNumber(value.latencyMs);
1040
+ }
1041
+ function isUsage(value) {
1042
+ if (!isRecord(value) || !hasOnlyKeys(value, [
1043
+ "inputTokens",
1044
+ "outputTokens",
1045
+ "totalTokens",
1046
+ "cachedInputTokens",
1047
+ "cacheCreationInputTokens",
1048
+ "details"
1049
+ ]) || ![
1050
+ value.inputTokens,
1051
+ value.outputTokens,
1052
+ value.totalTokens,
1053
+ value.cachedInputTokens,
1054
+ value.cacheCreationInputTokens
1055
+ ].every(isNonnegativeNumber)) {
1056
+ return false;
1057
+ }
1058
+ return value.details === void 0 || isRecord(value.details) && Object.values(value.details).every(isNonnegativeNumber);
1059
+ }
1060
+ function isContextUsage(value) {
1061
+ if (!isRecord(value) || !isRecord(value.model) || !isRecord(value.model.context)) return false;
1062
+ const context = value.model.context;
1063
+ return hasOnlyKeys(value, [
1064
+ "model",
1065
+ "usedTokens",
1066
+ "remainingTokens",
1067
+ "usedPercent",
1068
+ "remainingPercent"
1069
+ ]) && hasOnlyKeys(value.model, ["modelId", "context"]) && typeof value.model.modelId === "string" && hasOnlyKeys(context, ["contextWindow", "maxInputTokens", "maxOutputTokens"]) && isNonnegativeNumber(context.contextWindow) && (context.maxInputTokens === void 0 || isNonnegativeNumber(context.maxInputTokens)) && (context.maxOutputTokens === void 0 || isNonnegativeNumber(context.maxOutputTokens)) && isNonnegativeNumber(value.usedTokens) && isNonnegativeNumber(value.remainingTokens) && isNonnegativeNumber(value.usedPercent) && isNonnegativeNumber(value.remainingPercent);
1070
+ }
1071
+ function validateUsageAndContext(event, original) {
1072
+ if (event.usage !== void 0 && !isUsage(event.usage)) {
1073
+ invalid(`${String(event.type)}.usage`, original);
1074
+ }
1075
+ if (event.contextUsage !== void 0 && !isContextUsage(event.contextUsage)) {
1076
+ invalid(`${String(event.type)}.contextUsage`, original);
1077
+ }
1078
+ }
1079
+ function validateMemoryCompactionInfo(value, original) {
1080
+ for (const field of ["originalMessageCount", "compactedMessageCount", "retainedMessageCount"]) {
1081
+ if (!isEventId(value[field])) invalid(`memory_compaction.${field}`, original);
1082
+ }
1083
+ if (!isPositiveEventId(value.attempts)) invalid("memory_compaction.attempts", original);
1084
+ if (!isUsage(value.usage)) invalid("memory_compaction.usage", original);
1085
+ }
1086
+ function isTrace(value) {
1087
+ return isRecord(value) && hasOnlyKeys(value, ["observer", "traceId", "observationId"]) && typeof value.observer === "string" && value.observer.trim().length > 0 && (value.traceId === void 0 || typeof value.traceId === "string") && (value.observationId === void 0 || typeof value.observationId === "string");
1088
+ }
1089
+ function requireRecord(value, label) {
1090
+ if (!isRecord(value)) throw new ClientProtocolError(`${label} must be an object.`, value);
1091
+ return value;
1092
+ }
1093
+ function requireOnlyKeys(value, keys, label) {
1094
+ for (const key of Object.keys(value)) {
1095
+ if (!keys.includes(key)) throw new ClientProtocolError(`${label} has unknown field "${key}".`);
1096
+ }
1097
+ }
1098
+ function requireEventKeys(value, keys) {
1099
+ requireOnlyKeys(
1100
+ value,
1101
+ ["type", "runId", "turn", "scope", ...keys],
1102
+ `${String(value.type)} event`
1103
+ );
1104
+ }
1105
+ function requireStrings(value, keys, original) {
1106
+ for (const key of keys) {
1107
+ if (typeof value[key] !== "string") invalid(`${String(value.type)}.${key}`, original);
1108
+ }
1109
+ }
1110
+ function requireOptionalStrings(value, keys, original) {
1111
+ for (const key of keys) {
1112
+ if (value[key] !== void 0 && typeof value[key] !== "string") {
1113
+ invalid(`${String(value.type)}.${key}`, original);
1114
+ }
1115
+ }
1116
+ }
1117
+ function requireOneOf(value, allowed, label, original) {
1118
+ if (typeof value !== "string" || !allowed.includes(value)) invalid(label, original);
1119
+ }
1120
+ function invalid(label, value) {
1121
+ throw new ClientProtocolError(`Invalid ${label}.`, value);
1122
+ }
1123
+ function isEventId(value) {
1124
+ return typeof value === "number" && Number.isSafeInteger(value) && value >= 0;
1125
+ }
1126
+ function isPositiveEventId(value) {
1127
+ return isEventId(value) && value > 0;
1128
+ }
1129
+ function isNonnegativeNumber(value) {
1130
+ return typeof value === "number" && Number.isFinite(value) && value >= 0;
1131
+ }
1132
+ function hasOnlyKeys(value, keys) {
1133
+ return Object.keys(value).every((key) => keys.includes(key));
1134
+ }
1135
+ function isRecord(value) {
1136
+ return typeof value === "object" && value !== null && !Array.isArray(value);
1137
+ }
1138
+
1139
+ // src/adapters.ts
1140
+ function completionToClientStream(options) {
1141
+ const { events } = options;
1142
+ const runId = options.runId ?? createClientId("run");
1143
+ return propagateCancellation(events, (source) => ({
1144
+ async *[Symbol.asyncIterator]() {
1145
+ const state = createMessageState({ runId });
1146
+ const runStart = {
1147
+ type: "run_start",
1148
+ source: "completion"
1149
+ };
1150
+ if (options.metadata !== void 0) runStart.metadata = options.metadata;
1151
+ yield clientEvent(state, runStart);
1152
+ if (options.model !== void 0) {
1153
+ yield clientEvent(state, { type: "generation_start", model: options.model });
1154
+ }
1155
+ yield* startMessage(state);
1156
+ let terminal = false;
1157
+ try {
1158
+ for await (const event of source) {
1159
+ if (terminal) break;
1160
+ switch (event.type) {
1161
+ case "text_delta":
1162
+ yield* appendText(state, event.delta);
1163
+ break;
1164
+ case "reasoning_delta":
1165
+ yield* appendReasoning(state, event);
1166
+ break;
1167
+ case "tool_call_delta":
1168
+ yield* appendToolCall(state, event);
1169
+ break;
1170
+ case "tool_call":
1171
+ yield* finishToolCall(state, event.toolCall);
1172
+ break;
1173
+ case "source":
1174
+ yield* emitSource(state, event.source);
1175
+ break;
1176
+ case "provider_tool_call":
1177
+ yield* emitProviderToolCall(state, event.toolCall);
1178
+ break;
1179
+ case "message_id":
1180
+ state.modelMessageId = event.id;
1181
+ break;
1182
+ case "final": {
1183
+ const result = event.result;
1184
+ if (result.messageId !== void 0) state.modelMessageId = result.messageId;
1185
+ const finalMetadata = {
1186
+ usage: result.usage
1187
+ };
1188
+ if (result.contextUsage !== void 0) {
1189
+ finalMetadata.contextUsage = result.contextUsage;
1190
+ }
1191
+ if (result.sources !== void 0) finalMetadata.sources = result.sources;
1192
+ if (result.providerToolCalls !== void 0) {
1193
+ finalMetadata.providerToolCalls = result.providerToolCalls;
1194
+ }
1195
+ yield* finishMessage(state, result.content, finalMetadata);
1196
+ const output = clientOutput(result.output, options.mapOutput);
1197
+ const runEnd = {
1198
+ type: "run_end",
1199
+ status: "completed",
1200
+ text: result.text,
1201
+ usage: result.usage
1202
+ };
1203
+ if (output !== void 0) runEnd.output = output;
1204
+ if (result.contextUsage !== void 0) runEnd.contextUsage = result.contextUsage;
1205
+ yield clientEvent(state, runEnd);
1206
+ terminal = true;
1207
+ break;
1208
+ }
1209
+ case "error":
1210
+ yield* finishErroredRun(state, event.error, event.usage, options.mapError);
1211
+ terminal = true;
1212
+ break;
1213
+ }
1214
+ }
1215
+ if (!terminal) {
1216
+ yield* finishErroredRun(
1217
+ state,
1218
+ new Error("Completion stream ended without a terminal event."),
1219
+ void 0,
1220
+ options.mapError
1221
+ );
1222
+ }
1223
+ } catch (error) {
1224
+ if (!terminal) yield* finishErroredRun(state, error, void 0, options.mapError);
1225
+ }
1226
+ }
1227
+ }));
1228
+ }
1229
+ function agentToClientStream(options) {
1230
+ const { events } = options;
1231
+ const runId = options.runId ?? createClientId("run");
1232
+ return propagateCancellation(events, (source) => ({
1233
+ async *[Symbol.asyncIterator]() {
1234
+ const runtime = {
1235
+ runId,
1236
+ options,
1237
+ messages: /* @__PURE__ */ new Map(),
1238
+ startedScopes: /* @__PURE__ */ new Set(["root"])
1239
+ };
1240
+ const runStart = {
1241
+ type: "run_start",
1242
+ source: "agent"
1243
+ };
1244
+ if (options.metadata !== void 0) runStart.metadata = options.metadata;
1245
+ yield rootEvent(runId, runStart);
1246
+ let terminal = false;
1247
+ try {
1248
+ for await (const event of source) {
1249
+ if (terminal) break;
1250
+ yield* translateAgentEvent(runtime, event, void 0);
1251
+ terminal = isRootTerminalAgentEvent(event);
1252
+ }
1253
+ if (!terminal) {
1254
+ const error = mapClientError(
1255
+ new Error("Agent stream ended without a terminal event."),
1256
+ options.mapError
1257
+ );
1258
+ yield rootEvent(runId, { type: "error", error });
1259
+ yield rootEvent(runId, { type: "run_end", status: "error" });
1260
+ }
1261
+ } catch (error) {
1262
+ if (!terminal) {
1263
+ yield rootEvent(runId, {
1264
+ type: "error",
1265
+ error: mapClientError(error, options.mapError)
1266
+ });
1267
+ yield rootEvent(runId, { type: "run_end", status: "error" });
1268
+ }
1269
+ }
1270
+ }
1271
+ }));
1272
+ }
1273
+ function customAgentEventsToClientStream(options) {
1274
+ return agentToClientStream(
1275
+ options
1276
+ );
1277
+ }
1278
+ async function* translateAgentEvent(runtime, event, scope) {
1279
+ if (event.type === "agent_tool_event") {
1280
+ const childScope = {
1281
+ agentId: event.agentId,
1282
+ parentRunId: runtime.runId,
1283
+ parentToolName: event.toolName,
1284
+ parentToolCallId: event.toolCallId ?? event.internalCallId,
1285
+ parentInternalToolCallId: event.internalCallId
1286
+ };
1287
+ if (event.agentName !== void 0) childScope.agentName = event.agentName;
1288
+ const key = scopeKey(childScope);
1289
+ if (!runtime.startedScopes.has(key)) {
1290
+ runtime.startedScopes.add(key);
1291
+ yield rootEvent(runtime.runId, { type: "run_start", source: "agent" }, childScope);
1292
+ }
1293
+ yield* translateAgentEvent(runtime, event.event, childScope);
1294
+ return;
1295
+ }
1296
+ const turn = "turn" in event && typeof event.turn === "number" ? event.turn : void 0;
1297
+ switch (event.type) {
1298
+ case "memory_compaction":
1299
+ yield scopedEvent(runtime.runId, turn, scope, {
1300
+ type: "memory_compaction",
1301
+ originalMessageCount: event.originalMessageCount,
1302
+ compactedMessageCount: event.compactedMessageCount,
1303
+ retainedMessageCount: event.retainedMessageCount,
1304
+ attempts: event.attempts,
1305
+ usage: event.usage
1306
+ });
1307
+ return;
1308
+ case "turn_start":
1309
+ yield scopedEvent(runtime.runId, turn, scope, { type: "turn_start" });
1310
+ return;
1311
+ case "generation_start": {
1312
+ const state = getAgentMessage(runtime, event.turn, scope);
1313
+ yield scopedEvent(runtime.runId, event.turn, scope, {
1314
+ type: "generation_start",
1315
+ model: {
1316
+ provider: event.modelInfo.provider,
1317
+ modelId: event.modelInfo.modelId
1318
+ }
1319
+ });
1320
+ yield* startMessage(state);
1321
+ return;
1322
+ }
1323
+ case "text_delta": {
1324
+ const state = getAgentMessage(runtime, event.turn, scope);
1325
+ yield* startMessage(state);
1326
+ yield* appendText(state, event.delta);
1327
+ return;
1328
+ }
1329
+ case "reasoning_delta": {
1330
+ const state = getAgentMessage(runtime, event.turn, scope);
1331
+ yield* startMessage(state);
1332
+ yield* appendReasoning(state, event);
1333
+ return;
1334
+ }
1335
+ case "tool_call_delta": {
1336
+ const state = getAgentMessage(runtime, event.turn, scope);
1337
+ yield* startMessage(state);
1338
+ yield* appendToolCall(state, event);
1339
+ return;
1340
+ }
1341
+ case "tool_call": {
1342
+ const state = getAgentMessage(runtime, event.turn, scope);
1343
+ yield* startMessage(state);
1344
+ yield* finishToolCall(state, event.toolCall);
1345
+ return;
1346
+ }
1347
+ case "source": {
1348
+ const state = getAgentMessage(runtime, event.turn, scope);
1349
+ yield* startMessage(state);
1350
+ yield* emitSource(state, event.source);
1351
+ return;
1352
+ }
1353
+ case "provider_tool_call": {
1354
+ const state = getAgentMessage(runtime, event.turn, scope);
1355
+ yield* emitProviderToolCall(state, event.toolCall);
1356
+ return;
1357
+ }
1358
+ case "tool_result": {
1359
+ const state = getAgentMessage(runtime, event.turn, scope);
1360
+ yield* startMessage(state);
1361
+ const tool = getToolResultState(
1362
+ state,
1363
+ event.toolName,
1364
+ event.toolCallId,
1365
+ event.callId,
1366
+ event.internalCallId
1367
+ );
1368
+ tool.result = clientToolResult(event.output, event.result);
1369
+ const resultEvent = {
1370
+ type: "tool_result",
1371
+ messageId: state.messageId,
1372
+ partId: tool.partId,
1373
+ toolCallId: tool.toolCallId,
1374
+ internalCallId: event.internalCallId,
1375
+ toolName: event.toolName,
1376
+ input: parseJsonOrString(event.args),
1377
+ result: tool.result
1378
+ };
1379
+ if (tool.callId !== void 0) resultEvent.callId = tool.callId;
1380
+ yield clientEvent(state, resultEvent);
1381
+ return;
1382
+ }
1383
+ case "turn_end": {
1384
+ const state = getAgentMessage(runtime, event.turn, scope);
1385
+ yield* startMessage(state);
1386
+ if (event.response.messageId !== void 0) state.modelMessageId = event.response.messageId;
1387
+ const finalMetadata = {
1388
+ usage: event.response.usage
1389
+ };
1390
+ if (event.response.contextUsage !== void 0) {
1391
+ finalMetadata.contextUsage = event.response.contextUsage;
1392
+ }
1393
+ if (event.response.sources !== void 0) finalMetadata.sources = event.response.sources;
1394
+ if (event.response.providerToolCalls !== void 0) {
1395
+ finalMetadata.providerToolCalls = event.response.providerToolCalls;
1396
+ }
1397
+ yield* finishMessage(state, event.response.choice, finalMetadata);
1398
+ const turnEnd = {
1399
+ type: "turn_end",
1400
+ usage: event.response.usage
1401
+ };
1402
+ if (event.response.contextUsage !== void 0) {
1403
+ turnEnd.contextUsage = event.response.contextUsage;
1404
+ }
1405
+ if (event.firstDeltaMs !== void 0) turnEnd.firstDeltaMs = event.firstDeltaMs;
1406
+ yield scopedEvent(runtime.runId, event.turn, scope, turnEnd);
1407
+ return;
1408
+ }
1409
+ case "guardrail_decision":
1410
+ yield scopedEvent(runtime.runId, event.turn, scope, {
1411
+ type: "guardrail_decision",
1412
+ decision: event.decision
1413
+ });
1414
+ return;
1415
+ case "final": {
1416
+ const result = event.result;
1417
+ if (result.status === "suspended" && scope === void 0) {
1418
+ yield scopedEvent(runtime.runId, turn, scope, {
1419
+ type: "interaction",
1420
+ interaction: result.interaction
1421
+ });
1422
+ }
1423
+ const output = result.status === "completed" ? clientOutput(result.output, runtime.options.mapOutput) : void 0;
1424
+ const runEnd = {
1425
+ type: "run_end",
1426
+ status: result.status,
1427
+ text: result.text,
1428
+ usage: result.usage
1429
+ };
1430
+ if (output !== void 0) runEnd.output = output;
1431
+ if (result.contextUsage !== void 0) runEnd.contextUsage = result.contextUsage;
1432
+ if (result.trace !== void 0) runEnd.trace = clientTrace(result.trace);
1433
+ if (result.memoryCompaction !== void 0) {
1434
+ runEnd.memoryCompaction = result.memoryCompaction;
1435
+ }
1436
+ if (runtime.options.metadata !== void 0) runEnd.metadata = runtime.options.metadata;
1437
+ yield scopedEvent(runtime.runId, turn, scope, runEnd);
1438
+ return;
1439
+ }
1440
+ case "error": {
1441
+ const error = mapClientError(event.error, runtime.options.mapError);
1442
+ yield scopedEvent(runtime.runId, turn, scope, { type: "error", error, usage: event.usage });
1443
+ yield scopedEvent(runtime.runId, turn, scope, {
1444
+ type: "run_end",
1445
+ status: "error",
1446
+ usage: event.usage
1447
+ });
1448
+ return;
1449
+ }
1450
+ default: {
1451
+ const context = {
1452
+ runId: runtime.runId
1453
+ };
1454
+ if (turn !== void 0) context.turn = turn;
1455
+ if (scope !== void 0) context.scope = scope;
1456
+ const mapped = runtime.options.mapCustomEvent?.(event, context);
1457
+ if (mapped === void 0) return;
1458
+ if (Array.isArray(mapped)) {
1459
+ yield* mapped;
1460
+ } else {
1461
+ yield mapped;
1462
+ }
1463
+ }
1464
+ }
1465
+ }
1466
+ function createMessageState(input) {
1467
+ const state = {
1468
+ runId: input.runId,
1469
+ messageId: createClientId("msg"),
1470
+ started: false,
1471
+ ended: false,
1472
+ textPartId: createClientId("text"),
1473
+ text: "",
1474
+ textStarted: false,
1475
+ textEnded: false,
1476
+ reasoning: /* @__PURE__ */ new Map(),
1477
+ tools: /* @__PURE__ */ new Map(),
1478
+ sourceFingerprints: /* @__PURE__ */ new Set(),
1479
+ providerToolCallFingerprints: /* @__PURE__ */ new Set()
1480
+ };
1481
+ if (input.turn !== void 0) state.turn = input.turn;
1482
+ if (input.scope !== void 0) state.scope = input.scope;
1483
+ return state;
1484
+ }
1485
+ function getAgentMessage(runtime, turn, scope) {
1486
+ const key = `${scopeKey(scope)}:${turn}`;
1487
+ const current = runtime.messages.get(key);
1488
+ if (current !== void 0) return current;
1489
+ const input = {
1490
+ runId: runtime.runId,
1491
+ turn
1492
+ };
1493
+ if (scope !== void 0) input.scope = scope;
1494
+ const created = createMessageState(input);
1495
+ runtime.messages.set(key, created);
1496
+ return created;
1497
+ }
1498
+ async function* startMessage(state) {
1499
+ if (state.started) return;
1500
+ state.started = true;
1501
+ yield clientEvent(state, {
1502
+ type: "message_start",
1503
+ messageId: state.messageId,
1504
+ role: "assistant"
1505
+ });
1506
+ }
1507
+ async function* appendText(state, delta) {
1508
+ if (!state.textStarted) {
1509
+ state.textStarted = true;
1510
+ yield clientEvent(state, {
1511
+ type: "text_start",
1512
+ messageId: state.messageId,
1513
+ partId: state.textPartId
1514
+ });
1515
+ }
1516
+ state.text += delta;
1517
+ yield clientEvent(state, {
1518
+ type: "text_delta",
1519
+ messageId: state.messageId,
1520
+ partId: state.textPartId,
1521
+ delta
1522
+ });
1523
+ }
1524
+ async function* emitSource(state, source) {
1525
+ const fingerprint = valueFingerprint(source);
1526
+ if (state.sourceFingerprints.has(fingerprint)) return;
1527
+ state.sourceFingerprints.add(fingerprint);
1528
+ yield clientEvent(state, {
1529
+ type: "source",
1530
+ messageId: state.messageId,
1531
+ partId: createClientId("source"),
1532
+ source
1533
+ });
1534
+ }
1535
+ async function* emitProviderToolCall(state, toolCall) {
1536
+ const fingerprint = valueFingerprint(toolCall);
1537
+ if (state.providerToolCallFingerprints.has(fingerprint)) return;
1538
+ state.providerToolCallFingerprints.add(fingerprint);
1539
+ yield clientEvent(state, { type: "provider_tool_call", toolCall });
1540
+ }
1541
+ async function* appendReasoning(state, event) {
1542
+ const key = event.id ?? "default";
1543
+ let reasoning = state.reasoning.get(key);
1544
+ if (reasoning === void 0) {
1545
+ reasoning = {
1546
+ partId: createClientId("reasoning"),
1547
+ text: "",
1548
+ ended: false
1549
+ };
1550
+ if (event.id !== void 0) reasoning.reasoningId = event.id;
1551
+ state.reasoning.set(key, reasoning);
1552
+ const reasoningStart = {
1553
+ type: "reasoning_start",
1554
+ messageId: state.messageId,
1555
+ partId: reasoning.partId
1556
+ };
1557
+ if (event.id !== void 0) reasoningStart.reasoningId = event.id;
1558
+ yield clientEvent(state, reasoningStart);
1559
+ }
1560
+ reasoning.text += event.delta;
1561
+ const reasoningDelta = {
1562
+ type: "reasoning_delta",
1563
+ messageId: state.messageId,
1564
+ partId: reasoning.partId,
1565
+ delta: event.delta
1566
+ };
1567
+ if (event.contentType !== void 0) reasoningDelta.contentType = event.contentType;
1568
+ if (event.signature !== void 0) reasoningDelta.signature = event.signature;
1569
+ yield clientEvent(state, reasoningDelta);
1570
+ }
1571
+ async function* appendToolCall(state, event) {
1572
+ const tool = getToolState(state, event.id, event.name);
1573
+ if (!tool.started) {
1574
+ tool.started = true;
1575
+ const toolCallStart = {
1576
+ type: "tool_call_start",
1577
+ messageId: state.messageId,
1578
+ partId: tool.partId,
1579
+ toolCallId: event.id
1580
+ };
1581
+ if (event.callId !== void 0) toolCallStart.callId = event.callId;
1582
+ if (event.name !== void 0) toolCallStart.toolName = event.name;
1583
+ yield clientEvent(state, toolCallStart);
1584
+ }
1585
+ if (event.callId !== void 0) tool.callId = event.callId;
1586
+ if (event.name !== void 0) tool.toolName = event.name;
1587
+ if (event.signature !== void 0) tool.signature = event.signature;
1588
+ if (event.argumentsDelta === void 0) return;
1589
+ const mode = event.argumentsMode ?? "append";
1590
+ const prior = typeof tool.input === "string" ? tool.input : "";
1591
+ tool.input = mode === "replace" ? event.argumentsDelta : `${prior}${event.argumentsDelta}`;
1592
+ const toolCallDelta = {
1593
+ type: "tool_call_delta",
1594
+ messageId: state.messageId,
1595
+ partId: tool.partId,
1596
+ toolCallId: event.id,
1597
+ delta: event.argumentsDelta,
1598
+ mode
1599
+ };
1600
+ if (event.callId !== void 0) toolCallDelta.callId = event.callId;
1601
+ if (event.name !== void 0) toolCallDelta.toolName = event.name;
1602
+ if (event.signature !== void 0) toolCallDelta.signature = event.signature;
1603
+ yield clientEvent(state, toolCallDelta);
1604
+ }
1605
+ async function* finishToolCall(state, toolCall) {
1606
+ const tool = getToolState(state, toolCall.toolCallId, toolCall.toolName);
1607
+ const wasEnded = tool.ended;
1608
+ if (!tool.started) {
1609
+ tool.started = true;
1610
+ const toolCallStart = {
1611
+ type: "tool_call_start",
1612
+ messageId: state.messageId,
1613
+ partId: tool.partId,
1614
+ toolCallId: toolCall.toolCallId,
1615
+ toolName: toolCall.toolName
1616
+ };
1617
+ if (toolCall.callId !== void 0) toolCallStart.callId = toolCall.callId;
1618
+ yield clientEvent(state, toolCallStart);
1619
+ }
1620
+ if (toolCall.callId === void 0) delete tool.callId;
1621
+ else tool.callId = toolCall.callId;
1622
+ tool.toolName = toolCall.toolName;
1623
+ tool.input = toolCall.input;
1624
+ if (toolCall.signature === void 0) delete tool.signature;
1625
+ else tool.signature = toolCall.signature;
1626
+ if (wasEnded) return;
1627
+ tool.ended = true;
1628
+ const toolCallEnd = {
1629
+ type: "tool_call_end",
1630
+ messageId: state.messageId,
1631
+ partId: tool.partId,
1632
+ toolCallId: toolCall.toolCallId,
1633
+ toolName: toolCall.toolName,
1634
+ input: toolCall.input
1635
+ };
1636
+ if (toolCall.callId !== void 0) toolCallEnd.callId = toolCall.callId;
1637
+ if (toolCall.signature !== void 0) toolCallEnd.signature = toolCall.signature;
1638
+ yield clientEvent(state, toolCallEnd);
1639
+ }
1640
+ async function* finishMessage(state, content, metadata) {
1641
+ if (state.ended) return;
1642
+ const textContent2 = content.filter(
1643
+ (part) => part.type === "text"
1644
+ );
1645
+ const text = textContent2.map((part) => part.text).join("");
1646
+ if (state.textStarted || text.length > 0) {
1647
+ if (!state.textStarted) {
1648
+ state.textStarted = true;
1649
+ yield clientEvent(state, {
1650
+ type: "text_start",
1651
+ messageId: state.messageId,
1652
+ partId: state.textPartId
1653
+ });
1654
+ }
1655
+ state.text = text;
1656
+ state.textEnded = true;
1657
+ const textEnd = {
1658
+ type: "text_end",
1659
+ messageId: state.messageId,
1660
+ partId: state.textPartId,
1661
+ text
1662
+ };
1663
+ if (textContent2.length === 1 && textContent2[0]?.signature !== void 0) {
1664
+ textEnd.signature = textContent2[0].signature;
1665
+ }
1666
+ yield clientEvent(state, textEnd);
1667
+ }
1668
+ const finalReasoning = content.filter(
1669
+ (part) => part.type === "reasoning"
1670
+ );
1671
+ const anonymousReasoning = [...state.reasoning.values()].filter(
1672
+ (reasoning) => reasoning.reasoningId === void 0
1673
+ );
1674
+ let anonymousIndex = 0;
1675
+ for (const [index, reasoning] of finalReasoning.entries()) {
1676
+ const existing = reasoning.id === void 0 ? anonymousReasoning[anonymousIndex++] : state.reasoning.get(reasoning.id);
1677
+ const current = existing ?? createReasoningState(reasoning.id);
1678
+ if (existing === void 0) {
1679
+ state.reasoning.set(reasoning.id ?? `final:${index}`, current);
1680
+ const reasoningStart = {
1681
+ type: "reasoning_start",
1682
+ messageId: state.messageId,
1683
+ partId: current.partId
1684
+ };
1685
+ if (reasoning.id !== void 0) reasoningStart.reasoningId = reasoning.id;
1686
+ yield clientEvent(state, reasoningStart);
1687
+ }
1688
+ if (!current.ended) {
1689
+ current.ended = true;
1690
+ current.text = reasoning.text;
1691
+ const reasoningEnd = {
1692
+ type: "reasoning_end",
1693
+ messageId: state.messageId,
1694
+ partId: current.partId,
1695
+ text: reasoning.text
1696
+ };
1697
+ if (reasoning.details !== void 0) reasoningEnd.content = reasoning.details;
1698
+ yield clientEvent(state, reasoningEnd);
1699
+ }
1700
+ }
1701
+ for (const reasoning of state.reasoning.values()) {
1702
+ if (reasoning.ended) continue;
1703
+ reasoning.ended = true;
1704
+ yield clientEvent(state, {
1705
+ type: "reasoning_end",
1706
+ messageId: state.messageId,
1707
+ partId: reasoning.partId,
1708
+ text: reasoning.text
1709
+ });
1710
+ }
1711
+ for (const part of content) {
1712
+ if (part.type === "tool-call") yield* finishToolCall(state, part);
1713
+ if (part.type === "image" || part.type === "file") {
1714
+ const attachment = contentAttachment(part);
1715
+ yield clientEvent(state, {
1716
+ type: "attachment",
1717
+ messageId: state.messageId,
1718
+ partId: createClientId("attachment_part"),
1719
+ attachment
1720
+ });
1721
+ }
1722
+ }
1723
+ for (const source of metadata.sources ?? []) yield* emitSource(state, source);
1724
+ for (const toolCall of metadata.providerToolCalls ?? []) {
1725
+ yield* emitProviderToolCall(state, toolCall);
1726
+ }
1727
+ state.ended = true;
1728
+ const messageEnd = {
1729
+ type: "message_end",
1730
+ messageId: state.messageId,
1731
+ parts: contentToUIMessageParts(content, state),
1732
+ usage: metadata.usage
1733
+ };
1734
+ if (state.modelMessageId !== void 0) messageEnd.modelMessageId = state.modelMessageId;
1735
+ if (metadata.contextUsage !== void 0) messageEnd.contextUsage = metadata.contextUsage;
1736
+ yield clientEvent(state, messageEnd);
1737
+ }
1738
+ async function* finishErroredRun(state, error, usage, mapper) {
1739
+ const mapped = mapClientError(error, mapper);
1740
+ if (state.textStarted && !state.textEnded) {
1741
+ state.textEnded = true;
1742
+ yield clientEvent(state, {
1743
+ type: "text_end",
1744
+ messageId: state.messageId,
1745
+ partId: state.textPartId,
1746
+ text: state.text
1747
+ });
1748
+ }
1749
+ const errorEvent = {
1750
+ type: "error",
1751
+ error: mapped
1752
+ };
1753
+ if (usage !== void 0) errorEvent.usage = usage;
1754
+ yield clientEvent(state, errorEvent);
1755
+ if (!state.ended) {
1756
+ state.ended = true;
1757
+ const messageEnd = {
1758
+ type: "message_end",
1759
+ messageId: state.messageId
1760
+ };
1761
+ if (state.modelMessageId !== void 0) messageEnd.modelMessageId = state.modelMessageId;
1762
+ if (usage !== void 0) messageEnd.usage = usage;
1763
+ yield clientEvent(state, messageEnd);
1764
+ }
1765
+ const runEnd = {
1766
+ type: "run_end",
1767
+ status: "error"
1768
+ };
1769
+ if (usage !== void 0) runEnd.usage = usage;
1770
+ yield clientEvent(state, runEnd);
1771
+ }
1772
+ function contentToUIMessageParts(content, state) {
1773
+ let textIndex = 0;
1774
+ let anonymousReasoningIndex = 0;
1775
+ const anonymousReasoning = [...state.reasoning.values()].filter(
1776
+ (reasoning) => reasoning.reasoningId === void 0
1777
+ );
1778
+ return content.map((contentPart) => {
1779
+ if (contentPart.type === "text") {
1780
+ const part = {
1781
+ id: textIndex === 0 ? state.textPartId : createClientId("text"),
1782
+ type: "text",
1783
+ text: contentPart.text
1784
+ };
1785
+ textIndex += 1;
1786
+ if (contentPart.signature !== void 0) part.signature = contentPart.signature;
1787
+ return part;
1788
+ }
1789
+ if (contentPart.type === "reasoning") {
1790
+ const current = contentPart.id === void 0 ? anonymousReasoning[anonymousReasoningIndex++] : state.reasoning.get(contentPart.id);
1791
+ const part = {
1792
+ id: current?.partId ?? createClientId("reasoning"),
1793
+ type: "reasoning",
1794
+ text: contentPart.text
1795
+ };
1796
+ if (contentPart.id !== void 0) part.reasoningId = contentPart.id;
1797
+ if (contentPart.details !== void 0) part.content = contentPart.details;
1798
+ return part;
1799
+ }
1800
+ if (contentPart.type === "tool-call") {
1801
+ const tool = getToolState(state, contentPart.toolCallId, contentPart.toolName);
1802
+ const partBase = {
1803
+ id: tool.partId,
1804
+ type: "tool",
1805
+ toolName: contentPart.toolName,
1806
+ toolCallId: contentPart.toolCallId
1807
+ };
1808
+ if (contentPart.callId !== void 0) Object.assign(partBase, { callId: contentPart.callId });
1809
+ if (tool.internalCallId !== void 0) {
1810
+ Object.assign(partBase, { internalCallId: tool.internalCallId });
1811
+ }
1812
+ if (state.turn !== void 0) Object.assign(partBase, { turn: state.turn });
1813
+ if (contentPart.signature !== void 0) {
1814
+ Object.assign(partBase, { signature: contentPart.signature });
1815
+ }
1816
+ if (tool.result?.status === "success") {
1817
+ const part = {
1818
+ ...partBase,
1819
+ state: "output-available",
1820
+ input: contentPart.input,
1821
+ output: tool.result.output
1822
+ };
1823
+ if (tool.result.content !== void 0) part.resultContent = tool.result.content;
1824
+ return part;
1825
+ }
1826
+ if (tool.result?.status === "error") {
1827
+ return {
1828
+ ...partBase,
1829
+ state: "error",
1830
+ input: contentPart.input,
1831
+ error: tool.result.error
1832
+ };
1833
+ }
1834
+ return {
1835
+ ...partBase,
1836
+ state: "input-available",
1837
+ input: contentPart.input
1838
+ };
1839
+ }
1840
+ const attachment = contentAttachment(contentPart);
1841
+ return {
1842
+ id: createClientId("attachment_part"),
1843
+ type: "attachment",
1844
+ attachment
1845
+ };
1846
+ });
1847
+ }
1848
+ function getToolState(state, id, name) {
1849
+ let tool = state.tools.get(id);
1850
+ if (tool === void 0) {
1851
+ tool = {
1852
+ partId: createClientId("tool"),
1853
+ toolCallId: id,
1854
+ input: "",
1855
+ started: false,
1856
+ ended: false
1857
+ };
1858
+ if (name !== void 0) tool.toolName = name;
1859
+ state.tools.set(id, tool);
1860
+ } else if (name !== void 0) {
1861
+ tool.toolName = name;
1862
+ }
1863
+ return tool;
1864
+ }
1865
+ function getToolResultState(state, toolName, toolCallId, callId, internalCallId) {
1866
+ const matchedByToolCallId = state.tools.get(toolCallId);
1867
+ const matchedByCallId = callId === void 0 ? void 0 : [...state.tools.values()].find((tool2) => tool2.callId === callId);
1868
+ const tool = matchedByToolCallId ?? matchedByCallId ?? getToolState(state, toolCallId, toolName);
1869
+ tool.toolName = toolName;
1870
+ if (callId !== void 0) tool.callId = callId;
1871
+ tool.internalCallId = internalCallId;
1872
+ return tool;
1873
+ }
1874
+ function createReasoningState(id) {
1875
+ const state = {
1876
+ partId: createClientId("reasoning"),
1877
+ text: "",
1878
+ ended: false
1879
+ };
1880
+ if (id !== void 0) state.reasoningId = id;
1881
+ return state;
1882
+ }
1883
+ function contentAttachment(content) {
1884
+ const attachment = {
1885
+ id: createClientId("attachment"),
1886
+ type: content.type === "image" ? "image" : "file"
1887
+ };
1888
+ if (content.type === "image") {
1889
+ if (content.detail !== void 0) attachment.detail = content.detail;
1890
+ if (content.mediaType !== void 0) attachment.mediaType = content.mediaType;
1891
+ if (content.image.type === "url") attachment.url = content.image.url;
1892
+ else attachment.data = content.image.data;
1893
+ return attachment;
1894
+ }
1895
+ attachment.mediaType = content.mediaType;
1896
+ if (content.filename !== void 0) attachment.name = content.filename;
1897
+ if (content.data.type === "url") {
1898
+ attachment.url = content.data.url;
1899
+ } else if (content.data.type === "data") {
1900
+ attachment.data = content.data.data;
1901
+ } else {
1902
+ attachment.text = content.data.text;
1903
+ }
1904
+ return attachment;
1905
+ }
1906
+ function clientToolResult(output, result) {
1907
+ switch (output.type) {
1908
+ case "text":
1909
+ return { status: "success", output: output.value };
1910
+ case "json":
1911
+ return { status: "success", output: output.value };
1912
+ case "content":
1913
+ return { status: "success", output: result, content: output.value };
1914
+ case "execution-denied":
1915
+ return {
1916
+ status: "error",
1917
+ error: {
1918
+ message: output.reason ?? "Tool execution was denied.",
1919
+ code: "tool_execution_denied"
1920
+ }
1921
+ };
1922
+ case "error-text":
1923
+ return {
1924
+ status: "error",
1925
+ error: { message: output.value, code: "tool_execution_error" }
1926
+ };
1927
+ case "error-json":
1928
+ return {
1929
+ status: "error",
1930
+ error: {
1931
+ message: "Tool execution failed.",
1932
+ code: "tool_execution_error",
1933
+ details: output.value
1934
+ }
1935
+ };
1936
+ }
1937
+ }
1938
+ function parseJsonOrString(value) {
1939
+ try {
1940
+ const parsed = JSON.parse(value);
1941
+ return isJsonValue3(parsed) ? parsed : value;
1942
+ } catch {
1943
+ return value;
1944
+ }
1945
+ }
1946
+ function clientOutput(output, mapper) {
1947
+ const mapped = mapper === void 0 ? isJsonValue3(output) ? output : void 0 : mapper(output);
1948
+ if (mapped !== void 0 && !isJsonValue3(mapped)) {
1949
+ throw new TypeError("mapOutput must return a strict JSON value or undefined.");
1950
+ }
1951
+ return mapped;
1952
+ }
1953
+ function valueFingerprint(value) {
1954
+ if (value === null) return "null";
1955
+ if (value === void 0) return "undefined";
1956
+ if (Array.isArray(value)) return `[${value.map(valueFingerprint).join(",")}]`;
1957
+ if (typeof value === "object") {
1958
+ return `{${Object.entries(value).sort(([left], [right]) => left.localeCompare(right)).map(([key, entry]) => `${JSON.stringify(key)}:${valueFingerprint(entry)}`).join(",")}}`;
1959
+ }
1960
+ return `${typeof value}:${JSON.stringify(value)}`;
1961
+ }
1962
+ function clientTrace(trace) {
1963
+ const result = {
1964
+ observer: trace.observer
1965
+ };
1966
+ if (trace.traceId !== void 0) result.traceId = trace.traceId;
1967
+ if (trace.observationId !== void 0) result.observationId = trace.observationId;
1968
+ return result;
1969
+ }
1970
+ function mapClientError(error, mapper) {
1971
+ const mapped = mapper?.(error) ?? maskedClientError();
1972
+ if (typeof mapped.message !== "string" || mapped.details !== void 0 && !isJsonValue3(mapped.details)) {
1973
+ throw new TypeError("mapError must return a JSON-safe ClientStreamError.");
1974
+ }
1975
+ return mapped;
1976
+ }
1977
+ function clientEvent(state, event) {
1978
+ return scopedEvent(state.runId, state.turn, state.scope, event);
1979
+ }
1980
+ function rootEvent(runId, event, scope) {
1981
+ return scopedEvent(runId, void 0, scope, event);
1982
+ }
1983
+ function scopedEvent(runId, turn, scope, event) {
1984
+ let scoped = { runId, ...event };
1985
+ if (turn !== void 0) scoped = { ...scoped, turn };
1986
+ if (scope !== void 0) scoped = { ...scoped, scope };
1987
+ return scoped;
1988
+ }
1989
+ function scopeKey(scope) {
1990
+ if (scope === void 0) return "root";
1991
+ return [
1992
+ scope.agentId,
1993
+ scope.parentRunId,
1994
+ scope.parentToolName,
1995
+ scope.parentToolCallId,
1996
+ scope.parentInternalToolCallId
1997
+ ].join(":");
1998
+ }
1999
+ function isRootTerminalAgentEvent(event) {
2000
+ return event.type === "final" || event.type === "error";
2001
+ }
2002
+ function propagateCancellation(source, transform) {
2003
+ return {
2004
+ [Symbol.asyncIterator]() {
2005
+ const sourceIterator = source[Symbol.asyncIterator]();
2006
+ const sharedSource = {
2007
+ [Symbol.asyncIterator]: () => sourceIterator
2008
+ };
2009
+ const outputIterator = transform(sharedSource)[Symbol.asyncIterator]();
2010
+ let returned = false;
2011
+ return {
2012
+ next: () => outputIterator.next(),
2013
+ async return() {
2014
+ if (returned) return { done: true, value: void 0 };
2015
+ returned = true;
2016
+ const sourceReturn = sourceIterator.return?.();
2017
+ const outputReturn = outputIterator.return?.();
2018
+ await Promise.all([sourceReturn, outputReturn]);
2019
+ return { done: true, value: void 0 };
2020
+ }
2021
+ };
2022
+ }
2023
+ };
2024
+ }
2025
+
2026
+ // src/client-transport.ts
2027
+ function createHttpClientTransport(options) {
2028
+ const transport = createFetchEventTransport({
2029
+ ...options,
2030
+ mapEvent: (event) => parseClientStreamFrame(event, protocolOptions(options)),
2031
+ validateResponse(response) {
2032
+ if (response.headers.get("x-anvia-stream-protocol") !== CLIENT_STREAM_PROTOCOL) {
2033
+ throw new ClientProtocolError(
2034
+ `Expected x-anvia-stream-protocol: ${CLIENT_STREAM_PROTOCOL}.`
2035
+ );
2036
+ }
2037
+ }
2038
+ });
2039
+ return {
2040
+ async *send(sendOptions) {
2041
+ const resume = sendOptions.resume ?? resumeCursorFromRequest(sendOptions.request);
2042
+ yield* validateFrameSequence(transport.send(sendOptions), resume);
2043
+ }
2044
+ };
2045
+ }
2046
+ function createDirectClientTransport(options) {
2047
+ return {
2048
+ async *send(sendOptions) {
2049
+ const resume = sendOptions.resume ?? resumeCursorFromRequest(sendOptions.request);
2050
+ if (resume !== void 0) {
2051
+ throw new ClientProtocolError("Direct client transports do not support resume cursors.");
2052
+ }
2053
+ const handlerOptions = {
2054
+ request: sendOptions.request
2055
+ };
2056
+ if (sendOptions.abortSignal !== void 0) {
2057
+ handlerOptions.abortSignal = sendOptions.abortSignal;
2058
+ }
2059
+ if (sendOptions.headers !== void 0) handlerOptions.headers = sendOptions.headers;
2060
+ const events = await options.handler(handlerOptions);
2061
+ const iterator = events[Symbol.asyncIterator]();
2062
+ const streamId = createClientId("stream");
2063
+ let eventId = 0;
2064
+ yield {
2065
+ type: "stream_start",
2066
+ protocol: CLIENT_STREAM_PROTOCOL,
2067
+ streamId,
2068
+ eventId: 0,
2069
+ resumable: false
2070
+ };
2071
+ let status = "completed";
2072
+ try {
2073
+ let closePromise;
2074
+ const close = () => {
2075
+ closePromise ??= Promise.resolve(iterator.return?.());
2076
+ return closePromise;
2077
+ };
2078
+ const onAbort = () => {
2079
+ void close();
2080
+ };
2081
+ sendOptions.abortSignal?.addEventListener("abort", onAbort, { once: true });
2082
+ try {
2083
+ while (!sendOptions.abortSignal?.aborted) {
2084
+ const next = await iterator.next();
2085
+ if (next.done) break;
2086
+ const event = parseClientStreamEvent(
2087
+ next.value,
2088
+ protocolOptions(options)
2089
+ );
2090
+ eventId += 1;
2091
+ yield { type: "stream_event", streamId, eventId, event };
2092
+ }
2093
+ } finally {
2094
+ sendOptions.abortSignal?.removeEventListener("abort", onAbort);
2095
+ await close();
2096
+ }
2097
+ } catch {
2098
+ status = "error";
2099
+ }
2100
+ yield { type: "stream_end", streamId, eventId, status };
2101
+ }
2102
+ };
2103
+ }
2104
+ async function* validateFrameSequence(frames, resume) {
2105
+ let streamId;
2106
+ let lastEventId = resume?.after ?? 0;
2107
+ let ended = false;
2108
+ for await (const frame of frames) {
2109
+ if (ended) throw new ClientProtocolError("Received a frame after stream_end.", frame);
2110
+ if (streamId === void 0) {
2111
+ if (frame.type !== "stream_start") {
2112
+ throw new ClientProtocolError("The first client stream frame must be stream_start.", frame);
2113
+ }
2114
+ streamId = frame.streamId;
2115
+ if (resume !== void 0 && frame.streamId !== resume.streamId) {
2116
+ throw new ClientProtocolError("Resume response streamId does not match the cursor.", frame);
2117
+ }
2118
+ if (resume !== void 0 && !frame.resumable) {
2119
+ throw new ClientProtocolError("Resume response must identify a resumable stream.", frame);
2120
+ }
2121
+ } else if (frame.type === "stream_start") {
2122
+ throw new ClientProtocolError("Received more than one stream_start frame.", frame);
2123
+ } else if (frame.streamId !== streamId) {
2124
+ throw new ClientProtocolError("Client streamId changed during the response.", frame);
2125
+ }
2126
+ if (frame.type === "stream_event") {
2127
+ if (frame.eventId !== lastEventId + 1) {
2128
+ throw new ClientProtocolError("Client stream event IDs must be contiguous.", frame);
2129
+ }
2130
+ lastEventId = frame.eventId;
2131
+ } else if (frame.type === "stream_end") {
2132
+ if (frame.eventId !== lastEventId) {
2133
+ throw new ClientProtocolError("stream_end has an invalid eventId.", frame);
2134
+ }
2135
+ ended = true;
2136
+ }
2137
+ yield frame;
2138
+ }
2139
+ if (streamId === void 0 || !ended) {
2140
+ throw new ClientProtocolError("Client stream ended without a complete frame sequence.");
2141
+ }
2142
+ }
2143
+ function protocolOptions(options) {
2144
+ const result = {};
2145
+ if (options.metadataSchema !== void 0) result.metadataSchema = options.metadataSchema;
2146
+ if (options.dataSchemas !== void 0) result.dataSchemas = options.dataSchemas;
2147
+ return result;
2148
+ }
2149
+ function resumeCursorFromRequest(value) {
2150
+ if (typeof value !== "object" || value === null || !("resume" in value)) return void 0;
2151
+ const resume = value.resume;
2152
+ if (typeof resume !== "object" || resume === null) return void 0;
2153
+ if (!("streamId" in resume) || !("after" in resume)) return void 0;
2154
+ return typeof resume.streamId === "string" && typeof resume.after === "number" && Number.isSafeInteger(resume.after) && resume.after >= 0 ? { streamId: resume.streamId, after: resume.after } : void 0;
2155
+ }
2156
+
2157
+ // src/reducer.ts
2158
+ import { isJsonValue as isJsonValue4 } from "@anvia/core/completion";
2159
+ function applyClientStreamEvent(messages, event) {
2160
+ if (event.scope?.parentToolCallId !== void 0) {
2161
+ return messages;
2162
+ }
2163
+ switch (event.type) {
2164
+ case "message_start": {
2165
+ if (messages.some((message2) => message2.id === event.messageId)) return messages;
2166
+ let message = {
2167
+ id: event.messageId,
2168
+ role: event.role,
2169
+ parts: []
2170
+ };
2171
+ if (event.metadata !== void 0) message = { ...message, metadata: event.metadata };
2172
+ return [...messages, message];
2173
+ }
2174
+ case "text_start":
2175
+ return upsertPart(messages, event.messageId, {
2176
+ id: event.partId,
2177
+ type: "text",
2178
+ text: ""
2179
+ });
2180
+ case "text_delta":
2181
+ return updatePart(messages, event.messageId, event.partId, (part) => ({
2182
+ id: event.partId,
2183
+ type: "text",
2184
+ text: part?.type === "text" ? `${part.text}${event.delta}` : event.delta
2185
+ }));
2186
+ case "text_end":
2187
+ return updatePart(messages, event.messageId, event.partId, (part) => {
2188
+ const next = {
2189
+ id: event.partId,
2190
+ type: "text",
2191
+ text: event.text ?? (part?.type === "text" ? part.text : "")
2192
+ };
2193
+ if (event.signature !== void 0) next.signature = event.signature;
2194
+ return next;
2195
+ });
2196
+ case "reasoning_start": {
2197
+ const reasoning = {
2198
+ id: event.partId,
2199
+ type: "reasoning",
2200
+ text: ""
2201
+ };
2202
+ if (event.reasoningId !== void 0) reasoning.reasoningId = event.reasoningId;
2203
+ return upsertPart(messages, event.messageId, reasoning);
2204
+ }
2205
+ case "reasoning_delta":
2206
+ return updatePart(messages, event.messageId, event.partId, (part) => {
2207
+ const reasoning = {
2208
+ id: event.partId,
2209
+ type: "reasoning",
2210
+ text: part?.type === "reasoning" ? `${part.text}${event.delta}` : event.delta
2211
+ };
2212
+ if (part?.type === "reasoning" && part.reasoningId !== void 0) {
2213
+ reasoning.reasoningId = part.reasoningId;
2214
+ }
2215
+ const content = appendReasoningContent(
2216
+ part?.type === "reasoning" ? part.content : void 0,
2217
+ event
2218
+ );
2219
+ if (content !== void 0) reasoning.content = content;
2220
+ return reasoning;
2221
+ });
2222
+ case "reasoning_end":
2223
+ return updatePart(messages, event.messageId, event.partId, (part) => {
2224
+ const reasoning = {
2225
+ id: event.partId,
2226
+ type: "reasoning",
2227
+ text: event.text ?? (part?.type === "reasoning" ? part.text : "")
2228
+ };
2229
+ if (part?.type === "reasoning" && part.reasoningId !== void 0) {
2230
+ reasoning.reasoningId = part.reasoningId;
2231
+ }
2232
+ if (event.content !== void 0) {
2233
+ reasoning.content = event.content;
2234
+ } else if (part?.type === "reasoning" && part.content !== void 0) {
2235
+ reasoning.content = part.content;
2236
+ }
2237
+ return reasoning;
2238
+ });
2239
+ case "tool_call_start": {
2240
+ const part = {
2241
+ id: event.partId,
2242
+ type: "tool",
2243
+ toolName: event.toolName ?? "",
2244
+ toolCallId: event.toolCallId,
2245
+ state: "input-streaming",
2246
+ input: ""
2247
+ };
2248
+ if (event.callId !== void 0) part.callId = event.callId;
2249
+ if (event.turn !== void 0) part.turn = event.turn;
2250
+ return upsertPart(messages, event.messageId, part);
2251
+ }
2252
+ case "tool_call_delta":
2253
+ return updatePart(messages, event.messageId, event.partId, (current) => {
2254
+ const part = current?.type === "tool" ? toolPartBase(current) : {
2255
+ id: event.partId,
2256
+ type: "tool",
2257
+ toolName: event.toolName ?? "",
2258
+ toolCallId: event.toolCallId
2259
+ };
2260
+ const previous = current?.type === "tool" && typeof current.input === "string" ? current.input : "";
2261
+ if (event.toolName !== void 0) part.toolName = event.toolName;
2262
+ if (event.callId !== void 0) part.callId = event.callId;
2263
+ if (event.signature !== void 0) part.signature = event.signature;
2264
+ if (event.turn !== void 0) part.turn = event.turn;
2265
+ return {
2266
+ ...part,
2267
+ state: "input-streaming",
2268
+ input: event.mode === "replace" ? event.delta : `${previous}${event.delta}`
2269
+ };
2270
+ });
2271
+ case "tool_call_end": {
2272
+ const part = {
2273
+ id: event.partId,
2274
+ type: "tool",
2275
+ toolName: event.toolName,
2276
+ toolCallId: event.toolCallId,
2277
+ state: "input-available",
2278
+ input: event.input
2279
+ };
2280
+ if (event.callId !== void 0) part.callId = event.callId;
2281
+ if (event.turn !== void 0) part.turn = event.turn;
2282
+ if (event.signature !== void 0) part.signature = event.signature;
2283
+ return upsertPart(messages, event.messageId, part);
2284
+ }
2285
+ case "tool_result":
2286
+ return updatePart(messages, event.messageId, event.partId, (current) => {
2287
+ const part = current?.type === "tool" ? toolPartBase(current) : {
2288
+ id: event.partId,
2289
+ type: "tool",
2290
+ toolName: event.toolName,
2291
+ toolCallId: event.toolCallId
2292
+ };
2293
+ if (event.callId !== void 0) part.callId = event.callId;
2294
+ if (event.internalCallId !== void 0) part.internalCallId = event.internalCallId;
2295
+ if (event.turn !== void 0) part.turn = event.turn;
2296
+ if (event.result.status === "error") {
2297
+ return {
2298
+ ...part,
2299
+ state: "error",
2300
+ input: event.input,
2301
+ error: event.result.error
2302
+ };
2303
+ }
2304
+ const completed = {
2305
+ ...part,
2306
+ state: "output-available",
2307
+ input: event.input,
2308
+ output: event.result.output
2309
+ };
2310
+ if (event.result.content !== void 0) completed.resultContent = event.result.content;
2311
+ return completed;
2312
+ });
2313
+ case "source":
2314
+ return upsertPart(messages, event.messageId, {
2315
+ id: event.partId,
2316
+ type: "source",
2317
+ source: event.source
2318
+ });
2319
+ case "attachment":
2320
+ return upsertPart(messages, event.messageId, {
2321
+ id: event.partId,
2322
+ type: "attachment",
2323
+ attachment: event.attachment
2324
+ });
2325
+ case "data":
2326
+ if (event.transient === true) return messages;
2327
+ return appendToLastAssistant(messages, {
2328
+ id: createClientId("data"),
2329
+ type: "data",
2330
+ name: event.name,
2331
+ data: event.data
2332
+ });
2333
+ case "message_end":
2334
+ return messages.map((message) => {
2335
+ if (message.id !== event.messageId) return message;
2336
+ const metadata = mergeMetadata(message.metadata, event.metadata);
2337
+ const generationUpdate = {
2338
+ runId: event.runId
2339
+ };
2340
+ if (event.usage !== void 0) generationUpdate.usage = event.usage;
2341
+ if (event.contextUsage !== void 0) {
2342
+ generationUpdate.contextUsage = event.contextUsage;
2343
+ }
2344
+ const generation = mergeGeneration(message.generation, generationUpdate);
2345
+ let updated = {
2346
+ ...message,
2347
+ generation
2348
+ };
2349
+ if (event.parts !== void 0) {
2350
+ updated = { ...updated, parts: reconcileFinalParts(message.parts, event.parts) };
2351
+ }
2352
+ if (event.modelMessageId !== void 0) {
2353
+ updated = { ...updated, modelMessageId: event.modelMessageId };
2354
+ }
2355
+ if (metadata !== void 0) updated = { ...updated, metadata };
2356
+ return updated;
2357
+ });
2358
+ case "run_end": {
2359
+ const generation = {
2360
+ runId: event.runId,
2361
+ status: event.status
2362
+ };
2363
+ if (event.usage !== void 0) generation.usage = event.usage;
2364
+ if (event.contextUsage !== void 0) generation.contextUsage = event.contextUsage;
2365
+ if (event.trace !== void 0) generation.trace = event.trace;
2366
+ if (event.memoryCompaction !== void 0) {
2367
+ generation.memoryCompaction = event.memoryCompaction;
2368
+ }
2369
+ return updateLastAssistantGeneration(messages, generation);
2370
+ }
2371
+ case "error":
2372
+ return appendToLastAssistant(messages, {
2373
+ id: createClientId("error"),
2374
+ type: "error",
2375
+ error: event.error
2376
+ });
2377
+ default:
2378
+ return messages;
2379
+ }
2380
+ }
2381
+ function toolPartBase(part) {
2382
+ const base = {
2383
+ id: part.id,
2384
+ type: part.type,
2385
+ toolName: part.toolName,
2386
+ toolCallId: part.toolCallId
2387
+ };
2388
+ if (part.callId !== void 0) Object.assign(base, { callId: part.callId });
2389
+ if (part.internalCallId !== void 0) {
2390
+ Object.assign(base, { internalCallId: part.internalCallId });
2391
+ }
2392
+ if (part.turn !== void 0) Object.assign(base, { turn: part.turn });
2393
+ if (part.signature !== void 0) Object.assign(base, { signature: part.signature });
2394
+ return base;
2395
+ }
2396
+ function reconcileFinalParts(current, final) {
2397
+ const clientOnly = current.filter(
2398
+ (part) => part.type === "source" || part.type === "data" || part.type === "error"
2399
+ );
2400
+ return [...final, ...clientOnly];
2401
+ }
2402
+ function appendReasoningContent(current, event) {
2403
+ if (event.contentType === void 0 && event.signature === void 0) return current;
2404
+ const type = event.contentType ?? "text";
2405
+ const next = [...current ?? []];
2406
+ const last = next.at(-1);
2407
+ if (type === "text") {
2408
+ if (last?.type === "text" && last.signature === event.signature) {
2409
+ next[next.length - 1] = { ...last, text: `${last.text}${event.delta}` };
2410
+ } else {
2411
+ let detail = {
2412
+ type,
2413
+ text: event.delta
2414
+ };
2415
+ if (event.signature !== void 0) detail = { ...detail, signature: event.signature };
2416
+ next.push(detail);
2417
+ }
2418
+ return next;
2419
+ }
2420
+ if (type === "summary") {
2421
+ if (last?.type === "summary") {
2422
+ next[next.length - 1] = { ...last, text: `${last.text}${event.delta}` };
2423
+ } else next.push({ type, text: event.delta });
2424
+ return next;
2425
+ }
2426
+ if (type === "encrypted") {
2427
+ if (last?.type === "encrypted") {
2428
+ next[next.length - 1] = { ...last, data: `${last.data}${event.delta}` };
2429
+ } else next.push({ type, data: event.delta });
2430
+ return next;
2431
+ }
2432
+ if (last?.type === "redacted") {
2433
+ next[next.length - 1] = { ...last, data: `${last.data}${event.delta}` };
2434
+ } else next.push({ type, data: event.delta });
2435
+ return next;
2436
+ }
2437
+ function messageText(message) {
2438
+ return message.parts.flatMap((part) => part.type === "text" ? [part.text] : []).join("");
2439
+ }
2440
+ function assistantText(messages) {
2441
+ const assistant = [...messages].reverse().find((message) => message.role === "assistant");
2442
+ return assistant === void 0 ? "" : messageText(assistant);
2443
+ }
2444
+ function upsertPart(messages, messageId, part) {
2445
+ return updatePart(messages, messageId, part.id, () => part);
2446
+ }
2447
+ function updatePart(messages, messageId, partId, update) {
2448
+ const current = ensureAssistant(messages, messageId);
2449
+ return current.map((message) => {
2450
+ if (message.id !== messageId) return message;
2451
+ const index = message.parts.findIndex((part) => part.id === partId);
2452
+ if (index === -1) return { ...message, parts: [...message.parts, update(void 0)] };
2453
+ const parts = [...message.parts];
2454
+ parts[index] = update(parts[index]);
2455
+ return { ...message, parts };
2456
+ });
2457
+ }
2458
+ function ensureAssistant(messages, messageId) {
2459
+ return messages.some((message) => message.id === messageId) ? messages : [...messages, { id: messageId, role: "assistant", parts: [] }];
2460
+ }
2461
+ function appendToLastAssistant(messages, part) {
2462
+ const index = findLastIndex(messages, (message2) => message2.role === "assistant");
2463
+ if (index === -1) {
2464
+ return [...messages, { id: createClientId("msg"), role: "assistant", parts: [part] }];
2465
+ }
2466
+ const next = [...messages];
2467
+ const message = next[index];
2468
+ next[index] = { ...message, parts: [...message.parts, part] };
2469
+ return next;
2470
+ }
2471
+ function updateLastAssistantGeneration(messages, value) {
2472
+ const index = findLastIndex(messages, (message2) => message2.role === "assistant");
2473
+ if (index === -1) return messages;
2474
+ const next = [...messages];
2475
+ const message = next[index];
2476
+ next[index] = { ...message, generation: mergeGeneration(message.generation, value) };
2477
+ return next;
2478
+ }
2479
+ function mergeMetadata(current, provided) {
2480
+ if (provided === void 0) return current;
2481
+ if (!isRecord2(current) || !isRecord2(provided)) return provided;
2482
+ const next = { ...current, ...provided };
2483
+ return isJsonValue4(next) ? next : provided;
2484
+ }
2485
+ function mergeGeneration(current, provided) {
2486
+ return {
2487
+ ...current,
2488
+ ...Object.fromEntries(Object.entries(provided).filter(([, value]) => value !== void 0))
2489
+ };
2490
+ }
2491
+ function findLastIndex(items, predicate) {
2492
+ for (let index = items.length - 1; index >= 0; index -= 1) {
2493
+ if (predicate(items[index])) return index;
2494
+ }
2495
+ return -1;
2496
+ }
2497
+ function isRecord2(value) {
2498
+ return typeof value === "object" && value !== null && !Array.isArray(value);
2499
+ }
2500
+ export {
2501
+ CLIENT_STREAM_PROTOCOL,
2502
+ ClientProtocolError,
2503
+ agentToClientStream,
2504
+ applyClientStreamEvent,
2505
+ assistantText,
2506
+ completionToClientStream,
2507
+ createClientId,
2508
+ createDirectClientTransport,
2509
+ createHttpClientTransport,
2510
+ customAgentEventsToClientStream,
2511
+ maskedClientError,
2512
+ messageText,
2513
+ messagesToUIMessages,
2514
+ normalizeClientError,
2515
+ parseClientStreamEvent,
2516
+ parseClientStreamFrame,
2517
+ parseClientStreamRequest,
2518
+ parseUIMessage,
2519
+ parseUIMessages,
2520
+ uiMessagesToMessages
2521
+ };
2522
+ //# sourceMappingURL=index.js.map