assistant-stream 0.3.26 → 0.3.28
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/core/AssistantStream.d.ts.map +1 -1
- package/dist/core/AssistantStreamChunk.d.ts +3 -3
- package/dist/core/accumulators/AssistantMessageStream.d.ts.map +1 -1
- package/dist/core/accumulators/AssistantMessageStream.js +0 -1
- package/dist/core/accumulators/AssistantMessageStream.js.map +1 -1
- package/dist/core/accumulators/assistant-message-accumulator.d.ts.map +1 -1
- package/dist/core/accumulators/assistant-message-accumulator.js +65 -28
- package/dist/core/accumulators/assistant-message-accumulator.js.map +1 -1
- package/dist/core/converters/toGenericMessages.js.map +1 -1
- package/dist/core/gorp/GorpStreamAccumulator.d.ts +15 -0
- package/dist/core/gorp/GorpStreamAccumulator.d.ts.map +1 -0
- package/dist/core/{object/ObjectStreamAccumulator.js → gorp/GorpStreamAccumulator.js} +11 -9
- package/dist/core/gorp/GorpStreamAccumulator.js.map +1 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.d.ts +17 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.d.ts.map +1 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.js +38 -0
- package/dist/core/gorp/GorpStreamDeltaTracker.js.map +1 -0
- package/dist/core/gorp/GorpStreamResponse.d.ts +16 -0
- package/dist/core/gorp/GorpStreamResponse.d.ts.map +1 -0
- package/dist/core/gorp/GorpStreamResponse.js +51 -0
- package/dist/core/gorp/GorpStreamResponse.js.map +1 -0
- package/dist/core/gorp/changeTree.d.ts +16 -0
- package/dist/core/gorp/changeTree.d.ts.map +1 -0
- package/dist/core/gorp/changeTree.js +77 -0
- package/dist/core/gorp/changeTree.js.map +1 -0
- package/dist/core/gorp/createGorpStream.d.ts +16 -0
- package/dist/core/gorp/createGorpStream.d.ts.map +1 -0
- package/dist/core/{object/createObjectStream.js → gorp/createGorpStream.js} +13 -8
- package/dist/core/gorp/createGorpStream.js.map +1 -0
- package/dist/core/{object → gorp}/types.d.ts +6 -5
- package/dist/core/gorp/types.d.ts.map +1 -0
- package/dist/core/modules/assistant-stream.d.ts +5 -4
- package/dist/core/modules/assistant-stream.d.ts.map +1 -1
- package/dist/core/modules/assistant-stream.js +10 -6
- package/dist/core/modules/assistant-stream.js.map +1 -1
- package/dist/core/modules/tool-call.d.ts.map +1 -1
- package/dist/core/modules/tool-call.js +3 -3
- package/dist/core/modules/tool-call.js.map +1 -1
- package/dist/core/serialization/assistant-transport/AssistantTransport.d.ts.map +1 -1
- package/dist/core/serialization/assistant-transport/AssistantTransport.js +91 -1
- package/dist/core/serialization/assistant-transport/AssistantTransport.js.map +1 -1
- package/dist/core/serialization/data-stream/DataStream.js +48 -48
- package/dist/core/serialization/data-stream/DataStream.js.map +1 -1
- package/dist/core/serialization/data-stream/chunk-types.d.ts +25 -24
- package/dist/core/serialization/data-stream/chunk-types.d.ts.map +1 -1
- package/dist/core/serialization/data-stream/chunk-types.js +22 -23
- package/dist/core/serialization/data-stream/chunk-types.js.map +1 -1
- package/dist/core/serialization/data-stream/serialization.d.ts.map +1 -1
- package/dist/core/serialization/data-stream/serialization.js +14 -2
- package/dist/core/serialization/data-stream/serialization.js.map +1 -1
- package/dist/core/serialization/ui-message-stream/UIMessageStream.d.ts.map +1 -1
- package/dist/core/serialization/ui-message-stream/UIMessageStream.js +12 -1
- package/dist/core/serialization/ui-message-stream/UIMessageStream.js.map +1 -1
- package/dist/core/tool/ToolCallReader.d.ts.map +1 -1
- package/dist/core/tool/ToolCallReader.js.map +1 -1
- package/dist/core/tool/ToolExecutionStream.d.ts.map +1 -1
- package/dist/core/tool/ToolExecutionStream.js +9 -1
- package/dist/core/tool/ToolExecutionStream.js.map +1 -1
- package/dist/core/tool/ToolResponse.d.ts.map +1 -1
- package/dist/core/tool/tool-types.d.ts +6 -0
- package/dist/core/tool/tool-types.d.ts.map +1 -1
- package/dist/core/tool/toolResultStream.d.ts.map +1 -1
- package/dist/core/tool/toolResultStream.js +7 -2
- package/dist/core/tool/toolResultStream.js.map +1 -1
- package/dist/core/utils/stream/AssistantTransformStream.d.ts.map +1 -1
- package/dist/core/utils/stream/PipeableTransformStream.d.ts.map +1 -1
- package/dist/core/utils/stream/SSE.d.ts.map +1 -1
- package/dist/core/utils/stream/SSE.js +11 -2
- package/dist/core/utils/stream/SSE.js.map +1 -1
- package/dist/core/utils/stream/SSEEventDecoder.d.ts.map +1 -1
- package/dist/core/utils/stream/merge.d.ts +2 -0
- package/dist/core/utils/stream/merge.d.ts.map +1 -1
- package/dist/core/utils/stream/merge.js +27 -8
- package/dist/core/utils/stream/merge.js.map +1 -1
- package/dist/core/utils/stream/path-utils.d.ts.map +1 -1
- package/dist/index.d.ts +25 -4
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -3
- package/dist/index.js.map +1 -0
- package/dist/resumable/ResumableStreamContext.d.ts.map +1 -1
- package/dist/resumable/ResumableStreamContext.js +12 -5
- package/dist/resumable/ResumableStreamContext.js.map +1 -1
- package/dist/resumable/errors.d.ts.map +1 -1
- package/dist/resumable/stores/redis-impl.d.ts.map +1 -1
- package/dist/utils/AsyncIterableStream.d.ts.map +1 -1
- package/dist/utils/AsyncIterableStream.js +18 -3
- package/dist/utils/AsyncIterableStream.js.map +1 -1
- package/dist/utils/promiseWithResolvers.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/core/AssistantStreamChunk.ts +3 -3
- package/src/core/accumulators/AssistantMessageStream.ts +3 -1
- package/src/core/accumulators/assistant-message-accumulator.test.ts +374 -1
- package/src/core/accumulators/assistant-message-accumulator.ts +75 -26
- package/src/core/converters/toGenericMessages.test.ts +3 -39
- package/src/core/{object/ObjectStream.test.ts → gorp/GorpStream.test.ts} +86 -25
- package/src/core/gorp/GorpStreamAccumulator.test.ts +28 -0
- package/src/core/{object/ObjectStreamAccumulator.ts → gorp/GorpStreamAccumulator.ts} +13 -15
- package/src/core/gorp/GorpStreamDeltaTracker.test.ts +212 -0
- package/src/core/gorp/GorpStreamDeltaTracker.ts +55 -0
- package/src/core/{object/ObjectStreamResponse.test.ts → gorp/GorpStreamResponse.test.ts} +6 -6
- package/src/core/gorp/GorpStreamResponse.ts +88 -0
- package/src/core/gorp/changeTree.ts +96 -0
- package/src/core/{object/createObjectStream.ts → gorp/createGorpStream.ts} +23 -17
- package/src/core/{object → gorp}/types.ts +5 -3
- package/src/core/modules/assistant-stream.test.ts +154 -2
- package/src/core/modules/assistant-stream.ts +16 -6
- package/src/core/modules/tool-call.test.ts +67 -0
- package/src/core/modules/tool-call.ts +7 -4
- package/src/core/serialization/assistant-transport/AssistantTransport.test.ts +174 -1
- package/src/core/serialization/assistant-transport/AssistantTransport.ts +77 -1
- package/src/core/serialization/data-stream/DataStream.ts +1 -1
- package/src/core/serialization/data-stream/chunk-types.ts +26 -24
- package/src/core/serialization/data-stream/serialization.test.ts +133 -0
- package/src/core/serialization/data-stream/serialization.ts +20 -2
- package/src/core/serialization/ui-message-stream/UIMessageStream.test.ts +135 -0
- package/src/core/serialization/ui-message-stream/UIMessageStream.ts +21 -1
- package/src/core/tool/ToolCallReader.ts +5 -1
- package/src/core/tool/ToolExecutionStream.ts +10 -0
- package/src/core/tool/tool-types.ts +7 -0
- package/src/core/tool/toolResultStream.test.ts +50 -0
- package/src/core/tool/toolResultStream.ts +7 -2
- package/src/core/utils/stream/SSE.test.ts +97 -0
- package/src/core/utils/stream/SSE.ts +13 -2
- package/src/core/utils/stream/merge.ts +31 -9
- package/src/gorp.test.ts +32 -0
- package/src/index.ts +21 -6
- package/src/resumable/ResumableStreamContext.test.ts +116 -1
- package/src/resumable/ResumableStreamContext.ts +32 -5
- package/src/resumable/createResumableAssistantStreamResponse.test.ts +1 -25
- package/src/utils/AsyncIterableStream.test.ts +61 -0
- package/src/utils/AsyncIterableStream.ts +18 -3
- package/dist/core/object/ObjectStreamAccumulator.d.ts +0 -15
- package/dist/core/object/ObjectStreamAccumulator.d.ts.map +0 -1
- package/dist/core/object/ObjectStreamAccumulator.js.map +0 -1
- package/dist/core/object/ObjectStreamResponse.d.ts +0 -16
- package/dist/core/object/ObjectStreamResponse.d.ts.map +0 -1
- package/dist/core/object/ObjectStreamResponse.js +0 -57
- package/dist/core/object/ObjectStreamResponse.js.map +0 -1
- package/dist/core/object/createObjectStream.d.ts +0 -16
- package/dist/core/object/createObjectStream.d.ts.map +0 -1
- package/dist/core/object/createObjectStream.js.map +0 -1
- package/dist/core/object/types.d.ts.map +0 -1
- package/src/core/accumulators/TimingTracker.test.ts +0 -100
- package/src/core/object/ObjectStreamResponse.ts +0 -114
- /package/dist/core/{object → gorp}/types.js +0 -0
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UIMessageStream.d.ts","names":[],"sources":["../../../../src/core/serialization/ui-message-stream/UIMessageStream.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"UIMessageStream.d.ts","names":[],"sources":["../../../../src/core/serialization/ui-message-stream/UIMessageStream.ts"],"mappings":";;;;KAkBY;EACV,UAAU;IACR;IACA;IACA;IACA;;;;;;cAWS,+BAA+B,wBAC1C,WAAW,cACX;EAEY,YAAA,UAAS"}
|
|
@@ -2,6 +2,7 @@ import { AssistantTransformStream } from "../../utils/stream/AssistantTransformS
|
|
|
2
2
|
import { PipeableTransformStream } from "../../utils/stream/PipeableTransformStream.js";
|
|
3
3
|
import { generateId } from "../../utils/generateId.js";
|
|
4
4
|
import { SSEEventDecoderStream } from "../../utils/stream/SSEEventDecoderStream.js";
|
|
5
|
+
import sjson from "secure-json-parse";
|
|
5
6
|
//#region src/core/serialization/ui-message-stream/UIMessageStream.ts
|
|
6
7
|
const isDataChunk = (chunk) => chunk.type.startsWith("data-");
|
|
7
8
|
/**
|
|
@@ -92,6 +93,7 @@ var UIMessageStreamDecoder = class extends PipeableTransformStream {
|
|
|
92
93
|
case "tool-result": {
|
|
93
94
|
const toolCallController = toolCallControllers.get(chunk.toolCallId);
|
|
94
95
|
if (!toolCallController) throw new Error(`Encountered tool result with unknown id: ${chunk.toolCallId}`);
|
|
96
|
+
if (toolCallController.argsText === activeToolCallArgsText) activeToolCallArgsText = void 0;
|
|
95
97
|
toolCallController.setResponse({
|
|
96
98
|
result: chunk.result,
|
|
97
99
|
isError: chunk.isError ?? false,
|
|
@@ -147,7 +149,16 @@ var UIMessageStreamDecoder = class extends PipeableTransformStream {
|
|
|
147
149
|
controller.terminate();
|
|
148
150
|
return;
|
|
149
151
|
}
|
|
150
|
-
|
|
152
|
+
let chunk;
|
|
153
|
+
try {
|
|
154
|
+
chunk = sjson.parse(event.data);
|
|
155
|
+
} catch {
|
|
156
|
+
chunk = void 0;
|
|
157
|
+
}
|
|
158
|
+
if (typeof chunk !== "object" || chunk === null || Array.isArray(chunk) || typeof chunk.type !== "string") {
|
|
159
|
+
console.warn(`Dropped invalid UIMessageStream chunk: ${event.data.slice(0, 200)}`);
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
151
162
|
if (chunk.type === "text-delta" && chunk.textDelta === void 0) {
|
|
152
163
|
const { delta, ...rest } = chunk;
|
|
153
164
|
controller.enqueue({
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UIMessageStream.js","names":[],"sources":["../../../../src/core/serialization/ui-message-stream/UIMessageStream.ts"],"sourcesContent":["import type { AssistantStreamChunk } from \"../../AssistantStreamChunk\";\nimport type { ToolCallStreamController } from \"../../modules/tool-call\";\nimport type { TextStreamController } from \"../../modules/text\";\nimport { AssistantTransformStream } from \"../../utils/stream/AssistantTransformStream\";\nimport { PipeableTransformStream } from \"../../utils/stream/PipeableTransformStream\";\nimport {\n SSEEventDecoderStream,\n type PipelineSSEEvent,\n} from \"../../utils/stream/SSEEventDecoderStream\";\nimport type {\n UIMessageStreamChunk,\n UIMessageStreamDataChunk,\n} from \"./chunk-types\";\nimport { generateId } from \"../../utils/generateId\";\n\nexport type { UIMessageStreamChunk, UIMessageStreamDataChunk };\n\nexport type UIMessageStreamDecoderOptions = {\n onData?: (data: {\n type: string;\n name: string;\n data: unknown;\n transient?: boolean;\n }) => void;\n};\n\nconst isDataChunk = (\n chunk: UIMessageStreamChunk,\n): chunk is UIMessageStreamDataChunk => chunk.type.startsWith(\"data-\");\n\n/**\n * Decodes AI SDK v6 UI Message Stream format into AssistantStreamChunks.\n */\nexport class UIMessageStreamDecoder extends PipeableTransformStream<\n Uint8Array<ArrayBuffer>,\n AssistantStreamChunk\n> {\n constructor(options: UIMessageStreamDecoderOptions = {}) {\n super((readable) => {\n const toolCallControllers = new Map<string, ToolCallStreamController>();\n let activeToolCallArgsText: TextStreamController | undefined;\n let currentMessageId: string | undefined;\n let receivedDone = false;\n\n const transform = new AssistantTransformStream<UIMessageStreamChunk>({\n transform(chunk, controller) {\n const type = chunk.type;\n\n if (isDataChunk(chunk)) {\n const name = chunk.type.slice(5);\n\n if (options.onData) {\n options.onData({\n type: chunk.type,\n name,\n data: chunk.data,\n ...(chunk.transient !== undefined && {\n transient: chunk.transient,\n }),\n });\n }\n\n if (!chunk.transient) {\n controller.enqueue({\n type: \"data\",\n path: [],\n data: [{ name, data: chunk.data }],\n });\n }\n return;\n }\n\n switch (type) {\n case \"start\":\n currentMessageId = chunk.messageId;\n controller.enqueue({\n type: \"step-start\",\n path: [],\n messageId: chunk.messageId,\n });\n break;\n\n case \"text-start\":\n case \"text-end\":\n case \"reasoning-start\":\n case \"reasoning-end\":\n break;\n\n case \"text-delta\":\n controller.appendText(chunk.textDelta);\n break;\n\n case \"reasoning-delta\":\n controller.appendReasoning(chunk.delta);\n break;\n\n case \"source\":\n controller.appendSource({\n type: \"source\",\n sourceType: chunk.source.sourceType,\n id: chunk.source.id,\n url: chunk.source.url,\n ...(chunk.source.title && { title: chunk.source.title }),\n });\n break;\n\n case \"file\":\n controller.appendFile({\n type: \"file\",\n mimeType: chunk.file.mimeType,\n data: chunk.file.data,\n });\n break;\n\n case \"tool-call-start\": {\n activeToolCallArgsText?.close();\n activeToolCallArgsText = undefined;\n\n if (toolCallControllers.has(chunk.toolCallId)) {\n throw new Error(\n `Encountered duplicate tool call id: ${chunk.toolCallId}`,\n );\n }\n\n const toolCallController = controller.addToolCallPart({\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n });\n toolCallControllers.set(chunk.toolCallId, toolCallController);\n activeToolCallArgsText = toolCallController.argsText;\n break;\n }\n\n case \"tool-call-delta\":\n activeToolCallArgsText?.append(chunk.argsText);\n break;\n\n case \"tool-call-end\":\n activeToolCallArgsText?.close();\n activeToolCallArgsText = undefined;\n break;\n\n case \"tool-result\": {\n const toolCallController = toolCallControllers.get(\n chunk.toolCallId,\n );\n if (!toolCallController) {\n throw new Error(\n `Encountered tool result with unknown id: ${chunk.toolCallId}`,\n );\n }\n toolCallController.setResponse({\n result: chunk.result,\n isError: chunk.isError ?? false,\n ...(chunk.messages !== undefined\n ? { messages: chunk.messages }\n : {}),\n });\n break;\n }\n\n case \"start-step\":\n controller.enqueue({\n type: \"step-start\",\n path: [],\n messageId: chunk.messageId ?? currentMessageId ?? generateId(),\n });\n break;\n\n case \"finish-step\":\n controller.enqueue({\n type: \"step-finish\",\n path: [],\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n isContinued: chunk.isContinued,\n });\n break;\n\n case \"finish\":\n controller.enqueue({\n type: \"message-finish\",\n path: [],\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n });\n break;\n\n case \"error\":\n controller.enqueue({\n type: \"error\",\n path: [],\n error: chunk.errorText,\n });\n break;\n\n default:\n // ignore unknown types for forward compatibility\n break;\n }\n },\n flush() {\n activeToolCallArgsText?.close();\n toolCallControllers.forEach((ctrl) => ctrl.close());\n toolCallControllers.clear();\n },\n });\n\n return readable\n .pipeThrough(new TextDecoderStream())\n .pipeThrough(new SSEEventDecoderStream())\n .pipeThrough(\n new TransformStream<PipelineSSEEvent, UIMessageStreamChunk>({\n transform(event, controller) {\n if (event.event !== \"message\") {\n throw new Error(`Unknown SSE event type: ${event.event}`);\n }\n\n if (event.data === \"[DONE]\") {\n receivedDone = true;\n controller.terminate();\n return;\n }\n\n const chunk = JSON.parse(event.data);\n if (\n chunk.type === \"text-delta\" &&\n chunk.textDelta === undefined\n ) {\n const { delta, ...rest } = chunk;\n controller.enqueue({ ...rest, textDelta: delta ?? \"\" });\n return;\n }\n if (chunk.type === \"start\") {\n controller.enqueue({\n ...chunk,\n messageId: chunk.messageId ?? generateId(),\n });\n return;\n }\n if (chunk.type === \"source-url\") {\n controller.enqueue({\n type: \"source\",\n source: {\n sourceType: \"url\",\n id: chunk.sourceId,\n url: chunk.url,\n ...(chunk.title && { title: chunk.title }),\n },\n });\n return;\n }\n if (chunk.type === \"source\" && chunk.source == null) return;\n if (chunk.type === \"file\" && chunk.file == null) {\n if (chunk.url === undefined) return;\n controller.enqueue({\n type: \"file\",\n file: { mimeType: chunk.mediaType, data: chunk.url },\n });\n return;\n }\n if (chunk.type === \"finish-step\") {\n controller.enqueue({\n ...chunk,\n finishReason: chunk.finishReason ?? \"unknown\",\n usage: chunk.usage ?? { inputTokens: 0, outputTokens: 0 },\n isContinued: chunk.isContinued ?? false,\n });\n return;\n }\n if (chunk.type === \"finish\") {\n controller.enqueue({\n ...chunk,\n finishReason: chunk.finishReason ?? \"unknown\",\n usage: chunk.usage ?? { inputTokens: 0, outputTokens: 0 },\n });\n return;\n }\n\n controller.enqueue(chunk);\n },\n flush() {\n if (!receivedDone) {\n throw new Error(\n \"Stream ended abruptly without receiving [DONE] marker\",\n );\n }\n },\n }),\n )\n .pipeThrough(transform);\n });\n }\n}\n"],"mappings":";;;;;AA0BA,MAAM,eACJ,UACsC,MAAM,KAAK,WAAW,OAAO;;;;AAKrE,IAAa,yBAAb,cAA4C,wBAG1C;CACA,YAAY,UAAyC,CAAC,GAAG;EACvD,OAAO,aAAa;GAClB,MAAM,sCAAsB,IAAI,IAAsC;GACtE,IAAI;GACJ,IAAI;GACJ,IAAI,eAAe;GAEnB,MAAM,YAAY,IAAI,yBAA+C;IACnE,UAAU,OAAO,YAAY;KAC3B,MAAM,OAAO,MAAM;KAEnB,IAAI,YAAY,KAAK,GAAG;MACtB,MAAM,OAAO,MAAM,KAAK,MAAM,CAAC;MAE/B,IAAI,QAAQ,QACV,QAAQ,OAAO;OACb,MAAM,MAAM;OACZ;OACA,MAAM,MAAM;OACZ,GAAI,MAAM,cAAc,KAAA,KAAa,EACnC,WAAW,MAAM,UACnB;MACF,CAAC;MAGH,IAAI,CAAC,MAAM,WACT,WAAW,QAAQ;OACjB,MAAM;OACN,MAAM,CAAC;OACP,MAAM,CAAC;QAAE;QAAM,MAAM,MAAM;OAAK,CAAC;MACnC,CAAC;MAEH;KACF;KAEA,QAAQ,MAAR;MACE,KAAK;OACH,mBAAmB,MAAM;OACzB,WAAW,QAAQ;QACjB,MAAM;QACN,MAAM,CAAC;QACP,WAAW,MAAM;OACnB,CAAC;OACD;MAEF,KAAK;MACL,KAAK;MACL,KAAK;MACL,KAAK,iBACH;MAEF,KAAK;OACH,WAAW,WAAW,MAAM,SAAS;OACrC;MAEF,KAAK;OACH,WAAW,gBAAgB,MAAM,KAAK;OACtC;MAEF,KAAK;OACH,WAAW,aAAa;QACtB,MAAM;QACN,YAAY,MAAM,OAAO;QACzB,IAAI,MAAM,OAAO;QACjB,KAAK,MAAM,OAAO;QAClB,GAAI,MAAM,OAAO,SAAS,EAAE,OAAO,MAAM,OAAO,MAAM;OACxD,CAAC;OACD;MAEF,KAAK;OACH,WAAW,WAAW;QACpB,MAAM;QACN,UAAU,MAAM,KAAK;QACrB,MAAM,MAAM,KAAK;OACnB,CAAC;OACD;MAEF,KAAK,mBAAmB;OACtB,wBAAwB,MAAM;OAC9B,yBAAyB,KAAA;OAEzB,IAAI,oBAAoB,IAAI,MAAM,UAAU,GAC1C,MAAM,IAAI,MACR,uCAAuC,MAAM,YAC/C;OAGF,MAAM,qBAAqB,WAAW,gBAAgB;QACpD,YAAY,MAAM;QAClB,UAAU,MAAM;OAClB,CAAC;OACD,oBAAoB,IAAI,MAAM,YAAY,kBAAkB;OAC5D,yBAAyB,mBAAmB;OAC5C;MACF;MAEA,KAAK;OACH,wBAAwB,OAAO,MAAM,QAAQ;OAC7C;MAEF,KAAK;OACH,wBAAwB,MAAM;OAC9B,yBAAyB,KAAA;OACzB;MAEF,KAAK,eAAe;OAClB,MAAM,qBAAqB,oBAAoB,IAC7C,MAAM,UACR;OACA,IAAI,CAAC,oBACH,MAAM,IAAI,MACR,4CAA4C,MAAM,YACpD;OAEF,mBAAmB,YAAY;QAC7B,QAAQ,MAAM;QACd,SAAS,MAAM,WAAW;QAC1B,GAAI,MAAM,aAAa,KAAA,IACnB,EAAE,UAAU,MAAM,SAAS,IAC3B,CAAC;OACP,CAAC;OACD;MACF;MAEA,KAAK;OACH,WAAW,QAAQ;QACjB,MAAM;QACN,MAAM,CAAC;QACP,WAAW,MAAM,aAAa,oBAAoB,WAAW;OAC/D,CAAC;OACD;MAEF,KAAK;OACH,WAAW,QAAQ;QACjB,MAAM;QACN,MAAM,CAAC;QACP,cAAc,MAAM;QACpB,OAAO,MAAM;QACb,aAAa,MAAM;OACrB,CAAC;OACD;MAEF,KAAK;OACH,WAAW,QAAQ;QACjB,MAAM;QACN,MAAM,CAAC;QACP,cAAc,MAAM;QACpB,OAAO,MAAM;OACf,CAAC;OACD;MAEF,KAAK;OACH,WAAW,QAAQ;QACjB,MAAM;QACN,MAAM,CAAC;QACP,OAAO,MAAM;OACf,CAAC;OACD;MAEF,SAEE;KACJ;IACF;IACA,QAAQ;KACN,wBAAwB,MAAM;KAC9B,oBAAoB,SAAS,SAAS,KAAK,MAAM,CAAC;KAClD,oBAAoB,MAAM;IAC5B;GACF,CAAC;GAED,OAAO,SACJ,YAAY,IAAI,kBAAkB,CAAC,CAAC,CACpC,YAAY,IAAI,sBAAsB,CAAC,CAAC,CACxC,YACC,IAAI,gBAAwD;IAC1D,UAAU,OAAO,YAAY;KAC3B,IAAI,MAAM,UAAU,WAClB,MAAM,IAAI,MAAM,2BAA2B,MAAM,OAAO;KAG1D,IAAI,MAAM,SAAS,UAAU;MAC3B,eAAe;MACf,WAAW,UAAU;MACrB;KACF;KAEA,MAAM,QAAQ,KAAK,MAAM,MAAM,IAAI;KACnC,IACE,MAAM,SAAS,gBACf,MAAM,cAAc,KAAA,GACpB;MACA,MAAM,EAAE,OAAO,GAAG,SAAS;MAC3B,WAAW,QAAQ;OAAE,GAAG;OAAM,WAAW,SAAS;MAAG,CAAC;MACtD;KACF;KACA,IAAI,MAAM,SAAS,SAAS;MAC1B,WAAW,QAAQ;OACjB,GAAG;OACH,WAAW,MAAM,aAAa,WAAW;MAC3C,CAAC;MACD;KACF;KACA,IAAI,MAAM,SAAS,cAAc;MAC/B,WAAW,QAAQ;OACjB,MAAM;OACN,QAAQ;QACN,YAAY;QACZ,IAAI,MAAM;QACV,KAAK,MAAM;QACX,GAAI,MAAM,SAAS,EAAE,OAAO,MAAM,MAAM;OAC1C;MACF,CAAC;MACD;KACF;KACA,IAAI,MAAM,SAAS,YAAY,MAAM,UAAU,MAAM;KACrD,IAAI,MAAM,SAAS,UAAU,MAAM,QAAQ,MAAM;MAC/C,IAAI,MAAM,QAAQ,KAAA,GAAW;MAC7B,WAAW,QAAQ;OACjB,MAAM;OACN,MAAM;QAAE,UAAU,MAAM;QAAW,MAAM,MAAM;OAAI;MACrD,CAAC;MACD;KACF;KACA,IAAI,MAAM,SAAS,eAAe;MAChC,WAAW,QAAQ;OACjB,GAAG;OACH,cAAc,MAAM,gBAAgB;OACpC,OAAO,MAAM,SAAS;QAAE,aAAa;QAAG,cAAc;OAAE;OACxD,aAAa,MAAM,eAAe;MACpC,CAAC;MACD;KACF;KACA,IAAI,MAAM,SAAS,UAAU;MAC3B,WAAW,QAAQ;OACjB,GAAG;OACH,cAAc,MAAM,gBAAgB;OACpC,OAAO,MAAM,SAAS;QAAE,aAAa;QAAG,cAAc;OAAE;MAC1D,CAAC;MACD;KACF;KAEA,WAAW,QAAQ,KAAK;IAC1B;IACA,QAAQ;KACN,IAAI,CAAC,cACH,MAAM,IAAI,MACR,uDACF;IAEJ;GACF,CAAC,CACH,CAAC,CACA,YAAY,SAAS;EAC1B,CAAC;CACH;AACF"}
|
|
1
|
+
{"version":3,"file":"UIMessageStream.js","names":[],"sources":["../../../../src/core/serialization/ui-message-stream/UIMessageStream.ts"],"sourcesContent":["import sjson from \"secure-json-parse\";\nimport type { AssistantStreamChunk } from \"../../AssistantStreamChunk\";\nimport type { ToolCallStreamController } from \"../../modules/tool-call\";\nimport type { TextStreamController } from \"../../modules/text\";\nimport { AssistantTransformStream } from \"../../utils/stream/AssistantTransformStream\";\nimport { PipeableTransformStream } from \"../../utils/stream/PipeableTransformStream\";\nimport {\n SSEEventDecoderStream,\n type PipelineSSEEvent,\n} from \"../../utils/stream/SSEEventDecoderStream\";\nimport type {\n UIMessageStreamChunk,\n UIMessageStreamDataChunk,\n} from \"./chunk-types\";\nimport { generateId } from \"../../utils/generateId\";\n\nexport type { UIMessageStreamChunk, UIMessageStreamDataChunk };\n\nexport type UIMessageStreamDecoderOptions = {\n onData?: (data: {\n type: string;\n name: string;\n data: unknown;\n transient?: boolean;\n }) => void;\n};\n\nconst isDataChunk = (\n chunk: UIMessageStreamChunk,\n): chunk is UIMessageStreamDataChunk => chunk.type.startsWith(\"data-\");\n\n/**\n * Decodes AI SDK v6 UI Message Stream format into AssistantStreamChunks.\n */\nexport class UIMessageStreamDecoder extends PipeableTransformStream<\n Uint8Array<ArrayBuffer>,\n AssistantStreamChunk\n> {\n constructor(options: UIMessageStreamDecoderOptions = {}) {\n super((readable) => {\n const toolCallControllers = new Map<string, ToolCallStreamController>();\n let activeToolCallArgsText: TextStreamController | undefined;\n let currentMessageId: string | undefined;\n let receivedDone = false;\n\n const transform = new AssistantTransformStream<UIMessageStreamChunk>({\n transform(chunk, controller) {\n const type = chunk.type;\n\n if (isDataChunk(chunk)) {\n const name = chunk.type.slice(5);\n\n if (options.onData) {\n options.onData({\n type: chunk.type,\n name,\n data: chunk.data,\n ...(chunk.transient !== undefined && {\n transient: chunk.transient,\n }),\n });\n }\n\n if (!chunk.transient) {\n controller.enqueue({\n type: \"data\",\n path: [],\n data: [{ name, data: chunk.data }],\n });\n }\n return;\n }\n\n switch (type) {\n case \"start\":\n currentMessageId = chunk.messageId;\n controller.enqueue({\n type: \"step-start\",\n path: [],\n messageId: chunk.messageId,\n });\n break;\n\n case \"text-start\":\n case \"text-end\":\n case \"reasoning-start\":\n case \"reasoning-end\":\n break;\n\n case \"text-delta\":\n controller.appendText(chunk.textDelta);\n break;\n\n case \"reasoning-delta\":\n controller.appendReasoning(chunk.delta);\n break;\n\n case \"source\":\n controller.appendSource({\n type: \"source\",\n sourceType: chunk.source.sourceType,\n id: chunk.source.id,\n url: chunk.source.url,\n ...(chunk.source.title && { title: chunk.source.title }),\n });\n break;\n\n case \"file\":\n controller.appendFile({\n type: \"file\",\n mimeType: chunk.file.mimeType,\n data: chunk.file.data,\n });\n break;\n\n case \"tool-call-start\": {\n activeToolCallArgsText?.close();\n activeToolCallArgsText = undefined;\n\n if (toolCallControllers.has(chunk.toolCallId)) {\n throw new Error(\n `Encountered duplicate tool call id: ${chunk.toolCallId}`,\n );\n }\n\n const toolCallController = controller.addToolCallPart({\n toolCallId: chunk.toolCallId,\n toolName: chunk.toolName,\n });\n toolCallControllers.set(chunk.toolCallId, toolCallController);\n activeToolCallArgsText = toolCallController.argsText;\n break;\n }\n\n case \"tool-call-delta\":\n activeToolCallArgsText?.append(chunk.argsText);\n break;\n\n case \"tool-call-end\":\n activeToolCallArgsText?.close();\n activeToolCallArgsText = undefined;\n break;\n\n case \"tool-result\": {\n const toolCallController = toolCallControllers.get(\n chunk.toolCallId,\n );\n if (!toolCallController) {\n throw new Error(\n `Encountered tool result with unknown id: ${chunk.toolCallId}`,\n );\n }\n if (toolCallController.argsText === activeToolCallArgsText) {\n activeToolCallArgsText = undefined;\n }\n toolCallController.setResponse({\n result: chunk.result,\n isError: chunk.isError ?? false,\n ...(chunk.messages !== undefined\n ? { messages: chunk.messages }\n : {}),\n });\n break;\n }\n\n case \"start-step\":\n controller.enqueue({\n type: \"step-start\",\n path: [],\n messageId: chunk.messageId ?? currentMessageId ?? generateId(),\n });\n break;\n\n case \"finish-step\":\n controller.enqueue({\n type: \"step-finish\",\n path: [],\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n isContinued: chunk.isContinued,\n });\n break;\n\n case \"finish\":\n controller.enqueue({\n type: \"message-finish\",\n path: [],\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n });\n break;\n\n case \"error\":\n controller.enqueue({\n type: \"error\",\n path: [],\n error: chunk.errorText,\n });\n break;\n\n default:\n // ignore unknown types for forward compatibility\n break;\n }\n },\n flush() {\n activeToolCallArgsText?.close();\n toolCallControllers.forEach((ctrl) => ctrl.close());\n toolCallControllers.clear();\n },\n });\n\n return readable\n .pipeThrough(new TextDecoderStream())\n .pipeThrough(new SSEEventDecoderStream())\n .pipeThrough(\n new TransformStream<PipelineSSEEvent, UIMessageStreamChunk>({\n transform(event, controller) {\n if (event.event !== \"message\") {\n throw new Error(`Unknown SSE event type: ${event.event}`);\n }\n\n if (event.data === \"[DONE]\") {\n receivedDone = true;\n controller.terminate();\n return;\n }\n\n let chunk;\n try {\n chunk = sjson.parse(event.data);\n } catch {\n chunk = undefined;\n }\n if (\n typeof chunk !== \"object\" ||\n chunk === null ||\n Array.isArray(chunk) ||\n typeof chunk.type !== \"string\"\n ) {\n console.warn(\n `Dropped invalid UIMessageStream chunk: ${event.data.slice(0, 200)}`,\n );\n return;\n }\n if (\n chunk.type === \"text-delta\" &&\n chunk.textDelta === undefined\n ) {\n const { delta, ...rest } = chunk;\n controller.enqueue({ ...rest, textDelta: delta ?? \"\" });\n return;\n }\n if (chunk.type === \"start\") {\n controller.enqueue({\n ...chunk,\n messageId: chunk.messageId ?? generateId(),\n });\n return;\n }\n if (chunk.type === \"source-url\") {\n controller.enqueue({\n type: \"source\",\n source: {\n sourceType: \"url\",\n id: chunk.sourceId,\n url: chunk.url,\n ...(chunk.title && { title: chunk.title }),\n },\n });\n return;\n }\n if (chunk.type === \"source\" && chunk.source == null) return;\n if (chunk.type === \"file\" && chunk.file == null) {\n if (chunk.url === undefined) return;\n controller.enqueue({\n type: \"file\",\n file: { mimeType: chunk.mediaType, data: chunk.url },\n });\n return;\n }\n if (chunk.type === \"finish-step\") {\n controller.enqueue({\n ...chunk,\n finishReason: chunk.finishReason ?? \"unknown\",\n usage: chunk.usage ?? { inputTokens: 0, outputTokens: 0 },\n isContinued: chunk.isContinued ?? false,\n });\n return;\n }\n if (chunk.type === \"finish\") {\n controller.enqueue({\n ...chunk,\n finishReason: chunk.finishReason ?? \"unknown\",\n usage: chunk.usage ?? { inputTokens: 0, outputTokens: 0 },\n });\n return;\n }\n\n controller.enqueue(chunk);\n },\n flush() {\n if (!receivedDone) {\n throw new Error(\n \"Stream ended abruptly without receiving [DONE] marker\",\n );\n }\n },\n }),\n )\n .pipeThrough(transform);\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolCallReader.d.ts","names":[],"sources":["../../../src/core/tool/ToolCallReader.ts"],"mappings":";;;;;;;cA0Qa,uBACX,UAAU,+BACC,mBAAmB;UACtB;UACA;UACA;UACA;
|
|
1
|
+
{"version":3,"file":"ToolCallReader.d.ts","names":[],"sources":["../../../src/core/tool/ToolCallReader.ts"],"mappings":";;;;;;;cA0Qa,uBACX,UAAU,+BACC,mBAAmB;UACtB;UACA;UACA;UACA;EAEI,YAAA,eAAe;UAKb;EA+Bd,IAAI,cAAc,SAAS,OACtB,WAAW,QACb,QAAQ,WAAW,GAAG;EAiCzB,aAAa,cAAc,SAAS,OAC/B,WAAW,QACb,oBAAoB,YAAY,WAAW,GAAG;EA4BjD,WAAW,cAAc,SAAS,OAC7B,WAAW,QACb,WAAW,GAAG,+BAA+B,KAC5C,oBAAoB;EA6BxB,QAAQ,cAAc,SAAS,OAC1B,WAAW,QACb,YAAY,WAAW,GAAG,gBAAgB,YAAY,KACrD,oBAAoB;;cA8Bb,2BACX,gBAAgB,8BACL,uBAAuB;mBACjB;EAEL,YAAA,SAAS,QAAQ,aAAa;EAInC,OAAG,QAAA,aAAA;;cAKC,mBACX,cAAc,oBACd,gBAAgB,8BACL,eAAe,OAAO;WACjB,MAAM,uBAAuB;WAC7B,UAAU,2BAA2B;mBACpC;mBACA;EAEV;;EAYD,oBAAoB,eAAe;EAanC,kBAAkB;EAWxB,YAAY,OAAO,aAAa;EAIhC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolCallReader.js","names":[],"sources":["../../../src/core/tool/ToolCallReader.ts"],"sourcesContent":["import { promiseWithResolvers } from \"../../utils/promiseWithResolvers\";\nimport {\n parsePartialJsonObject,\n getPartialJsonObjectFieldState,\n} from \"../../utils/json/parse-partial-json-object\";\nimport type {\n ToolCallArgsReader,\n ToolCallReader,\n ToolCallResponseReader,\n} from \"./tool-types\";\nimport type { DeepPartial, TypeAtPath, TypePath } from \"./type-path-utils\";\nimport type { ToolResponse } from \"./ToolResponse\";\nimport { asAsyncIterableStream } from \"../../utils/AsyncIterableStream\";\nimport type {\n AsyncIterableStream,\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"../../utils\";\n\n// TODO: remove dispose\n\nfunction getField<T>(obj: T, fieldPath: (string | number)[]): unknown {\n let current: unknown = obj;\n for (const key of fieldPath) {\n if (current === undefined || current === null) {\n return undefined;\n }\n current = current[key as keyof typeof current];\n }\n return current;\n}\n\ninterface Handle {\n update(args: unknown): void;\n end(args: unknown): void;\n dispose(): void;\n}\n\nclass GetHandle<T, TValue> implements Handle {\n private resolve: (value: TValue) => void;\n private reject: (reason: unknown) => void;\n private disposed = false;\n private fieldPath: (string | number)[];\n\n constructor(\n resolve: (value: TValue) => void,\n reject: (reason: unknown) => void,\n fieldPath: (string | number)[],\n ) {\n this.resolve = resolve;\n this.reject = reject;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n // Check if the field is complete\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n const value = getField(args as T, this.fieldPath);\n if (value !== undefined) {\n this.resolve(value as TValue);\n this.dispose();\n }\n }\n } catch (e) {\n this.reject(e);\n this.dispose();\n }\n }\n\n end(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const value = getField(args as T, this.fieldPath);\n this.resolve(value as TValue);\n } catch (e) {\n this.reject(e);\n } finally {\n this.dispose();\n }\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\nclass StreamValuesHandle<T> implements Handle {\n private controller: ReadableStreamDefaultController<unknown>;\n private disposed = false;\n private fieldPath: (string | number)[];\n\n constructor(\n controller: ReadableStreamDefaultController<unknown>,\n fieldPath: (string | number)[],\n ) {\n this.controller = controller;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const value = getField(args as T, this.fieldPath);\n\n if (value !== undefined) {\n this.controller.enqueue(value);\n }\n\n // Check if the field is complete, if so close the stream\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n this.controller.close();\n this.dispose();\n }\n } catch (e) {\n this.controller.error(e);\n this.dispose();\n }\n }\n\n end(): void {\n if (this.disposed) return;\n this.controller.close();\n this.dispose();\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\nclass StreamTextHandle<T> implements Handle {\n private controller: ReadableStreamDefaultController<unknown>;\n private disposed = false;\n private fieldPath: (string | number)[];\n private lastValue: string | undefined = undefined;\n\n constructor(\n controller: ReadableStreamDefaultController<unknown>,\n fieldPath: (string | number)[],\n ) {\n this.controller = controller;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const value = getField(args as T, this.fieldPath);\n\n if (value !== undefined && typeof value === \"string\") {\n const delta = value.substring(this.lastValue?.length || 0);\n this.lastValue = value;\n this.controller.enqueue(delta);\n }\n\n // Check if the field is complete, if so close the stream\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n this.controller.close();\n this.dispose();\n }\n } catch (e) {\n this.controller.error(e);\n this.dispose();\n }\n }\n\n end(): void {\n if (this.disposed) return;\n this.controller.close();\n this.dispose();\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\nclass ForEachHandle<T> implements Handle {\n private controller: ReadableStreamDefaultController<unknown>;\n private disposed = false;\n private fieldPath: (string | number)[];\n private processedIndexes = new Set<number>();\n\n constructor(\n controller: ReadableStreamDefaultController<unknown>,\n fieldPath: (string | number)[],\n ) {\n this.controller = controller;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const array = getField(args as T, this.fieldPath);\n\n if (!Array.isArray(array)) {\n return;\n }\n\n // Check each array element and emit completed ones that haven't been processed\n for (let i = 0; i < array.length; i++) {\n if (!this.processedIndexes.has(i)) {\n const elementPath = [...this.fieldPath, i];\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n elementPath,\n ) === \"complete\"\n ) {\n this.controller.enqueue(array[i]);\n this.processedIndexes.add(i);\n }\n }\n }\n\n // Check if the entire array is complete\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n this.controller.close();\n this.dispose();\n }\n } catch (e) {\n this.controller.error(e);\n this.dispose();\n }\n }\n\n end(): void {\n if (this.disposed) return;\n this.controller.close();\n this.dispose();\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\n// Implementation of ToolCallReader that uses stream of partial JSON\nexport class ToolCallArgsReaderImpl<\n T extends ReadonlyJSONObject,\n> implements ToolCallArgsReader<T> {\n private argTextDeltas: ReadableStream<string>;\n private handles: Set<Handle> = new Set();\n private args: unknown = parsePartialJsonObject(\"\");\n private finished = false;\n\n constructor(argTextDeltas: ReadableStream<string>) {\n this.argTextDeltas = argTextDeltas;\n this.processStream();\n }\n\n private async processStream(): Promise<void> {\n try {\n let accumulatedText = \"\";\n const reader = this.argTextDeltas.getReader();\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n accumulatedText += value;\n const parsedArgs = parsePartialJsonObject(accumulatedText);\n\n if (parsedArgs !== undefined) {\n this.args = parsedArgs;\n // Notify all handles of the updated args\n for (const handle of this.handles) {\n handle.update(parsedArgs);\n }\n }\n }\n } catch (error) {\n console.error(\"Error processing argument stream:\", error);\n } finally {\n this.finished = true;\n for (const handle of this.handles) {\n handle.end(this.args);\n }\n this.handles.clear();\n }\n }\n\n get<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): Promise<TypeAtPath<T, PathT>> {\n return new Promise<TypeAtPath<T, PathT>>((resolve, reject) => {\n const handle = new GetHandle<T, TypeAtPath<T, PathT>>(\n resolve,\n reject,\n fieldPath,\n );\n\n // Check if the field is already complete in current args\n if (\n this.args &&\n getPartialJsonObjectFieldState(\n this.args as Record<string, unknown>,\n fieldPath,\n ) === \"complete\"\n ) {\n const value = getField(this.args as T, fieldPath);\n if (value !== undefined) {\n resolve(value as TypeAtPath<T, PathT>);\n return;\n }\n }\n\n if (this.finished) {\n handle.end(this.args);\n return;\n }\n\n this.handles.add(handle);\n handle.update(this.args);\n });\n }\n\n streamValues<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): AsyncIterableStream<DeepPartial<TypeAtPath<T, PathT>>> {\n // Use a type assertion to convert the complex TypePath to a simple array\n const simplePath = fieldPath as unknown as (string | number)[];\n\n let handle: StreamValuesHandle<T> | undefined;\n const stream = new ReadableStream<DeepPartial<TypeAtPath<T, PathT>>>({\n start: (controller) => {\n handle = new StreamValuesHandle<T>(controller, simplePath);\n if (!this.finished) this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n\n if (this.finished) handle.end();\n },\n cancel: () => {\n // Dispose this stream's own handle (captured above) — scanning for the\n // first match would dispose a concurrent streamValues()'s handle.\n if (handle) {\n handle.dispose();\n this.handles.delete(handle);\n }\n },\n });\n\n return asAsyncIterableStream(stream) as any;\n }\n\n streamText<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): TypeAtPath<T, PathT> extends string & (infer U)\n ? AsyncIterableStream<U>\n : never {\n // Use a type assertion to convert the complex TypePath to a simple array\n const simplePath = fieldPath as unknown as (string | number)[];\n\n let handle: StreamTextHandle<T> | undefined;\n const stream = new ReadableStream<unknown>({\n start: (controller) => {\n handle = new StreamTextHandle<T>(controller, simplePath);\n if (!this.finished) this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n\n if (this.finished) handle.end();\n },\n cancel: () => {\n // Dispose this stream's own handle (captured above) — scanning for the\n // first match would dispose a concurrent streamText()'s handle.\n if (handle) {\n handle.dispose();\n this.handles.delete(handle);\n }\n },\n });\n\n return asAsyncIterableStream(stream) as any;\n }\n\n forEach<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): NonNullable<TypeAtPath<T, PathT>> extends Array<infer U>\n ? AsyncIterableStream<U>\n : never {\n // Use a type assertion to convert the complex TypePath to a simple array\n const simplePath = fieldPath as unknown as (string | number)[];\n\n let handle: ForEachHandle<T> | undefined;\n const stream = new ReadableStream<unknown>({\n start: (controller) => {\n handle = new ForEachHandle<T>(controller, simplePath);\n if (!this.finished) this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n\n if (this.finished) handle.end();\n },\n cancel: () => {\n // Dispose this stream's own handle (captured above) — scanning for the\n // first match would dispose a concurrent forEach()'s handle.\n if (handle) {\n handle.dispose();\n this.handles.delete(handle);\n }\n },\n });\n\n return asAsyncIterableStream(stream) as any;\n }\n}\n\nexport class ToolCallResponseReaderImpl<\n TResult extends ReadonlyJSONValue,\n> implements ToolCallResponseReader<TResult> {\n constructor(private readonly promise: Promise<ToolResponse<TResult>>) {}\n\n public get() {\n return this.promise;\n }\n}\n\nexport class ToolCallReaderImpl<\n TArgs extends ReadonlyJSONObject,\n TResult extends ReadonlyJSONValue,\n> implements ToolCallReader<TArgs, TResult> {\n public readonly args: ToolCallArgsReaderImpl<TArgs>;\n public readonly response: ToolCallResponseReaderImpl<TResult>;\n private readonly writable: WritableStream<string>;\n private readonly resolve: (value: ToolResponse<TResult>) => void;\n\n public argsText: string = \"\";\n\n constructor() {\n const stream = new TransformStream<string, string>();\n this.writable = stream.writable;\n this.args = new ToolCallArgsReaderImpl<TArgs>(stream.readable);\n\n const { promise, resolve } = promiseWithResolvers<ToolResponse<TResult>>();\n this.resolve = resolve;\n this.response = new ToolCallResponseReaderImpl<TResult>(promise);\n }\n\n async appendArgsTextDelta(text: string): Promise<void> {\n const writer = this.writable.getWriter();\n try {\n await writer.write(text);\n } catch (err) {\n console.warn(err);\n } finally {\n writer.releaseLock();\n }\n\n this.argsText += text;\n }\n\n async finishArgsText(): Promise<void> {\n const writer = this.writable.getWriter();\n try {\n await writer.close();\n } catch (err) {\n console.warn(err);\n } finally {\n writer.releaseLock();\n }\n }\n\n setResponse(value: ToolResponse<TResult>): void {\n this.resolve(value);\n }\n\n result = {\n get: async () => {\n const response = await this.response.get();\n return response.result;\n },\n };\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ToolCallReader.js","names":[],"sources":["../../../src/core/tool/ToolCallReader.ts"],"sourcesContent":["import { promiseWithResolvers } from \"../../utils/promiseWithResolvers\";\nimport {\n parsePartialJsonObject,\n getPartialJsonObjectFieldState,\n} from \"../../utils/json/parse-partial-json-object\";\nimport type {\n ToolCallArgsReader,\n ToolCallReader,\n ToolCallResponseReader,\n} from \"./tool-types\";\nimport type { DeepPartial, TypeAtPath, TypePath } from \"./type-path-utils\";\nimport type { ToolResponse } from \"./ToolResponse\";\nimport { asAsyncIterableStream } from \"../../utils/AsyncIterableStream\";\nimport type {\n AsyncIterableStream,\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"../../utils\";\n\n// TODO: remove dispose\n\nfunction getField<T>(obj: T, fieldPath: (string | number)[]): unknown {\n let current: unknown = obj;\n for (const key of fieldPath) {\n if (current === undefined || current === null) {\n return undefined;\n }\n current = current[key as keyof typeof current];\n }\n return current;\n}\n\ninterface Handle {\n update(args: unknown): void;\n end(args: unknown): void;\n dispose(): void;\n}\n\nclass GetHandle<T, TValue> implements Handle {\n private resolve: (value: TValue) => void;\n private reject: (reason: unknown) => void;\n private disposed = false;\n private fieldPath: (string | number)[];\n\n constructor(\n resolve: (value: TValue) => void,\n reject: (reason: unknown) => void,\n fieldPath: (string | number)[],\n ) {\n this.resolve = resolve;\n this.reject = reject;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n // Check if the field is complete\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n const value = getField(args as T, this.fieldPath);\n if (value !== undefined) {\n this.resolve(value as TValue);\n this.dispose();\n }\n }\n } catch (e) {\n this.reject(e);\n this.dispose();\n }\n }\n\n end(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const value = getField(args as T, this.fieldPath);\n this.resolve(value as TValue);\n } catch (e) {\n this.reject(e);\n } finally {\n this.dispose();\n }\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\nclass StreamValuesHandle<T> implements Handle {\n private controller: ReadableStreamDefaultController<unknown>;\n private disposed = false;\n private fieldPath: (string | number)[];\n\n constructor(\n controller: ReadableStreamDefaultController<unknown>,\n fieldPath: (string | number)[],\n ) {\n this.controller = controller;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const value = getField(args as T, this.fieldPath);\n\n if (value !== undefined) {\n this.controller.enqueue(value);\n }\n\n // Check if the field is complete, if so close the stream\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n this.controller.close();\n this.dispose();\n }\n } catch (e) {\n this.controller.error(e);\n this.dispose();\n }\n }\n\n end(): void {\n if (this.disposed) return;\n this.controller.close();\n this.dispose();\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\nclass StreamTextHandle<T> implements Handle {\n private controller: ReadableStreamDefaultController<unknown>;\n private disposed = false;\n private fieldPath: (string | number)[];\n private lastValue: string | undefined = undefined;\n\n constructor(\n controller: ReadableStreamDefaultController<unknown>,\n fieldPath: (string | number)[],\n ) {\n this.controller = controller;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const value = getField(args as T, this.fieldPath);\n\n if (value !== undefined && typeof value === \"string\") {\n const delta = value.substring(this.lastValue?.length || 0);\n this.lastValue = value;\n this.controller.enqueue(delta);\n }\n\n // Check if the field is complete, if so close the stream\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n this.controller.close();\n this.dispose();\n }\n } catch (e) {\n this.controller.error(e);\n this.dispose();\n }\n }\n\n end(): void {\n if (this.disposed) return;\n this.controller.close();\n this.dispose();\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\nclass ForEachHandle<T> implements Handle {\n private controller: ReadableStreamDefaultController<unknown>;\n private disposed = false;\n private fieldPath: (string | number)[];\n private processedIndexes = new Set<number>();\n\n constructor(\n controller: ReadableStreamDefaultController<unknown>,\n fieldPath: (string | number)[],\n ) {\n this.controller = controller;\n this.fieldPath = fieldPath;\n }\n\n update(args: unknown): void {\n if (this.disposed) return;\n\n try {\n const array = getField(args as T, this.fieldPath);\n\n if (!Array.isArray(array)) {\n return;\n }\n\n // Check each array element and emit completed ones that haven't been processed\n for (let i = 0; i < array.length; i++) {\n if (!this.processedIndexes.has(i)) {\n const elementPath = [...this.fieldPath, i];\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n elementPath,\n ) === \"complete\"\n ) {\n this.controller.enqueue(array[i]);\n this.processedIndexes.add(i);\n }\n }\n }\n\n // Check if the entire array is complete\n if (\n getPartialJsonObjectFieldState(\n args as Record<string, unknown>,\n this.fieldPath,\n ) === \"complete\"\n ) {\n this.controller.close();\n this.dispose();\n }\n } catch (e) {\n this.controller.error(e);\n this.dispose();\n }\n }\n\n end(): void {\n if (this.disposed) return;\n this.controller.close();\n this.dispose();\n }\n\n dispose(): void {\n this.disposed = true;\n }\n}\n\n// Implementation of ToolCallReader that uses stream of partial JSON\nexport class ToolCallArgsReaderImpl<\n T extends ReadonlyJSONObject,\n> implements ToolCallArgsReader<T> {\n private argTextDeltas: ReadableStream<string>;\n private handles: Set<Handle> = new Set();\n private args: unknown = parsePartialJsonObject(\"\");\n private finished = false;\n\n constructor(argTextDeltas: ReadableStream<string>) {\n this.argTextDeltas = argTextDeltas;\n this.processStream();\n }\n\n private async processStream(): Promise<void> {\n try {\n let accumulatedText = \"\";\n const reader = this.argTextDeltas.getReader();\n\n while (true) {\n const { value, done } = await reader.read();\n if (done) break;\n\n accumulatedText += value;\n const parsedArgs = parsePartialJsonObject(accumulatedText);\n\n if (parsedArgs !== undefined) {\n this.args = parsedArgs;\n // Notify all handles of the updated args\n for (const handle of this.handles) {\n handle.update(parsedArgs);\n }\n }\n }\n } catch (error) {\n console.error(\"Error processing argument stream:\", error);\n } finally {\n this.finished = true;\n for (const handle of this.handles) {\n handle.end(this.args);\n }\n this.handles.clear();\n }\n }\n\n get<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): Promise<TypeAtPath<T, PathT>> {\n return new Promise<TypeAtPath<T, PathT>>((resolve, reject) => {\n const handle = new GetHandle<T, TypeAtPath<T, PathT>>(\n resolve,\n reject,\n fieldPath,\n );\n\n // Check if the field is already complete in current args\n if (\n this.args &&\n getPartialJsonObjectFieldState(\n this.args as Record<string, unknown>,\n fieldPath,\n ) === \"complete\"\n ) {\n const value = getField(this.args as T, fieldPath);\n if (value !== undefined) {\n resolve(value as TypeAtPath<T, PathT>);\n return;\n }\n }\n\n if (this.finished) {\n handle.end(this.args);\n return;\n }\n\n this.handles.add(handle);\n handle.update(this.args);\n });\n }\n\n streamValues<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): AsyncIterableStream<DeepPartial<TypeAtPath<T, PathT>>> {\n // Use a type assertion to convert the complex TypePath to a simple array\n const simplePath = fieldPath as unknown as (string | number)[];\n\n let handle: StreamValuesHandle<T> | undefined;\n const stream = new ReadableStream<DeepPartial<TypeAtPath<T, PathT>>>({\n start: (controller) => {\n handle = new StreamValuesHandle<T>(controller, simplePath);\n if (!this.finished) this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n\n if (this.finished) handle.end();\n },\n cancel: () => {\n // Dispose this stream's own handle (captured above) — scanning for the\n // first match would dispose a concurrent streamValues()'s handle.\n if (handle) {\n handle.dispose();\n this.handles.delete(handle);\n }\n },\n });\n\n return asAsyncIterableStream(stream) as any;\n }\n\n streamText<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): TypeAtPath<T, PathT> extends string & (infer U)\n ? AsyncIterableStream<U>\n : never {\n // Use a type assertion to convert the complex TypePath to a simple array\n const simplePath = fieldPath as unknown as (string | number)[];\n\n let handle: StreamTextHandle<T> | undefined;\n const stream = new ReadableStream<unknown>({\n start: (controller) => {\n handle = new StreamTextHandle<T>(controller, simplePath);\n if (!this.finished) this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n\n if (this.finished) handle.end();\n },\n cancel: () => {\n // Dispose this stream's own handle (captured above) — scanning for the\n // first match would dispose a concurrent streamText()'s handle.\n if (handle) {\n handle.dispose();\n this.handles.delete(handle);\n }\n },\n });\n\n return asAsyncIterableStream(stream) as any;\n }\n\n forEach<PathT extends TypePath<T>>(\n ...fieldPath: PathT\n ): NonNullable<TypeAtPath<T, PathT>> extends Array<infer U>\n ? AsyncIterableStream<U>\n : never {\n // Use a type assertion to convert the complex TypePath to a simple array\n const simplePath = fieldPath as unknown as (string | number)[];\n\n let handle: ForEachHandle<T> | undefined;\n const stream = new ReadableStream<unknown>({\n start: (controller) => {\n handle = new ForEachHandle<T>(controller, simplePath);\n if (!this.finished) this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n\n if (this.finished) handle.end();\n },\n cancel: () => {\n // Dispose this stream's own handle (captured above) — scanning for the\n // first match would dispose a concurrent forEach()'s handle.\n if (handle) {\n handle.dispose();\n this.handles.delete(handle);\n }\n },\n });\n\n return asAsyncIterableStream(stream) as any;\n }\n}\n\nexport class ToolCallResponseReaderImpl<\n TResult extends ReadonlyJSONValue,\n> implements ToolCallResponseReader<TResult> {\n private readonly promise: Promise<ToolResponse<TResult>>;\n\n constructor(promise: Promise<ToolResponse<TResult>>) {\n this.promise = promise;\n }\n\n public get() {\n return this.promise;\n }\n}\n\nexport class ToolCallReaderImpl<\n TArgs extends ReadonlyJSONObject,\n TResult extends ReadonlyJSONValue,\n> implements ToolCallReader<TArgs, TResult> {\n public readonly args: ToolCallArgsReaderImpl<TArgs>;\n public readonly response: ToolCallResponseReaderImpl<TResult>;\n private readonly writable: WritableStream<string>;\n private readonly resolve: (value: ToolResponse<TResult>) => void;\n\n public argsText: string = \"\";\n\n constructor() {\n const stream = new TransformStream<string, string>();\n this.writable = stream.writable;\n this.args = new ToolCallArgsReaderImpl<TArgs>(stream.readable);\n\n const { promise, resolve } = promiseWithResolvers<ToolResponse<TResult>>();\n this.resolve = resolve;\n this.response = new ToolCallResponseReaderImpl<TResult>(promise);\n }\n\n async appendArgsTextDelta(text: string): Promise<void> {\n const writer = this.writable.getWriter();\n try {\n await writer.write(text);\n } catch (err) {\n console.warn(err);\n } finally {\n writer.releaseLock();\n }\n\n this.argsText += text;\n }\n\n async finishArgsText(): Promise<void> {\n const writer = this.writable.getWriter();\n try {\n await writer.close();\n } catch (err) {\n console.warn(err);\n } finally {\n writer.releaseLock();\n }\n }\n\n setResponse(value: ToolResponse<TResult>): void {\n this.resolve(value);\n }\n\n result = {\n get: async () => {\n const response = await this.response.get();\n return response.result;\n },\n };\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolExecutionStream.d.ts","names":[],"sources":["../../../src/core/tool/ToolExecutionStream.ts"],"mappings":";;;;;;KAgBK,gBAAgB;EACnB;EACA;EACA,MAAM;MAEJ,QAAQ,aAAa,sBACrB,aAAa;KAGZ,sBACH,cAAc,qBAAqB,oBACnC,gBAAgB,oBAAoB,mBACpC;EACA,QAAQ,eAAe,OAAO;EAC9B;EACA;;KAGG;EACH,SAAS;EACT,YAAY;EACZ,qBACM,oBAAoB;EAE1B,mBAAmB,oBAAoB;;cAG5B,4BAA4B,wBACvC,sBACA;
|
|
1
|
+
{"version":3,"file":"ToolExecutionStream.d.ts","names":[],"sources":["../../../src/core/tool/ToolExecutionStream.ts"],"mappings":";;;;;;KAgBK,gBAAgB;EACnB;EACA;EACA,MAAM;MAEJ,QAAQ,aAAa,sBACrB,aAAa;KAGZ,sBACH,cAAc,qBAAqB,oBACnC,gBAAgB,oBAAoB,mBACpC;EACA,QAAQ,eAAe,OAAO;EAC9B;EACA;;KAGG;EACH,SAAS;EACT,YAAY;EACZ,qBACM,oBAAoB;EAE1B,mBAAmB,oBAAoB;;cAG5B,4BAA4B,wBACvC,sBACA;EAEY,YAAA,SAAS"}
|
|
@@ -9,6 +9,7 @@ var ToolExecutionStream = class extends PipeableTransformStream {
|
|
|
9
9
|
constructor(options) {
|
|
10
10
|
const toolCallPromises = /* @__PURE__ */ new Map();
|
|
11
11
|
const toolCallControllers = /* @__PURE__ */ new Map();
|
|
12
|
+
const toolCallIdsWithBackendResult = /* @__PURE__ */ new Set();
|
|
12
13
|
super((readable) => {
|
|
13
14
|
const transform = new TransformStream({
|
|
14
15
|
async transform(chunk, controller) {
|
|
@@ -44,6 +45,7 @@ var ToolExecutionStream = class extends PipeableTransformStream {
|
|
|
44
45
|
isError: chunk.isError,
|
|
45
46
|
modelContent: chunk.modelContent
|
|
46
47
|
}));
|
|
48
|
+
toolCallIdsWithBackendResult.add(toolCallId);
|
|
47
49
|
break;
|
|
48
50
|
}
|
|
49
51
|
case "tool-call-args-text-finish": {
|
|
@@ -52,6 +54,7 @@ var ToolExecutionStream = class extends PipeableTransformStream {
|
|
|
52
54
|
const streamController = toolCallControllers.get(toolCallId);
|
|
53
55
|
if (!streamController) throw new Error("No controller found for tool call");
|
|
54
56
|
await streamController.finishArgsText();
|
|
57
|
+
if (toolCallIdsWithBackendResult.has(toolCallId)) break;
|
|
55
58
|
let isExecuting = false;
|
|
56
59
|
const promise = withPromiseOrValue(() => {
|
|
57
60
|
let args;
|
|
@@ -109,9 +112,14 @@ var ToolExecutionStream = class extends PipeableTransformStream {
|
|
|
109
112
|
if (toolCallPromise) toolCallPromise.then(() => {
|
|
110
113
|
toolCallPromises.delete(toolCallId);
|
|
111
114
|
toolCallControllers.delete(toolCallId);
|
|
115
|
+
toolCallIdsWithBackendResult.delete(toolCallId);
|
|
112
116
|
controller.enqueue(chunk);
|
|
113
117
|
});
|
|
114
|
-
else
|
|
118
|
+
else {
|
|
119
|
+
toolCallControllers.delete(toolCallId);
|
|
120
|
+
toolCallIdsWithBackendResult.delete(toolCallId);
|
|
121
|
+
controller.enqueue(chunk);
|
|
122
|
+
}
|
|
115
123
|
}
|
|
116
124
|
}
|
|
117
125
|
},
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolExecutionStream.js","names":[],"sources":["../../../src/core/tool/ToolExecutionStream.ts"],"sourcesContent":["import sjson from \"secure-json-parse\";\nimport type { AssistantStreamChunk } from \"../AssistantStreamChunk\";\nimport {\n type AssistantMetaStreamChunk,\n AssistantMetaTransformStream,\n} from \"../utils/stream/AssistantMetaTransformStream\";\nimport { PipeableTransformStream } from \"../utils/stream/PipeableTransformStream\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"../../utils/json/json-value\";\nimport { ToolResponse } from \"./ToolResponse\";\nimport { withPromiseOrValue } from \"../utils/withPromiseOrValue\";\nimport { ToolCallReaderImpl } from \"./ToolCallReader\";\nimport type { ToolCallReader } from \"./tool-types\";\n\ntype ToolCallback = (toolCall: {\n toolCallId: string;\n toolName: string;\n args: ReadonlyJSONObject;\n}) =>\n | Promise<ToolResponse<ReadonlyJSONValue>>\n | ToolResponse<ReadonlyJSONValue>\n | undefined;\n\ntype ToolStreamCallback = <\n TArgs extends ReadonlyJSONObject = ReadonlyJSONObject,\n TResult extends ReadonlyJSONValue = ReadonlyJSONValue,\n>(toolCall: {\n reader: ToolCallReader<TArgs, TResult>;\n toolCallId: string;\n toolName: string;\n}) => void;\n\ntype ToolExecutionOptions = {\n execute: ToolCallback;\n streamCall: ToolStreamCallback;\n onExecutionStart?:\n | ((toolCallId: string, toolName: string) => void)\n | undefined;\n onExecutionEnd?: ((toolCallId: string, toolName: string) => void) | undefined;\n};\n\nexport class ToolExecutionStream extends PipeableTransformStream<\n AssistantStreamChunk,\n AssistantStreamChunk\n> {\n constructor(options: ToolExecutionOptions) {\n const toolCallPromises = new Map<string, PromiseLike<void>>();\n const toolCallControllers = new Map<\n string,\n ToolCallReaderImpl<ReadonlyJSONObject, ReadonlyJSONValue>\n >();\n\n super((readable) => {\n const transform = new TransformStream<\n AssistantMetaStreamChunk,\n AssistantStreamChunk\n >({\n async transform(chunk, controller) {\n // forward everything\n if (chunk.type !== \"part-finish\" || chunk.meta.type !== \"tool-call\") {\n controller.enqueue(chunk);\n }\n\n const type = chunk.type;\n\n switch (type) {\n case \"part-start\":\n if (chunk.part.type === \"tool-call\") {\n const reader = new ToolCallReaderImpl<\n ReadonlyJSONObject,\n ReadonlyJSONValue\n >();\n toolCallControllers.set(chunk.part.toolCallId, reader);\n\n options.streamCall({\n reader,\n toolCallId: chunk.part.toolCallId,\n toolName: chunk.part.toolName,\n });\n }\n break;\n case \"text-delta\": {\n if (chunk.meta.type === \"tool-call\") {\n const toolCallId = chunk.meta.toolCallId;\n\n const controller = toolCallControllers.get(toolCallId);\n if (!controller)\n throw new Error(\"No controller found for tool call\");\n // Awaited so the writer lock is released (and argsText updated)\n // before the next chunk acquires the writer.\n await controller.appendArgsTextDelta(chunk.textDelta);\n }\n break;\n }\n case \"result\": {\n if (chunk.meta.type !== \"tool-call\") break;\n\n const { toolCallId } = chunk.meta;\n const controller = toolCallControllers.get(toolCallId);\n if (!controller)\n throw new Error(\"No controller found for tool call\");\n controller.setResponse(\n new ToolResponse({\n result: chunk.result,\n artifact: chunk.artifact,\n isError: chunk.isError,\n modelContent: chunk.modelContent,\n }),\n );\n break;\n }\n case \"tool-call-args-text-finish\": {\n if (chunk.meta.type !== \"tool-call\") break;\n\n const { toolCallId, toolName } = chunk.meta;\n const streamController = toolCallControllers.get(toolCallId)!;\n if (!streamController)\n throw new Error(\"No controller found for tool call\");\n\n // Args fully streamed: close the reader so awaited absent fields\n // resolve. Awaited so the close settles before the writer is reused.\n await streamController.finishArgsText();\n\n let isExecuting = false;\n const promise = withPromiseOrValue(\n () => {\n let args: ReadonlyJSONObject;\n try {\n args = sjson.parse(\n streamController.argsText,\n ) as ReadonlyJSONObject;\n } catch (e) {\n throw new Error(\n `Function parameter parsing failed. ${JSON.stringify((e as Error).message)}`,\n );\n }\n\n const executeResult = options.execute({\n toolCallId,\n toolName,\n args,\n });\n\n // Only mark as executing if the tool has frontend execution\n if (executeResult !== undefined) {\n isExecuting = true;\n options.onExecutionStart?.(toolCallId, toolName);\n }\n\n return executeResult;\n },\n (c) => {\n if (isExecuting) {\n options.onExecutionEnd?.(toolCallId, toolName);\n }\n\n if (c === undefined) return;\n\n // TODO how to handle new ToolResult({ result: undefined })?\n const result = new ToolResponse({\n artifact: c.artifact,\n result: c.result,\n isError: c.isError,\n messages: c.messages,\n modelContent: c.modelContent,\n });\n streamController.setResponse(result);\n controller.enqueue({\n type: \"result\",\n path: chunk.path,\n ...result,\n });\n },\n (e) => {\n if (isExecuting) {\n options.onExecutionEnd?.(toolCallId, toolName);\n }\n\n const result = new ToolResponse({\n result: String(e),\n isError: true,\n });\n\n streamController.setResponse(result);\n controller.enqueue({\n type: \"result\",\n path: chunk.path,\n ...result,\n });\n },\n );\n if (promise) {\n toolCallPromises.set(toolCallId, promise);\n }\n break;\n }\n\n case \"part-finish\": {\n if (chunk.meta.type !== \"tool-call\") break;\n\n const { toolCallId } = chunk.meta;\n const toolCallPromise = toolCallPromises.get(toolCallId);\n if (toolCallPromise) {\n toolCallPromise.then(() => {\n toolCallPromises.delete(toolCallId);\n toolCallControllers.delete(toolCallId);\n\n controller.enqueue(chunk);\n });\n } else {\n controller.enqueue(chunk);\n }\n }\n }\n },\n async flush() {\n await Promise.all(toolCallPromises.values());\n },\n });\n\n return readable\n .pipeThrough(new AssistantMetaTransformStream())\n .pipeThrough(transform);\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"ToolExecutionStream.js","names":[],"sources":["../../../src/core/tool/ToolExecutionStream.ts"],"sourcesContent":["import sjson from \"secure-json-parse\";\nimport type { AssistantStreamChunk } from \"../AssistantStreamChunk\";\nimport {\n type AssistantMetaStreamChunk,\n AssistantMetaTransformStream,\n} from \"../utils/stream/AssistantMetaTransformStream\";\nimport { PipeableTransformStream } from \"../utils/stream/PipeableTransformStream\";\nimport type {\n ReadonlyJSONObject,\n ReadonlyJSONValue,\n} from \"../../utils/json/json-value\";\nimport { ToolResponse } from \"./ToolResponse\";\nimport { withPromiseOrValue } from \"../utils/withPromiseOrValue\";\nimport { ToolCallReaderImpl } from \"./ToolCallReader\";\nimport type { ToolCallReader } from \"./tool-types\";\n\ntype ToolCallback = (toolCall: {\n toolCallId: string;\n toolName: string;\n args: ReadonlyJSONObject;\n}) =>\n | Promise<ToolResponse<ReadonlyJSONValue>>\n | ToolResponse<ReadonlyJSONValue>\n | undefined;\n\ntype ToolStreamCallback = <\n TArgs extends ReadonlyJSONObject = ReadonlyJSONObject,\n TResult extends ReadonlyJSONValue = ReadonlyJSONValue,\n>(toolCall: {\n reader: ToolCallReader<TArgs, TResult>;\n toolCallId: string;\n toolName: string;\n}) => void;\n\ntype ToolExecutionOptions = {\n execute: ToolCallback;\n streamCall: ToolStreamCallback;\n onExecutionStart?:\n | ((toolCallId: string, toolName: string) => void)\n | undefined;\n onExecutionEnd?: ((toolCallId: string, toolName: string) => void) | undefined;\n};\n\nexport class ToolExecutionStream extends PipeableTransformStream<\n AssistantStreamChunk,\n AssistantStreamChunk\n> {\n constructor(options: ToolExecutionOptions) {\n const toolCallPromises = new Map<string, PromiseLike<void>>();\n const toolCallControllers = new Map<\n string,\n ToolCallReaderImpl<ReadonlyJSONObject, ReadonlyJSONValue>\n >();\n const toolCallIdsWithBackendResult = new Set<string>();\n\n super((readable) => {\n const transform = new TransformStream<\n AssistantMetaStreamChunk,\n AssistantStreamChunk\n >({\n async transform(chunk, controller) {\n // forward everything\n if (chunk.type !== \"part-finish\" || chunk.meta.type !== \"tool-call\") {\n controller.enqueue(chunk);\n }\n\n const type = chunk.type;\n\n switch (type) {\n case \"part-start\":\n if (chunk.part.type === \"tool-call\") {\n const reader = new ToolCallReaderImpl<\n ReadonlyJSONObject,\n ReadonlyJSONValue\n >();\n toolCallControllers.set(chunk.part.toolCallId, reader);\n\n options.streamCall({\n reader,\n toolCallId: chunk.part.toolCallId,\n toolName: chunk.part.toolName,\n });\n }\n break;\n case \"text-delta\": {\n if (chunk.meta.type === \"tool-call\") {\n const toolCallId = chunk.meta.toolCallId;\n\n const controller = toolCallControllers.get(toolCallId);\n if (!controller)\n throw new Error(\"No controller found for tool call\");\n // Awaited so the writer lock is released (and argsText updated)\n // before the next chunk acquires the writer.\n await controller.appendArgsTextDelta(chunk.textDelta);\n }\n break;\n }\n case \"result\": {\n if (chunk.meta.type !== \"tool-call\") break;\n\n const { toolCallId } = chunk.meta;\n const controller = toolCallControllers.get(toolCallId);\n if (!controller)\n throw new Error(\"No controller found for tool call\");\n controller.setResponse(\n new ToolResponse({\n result: chunk.result,\n artifact: chunk.artifact,\n isError: chunk.isError,\n modelContent: chunk.modelContent,\n }),\n );\n toolCallIdsWithBackendResult.add(toolCallId);\n break;\n }\n case \"tool-call-args-text-finish\": {\n if (chunk.meta.type !== \"tool-call\") break;\n\n const { toolCallId, toolName } = chunk.meta;\n const streamController = toolCallControllers.get(toolCallId)!;\n if (!streamController)\n throw new Error(\"No controller found for tool call\");\n\n // Args fully streamed: close the reader so awaited absent fields\n // resolve. Awaited so the close settles before the writer is reused.\n await streamController.finishArgsText();\n\n // A backend result is authoritative. Closing the args stream still\n // emits this finish chunk, but must not parse stale/incomplete args,\n // execute the frontend tool, or enqueue a second result.\n if (toolCallIdsWithBackendResult.has(toolCallId)) break;\n\n let isExecuting = false;\n const promise = withPromiseOrValue(\n () => {\n let args: ReadonlyJSONObject;\n try {\n args = sjson.parse(\n streamController.argsText,\n ) as ReadonlyJSONObject;\n } catch (e) {\n throw new Error(\n `Function parameter parsing failed. ${JSON.stringify((e as Error).message)}`,\n );\n }\n\n const executeResult = options.execute({\n toolCallId,\n toolName,\n args,\n });\n\n // Only mark as executing if the tool has frontend execution\n if (executeResult !== undefined) {\n isExecuting = true;\n options.onExecutionStart?.(toolCallId, toolName);\n }\n\n return executeResult;\n },\n (c) => {\n if (isExecuting) {\n options.onExecutionEnd?.(toolCallId, toolName);\n }\n\n if (c === undefined) return;\n\n // TODO how to handle new ToolResult({ result: undefined })?\n const result = new ToolResponse({\n artifact: c.artifact,\n result: c.result,\n isError: c.isError,\n messages: c.messages,\n modelContent: c.modelContent,\n });\n streamController.setResponse(result);\n controller.enqueue({\n type: \"result\",\n path: chunk.path,\n ...result,\n });\n },\n (e) => {\n if (isExecuting) {\n options.onExecutionEnd?.(toolCallId, toolName);\n }\n\n const result = new ToolResponse({\n result: String(e),\n isError: true,\n });\n\n streamController.setResponse(result);\n controller.enqueue({\n type: \"result\",\n path: chunk.path,\n ...result,\n });\n },\n );\n if (promise) {\n toolCallPromises.set(toolCallId, promise);\n }\n break;\n }\n\n case \"part-finish\": {\n if (chunk.meta.type !== \"tool-call\") break;\n\n const { toolCallId } = chunk.meta;\n const toolCallPromise = toolCallPromises.get(toolCallId);\n if (toolCallPromise) {\n toolCallPromise.then(() => {\n toolCallPromises.delete(toolCallId);\n toolCallControllers.delete(toolCallId);\n toolCallIdsWithBackendResult.delete(toolCallId);\n\n controller.enqueue(chunk);\n });\n } else {\n toolCallControllers.delete(toolCallId);\n toolCallIdsWithBackendResult.delete(toolCallId);\n controller.enqueue(chunk);\n }\n }\n }\n },\n async flush() {\n await Promise.all(toolCallPromises.values());\n },\n });\n\n return readable\n .pipeThrough(new AssistantMetaTransformStream())\n .pipeThrough(transform);\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolResponse.d.ts","names":[],"sources":["../../../src/core/tool/ToolResponse.ts"],"mappings":";;;cAOM;;;;KAKM,iBAAiB;;EAE3B,QAAQ;;;;;;;EAOR,WAAW;;EAEX;;;;;;;EAOA,wBAAwB;;EAExB,WAAW;;;;;;;;;;;;;;;;;;cAmBA,aAAa;OACnB;WAII,WAAW;WACX,QAAQ;WACR;WACA,wBAAwB;WACxB,WAAW;
|
|
1
|
+
{"version":3,"file":"ToolResponse.d.ts","names":[],"sources":["../../../src/core/tool/ToolResponse.ts"],"mappings":";;;cAOM;;;;KAKM,iBAAiB;;EAE3B,QAAQ;;;;;;;EAOR,WAAW;;EAEX;;;;;;;EAOA,wBAAwB;;EAExB,WAAW;;;;;;;;;;;;;;;;;;cAmBA,aAAa;OACnB;WAII,WAAW;WACX,QAAQ;WACR;WACA,wBAAwB;WACxB,WAAW;EAER,YAAA,SAAS,iBAAiB;UAc9B,OAAO,aACb,eACC,OAAO,aAAa;;;;;;;;SAahB,WAAW,cAAc,oBAAoB"}
|
|
@@ -167,6 +167,12 @@ type ToolBase<TArgs extends Record<string, unknown> = Record<string, unknown>, T
|
|
|
167
167
|
* @see ToolDisplay
|
|
168
168
|
*/
|
|
169
169
|
display?: ToolDisplay;
|
|
170
|
+
/**
|
|
171
|
+
* Replaces an already-registered same-priority tool with the same name
|
|
172
|
+
* instead of throwing. Discouraged escape hatch — overwriting a same-priority
|
|
173
|
+
* tool is usually a design smell; prefer distinct names or priorities.
|
|
174
|
+
*/
|
|
175
|
+
overwrite?: boolean;
|
|
170
176
|
};
|
|
171
177
|
type BackendTool<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = ToolBase<TArgs, TResult> & {
|
|
172
178
|
/** Tool that is executed by the backend rather than in the browser. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-types.d.ts","names":[],"sources":["../../../src/core/tool/tool-types.ts"],"mappings":";;;;;;;KAMY;;WAGG;;WAEA;;;WAIA;;;;;WAKA;;WAEA;;WAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4BH,wBAAwB,OAAO,YAAY;;EAErD;;EAEA,OAAO;;EAEP,QAAQ;eAEG,yBACT,iBAAiB;;;;;;;;;UAUJ,mBAAmB,cAAc;;;;;;;EAOhD,IAAI,cAAc,SAAS,WACtB,WAAW,QACb,QAAQ,WAAW,OAAO;;;;;;;EAQ7B,aAAa,cAAc,SAAS,WAC/B,WAAW,QACb,oBAAoB,YAAY,WAAW,OAAO;;;;;;;EAQrD,WAAW,cAAc,SAAS,WAC7B,WAAW,QACb,WAAW,OAAO,+BAA+B,KAChD,oBAAoB;;;;;;;EASxB,QAAQ,cAAc,SAAS,WAC1B,WAAW,QACb,YAAY,WAAW,OAAO,gBAAgB,YAAY,KACzD,oBAAoB;;UAIT,uBAAuB;EACtC,WAAW,QAAQ,aAAa;;UAGjB,eACf,cAAc,0BAA0B,yBACxC;EAEA,MAAM,mBAAmB;EACzB,UAAU,uBAAuB;;;;;EAMjC;IACE,WAAW,QAAQ;;;KAIX;;EAEV;;EAEA,aAAa;;;;;EAKb,QAAQ,qBAAqB;;;;;KAMnB,oBAAoB,OAAO,YACrC,MAAM,OACN,SAAS,yBACN,UAAU,QAAQ;KAEX,uBACV,cAAc,0BAA0B,yBACxC,sBAEA,QAAQ,eAAe,OAAO,UAC9B,SAAS;KAGN,gCAAgC,WAAW,6BAE9C;;;;;;;;;;;;;KAeU,kBAAkB,eAAe;;;;;;;;;;;;;;KAexC;KAEA,SACH,cAAc,0BAA0B,yBACxC;;;;EAKA,aAAa,uBAAuB,OAAO;;;;;;;;;;EAW3C,UAAU;;
|
|
1
|
+
{"version":3,"file":"tool-types.d.ts","names":[],"sources":["../../../src/core/tool/tool-types.ts"],"mappings":";;;;;;;KAMY;;WAGG;;WAEA;;;WAIA;;;;;WAKA;;WAEA;;WAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4BH,wBAAwB,OAAO,YAAY;;EAErD;;EAEA,OAAO;;EAEP,QAAQ;eAEG,yBACT,iBAAiB;;;;;;;;;UAUJ,mBAAmB,cAAc;;;;;;;EAOhD,IAAI,cAAc,SAAS,WACtB,WAAW,QACb,QAAQ,WAAW,OAAO;;;;;;;EAQ7B,aAAa,cAAc,SAAS,WAC/B,WAAW,QACb,oBAAoB,YAAY,WAAW,OAAO;;;;;;;EAQrD,WAAW,cAAc,SAAS,WAC7B,WAAW,QACb,WAAW,OAAO,+BAA+B,KAChD,oBAAoB;;;;;;;EASxB,QAAQ,cAAc,SAAS,WAC1B,WAAW,QACb,YAAY,WAAW,OAAO,gBAAgB,YAAY,KACzD,oBAAoB;;UAIT,uBAAuB;EACtC,WAAW,QAAQ,aAAa;;UAGjB,eACf,cAAc,0BAA0B,yBACxC;EAEA,MAAM,mBAAmB;EACzB,UAAU,uBAAuB;;;;;EAMjC;IACE,WAAW,QAAQ;;;KAIX;;EAEV;;EAEA,aAAa;;;;;EAKb,QAAQ,qBAAqB;;;;;KAMnB,oBAAoB,OAAO,YACrC,MAAM,OACN,SAAS,yBACN,UAAU,QAAQ;KAEX,uBACV,cAAc,0BAA0B,yBACxC,sBAEA,QAAQ,eAAe,OAAO,UAC9B,SAAS;KAGN,gCAAgC,WAAW,6BAE9C;;;;;;;;;;;;;KAeU,kBAAkB,eAAe;;;;;;;;;;;;;;KAexC;KAEA,SACH,cAAc,0BAA0B,yBACxC;;;;EAKA,aAAa,uBAAuB,OAAO;;;;;;;;;;EAW3C,UAAU;;;;;;EAiBV;;KAGG,YACH,cAAc,0BAA0B,yBACxC,qBACE,SAAS,OAAO;;EAElB;EAEA;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;;;;KAUG,uBACH,cAAc,0BAA0B,yBACxC,qBACE,SAAS,OAAO;EAClB;;EAGA;;EAEA,aAAa,iBAAiB,SAAS;;EAEvC;;EAEA,UAAU,oBAAoB,OAAO;;EAErC,gBAAgB,wBAAwB,OAAO;;EAE/C,uCAAuC,gCAAgC;EACvE,kBAAkB;;KAGf,aACH,cAAc,0BAA0B,yBACxC,qBACE,SAAS,OAAO;;EAElB;;EAGA;;EAEA,YAAY,iBAAiB,SAAS;;EAEtC;;EAEA,UAAU,oBAAoB,OAAO;;EAErC,gBAAgB,wBAAwB,OAAO;;EAE/C,uCAAuC,gCAAgC;EACvE,kBAAkB;;KAGf,UACH,cAAc,0BAA0B,yBACxC,qBACE,SAAS,OAAO;;EAElB;;EAGA;;EAEA,YAAY,iBAAiB,SAAS;;EAEtC;;EAEA;EACA;EACA;EACA;EACA,kBAAkB;;KAGf,aACH,cAAc,0BAA0B,yBACxC,qBACE,SAAS,OAAO;;EAElB;;EAGA;;EAEA,aAAa,iBAAiB,SAAS;;EAEvC,MAAM;;;;EAIN;EAEA;EACA;EACA;EACA;EACA;EACA,kBAAkB;;KAGR;;EAGN;EACA;EACA,UAAU;EACV;;EAEA;;;EAIA;EACA;EACA;EACA,MAAM;EACN;;EAEA;;KAGD,UAAU,SAAS;;EAEtB;EACA,QAAQ;EAER;EACA;EACA;EACA;EACA;EACA;EACA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;KA4CU,KACV,cAAc,0BAA0B,yBACxC,qBAEE,aAAa,OAAO,WACpB,YAAY,OAAO,WACnB,UAAU,OAAO,WACjB,aAAa,OAAO,WACpB,UACA,gBAAgB,OAAO;;;;;;;KAQf,gBACV,cAAc,0BAA0B,yBACxC,qBAEE,aAAa,OAAO,WACpB,uBAAuB,OAAO,WAC9B,UAAU,OAAO,WACjB,aAAa,OAAO,WACpB,UACA,gBAAgB,OAAO;;;;KAKf,gBACV,cAAc,0BAA0B,yBACxC,sBAEE,KAAK,aAAa,OAAO,oBACzB,KAAK,YAAY,OAAO,oBACxB,KAAK,UAAU,OAAO,oBACtB,KAAK,aAAa,OAAO;EACvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolResultStream.d.ts","names":[],"sources":["../../../src/core/tool/toolResultStream.ts"],"mappings":";;;;
|
|
1
|
+
{"version":3,"file":"toolResultStream.d.ts","names":[],"sources":["../../../src/core/tool/toolResultStream.ts"],"mappings":";;;;iBAkJsB,yBACpB,SAAS,kBACT,OAAO,eAAe,mBACtB,aAAa,aACb,QAAQ,oBAAoB,qBAAqB,mBAAgB,QAAA;KAsEvD;;EAEV,oBAAoB,oBAAoB;;EAExC,kBAAkB,oBAAoB;;;;;;;;;;;;;;;iBAgBxB,iBACd,OACI,eAAe,eACR,eAAe,gCAE1B,aAAa,qBAAqB,cAClC,QAAQ,oBAAoB,qBAAqB,kBACjD,UAAU,0BAAuB"}
|
|
@@ -20,8 +20,9 @@ function getToolResponse(tools, abortSignal, toolCall, human) {
|
|
|
20
20
|
throw new Error(`Function parameter validation failed. ${JSON.stringify(result.issues)}`);
|
|
21
21
|
});
|
|
22
22
|
}
|
|
23
|
+
let onAbort;
|
|
23
24
|
const abortPromise = new Promise((resolve) => {
|
|
24
|
-
|
|
25
|
+
onAbort = () => {
|
|
25
26
|
queueMicrotask(() => {
|
|
26
27
|
queueMicrotask(() => {
|
|
27
28
|
resolve(new ToolResponse({
|
|
@@ -59,7 +60,11 @@ function getToolResponse(tools, abortSignal, toolCall, human) {
|
|
|
59
60
|
}
|
|
60
61
|
return response;
|
|
61
62
|
})();
|
|
62
|
-
|
|
63
|
+
try {
|
|
64
|
+
return await Promise.race([executePromise, abortPromise]);
|
|
65
|
+
} finally {
|
|
66
|
+
abortSignal.removeEventListener("abort", onAbort);
|
|
67
|
+
}
|
|
63
68
|
};
|
|
64
69
|
return getResult(tool.execute);
|
|
65
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"toolResultStream.js","names":[],"sources":["../../../src/core/tool/toolResultStream.ts"],"sourcesContent":["import type { Tool, ToolCallReader, ToolExecuteFunction } from \"./tool-types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { ToolResponse } from \"./ToolResponse\";\nimport { ToolExecutionStream } from \"./ToolExecutionStream\";\nimport type { AssistantMessage } from \"../utils/types\";\nimport type { ReadonlyJSONObject, ReadonlyJSONValue } from \"../../utils\";\n\nconst isStandardSchemaV1 = (\n schema: unknown,\n): schema is StandardSchemaV1<unknown> => {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"~standard\" in schema &&\n (schema as StandardSchemaV1<unknown>)[\"~standard\"].version === 1\n );\n};\n\nfunction getToolResponse(\n tools: Record<string, Tool> | undefined,\n abortSignal: AbortSignal,\n toolCall: {\n toolCallId: string;\n toolName: string;\n args: ReadonlyJSONObject;\n },\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n) {\n const tool = tools?.[toolCall.toolName];\n if (!tool?.execute) return undefined;\n\n const getResult = async (\n toolExecute: ToolExecuteFunction<ReadonlyJSONObject, unknown>,\n ): Promise<ToolResponse<ReadonlyJSONValue>> => {\n // Check if already aborted before starting\n if (abortSignal.aborted) {\n return new ToolResponse({\n result: \"Tool execution was cancelled.\",\n isError: true,\n });\n }\n\n let executeFn = toolExecute;\n\n if (isStandardSchemaV1(tool.parameters)) {\n let result = tool.parameters[\"~standard\"].validate(toolCall.args);\n if (result instanceof Promise) result = await result;\n\n if (result.issues) {\n executeFn =\n tool.experimental_onSchemaValidationError ??\n (() => {\n throw new Error(\n `Function parameter validation failed. ${JSON.stringify(result.issues)}`,\n );\n });\n }\n }\n\n // Create abort promise that resolves after 2 microtasks\n // This gives tools that handle abort a chance to win the race\n const abortPromise = new Promise<ToolResponse<ReadonlyJSONValue>>(\n (resolve) => {\n const onAbort = () => {\n queueMicrotask(() => {\n queueMicrotask(() => {\n resolve(\n new ToolResponse({\n result: \"Tool execution was cancelled.\",\n isError: true,\n }),\n );\n });\n });\n };\n if (abortSignal.aborted) {\n onAbort();\n } else {\n abortSignal.addEventListener(\"abort\", onAbort, { once: true });\n }\n },\n );\n\n const executePromise = (async () => {\n const result = (await executeFn(toolCall.args, {\n toolCallId: toolCall.toolCallId,\n abortSignal,\n human: (payload: unknown) => human(toolCall.toolCallId, payload),\n })) as unknown as ReadonlyJSONValue;\n const response = ToolResponse.toResponse(result);\n if (\n tool.toModelOutput &&\n !response.isError &&\n response.modelContent === undefined\n ) {\n try {\n const modelContent = await tool.toModelOutput({\n toolCallId: toolCall.toolCallId,\n input: toolCall.args,\n output: response.result,\n });\n return new ToolResponse({\n result: response.result,\n artifact: response.artifact,\n isError: response.isError,\n messages: response.messages,\n modelContent,\n });\n } catch (e) {\n console.warn(\n `[assistant-stream] tool \"${toolCall.toolName}\" toModelOutput threw; falling back to default projection.`,\n e,\n );\n }\n }\n return response;\n })();\n\n return Promise.race([executePromise, abortPromise]);\n };\n\n return getResult(tool.execute);\n}\n\nfunction getToolStreamResponse(\n tools: Record<string, Tool> | undefined,\n abortSignal: AbortSignal,\n reader: ToolCallReader<any, ReadonlyJSONValue>,\n context: {\n toolCallId: string;\n toolName: string;\n },\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n) {\n tools?.[context.toolName]?.streamCall?.(reader, {\n toolCallId: context.toolCallId,\n abortSignal,\n human: (payload: unknown) => human(context.toolCallId, payload),\n });\n}\n\nexport async function unstable_runPendingTools(\n message: AssistantMessage,\n tools: Record<string, Tool> | undefined,\n abortSignal: AbortSignal,\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n) {\n const toolCallPromises = message.parts\n .filter((part) => part.type === \"tool-call\")\n .map(async (part) => {\n const promiseOrUndefined = getToolResponse(\n tools,\n abortSignal,\n part,\n human ??\n (async () => {\n throw new Error(\n \"Tool human input is not supported in this context\",\n );\n }),\n );\n if (promiseOrUndefined) {\n const result = await promiseOrUndefined;\n return {\n toolCallId: part.toolCallId,\n result,\n };\n }\n return null;\n });\n\n const toolCallResults = (await Promise.all(toolCallPromises)).filter(\n (result) => result !== null,\n ) as { toolCallId: string; result: ToolResponse<ReadonlyJSONValue> }[];\n\n if (toolCallResults.length === 0) {\n return message;\n }\n\n const toolCallResultsById = toolCallResults.reduce(\n (acc, { toolCallId, result }) => {\n acc[toolCallId] = result;\n return acc;\n },\n {} as Record<string, ToolResponse<ReadonlyJSONValue>>,\n );\n\n const updatedParts = message.parts.map((p) => {\n if (p.type === \"tool-call\") {\n const toolResponse = toolCallResultsById[p.toolCallId];\n if (toolResponse) {\n return {\n ...p,\n state: \"result\" as const,\n ...(toolResponse.artifact !== undefined\n ? { artifact: toolResponse.artifact }\n : {}),\n ...(toolResponse.modelContent !== undefined\n ? { modelContent: toolResponse.modelContent }\n : {}),\n result: toolResponse.result as ReadonlyJSONValue,\n isError: toolResponse.isError,\n };\n }\n }\n return p;\n });\n\n return {\n ...message,\n parts: updatedParts,\n content: updatedParts,\n };\n}\n\nexport type ToolResultStreamOptions = {\n /** Called immediately before a frontend tool's `execute` function runs. */\n onExecutionStart?: (toolCallId: string, toolName: string) => void;\n /** Called after frontend tool execution finishes or fails. */\n onExecutionEnd?: (toolCallId: string, toolName: string) => void;\n};\n\n/**\n * Transform stream that executes frontend tools and appends tool results.\n *\n * The transform watches streamed tool-call arguments, runs the matching\n * frontend tool once its arguments are complete, and emits a result chunk for\n * the tool call. Backend and human tools pass through according to their tool\n * definition.\n *\n * @param tools Tool registry or function returning the current registry.\n * @param abortSignal Signal, or signal getter, used for the current run.\n * @param human Callback used to resolve human-tool requests from UI input.\n * @param options Optional execution lifecycle callbacks.\n */\nexport function toolResultStream(\n tools:\n | Record<string, Tool>\n | (() => Record<string, Tool> | undefined)\n | undefined,\n abortSignal: AbortSignal | (() => AbortSignal),\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n options?: ToolResultStreamOptions,\n) {\n const toolsFn = typeof tools === \"function\" ? tools : () => tools;\n const abortSignalFn =\n typeof abortSignal === \"function\" ? abortSignal : () => abortSignal;\n return new ToolExecutionStream({\n execute: (toolCall) =>\n getToolResponse(toolsFn(), abortSignalFn(), toolCall, human),\n streamCall: ({ reader, ...context }) =>\n getToolStreamResponse(toolsFn(), abortSignalFn(), reader, context, human),\n onExecutionStart: options?.onExecutionStart,\n onExecutionEnd: options?.onExecutionEnd,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"toolResultStream.js","names":[],"sources":["../../../src/core/tool/toolResultStream.ts"],"sourcesContent":["import type { Tool, ToolCallReader, ToolExecuteFunction } from \"./tool-types\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport { ToolResponse } from \"./ToolResponse\";\nimport { ToolExecutionStream } from \"./ToolExecutionStream\";\nimport type { AssistantMessage } from \"../utils/types\";\nimport type { ReadonlyJSONObject, ReadonlyJSONValue } from \"../../utils\";\n\nconst isStandardSchemaV1 = (\n schema: unknown,\n): schema is StandardSchemaV1<unknown> => {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"~standard\" in schema &&\n (schema as StandardSchemaV1<unknown>)[\"~standard\"].version === 1\n );\n};\n\nfunction getToolResponse(\n tools: Record<string, Tool> | undefined,\n abortSignal: AbortSignal,\n toolCall: {\n toolCallId: string;\n toolName: string;\n args: ReadonlyJSONObject;\n },\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n) {\n const tool = tools?.[toolCall.toolName];\n if (!tool?.execute) return undefined;\n\n const getResult = async (\n toolExecute: ToolExecuteFunction<ReadonlyJSONObject, unknown>,\n ): Promise<ToolResponse<ReadonlyJSONValue>> => {\n // Check if already aborted before starting\n if (abortSignal.aborted) {\n return new ToolResponse({\n result: \"Tool execution was cancelled.\",\n isError: true,\n });\n }\n\n let executeFn = toolExecute;\n\n if (isStandardSchemaV1(tool.parameters)) {\n let result = tool.parameters[\"~standard\"].validate(toolCall.args);\n if (result instanceof Promise) result = await result;\n\n if (result.issues) {\n executeFn =\n tool.experimental_onSchemaValidationError ??\n (() => {\n throw new Error(\n `Function parameter validation failed. ${JSON.stringify(result.issues)}`,\n );\n });\n }\n }\n\n // Create abort promise that resolves after 2 microtasks\n // This gives tools that handle abort a chance to win the race\n let onAbort!: () => void;\n const abortPromise = new Promise<ToolResponse<ReadonlyJSONValue>>(\n (resolve) => {\n onAbort = () => {\n queueMicrotask(() => {\n queueMicrotask(() => {\n resolve(\n new ToolResponse({\n result: \"Tool execution was cancelled.\",\n isError: true,\n }),\n );\n });\n });\n };\n if (abortSignal.aborted) {\n onAbort();\n } else {\n abortSignal.addEventListener(\"abort\", onAbort, { once: true });\n }\n },\n );\n\n const executePromise = (async () => {\n const result = (await executeFn(toolCall.args, {\n toolCallId: toolCall.toolCallId,\n abortSignal,\n human: (payload: unknown) => human(toolCall.toolCallId, payload),\n })) as unknown as ReadonlyJSONValue;\n const response = ToolResponse.toResponse(result);\n if (\n tool.toModelOutput &&\n !response.isError &&\n response.modelContent === undefined\n ) {\n try {\n const modelContent = await tool.toModelOutput({\n toolCallId: toolCall.toolCallId,\n input: toolCall.args,\n output: response.result,\n });\n return new ToolResponse({\n result: response.result,\n artifact: response.artifact,\n isError: response.isError,\n messages: response.messages,\n modelContent,\n });\n } catch (e) {\n console.warn(\n `[assistant-stream] tool \"${toolCall.toolName}\" toModelOutput threw; falling back to default projection.`,\n e,\n );\n }\n }\n return response;\n })();\n\n try {\n return await Promise.race([executePromise, abortPromise]);\n } finally {\n abortSignal.removeEventListener(\"abort\", onAbort);\n }\n };\n\n return getResult(tool.execute);\n}\n\nfunction getToolStreamResponse(\n tools: Record<string, Tool> | undefined,\n abortSignal: AbortSignal,\n reader: ToolCallReader<any, ReadonlyJSONValue>,\n context: {\n toolCallId: string;\n toolName: string;\n },\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n) {\n tools?.[context.toolName]?.streamCall?.(reader, {\n toolCallId: context.toolCallId,\n abortSignal,\n human: (payload: unknown) => human(context.toolCallId, payload),\n });\n}\n\nexport async function unstable_runPendingTools(\n message: AssistantMessage,\n tools: Record<string, Tool> | undefined,\n abortSignal: AbortSignal,\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n) {\n const toolCallPromises = message.parts\n .filter((part) => part.type === \"tool-call\")\n .map(async (part) => {\n const promiseOrUndefined = getToolResponse(\n tools,\n abortSignal,\n part,\n human ??\n (async () => {\n throw new Error(\n \"Tool human input is not supported in this context\",\n );\n }),\n );\n if (promiseOrUndefined) {\n const result = await promiseOrUndefined;\n return {\n toolCallId: part.toolCallId,\n result,\n };\n }\n return null;\n });\n\n const toolCallResults = (await Promise.all(toolCallPromises)).filter(\n (result) => result !== null,\n ) as { toolCallId: string; result: ToolResponse<ReadonlyJSONValue> }[];\n\n if (toolCallResults.length === 0) {\n return message;\n }\n\n const toolCallResultsById = toolCallResults.reduce(\n (acc, { toolCallId, result }) => {\n acc[toolCallId] = result;\n return acc;\n },\n {} as Record<string, ToolResponse<ReadonlyJSONValue>>,\n );\n\n const updatedParts = message.parts.map((p) => {\n if (p.type === \"tool-call\") {\n const toolResponse = toolCallResultsById[p.toolCallId];\n if (toolResponse) {\n return {\n ...p,\n state: \"result\" as const,\n ...(toolResponse.artifact !== undefined\n ? { artifact: toolResponse.artifact }\n : {}),\n ...(toolResponse.modelContent !== undefined\n ? { modelContent: toolResponse.modelContent }\n : {}),\n result: toolResponse.result as ReadonlyJSONValue,\n isError: toolResponse.isError,\n };\n }\n }\n return p;\n });\n\n return {\n ...message,\n parts: updatedParts,\n content: updatedParts,\n };\n}\n\nexport type ToolResultStreamOptions = {\n /** Called immediately before a frontend tool's `execute` function runs. */\n onExecutionStart?: (toolCallId: string, toolName: string) => void;\n /** Called after frontend tool execution finishes or fails. */\n onExecutionEnd?: (toolCallId: string, toolName: string) => void;\n};\n\n/**\n * Transform stream that executes frontend tools and appends tool results.\n *\n * The transform watches streamed tool-call arguments, runs the matching\n * frontend tool once its arguments are complete, and emits a result chunk for\n * the tool call. Backend and human tools pass through according to their tool\n * definition.\n *\n * @param tools Tool registry or function returning the current registry.\n * @param abortSignal Signal, or signal getter, used for the current run.\n * @param human Callback used to resolve human-tool requests from UI input.\n * @param options Optional execution lifecycle callbacks.\n */\nexport function toolResultStream(\n tools:\n | Record<string, Tool>\n | (() => Record<string, Tool> | undefined)\n | undefined,\n abortSignal: AbortSignal | (() => AbortSignal),\n human: (toolCallId: string, payload: unknown) => Promise<unknown>,\n options?: ToolResultStreamOptions,\n) {\n const toolsFn = typeof tools === \"function\" ? tools : () => tools;\n const abortSignalFn =\n typeof abortSignal === \"function\" ? abortSignal : () => abortSignal;\n return new ToolExecutionStream({\n execute: (toolCall) =>\n getToolResponse(toolsFn(), abortSignalFn(), toolCall, human),\n streamCall: ({ reader, ...context }) =>\n getToolStreamResponse(toolsFn(), abortSignalFn(), reader, context, human),\n onExecutionStart: options?.onExecutionStart,\n onExecutionEnd: options?.onExecutionEnd,\n });\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantTransformStream.d.ts","names":[],"sources":["../../../../src/core/utils/stream/AssistantTransformStream.ts"],"mappings":";;;KAMK,qCACH,YAAY,qCACF;KAEP,qCACH,YAAY,qCACF;KAEP,sCAAsC,MACzC,OAAO,GACP,YAAY,qCACF;KAEP,qBAAqB;EACxB,QAAQ;EACR,QAAQ;EACR,YAAY,sCAAsC;;cAGvC,yBAAyB,WAAW,gBAC/C,GACA;
|
|
1
|
+
{"version":3,"file":"AssistantTransformStream.d.ts","names":[],"sources":["../../../../src/core/utils/stream/AssistantTransformStream.ts"],"mappings":";;;KAMK,qCACH,YAAY,qCACF;KAEP,qCACH,YAAY,qCACF;KAEP,sCAAsC,MACzC,OAAO,GACP,YAAY,qCACF;KAEP,qBAAqB;EACxB,QAAQ;EACR,QAAQ;EACR,YAAY,sCAAsC;;cAGvC,yBAAyB,WAAW,gBAC/C,GACA;EAGE,YAAA,aAAa,qBAAqB,IAClC,mBAAmB,gBAAgB,IACnC,mBAAmB,gBAAgB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"PipeableTransformStream.d.ts","names":[],"sources":["../../../../src/core/utils/stream/PipeableTransformStream.ts"],"mappings":";cAAa,wBAAwB,GAAG,WAAW,gBAAgB,GAAG;
|
|
1
|
+
{"version":3,"file":"PipeableTransformStream.d.ts","names":[],"sources":["../../../../src/core/utils/stream/PipeableTransformStream.ts"],"mappings":";cAAa,wBAAwB,GAAG,WAAW,gBAAgB,GAAG;EACxD,YAAA,YAAY,UAAU,eAAe,OAAO,eAAe"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SSE.d.ts","names":[],"sources":["../../../../src/core/utils/stream/SSE.ts"],"mappings":";;
|
|
1
|
+
{"version":3,"file":"SSE.d.ts","names":[],"sources":["../../../../src/core/utils/stream/SSE.ts"],"mappings":";;cAOa,WAAW,WAAW,wBACjC,GACA,WAAW;kBAEK,SAAO;EAMvB,SAAO;;;cAiBI,WAAW,WAAW,wBACjC,WAAW,cACX"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { PipeableTransformStream } from "./PipeableTransformStream.js";
|
|
2
2
|
import { SSEEventDecoderStream } from "./SSEEventDecoderStream.js";
|
|
3
|
+
import sjson from "secure-json-parse";
|
|
3
4
|
//#region src/core/utils/stream/SSE.ts
|
|
4
5
|
var SSEEncoder = class SSEEncoder extends PipeableTransformStream {
|
|
5
6
|
static headers = new Headers({
|
|
@@ -18,9 +19,17 @@ var SSEDecoder = class extends PipeableTransformStream {
|
|
|
18
19
|
constructor() {
|
|
19
20
|
super((readable) => readable.pipeThrough(new TextDecoderStream()).pipeThrough(new SSEEventDecoderStream()).pipeThrough(new TransformStream({ transform(event, controller) {
|
|
20
21
|
switch (event.event) {
|
|
21
|
-
case "message":
|
|
22
|
-
|
|
22
|
+
case "message": {
|
|
23
|
+
let value;
|
|
24
|
+
try {
|
|
25
|
+
value = sjson.parse(event.data);
|
|
26
|
+
} catch {
|
|
27
|
+
console.warn(`Dropped invalid SSE message: ${event.data.slice(0, 200)}`);
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
controller.enqueue(value);
|
|
23
31
|
break;
|
|
32
|
+
}
|
|
24
33
|
default: throw new Error(`Unknown SSE event type: ${event.event}`);
|
|
25
34
|
}
|
|
26
35
|
} })));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SSE.js","names":[],"sources":["../../../../src/core/utils/stream/SSE.ts"],"sourcesContent":["import { PipeableTransformStream } from \"./PipeableTransformStream\";\nimport {\n SSEEventDecoderStream,\n type PipelineSSEEvent,\n} from \"./SSEEventDecoderStream\";\n\nexport class SSEEncoder<T> extends PipeableTransformStream<\n T,\n Uint8Array<ArrayBuffer>\n> {\n static readonly headers = new Headers({\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n\n headers = SSEEncoder.headers;\n\n constructor() {\n super((readable) =>\n readable\n .pipeThrough(\n new TransformStream<T, string>({\n transform(chunk, controller) {\n controller.enqueue(`data: ${JSON.stringify(chunk)}\\n\\n`);\n },\n }),\n )\n .pipeThrough(new TextEncoderStream()),\n );\n }\n}\n\nexport class SSEDecoder<T> extends PipeableTransformStream<\n Uint8Array<ArrayBuffer>,\n T\n> {\n constructor() {\n super((readable) =>\n readable\n .pipeThrough(new TextDecoderStream())\n .pipeThrough(new SSEEventDecoderStream())\n .pipeThrough(\n new TransformStream<PipelineSSEEvent, T>({\n transform(event, controller) {\n switch (event.event) {\n case \"message\"
|
|
1
|
+
{"version":3,"file":"SSE.js","names":[],"sources":["../../../../src/core/utils/stream/SSE.ts"],"sourcesContent":["import sjson from \"secure-json-parse\";\nimport { PipeableTransformStream } from \"./PipeableTransformStream\";\nimport {\n SSEEventDecoderStream,\n type PipelineSSEEvent,\n} from \"./SSEEventDecoderStream\";\n\nexport class SSEEncoder<T> extends PipeableTransformStream<\n T,\n Uint8Array<ArrayBuffer>\n> {\n static readonly headers = new Headers({\n \"Content-Type\": \"text/event-stream\",\n \"Cache-Control\": \"no-cache\",\n Connection: \"keep-alive\",\n });\n\n headers = SSEEncoder.headers;\n\n constructor() {\n super((readable) =>\n readable\n .pipeThrough(\n new TransformStream<T, string>({\n transform(chunk, controller) {\n controller.enqueue(`data: ${JSON.stringify(chunk)}\\n\\n`);\n },\n }),\n )\n .pipeThrough(new TextEncoderStream()),\n );\n }\n}\n\nexport class SSEDecoder<T> extends PipeableTransformStream<\n Uint8Array<ArrayBuffer>,\n T\n> {\n constructor() {\n super((readable) =>\n readable\n .pipeThrough(new TextDecoderStream())\n .pipeThrough(new SSEEventDecoderStream())\n .pipeThrough(\n new TransformStream<PipelineSSEEvent, T>({\n transform(event, controller) {\n switch (event.event) {\n case \"message\": {\n let value;\n try {\n value = sjson.parse(event.data);\n } catch {\n console.warn(\n `Dropped invalid SSE message: ${event.data.slice(0, 200)}`,\n );\n break;\n }\n controller.enqueue(value);\n break;\n }\n default:\n throw new Error(`Unknown SSE event type: ${event.event}`);\n }\n },\n }),\n ),\n );\n }\n}\n"],"mappings":";;;;AAOA,IAAa,aAAb,MAAa,mBAAsB,wBAGjC;CACA,OAAgB,UAAU,IAAI,QAAQ;EACpC,gBAAgB;EAChB,iBAAiB;EACjB,YAAY;CACd,CAAC;CAED,UAAU,WAAW;CAErB,cAAc;EACZ,OAAO,aACL,SACG,YACC,IAAI,gBAA2B,EAC7B,UAAU,OAAO,YAAY;GAC3B,WAAW,QAAQ,SAAS,KAAK,UAAU,KAAK,EAAE,KAAK;EACzD,EACF,CAAC,CACH,CAAC,CACA,YAAY,IAAI,kBAAkB,CAAC,CACxC;CACF;AACF;AAEA,IAAa,aAAb,cAAmC,wBAGjC;CACA,cAAc;EACZ,OAAO,aACL,SACG,YAAY,IAAI,kBAAkB,CAAC,CAAC,CACpC,YAAY,IAAI,sBAAsB,CAAC,CAAC,CACxC,YACC,IAAI,gBAAqC,EACvC,UAAU,OAAO,YAAY;GAC3B,QAAQ,MAAM,OAAd;IACE,KAAK,WAAW;KACd,IAAI;KACJ,IAAI;MACF,QAAQ,MAAM,MAAM,MAAM,IAAI;KAChC,QAAQ;MACN,QAAQ,KACN,gCAAgC,MAAM,KAAK,MAAM,GAAG,GAAG,GACzD;MACA;KACF;KACA,WAAW,QAAQ,KAAK;KACxB;IACF;IACA,SACE,MAAM,IAAI,MAAM,2BAA2B,MAAM,OAAO;GAC5D;EACF,EACF,CAAC,CACH,CACJ;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SSEEventDecoder.d.ts","names":[],"sources":["../../../../src/core/utils/stream/SSEEventDecoder.ts"],"mappings":";KAAY;EACV;EACA;EACA;EACA;;cAGW;UACH;UACA;UACA;UACA;UACA;UACA;mBACS;
|
|
1
|
+
{"version":3,"file":"SSEEventDecoder.d.ts","names":[],"sources":["../../../../src/core/utils/stream/SSEEventDecoder.ts"],"mappings":";KAAY;EACV;EACA;EACA;EACA;;cAGW;UACH;UACA;UACA;UACA;UACA;UACA;mBACS;EAEL,YAAA;IAAY;;EAIxB,KAAK,eAAe;EAsBpB,SAAS;UAiBD;UA+BA;UAcA"}
|
|
@@ -3,6 +3,8 @@ import { AssistantStreamChunk } from "../../AssistantStreamChunk.js";
|
|
|
3
3
|
declare const createMergeStream: () => {
|
|
4
4
|
readable: ReadableStream<AssistantStreamChunk>;
|
|
5
5
|
isSealed(): boolean;
|
|
6
|
+
isCancelled(): boolean;
|
|
7
|
+
isErrored(): boolean;
|
|
6
8
|
seal(): void;
|
|
7
9
|
addStream(stream: ReadableStream<AssistantStreamChunk>): void;
|
|
8
10
|
enqueue(chunk: AssistantStreamChunk): void;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.d.ts","names":[],"sources":["../../../../src/core/utils/stream/merge.ts"],"mappings":";;cAQa
|
|
1
|
+
{"version":3,"file":"merge.d.ts","names":[],"sources":["../../../../src/core/utils/stream/merge.ts"],"mappings":";;cAQa;;;;;;EA2FS,UAAA,QAAA,eAAe;EAelB,QAAA,OAAA"}
|
|
@@ -3,11 +3,20 @@ import { promiseWithResolvers } from "../../../utils/promiseWithResolvers.js";
|
|
|
3
3
|
const createMergeStream = () => {
|
|
4
4
|
const list = [];
|
|
5
5
|
let sealed = false;
|
|
6
|
+
let cancelled = false;
|
|
7
|
+
let errored = false;
|
|
6
8
|
let controller;
|
|
7
9
|
let currentPull;
|
|
10
|
+
const cancelAllReaders = () => {
|
|
11
|
+
list.forEach((item) => {
|
|
12
|
+
item.reader.cancel().catch(() => void 0);
|
|
13
|
+
});
|
|
14
|
+
list.length = 0;
|
|
15
|
+
};
|
|
8
16
|
const handlePull = (item) => {
|
|
9
17
|
if (!item.promise) item.promise = item.reader.read().then(({ done, value }) => {
|
|
10
18
|
item.promise = void 0;
|
|
19
|
+
if (cancelled || errored) return;
|
|
11
20
|
if (done) {
|
|
12
21
|
list.splice(list.indexOf(item), 1);
|
|
13
22
|
if (sealed && list.length === 0) controller.close();
|
|
@@ -15,11 +24,10 @@ const createMergeStream = () => {
|
|
|
15
24
|
currentPull?.resolve();
|
|
16
25
|
currentPull = void 0;
|
|
17
26
|
}).catch((e) => {
|
|
27
|
+
if (cancelled || errored) return;
|
|
28
|
+
errored = true;
|
|
18
29
|
console.error(e);
|
|
19
|
-
|
|
20
|
-
item.reader.cancel();
|
|
21
|
-
});
|
|
22
|
-
list.length = 0;
|
|
30
|
+
cancelAllReaders();
|
|
23
31
|
controller.error(e);
|
|
24
32
|
currentPull?.reject(e);
|
|
25
33
|
currentPull = void 0;
|
|
@@ -38,20 +46,31 @@ const createMergeStream = () => {
|
|
|
38
46
|
return currentPull.promise;
|
|
39
47
|
},
|
|
40
48
|
cancel() {
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
cancelled = true;
|
|
50
|
+
cancelAllReaders();
|
|
51
|
+
currentPull?.resolve();
|
|
52
|
+
currentPull = void 0;
|
|
45
53
|
}
|
|
46
54
|
}),
|
|
47
55
|
isSealed() {
|
|
48
56
|
return sealed;
|
|
49
57
|
},
|
|
58
|
+
isCancelled() {
|
|
59
|
+
return cancelled;
|
|
60
|
+
},
|
|
61
|
+
isErrored() {
|
|
62
|
+
return errored;
|
|
63
|
+
},
|
|
50
64
|
seal() {
|
|
65
|
+
if (cancelled || errored) return;
|
|
51
66
|
sealed = true;
|
|
52
67
|
if (list.length === 0) controller.close();
|
|
53
68
|
},
|
|
54
69
|
addStream(stream) {
|
|
70
|
+
if (cancelled || errored) {
|
|
71
|
+
stream.cancel().catch(() => void 0);
|
|
72
|
+
return;
|
|
73
|
+
}
|
|
55
74
|
if (sealed) throw new Error("Cannot add streams after the run callback has settled.");
|
|
56
75
|
const item = { reader: stream.getReader() };
|
|
57
76
|
list.push(item);
|