assistant-stream 0.3.21 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/core/accumulators/assistant-message-accumulator.d.ts.map +1 -1
- package/dist/core/accumulators/assistant-message-accumulator.js +5 -0
- package/dist/core/accumulators/assistant-message-accumulator.js.map +1 -1
- package/dist/core/tool/ToolCallReader.d.ts +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/tool-types.d.ts +1 -1
- package/dist/core/tool/tool-types.d.ts.map +1 -1
- package/dist/core/utils/types.d.ts +12 -1
- package/dist/core/utils/types.d.ts.map +1 -1
- package/dist/index.d.ts +2 -2
- package/package.json +2 -2
- package/src/core/accumulators/assistant-message-accumulator.test.ts +51 -0
- package/src/core/accumulators/assistant-message-accumulator.ts +9 -0
- package/src/core/tool/ToolCallReader.ts +1 -1
- package/src/core/tool/tool-types.ts +1 -1
- package/src/core/utils/types.ts +14 -0
- package/src/index.ts +1 -0
- package/src/resumable/__tests__/integration.test.ts +12 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-message-accumulator.d.ts","names":[],"sources":["../../../src/core/accumulators/assistant-message-accumulator.ts"],"mappings":";;;;;cAmBa,oBAAA;EAAwB;AAAA;EAGnC,cAAA,GAAiB,iBAAA;AAAA,MACV,gBAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"assistant-message-accumulator.d.ts","names":[],"sources":["../../../src/core/accumulators/assistant-message-accumulator.ts"],"mappings":";;;;;cAmBa,oBAAA;EAAwB;AAAA;EAGnC,cAAA,GAAiB,iBAAA;AAAA,MACV,gBAAA;AAAA,cAiZI,2BAAA,SAAoC,eAAA,CAC/C,oBAAA,EACA,gBAAA;;IAGE,cAAA;IACA,QAAA;IACA;EAAA;IAEA,cAAA,GAAiB,gBAAA;IACjB,QAAA;IACA,OAAA,IAAW,KAAA;EAAA;AAAA"}
|
|
@@ -63,6 +63,7 @@ const handlePartStart = (message, chunk) => {
|
|
|
63
63
|
toolName: partInit.toolName,
|
|
64
64
|
argsText: "",
|
|
65
65
|
args: {},
|
|
66
|
+
timing: { startedAt: Date.now() },
|
|
66
67
|
...partInit.parentId && { parentId: partInit.parentId }
|
|
67
68
|
};
|
|
68
69
|
return {
|
|
@@ -159,6 +160,10 @@ const handleResult = (message, chunk) => {
|
|
|
159
160
|
if (part.type === "tool-call") return {
|
|
160
161
|
...part,
|
|
161
162
|
state: "result",
|
|
163
|
+
...part.timing !== void 0 ? { timing: {
|
|
164
|
+
...part.timing,
|
|
165
|
+
completedAt: part.timing.completedAt ?? Date.now()
|
|
166
|
+
} } : {},
|
|
162
167
|
...chunk.artifact !== void 0 ? { artifact: chunk.artifact } : {},
|
|
163
168
|
result: chunk.result,
|
|
164
169
|
isError: chunk.isError ?? false,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"assistant-message-accumulator.js","names":["unhandledType"],"sources":["../../../src/core/accumulators/assistant-message-accumulator.ts"],"sourcesContent":["import type { AssistantStreamChunk } from \"../AssistantStreamChunk\";\nimport { generateId } from \"../utils/generateId\";\nimport { parsePartialJsonObject } from \"../../utils/json/parse-partial-json-object\";\nimport type {\n AssistantMessage,\n AssistantMessageStatus,\n AssistantMessageTiming,\n TextPart,\n ToolCallPart,\n SourcePart,\n AssistantMessagePart,\n ReasoningPart,\n FilePart,\n DataPart,\n} from \"../utils/types\";\nimport { ObjectStreamAccumulator } from \"../object/ObjectStreamAccumulator\";\nimport type { ReadonlyJSONValue } from \"../../utils\";\nimport { TimingTracker } from \"./TimingTracker\";\n\nexport const createInitialMessage = ({\n unstable_state = null,\n}: {\n unstable_state?: ReadonlyJSONValue;\n} = {}): AssistantMessage => ({\n role: \"assistant\",\n status: { type: \"running\" },\n parts: [],\n get content() {\n return this.parts;\n },\n metadata: {\n unstable_state,\n unstable_data: [],\n unstable_annotations: [],\n steps: [],\n custom: {},\n },\n});\n\nconst updatePartForPath = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk,\n updater: (part: AssistantMessagePart) => AssistantMessagePart,\n): AssistantMessage => {\n if (message.parts.length === 0) {\n throw new Error(\"No parts available to update.\");\n }\n\n if (chunk.path.length !== 1)\n throw new Error(\"Nested paths are not supported yet.\");\n\n const partIndex = chunk.path[0]!;\n const updatedPart = updater(message.parts[partIndex]!);\n return {\n ...message,\n parts: [\n ...message.parts.slice(0, partIndex),\n updatedPart,\n ...message.parts.slice(partIndex + 1),\n ],\n get content() {\n return this.parts;\n },\n };\n};\n\nconst handlePartStart = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { readonly type: \"part-start\" },\n): AssistantMessage => {\n const partInit = chunk.part;\n if (partInit.type === \"text\" || partInit.type === \"reasoning\") {\n const newTextPart: TextPart | ReasoningPart = {\n type: partInit.type,\n text: \"\",\n status: { type: \"running\" },\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newTextPart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"tool-call\") {\n const newToolCallPart: ToolCallPart = {\n type: \"tool-call\",\n state: \"partial-call\",\n status: { type: \"running\", isArgsComplete: false },\n toolCallId: partInit.toolCallId,\n toolName: partInit.toolName,\n argsText: \"\",\n args: {},\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newToolCallPart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"source\") {\n const newSourcePart: SourcePart = {\n type: \"source\",\n sourceType: partInit.sourceType,\n id: partInit.id,\n url: partInit.url,\n ...(partInit.title ? { title: partInit.title } : undefined),\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newSourcePart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"file\") {\n const newFilePart: FilePart = {\n type: \"file\",\n mimeType: partInit.mimeType,\n data: partInit.data,\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newFilePart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"data\") {\n const newDataPart: DataPart = {\n type: \"data\",\n name: partInit.name,\n data: partInit.data,\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newDataPart],\n get content() {\n return this.parts;\n },\n };\n } else {\n throw new Error(`Unsupported part type: ${partInit.type}`);\n }\n};\n\nconst handleToolCallArgsTextFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & {\n readonly type: \"tool-call-args-text-finish\";\n },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => {\n if (part.type !== \"tool-call\") {\n throw new Error(\"Last is not a tool call\");\n }\n\n // TODO this should never be hit; this happens if args-text-finish is emitted after result\n if (part.state !== \"partial-call\") return part;\n // throw new Error(\"Last is not a partial call\");\n\n return {\n ...part,\n state: \"call\",\n };\n });\n};\n\nconst handlePartFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { readonly type: \"part-finish\" },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => ({\n ...part,\n status: { type: \"complete\", reason: \"unknown\" },\n }));\n};\n\nconst handleTextDelta = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"text-delta\" },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => {\n if (part.type === \"text\" || part.type === \"reasoning\") {\n return { ...part, text: part.text + chunk.textDelta };\n } else if (part.type === \"tool-call\") {\n const newArgsText = part.argsText + chunk.textDelta;\n\n // Fall back to existing args if parsing fails\n const newArgs = parsePartialJsonObject(newArgsText) ?? part.args;\n\n return { ...part, argsText: newArgsText, args: newArgs };\n } else {\n throw new Error(\n \"text-delta received but part is neither text nor tool-call\",\n );\n }\n });\n};\n\nconst handleResult = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"result\" },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => {\n if (part.type === \"tool-call\") {\n return {\n ...part,\n state: \"result\",\n ...(chunk.artifact !== undefined ? { artifact: chunk.artifact } : {}),\n result: chunk.result,\n isError: chunk.isError ?? false,\n ...(chunk.modelContent !== undefined\n ? { modelContent: chunk.modelContent }\n : {}),\n ...(chunk.messages !== undefined ? { messages: chunk.messages } : {}),\n status: { type: \"complete\", reason: \"stop\" },\n };\n } else {\n throw new Error(\"Result chunk received but part is not a tool-call\");\n }\n });\n};\n\nconst handleMessageFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"message-finish\" },\n): AssistantMessage => {\n // avoid edge case where providers send finish chunks that overwrite message error status (issue #2181)\n if (\n message.status?.type === \"incomplete\" &&\n message.status?.reason === \"error\"\n ) {\n return message;\n }\n\n const newStatus = getStatus(chunk);\n return { ...message, status: newStatus };\n};\n\nconst getStatus = (\n chunk:\n | (AssistantStreamChunk & { type: \"message-finish\" })\n | (AssistantStreamChunk & { type: \"step-finish\" }),\n): AssistantMessageStatus => {\n if (chunk.finishReason === \"tool-calls\") {\n return {\n type: \"requires-action\",\n reason: \"tool-calls\",\n };\n } else if (\n chunk.finishReason === \"stop\" ||\n chunk.finishReason === \"unknown\"\n ) {\n return {\n type: \"complete\",\n reason: chunk.finishReason,\n };\n } else {\n return {\n type: \"incomplete\",\n reason: chunk.finishReason,\n };\n }\n};\n\nconst handleAnnotations = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"annotations\" },\n): AssistantMessage => {\n return {\n ...message,\n metadata: {\n ...message.metadata,\n unstable_annotations: [\n ...message.metadata.unstable_annotations,\n ...chunk.annotations,\n ],\n },\n };\n};\n\nconst handleData = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"data\" },\n): AssistantMessage => {\n return {\n ...message,\n metadata: {\n ...message.metadata,\n unstable_data: [...message.metadata.unstable_data, ...chunk.data],\n },\n };\n};\n\nconst handleStepStart = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"step-start\" },\n): AssistantMessage => {\n return {\n ...message,\n metadata: {\n ...message.metadata,\n steps: [\n ...message.metadata.steps,\n { state: \"started\", messageId: chunk.messageId },\n ],\n },\n };\n};\n\nconst handleStepFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"step-finish\" },\n): AssistantMessage => {\n const steps = message.metadata.steps.slice();\n const lastIndex = steps.length - 1;\n\n // Check if the previous step is a step-start (has state \"started\")\n if (steps.length > 0 && steps[lastIndex]?.state === \"started\") {\n steps[lastIndex] = {\n ...steps[lastIndex],\n state: \"finished\",\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n isContinued: chunk.isContinued,\n };\n } else {\n // If no previous step-start exists, append a finished step\n steps.push({\n state: \"finished\",\n messageId: generateId(),\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n isContinued: chunk.isContinued,\n });\n }\n\n return {\n ...message,\n metadata: {\n ...message.metadata,\n steps,\n },\n };\n};\n\nconst handleErrorChunk = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"error\" },\n): AssistantMessage => {\n return {\n ...message,\n status: { type: \"incomplete\", reason: \"error\", error: chunk.error },\n };\n};\n\nconst handleUpdateState = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"update-state\" },\n): AssistantMessage => {\n const acc = new ObjectStreamAccumulator(message.metadata.unstable_state);\n acc.append(chunk.operations);\n\n return {\n ...message,\n metadata: {\n ...message.metadata,\n unstable_state: acc.state,\n },\n };\n};\n\nconst computeTiming = (\n tracker: TimingTracker,\n message: AssistantMessage,\n): AssistantMessageTiming => {\n let outputTokens = 0;\n for (const step of message.metadata.steps) {\n if (step.state === \"finished\" && step.usage) {\n outputTokens += step.usage.outputTokens;\n }\n }\n\n let totalText = \"\";\n for (const part of message.parts) {\n if (part.type === \"text\" || part.type === \"reasoning\") {\n totalText += part.text;\n }\n }\n\n return tracker.getTiming(\n outputTokens > 0 ? outputTokens : undefined,\n totalText || undefined,\n );\n};\n\nconst throttleCallback = (callback: () => void) => {\n let hasScheduled = false;\n return () => {\n if (hasScheduled) return;\n hasScheduled = true;\n queueMicrotask(() => {\n hasScheduled = false;\n callback();\n });\n };\n};\n\nexport class AssistantMessageAccumulator extends TransformStream<\n AssistantStreamChunk,\n AssistantMessage\n> {\n constructor({\n initialMessage,\n throttle,\n onError,\n }: {\n initialMessage?: AssistantMessage;\n throttle?: boolean;\n onError?: (error: string) => void;\n } = {}) {\n let message = initialMessage ?? createInitialMessage();\n const tracker = new TimingTracker();\n let controller:\n | TransformStreamDefaultController<AssistantMessage>\n | undefined;\n const emitChunk = throttle\n ? throttleCallback(() => {\n controller?.enqueue(message);\n })\n : () => {\n controller?.enqueue(message);\n };\n super({\n start(c) {\n controller = c;\n },\n transform(chunk) {\n tracker.recordChunk();\n const type = chunk.type;\n switch (type) {\n case \"part-start\":\n message = handlePartStart(message, chunk);\n if (chunk.part.type === \"tool-call\") {\n tracker.recordToolCallStart(chunk.part.toolCallId);\n }\n break;\n\n case \"tool-call-args-text-finish\":\n message = handleToolCallArgsTextFinish(message, chunk);\n break;\n\n case \"part-finish\":\n message = handlePartFinish(message, chunk);\n break;\n\n case \"text-delta\":\n message = handleTextDelta(message, chunk);\n tracker.recordFirstToken();\n break;\n case \"result\":\n message = handleResult(message, chunk);\n break;\n case \"message-finish\":\n message = handleMessageFinish(message, chunk);\n break;\n case \"annotations\":\n message = handleAnnotations(message, chunk);\n break;\n case \"data\":\n message = handleData(message, chunk);\n break;\n case \"step-start\":\n message = handleStepStart(message, chunk);\n break;\n case \"step-finish\":\n message = handleStepFinish(message, chunk);\n break;\n case \"error\":\n message = handleErrorChunk(message, chunk);\n onError?.(chunk.error);\n break;\n case \"update-state\":\n message = handleUpdateState(message, chunk);\n break;\n default: {\n const unhandledType: never = type;\n throw new Error(`Unsupported chunk type: ${unhandledType}`);\n }\n }\n\n if (message.status.type !== \"running\") {\n message = {\n ...message,\n metadata: {\n ...message.metadata,\n timing: computeTiming(tracker, message),\n },\n };\n }\n\n emitChunk();\n },\n flush(controller) {\n if (message.status?.type === \"running\") {\n // Check if there are any tool calls that require action\n const requiresAction =\n message.parts?.some(\n (part) =>\n part.type === \"tool-call\" &&\n (part.state === \"call\" || part.state === \"partial-call\") &&\n part.result === undefined,\n ) ?? false;\n message = handleMessageFinish(message, {\n type: \"message-finish\",\n path: [],\n finishReason: requiresAction ? \"tool-calls\" : \"unknown\",\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n });\n\n message = {\n ...message,\n metadata: {\n ...message.metadata,\n timing: computeTiming(tracker, message),\n },\n };\n\n controller.enqueue(message);\n }\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"assistant-message-accumulator.js","names":["unhandledType"],"sources":["../../../src/core/accumulators/assistant-message-accumulator.ts"],"sourcesContent":["import type { AssistantStreamChunk } from \"../AssistantStreamChunk\";\nimport { generateId } from \"../utils/generateId\";\nimport { parsePartialJsonObject } from \"../../utils/json/parse-partial-json-object\";\nimport type {\n AssistantMessage,\n AssistantMessageStatus,\n AssistantMessageTiming,\n TextPart,\n ToolCallPart,\n SourcePart,\n AssistantMessagePart,\n ReasoningPart,\n FilePart,\n DataPart,\n} from \"../utils/types\";\nimport { ObjectStreamAccumulator } from \"../object/ObjectStreamAccumulator\";\nimport type { ReadonlyJSONValue } from \"../../utils\";\nimport { TimingTracker } from \"./TimingTracker\";\n\nexport const createInitialMessage = ({\n unstable_state = null,\n}: {\n unstable_state?: ReadonlyJSONValue;\n} = {}): AssistantMessage => ({\n role: \"assistant\",\n status: { type: \"running\" },\n parts: [],\n get content() {\n return this.parts;\n },\n metadata: {\n unstable_state,\n unstable_data: [],\n unstable_annotations: [],\n steps: [],\n custom: {},\n },\n});\n\nconst updatePartForPath = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk,\n updater: (part: AssistantMessagePart) => AssistantMessagePart,\n): AssistantMessage => {\n if (message.parts.length === 0) {\n throw new Error(\"No parts available to update.\");\n }\n\n if (chunk.path.length !== 1)\n throw new Error(\"Nested paths are not supported yet.\");\n\n const partIndex = chunk.path[0]!;\n const updatedPart = updater(message.parts[partIndex]!);\n return {\n ...message,\n parts: [\n ...message.parts.slice(0, partIndex),\n updatedPart,\n ...message.parts.slice(partIndex + 1),\n ],\n get content() {\n return this.parts;\n },\n };\n};\n\nconst handlePartStart = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { readonly type: \"part-start\" },\n): AssistantMessage => {\n const partInit = chunk.part;\n if (partInit.type === \"text\" || partInit.type === \"reasoning\") {\n const newTextPart: TextPart | ReasoningPart = {\n type: partInit.type,\n text: \"\",\n status: { type: \"running\" },\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newTextPart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"tool-call\") {\n const newToolCallPart: ToolCallPart = {\n type: \"tool-call\",\n state: \"partial-call\",\n status: { type: \"running\", isArgsComplete: false },\n toolCallId: partInit.toolCallId,\n toolName: partInit.toolName,\n argsText: \"\",\n args: {},\n timing: { startedAt: Date.now() },\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newToolCallPart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"source\") {\n const newSourcePart: SourcePart = {\n type: \"source\",\n sourceType: partInit.sourceType,\n id: partInit.id,\n url: partInit.url,\n ...(partInit.title ? { title: partInit.title } : undefined),\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newSourcePart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"file\") {\n const newFilePart: FilePart = {\n type: \"file\",\n mimeType: partInit.mimeType,\n data: partInit.data,\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newFilePart],\n get content() {\n return this.parts;\n },\n };\n } else if (partInit.type === \"data\") {\n const newDataPart: DataPart = {\n type: \"data\",\n name: partInit.name,\n data: partInit.data,\n ...(partInit.parentId && { parentId: partInit.parentId }),\n };\n return {\n ...message,\n parts: [...message.parts, newDataPart],\n get content() {\n return this.parts;\n },\n };\n } else {\n throw new Error(`Unsupported part type: ${partInit.type}`);\n }\n};\n\nconst handleToolCallArgsTextFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & {\n readonly type: \"tool-call-args-text-finish\";\n },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => {\n if (part.type !== \"tool-call\") {\n throw new Error(\"Last is not a tool call\");\n }\n\n // TODO this should never be hit; this happens if args-text-finish is emitted after result\n if (part.state !== \"partial-call\") return part;\n // throw new Error(\"Last is not a partial call\");\n\n return {\n ...part,\n state: \"call\",\n };\n });\n};\n\nconst handlePartFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { readonly type: \"part-finish\" },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => ({\n ...part,\n status: { type: \"complete\", reason: \"unknown\" },\n }));\n};\n\nconst handleTextDelta = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"text-delta\" },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => {\n if (part.type === \"text\" || part.type === \"reasoning\") {\n return { ...part, text: part.text + chunk.textDelta };\n } else if (part.type === \"tool-call\") {\n const newArgsText = part.argsText + chunk.textDelta;\n\n // Fall back to existing args if parsing fails\n const newArgs = parsePartialJsonObject(newArgsText) ?? part.args;\n\n return { ...part, argsText: newArgsText, args: newArgs };\n } else {\n throw new Error(\n \"text-delta received but part is neither text nor tool-call\",\n );\n }\n });\n};\n\nconst handleResult = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"result\" },\n): AssistantMessage => {\n return updatePartForPath(message, chunk, (part) => {\n if (part.type === \"tool-call\") {\n return {\n ...part,\n state: \"result\",\n ...(part.timing !== undefined\n ? {\n timing: {\n ...part.timing,\n completedAt: part.timing.completedAt ?? Date.now(),\n },\n }\n : {}),\n ...(chunk.artifact !== undefined ? { artifact: chunk.artifact } : {}),\n result: chunk.result,\n isError: chunk.isError ?? false,\n ...(chunk.modelContent !== undefined\n ? { modelContent: chunk.modelContent }\n : {}),\n ...(chunk.messages !== undefined ? { messages: chunk.messages } : {}),\n status: { type: \"complete\", reason: \"stop\" },\n };\n } else {\n throw new Error(\"Result chunk received but part is not a tool-call\");\n }\n });\n};\n\nconst handleMessageFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"message-finish\" },\n): AssistantMessage => {\n // avoid edge case where providers send finish chunks that overwrite message error status (issue #2181)\n if (\n message.status?.type === \"incomplete\" &&\n message.status?.reason === \"error\"\n ) {\n return message;\n }\n\n const newStatus = getStatus(chunk);\n return { ...message, status: newStatus };\n};\n\nconst getStatus = (\n chunk:\n | (AssistantStreamChunk & { type: \"message-finish\" })\n | (AssistantStreamChunk & { type: \"step-finish\" }),\n): AssistantMessageStatus => {\n if (chunk.finishReason === \"tool-calls\") {\n return {\n type: \"requires-action\",\n reason: \"tool-calls\",\n };\n } else if (\n chunk.finishReason === \"stop\" ||\n chunk.finishReason === \"unknown\"\n ) {\n return {\n type: \"complete\",\n reason: chunk.finishReason,\n };\n } else {\n return {\n type: \"incomplete\",\n reason: chunk.finishReason,\n };\n }\n};\n\nconst handleAnnotations = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"annotations\" },\n): AssistantMessage => {\n return {\n ...message,\n metadata: {\n ...message.metadata,\n unstable_annotations: [\n ...message.metadata.unstable_annotations,\n ...chunk.annotations,\n ],\n },\n };\n};\n\nconst handleData = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"data\" },\n): AssistantMessage => {\n return {\n ...message,\n metadata: {\n ...message.metadata,\n unstable_data: [...message.metadata.unstable_data, ...chunk.data],\n },\n };\n};\n\nconst handleStepStart = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"step-start\" },\n): AssistantMessage => {\n return {\n ...message,\n metadata: {\n ...message.metadata,\n steps: [\n ...message.metadata.steps,\n { state: \"started\", messageId: chunk.messageId },\n ],\n },\n };\n};\n\nconst handleStepFinish = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"step-finish\" },\n): AssistantMessage => {\n const steps = message.metadata.steps.slice();\n const lastIndex = steps.length - 1;\n\n // Check if the previous step is a step-start (has state \"started\")\n if (steps.length > 0 && steps[lastIndex]?.state === \"started\") {\n steps[lastIndex] = {\n ...steps[lastIndex],\n state: \"finished\",\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n isContinued: chunk.isContinued,\n };\n } else {\n // If no previous step-start exists, append a finished step\n steps.push({\n state: \"finished\",\n messageId: generateId(),\n finishReason: chunk.finishReason,\n usage: chunk.usage,\n isContinued: chunk.isContinued,\n });\n }\n\n return {\n ...message,\n metadata: {\n ...message.metadata,\n steps,\n },\n };\n};\n\nconst handleErrorChunk = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"error\" },\n): AssistantMessage => {\n return {\n ...message,\n status: { type: \"incomplete\", reason: \"error\", error: chunk.error },\n };\n};\n\nconst handleUpdateState = (\n message: AssistantMessage,\n chunk: AssistantStreamChunk & { type: \"update-state\" },\n): AssistantMessage => {\n const acc = new ObjectStreamAccumulator(message.metadata.unstable_state);\n acc.append(chunk.operations);\n\n return {\n ...message,\n metadata: {\n ...message.metadata,\n unstable_state: acc.state,\n },\n };\n};\n\nconst computeTiming = (\n tracker: TimingTracker,\n message: AssistantMessage,\n): AssistantMessageTiming => {\n let outputTokens = 0;\n for (const step of message.metadata.steps) {\n if (step.state === \"finished\" && step.usage) {\n outputTokens += step.usage.outputTokens;\n }\n }\n\n let totalText = \"\";\n for (const part of message.parts) {\n if (part.type === \"text\" || part.type === \"reasoning\") {\n totalText += part.text;\n }\n }\n\n return tracker.getTiming(\n outputTokens > 0 ? outputTokens : undefined,\n totalText || undefined,\n );\n};\n\nconst throttleCallback = (callback: () => void) => {\n let hasScheduled = false;\n return () => {\n if (hasScheduled) return;\n hasScheduled = true;\n queueMicrotask(() => {\n hasScheduled = false;\n callback();\n });\n };\n};\n\nexport class AssistantMessageAccumulator extends TransformStream<\n AssistantStreamChunk,\n AssistantMessage\n> {\n constructor({\n initialMessage,\n throttle,\n onError,\n }: {\n initialMessage?: AssistantMessage;\n throttle?: boolean;\n onError?: (error: string) => void;\n } = {}) {\n let message = initialMessage ?? createInitialMessage();\n const tracker = new TimingTracker();\n let controller:\n | TransformStreamDefaultController<AssistantMessage>\n | undefined;\n const emitChunk = throttle\n ? throttleCallback(() => {\n controller?.enqueue(message);\n })\n : () => {\n controller?.enqueue(message);\n };\n super({\n start(c) {\n controller = c;\n },\n transform(chunk) {\n tracker.recordChunk();\n const type = chunk.type;\n switch (type) {\n case \"part-start\":\n message = handlePartStart(message, chunk);\n if (chunk.part.type === \"tool-call\") {\n tracker.recordToolCallStart(chunk.part.toolCallId);\n }\n break;\n\n case \"tool-call-args-text-finish\":\n message = handleToolCallArgsTextFinish(message, chunk);\n break;\n\n case \"part-finish\":\n message = handlePartFinish(message, chunk);\n break;\n\n case \"text-delta\":\n message = handleTextDelta(message, chunk);\n tracker.recordFirstToken();\n break;\n case \"result\":\n message = handleResult(message, chunk);\n break;\n case \"message-finish\":\n message = handleMessageFinish(message, chunk);\n break;\n case \"annotations\":\n message = handleAnnotations(message, chunk);\n break;\n case \"data\":\n message = handleData(message, chunk);\n break;\n case \"step-start\":\n message = handleStepStart(message, chunk);\n break;\n case \"step-finish\":\n message = handleStepFinish(message, chunk);\n break;\n case \"error\":\n message = handleErrorChunk(message, chunk);\n onError?.(chunk.error);\n break;\n case \"update-state\":\n message = handleUpdateState(message, chunk);\n break;\n default: {\n const unhandledType: never = type;\n throw new Error(`Unsupported chunk type: ${unhandledType}`);\n }\n }\n\n if (message.status.type !== \"running\") {\n message = {\n ...message,\n metadata: {\n ...message.metadata,\n timing: computeTiming(tracker, message),\n },\n };\n }\n\n emitChunk();\n },\n flush(controller) {\n if (message.status?.type === \"running\") {\n // Check if there are any tool calls that require action\n const requiresAction =\n message.parts?.some(\n (part) =>\n part.type === \"tool-call\" &&\n (part.state === \"call\" || part.state === \"partial-call\") &&\n part.result === undefined,\n ) ?? false;\n message = handleMessageFinish(message, {\n type: \"message-finish\",\n path: [],\n finishReason: requiresAction ? \"tool-calls\" : \"unknown\",\n usage: {\n inputTokens: 0,\n outputTokens: 0,\n },\n });\n\n message = {\n ...message,\n metadata: {\n ...message.metadata,\n timing: computeTiming(tracker, message),\n },\n };\n\n controller.enqueue(message);\n }\n },\n });\n }\n}\n"],"mappings":"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"}
|
|
@@ -14,7 +14,7 @@ declare class ToolCallArgsReaderImpl<T extends ReadonlyJSONObject> implements To
|
|
|
14
14
|
get<PathT extends TypePath<T>>(...fieldPath: PathT): Promise<TypeAtPath<T, PathT>>;
|
|
15
15
|
streamValues<PathT extends TypePath<T>>(...fieldPath: PathT): AsyncIterableStream<DeepPartial<TypeAtPath<T, PathT>>>;
|
|
16
16
|
streamText<PathT extends TypePath<T>>(...fieldPath: PathT): TypeAtPath<T, PathT> extends string & (infer U) ? AsyncIterableStream<U> : never;
|
|
17
|
-
forEach<PathT extends TypePath<T>>(...fieldPath: PathT): TypeAtPath<T, PathT
|
|
17
|
+
forEach<PathT extends TypePath<T>>(...fieldPath: PathT): NonNullable<TypeAtPath<T, PathT>> extends Array<infer U> ? AsyncIterableStream<U> : never;
|
|
18
18
|
}
|
|
19
19
|
declare class ToolCallResponseReaderImpl<TResult extends ReadonlyJSONValue> implements ToolCallResponseReader<TResult> {
|
|
20
20
|
private readonly promise;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ToolCallReader.d.ts","names":[],"sources":["../../../src/core/tool/ToolCallReader.ts"],"mappings":";;;;;;cA0Qa,sBAAA,WACD,kBAAA,aACC,kBAAA,CAAmB,CAAA;EAAA,QACtB,aAAA;EAAA,QACA,OAAA;EAAA,QACA,IAAA;EAAA,QACA,QAAA;cAEI,aAAA,EAAe,cAAA;EAAA,QAKb,aAAA;EA+Bd,GAAA,eAAkB,QAAA,CAAS,CAAA,MACtB,SAAA,EAAW,KAAA,GACb,OAAA,CAAQ,UAAA,CAAW,CAAA,EAAG,KAAA;EAiCzB,YAAA,eAA2B,QAAA,CAAS,CAAA,MAC/B,SAAA,EAAW,KAAA,GACb,mBAAA,CAAoB,WAAA,CAAY,UAAA,CAAW,CAAA,EAAG,KAAA;EA4BjD,UAAA,eAAyB,QAAA,CAAS,CAAA,MAC7B,SAAA,EAAW,KAAA,GACb,UAAA,CAAW,CAAA,EAAG,KAAA,+BACb,mBAAA,CAAoB,CAAA;EA6BxB,OAAA,eAAsB,QAAA,CAAS,CAAA,MAC1B,SAAA,EAAW,KAAA,GACb,UAAA,CAAW,CAAA,EAAG,KAAA,
|
|
1
|
+
{"version":3,"file":"ToolCallReader.d.ts","names":[],"sources":["../../../src/core/tool/ToolCallReader.ts"],"mappings":";;;;;;cA0Qa,sBAAA,WACD,kBAAA,aACC,kBAAA,CAAmB,CAAA;EAAA,QACtB,aAAA;EAAA,QACA,OAAA;EAAA,QACA,IAAA;EAAA,QACA,QAAA;cAEI,aAAA,EAAe,cAAA;EAAA,QAKb,aAAA;EA+Bd,GAAA,eAAkB,QAAA,CAAS,CAAA,MACtB,SAAA,EAAW,KAAA,GACb,OAAA,CAAQ,UAAA,CAAW,CAAA,EAAG,KAAA;EAiCzB,YAAA,eAA2B,QAAA,CAAS,CAAA,MAC/B,SAAA,EAAW,KAAA,GACb,mBAAA,CAAoB,WAAA,CAAY,UAAA,CAAW,CAAA,EAAG,KAAA;EA4BjD,UAAA,eAAyB,QAAA,CAAS,CAAA,MAC7B,SAAA,EAAW,KAAA,GACb,UAAA,CAAW,CAAA,EAAG,KAAA,+BACb,mBAAA,CAAoB,CAAA;EA6BxB,OAAA,eAAsB,QAAA,CAAS,CAAA,MAC1B,SAAA,EAAW,KAAA,GACb,WAAA,CAAY,UAAA,CAAW,CAAA,EAAG,KAAA,WAAgB,KAAA,YACzC,mBAAA,CAAoB,CAAA;AAAA;AAAA,cA8Bb,0BAAA,iBACK,iBAAA,aACL,sBAAA,CAAuB,OAAA;EAAA,iBACL,OAAA;cAAA,OAAA,EAAS,OAAA,CAAQ,YAAA,CAAa,OAAA;EAEpD,GAAA,IAAG,OAAA,CAAA,YAAA,CAAA,OAAA;AAAA;AAAA,cAKC,kBAAA,eACG,kBAAA,kBACE,iBAAA,aACL,cAAA,CAAe,KAAA,EAAO,OAAA;EAAA,SACjB,IAAA,EAAM,sBAAA,CAAuB,KAAA;EAAA,SAC7B,QAAA,EAAU,0BAAA,CAA2B,OAAA;EAAA,iBACpC,QAAA;EAAA,iBACA,OAAA;EAEV,QAAA;;EAYD,mBAAA,CAAoB,IAAA,WAAe,OAAA;EAanC,cAAA,IAAkB,OAAA;EAWxB,WAAA,CAAY,KAAA,EAAO,YAAA,CAAa,OAAA;EAIhC,MAAA"}
|
|
@@ -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 ): 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":";;;;AAqBA,SAAS,SAAY,KAAQ,WAAyC;CACpE,IAAI,UAAmB;CACvB,KAAK,MAAM,OAAO,WAAW;EAC3B,IAAI,YAAY,KAAA,KAAa,YAAY,MACvC;EAEF,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAQA,IAAM,YAAN,MAA6C;CAC3C;CACA;CACA,WAAmB;CACnB;CAEA,YACE,SACA,QACA,WACA;EACA,KAAK,UAAU;EACf,KAAK,SAAS;EACd,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GAEF,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;IAChD,IAAI,UAAU,KAAA,GAAW;KACvB,KAAK,QAAQ,KAAe;KAC5B,KAAK,QAAQ;IACf;GACF;EACF,SAAS,GAAG;GACV,KAAK,OAAO,CAAC;GACb,KAAK,QAAQ;EACf;CACF;CAEA,IAAI,MAAqB;EACvB,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAChD,KAAK,QAAQ,KAAe;EAC9B,SAAS,GAAG;GACV,KAAK,OAAO,CAAC;EACf,UAAU;GACR,KAAK,QAAQ;EACf;CACF;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAEA,IAAM,qBAAN,MAA8C;CAC5C;CACA,WAAmB;CACnB;CAEA,YACE,YACA,WACA;EACA,KAAK,aAAa;EAClB,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAEhD,IAAI,UAAU,KAAA,GACZ,KAAK,WAAW,QAAQ,KAAK;GAI/B,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,KAAK,WAAW,MAAM;IACtB,KAAK,QAAQ;GACf;EACF,SAAS,GAAG;GACV,KAAK,WAAW,MAAM,CAAC;GACvB,KAAK,QAAQ;EACf;CACF;CAEA,MAAY;EACV,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW,MAAM;EACtB,KAAK,QAAQ;CACf;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAEA,IAAM,mBAAN,MAA4C;CAC1C;CACA,WAAmB;CACnB;CACA,YAAwC,KAAA;CAExC,YACE,YACA,WACA;EACA,KAAK,aAAa;EAClB,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAEhD,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,UAAU;IACpD,MAAM,QAAQ,MAAM,UAAU,KAAK,WAAW,UAAU,CAAC;IACzD,KAAK,YAAY;IACjB,KAAK,WAAW,QAAQ,KAAK;GAC/B;GAGA,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,KAAK,WAAW,MAAM;IACtB,KAAK,QAAQ;GACf;EACF,SAAS,GAAG;GACV,KAAK,WAAW,MAAM,CAAC;GACvB,KAAK,QAAQ;EACf;CACF;CAEA,MAAY;EACV,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW,MAAM;EACtB,KAAK,QAAQ;CACf;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAEA,IAAM,gBAAN,MAAyC;CACvC;CACA,WAAmB;CACnB;CACA,mCAA2B,IAAI,IAAY;CAE3C,YACE,YACA,WACA;EACA,KAAK,aAAa;EAClB,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAEhD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB;GAIF,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,IAAI,CAAC,KAAK,iBAAiB,IAAI,CAAC;QAG5B,+BACE,MACA,CAJiB,GAAG,KAAK,WAAW,CAI1B,CACZ,MAAM,YACN;KACA,KAAK,WAAW,QAAQ,MAAM,EAAE;KAChC,KAAK,iBAAiB,IAAI,CAAC;IAC7B;;GAKJ,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,KAAK,WAAW,MAAM;IACtB,KAAK,QAAQ;GACf;EACF,SAAS,GAAG;GACV,KAAK,WAAW,MAAM,CAAC;GACvB,KAAK,QAAQ;EACf;CACF;CAEA,MAAY;EACV,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW,MAAM;EACtB,KAAK,QAAQ;CACf;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAGA,IAAa,yBAAb,MAEmC;CACjC;CACA,0BAA+B,IAAI,IAAI;CACvC,OAAwB,uBAAuB,EAAE;CACjD,WAAmB;CAEnB,YAAY,eAAuC;EACjD,KAAK,gBAAgB;EACrB,KAAK,cAAc;CACrB;CAEA,MAAc,gBAA+B;EAC3C,IAAI;GACF,IAAI,kBAAkB;GACtB,MAAM,SAAS,KAAK,cAAc,UAAU;GAE5C,OAAO,MAAM;IACX,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;IAC1C,IAAI,MAAM;IAEV,mBAAmB;IACnB,MAAM,aAAa,uBAAuB,eAAe;IAEzD,IAAI,eAAe,KAAA,GAAW;KAC5B,KAAK,OAAO;KAEZ,KAAK,MAAM,UAAU,KAAK,SACxB,OAAO,OAAO,UAAU;IAE5B;GACF;EACF,SAAS,OAAO;GACd,QAAQ,MAAM,qCAAqC,KAAK;EAC1D,UAAU;GACR,KAAK,WAAW;GAChB,KAAK,MAAM,UAAU,KAAK,SACxB,OAAO,IAAI,KAAK,IAAI;GAEtB,KAAK,QAAQ,MAAM;EACrB;CACF;CAEA,IACE,GAAG,WAC4B;EAC/B,OAAO,IAAI,SAA+B,SAAS,WAAW;GAC5D,MAAM,SAAS,IAAI,UACjB,SACA,QACA,SACF;GAGA,IACE,KAAK,QACL,+BACE,KAAK,MACL,SACF,MAAM,YACN;IACA,MAAM,QAAQ,SAAS,KAAK,MAAW,SAAS;IAChD,IAAI,UAAU,KAAA,GAAW;KACvB,QAAQ,KAA6B;KACrC;IACF;GACF;GAEA,IAAI,KAAK,UAAU;IACjB,OAAO,IAAI,KAAK,IAAI;IACpB;GACF;GAEA,KAAK,QAAQ,IAAI,MAAM;GACvB,OAAO,OAAO,KAAK,IAAI;EACzB,CAAC;CACH;CAEA,aACE,GAAG,WACqD;EAExD,MAAM,aAAa;EAEnB,IAAI;EAqBJ,OAAO,sBAAsB,IApBV,eAAkD;GACnE,QAAQ,eAAe;IACrB,SAAS,IAAI,mBAAsB,YAAY,UAAU;IACzD,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,MAAM;IAG3C,OAAO,OAAO,KAAK,IAAI;IAEvB,IAAI,KAAK,UAAU,OAAO,IAAI;GAChC;GACA,cAAc;IAGZ,IAAI,QAAQ;KACV,OAAO,QAAQ;KACf,KAAK,QAAQ,OAAO,MAAM;IAC5B;GACF;EACF,CAEkC,CAAC;CACrC;CAEA,WACE,GAAG,WAGK;EAER,MAAM,aAAa;EAEnB,IAAI;EAqBJ,OAAO,sBAAsB,IApBV,eAAwB;GACzC,QAAQ,eAAe;IACrB,SAAS,IAAI,iBAAoB,YAAY,UAAU;IACvD,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,MAAM;IAG3C,OAAO,OAAO,KAAK,IAAI;IAEvB,IAAI,KAAK,UAAU,OAAO,IAAI;GAChC;GACA,cAAc;IAGZ,IAAI,QAAQ;KACV,OAAO,QAAQ;KACf,KAAK,QAAQ,OAAO,MAAM;IAC5B;GACF;EACF,CAEkC,CAAC;CACrC;CAEA,QACE,GAAG,WAGK;EAER,MAAM,aAAa;EAEnB,IAAI;EAqBJ,OAAO,sBAAsB,IApBV,eAAwB;GACzC,QAAQ,eAAe;IACrB,SAAS,IAAI,cAAiB,YAAY,UAAU;IACpD,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,MAAM;IAG3C,OAAO,OAAO,KAAK,IAAI;IAEvB,IAAI,KAAK,UAAU,OAAO,IAAI;GAChC;GACA,cAAc;IAGZ,IAAI,QAAQ;KACV,OAAO,QAAQ;KACf,KAAK,QAAQ,OAAO,MAAM;IAC5B;GACF;EACF,CAEkC,CAAC;CACrC;AACF;AAEA,IAAa,6BAAb,MAE6C;CACd;CAA7B,YAAY,SAA0D;EAAzC,KAAA,UAAA;CAA0C;CAEvE,MAAa;EACX,OAAO,KAAK;CACd;AACF;AAEA,IAAa,qBAAb,MAG4C;CAC1C;CACA;CACA;CACA;CAEA,WAA0B;CAE1B,cAAc;EACZ,MAAM,SAAS,IAAI,gBAAgC;EACnD,KAAK,WAAW,OAAO;EACvB,KAAK,OAAO,IAAI,uBAA8B,OAAO,QAAQ;EAE7D,MAAM,EAAE,SAAS,YAAY,qBAA4C;EACzE,KAAK,UAAU;EACf,KAAK,WAAW,IAAI,2BAAoC,OAAO;CACjE;CAEA,MAAM,oBAAoB,MAA6B;EACrD,MAAM,SAAS,KAAK,SAAS,UAAU;EACvC,IAAI;GACF,MAAM,OAAO,MAAM,IAAI;EACzB,SAAS,KAAK;GACZ,QAAQ,KAAK,GAAG;EAClB,UAAU;GACR,OAAO,YAAY;EACrB;EAEA,KAAK,YAAY;CACnB;CAEA,MAAM,iBAAgC;EACpC,MAAM,SAAS,KAAK,SAAS,UAAU;EACvC,IAAI;GACF,MAAM,OAAO,MAAM;EACrB,SAAS,KAAK;GACZ,QAAQ,KAAK,GAAG;EAClB,UAAU;GACR,OAAO,YAAY;EACrB;CACF;CAEA,YAAY,OAAoC;EAC9C,KAAK,QAAQ,KAAK;CACpB;CAEA,SAAS,EACP,KAAK,YAAY;EAEf,QAAO,MADgB,KAAK,SAAS,IAAI,EAAA,CACzB;CAClB,EACF;AACF"}
|
|
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":";;;;AAqBA,SAAS,SAAY,KAAQ,WAAyC;CACpE,IAAI,UAAmB;CACvB,KAAK,MAAM,OAAO,WAAW;EAC3B,IAAI,YAAY,KAAA,KAAa,YAAY,MACvC;EAEF,UAAU,QAAQ;CACpB;CACA,OAAO;AACT;AAQA,IAAM,YAAN,MAA6C;CAC3C;CACA;CACA,WAAmB;CACnB;CAEA,YACE,SACA,QACA,WACA;EACA,KAAK,UAAU;EACf,KAAK,SAAS;EACd,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GAEF,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;IAChD,IAAI,UAAU,KAAA,GAAW;KACvB,KAAK,QAAQ,KAAe;KAC5B,KAAK,QAAQ;IACf;GACF;EACF,SAAS,GAAG;GACV,KAAK,OAAO,CAAC;GACb,KAAK,QAAQ;EACf;CACF;CAEA,IAAI,MAAqB;EACvB,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAChD,KAAK,QAAQ,KAAe;EAC9B,SAAS,GAAG;GACV,KAAK,OAAO,CAAC;EACf,UAAU;GACR,KAAK,QAAQ;EACf;CACF;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAEA,IAAM,qBAAN,MAA8C;CAC5C;CACA,WAAmB;CACnB;CAEA,YACE,YACA,WACA;EACA,KAAK,aAAa;EAClB,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAEhD,IAAI,UAAU,KAAA,GACZ,KAAK,WAAW,QAAQ,KAAK;GAI/B,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,KAAK,WAAW,MAAM;IACtB,KAAK,QAAQ;GACf;EACF,SAAS,GAAG;GACV,KAAK,WAAW,MAAM,CAAC;GACvB,KAAK,QAAQ;EACf;CACF;CAEA,MAAY;EACV,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW,MAAM;EACtB,KAAK,QAAQ;CACf;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAEA,IAAM,mBAAN,MAA4C;CAC1C;CACA,WAAmB;CACnB;CACA,YAAwC,KAAA;CAExC,YACE,YACA,WACA;EACA,KAAK,aAAa;EAClB,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAEhD,IAAI,UAAU,KAAA,KAAa,OAAO,UAAU,UAAU;IACpD,MAAM,QAAQ,MAAM,UAAU,KAAK,WAAW,UAAU,CAAC;IACzD,KAAK,YAAY;IACjB,KAAK,WAAW,QAAQ,KAAK;GAC/B;GAGA,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,KAAK,WAAW,MAAM;IACtB,KAAK,QAAQ;GACf;EACF,SAAS,GAAG;GACV,KAAK,WAAW,MAAM,CAAC;GACvB,KAAK,QAAQ;EACf;CACF;CAEA,MAAY;EACV,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW,MAAM;EACtB,KAAK,QAAQ;CACf;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAEA,IAAM,gBAAN,MAAyC;CACvC;CACA,WAAmB;CACnB;CACA,mCAA2B,IAAI,IAAY;CAE3C,YACE,YACA,WACA;EACA,KAAK,aAAa;EAClB,KAAK,YAAY;CACnB;CAEA,OAAO,MAAqB;EAC1B,IAAI,KAAK,UAAU;EAEnB,IAAI;GACF,MAAM,QAAQ,SAAS,MAAW,KAAK,SAAS;GAEhD,IAAI,CAAC,MAAM,QAAQ,KAAK,GACtB;GAIF,KAAK,IAAI,IAAI,GAAG,IAAI,MAAM,QAAQ,KAChC,IAAI,CAAC,KAAK,iBAAiB,IAAI,CAAC;QAG5B,+BACE,MACA,CAJiB,GAAG,KAAK,WAAW,CAI1B,CACZ,MAAM,YACN;KACA,KAAK,WAAW,QAAQ,MAAM,EAAE;KAChC,KAAK,iBAAiB,IAAI,CAAC;IAC7B;;GAKJ,IACE,+BACE,MACA,KAAK,SACP,MAAM,YACN;IACA,KAAK,WAAW,MAAM;IACtB,KAAK,QAAQ;GACf;EACF,SAAS,GAAG;GACV,KAAK,WAAW,MAAM,CAAC;GACvB,KAAK,QAAQ;EACf;CACF;CAEA,MAAY;EACV,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW,MAAM;EACtB,KAAK,QAAQ;CACf;CAEA,UAAgB;EACd,KAAK,WAAW;CAClB;AACF;AAGA,IAAa,yBAAb,MAEmC;CACjC;CACA,0BAA+B,IAAI,IAAI;CACvC,OAAwB,uBAAuB,EAAE;CACjD,WAAmB;CAEnB,YAAY,eAAuC;EACjD,KAAK,gBAAgB;EACrB,KAAK,cAAc;CACrB;CAEA,MAAc,gBAA+B;EAC3C,IAAI;GACF,IAAI,kBAAkB;GACtB,MAAM,SAAS,KAAK,cAAc,UAAU;GAE5C,OAAO,MAAM;IACX,MAAM,EAAE,OAAO,SAAS,MAAM,OAAO,KAAK;IAC1C,IAAI,MAAM;IAEV,mBAAmB;IACnB,MAAM,aAAa,uBAAuB,eAAe;IAEzD,IAAI,eAAe,KAAA,GAAW;KAC5B,KAAK,OAAO;KAEZ,KAAK,MAAM,UAAU,KAAK,SACxB,OAAO,OAAO,UAAU;IAE5B;GACF;EACF,SAAS,OAAO;GACd,QAAQ,MAAM,qCAAqC,KAAK;EAC1D,UAAU;GACR,KAAK,WAAW;GAChB,KAAK,MAAM,UAAU,KAAK,SACxB,OAAO,IAAI,KAAK,IAAI;GAEtB,KAAK,QAAQ,MAAM;EACrB;CACF;CAEA,IACE,GAAG,WAC4B;EAC/B,OAAO,IAAI,SAA+B,SAAS,WAAW;GAC5D,MAAM,SAAS,IAAI,UACjB,SACA,QACA,SACF;GAGA,IACE,KAAK,QACL,+BACE,KAAK,MACL,SACF,MAAM,YACN;IACA,MAAM,QAAQ,SAAS,KAAK,MAAW,SAAS;IAChD,IAAI,UAAU,KAAA,GAAW;KACvB,QAAQ,KAA6B;KACrC;IACF;GACF;GAEA,IAAI,KAAK,UAAU;IACjB,OAAO,IAAI,KAAK,IAAI;IACpB;GACF;GAEA,KAAK,QAAQ,IAAI,MAAM;GACvB,OAAO,OAAO,KAAK,IAAI;EACzB,CAAC;CACH;CAEA,aACE,GAAG,WACqD;EAExD,MAAM,aAAa;EAEnB,IAAI;EAqBJ,OAAO,sBAAsB,IApBV,eAAkD;GACnE,QAAQ,eAAe;IACrB,SAAS,IAAI,mBAAsB,YAAY,UAAU;IACzD,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,MAAM;IAG3C,OAAO,OAAO,KAAK,IAAI;IAEvB,IAAI,KAAK,UAAU,OAAO,IAAI;GAChC;GACA,cAAc;IAGZ,IAAI,QAAQ;KACV,OAAO,QAAQ;KACf,KAAK,QAAQ,OAAO,MAAM;IAC5B;GACF;EACF,CAEkC,CAAC;CACrC;CAEA,WACE,GAAG,WAGK;EAER,MAAM,aAAa;EAEnB,IAAI;EAqBJ,OAAO,sBAAsB,IApBV,eAAwB;GACzC,QAAQ,eAAe;IACrB,SAAS,IAAI,iBAAoB,YAAY,UAAU;IACvD,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,MAAM;IAG3C,OAAO,OAAO,KAAK,IAAI;IAEvB,IAAI,KAAK,UAAU,OAAO,IAAI;GAChC;GACA,cAAc;IAGZ,IAAI,QAAQ;KACV,OAAO,QAAQ;KACf,KAAK,QAAQ,OAAO,MAAM;IAC5B;GACF;EACF,CAEkC,CAAC;CACrC;CAEA,QACE,GAAG,WAGK;EAER,MAAM,aAAa;EAEnB,IAAI;EAqBJ,OAAO,sBAAsB,IApBV,eAAwB;GACzC,QAAQ,eAAe;IACrB,SAAS,IAAI,cAAiB,YAAY,UAAU;IACpD,IAAI,CAAC,KAAK,UAAU,KAAK,QAAQ,IAAI,MAAM;IAG3C,OAAO,OAAO,KAAK,IAAI;IAEvB,IAAI,KAAK,UAAU,OAAO,IAAI;GAChC;GACA,cAAc;IAGZ,IAAI,QAAQ;KACV,OAAO,QAAQ;KACf,KAAK,QAAQ,OAAO,MAAM;IAC5B;GACF;EACF,CAEkC,CAAC;CACrC;AACF;AAEA,IAAa,6BAAb,MAE6C;CACd;CAA7B,YAAY,SAA0D;EAAzC,KAAA,UAAA;CAA0C;CAEvE,MAAa;EACX,OAAO,KAAK;CACd;AACF;AAEA,IAAa,qBAAb,MAG4C;CAC1C;CACA;CACA;CACA;CAEA,WAA0B;CAE1B,cAAc;EACZ,MAAM,SAAS,IAAI,gBAAgC;EACnD,KAAK,WAAW,OAAO;EACvB,KAAK,OAAO,IAAI,uBAA8B,OAAO,QAAQ;EAE7D,MAAM,EAAE,SAAS,YAAY,qBAA4C;EACzE,KAAK,UAAU;EACf,KAAK,WAAW,IAAI,2BAAoC,OAAO;CACjE;CAEA,MAAM,oBAAoB,MAA6B;EACrD,MAAM,SAAS,KAAK,SAAS,UAAU;EACvC,IAAI;GACF,MAAM,OAAO,MAAM,IAAI;EACzB,SAAS,KAAK;GACZ,QAAQ,KAAK,GAAG;EAClB,UAAU;GACR,OAAO,YAAY;EACrB;EAEA,KAAK,YAAY;CACnB;CAEA,MAAM,iBAAgC;EACpC,MAAM,SAAS,KAAK,SAAS,UAAU;EACvC,IAAI;GACF,MAAM,OAAO,MAAM;EACrB,SAAS,KAAK;GACZ,QAAQ,KAAK,GAAG;EAClB,UAAU;GACR,OAAO,YAAY;EACrB;CACF;CAEA,YAAY,OAAoC;EAC9C,KAAK,QAAQ,KAAK;CACpB;CAEA,SAAS,EACP,KAAK,YAAY;EAEf,QAAO,MADgB,KAAK,SAAS,IAAI,EAAA,CACzB;CAClB,EACF;AACF"}
|
|
@@ -84,7 +84,7 @@ interface ToolCallArgsReader<TArgs extends Record<string, unknown>> {
|
|
|
84
84
|
*
|
|
85
85
|
* @param fieldPath An array of object keys or array indices.
|
|
86
86
|
*/
|
|
87
|
-
forEach<PathT extends TypePath<TArgs>>(...fieldPath: PathT): TypeAtPath<TArgs, PathT
|
|
87
|
+
forEach<PathT extends TypePath<TArgs>>(...fieldPath: PathT): NonNullable<TypeAtPath<TArgs, PathT>> extends Array<infer U> ? AsyncIterableStream<U> : never;
|
|
88
88
|
}
|
|
89
89
|
interface ToolCallResponseReader<TResult> {
|
|
90
90
|
get: () => Promise<ToolResponse<TResult>>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"tool-types.d.ts","names":[],"sources":["../../../src/core/tool/tool-types.ts"],"mappings":";;;;;;;KAMY,oBAAA;8EAGG,IAAA,UAHH;EAAA,SAKG,IAAA;AAAA;EALiB,4EASjB,IAAA;EAJA;;;;EAAA,SASA,IAAA,UAIQ;EAAA,SAFR,SAAA,UA8BH;EAAA,SA5BG,QAAA;AAAA;;;;;;;;;;;;;;;;;;;;AAqC0B;AAUzC;;;;;KAnBY,uBAAA,oBAA2C,OAAA;EA2BrC,2DAzBhB,UAAA,UA0B6B;EAxB7B,KAAA,EAAO,KAAA,EAwBJ;EAtBH,MAAA,EAAQ,OAAA;AAAA,eAEG,oBAAA,KACT,OAAA,UAAiB,oBAAA;;;;;;;;;UAUJ,kBAAA,eAAiC,MAAA;EA6BlC;;;;;;EAtBd,GAAA,eAAkB,QAAA,CAAS,KAAA,MACtB,SAAA,EAAW,KAAA,GACb,OAAA,CAAQ,UAAA,CAAW,KAAA,EAAO,KAAA;EA+Bb;;;;;;EAvBhB,YAAA,eAA2B,QAAA,CAAS,KAAA,MAC/B,SAAA,EAAW,KAAA,GACb,mBAAA,CAAoB,WAAA,CAAY,UAAA,CAAW,KAAA,EAAO,KAAA;
|
|
1
|
+
{"version":3,"file":"tool-types.d.ts","names":[],"sources":["../../../src/core/tool/tool-types.ts"],"mappings":"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"}
|
|
@@ -36,6 +36,16 @@ type ToolCallStatus = {
|
|
|
36
36
|
type: "incomplete";
|
|
37
37
|
reason: "cancelled" | "length" | "content-filter" | "other";
|
|
38
38
|
};
|
|
39
|
+
/**
|
|
40
|
+
* Wall-clock timing of a tool call. Accumulator-populated timings are
|
|
41
|
+
* measured by the consuming accumulator, so resumed or replayed streams
|
|
42
|
+
* re-measure them; hosts that need authoritative timings supply the field
|
|
43
|
+
* themselves.
|
|
44
|
+
*/
|
|
45
|
+
type ToolCallTiming = {
|
|
46
|
+
/** Epoch milliseconds when the tool call started streaming or executing. */readonly startedAt: number; /** Epoch milliseconds when the result landed. Absent while the call runs. */
|
|
47
|
+
readonly completedAt?: number;
|
|
48
|
+
};
|
|
39
49
|
type ToolCallPartBase = {
|
|
40
50
|
type: "tool-call";
|
|
41
51
|
status: ToolCallStatus;
|
|
@@ -43,6 +53,7 @@ type ToolCallPartBase = {
|
|
|
43
53
|
toolName: string;
|
|
44
54
|
argsText: string;
|
|
45
55
|
args: ReadonlyJSONObject;
|
|
56
|
+
timing?: ToolCallTiming;
|
|
46
57
|
artifact?: ReadonlyJSONValue;
|
|
47
58
|
result?: ReadonlyJSONValue;
|
|
48
59
|
modelContent?: readonly ToolModelContentPart[];
|
|
@@ -137,5 +148,5 @@ type AssistantMessage = {
|
|
|
137
148
|
};
|
|
138
149
|
};
|
|
139
150
|
//#endregion
|
|
140
|
-
export { AssistantMessage, AssistantMessagePart, AssistantMessageStatus, AssistantMessageTiming, DataPart, FilePart, ReasoningPart, SourcePart, TextPart, ToolCallPart };
|
|
151
|
+
export { AssistantMessage, AssistantMessagePart, AssistantMessageStatus, AssistantMessageTiming, DataPart, FilePart, ReasoningPart, SourcePart, TextPart, ToolCallPart, ToolCallTiming };
|
|
141
152
|
//# sourceMappingURL=types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/core/utils/types.ts"],"mappings":";;;;KAMK,UAAA;EAEC,IAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;AAAA,KAOM,QAAA;EACV,IAAA;EACA,IAAA;EACA,MAAA,EAAQ,UAAU;EAClB,QAAA;AAAA;AAAA,KAGU,aAAA;EACV,IAAA;EACA,IAAA;EACA,MAAA,EAAQ,UAAU;EAClB,QAAA;AAAA;AAAA,KAGG,cAAA;EAEC,IAAA;EACA,cAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/core/utils/types.ts"],"mappings":";;;;KAMK,UAAA;EAEC,IAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;AAAA,KAOM,QAAA;EACV,IAAA;EACA,IAAA;EACA,MAAA,EAAQ,UAAU;EAClB,QAAA;AAAA;AAAA,KAGU,aAAA;EACV,IAAA;EACA,IAAA;EACA,MAAA,EAAQ,UAAU;EAClB,QAAA;AAAA;AAAA,KAGG,cAAA;EAEC,IAAA;EACA,cAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;AAlBI;AACR;;;;;AADQ,KA2BE,cAAA;EAlBN,qFAoBK,SAAA,UAhBL;EAAA,SAkBK,WAAW;AAAA;AAAA,KAGjB,gBAAA;EACH,IAAA;EACA,MAAA,EAAQ,cAAA;EACR,UAAA;EACA,QAAA;EACA,QAAA;EACA,IAAA,EAAM,kBAAA;EACN,MAAA,GAAS,cAAA;EACT,QAAA,GAAW,iBAAA;EACX,MAAA,GAAS,iBAAA;EACT,YAAA,YAAwB,oBAAA;EACxB,OAAA;EACA,QAAA;AAAA;AAAA,KAGG,yBAAA,GAA4B,gBAAgB;EAC/C,KAAA;EACA,MAAA;EACA,YAAA;AAAA;AAAA,KAGG,sBAAA,GAAyB,gBAAA;EAC5B,KAAA;EACA,MAAA,EAAQ,iBAAA;EACR,QAAA,GAAW,iBAAA;EACX,YAAA,YAAwB,oBAAA;EACxB,OAAA;AAAA;AAAA,KAGU,YAAA,GAAe,yBAAA,GAA4B,sBAAsB;AAAA,KAEjE,UAAA;EACV,IAAA;EACA,UAAA;EACA,EAAA;EACA,GAAA;EACA,KAAA;EACA,QAAA;AAAA;AAAA,KAGU,QAAA;EACV,IAAA;EACA,IAAA;EACA,QAAA;EACA,QAAA;AAAA;AAAA,KAGU,QAAA;EACV,IAAA;EACA,IAAA;EACA,IAAA,EAAM,iBAAiB;EACvB,QAAA;AAAA;AAAA,KAGU,oBAAA,GACR,QAAA,GACA,aAAA,GACA,YAAA,GACA,UAAA,GACA,QAAA,GACA,QAAA;AAAA,KAEC,yBAAA;EACH,WAAA;EACA,YAAY;AAAA;AAAA,KAGT,4BAAA;EAEC,KAAA;EACA,SAAA;AAAA;EAGA,KAAA;EACA,SAAA;EACA,YAAA;EAQA,KAAA,GAAQ,yBAAyB;EACjC,WAAA;AAAA;AAAA,KAGM,sBAAA;EAEN,IAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;AAAA;EAGA,IAAA;EACA,MAAA;EAOA,KAAA,GAAQ,iBAAiB;AAAA;AAAA,KAGnB,sBAAA;2DAEV,eAAA,UAjFA;EAmFA,cAAA,WAjFA;EAmFA,eAAA,WAjFA;EAmFA,UAAA,WAlFQ;EAoFR,eAAA,WAjFU;EAmFV,WAAA;EAEA,aAAA;AAAA;AAAA,KAGU,gBAAA;EACV,IAAA;EACA,MAAA,EAAQ,sBAAA;EACR,KAAA,EAAO,oBAAA;EAvFC;AAGV;;EAwFE,OAAA,EAAS,oBAAA;EAET,QAAA;IACE,cAAA,EAAgB,iBAAA;IAChB,aAAA,EAAe,iBAAA;IACf,oBAAA,EAAsB,iBAAA;IACtB,KAAA,EAAO,4BAAA;IACP,MAAA,EAAQ,MAAA;IACR,MAAA,GAAS,sBAAA;EAAA;AAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { TextStreamController } from "./core/modules/text.js";
|
|
|
2
2
|
import { McpServerConfig, ProviderOptions, Tool, ToolCallReader, ToolDeclaration, ToolModelContentPart, ToolModelOutputFunction } from "./core/tool/tool-types.js";
|
|
3
3
|
import { ToolResponse, ToolResponseLike } from "./core/tool/ToolResponse.js";
|
|
4
4
|
import { ToolCallStreamController } from "./core/modules/tool-call.js";
|
|
5
|
-
import { AssistantMessage, AssistantMessageTiming, DataPart } from "./core/utils/types.js";
|
|
5
|
+
import { AssistantMessage, AssistantMessageTiming, DataPart, ToolCallTiming } from "./core/utils/types.js";
|
|
6
6
|
import { AssistantStreamController, createAssistantStream, createAssistantStreamController, createAssistantStreamResponse } from "./core/modules/assistant-stream.js";
|
|
7
7
|
import { ObjectStreamChunk } from "./core/object/types.js";
|
|
8
8
|
import { AssistantStreamChunk } from "./core/AssistantStreamChunk.js";
|
|
@@ -20,4 +20,4 @@ import { UIMessageStreamDecoder, UIMessageStreamDecoderOptions } from "./core/se
|
|
|
20
20
|
import { ToolExecutionStream } from "./core/tool/ToolExecutionStream.js";
|
|
21
21
|
import { ToToolsJSONSchemaOptions, ToolJSONSchema, toJSONSchema, toPartialJSONSchema, toToolsJSONSchema } from "./core/tool/schema-utils.js";
|
|
22
22
|
import { ToolResultStreamOptions, toolResultStream, unstable_runPendingTools } from "./core/tool/toolResultStream.js";
|
|
23
|
-
export { type AssistantMessage, AssistantMessageAccumulator, AssistantMessageStream, type AssistantMessageTiming, AssistantStream, type AssistantStreamChunk, type AssistantStreamController, AssistantTransportDecoder, AssistantTransportEncoder, type DataPart, DataStreamDecoder, DataStreamEncoder, type GenericAssistantMessage, type GenericFilePart, type GenericMessage, type GenericSystemMessage, type GenericTextPart, type GenericToolCallPart, type GenericToolMessage, type GenericToolResultPart, type GenericUserMessage, type McpServerConfig, type ObjectStreamChunk, ObjectStreamResponse, PlainTextDecoder, PlainTextEncoder, type ProviderOptions, type TextStreamController, type ToToolsJSONSchemaOptions, type Tool, type ToolCallReader, type ToolCallStreamController, type ToolDeclaration, ToolExecutionStream, type ToolJSONSchema, type ToolModelContentPart, type ToolModelOutputFunction, ToolResponse, type ToolResponseLike, type ToolResultStreamOptions, type UIMessageStreamChunk, type UIMessageStreamDataChunk, UIMessageStreamDecoder, type UIMessageStreamDecoderOptions, createAssistantStream, createAssistantStreamController, createAssistantStreamResponse, createObjectStream, fromObjectStreamResponse, toGenericMessages, toJSONSchema, toPartialJSONSchema, toToolsJSONSchema, createInitialMessage as unstable_createInitialMessage, unstable_runPendingTools, toolResultStream as unstable_toolResultStream };
|
|
23
|
+
export { type AssistantMessage, AssistantMessageAccumulator, AssistantMessageStream, type AssistantMessageTiming, AssistantStream, type AssistantStreamChunk, type AssistantStreamController, AssistantTransportDecoder, AssistantTransportEncoder, type DataPart, DataStreamDecoder, DataStreamEncoder, type GenericAssistantMessage, type GenericFilePart, type GenericMessage, type GenericSystemMessage, type GenericTextPart, type GenericToolCallPart, type GenericToolMessage, type GenericToolResultPart, type GenericUserMessage, type McpServerConfig, type ObjectStreamChunk, ObjectStreamResponse, PlainTextDecoder, PlainTextEncoder, type ProviderOptions, type TextStreamController, type ToToolsJSONSchemaOptions, type Tool, type ToolCallReader, type ToolCallStreamController, type ToolCallTiming, type ToolDeclaration, ToolExecutionStream, type ToolJSONSchema, type ToolModelContentPart, type ToolModelOutputFunction, ToolResponse, type ToolResponseLike, type ToolResultStreamOptions, type UIMessageStreamChunk, type UIMessageStreamDataChunk, UIMessageStreamDecoder, type UIMessageStreamDecoderOptions, createAssistantStream, createAssistantStreamController, createAssistantStreamResponse, createObjectStream, fromObjectStreamResponse, toGenericMessages, toJSONSchema, toPartialJSONSchema, toToolsJSONSchema, createInitialMessage as unstable_createInitialMessage, unstable_runPendingTools, toolResultStream as unstable_toolResultStream };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "assistant-stream",
|
|
3
|
-
"version": "0.3.
|
|
3
|
+
"version": "0.3.23",
|
|
4
4
|
"description": "Streaming utilities for AI assistants",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"ai",
|
|
@@ -67,7 +67,7 @@
|
|
|
67
67
|
"ioredis": "^5.11.1",
|
|
68
68
|
"redis": "^6.0.0",
|
|
69
69
|
"vitest": "^4.1.8",
|
|
70
|
-
"@assistant-ui/x-buildutils": "0.0.
|
|
70
|
+
"@assistant-ui/x-buildutils": "0.0.14"
|
|
71
71
|
},
|
|
72
72
|
"publishConfig": {
|
|
73
73
|
"access": "public",
|
|
@@ -101,6 +101,57 @@ describe("AssistantMessageAccumulator timing", () => {
|
|
|
101
101
|
expect(last.metadata.timing!.toolCallCount).toBe(1);
|
|
102
102
|
});
|
|
103
103
|
|
|
104
|
+
it("should record per-tool-call timing on the part", async () => {
|
|
105
|
+
const before = Date.now();
|
|
106
|
+
const chunks: AssistantStreamChunk[] = [
|
|
107
|
+
{
|
|
108
|
+
type: "part-start",
|
|
109
|
+
path: [0],
|
|
110
|
+
part: {
|
|
111
|
+
type: "tool-call",
|
|
112
|
+
toolCallId: "tc-1",
|
|
113
|
+
toolName: "search",
|
|
114
|
+
},
|
|
115
|
+
},
|
|
116
|
+
{ type: "text-delta", path: [0], textDelta: '{"q":"test"}' },
|
|
117
|
+
{ type: "tool-call-args-text-finish", path: [0] },
|
|
118
|
+
{
|
|
119
|
+
type: "result",
|
|
120
|
+
path: [0],
|
|
121
|
+
result: "found",
|
|
122
|
+
isError: false,
|
|
123
|
+
},
|
|
124
|
+
{ type: "part-finish", path: [0] },
|
|
125
|
+
{
|
|
126
|
+
type: "message-finish",
|
|
127
|
+
path: [],
|
|
128
|
+
finishReason: "stop",
|
|
129
|
+
usage: { inputTokens: 0, outputTokens: 0 },
|
|
130
|
+
},
|
|
131
|
+
];
|
|
132
|
+
|
|
133
|
+
const messages = await collectStream(chunks);
|
|
134
|
+
const after = Date.now();
|
|
135
|
+
|
|
136
|
+
const runningPart = messages
|
|
137
|
+
.find((m) =>
|
|
138
|
+
m.parts.some((p) => p.type === "tool-call" && p.state !== "result"),
|
|
139
|
+
)!
|
|
140
|
+
.parts.find((p) => p.type === "tool-call")!;
|
|
141
|
+
expect(runningPart.timing).toBeDefined();
|
|
142
|
+
expect(runningPart.timing!.startedAt).toBeGreaterThanOrEqual(before);
|
|
143
|
+
expect(runningPart.timing!.completedAt).toBeUndefined();
|
|
144
|
+
|
|
145
|
+
const settledPart = messages
|
|
146
|
+
.at(-1)!
|
|
147
|
+
.parts.find((p) => p.type === "tool-call")!;
|
|
148
|
+
expect(settledPart.timing).toBeDefined();
|
|
149
|
+
expect(settledPart.timing!.completedAt).toBeGreaterThanOrEqual(
|
|
150
|
+
settledPart.timing!.startedAt,
|
|
151
|
+
);
|
|
152
|
+
expect(settledPart.timing!.completedAt).toBeLessThanOrEqual(after);
|
|
153
|
+
});
|
|
154
|
+
|
|
104
155
|
it("should include timing on flush when stream closes without message-finish", async () => {
|
|
105
156
|
const chunks: AssistantStreamChunk[] = [
|
|
106
157
|
{ type: "part-start", path: [0], part: { type: "text" } },
|
|
@@ -92,6 +92,7 @@ const handlePartStart = (
|
|
|
92
92
|
toolName: partInit.toolName,
|
|
93
93
|
argsText: "",
|
|
94
94
|
args: {},
|
|
95
|
+
timing: { startedAt: Date.now() },
|
|
95
96
|
...(partInit.parentId && { parentId: partInit.parentId }),
|
|
96
97
|
};
|
|
97
98
|
return {
|
|
@@ -213,6 +214,14 @@ const handleResult = (
|
|
|
213
214
|
return {
|
|
214
215
|
...part,
|
|
215
216
|
state: "result",
|
|
217
|
+
...(part.timing !== undefined
|
|
218
|
+
? {
|
|
219
|
+
timing: {
|
|
220
|
+
...part.timing,
|
|
221
|
+
completedAt: part.timing.completedAt ?? Date.now(),
|
|
222
|
+
},
|
|
223
|
+
}
|
|
224
|
+
: {}),
|
|
216
225
|
...(chunk.artifact !== undefined ? { artifact: chunk.artifact } : {}),
|
|
217
226
|
result: chunk.result,
|
|
218
227
|
isError: chunk.isError ?? false,
|
|
@@ -407,7 +407,7 @@ export class ToolCallArgsReaderImpl<
|
|
|
407
407
|
|
|
408
408
|
forEach<PathT extends TypePath<T>>(
|
|
409
409
|
...fieldPath: PathT
|
|
410
|
-
): TypeAtPath<T, PathT
|
|
410
|
+
): NonNullable<TypeAtPath<T, PathT>> extends Array<infer U>
|
|
411
411
|
? AsyncIterableStream<U>
|
|
412
412
|
: never {
|
|
413
413
|
// Use a type assertion to convert the complex TypePath to a simple array
|
|
@@ -110,7 +110,7 @@ export interface ToolCallArgsReader<TArgs extends Record<string, unknown>> {
|
|
|
110
110
|
*/
|
|
111
111
|
forEach<PathT extends TypePath<TArgs>>(
|
|
112
112
|
...fieldPath: PathT
|
|
113
|
-
): TypeAtPath<TArgs, PathT
|
|
113
|
+
): NonNullable<TypeAtPath<TArgs, PathT>> extends Array<infer U>
|
|
114
114
|
? AsyncIterableStream<U>
|
|
115
115
|
: never;
|
|
116
116
|
}
|
package/src/core/utils/types.ts
CHANGED
|
@@ -53,6 +53,19 @@ type ToolCallStatus =
|
|
|
53
53
|
reason: "cancelled" | "length" | "content-filter" | "other";
|
|
54
54
|
};
|
|
55
55
|
|
|
56
|
+
/**
|
|
57
|
+
* Wall-clock timing of a tool call. Accumulator-populated timings are
|
|
58
|
+
* measured by the consuming accumulator, so resumed or replayed streams
|
|
59
|
+
* re-measure them; hosts that need authoritative timings supply the field
|
|
60
|
+
* themselves.
|
|
61
|
+
*/
|
|
62
|
+
export type ToolCallTiming = {
|
|
63
|
+
/** Epoch milliseconds when the tool call started streaming or executing. */
|
|
64
|
+
readonly startedAt: number;
|
|
65
|
+
/** Epoch milliseconds when the result landed. Absent while the call runs. */
|
|
66
|
+
readonly completedAt?: number;
|
|
67
|
+
};
|
|
68
|
+
|
|
56
69
|
type ToolCallPartBase = {
|
|
57
70
|
type: "tool-call";
|
|
58
71
|
status: ToolCallStatus;
|
|
@@ -60,6 +73,7 @@ type ToolCallPartBase = {
|
|
|
60
73
|
toolName: string;
|
|
61
74
|
argsText: string;
|
|
62
75
|
args: ReadonlyJSONObject;
|
|
76
|
+
timing?: ToolCallTiming;
|
|
63
77
|
artifact?: ReadonlyJSONValue;
|
|
64
78
|
result?: ReadonlyJSONValue;
|
|
65
79
|
modelContent?: readonly ToolModelContentPart[];
|
package/src/index.ts
CHANGED
|
@@ -145,7 +145,17 @@ describe("resumable integration", () => {
|
|
|
145
145
|
new AssistantTransportDecoder(),
|
|
146
146
|
);
|
|
147
147
|
|
|
148
|
-
|
|
148
|
+
// Tool-call timing is measured by the consuming accumulator, so a replay
|
|
149
|
+
// re-measures it; compare parts modulo timing.
|
|
150
|
+
const withoutTiming = (parts: typeof replayMessage.parts) =>
|
|
151
|
+
parts.map((part) =>
|
|
152
|
+
part.type === "tool-call"
|
|
153
|
+
? (({ timing: _timing, ...rest }) => rest)(part)
|
|
154
|
+
: part,
|
|
155
|
+
);
|
|
156
|
+
expect(withoutTiming(replayMessage.parts)).toEqual(
|
|
157
|
+
withoutTiming(producerMessage.parts),
|
|
158
|
+
);
|
|
149
159
|
expect(replayMessage.status).toEqual(producerMessage.status);
|
|
150
160
|
const toolPart = replayMessage.parts.find((p) => p.type === "tool-call");
|
|
151
161
|
expect(toolPart).toBeDefined();
|
|
@@ -154,6 +164,7 @@ describe("resumable integration", () => {
|
|
|
154
164
|
toolCallId: "tool-1",
|
|
155
165
|
args: { query: "weather" },
|
|
156
166
|
result: { temperature: 72 },
|
|
167
|
+
timing: { startedAt: expect.any(Number) },
|
|
157
168
|
});
|
|
158
169
|
});
|
|
159
170
|
});
|