assistant-stream 0.0.20 → 0.0.22
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ai-sdk.d.mts +20 -4
- package/dist/ai-sdk.d.ts +20 -4
- package/dist/ai-sdk.js +691 -42
- package/dist/ai-sdk.js.map +1 -1
- package/dist/ai-sdk.mjs +190 -44
- package/dist/ai-sdk.mjs.map +1 -1
- package/dist/assistant-stream-CEVTPU3I.d.mts +211 -0
- package/dist/assistant-stream-CEVTPU3I.d.ts +211 -0
- package/dist/chunk-DISBVUTK.mjs +932 -0
- package/dist/chunk-DISBVUTK.mjs.map +1 -0
- package/dist/index.d.mts +23 -103
- package/dist/index.d.ts +23 -103
- package/dist/index.js +1189 -490
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +417 -625
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/dist/AssistantStream-dm_T4K6d.d.mts +0 -28
- package/dist/AssistantStream-dm_T4K6d.d.ts +0 -28
- package/dist/chunk-ZSSWV6GU.mjs +0 -11
- package/dist/chunk-ZSSWV6GU.mjs.map +0 -1
package/dist/index.js
CHANGED
|
@@ -30,12 +30,14 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
AssistantMessageAccumulator: () => AssistantMessageAccumulator,
|
|
33
34
|
AssistantMessageStream: () => AssistantMessageStream,
|
|
34
35
|
AssistantStream: () => AssistantStream,
|
|
35
36
|
DataStreamDecoder: () => DataStreamDecoder,
|
|
36
37
|
DataStreamEncoder: () => DataStreamEncoder,
|
|
37
38
|
PlainTextDecoder: () => PlainTextDecoder,
|
|
38
39
|
PlainTextEncoder: () => PlainTextEncoder,
|
|
40
|
+
ToolExecutionStream: () => ToolExecutionStream,
|
|
39
41
|
createAssistantStream: () => createAssistantStream,
|
|
40
42
|
createAssistantStreamResponse: () => createAssistantStreamResponse
|
|
41
43
|
});
|
|
@@ -44,7 +46,9 @@ module.exports = __toCommonJS(index_exports);
|
|
|
44
46
|
// src/core/AssistantStream.ts
|
|
45
47
|
var AssistantStream = {
|
|
46
48
|
toResponse(stream, transformer) {
|
|
47
|
-
return new Response(AssistantStream.toByteStream(stream, transformer)
|
|
49
|
+
return new Response(AssistantStream.toByteStream(stream, transformer), {
|
|
50
|
+
headers: transformer.headers ?? {}
|
|
51
|
+
});
|
|
48
52
|
},
|
|
49
53
|
fromResponse(response, transformer) {
|
|
50
54
|
return AssistantStream.fromByteStream(response.body, transformer);
|
|
@@ -57,202 +61,118 @@ var AssistantStream = {
|
|
|
57
61
|
}
|
|
58
62
|
};
|
|
59
63
|
|
|
60
|
-
// src/core/utils/
|
|
61
|
-
var
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
}
|
|
64
|
+
// src/core/utils/stream/merge.ts
|
|
65
|
+
var promiseWithResolvers = () => {
|
|
66
|
+
let resolve;
|
|
67
|
+
let reject;
|
|
68
|
+
const promise = new Promise((res, rej) => {
|
|
69
|
+
resolve = res;
|
|
70
|
+
reject = rej;
|
|
71
|
+
});
|
|
72
|
+
return { promise, resolve, reject };
|
|
70
73
|
};
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
transform(chunk, controller) {
|
|
85
|
-
const type = chunk.type;
|
|
86
|
-
switch (type) {
|
|
87
|
-
case "text-delta":
|
|
88
|
-
controller.enqueue("0:" + JSON.stringify(chunk.textDelta) + "\n");
|
|
89
|
-
break;
|
|
90
|
-
case "tool-call-begin":
|
|
91
|
-
controller.enqueue(
|
|
92
|
-
"b:" + JSON.stringify({
|
|
93
|
-
toolCallId: chunk.toolCallId,
|
|
94
|
-
toolName: chunk.toolName
|
|
95
|
-
}) + "\n"
|
|
96
|
-
);
|
|
97
|
-
break;
|
|
98
|
-
case "tool-call-delta":
|
|
99
|
-
controller.enqueue(
|
|
100
|
-
"c:" + JSON.stringify({
|
|
101
|
-
toolCallId: chunk.toolCallId,
|
|
102
|
-
argsTextDelta: chunk.argsTextDelta
|
|
103
|
-
}) + "\n"
|
|
104
|
-
);
|
|
105
|
-
break;
|
|
106
|
-
case "tool-result":
|
|
107
|
-
controller.enqueue(
|
|
108
|
-
"a:" + JSON.stringify({
|
|
109
|
-
toolCallId: chunk.toolCallId,
|
|
110
|
-
result: chunk.result
|
|
111
|
-
}) + "\n"
|
|
112
|
-
);
|
|
113
|
-
break;
|
|
114
|
-
case "error":
|
|
115
|
-
controller.enqueue(`3:${JSON.stringify(chunk.error)}
|
|
116
|
-
`);
|
|
117
|
-
break;
|
|
118
|
-
default:
|
|
119
|
-
const exhaustiveCheck = type;
|
|
120
|
-
throw new Error(`unsupported chunk type: ${exhaustiveCheck}`);
|
|
74
|
+
var createMergeStream = () => {
|
|
75
|
+
const list = [];
|
|
76
|
+
let sealed = false;
|
|
77
|
+
let controller;
|
|
78
|
+
let currentPull;
|
|
79
|
+
const handlePull = (item) => {
|
|
80
|
+
if (!item.promise) {
|
|
81
|
+
item.promise = item.reader.read().then(({ done, value }) => {
|
|
82
|
+
item.promise = void 0;
|
|
83
|
+
if (done) {
|
|
84
|
+
list.splice(list.indexOf(item), 1);
|
|
85
|
+
if (sealed && list.length === 0) {
|
|
86
|
+
controller.close();
|
|
121
87
|
}
|
|
88
|
+
} else {
|
|
89
|
+
controller.enqueue(value);
|
|
122
90
|
}
|
|
91
|
+
currentPull?.resolve();
|
|
92
|
+
currentPull = void 0;
|
|
93
|
+
}).catch((e) => {
|
|
94
|
+
console.error(e);
|
|
95
|
+
list.forEach((item2) => {
|
|
96
|
+
item2.reader.cancel();
|
|
97
|
+
});
|
|
98
|
+
list.length = 0;
|
|
99
|
+
controller.error(e);
|
|
100
|
+
currentPull?.reject(e);
|
|
101
|
+
currentPull = void 0;
|
|
123
102
|
});
|
|
124
|
-
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
};
|
|
128
|
-
var decodeStreamPart = (part) => {
|
|
129
|
-
const index = part.indexOf(":");
|
|
130
|
-
if (index === -1) throw new Error("Invalid stream part");
|
|
131
|
-
return {
|
|
132
|
-
type: part.slice(0, index),
|
|
133
|
-
value: JSON.parse(part.slice(index + 1))
|
|
103
|
+
}
|
|
134
104
|
};
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
}
|
|
144
|
-
constructor() {
|
|
145
|
-
this._transformStream = new PipeableTransformStream((readable) => {
|
|
146
|
-
const transform = new TransformStream({
|
|
147
|
-
transform(chunk, controller) {
|
|
148
|
-
const { type, value } = decodeStreamPart(chunk);
|
|
149
|
-
switch (type) {
|
|
150
|
-
case "0":
|
|
151
|
-
controller.enqueue({
|
|
152
|
-
type: "text-delta",
|
|
153
|
-
textDelta: value
|
|
154
|
-
});
|
|
155
|
-
break;
|
|
156
|
-
case "b": {
|
|
157
|
-
const { toolCallId, toolName } = value;
|
|
158
|
-
controller.enqueue({
|
|
159
|
-
type: "tool-call-begin",
|
|
160
|
-
toolCallId,
|
|
161
|
-
toolName
|
|
162
|
-
});
|
|
163
|
-
break;
|
|
164
|
-
}
|
|
165
|
-
case "c": {
|
|
166
|
-
const { toolCallId, argsTextDelta } = value;
|
|
167
|
-
controller.enqueue({
|
|
168
|
-
type: "tool-call-delta",
|
|
169
|
-
toolCallId,
|
|
170
|
-
argsTextDelta
|
|
171
|
-
});
|
|
172
|
-
break;
|
|
173
|
-
}
|
|
174
|
-
case "a": {
|
|
175
|
-
const { toolCallId, result } = value;
|
|
176
|
-
controller.enqueue({
|
|
177
|
-
type: "tool-result",
|
|
178
|
-
toolCallId,
|
|
179
|
-
result
|
|
180
|
-
});
|
|
181
|
-
break;
|
|
182
|
-
}
|
|
183
|
-
case "9": {
|
|
184
|
-
const { toolCallId, args } = value;
|
|
185
|
-
controller.enqueue({
|
|
186
|
-
type: "tool-call-begin",
|
|
187
|
-
toolCallId,
|
|
188
|
-
toolName: toolCallId
|
|
189
|
-
});
|
|
190
|
-
controller.enqueue({
|
|
191
|
-
type: "tool-call-delta",
|
|
192
|
-
toolCallId,
|
|
193
|
-
argsTextDelta: JSON.stringify(args)
|
|
194
|
-
});
|
|
195
|
-
break;
|
|
196
|
-
}
|
|
197
|
-
case "2":
|
|
198
|
-
case "3":
|
|
199
|
-
case "8":
|
|
200
|
-
case "d":
|
|
201
|
-
case "e": {
|
|
202
|
-
break;
|
|
203
|
-
}
|
|
204
|
-
default:
|
|
205
|
-
const exhaustiveCheck = type;
|
|
206
|
-
throw new Error(`unsupported chunk type: ${exhaustiveCheck}`);
|
|
207
|
-
}
|
|
208
|
-
}
|
|
105
|
+
const readable = new ReadableStream({
|
|
106
|
+
start(c) {
|
|
107
|
+
controller = c;
|
|
108
|
+
},
|
|
109
|
+
pull() {
|
|
110
|
+
currentPull = promiseWithResolvers();
|
|
111
|
+
list.forEach((item) => {
|
|
112
|
+
handlePull(item);
|
|
209
113
|
});
|
|
210
|
-
return
|
|
211
|
-
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
114
|
+
return currentPull.promise;
|
|
115
|
+
},
|
|
116
|
+
cancel() {
|
|
117
|
+
list.forEach((item) => {
|
|
118
|
+
item.reader.cancel();
|
|
119
|
+
});
|
|
120
|
+
list.length = 0;
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
return {
|
|
124
|
+
readable,
|
|
125
|
+
isSealed() {
|
|
126
|
+
return sealed;
|
|
127
|
+
},
|
|
128
|
+
seal() {
|
|
129
|
+
sealed = true;
|
|
130
|
+
if (list.length === 0) controller.close();
|
|
131
|
+
},
|
|
132
|
+
addStream(stream) {
|
|
133
|
+
if (sealed)
|
|
134
|
+
throw new Error(
|
|
135
|
+
"Cannot add streams after the run callback has settled."
|
|
136
|
+
);
|
|
137
|
+
const item = { reader: stream.getReader() };
|
|
138
|
+
list.push(item);
|
|
139
|
+
handlePull(item);
|
|
140
|
+
},
|
|
141
|
+
enqueue(chunk) {
|
|
142
|
+
this.addStream(
|
|
143
|
+
new ReadableStream({
|
|
144
|
+
start(c) {
|
|
145
|
+
c.enqueue(chunk);
|
|
146
|
+
c.close();
|
|
147
|
+
}
|
|
148
|
+
})
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
};
|
|
233
152
|
};
|
|
234
153
|
|
|
235
|
-
// src/core/utils/generateId.tsx
|
|
236
|
-
var import_non_secure = require("nanoid/non-secure");
|
|
237
|
-
var generateId = (0, import_non_secure.customAlphabet)(
|
|
238
|
-
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
|
239
|
-
7
|
|
240
|
-
);
|
|
241
|
-
|
|
242
154
|
// src/core/modules/text.ts
|
|
243
155
|
var TextStreamControllerImpl = class {
|
|
244
156
|
_controller;
|
|
157
|
+
_isClosed = false;
|
|
245
158
|
constructor(controller) {
|
|
246
159
|
this._controller = controller;
|
|
247
160
|
}
|
|
248
161
|
append(textDelta) {
|
|
249
162
|
this._controller.enqueue({
|
|
250
163
|
type: "text-delta",
|
|
164
|
+
path: [],
|
|
251
165
|
textDelta
|
|
252
166
|
});
|
|
253
167
|
return this;
|
|
254
168
|
}
|
|
255
169
|
close() {
|
|
170
|
+
if (this._isClosed) return;
|
|
171
|
+
this._isClosed = true;
|
|
172
|
+
this._controller.enqueue({
|
|
173
|
+
type: "part-finish",
|
|
174
|
+
path: []
|
|
175
|
+
});
|
|
256
176
|
this._controller.close();
|
|
257
177
|
}
|
|
258
178
|
};
|
|
@@ -269,17 +189,20 @@ var createTextStream = (readable) => {
|
|
|
269
189
|
}
|
|
270
190
|
});
|
|
271
191
|
};
|
|
192
|
+
var createTextStreamController = () => {
|
|
193
|
+
let controller;
|
|
194
|
+
const stream = createTextStream({
|
|
195
|
+
start(c) {
|
|
196
|
+
controller = c;
|
|
197
|
+
}
|
|
198
|
+
});
|
|
199
|
+
return [stream, controller];
|
|
200
|
+
};
|
|
272
201
|
|
|
273
202
|
// src/core/modules/tool-call.ts
|
|
274
203
|
var ToolCallStreamControllerImpl = class {
|
|
275
|
-
constructor(_controller
|
|
204
|
+
constructor(_controller) {
|
|
276
205
|
this._controller = _controller;
|
|
277
|
-
this._options = _options;
|
|
278
|
-
this._controller.enqueue({
|
|
279
|
-
type: "tool-call-begin",
|
|
280
|
-
toolCallId: this._options.toolCallId,
|
|
281
|
-
toolName: this._options.toolName
|
|
282
|
-
});
|
|
283
206
|
const stream = createTextStream({
|
|
284
207
|
start: (c) => {
|
|
285
208
|
this._argsTextController = c;
|
|
@@ -288,215 +211,750 @@ var ToolCallStreamControllerImpl = class {
|
|
|
288
211
|
stream.pipeTo(
|
|
289
212
|
new WritableStream({
|
|
290
213
|
write: (chunk) => {
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
214
|
+
switch (chunk.type) {
|
|
215
|
+
case "text-delta":
|
|
216
|
+
this._controller.enqueue(chunk);
|
|
217
|
+
break;
|
|
218
|
+
case "part-finish":
|
|
219
|
+
this._controller.enqueue({
|
|
220
|
+
type: "tool-call-args-text-finish",
|
|
221
|
+
path: []
|
|
222
|
+
});
|
|
223
|
+
break;
|
|
224
|
+
default:
|
|
225
|
+
throw new Error(`Unexpected chunk type: ${chunk.type}`);
|
|
226
|
+
}
|
|
298
227
|
}
|
|
299
228
|
})
|
|
300
229
|
);
|
|
301
230
|
}
|
|
302
|
-
|
|
303
|
-
return this._options.toolCallId;
|
|
304
|
-
}
|
|
305
|
-
get toolName() {
|
|
306
|
-
return this._options.toolName;
|
|
307
|
-
}
|
|
231
|
+
_isClosed = false;
|
|
308
232
|
get argsText() {
|
|
309
233
|
return this._argsTextController;
|
|
310
234
|
}
|
|
311
235
|
_argsTextController;
|
|
312
|
-
setResult(result) {
|
|
236
|
+
setResult(result, isError) {
|
|
313
237
|
this._controller.enqueue({
|
|
314
|
-
type: "
|
|
315
|
-
|
|
316
|
-
result
|
|
238
|
+
type: "result",
|
|
239
|
+
path: [],
|
|
240
|
+
result,
|
|
241
|
+
isError: isError ?? false
|
|
317
242
|
});
|
|
318
243
|
}
|
|
319
244
|
close() {
|
|
245
|
+
if (this._isClosed) return;
|
|
246
|
+
this._isClosed = true;
|
|
247
|
+
this._argsTextController.close();
|
|
248
|
+
this._controller.enqueue({
|
|
249
|
+
type: "part-finish",
|
|
250
|
+
path: []
|
|
251
|
+
});
|
|
320
252
|
this._controller.close();
|
|
321
253
|
}
|
|
322
254
|
};
|
|
323
255
|
var createToolCallStream = (readable) => {
|
|
324
|
-
const options = {
|
|
325
|
-
toolCallId: readable.toolCallId,
|
|
326
|
-
toolName: readable.toolName
|
|
327
|
-
};
|
|
328
256
|
return new ReadableStream({
|
|
329
257
|
start(c) {
|
|
330
|
-
return readable.start?.(new ToolCallStreamControllerImpl(c
|
|
258
|
+
return readable.start?.(new ToolCallStreamControllerImpl(c));
|
|
331
259
|
},
|
|
332
260
|
pull(c) {
|
|
333
|
-
return readable.pull?.(new ToolCallStreamControllerImpl(c
|
|
261
|
+
return readable.pull?.(new ToolCallStreamControllerImpl(c));
|
|
334
262
|
},
|
|
335
263
|
cancel(c) {
|
|
336
264
|
return readable.cancel?.(c);
|
|
337
265
|
}
|
|
338
266
|
});
|
|
339
267
|
};
|
|
340
|
-
|
|
341
|
-
// src/core/modules/runs.ts
|
|
342
|
-
var promiseWithResolvers = () => {
|
|
343
|
-
let resolve;
|
|
344
|
-
let reject;
|
|
345
|
-
const promise = new Promise((res, rej) => {
|
|
346
|
-
resolve = res;
|
|
347
|
-
reject = rej;
|
|
348
|
-
});
|
|
349
|
-
return { promise, resolve, reject };
|
|
350
|
-
};
|
|
351
|
-
var createMergeStream = () => {
|
|
352
|
-
const list = [];
|
|
353
|
-
let sealed = false;
|
|
268
|
+
var createToolCallStreamController = () => {
|
|
354
269
|
let controller;
|
|
355
|
-
|
|
356
|
-
const handlePull = (item) => {
|
|
357
|
-
if (!item.promise) {
|
|
358
|
-
item.promise = item.reader.read().then(({ done, value }) => {
|
|
359
|
-
item.promise = void 0;
|
|
360
|
-
if (done) {
|
|
361
|
-
list.splice(list.indexOf(item), 1);
|
|
362
|
-
if (sealed && list.length === 0) {
|
|
363
|
-
controller.close();
|
|
364
|
-
}
|
|
365
|
-
} else {
|
|
366
|
-
controller.enqueue(value);
|
|
367
|
-
}
|
|
368
|
-
currentPull?.resolve();
|
|
369
|
-
currentPull = void 0;
|
|
370
|
-
}).catch((e) => {
|
|
371
|
-
list.forEach((item2) => {
|
|
372
|
-
item2.reader.cancel();
|
|
373
|
-
});
|
|
374
|
-
list.length = 0;
|
|
375
|
-
controller.error(e);
|
|
376
|
-
currentPull?.reject(e);
|
|
377
|
-
currentPull = void 0;
|
|
378
|
-
});
|
|
379
|
-
}
|
|
380
|
-
};
|
|
381
|
-
const readable = new ReadableStream({
|
|
270
|
+
const stream = createToolCallStream({
|
|
382
271
|
start(c) {
|
|
383
272
|
controller = c;
|
|
384
|
-
},
|
|
385
|
-
async pull() {
|
|
386
|
-
list.map((item) => {
|
|
387
|
-
handlePull(item);
|
|
388
|
-
return item.promise;
|
|
389
|
-
});
|
|
390
|
-
currentPull = promiseWithResolvers();
|
|
391
|
-
return currentPull.promise;
|
|
392
|
-
},
|
|
393
|
-
cancel() {
|
|
394
|
-
list.forEach((item) => {
|
|
395
|
-
item.reader.cancel();
|
|
396
|
-
});
|
|
397
|
-
list.length = 0;
|
|
398
273
|
}
|
|
399
274
|
});
|
|
400
|
-
return
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
275
|
+
return [stream, controller];
|
|
276
|
+
};
|
|
277
|
+
|
|
278
|
+
// src/core/utils/Counter.ts
|
|
279
|
+
var Counter = class {
|
|
280
|
+
value = -1;
|
|
281
|
+
up() {
|
|
282
|
+
return ++this.value;
|
|
283
|
+
}
|
|
284
|
+
};
|
|
285
|
+
|
|
286
|
+
// src/core/utils/stream/path-utils.ts
|
|
287
|
+
var PathAppendEncoder = class extends TransformStream {
|
|
288
|
+
constructor(idx) {
|
|
289
|
+
super({
|
|
290
|
+
transform(chunk, controller) {
|
|
291
|
+
controller.enqueue({
|
|
292
|
+
...chunk,
|
|
293
|
+
path: [idx, ...chunk.path]
|
|
294
|
+
});
|
|
415
295
|
}
|
|
416
|
-
}
|
|
417
|
-
}
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
};
|
|
299
|
+
var PathAppendDecoder = class extends TransformStream {
|
|
300
|
+
constructor(idx) {
|
|
301
|
+
super({
|
|
302
|
+
transform(chunk, controller) {
|
|
303
|
+
const {
|
|
304
|
+
path: [idx2, ...path]
|
|
305
|
+
} = chunk;
|
|
306
|
+
if (idx !== idx2)
|
|
307
|
+
throw new Error(`Path mismatch: expected ${idx}, got ${idx2}`);
|
|
308
|
+
controller.enqueue({
|
|
309
|
+
...chunk,
|
|
310
|
+
path
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
});
|
|
314
|
+
}
|
|
315
|
+
};
|
|
316
|
+
var PathMergeEncoder = class extends TransformStream {
|
|
317
|
+
constructor(counter) {
|
|
318
|
+
const innerCounter = new Counter();
|
|
319
|
+
const mapping = /* @__PURE__ */ new Map();
|
|
320
|
+
super({
|
|
321
|
+
transform(chunk, controller) {
|
|
322
|
+
if (chunk.type === "part-start" && chunk.path.length === 0) {
|
|
323
|
+
mapping.set(innerCounter.up(), counter.up());
|
|
324
|
+
}
|
|
325
|
+
const [idx, ...path] = chunk.path;
|
|
326
|
+
if (idx === void 0) {
|
|
327
|
+
controller.enqueue(chunk);
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
const mappedIdx = mapping.get(idx);
|
|
331
|
+
if (mappedIdx === void 0) throw new Error("Path not found");
|
|
332
|
+
controller.enqueue({
|
|
333
|
+
...chunk,
|
|
334
|
+
path: [mappedIdx, ...path]
|
|
335
|
+
});
|
|
336
|
+
}
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// src/core/utils/stream/AssistantTransformStream.ts
|
|
342
|
+
var AssistantTransformStream = class extends TransformStream {
|
|
343
|
+
constructor(transformer, writableStrategy, readableStrategy) {
|
|
344
|
+
const [stream, runController] = createAssistantStreamController();
|
|
345
|
+
let runPipeTask;
|
|
346
|
+
super(
|
|
347
|
+
{
|
|
348
|
+
start(controller) {
|
|
349
|
+
runPipeTask = stream.pipeTo(
|
|
350
|
+
new WritableStream({
|
|
351
|
+
write(chunk) {
|
|
352
|
+
controller.enqueue(chunk);
|
|
353
|
+
},
|
|
354
|
+
abort(reason) {
|
|
355
|
+
controller.error(reason);
|
|
356
|
+
},
|
|
357
|
+
close() {
|
|
358
|
+
controller.terminate();
|
|
359
|
+
}
|
|
360
|
+
})
|
|
361
|
+
).catch((error) => {
|
|
362
|
+
controller.error(error);
|
|
363
|
+
});
|
|
364
|
+
return transformer.start?.(runController);
|
|
365
|
+
},
|
|
366
|
+
transform(chunk) {
|
|
367
|
+
return transformer.transform?.(chunk, runController);
|
|
368
|
+
},
|
|
369
|
+
async flush() {
|
|
370
|
+
await transformer.flush?.(runController);
|
|
371
|
+
runController.close();
|
|
372
|
+
await runPipeTask;
|
|
373
|
+
}
|
|
374
|
+
},
|
|
375
|
+
writableStrategy,
|
|
376
|
+
readableStrategy
|
|
377
|
+
);
|
|
378
|
+
}
|
|
379
|
+
};
|
|
380
|
+
|
|
381
|
+
// src/core/utils/stream/PipeableTransformStream.ts
|
|
382
|
+
var PipeableTransformStream = class extends TransformStream {
|
|
383
|
+
constructor(transform) {
|
|
384
|
+
super();
|
|
385
|
+
const readable = transform(super.readable);
|
|
386
|
+
Object.defineProperty(this, "readable", {
|
|
387
|
+
value: readable,
|
|
388
|
+
writable: false
|
|
389
|
+
});
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
|
|
393
|
+
// src/core/utils/stream/LineDecoderStream.ts
|
|
394
|
+
var LineDecoderStream = class extends TransformStream {
|
|
395
|
+
buffer = "";
|
|
396
|
+
constructor() {
|
|
397
|
+
super({
|
|
398
|
+
transform: (chunk, controller) => {
|
|
399
|
+
this.buffer += chunk;
|
|
400
|
+
const lines = this.buffer.split("\n");
|
|
401
|
+
for (let i = 0; i < lines.length - 1; i++) {
|
|
402
|
+
controller.enqueue(lines[i]);
|
|
403
|
+
}
|
|
404
|
+
this.buffer = lines[lines.length - 1] || "";
|
|
405
|
+
},
|
|
406
|
+
flush: (controller) => {
|
|
407
|
+
if (this.buffer) {
|
|
408
|
+
controller.enqueue(this.buffer);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
}
|
|
413
|
+
};
|
|
414
|
+
|
|
415
|
+
// src/core/serialization/data-stream/serialization.ts
|
|
416
|
+
var DataStreamChunkEncoder = class extends TransformStream {
|
|
417
|
+
constructor() {
|
|
418
|
+
super({
|
|
419
|
+
transform: (chunk, controller) => {
|
|
420
|
+
controller.enqueue(`${chunk.type}:${JSON.stringify(chunk.value)}
|
|
421
|
+
`);
|
|
422
|
+
}
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
};
|
|
426
|
+
var DataStreamChunkDecoder = class extends TransformStream {
|
|
427
|
+
constructor() {
|
|
428
|
+
super({
|
|
429
|
+
transform: (chunk, controller) => {
|
|
430
|
+
const index = chunk.indexOf(":");
|
|
431
|
+
if (index === -1) throw new Error("Invalid stream part");
|
|
432
|
+
controller.enqueue({
|
|
433
|
+
type: chunk.slice(0, index),
|
|
434
|
+
value: JSON.parse(chunk.slice(index + 1))
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
}
|
|
439
|
+
};
|
|
440
|
+
|
|
441
|
+
// src/core/utils/stream/AssistantMetaTransformStream.ts
|
|
442
|
+
var AssistantMetaTransformStream = class extends TransformStream {
|
|
443
|
+
constructor() {
|
|
444
|
+
const parts = [];
|
|
445
|
+
super({
|
|
446
|
+
transform(chunk, controller) {
|
|
447
|
+
if (chunk.type === "part-start") {
|
|
448
|
+
if (chunk.path.length !== 0) {
|
|
449
|
+
controller.error(new Error("Nested parts are not supported"));
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
parts.push(chunk.part);
|
|
453
|
+
controller.enqueue(chunk);
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (chunk.type === "text-delta" || chunk.type === "result" || chunk.type === "part-finish" || chunk.type === "tool-call-args-text-finish") {
|
|
457
|
+
if (chunk.path.length !== 1) {
|
|
458
|
+
controller.error(
|
|
459
|
+
new Error(`${chunk.type} chunks must have a path of length 1`)
|
|
460
|
+
);
|
|
461
|
+
return;
|
|
462
|
+
}
|
|
463
|
+
const idx = chunk.path[0];
|
|
464
|
+
if (idx < 0 || idx >= parts.length) {
|
|
465
|
+
controller.error(new Error(`Invalid path index: ${idx}`));
|
|
466
|
+
return;
|
|
467
|
+
}
|
|
468
|
+
const part = parts[idx];
|
|
469
|
+
controller.enqueue({
|
|
470
|
+
...chunk,
|
|
471
|
+
meta: part
|
|
472
|
+
// TODO
|
|
473
|
+
});
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
controller.enqueue(chunk);
|
|
477
|
+
}
|
|
478
|
+
});
|
|
479
|
+
}
|
|
480
|
+
};
|
|
481
|
+
|
|
482
|
+
// src/core/serialization/data-stream/DataStream.ts
|
|
483
|
+
var DataStreamEncoder = class extends PipeableTransformStream {
|
|
484
|
+
headers = new Headers({
|
|
485
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
486
|
+
"x-vercel-ai-data-stream": "v1"
|
|
487
|
+
});
|
|
488
|
+
constructor() {
|
|
489
|
+
super((readable) => {
|
|
490
|
+
const transform = new TransformStream({
|
|
491
|
+
transform(chunk, controller) {
|
|
492
|
+
const type = chunk.type;
|
|
493
|
+
switch (type) {
|
|
494
|
+
case "part-start": {
|
|
495
|
+
const part = chunk.part;
|
|
496
|
+
if (part.type === "tool-call") {
|
|
497
|
+
const { type: type2, ...value } = part;
|
|
498
|
+
controller.enqueue({
|
|
499
|
+
type: "b" /* StartToolCall */,
|
|
500
|
+
value
|
|
501
|
+
});
|
|
502
|
+
}
|
|
503
|
+
if (part.type === "source") {
|
|
504
|
+
const { type: type2, ...value } = part;
|
|
505
|
+
controller.enqueue({
|
|
506
|
+
type: "h" /* Source */,
|
|
507
|
+
value
|
|
508
|
+
});
|
|
509
|
+
}
|
|
510
|
+
break;
|
|
511
|
+
}
|
|
512
|
+
case "text-delta": {
|
|
513
|
+
const part = chunk.meta;
|
|
514
|
+
switch (part.type) {
|
|
515
|
+
case "text": {
|
|
516
|
+
controller.enqueue({
|
|
517
|
+
type: "0" /* TextDelta */,
|
|
518
|
+
value: chunk.textDelta
|
|
519
|
+
});
|
|
520
|
+
break;
|
|
521
|
+
}
|
|
522
|
+
case "reasoning": {
|
|
523
|
+
controller.enqueue({
|
|
524
|
+
type: "g" /* ReasoningDelta */,
|
|
525
|
+
value: chunk.textDelta
|
|
526
|
+
});
|
|
527
|
+
break;
|
|
528
|
+
}
|
|
529
|
+
case "tool-call": {
|
|
530
|
+
controller.enqueue({
|
|
531
|
+
type: "c" /* ToolCallDelta */,
|
|
532
|
+
value: {
|
|
533
|
+
toolCallId: part.toolCallId,
|
|
534
|
+
argsTextDelta: chunk.textDelta
|
|
535
|
+
}
|
|
536
|
+
});
|
|
537
|
+
break;
|
|
538
|
+
}
|
|
539
|
+
default:
|
|
540
|
+
throw new Error(
|
|
541
|
+
`Unsupported part type for text-delta: ${part.type}`
|
|
542
|
+
);
|
|
543
|
+
}
|
|
544
|
+
break;
|
|
545
|
+
}
|
|
546
|
+
case "result": {
|
|
547
|
+
const part = chunk.meta;
|
|
548
|
+
if (part.type !== "tool-call") {
|
|
549
|
+
throw new Error(
|
|
550
|
+
`Result chunk on non-tool-call part not supported: ${part.type}`
|
|
551
|
+
);
|
|
552
|
+
}
|
|
553
|
+
controller.enqueue({
|
|
554
|
+
type: "a" /* ToolCallResult */,
|
|
555
|
+
value: {
|
|
556
|
+
toolCallId: part.toolCallId,
|
|
557
|
+
result: chunk.result
|
|
558
|
+
}
|
|
559
|
+
});
|
|
560
|
+
break;
|
|
561
|
+
}
|
|
562
|
+
case "step-start": {
|
|
563
|
+
const { type: type2, ...value } = chunk;
|
|
564
|
+
controller.enqueue({
|
|
565
|
+
type: "f" /* StartStep */,
|
|
566
|
+
value
|
|
567
|
+
});
|
|
568
|
+
break;
|
|
569
|
+
}
|
|
570
|
+
case "step-finish": {
|
|
571
|
+
const { type: type2, ...value } = chunk;
|
|
572
|
+
controller.enqueue({
|
|
573
|
+
type: "e" /* FinishStep */,
|
|
574
|
+
value
|
|
575
|
+
});
|
|
576
|
+
break;
|
|
577
|
+
}
|
|
578
|
+
case "message-finish": {
|
|
579
|
+
const { type: type2, ...value } = chunk;
|
|
580
|
+
controller.enqueue({
|
|
581
|
+
type: "d" /* FinishMessage */,
|
|
582
|
+
value
|
|
583
|
+
});
|
|
584
|
+
break;
|
|
585
|
+
}
|
|
586
|
+
case "error": {
|
|
587
|
+
controller.enqueue({
|
|
588
|
+
type: "3" /* Error */,
|
|
589
|
+
value: chunk.error
|
|
590
|
+
});
|
|
591
|
+
break;
|
|
592
|
+
}
|
|
593
|
+
case "annotations": {
|
|
594
|
+
controller.enqueue({
|
|
595
|
+
type: "8" /* Annotation */,
|
|
596
|
+
value: chunk.annotations
|
|
597
|
+
});
|
|
598
|
+
break;
|
|
599
|
+
}
|
|
600
|
+
case "data": {
|
|
601
|
+
controller.enqueue({
|
|
602
|
+
type: "2" /* Data */,
|
|
603
|
+
value: chunk.data
|
|
604
|
+
});
|
|
605
|
+
break;
|
|
606
|
+
}
|
|
607
|
+
// TODO ignore for now
|
|
608
|
+
// in the future, we should create a handler that waits for text parts to finish before continuing
|
|
609
|
+
case "tool-call-args-text-finish":
|
|
610
|
+
case "part-finish":
|
|
611
|
+
break;
|
|
612
|
+
default: {
|
|
613
|
+
const exhaustiveCheck = type;
|
|
614
|
+
throw new Error(`Unsupported chunk type: ${exhaustiveCheck}`);
|
|
615
|
+
}
|
|
616
|
+
}
|
|
617
|
+
}
|
|
618
|
+
});
|
|
619
|
+
return readable.pipeThrough(new AssistantMetaTransformStream()).pipeThrough(transform).pipeThrough(new DataStreamChunkEncoder()).pipeThrough(new TextEncoderStream());
|
|
620
|
+
});
|
|
621
|
+
}
|
|
622
|
+
};
|
|
623
|
+
var TOOL_CALL_ARGS_CLOSING_CHUNKS = [
|
|
624
|
+
"b" /* StartToolCall */,
|
|
625
|
+
"9" /* ToolCall */,
|
|
626
|
+
"0" /* TextDelta */,
|
|
627
|
+
"g" /* ReasoningDelta */,
|
|
628
|
+
"h" /* Source */,
|
|
629
|
+
"3" /* Error */,
|
|
630
|
+
"e" /* FinishStep */,
|
|
631
|
+
"d" /* FinishMessage */
|
|
632
|
+
];
|
|
633
|
+
var DataStreamDecoder = class extends PipeableTransformStream {
|
|
634
|
+
constructor() {
|
|
635
|
+
super((readable) => {
|
|
636
|
+
const toolCallControllers = /* @__PURE__ */ new Map();
|
|
637
|
+
let activeToolCallArgsText;
|
|
638
|
+
const transform = new AssistantTransformStream({
|
|
639
|
+
transform(chunk, controller) {
|
|
640
|
+
const { type, value } = chunk;
|
|
641
|
+
if (TOOL_CALL_ARGS_CLOSING_CHUNKS.includes(type)) {
|
|
642
|
+
activeToolCallArgsText?.close();
|
|
643
|
+
activeToolCallArgsText = void 0;
|
|
644
|
+
}
|
|
645
|
+
switch (type) {
|
|
646
|
+
case "g" /* ReasoningDelta */:
|
|
647
|
+
controller.appendReasoning(value);
|
|
648
|
+
break;
|
|
649
|
+
case "0" /* TextDelta */:
|
|
650
|
+
controller.appendText(value);
|
|
651
|
+
break;
|
|
652
|
+
case "b" /* StartToolCall */: {
|
|
653
|
+
const { toolCallId, toolName } = value;
|
|
654
|
+
const toolCallController = controller.addToolCallPart({
|
|
655
|
+
toolCallId,
|
|
656
|
+
toolName
|
|
657
|
+
});
|
|
658
|
+
toolCallControllers.set(toolCallId, toolCallController);
|
|
659
|
+
activeToolCallArgsText = toolCallController.argsText;
|
|
660
|
+
break;
|
|
661
|
+
}
|
|
662
|
+
case "c" /* ToolCallDelta */: {
|
|
663
|
+
const { toolCallId, argsTextDelta } = value;
|
|
664
|
+
const toolCallController = toolCallControllers.get(toolCallId);
|
|
665
|
+
if (!toolCallController)
|
|
666
|
+
throw new Error(
|
|
667
|
+
"Encountered tool call with unknown id: " + toolCallId
|
|
668
|
+
);
|
|
669
|
+
toolCallController.argsText.append(argsTextDelta);
|
|
670
|
+
break;
|
|
671
|
+
}
|
|
672
|
+
case "a" /* ToolCallResult */: {
|
|
673
|
+
const { toolCallId, result } = value;
|
|
674
|
+
const toolCallController = toolCallControllers.get(toolCallId);
|
|
675
|
+
if (!toolCallController)
|
|
676
|
+
throw new Error(
|
|
677
|
+
"Encountered tool call result with unknown id: " + toolCallId
|
|
678
|
+
);
|
|
679
|
+
toolCallController.setResult(result);
|
|
680
|
+
break;
|
|
681
|
+
}
|
|
682
|
+
case "9" /* ToolCall */: {
|
|
683
|
+
const { toolCallId, toolName, args } = value;
|
|
684
|
+
const toolCallController = controller.addToolCallPart({
|
|
685
|
+
toolCallId,
|
|
686
|
+
toolName
|
|
687
|
+
});
|
|
688
|
+
toolCallControllers.set(toolCallId, toolCallController);
|
|
689
|
+
toolCallController.argsText.append(JSON.stringify(args));
|
|
690
|
+
toolCallController.argsText.close();
|
|
691
|
+
break;
|
|
692
|
+
}
|
|
693
|
+
case "d" /* FinishMessage */:
|
|
694
|
+
controller.enqueue({
|
|
695
|
+
type: "message-finish",
|
|
696
|
+
path: [],
|
|
697
|
+
...value
|
|
698
|
+
});
|
|
699
|
+
break;
|
|
700
|
+
case "f" /* StartStep */:
|
|
701
|
+
controller.enqueue({
|
|
702
|
+
type: "step-start",
|
|
703
|
+
path: [],
|
|
704
|
+
...value
|
|
705
|
+
});
|
|
706
|
+
break;
|
|
707
|
+
case "e" /* FinishStep */:
|
|
708
|
+
controller.enqueue({
|
|
709
|
+
type: "step-finish",
|
|
710
|
+
path: [],
|
|
711
|
+
...value
|
|
712
|
+
});
|
|
713
|
+
break;
|
|
714
|
+
case "2" /* Data */:
|
|
715
|
+
controller.enqueue({
|
|
716
|
+
type: "data",
|
|
717
|
+
path: [],
|
|
718
|
+
data: value
|
|
719
|
+
});
|
|
720
|
+
break;
|
|
721
|
+
case "8" /* Annotation */:
|
|
722
|
+
controller.enqueue({
|
|
723
|
+
type: "annotations",
|
|
724
|
+
path: [],
|
|
725
|
+
annotations: value
|
|
726
|
+
});
|
|
727
|
+
break;
|
|
728
|
+
case "h" /* Source */:
|
|
729
|
+
controller.appendSource({
|
|
730
|
+
type: "source",
|
|
731
|
+
...value
|
|
732
|
+
});
|
|
733
|
+
break;
|
|
734
|
+
case "3" /* Error */:
|
|
735
|
+
controller.enqueue({
|
|
736
|
+
type: "error",
|
|
737
|
+
path: [],
|
|
738
|
+
error: value
|
|
739
|
+
});
|
|
740
|
+
break;
|
|
741
|
+
case "k" /* File */:
|
|
742
|
+
controller.appendFile({
|
|
743
|
+
type: "file",
|
|
744
|
+
...value
|
|
745
|
+
});
|
|
746
|
+
break;
|
|
747
|
+
case "j" /* ReasoningSignature */:
|
|
748
|
+
case "i" /* RedactedReasoning */:
|
|
749
|
+
break;
|
|
750
|
+
default: {
|
|
751
|
+
const exhaustiveCheck = type;
|
|
752
|
+
throw new Error(`unsupported chunk type: ${exhaustiveCheck}`);
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
},
|
|
756
|
+
flush() {
|
|
757
|
+
activeToolCallArgsText?.close();
|
|
758
|
+
activeToolCallArgsText = void 0;
|
|
759
|
+
toolCallControllers.forEach((controller) => controller.close());
|
|
760
|
+
toolCallControllers.clear();
|
|
761
|
+
}
|
|
762
|
+
});
|
|
763
|
+
return readable.pipeThrough(new TextDecoderStream()).pipeThrough(new LineDecoderStream()).pipeThrough(new DataStreamChunkDecoder()).pipeThrough(transform);
|
|
764
|
+
});
|
|
765
|
+
}
|
|
418
766
|
};
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
767
|
+
|
|
768
|
+
// src/core/utils/generateId.tsx
|
|
769
|
+
var import_non_secure = require("nanoid/non-secure");
|
|
770
|
+
var generateId = (0, import_non_secure.customAlphabet)(
|
|
771
|
+
"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz",
|
|
772
|
+
7
|
|
773
|
+
);
|
|
774
|
+
|
|
775
|
+
// src/core/modules/assistant-stream.ts
|
|
776
|
+
var AssistantStreamControllerImpl = class {
|
|
777
|
+
_merger = createMergeStream();
|
|
778
|
+
_append;
|
|
779
|
+
_contentCounter = new Counter();
|
|
780
|
+
get __internal_isClosed() {
|
|
781
|
+
return this._merger.isSealed();
|
|
424
782
|
}
|
|
425
|
-
|
|
426
|
-
this.
|
|
427
|
-
|
|
783
|
+
__internal_getReadable() {
|
|
784
|
+
return this._merger.readable;
|
|
785
|
+
}
|
|
786
|
+
_closeSubscriber;
|
|
787
|
+
__internal_subscribeToClose(callback) {
|
|
788
|
+
this._closeSubscriber = callback;
|
|
789
|
+
}
|
|
790
|
+
_addPart(part, stream) {
|
|
791
|
+
this.enqueue({
|
|
792
|
+
type: "part-start",
|
|
793
|
+
part,
|
|
794
|
+
path: []
|
|
795
|
+
});
|
|
796
|
+
this._merger.addStream(
|
|
797
|
+
stream.pipeThrough(new PathAppendEncoder(this._contentCounter.value))
|
|
798
|
+
);
|
|
428
799
|
}
|
|
429
800
|
merge(stream) {
|
|
430
|
-
this.
|
|
801
|
+
this._merger.addStream(
|
|
802
|
+
stream.pipeThrough(new PathMergeEncoder(this._contentCounter))
|
|
803
|
+
);
|
|
431
804
|
}
|
|
432
805
|
appendText(textDelta) {
|
|
433
|
-
if (
|
|
434
|
-
|
|
806
|
+
if (this._append?.kind !== "text") {
|
|
807
|
+
if (this._append) {
|
|
808
|
+
this._append.controller.close();
|
|
809
|
+
}
|
|
810
|
+
this._append = {
|
|
811
|
+
kind: "text",
|
|
812
|
+
controller: this.addTextPart()
|
|
813
|
+
};
|
|
435
814
|
}
|
|
436
|
-
this.
|
|
815
|
+
this._append.controller.append(textDelta);
|
|
437
816
|
}
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
controller = c;
|
|
817
|
+
appendReasoning(textDelta) {
|
|
818
|
+
if (this._append?.kind !== "reasoning") {
|
|
819
|
+
if (this._append) {
|
|
820
|
+
this._append.controller.close();
|
|
443
821
|
}
|
|
444
|
-
|
|
445
|
-
|
|
822
|
+
this._append = {
|
|
823
|
+
kind: "reasoning",
|
|
824
|
+
controller: this.addReasoningPart()
|
|
825
|
+
};
|
|
826
|
+
}
|
|
827
|
+
this._append.controller.append(textDelta);
|
|
828
|
+
}
|
|
829
|
+
addTextPart() {
|
|
830
|
+
const [stream, controller] = createTextStreamController();
|
|
831
|
+
this._addPart({ type: "text" }, stream);
|
|
832
|
+
return controller;
|
|
833
|
+
}
|
|
834
|
+
addReasoningPart() {
|
|
835
|
+
const [stream, controller] = createTextStreamController();
|
|
836
|
+
this._addPart({ type: "reasoning" }, stream);
|
|
446
837
|
return controller;
|
|
447
838
|
}
|
|
448
839
|
addToolCallPart(options) {
|
|
449
840
|
const opt = typeof options === "string" ? { toolName: options } : options;
|
|
450
|
-
|
|
451
|
-
const
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
start(c) {
|
|
455
|
-
controller = c;
|
|
456
|
-
}
|
|
457
|
-
});
|
|
458
|
-
this.merge(toolCallStream);
|
|
841
|
+
const toolName = opt.toolName;
|
|
842
|
+
const toolCallId = opt.toolCallId ?? generateId();
|
|
843
|
+
const [stream, controller] = createToolCallStreamController();
|
|
844
|
+
this._addPart({ type: "tool-call", toolName, toolCallId }, stream);
|
|
459
845
|
if (opt.args !== void 0) {
|
|
460
846
|
controller.argsText.append(JSON.stringify(opt.args));
|
|
461
847
|
controller.argsText.close();
|
|
462
848
|
}
|
|
463
|
-
if (opt !== void 0) {
|
|
464
|
-
controller.setResult(opt.result);
|
|
849
|
+
if (opt.result !== void 0) {
|
|
850
|
+
controller.setResult(opt.result, opt.isError);
|
|
465
851
|
}
|
|
466
852
|
return controller;
|
|
467
853
|
}
|
|
468
|
-
|
|
469
|
-
this.
|
|
854
|
+
appendSource(options) {
|
|
855
|
+
this._addPart(
|
|
856
|
+
options,
|
|
470
857
|
new ReadableStream({
|
|
471
|
-
start(
|
|
472
|
-
|
|
473
|
-
type: "
|
|
474
|
-
|
|
858
|
+
start(controller) {
|
|
859
|
+
controller.enqueue({
|
|
860
|
+
type: "part-finish",
|
|
861
|
+
path: []
|
|
475
862
|
});
|
|
863
|
+
controller.close();
|
|
476
864
|
}
|
|
477
865
|
})
|
|
478
866
|
);
|
|
479
867
|
}
|
|
868
|
+
appendFile(options) {
|
|
869
|
+
this._addPart(
|
|
870
|
+
options,
|
|
871
|
+
new ReadableStream({
|
|
872
|
+
start(controller) {
|
|
873
|
+
controller.enqueue({
|
|
874
|
+
type: "part-finish",
|
|
875
|
+
path: []
|
|
876
|
+
});
|
|
877
|
+
controller.close();
|
|
878
|
+
}
|
|
879
|
+
})
|
|
880
|
+
);
|
|
881
|
+
}
|
|
882
|
+
enqueue(chunk) {
|
|
883
|
+
this._merger.enqueue(chunk);
|
|
884
|
+
if (chunk.type === "part-start" && chunk.path.length === 0) {
|
|
885
|
+
this._contentCounter.up();
|
|
886
|
+
}
|
|
887
|
+
}
|
|
888
|
+
close() {
|
|
889
|
+
this._merger.seal();
|
|
890
|
+
this._append?.controller?.close();
|
|
891
|
+
this._closeSubscriber?.();
|
|
892
|
+
}
|
|
480
893
|
};
|
|
481
894
|
function createAssistantStream(callback) {
|
|
482
|
-
const controller = new
|
|
483
|
-
|
|
895
|
+
const controller = new AssistantStreamControllerImpl();
|
|
896
|
+
let promiseOrVoid;
|
|
897
|
+
try {
|
|
898
|
+
promiseOrVoid = callback(controller);
|
|
899
|
+
} catch (e) {
|
|
900
|
+
if (!controller.__internal_isClosed) {
|
|
901
|
+
controller.enqueue({
|
|
902
|
+
type: "error",
|
|
903
|
+
path: [],
|
|
904
|
+
error: String(e)
|
|
905
|
+
});
|
|
906
|
+
controller.close();
|
|
907
|
+
}
|
|
908
|
+
throw e;
|
|
909
|
+
}
|
|
484
910
|
if (promiseOrVoid instanceof Promise) {
|
|
485
911
|
const runTask = async () => {
|
|
486
912
|
try {
|
|
487
913
|
await promiseOrVoid;
|
|
488
914
|
} catch (e) {
|
|
489
|
-
controller.
|
|
915
|
+
if (!controller.__internal_isClosed) {
|
|
916
|
+
controller.enqueue({
|
|
917
|
+
type: "error",
|
|
918
|
+
path: [],
|
|
919
|
+
error: String(e)
|
|
920
|
+
});
|
|
921
|
+
}
|
|
490
922
|
throw e;
|
|
491
923
|
} finally {
|
|
492
|
-
controller.
|
|
924
|
+
if (!controller.__internal_isClosed) {
|
|
925
|
+
controller.close();
|
|
926
|
+
}
|
|
493
927
|
}
|
|
494
928
|
};
|
|
495
929
|
runTask();
|
|
496
930
|
} else {
|
|
497
|
-
controller.
|
|
931
|
+
if (!controller.__internal_isClosed) {
|
|
932
|
+
controller.close();
|
|
933
|
+
}
|
|
498
934
|
}
|
|
499
|
-
return controller.
|
|
935
|
+
return controller.__internal_getReadable();
|
|
936
|
+
}
|
|
937
|
+
var promiseWithResolvers2 = function() {
|
|
938
|
+
let resolve;
|
|
939
|
+
let reject;
|
|
940
|
+
const promise = new Promise((res, rej) => {
|
|
941
|
+
resolve = res;
|
|
942
|
+
reject = rej;
|
|
943
|
+
});
|
|
944
|
+
if (!resolve || !reject) throw new Error("Failed to create promise");
|
|
945
|
+
return { promise, resolve, reject };
|
|
946
|
+
};
|
|
947
|
+
function createAssistantStreamController() {
|
|
948
|
+
const { resolve, promise } = promiseWithResolvers2();
|
|
949
|
+
let controller;
|
|
950
|
+
const stream = createAssistantStream((c) => {
|
|
951
|
+
controller = c;
|
|
952
|
+
controller.__internal_subscribeToClose(
|
|
953
|
+
resolve
|
|
954
|
+
);
|
|
955
|
+
return promise;
|
|
956
|
+
});
|
|
957
|
+
return [stream, controller];
|
|
500
958
|
}
|
|
501
959
|
function createAssistantStreamResponse(callback) {
|
|
502
960
|
return AssistantStream.toResponse(
|
|
@@ -505,61 +963,119 @@ function createAssistantStreamResponse(callback) {
|
|
|
505
963
|
);
|
|
506
964
|
}
|
|
507
965
|
|
|
508
|
-
// src/core/
|
|
509
|
-
var
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
return this._transformStream.readable;
|
|
516
|
-
}
|
|
517
|
-
constructor() {
|
|
518
|
-
this._transformStream = new PipeableTransformStream((readable) => {
|
|
966
|
+
// src/core/effects/ToolExecutionStream.ts
|
|
967
|
+
var import_secure_json_parse = __toESM(require("secure-json-parse"));
|
|
968
|
+
var ToolExecutionStream = class extends PipeableTransformStream {
|
|
969
|
+
constructor(toolCallback) {
|
|
970
|
+
const toolCallPromises = /* @__PURE__ */ new Map();
|
|
971
|
+
const toolCallArgsText = {};
|
|
972
|
+
super((readable) => {
|
|
519
973
|
const transform = new TransformStream({
|
|
520
974
|
transform(chunk, controller) {
|
|
975
|
+
if (chunk.type !== "part-finish" || chunk.meta.type !== "tool-call") {
|
|
976
|
+
controller.enqueue(chunk);
|
|
977
|
+
}
|
|
521
978
|
const type = chunk.type;
|
|
522
979
|
switch (type) {
|
|
523
|
-
case "text-delta":
|
|
524
|
-
|
|
980
|
+
case "text-delta": {
|
|
981
|
+
if (chunk.meta.type === "tool-call") {
|
|
982
|
+
const toolCallId = chunk.meta.toolCallId;
|
|
983
|
+
if (toolCallArgsText[toolCallId] === void 0) {
|
|
984
|
+
toolCallArgsText[toolCallId] = chunk.textDelta;
|
|
985
|
+
} else {
|
|
986
|
+
toolCallArgsText[toolCallId] += chunk.textDelta;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
525
989
|
break;
|
|
526
|
-
|
|
527
|
-
|
|
528
|
-
|
|
990
|
+
}
|
|
991
|
+
case "tool-call-args-text-finish": {
|
|
992
|
+
if (chunk.meta.type !== "tool-call") break;
|
|
993
|
+
const { toolCallId, toolName } = chunk.meta;
|
|
994
|
+
const argsText = toolCallArgsText[toolCallId];
|
|
995
|
+
if (!argsText)
|
|
996
|
+
throw new Error("Unexpected tool call without args");
|
|
997
|
+
const executeTool = () => {
|
|
998
|
+
let args;
|
|
999
|
+
try {
|
|
1000
|
+
args = import_secure_json_parse.default.parse(argsText);
|
|
1001
|
+
} catch (e) {
|
|
1002
|
+
throw new Error(
|
|
1003
|
+
`Function parameter parsing failed. ${JSON.stringify(e.message)}`
|
|
1004
|
+
);
|
|
1005
|
+
}
|
|
1006
|
+
return toolCallback({
|
|
1007
|
+
toolCallId,
|
|
1008
|
+
toolName,
|
|
1009
|
+
args
|
|
1010
|
+
});
|
|
1011
|
+
};
|
|
1012
|
+
let promiseOrUndefined;
|
|
1013
|
+
try {
|
|
1014
|
+
promiseOrUndefined = executeTool();
|
|
1015
|
+
} catch (e) {
|
|
1016
|
+
controller.enqueue({
|
|
1017
|
+
type: "result",
|
|
1018
|
+
path: chunk.path,
|
|
1019
|
+
result: String(e),
|
|
1020
|
+
isError: true
|
|
1021
|
+
});
|
|
1022
|
+
break;
|
|
1023
|
+
}
|
|
1024
|
+
if (promiseOrUndefined instanceof Promise) {
|
|
1025
|
+
const toolCallPromise = promiseOrUndefined.then((c) => {
|
|
1026
|
+
if (c === void 0) return;
|
|
1027
|
+
controller.enqueue({
|
|
1028
|
+
type: "result",
|
|
1029
|
+
path: chunk.path,
|
|
1030
|
+
result: c,
|
|
1031
|
+
isError: false
|
|
1032
|
+
});
|
|
1033
|
+
}).catch((e) => {
|
|
1034
|
+
controller.enqueue({
|
|
1035
|
+
type: "result",
|
|
1036
|
+
path: chunk.path,
|
|
1037
|
+
result: String(e),
|
|
1038
|
+
isError: true
|
|
1039
|
+
});
|
|
1040
|
+
});
|
|
1041
|
+
toolCallPromises.set(toolCallId, toolCallPromise);
|
|
1042
|
+
} else if (promiseOrUndefined !== void 0) {
|
|
1043
|
+
controller.enqueue({
|
|
1044
|
+
type: "result",
|
|
1045
|
+
path: chunk.path,
|
|
1046
|
+
result: promiseOrUndefined,
|
|
1047
|
+
isError: false
|
|
1048
|
+
});
|
|
1049
|
+
}
|
|
1050
|
+
break;
|
|
1051
|
+
}
|
|
1052
|
+
case "part-finish": {
|
|
1053
|
+
if (chunk.meta.type !== "tool-call") break;
|
|
1054
|
+
const { toolCallId } = chunk.meta;
|
|
1055
|
+
const toolCallPromise = toolCallPromises.get(toolCallId);
|
|
1056
|
+
if (toolCallPromise) {
|
|
1057
|
+
toolCallPromise.then(() => {
|
|
1058
|
+
controller.enqueue(chunk);
|
|
1059
|
+
});
|
|
1060
|
+
} else {
|
|
1061
|
+
controller.enqueue(chunk);
|
|
1062
|
+
}
|
|
1063
|
+
}
|
|
529
1064
|
}
|
|
1065
|
+
},
|
|
1066
|
+
async flush() {
|
|
1067
|
+
await Promise.all(toolCallPromises);
|
|
530
1068
|
}
|
|
531
1069
|
});
|
|
532
|
-
return readable.pipeThrough(
|
|
533
|
-
});
|
|
534
|
-
}
|
|
535
|
-
};
|
|
536
|
-
var PlainTextDecoder = class {
|
|
537
|
-
_transformStream;
|
|
538
|
-
get writable() {
|
|
539
|
-
return this._transformStream.writable;
|
|
540
|
-
}
|
|
541
|
-
get readable() {
|
|
542
|
-
return this._transformStream.readable;
|
|
543
|
-
}
|
|
544
|
-
constructor() {
|
|
545
|
-
this._transformStream = new PipeableTransformStream((readable) => {
|
|
546
|
-
const transform = new TransformStream({
|
|
547
|
-
transform(chunk, controller) {
|
|
548
|
-
controller.enqueue({
|
|
549
|
-
type: "text-delta",
|
|
550
|
-
textDelta: chunk
|
|
551
|
-
});
|
|
552
|
-
}
|
|
553
|
-
});
|
|
554
|
-
return readable.pipeThrough(new TextDecoderStream()).pipeThrough(transform);
|
|
1070
|
+
return readable.pipeThrough(new AssistantMetaTransformStream()).pipeThrough(transform);
|
|
555
1071
|
});
|
|
556
1072
|
}
|
|
557
1073
|
};
|
|
558
1074
|
|
|
559
|
-
// src/core/
|
|
560
|
-
var
|
|
1075
|
+
// src/core/utils/json/parse-partial-json.ts
|
|
1076
|
+
var import_secure_json_parse2 = __toESM(require("secure-json-parse"));
|
|
561
1077
|
|
|
562
|
-
// src/core/
|
|
1078
|
+
// src/core/utils/json/fix-json.ts
|
|
563
1079
|
function fixJson(input) {
|
|
564
1080
|
const stack = ["ROOT"];
|
|
565
1081
|
let lastValidIndex = -1;
|
|
@@ -877,176 +1393,354 @@ function fixJson(input) {
|
|
|
877
1393
|
return result;
|
|
878
1394
|
}
|
|
879
1395
|
|
|
880
|
-
// src/core/
|
|
1396
|
+
// src/core/utils/json/parse-partial-json.ts
|
|
881
1397
|
var parsePartialJson = (json) => {
|
|
882
1398
|
try {
|
|
883
|
-
return
|
|
1399
|
+
return import_secure_json_parse2.default.parse(json);
|
|
884
1400
|
} catch {
|
|
885
1401
|
try {
|
|
886
|
-
return
|
|
1402
|
+
return import_secure_json_parse2.default.parse(fixJson(json));
|
|
887
1403
|
} catch {
|
|
888
1404
|
return void 0;
|
|
889
1405
|
}
|
|
890
1406
|
}
|
|
891
1407
|
};
|
|
892
1408
|
|
|
893
|
-
// src/core/accumulators/
|
|
894
|
-
var
|
|
895
|
-
|
|
896
|
-
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
901
|
-
|
|
1409
|
+
// src/core/accumulators/assistant-message-accumulator.ts
|
|
1410
|
+
var createInitialMessage = () => ({
|
|
1411
|
+
role: "assistant",
|
|
1412
|
+
status: { type: "running" },
|
|
1413
|
+
parts: [],
|
|
1414
|
+
get content() {
|
|
1415
|
+
return this.parts;
|
|
1416
|
+
},
|
|
1417
|
+
metadata: {
|
|
1418
|
+
unstable_data: [],
|
|
1419
|
+
unstable_annotations: [],
|
|
1420
|
+
steps: [],
|
|
1421
|
+
custom: {}
|
|
1422
|
+
}
|
|
1423
|
+
});
|
|
1424
|
+
var updatePartForPath = (message, chunk, updater) => {
|
|
1425
|
+
if (message.parts.length === 0) {
|
|
1426
|
+
throw new Error("No parts available to update.");
|
|
1427
|
+
}
|
|
1428
|
+
if (chunk.path.length !== 1)
|
|
1429
|
+
throw new Error("Nested paths are not supported yet.");
|
|
1430
|
+
const partIndex = chunk.path[0];
|
|
1431
|
+
const updatedPart = updater(message.parts[partIndex]);
|
|
1432
|
+
return {
|
|
1433
|
+
...message,
|
|
1434
|
+
parts: [
|
|
1435
|
+
...message.parts.slice(0, partIndex),
|
|
1436
|
+
updatedPart,
|
|
1437
|
+
...message.parts.slice(partIndex + 1)
|
|
1438
|
+
],
|
|
1439
|
+
get content() {
|
|
1440
|
+
return this.parts;
|
|
902
1441
|
}
|
|
903
1442
|
};
|
|
904
|
-
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
917
|
-
|
|
918
|
-
}
|
|
919
|
-
case "tool-call-delta": {
|
|
920
|
-
const { toolCallId, argsTextDelta } = chunk;
|
|
921
|
-
message = appendToolArgsTextDelta(message, toolCallId, argsTextDelta);
|
|
922
|
-
controller.enqueue(message);
|
|
923
|
-
break;
|
|
924
|
-
}
|
|
925
|
-
case "tool-result": {
|
|
926
|
-
const { toolCallId, result } = chunk;
|
|
927
|
-
message = setToolResult(message, toolCallId, result);
|
|
928
|
-
controller.enqueue(message);
|
|
929
|
-
break;
|
|
930
|
-
}
|
|
931
|
-
case "error": {
|
|
932
|
-
const { error } = chunk;
|
|
933
|
-
message = setError(message, error);
|
|
934
|
-
controller.enqueue(message);
|
|
935
|
-
break;
|
|
936
|
-
}
|
|
937
|
-
default: {
|
|
938
|
-
const _exhaustiveCheck = type;
|
|
939
|
-
throw new Error(`Unsupported chunk type: ${_exhaustiveCheck}`);
|
|
940
|
-
}
|
|
1443
|
+
};
|
|
1444
|
+
var handlePartStart = (message, chunk) => {
|
|
1445
|
+
const partInit = chunk.part;
|
|
1446
|
+
if (partInit.type === "text" || partInit.type === "reasoning") {
|
|
1447
|
+
const newTextPart = {
|
|
1448
|
+
type: partInit.type,
|
|
1449
|
+
text: "",
|
|
1450
|
+
status: { type: "running" }
|
|
1451
|
+
};
|
|
1452
|
+
return {
|
|
1453
|
+
...message,
|
|
1454
|
+
parts: [...message.parts, newTextPart],
|
|
1455
|
+
get content() {
|
|
1456
|
+
return this.parts;
|
|
941
1457
|
}
|
|
942
|
-
}
|
|
943
|
-
|
|
944
|
-
|
|
945
|
-
|
|
1458
|
+
};
|
|
1459
|
+
} else if (partInit.type === "tool-call") {
|
|
1460
|
+
const newToolCallPart = {
|
|
1461
|
+
type: "tool-call",
|
|
1462
|
+
state: "partial-call",
|
|
1463
|
+
status: { type: "running", isArgsComplete: false },
|
|
1464
|
+
toolCallId: partInit.toolCallId,
|
|
1465
|
+
toolName: partInit.toolName,
|
|
1466
|
+
argsText: "",
|
|
1467
|
+
args: {}
|
|
1468
|
+
};
|
|
1469
|
+
return {
|
|
1470
|
+
...message,
|
|
1471
|
+
parts: [...message.parts, newToolCallPart],
|
|
1472
|
+
get content() {
|
|
1473
|
+
return this.parts;
|
|
1474
|
+
}
|
|
1475
|
+
};
|
|
1476
|
+
} else if (partInit.type === "source") {
|
|
1477
|
+
const newSourcePart = {
|
|
1478
|
+
type: "source",
|
|
1479
|
+
sourceType: partInit.sourceType,
|
|
1480
|
+
id: partInit.id,
|
|
1481
|
+
url: partInit.url,
|
|
1482
|
+
...partInit.title ? { title: partInit.title } : void 0
|
|
1483
|
+
};
|
|
1484
|
+
return {
|
|
1485
|
+
...message,
|
|
1486
|
+
parts: [...message.parts, newSourcePart],
|
|
1487
|
+
get content() {
|
|
1488
|
+
return this.parts;
|
|
1489
|
+
}
|
|
1490
|
+
};
|
|
1491
|
+
} else if (partInit.type === "file") {
|
|
1492
|
+
const newFilePart = {
|
|
1493
|
+
type: "file",
|
|
1494
|
+
mimeType: partInit.mimeType,
|
|
1495
|
+
data: partInit.data
|
|
1496
|
+
};
|
|
1497
|
+
return {
|
|
1498
|
+
...message,
|
|
1499
|
+
parts: [...message.parts, newFilePart],
|
|
1500
|
+
get content() {
|
|
1501
|
+
return this.parts;
|
|
1502
|
+
}
|
|
1503
|
+
};
|
|
1504
|
+
} else {
|
|
1505
|
+
throw new Error(`Unsupported part type: ${partInit.type}`);
|
|
1506
|
+
}
|
|
1507
|
+
};
|
|
1508
|
+
var handleToolCallArgsTextFinish = (message, chunk) => {
|
|
1509
|
+
return updatePartForPath(message, chunk, (lastPart) => {
|
|
1510
|
+
if (lastPart.type !== "tool-call") {
|
|
1511
|
+
throw new Error("Last part is not a tool call");
|
|
946
1512
|
}
|
|
1513
|
+
return {
|
|
1514
|
+
...lastPart,
|
|
1515
|
+
state: "call"
|
|
1516
|
+
};
|
|
947
1517
|
});
|
|
948
|
-
return transformer;
|
|
949
1518
|
};
|
|
950
|
-
var
|
|
951
|
-
|
|
952
|
-
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
1519
|
+
var handlePartFinish = (message, chunk) => {
|
|
1520
|
+
return updatePartForPath(message, chunk, (lastPart) => ({
|
|
1521
|
+
...lastPart,
|
|
1522
|
+
status: { type: "complete", reason: "unknown" }
|
|
1523
|
+
}));
|
|
1524
|
+
};
|
|
1525
|
+
var handleTextDelta = (message, chunk) => {
|
|
1526
|
+
return updatePartForPath(message, chunk, (lastPart) => {
|
|
1527
|
+
if (lastPart.type === "text") {
|
|
1528
|
+
return { ...lastPart, text: lastPart.text + chunk.textDelta };
|
|
1529
|
+
} else if (lastPart.type === "tool-call") {
|
|
1530
|
+
const newArgsText = lastPart.argsText + chunk.textDelta;
|
|
1531
|
+
let newArgs;
|
|
1532
|
+
try {
|
|
1533
|
+
newArgs = parsePartialJson(newArgsText);
|
|
1534
|
+
} catch (err) {
|
|
1535
|
+
newArgs = lastPart.args;
|
|
1536
|
+
}
|
|
1537
|
+
return { ...lastPart, argsText: newArgsText, args: newArgs };
|
|
1538
|
+
} else {
|
|
1539
|
+
throw new Error(
|
|
1540
|
+
"text-delta received but last part is neither text nor tool-call"
|
|
1541
|
+
);
|
|
1542
|
+
}
|
|
1543
|
+
});
|
|
1544
|
+
};
|
|
1545
|
+
var handleResult = (message, chunk) => {
|
|
1546
|
+
return updatePartForPath(message, chunk, (lastPart) => {
|
|
1547
|
+
if (lastPart.type === "tool-call") {
|
|
1548
|
+
return {
|
|
1549
|
+
...lastPart,
|
|
1550
|
+
state: "result",
|
|
1551
|
+
result: chunk.result,
|
|
1552
|
+
isError: chunk.isError ?? false,
|
|
1553
|
+
status: { type: "complete", reason: "stop" }
|
|
1554
|
+
};
|
|
1555
|
+
} else {
|
|
1556
|
+
throw new Error("Result chunk received but last part is not a tool-call");
|
|
1557
|
+
}
|
|
1558
|
+
});
|
|
1559
|
+
};
|
|
1560
|
+
var handleMessageFinish = (message, chunk) => {
|
|
1561
|
+
const newStatus = getStatus(chunk);
|
|
1562
|
+
return { ...message, status: newStatus };
|
|
1563
|
+
};
|
|
1564
|
+
var getStatus = (chunk) => {
|
|
1565
|
+
if (chunk.finishReason === "tool-calls") {
|
|
1566
|
+
return {
|
|
1567
|
+
type: "requires-action",
|
|
1568
|
+
reason: "tool-calls"
|
|
1569
|
+
};
|
|
1570
|
+
} else if (chunk.finishReason === "stop" || chunk.finishReason === "unknown") {
|
|
1571
|
+
return {
|
|
1572
|
+
type: "complete",
|
|
1573
|
+
reason: chunk.finishReason
|
|
958
1574
|
};
|
|
959
1575
|
} else {
|
|
960
|
-
|
|
961
|
-
|
|
962
|
-
|
|
963
|
-
text: contentPart.text + textDelta,
|
|
964
|
-
status: { type: "running" }
|
|
1576
|
+
return {
|
|
1577
|
+
type: "incomplete",
|
|
1578
|
+
reason: chunk.finishReason
|
|
965
1579
|
};
|
|
966
1580
|
}
|
|
967
|
-
return {
|
|
968
|
-
...message,
|
|
969
|
-
content: contentParts.concat([contentPart])
|
|
970
|
-
};
|
|
971
1581
|
};
|
|
972
|
-
var
|
|
1582
|
+
var handleAnnotations = (message, chunk) => {
|
|
973
1583
|
return {
|
|
974
1584
|
...message,
|
|
975
|
-
|
|
976
|
-
...message.
|
|
977
|
-
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
args: {},
|
|
983
|
-
status: { type: "running", isArgsComplete: false }
|
|
984
|
-
}
|
|
985
|
-
]
|
|
1585
|
+
metadata: {
|
|
1586
|
+
...message.metadata,
|
|
1587
|
+
unstable_annotations: [
|
|
1588
|
+
...message.metadata.unstable_annotations,
|
|
1589
|
+
...chunk.annotations
|
|
1590
|
+
]
|
|
1591
|
+
}
|
|
986
1592
|
};
|
|
987
1593
|
};
|
|
988
|
-
var
|
|
989
|
-
const contentPartIdx = message.content.findIndex(
|
|
990
|
-
(part) => part.type === "tool-call" && part.toolCallId === toolCallId
|
|
991
|
-
);
|
|
992
|
-
if (contentPartIdx === -1)
|
|
993
|
-
throw new Error(
|
|
994
|
-
`Received tool call delta for unknown tool call "${toolCallId}".`
|
|
995
|
-
);
|
|
996
|
-
const contentPart = message.content[contentPartIdx];
|
|
997
|
-
const newArgsText = contentPart.argsText + argsTextDelta;
|
|
1594
|
+
var handleData = (message, chunk) => {
|
|
998
1595
|
return {
|
|
999
1596
|
...message,
|
|
1000
|
-
|
|
1001
|
-
...message.
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
argsText: newArgsText,
|
|
1005
|
-
args: parsePartialJson(newArgsText)
|
|
1006
|
-
},
|
|
1007
|
-
...message.content.slice(contentPartIdx + 1)
|
|
1008
|
-
]
|
|
1597
|
+
metadata: {
|
|
1598
|
+
...message.metadata,
|
|
1599
|
+
unstable_data: [...message.metadata.unstable_data, ...chunk.data]
|
|
1600
|
+
}
|
|
1009
1601
|
};
|
|
1010
1602
|
};
|
|
1011
|
-
var
|
|
1012
|
-
let found = false;
|
|
1013
|
-
const newContentParts = message.content?.map((part) => {
|
|
1014
|
-
if (part.type !== "tool-call" || part.toolCallId !== toolCallId)
|
|
1015
|
-
return part;
|
|
1016
|
-
found = true;
|
|
1017
|
-
return {
|
|
1018
|
-
...part,
|
|
1019
|
-
result
|
|
1020
|
-
};
|
|
1021
|
-
});
|
|
1022
|
-
if (!found)
|
|
1023
|
-
throw new Error(
|
|
1024
|
-
`Received tool result for unknown tool call "${toolCallId}". This is likely an internal bug in assistant-ui.`
|
|
1025
|
-
);
|
|
1603
|
+
var handleStepStart = (message, chunk) => {
|
|
1026
1604
|
return {
|
|
1027
1605
|
...message,
|
|
1028
|
-
|
|
1606
|
+
metadata: {
|
|
1607
|
+
...message.metadata,
|
|
1608
|
+
steps: [
|
|
1609
|
+
...message.metadata.steps,
|
|
1610
|
+
{ state: "started", messageId: chunk.messageId }
|
|
1611
|
+
]
|
|
1612
|
+
}
|
|
1029
1613
|
};
|
|
1030
1614
|
};
|
|
1031
|
-
var
|
|
1615
|
+
var handleStepFinish = (message, chunk) => {
|
|
1616
|
+
const steps = message.metadata.steps.slice();
|
|
1617
|
+
const lastIndex = steps.length - 1;
|
|
1618
|
+
if (steps.length > 0 && steps[lastIndex]?.state === "started") {
|
|
1619
|
+
steps[lastIndex] = {
|
|
1620
|
+
...steps[lastIndex],
|
|
1621
|
+
state: "finished",
|
|
1622
|
+
finishReason: chunk.finishReason,
|
|
1623
|
+
usage: chunk.usage,
|
|
1624
|
+
isContinued: chunk.isContinued
|
|
1625
|
+
};
|
|
1626
|
+
} else {
|
|
1627
|
+
steps.push({
|
|
1628
|
+
state: "finished",
|
|
1629
|
+
messageId: generateId(),
|
|
1630
|
+
finishReason: chunk.finishReason,
|
|
1631
|
+
usage: chunk.usage,
|
|
1632
|
+
isContinued: chunk.isContinued
|
|
1633
|
+
});
|
|
1634
|
+
}
|
|
1032
1635
|
return {
|
|
1033
1636
|
...message,
|
|
1034
|
-
|
|
1035
|
-
|
|
1036
|
-
|
|
1637
|
+
metadata: {
|
|
1638
|
+
...message.metadata,
|
|
1639
|
+
steps
|
|
1037
1640
|
}
|
|
1038
1641
|
};
|
|
1039
1642
|
};
|
|
1040
|
-
var
|
|
1643
|
+
var handleErrorChunk = (message, chunk) => {
|
|
1041
1644
|
return {
|
|
1042
1645
|
...message,
|
|
1043
|
-
status: {
|
|
1044
|
-
type: "incomplete",
|
|
1045
|
-
reason: "error",
|
|
1046
|
-
error
|
|
1047
|
-
}
|
|
1646
|
+
status: { type: "incomplete", reason: "error", error: chunk.error }
|
|
1048
1647
|
};
|
|
1049
1648
|
};
|
|
1649
|
+
var AssistantMessageAccumulator = class extends TransformStream {
|
|
1650
|
+
constructor() {
|
|
1651
|
+
let message = createInitialMessage();
|
|
1652
|
+
let hadChunks = false;
|
|
1653
|
+
super({
|
|
1654
|
+
transform(chunk, controller) {
|
|
1655
|
+
const type = chunk.type;
|
|
1656
|
+
switch (type) {
|
|
1657
|
+
case "part-start":
|
|
1658
|
+
message = handlePartStart(message, chunk);
|
|
1659
|
+
break;
|
|
1660
|
+
case "tool-call-args-text-finish":
|
|
1661
|
+
message = handleToolCallArgsTextFinish(message, chunk);
|
|
1662
|
+
break;
|
|
1663
|
+
case "part-finish":
|
|
1664
|
+
message = handlePartFinish(message, chunk);
|
|
1665
|
+
break;
|
|
1666
|
+
case "text-delta":
|
|
1667
|
+
message = handleTextDelta(message, chunk);
|
|
1668
|
+
break;
|
|
1669
|
+
case "result":
|
|
1670
|
+
message = handleResult(message, chunk);
|
|
1671
|
+
break;
|
|
1672
|
+
case "message-finish":
|
|
1673
|
+
message = handleMessageFinish(message, chunk);
|
|
1674
|
+
break;
|
|
1675
|
+
case "annotations":
|
|
1676
|
+
message = handleAnnotations(message, chunk);
|
|
1677
|
+
break;
|
|
1678
|
+
case "data":
|
|
1679
|
+
message = handleData(message, chunk);
|
|
1680
|
+
break;
|
|
1681
|
+
case "step-start":
|
|
1682
|
+
message = handleStepStart(message, chunk);
|
|
1683
|
+
break;
|
|
1684
|
+
case "step-finish":
|
|
1685
|
+
message = handleStepFinish(message, chunk);
|
|
1686
|
+
break;
|
|
1687
|
+
case "error":
|
|
1688
|
+
message = handleErrorChunk(message, chunk);
|
|
1689
|
+
break;
|
|
1690
|
+
default: {
|
|
1691
|
+
const unhandledType = type;
|
|
1692
|
+
throw new Error(`Unsupported chunk type: ${unhandledType}`);
|
|
1693
|
+
}
|
|
1694
|
+
}
|
|
1695
|
+
controller.enqueue(message);
|
|
1696
|
+
hadChunks = true;
|
|
1697
|
+
},
|
|
1698
|
+
flush(controller) {
|
|
1699
|
+
if (!hadChunks) {
|
|
1700
|
+
controller.enqueue(message);
|
|
1701
|
+
}
|
|
1702
|
+
}
|
|
1703
|
+
});
|
|
1704
|
+
}
|
|
1705
|
+
};
|
|
1706
|
+
|
|
1707
|
+
// src/core/serialization/PlainText.ts
|
|
1708
|
+
var PlainTextEncoder = class extends PipeableTransformStream {
|
|
1709
|
+
headers = new Headers({
|
|
1710
|
+
"Content-Type": "text/plain; charset=utf-8",
|
|
1711
|
+
"x-vercel-ai-data-stream": "v1"
|
|
1712
|
+
});
|
|
1713
|
+
constructor() {
|
|
1714
|
+
super((readable) => {
|
|
1715
|
+
const transform = new TransformStream({
|
|
1716
|
+
transform(chunk, controller) {
|
|
1717
|
+
const type = chunk.type;
|
|
1718
|
+
switch (type) {
|
|
1719
|
+
case "text-delta":
|
|
1720
|
+
controller.enqueue(chunk.textDelta);
|
|
1721
|
+
break;
|
|
1722
|
+
default:
|
|
1723
|
+
const unsupportedType = type;
|
|
1724
|
+
throw new Error(`unsupported chunk type: ${unsupportedType}`);
|
|
1725
|
+
}
|
|
1726
|
+
}
|
|
1727
|
+
});
|
|
1728
|
+
return readable.pipeThrough(transform).pipeThrough(new TextEncoderStream());
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
};
|
|
1732
|
+
var PlainTextDecoder = class extends PipeableTransformStream {
|
|
1733
|
+
constructor() {
|
|
1734
|
+
super((readable) => {
|
|
1735
|
+
const transform = new AssistantTransformStream({
|
|
1736
|
+
transform(chunk, controller) {
|
|
1737
|
+
controller.appendText(chunk);
|
|
1738
|
+
}
|
|
1739
|
+
});
|
|
1740
|
+
return readable.pipeThrough(new TextDecoderStream()).pipeThrough(transform);
|
|
1741
|
+
});
|
|
1742
|
+
}
|
|
1743
|
+
};
|
|
1050
1744
|
|
|
1051
1745
|
// src/core/accumulators/AssistantMessageStream.ts
|
|
1052
1746
|
var AssistantMessageStream = class _AssistantMessageStream {
|
|
@@ -1056,7 +1750,7 @@ var AssistantMessageStream = class _AssistantMessageStream {
|
|
|
1056
1750
|
}
|
|
1057
1751
|
static fromAssistantStream(stream) {
|
|
1058
1752
|
return new _AssistantMessageStream(
|
|
1059
|
-
stream.pipeThrough(
|
|
1753
|
+
stream.pipeThrough(new AssistantMessageAccumulator())
|
|
1060
1754
|
);
|
|
1061
1755
|
}
|
|
1062
1756
|
async unstable_result() {
|
|
@@ -1068,8 +1762,11 @@ var AssistantMessageStream = class _AssistantMessageStream {
|
|
|
1068
1762
|
return {
|
|
1069
1763
|
role: "assistant",
|
|
1070
1764
|
status: { type: "complete", reason: "unknown" },
|
|
1765
|
+
parts: [],
|
|
1071
1766
|
content: [],
|
|
1072
1767
|
metadata: {
|
|
1768
|
+
unstable_data: [],
|
|
1769
|
+
unstable_annotations: [],
|
|
1073
1770
|
steps: [],
|
|
1074
1771
|
custom: {}
|
|
1075
1772
|
}
|
|
@@ -1096,12 +1793,14 @@ var AssistantMessageStream = class _AssistantMessageStream {
|
|
|
1096
1793
|
};
|
|
1097
1794
|
// Annotate the CommonJS export names for ESM import in node:
|
|
1098
1795
|
0 && (module.exports = {
|
|
1796
|
+
AssistantMessageAccumulator,
|
|
1099
1797
|
AssistantMessageStream,
|
|
1100
1798
|
AssistantStream,
|
|
1101
1799
|
DataStreamDecoder,
|
|
1102
1800
|
DataStreamEncoder,
|
|
1103
1801
|
PlainTextDecoder,
|
|
1104
1802
|
PlainTextEncoder,
|
|
1803
|
+
ToolExecutionStream,
|
|
1105
1804
|
createAssistantStream,
|
|
1106
1805
|
createAssistantStreamResponse
|
|
1107
1806
|
});
|