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