@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/LICENSE +21 -0
- package/README.md +70 -0
- package/dist/chunk-2KGXQZWA.js +201 -0
- package/dist/chunk-2KGXQZWA.js.map +1 -0
- package/dist/event-transport-CC5RD-hT.d.ts +31 -0
- package/dist/index.d.ts +433 -0
- package/dist/index.js +2522 -0
- package/dist/index.js.map +1 -0
- package/dist/transport/index.d.ts +21 -0
- package/dist/transport/index.js +17 -0
- package/dist/transport/index.js.map +1 -0
- package/package.json +48 -0
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
|