assistant-stream 0.3.19 → 0.3.21
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.js.map +1 -1
- package/dist/core/converters/toGenericMessages.js.map +1 -1
- package/dist/core/object/ObjectStreamResponse.js.map +1 -1
- package/dist/core/serialization/PlainText.js.map +1 -1
- package/dist/core/serialization/assistant-transport/AssistantTransport.js.map +1 -1
- package/dist/core/serialization/data-stream/DataStream.js.map +1 -1
- package/dist/core/serialization/ui-message-stream/UIMessageStream.js.map +1 -1
- package/dist/core/tool/ToolCallReader.d.ts +2 -0
- package/dist/core/tool/ToolCallReader.d.ts.map +1 -1
- package/dist/core/tool/ToolCallReader.js +60 -13
- package/dist/core/tool/ToolCallReader.js.map +1 -1
- package/dist/core/tool/ToolExecutionStream.js +3 -2
- package/dist/core/tool/ToolExecutionStream.js.map +1 -1
- package/dist/core/tool/schema-utils.d.ts +2 -0
- package/dist/core/tool/schema-utils.d.ts.map +1 -1
- package/dist/core/tool/schema-utils.js +5 -2
- package/dist/core/tool/schema-utils.js.map +1 -1
- package/dist/core/tool/tool-types.d.ts +44 -5
- package/dist/core/tool/tool-types.d.ts.map +1 -1
- package/dist/core/tool/toolResultStream.js.map +1 -1
- package/dist/core/utils/stream/AssistantTransformStream.js.map +1 -1
- package/dist/core/utils/stream/SSE.js.map +1 -1
- package/dist/core/utils/stream/merge.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/resumable/ResumableStreamContext.js.map +1 -1
- package/dist/resumable/createResumableAssistantStreamResponse.js.map +1 -1
- package/dist/resumable/stores/InMemoryResumableStreamStore.js.map +1 -1
- package/dist/resumable/stores/ioredis.js.map +1 -1
- package/dist/utils/json/fix-json.js.map +1 -1
- package/dist/utils/json/is-json.js.map +1 -1
- package/package.json +4 -4
- package/src/core/tool/ToolCallReader.test.ts +86 -0
- package/src/core/tool/ToolCallReader.ts +83 -29
- package/src/core/tool/ToolExecutionStream.ts +8 -2
- package/src/core/tool/schema-utils.test.ts +63 -0
- package/src/core/tool/schema-utils.ts +25 -3
- package/src/core/tool/tool-types.ts +73 -1
- package/src/index.ts +1 -0
|
@@ -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 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 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 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 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 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\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 // Notify handles of the error\n for (const handle of this.handles) {\n handle.dispose();\n }\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 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 const stream = new ReadableStream<DeepPartial<TypeAtPath<T, PathT>>>({\n start: (controller) => {\n const handle = new StreamValuesHandle<T>(controller, simplePath);\n this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n },\n cancel: () => {\n // Find and dispose the corresponding handle\n for (const handle of this.handles) {\n if (handle instanceof StreamValuesHandle) {\n handle.dispose();\n this.handles.delete(handle);\n break;\n }\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 const stream = new ReadableStream<unknown>({\n start: (controller) => {\n const handle = new StreamTextHandle<T>(controller, simplePath);\n this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n },\n cancel: () => {\n // Find and dispose the corresponding handle\n for (const handle of this.handles) {\n if (handle instanceof StreamTextHandle) {\n handle.dispose();\n this.handles.delete(handle);\n break;\n }\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 const stream = new ReadableStream<unknown>({\n start: (controller) => {\n const handle = new ForEachHandle<T>(controller, simplePath);\n this.handles.add(handle);\n\n // Check current args immediately\n handle.update(this.args);\n },\n cancel: () => {\n // Find and dispose the corresponding handle\n for (const handle of this.handles) {\n if (handle instanceof ForEachHandle) {\n handle.dispose();\n this.handles.delete(handle);\n break;\n }\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 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 ): 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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"}
|
|
@@ -11,7 +11,7 @@ var ToolExecutionStream = class extends PipeableTransformStream {
|
|
|
11
11
|
const toolCallControllers = /* @__PURE__ */ new Map();
|
|
12
12
|
super((readable) => {
|
|
13
13
|
const transform = new TransformStream({
|
|
14
|
-
transform(chunk, controller) {
|
|
14
|
+
async transform(chunk, controller) {
|
|
15
15
|
if (chunk.type !== "part-finish" || chunk.meta.type !== "tool-call") controller.enqueue(chunk);
|
|
16
16
|
switch (chunk.type) {
|
|
17
17
|
case "part-start":
|
|
@@ -30,7 +30,7 @@ var ToolExecutionStream = class extends PipeableTransformStream {
|
|
|
30
30
|
const toolCallId = chunk.meta.toolCallId;
|
|
31
31
|
const controller = toolCallControllers.get(toolCallId);
|
|
32
32
|
if (!controller) throw new Error("No controller found for tool call");
|
|
33
|
-
controller.appendArgsTextDelta(chunk.textDelta);
|
|
33
|
+
await controller.appendArgsTextDelta(chunk.textDelta);
|
|
34
34
|
}
|
|
35
35
|
break;
|
|
36
36
|
case "result": {
|
|
@@ -51,6 +51,7 @@ var ToolExecutionStream = class extends PipeableTransformStream {
|
|
|
51
51
|
const { toolCallId, toolName } = chunk.meta;
|
|
52
52
|
const streamController = toolCallControllers.get(toolCallId);
|
|
53
53
|
if (!streamController) throw new Error("No controller found for tool call");
|
|
54
|
+
await streamController.finishArgsText();
|
|
54
55
|
let isExecuting = false;
|
|
55
56
|
const promise = withPromiseOrValue(() => {
|
|
56
57
|
let args;
|
|
@@ -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 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 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 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\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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"}
|
|
@@ -15,6 +15,8 @@ type ToToolsJSONSchemaOptions = {
|
|
|
15
15
|
/**
|
|
16
16
|
* Filter to determine which tools to include.
|
|
17
17
|
* Defaults to excluding disabled tools and backend tools.
|
|
18
|
+
*
|
|
19
|
+
* Tools with backend-default parameters are always excluded.
|
|
18
20
|
*/
|
|
19
21
|
filter?: (name: string, tool: Tool) => boolean;
|
|
20
22
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-utils.d.ts","names":[],"sources":["../../../src/core/tool/schema-utils.ts"],"mappings":";;;;;;;AAOA;KAAY,cAAA;EACV,WAAA;EACA,UAAA,EAAY,WAAA;EACZ,eAAA,GAAkB,eAAe;AAAA;AAAA,KAGvB,wBAAA;EAHV;;;AAAiC;
|
|
1
|
+
{"version":3,"file":"schema-utils.d.ts","names":[],"sources":["../../../src/core/tool/schema-utils.ts"],"mappings":";;;;;;;AAOA;KAAY,cAAA;EACV,WAAA;EACA,UAAA,EAAY,WAAA;EACZ,eAAA,GAAkB,eAAe;AAAA;AAAA,KAGvB,wBAAA;EAHV;;;AAAiC;AAGnC;;EAOE,MAAA,IAAU,IAAA,UAAc,IAAA,EAAM,IAAI;AAAA;;;;;;AAAA;AA8CpC;;;iBAAgB,YAAA,CACd,MAAA,EAAQ,gBAAA,GAAmB,WAAA,GAC1B,WAAA;;;;;iBA+Ca,mBAAA,CAAoB,MAAA,EAAQ,WAAA,GAAc,WAAW;;;;;AA/CvD;AA+Cd;;;;iBA2CgB,iBAAA,CACd,KAAA,EAAO,MAAA,SAAe,IAAA,eACtB,OAAA,GAAS,wBAAA,GACR,MAAA,SAAe,cAAA"}
|
|
@@ -45,7 +45,10 @@ function toPartialJSONSchema(schema) {
|
|
|
45
45
|
return result;
|
|
46
46
|
}
|
|
47
47
|
function defaultToolFilter(_name, tool) {
|
|
48
|
-
return !tool.disabled && tool.type !== "backend";
|
|
48
|
+
return !tool.disabled && tool.type !== "backend" && (tool.type !== "frontend" || tool.execute !== void 0);
|
|
49
|
+
}
|
|
50
|
+
function toolHasUploadableParameters(tool) {
|
|
51
|
+
return tool.parameters !== void 0 && !tool.unstable_backendDefault?.parameters;
|
|
49
52
|
}
|
|
50
53
|
/**
|
|
51
54
|
* Converts a record of tools to a record of tool definitions with JSON Schema parameters.
|
|
@@ -59,7 +62,7 @@ function defaultToolFilter(_name, tool) {
|
|
|
59
62
|
function toToolsJSONSchema(tools, options = {}) {
|
|
60
63
|
if (!tools) return {};
|
|
61
64
|
const filter = options.filter ?? defaultToolFilter;
|
|
62
|
-
return Object.fromEntries(Object.entries(tools).filter(([name, tool]) => filter(name, tool)
|
|
65
|
+
return Object.fromEntries(Object.entries(tools).filter(([name, tool]) => filter(name, tool)).filter((entry) => toolHasUploadableParameters(entry[1])).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([name, tool]) => [name, {
|
|
63
66
|
...tool.description && { description: tool.description },
|
|
64
67
|
parameters: toJSONSchema(tool.parameters),
|
|
65
68
|
...tool.providerOptions && { providerOptions: tool.providerOptions }
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"schema-utils.js","names":[],"sources":["../../../src/core/tool/schema-utils.ts"],"sourcesContent":["import type { JSONSchema7 } from \"json-schema\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { ProviderOptions, Tool } from \"./tool-types\";\n\n/**\n * Type for a tool definition with JSON Schema parameters.\n */\nexport type ToolJSONSchema = {\n description?: string;\n parameters: JSONSchema7;\n providerOptions?: ProviderOptions;\n};\n\nexport type ToToolsJSONSchemaOptions = {\n /**\n * Filter to determine which tools to include.\n * Defaults to excluding disabled tools and backend tools.\n */\n filter?: (name: string, tool: Tool) => boolean;\n};\n\nfunction isStandardSchema(schema: unknown): schema is StandardSchemaV1 & {\n \"~standard\": StandardSchemaV1[\"~standard\"] & {\n toJSONSchema?: () => unknown;\n jsonSchema?: { input?: () => unknown; output?: () => unknown };\n };\n} {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"~standard\" in schema &&\n typeof (schema as StandardSchemaV1)[\"~standard\"] === \"object\"\n );\n}\n\nfunction hasToJSONSchemaMethod(\n schema: unknown,\n): schema is { toJSONSchema: () => unknown } {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"toJSONSchema\" in schema &&\n typeof (schema as { toJSONSchema: unknown }).toJSONSchema === \"function\"\n );\n}\n\nfunction hasToJSONMethod(schema: unknown): schema is { toJSON: () => unknown } {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"toJSON\" in schema &&\n typeof (schema as { toJSON: unknown }).toJSON === \"function\"\n );\n}\n\n/**\n * Converts a schema to JSONSchema7.\n * Supports:\n * - StandardSchemaV1 with ~standard.toJSONSchema (e.g., Zod v4)\n * - StandardSchemaV1 with ~standard.jsonSchema.input() (e.g., Zod v4)\n * - Objects with toJSONSchema() method (e.g., Zod v4)\n * - Objects with toJSON() method\n * - Plain JSONSchema7 objects (must have a \"type\" property)\n */\nexport function toJSONSchema(\n schema: StandardSchemaV1 | JSONSchema7,\n): JSONSchema7 {\n // StandardSchemaV1 with ~standard.toJSONSchema (e.g., Zod v4)\n if (isStandardSchema(schema)) {\n const toJSONSchemaMethod = schema[\"~standard\"].toJSONSchema;\n if (typeof toJSONSchemaMethod === \"function\") {\n return toJSONSchemaMethod() as JSONSchema7;\n }\n\n // StandardSchemaV1 with ~standard.jsonSchema.input()\n const jsonSchema = schema[\"~standard\"].jsonSchema;\n if (\n typeof jsonSchema === \"object\" &&\n jsonSchema !== null &&\n typeof jsonSchema.input === \"function\"\n ) {\n return jsonSchema.input() as JSONSchema7;\n }\n }\n\n // toJSONSchema method on the schema itself\n if (hasToJSONSchemaMethod(schema)) {\n return schema.toJSONSchema() as JSONSchema7;\n }\n\n // toJSON method on the schema\n if (hasToJSONMethod(schema)) {\n return schema.toJSON() as JSONSchema7;\n }\n\n // If it's a Standard Schema that we couldn't convert, throw a helpful error\n if (isStandardSchema(schema)) {\n throw new Error(\n \"Could not convert schema to JSON Schema. \" +\n \"The schema implements Standard Schema but does not support JSON Schema conversion. \" +\n \"If you are using Zod, please upgrade to Zod v4 (npm install zod@latest). \" +\n \"Alternatively, pass a plain JSON Schema object instead.\",\n );\n }\n\n // Already a plain JSONSchema7\n return schema as JSONSchema7;\n}\n\n/**\n * Returns a copy of the JSON Schema with `required` removed recursively,\n * making every property optional. Array item schemas are left unchanged.\n */\nexport function toPartialJSONSchema(schema: JSONSchema7): JSONSchema7 {\n const { required: _, ...result } = schema;\n\n if (result.properties) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, prop]) => {\n if (typeof prop === \"object\" && prop !== null && !Array.isArray(prop)) {\n const p = prop as JSONSchema7;\n return [key, p.properties != null ? toPartialJSONSchema(p) : prop];\n }\n return [key, prop];\n }),\n );\n }\n\n return result;\n}\n\nfunction defaultToolFilter(_name: string, tool: Tool): boolean {\n return !tool.disabled
|
|
1
|
+
{"version":3,"file":"schema-utils.js","names":[],"sources":["../../../src/core/tool/schema-utils.ts"],"sourcesContent":["import type { JSONSchema7 } from \"json-schema\";\nimport type { StandardSchemaV1 } from \"@standard-schema/spec\";\nimport type { ProviderOptions, Tool } from \"./tool-types\";\n\n/**\n * Type for a tool definition with JSON Schema parameters.\n */\nexport type ToolJSONSchema = {\n description?: string;\n parameters: JSONSchema7;\n providerOptions?: ProviderOptions;\n};\n\nexport type ToToolsJSONSchemaOptions = {\n /**\n * Filter to determine which tools to include.\n * Defaults to excluding disabled tools and backend tools.\n *\n * Tools with backend-default parameters are always excluded.\n */\n filter?: (name: string, tool: Tool) => boolean;\n};\n\nfunction isStandardSchema(schema: unknown): schema is StandardSchemaV1 & {\n \"~standard\": StandardSchemaV1[\"~standard\"] & {\n toJSONSchema?: () => unknown;\n jsonSchema?: { input?: () => unknown; output?: () => unknown };\n };\n} {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"~standard\" in schema &&\n typeof (schema as StandardSchemaV1)[\"~standard\"] === \"object\"\n );\n}\n\nfunction hasToJSONSchemaMethod(\n schema: unknown,\n): schema is { toJSONSchema: () => unknown } {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"toJSONSchema\" in schema &&\n typeof (schema as { toJSONSchema: unknown }).toJSONSchema === \"function\"\n );\n}\n\nfunction hasToJSONMethod(schema: unknown): schema is { toJSON: () => unknown } {\n return (\n typeof schema === \"object\" &&\n schema !== null &&\n \"toJSON\" in schema &&\n typeof (schema as { toJSON: unknown }).toJSON === \"function\"\n );\n}\n\n/**\n * Converts a schema to JSONSchema7.\n * Supports:\n * - StandardSchemaV1 with ~standard.toJSONSchema (e.g., Zod v4)\n * - StandardSchemaV1 with ~standard.jsonSchema.input() (e.g., Zod v4)\n * - Objects with toJSONSchema() method (e.g., Zod v4)\n * - Objects with toJSON() method\n * - Plain JSONSchema7 objects (must have a \"type\" property)\n */\nexport function toJSONSchema(\n schema: StandardSchemaV1 | JSONSchema7,\n): JSONSchema7 {\n // StandardSchemaV1 with ~standard.toJSONSchema (e.g., Zod v4)\n if (isStandardSchema(schema)) {\n const toJSONSchemaMethod = schema[\"~standard\"].toJSONSchema;\n if (typeof toJSONSchemaMethod === \"function\") {\n return toJSONSchemaMethod() as JSONSchema7;\n }\n\n // StandardSchemaV1 with ~standard.jsonSchema.input()\n const jsonSchema = schema[\"~standard\"].jsonSchema;\n if (\n typeof jsonSchema === \"object\" &&\n jsonSchema !== null &&\n typeof jsonSchema.input === \"function\"\n ) {\n return jsonSchema.input() as JSONSchema7;\n }\n }\n\n // toJSONSchema method on the schema itself\n if (hasToJSONSchemaMethod(schema)) {\n return schema.toJSONSchema() as JSONSchema7;\n }\n\n // toJSON method on the schema\n if (hasToJSONMethod(schema)) {\n return schema.toJSON() as JSONSchema7;\n }\n\n // If it's a Standard Schema that we couldn't convert, throw a helpful error\n if (isStandardSchema(schema)) {\n throw new Error(\n \"Could not convert schema to JSON Schema. \" +\n \"The schema implements Standard Schema but does not support JSON Schema conversion. \" +\n \"If you are using Zod, please upgrade to Zod v4 (npm install zod@latest). \" +\n \"Alternatively, pass a plain JSON Schema object instead.\",\n );\n }\n\n // Already a plain JSONSchema7\n return schema as JSONSchema7;\n}\n\n/**\n * Returns a copy of the JSON Schema with `required` removed recursively,\n * making every property optional. Array item schemas are left unchanged.\n */\nexport function toPartialJSONSchema(schema: JSONSchema7): JSONSchema7 {\n const { required: _, ...result } = schema;\n\n if (result.properties) {\n result.properties = Object.fromEntries(\n Object.entries(result.properties).map(([key, prop]) => {\n if (typeof prop === \"object\" && prop !== null && !Array.isArray(prop)) {\n const p = prop as JSONSchema7;\n return [key, p.properties != null ? toPartialJSONSchema(p) : prop];\n }\n return [key, prop];\n }),\n );\n }\n\n return result;\n}\n\nfunction defaultToolFilter(_name: string, tool: Tool): boolean {\n return (\n !tool.disabled &&\n tool.type !== \"backend\" &&\n (tool.type !== \"frontend\" || tool.execute !== undefined)\n );\n}\n\nfunction toolHasUploadableParameters(\n tool: Tool,\n): tool is Tool & { parameters: NonNullable<Tool[\"parameters\"]> } {\n return (\n tool.parameters !== undefined && !tool.unstable_backendDefault?.parameters\n );\n}\n\n/**\n * Converts a record of tools to a record of tool definitions with JSON Schema parameters.\n * By default, filters out disabled tools and backend tools.\n *\n * Entries are emitted in alphabetical order so the resulting request body is\n * byte-identical regardless of the order in which tools were registered. This\n * keeps provider prompt caches stable across renders that mount tools in\n * different orders.\n */\nexport function toToolsJSONSchema(\n tools: Record<string, Tool> | undefined,\n options: ToToolsJSONSchemaOptions = {},\n): Record<string, ToolJSONSchema> {\n if (!tools) return {};\n\n const filter = options.filter ?? defaultToolFilter;\n\n return Object.fromEntries(\n Object.entries(tools)\n .filter(([name, tool]) => filter(name, tool))\n .filter(\n (\n entry,\n ): entry is [\n string,\n Tool & { parameters: NonNullable<Tool[\"parameters\"]> },\n ] => toolHasUploadableParameters(entry[1]),\n )\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([name, tool]) => [\n name,\n {\n ...(tool.description && { description: tool.description }),\n parameters: toJSONSchema(tool.parameters),\n ...(tool.providerOptions && {\n providerOptions: tool.providerOptions,\n }),\n },\n ]),\n );\n}\n"],"mappings":";AAuBA,SAAS,iBAAiB,QAKxB;CACA,OACE,OAAO,WAAW,YAClB,WAAW,QACX,eAAe,UACf,OAAQ,OAA4B,iBAAiB;AAEzD;AAEA,SAAS,sBACP,QAC2C;CAC3C,OACE,OAAO,WAAW,YAClB,WAAW,QACX,kBAAkB,UAClB,OAAQ,OAAqC,iBAAiB;AAElE;AAEA,SAAS,gBAAgB,QAAsD;CAC7E,OACE,OAAO,WAAW,YAClB,WAAW,QACX,YAAY,UACZ,OAAQ,OAA+B,WAAW;AAEtD;;;;;;;;;;AAWA,SAAgB,aACd,QACa;CAEb,IAAI,iBAAiB,MAAM,GAAG;EAC5B,MAAM,qBAAqB,OAAO,YAAY,CAAC;EAC/C,IAAI,OAAO,uBAAuB,YAChC,OAAO,mBAAmB;EAI5B,MAAM,aAAa,OAAO,YAAY,CAAC;EACvC,IACE,OAAO,eAAe,YACtB,eAAe,QACf,OAAO,WAAW,UAAU,YAE5B,OAAO,WAAW,MAAM;CAE5B;CAGA,IAAI,sBAAsB,MAAM,GAC9B,OAAO,OAAO,aAAa;CAI7B,IAAI,gBAAgB,MAAM,GACxB,OAAO,OAAO,OAAO;CAIvB,IAAI,iBAAiB,MAAM,GACzB,MAAM,IAAI,MACR,8PAIF;CAIF,OAAO;AACT;;;;;AAMA,SAAgB,oBAAoB,QAAkC;CACpE,MAAM,EAAE,UAAU,GAAG,GAAG,WAAW;CAEnC,IAAI,OAAO,YACT,OAAO,aAAa,OAAO,YACzB,OAAO,QAAQ,OAAO,UAAU,CAAC,CAAC,KAAK,CAAC,KAAK,UAAU;EACrD,IAAI,OAAO,SAAS,YAAY,SAAS,QAAQ,CAAC,MAAM,QAAQ,IAAI,GAAG;GACrE,MAAM,IAAI;GACV,OAAO,CAAC,KAAK,EAAE,cAAc,OAAO,oBAAoB,CAAC,IAAI,IAAI;EACnE;EACA,OAAO,CAAC,KAAK,IAAI;CACnB,CAAC,CACH;CAGF,OAAO;AACT;AAEA,SAAS,kBAAkB,OAAe,MAAqB;CAC7D,OACE,CAAC,KAAK,YACN,KAAK,SAAS,cACb,KAAK,SAAS,cAAc,KAAK,YAAY,KAAA;AAElD;AAEA,SAAS,4BACP,MACgE;CAChE,OACE,KAAK,eAAe,KAAA,KAAa,CAAC,KAAK,yBAAyB;AAEpE;;;;;;;;;;AAWA,SAAgB,kBACd,OACA,UAAoC,CAAC,GACL;CAChC,IAAI,CAAC,OAAO,OAAO,CAAC;CAEpB,MAAM,SAAS,QAAQ,UAAU;CAEjC,OAAO,OAAO,YACZ,OAAO,QAAQ,KAAK,CAAC,CAClB,QAAQ,CAAC,MAAM,UAAU,OAAO,MAAM,IAAI,CAAC,CAAC,CAC5C,QAEG,UAIG,4BAA4B,MAAM,EAAE,CAC3C,CAAC,CACA,MAAM,CAAC,IAAI,CAAC,OAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,CAAE,CAAC,CAChD,KAAK,CAAC,MAAM,UAAU,CACrB,MACA;EACE,GAAI,KAAK,eAAe,EAAE,aAAa,KAAK,YAAY;EACxD,YAAY,aAAa,KAAK,UAAU;EACxC,GAAI,KAAK,mBAAmB,EAC1B,iBAAiB,KAAK,gBACxB;CACF,CACF,CAAC,CACL;AACF"}
|
|
@@ -190,7 +190,7 @@ type FrontendTool<TArgs extends Record<string, unknown> = Record<string, unknown
|
|
|
190
190
|
description?: string | undefined; /** Schema for the arguments the model must provide when calling the tool. */
|
|
191
191
|
parameters: StandardSchemaV1<TArgs> | JSONSchema7; /** Prevents the tool from being exposed to the model while true. */
|
|
192
192
|
disabled?: boolean; /** Executes the tool after the model provides valid arguments. */
|
|
193
|
-
execute
|
|
193
|
+
execute?: ToolExecuteFunction<TArgs, TResult>; /** Converts the execution result into model-visible output. */
|
|
194
194
|
toModelOutput?: ToolModelOutputFunction<TArgs, TResult>; /** Handles invalid tool arguments when schema validation fails. */
|
|
195
195
|
experimental_onSchemaValidationError?: OnSchemaValidationErrorFunction<TResult>;
|
|
196
196
|
providerOptions?: ProviderOptions;
|
|
@@ -206,6 +206,45 @@ type HumanTool<TArgs extends Record<string, unknown> = Record<string, unknown>,
|
|
|
206
206
|
experimental_onSchemaValidationError?: undefined;
|
|
207
207
|
providerOptions?: ProviderOptions;
|
|
208
208
|
};
|
|
209
|
+
type ProviderTool<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = ToolBase<TArgs, TResult> & {
|
|
210
|
+
/** Tool executed by the LLM provider rather than assistant-ui. */type: "provider"; /** Provider-defined tool identifier, e.g. `openai.web_search_preview`. */
|
|
211
|
+
providerId: `${string}.${string}`; /** Schema used by adapters for validation and type plumbing. */
|
|
212
|
+
parameters?: StandardSchemaV1<TArgs> | JSONSchema7 | undefined; /** Provider-specific configuration for this tool. */
|
|
213
|
+
args: Record<string, unknown>;
|
|
214
|
+
/**
|
|
215
|
+
* Whether provider results may arrive after the originating response turn.
|
|
216
|
+
*/
|
|
217
|
+
supportsDeferredResults?: boolean;
|
|
218
|
+
description?: undefined;
|
|
219
|
+
disabled?: boolean;
|
|
220
|
+
execute?: undefined;
|
|
221
|
+
toModelOutput?: undefined;
|
|
222
|
+
experimental_onSchemaValidationError?: undefined;
|
|
223
|
+
providerOptions?: ProviderOptions;
|
|
224
|
+
};
|
|
225
|
+
type McpServerConfig = {
|
|
226
|
+
/** Connect to an MCP server over Streamable HTTP or server-sent events. */type: "http" | "sse";
|
|
227
|
+
url: string;
|
|
228
|
+
headers?: Record<string, string>;
|
|
229
|
+
redirect?: "follow" | "error";
|
|
230
|
+
} | {
|
|
231
|
+
/** Start and connect to a local MCP server over stdio. */type: "stdio";
|
|
232
|
+
command: string;
|
|
233
|
+
args?: readonly string[];
|
|
234
|
+
env?: Record<string, string>;
|
|
235
|
+
cwd?: string;
|
|
236
|
+
};
|
|
237
|
+
type McpTool = ToolBase<Record<string, unknown>, unknown> & {
|
|
238
|
+
/** Tools loaded from an MCP server by a server adapter. */type: "mcp";
|
|
239
|
+
server: McpServerConfig;
|
|
240
|
+
description?: undefined;
|
|
241
|
+
parameters?: undefined;
|
|
242
|
+
disabled?: boolean;
|
|
243
|
+
execute?: undefined;
|
|
244
|
+
toModelOutput?: undefined;
|
|
245
|
+
experimental_onSchemaValidationError?: undefined;
|
|
246
|
+
providerOptions?: undefined;
|
|
247
|
+
};
|
|
209
248
|
/**
|
|
210
249
|
* Definition for a tool that can be exposed to the assistant model.
|
|
211
250
|
*
|
|
@@ -247,20 +286,20 @@ type HumanTool<TArgs extends Record<string, unknown> = Record<string, unknown>,
|
|
|
247
286
|
* };
|
|
248
287
|
* ```
|
|
249
288
|
*/
|
|
250
|
-
type Tool<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = FrontendTool<TArgs, TResult> | BackendTool<TArgs, TResult> | HumanTool<TArgs, TResult> | ToolWithoutType<TArgs, TResult>;
|
|
289
|
+
type Tool<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = FrontendTool<TArgs, TResult> | BackendTool<TArgs, TResult> | HumanTool<TArgs, TResult> | ProviderTool<TArgs, TResult> | McpTool | ToolWithoutType<TArgs, TResult>;
|
|
251
290
|
/**
|
|
252
291
|
* A tool as *authored* — the permissive counterpart to {@link Tool}. Unlike
|
|
253
292
|
* {@link Tool}, a `backend` entry may declare `description`, `parameters`, and a
|
|
254
293
|
* server-side `execute`. Use this for the input of authoring helpers (e.g.
|
|
255
294
|
* `defineToolkit`); the canonical {@link Tool} is the output.
|
|
256
295
|
*/
|
|
257
|
-
type ToolDeclaration<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = FrontendTool<TArgs, TResult> | BackendToolDeclaration<TArgs, TResult> | HumanTool<TArgs, TResult> | ToolWithoutType<TArgs, TResult>;
|
|
296
|
+
type ToolDeclaration<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = FrontendTool<TArgs, TResult> | BackendToolDeclaration<TArgs, TResult> | HumanTool<TArgs, TResult> | ProviderTool<TArgs, TResult> | McpTool | ToolWithoutType<TArgs, TResult>;
|
|
258
297
|
/**
|
|
259
298
|
* @deprecated Use {@link Tool} with an explicit `type` field instead.
|
|
260
299
|
*/
|
|
261
|
-
type ToolWithoutType<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = (Omit<FrontendTool<TArgs, TResult>, "type"> | Omit<BackendTool<TArgs, TResult>, "type"> | Omit<HumanTool<TArgs, TResult>, "type">) & {
|
|
300
|
+
type ToolWithoutType<TArgs extends Record<string, unknown> = Record<string, unknown>, TResult = unknown> = (Omit<FrontendTool<TArgs, TResult>, "type"> | Omit<BackendTool<TArgs, TResult>, "type"> | Omit<HumanTool<TArgs, TResult>, "type"> | Omit<ProviderTool<TArgs, TResult>, "type">) & {
|
|
262
301
|
type?: undefined;
|
|
263
302
|
};
|
|
264
303
|
//#endregion
|
|
265
|
-
export { ProviderOptions, Tool, ToolCallArgsReader, ToolCallReader, ToolCallResponseReader, ToolDeclaration, ToolExecuteFunction, ToolExecutionContext, ToolModelContentPart, ToolModelOutputFunction, ToolStreamCallFunction, ToolWithoutType };
|
|
304
|
+
export { McpServerConfig, ProviderOptions, Tool, ToolCallArgsReader, ToolCallReader, ToolCallResponseReader, ToolDeclaration, ToolExecuteFunction, ToolExecutionContext, ToolModelContentPart, ToolModelOutputFunction, ToolStreamCallFunction, ToolWithoutType };
|
|
266
305
|
//# sourceMappingURL=tool-types.d.ts.map
|
|
@@ -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;EAuB9B;;;;;;EAfvB,UAAA,eAAyB,QAAA,CAAS,KAAA,MAC7B,SAAA,EAAW,KAAA,GACb,UAAA,CAAW,KAAA,EAAO,KAAA,+BACjB,mBAAA,CAAoB,CAAA;EAvBG;;;;;;EAgC3B,OAAA,eAAsB,QAAA,CAAS,KAAA,MAC1B,SAAA,EAAW,KAAA,GACb,UAAA,CAAW,KAAA,EAAO,KAAA,UAAe,KAAA,YAChC,mBAAA,CAAoB,CAAA;AAAA;AAAA,UAIT,sBAAA;EACf,GAAA,QAAW,OAAA,CAAQ,YAAA,CAAa,OAAA;AAAA;AAAA,UAGjB,cAAA,eACD,MAAA,oBAA0B,MAAA;EAGxC,IAAA,EAAM,kBAAA,CAAmB,KAAA;EACzB,QAAA,EAAU,sBAAA,CAAuB,OAAA;EApCV;;;;EA0CvB,MAAA;IACE,GAAA,QAAW,OAAA,CAAQ,OAAA;EAAA;AAAA;AAAA,KAIX,oBAAA;EAtCM,0DAwChB,UAAA,UAvCc;EAyCd,WAAA,EAAa,WAAA;EAzCuC;;;;EA8CpD,KAAA,GAAQ,OAAA,cAAqB,OAAO;AAAA;;;;KAM1B,mBAAA,oBACV,IAAA,EAAM,KAAA,EACN,OAAA,EAAS,oBAAA,KACN,OAAA,GAAU,OAAA,CAAQ,OAAA;AAAA,KAEX,sBAAA,eACI,MAAA,oBAA0B,MAAA,yCAGxC,MAAA,EAAQ,cAAA,CAAe,KAAA,EAAO,OAAA,GAC9B,OAAA,EAAS,oBAAA;AAAA,KAGN,+BAAA,YAA2C,mBAAmB,UAEjE,OAAA;;;;;;AAtDyB;AAI3B;;;;;;KAiEY,eAAA,GAAkB,MAAM,SAAS,MAAA;;;;;;;;AAhEJ;AAGzC;;;;;KA4EK,WAAA;AAAA,KAEA,QAAA,eACW,MAAA,oBAA0B,MAAA;EA1EP;;;EAgFjC,UAAA,GAAa,sBAAA,CAAuB,KAAA,EAAO,OAAA;EAzEvB;;;;;;;;;EAoFpB,OAAA,GAAU,WAAA;AAAA;AAAA,
|
|
1
|
+
{"version":3,"file":"tool-types.d.ts","names":[],"sources":["../../../src/core/tool/tool-types.ts"],"mappings":"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"}
|
|
@@ -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 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 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AssistantTransformStream.js","names":[],"sources":["../../../../src/core/utils/stream/AssistantTransformStream.ts"],"sourcesContent":["import type { AssistantStreamChunk } from \"../../AssistantStreamChunk\";\nimport {\n type AssistantStreamController,\n createAssistantStreamController,\n} from \"../../modules/assistant-stream\";\n\ntype AssistantTransformerFlushCallback = (\n controller: AssistantStreamController,\n) => void | PromiseLike<void>;\n\ntype AssistantTransformerStartCallback = (\n controller: AssistantStreamController,\n) => void | PromiseLike<void>;\n\ntype AssistantTransformerTransformCallback<I> = (\n chunk: I,\n controller: AssistantStreamController,\n) => void | PromiseLike<void>;\n\ntype AssistantTransformer<I> = {\n flush?: AssistantTransformerFlushCallback;\n start?: AssistantTransformerStartCallback;\n transform?: AssistantTransformerTransformCallback<I>;\n};\n\nexport class AssistantTransformStream<I> extends TransformStream<\n I,\n AssistantStreamChunk\n> {\n constructor(\n transformer: AssistantTransformer<I>,\n writableStrategy?: QueuingStrategy<I>,\n readableStrategy?: QueuingStrategy<AssistantStreamChunk>,\n ) {\n const [stream, runController] = createAssistantStreamController();\n\n let runPipeTask: Promise<void>;\n super(\n {\n start(controller) {\n runPipeTask = stream\n .pipeTo(\n new WritableStream({\n write(chunk) {\n controller.enqueue(chunk);\n },\n abort(reason?: any) {\n controller.error(reason);\n },\n close() {\n controller.terminate();\n },\n }),\n )\n .catch((error) => {\n controller.error(error);\n });\n\n return transformer.start?.(runController);\n },\n transform(chunk) {\n return transformer.transform?.(chunk, runController);\n },\n async flush() {\n await transformer.flush?.(runController);\n runController.close();\n await runPipeTask;\n },\n },\n writableStrategy,\n readableStrategy,\n );\n }\n}\n"],"mappings":";;AAyBA,IAAa,2BAAb,cAAiD,gBAG/C;CACA,YACE,aACA,kBACA,kBACA;EACA,MAAM,CAAC,QAAQ,iBAAiB,gCAAgC;EAEhE,IAAI;EACJ,MACE;GACE,MAAM,YAAY;IAChB,cAAc,OACX,OACC,IAAI,eAAe;KACjB,MAAM,OAAO;MACX,WAAW,QAAQ,KAAK;KAC1B;KACA,MAAM,QAAc;MAClB,WAAW,MAAM,MAAM;KACzB;KACA,QAAQ;MACN,WAAW,UAAU;KACvB;IACF,CAAC,CACH,
|
|
1
|
+
{"version":3,"file":"AssistantTransformStream.js","names":[],"sources":["../../../../src/core/utils/stream/AssistantTransformStream.ts"],"sourcesContent":["import type { AssistantStreamChunk } from \"../../AssistantStreamChunk\";\nimport {\n type AssistantStreamController,\n createAssistantStreamController,\n} from \"../../modules/assistant-stream\";\n\ntype AssistantTransformerFlushCallback = (\n controller: AssistantStreamController,\n) => void | PromiseLike<void>;\n\ntype AssistantTransformerStartCallback = (\n controller: AssistantStreamController,\n) => void | PromiseLike<void>;\n\ntype AssistantTransformerTransformCallback<I> = (\n chunk: I,\n controller: AssistantStreamController,\n) => void | PromiseLike<void>;\n\ntype AssistantTransformer<I> = {\n flush?: AssistantTransformerFlushCallback;\n start?: AssistantTransformerStartCallback;\n transform?: AssistantTransformerTransformCallback<I>;\n};\n\nexport class AssistantTransformStream<I> extends TransformStream<\n I,\n AssistantStreamChunk\n> {\n constructor(\n transformer: AssistantTransformer<I>,\n writableStrategy?: QueuingStrategy<I>,\n readableStrategy?: QueuingStrategy<AssistantStreamChunk>,\n ) {\n const [stream, runController] = createAssistantStreamController();\n\n let runPipeTask: Promise<void>;\n super(\n {\n start(controller) {\n runPipeTask = stream\n .pipeTo(\n new WritableStream({\n write(chunk) {\n controller.enqueue(chunk);\n },\n abort(reason?: any) {\n controller.error(reason);\n },\n close() {\n controller.terminate();\n },\n }),\n )\n .catch((error) => {\n controller.error(error);\n });\n\n return transformer.start?.(runController);\n },\n transform(chunk) {\n return transformer.transform?.(chunk, runController);\n },\n async flush() {\n await transformer.flush?.(runController);\n runController.close();\n await runPipeTask;\n },\n },\n writableStrategy,\n readableStrategy,\n );\n }\n}\n"],"mappings":";;AAyBA,IAAa,2BAAb,cAAiD,gBAG/C;CACA,YACE,aACA,kBACA,kBACA;EACA,MAAM,CAAC,QAAQ,iBAAiB,gCAAgC;EAEhE,IAAI;EACJ,MACE;GACE,MAAM,YAAY;IAChB,cAAc,OACX,OACC,IAAI,eAAe;KACjB,MAAM,OAAO;MACX,WAAW,QAAQ,KAAK;KAC1B;KACA,MAAM,QAAc;MAClB,WAAW,MAAM,MAAM;KACzB;KACA,QAAQ;MACN,WAAW,UAAU;KACvB;IACF,CAAC,CACH,CAAC,CACA,OAAO,UAAU;KAChB,WAAW,MAAM,KAAK;IACxB,CAAC;IAEH,OAAO,YAAY,QAAQ,aAAa;GAC1C;GACA,UAAU,OAAO;IACf,OAAO,YAAY,YAAY,OAAO,aAAa;GACrD;GACA,MAAM,QAAQ;IACZ,MAAM,YAAY,QAAQ,aAAa;IACvC,cAAc,MAAM;IACpB,MAAM;GACR;EACF,GACA,kBACA,gBACF;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"SSE.js","names":[],"sources":["../../../../src/core/utils/stream/SSE.ts"],"sourcesContent":["import { PipeableTransformStream } from \"./PipeableTransformStream\";\nimport { LineDecoderStream } from \"./LineDecoderStream\";\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\ntype SSEEvent = {\n event: string;\n data: string;\n id?: string | undefined;\n retry?: number | undefined;\n};\n\nclass SSEEventStream extends TransformStream<string, SSEEvent> {\n constructor() {\n let eventBuffer: Partial<SSEEvent> = {};\n let dataLines: string[] = [];\n\n super({\n start() {\n eventBuffer = {};\n dataLines = [];\n },\n transform(line, controller) {\n if (line.startsWith(\":\")) return; // Ignore comments\n\n if (line === \"\") {\n if (dataLines.length > 0) {\n controller.enqueue({\n event: eventBuffer.event || \"message\",\n data: dataLines.join(\"\\n\"),\n id: eventBuffer.id,\n retry: eventBuffer.retry,\n });\n }\n eventBuffer = {};\n dataLines = [];\n return;\n }\n\n const [field, ...rest] = line.split(\":\");\n const value = rest.join(\":\").trimStart();\n\n switch (field) {\n case \"event\":\n eventBuffer.event = value;\n break;\n case \"data\":\n dataLines.push(value);\n break;\n case \"id\":\n eventBuffer.id = value;\n break;\n case \"retry\":\n eventBuffer.retry = Number(value);\n break;\n }\n },\n flush(controller) {\n if (dataLines.length > 0) {\n controller.enqueue({\n event: eventBuffer.event || \"message\",\n data: dataLines.join(\"\\n\"),\n id: eventBuffer.id,\n retry: eventBuffer.retry,\n });\n }\n },\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 LineDecoderStream())\n .pipeThrough(new SSEEventStream())\n .pipeThrough(\n new TransformStream<SSEEvent, T>({\n transform(event, controller) {\n switch (event.event) {\n case \"message\":\n controller.enqueue(JSON.parse(event.data));\n break;\n default:\n throw new Error(`Unknown SSE event type: ${event.event}`);\n }\n },\n }),\n ),\n );\n }\n}\n"],"mappings":";;;AAGA,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,
|
|
1
|
+
{"version":3,"file":"SSE.js","names":[],"sources":["../../../../src/core/utils/stream/SSE.ts"],"sourcesContent":["import { PipeableTransformStream } from \"./PipeableTransformStream\";\nimport { LineDecoderStream } from \"./LineDecoderStream\";\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\ntype SSEEvent = {\n event: string;\n data: string;\n id?: string | undefined;\n retry?: number | undefined;\n};\n\nclass SSEEventStream extends TransformStream<string, SSEEvent> {\n constructor() {\n let eventBuffer: Partial<SSEEvent> = {};\n let dataLines: string[] = [];\n\n super({\n start() {\n eventBuffer = {};\n dataLines = [];\n },\n transform(line, controller) {\n if (line.startsWith(\":\")) return; // Ignore comments\n\n if (line === \"\") {\n if (dataLines.length > 0) {\n controller.enqueue({\n event: eventBuffer.event || \"message\",\n data: dataLines.join(\"\\n\"),\n id: eventBuffer.id,\n retry: eventBuffer.retry,\n });\n }\n eventBuffer = {};\n dataLines = [];\n return;\n }\n\n const [field, ...rest] = line.split(\":\");\n const value = rest.join(\":\").trimStart();\n\n switch (field) {\n case \"event\":\n eventBuffer.event = value;\n break;\n case \"data\":\n dataLines.push(value);\n break;\n case \"id\":\n eventBuffer.id = value;\n break;\n case \"retry\":\n eventBuffer.retry = Number(value);\n break;\n }\n },\n flush(controller) {\n if (dataLines.length > 0) {\n controller.enqueue({\n event: eventBuffer.event || \"message\",\n data: dataLines.join(\"\\n\"),\n id: eventBuffer.id,\n retry: eventBuffer.retry,\n });\n }\n },\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 LineDecoderStream())\n .pipeThrough(new SSEEventStream())\n .pipeThrough(\n new TransformStream<SSEEvent, T>({\n transform(event, controller) {\n switch (event.event) {\n case \"message\":\n controller.enqueue(JSON.parse(event.data));\n break;\n default:\n throw new Error(`Unknown SSE event type: ${event.event}`);\n }\n },\n }),\n ),\n );\n }\n}\n"],"mappings":";;;AAGA,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;AASA,IAAM,iBAAN,cAA6B,gBAAkC;CAC7D,cAAc;EACZ,IAAI,cAAiC,CAAC;EACtC,IAAI,YAAsB,CAAC;EAE3B,MAAM;GACJ,QAAQ;IACN,cAAc,CAAC;IACf,YAAY,CAAC;GACf;GACA,UAAU,MAAM,YAAY;IAC1B,IAAI,KAAK,WAAW,GAAG,GAAG;IAE1B,IAAI,SAAS,IAAI;KACf,IAAI,UAAU,SAAS,GACrB,WAAW,QAAQ;MACjB,OAAO,YAAY,SAAS;MAC5B,MAAM,UAAU,KAAK,IAAI;MACzB,IAAI,YAAY;MAChB,OAAO,YAAY;KACrB,CAAC;KAEH,cAAc,CAAC;KACf,YAAY,CAAC;KACb;IACF;IAEA,MAAM,CAAC,OAAO,GAAG,QAAQ,KAAK,MAAM,GAAG;IACvC,MAAM,QAAQ,KAAK,KAAK,GAAG,CAAC,CAAC,UAAU;IAEvC,QAAQ,OAAR;KACE,KAAK;MACH,YAAY,QAAQ;MACpB;KACF,KAAK;MACH,UAAU,KAAK,KAAK;MACpB;KACF,KAAK;MACH,YAAY,KAAK;MACjB;KACF,KAAK;MACH,YAAY,QAAQ,OAAO,KAAK;MAChC;IACJ;GACF;GACA,MAAM,YAAY;IAChB,IAAI,UAAU,SAAS,GACrB,WAAW,QAAQ;KACjB,OAAO,YAAY,SAAS;KAC5B,MAAM,UAAU,KAAK,IAAI;KACzB,IAAI,YAAY;KAChB,OAAO,YAAY;IACrB,CAAC;GAEL;EACF,CAAC;CACH;AACF;AAEA,IAAa,aAAb,cAAmC,wBAGjC;CACA,cAAc;EACZ,OAAO,aACL,SACG,YAAY,IAAI,kBAAkB,CAAC,CAAC,CACpC,YAAY,IAAI,kBAAkB,CAAC,CAAC,CACpC,YAAY,IAAI,eAAe,CAAC,CAAC,CACjC,YACC,IAAI,gBAA6B,EAC/B,UAAU,OAAO,YAAY;GAC3B,QAAQ,MAAM,OAAd;IACE,KAAK;KACH,WAAW,QAAQ,KAAK,MAAM,MAAM,IAAI,CAAC;KACzC;IACF,SACE,MAAM,IAAI,MAAM,2BAA2B,MAAM,OAAO;GAC5D;EACF,EACF,CAAC,CACH,CACJ;CACF;AACF"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"merge.js","names":[],"sources":["../../../../src/core/utils/stream/merge.ts"],"sourcesContent":["import type { AssistantStreamChunk } from \"../../AssistantStreamChunk\";\nimport { promiseWithResolvers } from \"../../../utils/promiseWithResolvers\";\n\ntype MergeStreamItem = {\n reader: ReadableStreamDefaultReader<AssistantStreamChunk>;\n promise?: Promise<unknown> | undefined;\n};\n\nexport const createMergeStream = () => {\n const list: MergeStreamItem[] = [];\n let sealed = false;\n let controller: ReadableStreamDefaultController<AssistantStreamChunk>;\n let currentPull: ReturnType<typeof promiseWithResolvers<void>> | undefined;\n\n const handlePull = (item: MergeStreamItem) => {\n if (!item.promise) {\n // TODO for most streams, we can directly pipeTo to avoid the microTask queue\n // add an option to eagerly pipe the stream to the merge stream\n // ideally, using assistant-stream w sync run method + piping to a sync WritableStream runs in the same microtask\n // this is useful because we often use AssistantStreams internally as a serialization utility, e. g. AssistantTransformStream\n // idea: avoid reader.read() by instead using a WritableStream & if (!hasPendingPull) await waitForPull()?\n item.promise = item.reader\n .read()\n .then(({ done, value }) => {\n item.promise = undefined;\n if (done) {\n list.splice(list.indexOf(item), 1);\n if (sealed && list.length === 0) {\n controller.close();\n }\n } else {\n controller.enqueue(value);\n }\n\n currentPull?.resolve();\n currentPull = undefined;\n })\n .catch((e) => {\n console.error(e);\n\n list.forEach((item) => {\n item.reader.cancel();\n });\n list.length = 0;\n\n controller.error(e);\n\n currentPull?.reject(e);\n currentPull = undefined;\n });\n }\n };\n\n const readable = new ReadableStream<AssistantStreamChunk>({\n start(c) {\n controller = c;\n },\n pull() {\n currentPull = promiseWithResolvers();\n list.forEach((item) => {\n handlePull(item);\n });\n\n return currentPull.promise;\n },\n cancel() {\n list.forEach((item) => {\n item.reader.cancel();\n });\n list.length = 0;\n },\n });\n\n return {\n readable,\n isSealed() {\n return sealed;\n },\n seal() {\n sealed = true;\n if (list.length === 0) controller.close();\n },\n addStream(stream: ReadableStream<AssistantStreamChunk>) {\n if (sealed)\n throw new Error(\n \"Cannot add streams after the run callback has settled.\",\n );\n\n const item = { reader: stream.getReader() };\n list.push(item);\n handlePull(item);\n },\n enqueue(chunk: AssistantStreamChunk) {\n this.addStream(\n new ReadableStream({\n start(c) {\n c.enqueue(chunk);\n c.close();\n },\n }),\n );\n },\n };\n};\n\n// TODO\n// export class SpanContainerMerger {\n// public get isSealed() {\n// return this.mergeStream.isSealed();\n// }\n\n// public get readable() {\n// return this.mergeStream.readable;\n// }\n\n// private subAllocator = new Counter();\n// private mergeStream = createMergeStream();\n\n// constructor() {\n// // id 0 is auto allocated\n// this.subAllocator.up();\n// }\n\n// add(stream: ReadableStream<AssistantStreamChunk>) {\n// this.mergeStream.addStream(\n// stream.pipeThrough(new SpanParentEncoder(this.subAllocator)),\n// );\n// }\n\n// enqueue(chunk: AssistantStreamChunk & { parentId: 0 }) {\n// this.mergeStream.addStream(\n// new ReadableStream({\n// start(c) {\n// c.enqueue(chunk);\n// c.close();\n// },\n// }),\n// );\n// }\n\n// seal() {\n// this.mergeStream.seal();\n// }\n// }\n\n// export class SpanContainerSplitter {\n// public writable;\n\n// private isSealed = false;\n// private writers = new Map<\n// number,\n// WritableStreamDefaultWriter<AssistantStreamChunk>\n// >();\n\n// private closeTasks: Promise<void>[] = [];\n\n// private allocator = new Counter();\n// private subAllocator = new Counter();\n\n// constructor() {\n// // id 0 is auto-allocated\n// this.allocator.up();\n\n// this.writable = new WritableStream({\n// write: (chunk) => {\n// const { type, parentId } = chunk;\n\n// const writer = this.writers.get(parentId);\n// if (writer === undefined) throw new Error(\"Parent id not found\");\n\n// writer.write(chunk);\n\n// if (type === \"span\") {\n// // allocate a new span id\n// this.writers.set(this.allocator.up(), writer);\n// }\n// if (type === \"finish\") {\n// this.writers.delete(parentId);\n// writer.close();\n\n// if (this.writers.size === 0) {\n// const closeTask = this.writable.close();\n// this.closeTasks.push(closeTask);\n// closeTask.then(() => {\n// this.closeTasks.splice(this.closeTasks.indexOf(closeTask), 1);\n// });\n// }\n// }\n// },\n// close: async () => {\n// if (this.writers.size > 0) throw new Error(\"Not all writers closed\");\n\n// // await and throw on any errors\n// await Promise.all(this.closeTasks);\n// },\n// });\n// }\n\n// add(stream: WritableStream<AssistantStreamChunk>) {\n// if (this.isSealed) throw new Error(\"Cannot add streams after sealing\");\n\n// const decoder = new SpanParentDecoder(this.subAllocator);\n// decoder.readable.pipeTo(stream);\n\n// this.writers.set(this.allocator.up(), decoder.writable.getWriter());\n// }\n\n// seal() {\n// this.isSealed = true;\n// if (this.writers.size === 0) this.writable.close();\n// }\n// }\n"],"mappings":";;AAQA,MAAa,0BAA0B;CACrC,MAAM,OAA0B,CAAC;CACjC,IAAI,SAAS;CACb,IAAI;CACJ,IAAI;CAEJ,MAAM,cAAc,SAA0B;EAC5C,IAAI,CAAC,KAAK,SAMR,KAAK,UAAU,KAAK,OACjB,KAAK,
|
|
1
|
+
{"version":3,"file":"merge.js","names":[],"sources":["../../../../src/core/utils/stream/merge.ts"],"sourcesContent":["import type { AssistantStreamChunk } from \"../../AssistantStreamChunk\";\nimport { promiseWithResolvers } from \"../../../utils/promiseWithResolvers\";\n\ntype MergeStreamItem = {\n reader: ReadableStreamDefaultReader<AssistantStreamChunk>;\n promise?: Promise<unknown> | undefined;\n};\n\nexport const createMergeStream = () => {\n const list: MergeStreamItem[] = [];\n let sealed = false;\n let controller: ReadableStreamDefaultController<AssistantStreamChunk>;\n let currentPull: ReturnType<typeof promiseWithResolvers<void>> | undefined;\n\n const handlePull = (item: MergeStreamItem) => {\n if (!item.promise) {\n // TODO for most streams, we can directly pipeTo to avoid the microTask queue\n // add an option to eagerly pipe the stream to the merge stream\n // ideally, using assistant-stream w sync run method + piping to a sync WritableStream runs in the same microtask\n // this is useful because we often use AssistantStreams internally as a serialization utility, e. g. AssistantTransformStream\n // idea: avoid reader.read() by instead using a WritableStream & if (!hasPendingPull) await waitForPull()?\n item.promise = item.reader\n .read()\n .then(({ done, value }) => {\n item.promise = undefined;\n if (done) {\n list.splice(list.indexOf(item), 1);\n if (sealed && list.length === 0) {\n controller.close();\n }\n } else {\n controller.enqueue(value);\n }\n\n currentPull?.resolve();\n currentPull = undefined;\n })\n .catch((e) => {\n console.error(e);\n\n list.forEach((item) => {\n item.reader.cancel();\n });\n list.length = 0;\n\n controller.error(e);\n\n currentPull?.reject(e);\n currentPull = undefined;\n });\n }\n };\n\n const readable = new ReadableStream<AssistantStreamChunk>({\n start(c) {\n controller = c;\n },\n pull() {\n currentPull = promiseWithResolvers();\n list.forEach((item) => {\n handlePull(item);\n });\n\n return currentPull.promise;\n },\n cancel() {\n list.forEach((item) => {\n item.reader.cancel();\n });\n list.length = 0;\n },\n });\n\n return {\n readable,\n isSealed() {\n return sealed;\n },\n seal() {\n sealed = true;\n if (list.length === 0) controller.close();\n },\n addStream(stream: ReadableStream<AssistantStreamChunk>) {\n if (sealed)\n throw new Error(\n \"Cannot add streams after the run callback has settled.\",\n );\n\n const item = { reader: stream.getReader() };\n list.push(item);\n handlePull(item);\n },\n enqueue(chunk: AssistantStreamChunk) {\n this.addStream(\n new ReadableStream({\n start(c) {\n c.enqueue(chunk);\n c.close();\n },\n }),\n );\n },\n };\n};\n\n// TODO\n// export class SpanContainerMerger {\n// public get isSealed() {\n// return this.mergeStream.isSealed();\n// }\n\n// public get readable() {\n// return this.mergeStream.readable;\n// }\n\n// private subAllocator = new Counter();\n// private mergeStream = createMergeStream();\n\n// constructor() {\n// // id 0 is auto allocated\n// this.subAllocator.up();\n// }\n\n// add(stream: ReadableStream<AssistantStreamChunk>) {\n// this.mergeStream.addStream(\n// stream.pipeThrough(new SpanParentEncoder(this.subAllocator)),\n// );\n// }\n\n// enqueue(chunk: AssistantStreamChunk & { parentId: 0 }) {\n// this.mergeStream.addStream(\n// new ReadableStream({\n// start(c) {\n// c.enqueue(chunk);\n// c.close();\n// },\n// }),\n// );\n// }\n\n// seal() {\n// this.mergeStream.seal();\n// }\n// }\n\n// export class SpanContainerSplitter {\n// public writable;\n\n// private isSealed = false;\n// private writers = new Map<\n// number,\n// WritableStreamDefaultWriter<AssistantStreamChunk>\n// >();\n\n// private closeTasks: Promise<void>[] = [];\n\n// private allocator = new Counter();\n// private subAllocator = new Counter();\n\n// constructor() {\n// // id 0 is auto-allocated\n// this.allocator.up();\n\n// this.writable = new WritableStream({\n// write: (chunk) => {\n// const { type, parentId } = chunk;\n\n// const writer = this.writers.get(parentId);\n// if (writer === undefined) throw new Error(\"Parent id not found\");\n\n// writer.write(chunk);\n\n// if (type === \"span\") {\n// // allocate a new span id\n// this.writers.set(this.allocator.up(), writer);\n// }\n// if (type === \"finish\") {\n// this.writers.delete(parentId);\n// writer.close();\n\n// if (this.writers.size === 0) {\n// const closeTask = this.writable.close();\n// this.closeTasks.push(closeTask);\n// closeTask.then(() => {\n// this.closeTasks.splice(this.closeTasks.indexOf(closeTask), 1);\n// });\n// }\n// }\n// },\n// close: async () => {\n// if (this.writers.size > 0) throw new Error(\"Not all writers closed\");\n\n// // await and throw on any errors\n// await Promise.all(this.closeTasks);\n// },\n// });\n// }\n\n// add(stream: WritableStream<AssistantStreamChunk>) {\n// if (this.isSealed) throw new Error(\"Cannot add streams after sealing\");\n\n// const decoder = new SpanParentDecoder(this.subAllocator);\n// decoder.readable.pipeTo(stream);\n\n// this.writers.set(this.allocator.up(), decoder.writable.getWriter());\n// }\n\n// seal() {\n// this.isSealed = true;\n// if (this.writers.size === 0) this.writable.close();\n// }\n// }\n"],"mappings":";;AAQA,MAAa,0BAA0B;CACrC,MAAM,OAA0B,CAAC;CACjC,IAAI,SAAS;CACb,IAAI;CACJ,IAAI;CAEJ,MAAM,cAAc,SAA0B;EAC5C,IAAI,CAAC,KAAK,SAMR,KAAK,UAAU,KAAK,OACjB,KAAK,CAAC,CACN,MAAM,EAAE,MAAM,YAAY;GACzB,KAAK,UAAU,KAAA;GACf,IAAI,MAAM;IACR,KAAK,OAAO,KAAK,QAAQ,IAAI,GAAG,CAAC;IACjC,IAAI,UAAU,KAAK,WAAW,GAC5B,WAAW,MAAM;GAErB,OACE,WAAW,QAAQ,KAAK;GAG1B,aAAa,QAAQ;GACrB,cAAc,KAAA;EAChB,CAAC,CAAC,CACD,OAAO,MAAM;GACZ,QAAQ,MAAM,CAAC;GAEf,KAAK,SAAS,SAAS;IACrB,KAAK,OAAO,OAAO;GACrB,CAAC;GACD,KAAK,SAAS;GAEd,WAAW,MAAM,CAAC;GAElB,aAAa,OAAO,CAAC;GACrB,cAAc,KAAA;EAChB,CAAC;CAEP;CAsBA,OAAO;EACL,UAAA,IArBmB,eAAqC;GACxD,MAAM,GAAG;IACP,aAAa;GACf;GACA,OAAO;IACL,cAAc,qBAAqB;IACnC,KAAK,SAAS,SAAS;KACrB,WAAW,IAAI;IACjB,CAAC;IAED,OAAO,YAAY;GACrB;GACA,SAAS;IACP,KAAK,SAAS,SAAS;KACrB,KAAK,OAAO,OAAO;IACrB,CAAC;IACD,KAAK,SAAS;GAChB;EACF,CAGS;EACP,WAAW;GACT,OAAO;EACT;EACA,OAAO;GACL,SAAS;GACT,IAAI,KAAK,WAAW,GAAG,WAAW,MAAM;EAC1C;EACA,UAAU,QAA8C;GACtD,IAAI,QACF,MAAM,IAAI,MACR,wDACF;GAEF,MAAM,OAAO,EAAE,QAAQ,OAAO,UAAU,EAAE;GAC1C,KAAK,KAAK,IAAI;GACd,WAAW,IAAI;EACjB;EACA,QAAQ,OAA6B;GACnC,KAAK,UACH,IAAI,eAAe,EACjB,MAAM,GAAG;IACP,EAAE,QAAQ,KAAK;IACf,EAAE,MAAM;GACV,EACF,CAAC,CACH;EACF;CACF;AACF"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { TextStreamController } from "./core/modules/text.js";
|
|
2
|
-
import { ProviderOptions, Tool, ToolCallReader, ToolDeclaration, ToolModelContentPart, ToolModelOutputFunction } from "./core/tool/tool-types.js";
|
|
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
5
|
import { AssistantMessage, AssistantMessageTiming, DataPart } from "./core/utils/types.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 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 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 };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ResumableStreamContext.js","names":[],"sources":["../../src/resumable/ResumableStreamContext.ts"],"sourcesContent":["import { ResumableStreamError } from \"./errors\";\nimport type {\n ResumableStreamRole,\n ResumableStreamStatus,\n ResumableStreamStore,\n} from \"./types\";\n\nexport type ResumableStreamContextOptions = {\n readonly store: ResumableStreamStore;\n readonly ttlMs?: number;\n /**\n * Required on serverless runtimes that terminate background work when the\n * request handler returns (Vercel, Cloudflare). Pass `after` from\n * `next/server` so the producer task outlives the response.\n */\n readonly waitUntil?: (promise: Promise<unknown>) => void;\n readonly onAcquire?: (streamId: string, role: ResumableStreamRole) => void;\n readonly onAppend?: (streamId: string, byteLength: number) => void;\n readonly onFinalize?: (\n streamId: string,\n status: \"done\" | \"error\",\n error?: string,\n ) => void;\n readonly onError?: (streamId: string, error: unknown) => void;\n};\n\nexport interface ResumableStreamContext {\n /** Producer or consumer entrypoint. Atomically elects the role. */\n run(\n streamId: string,\n makeStream: () => ReadableStream<Uint8Array>,\n ): Promise<ReadableStream<Uint8Array>>;\n\n /** Returns `null` when the stream does not exist. */\n resume(streamId: string): Promise<ReadableStream<Uint8Array> | null>;\n\n /** Throws `ResumableStreamError(\"missing\")` when the stream does not exist. */\n requireResume(streamId: string): Promise<ReadableStream<Uint8Array>>;\n\n status(streamId: string): Promise<ResumableStreamStatus>;\n\n delete(streamId: string): Promise<void>;\n}\n\nexport function createResumableStreamContext(\n options: ResumableStreamContextOptions,\n): ResumableStreamContext {\n const { store, waitUntil, onAcquire, onAppend, onFinalize, onError } =\n options;\n const acquireOptions =\n options.ttlMs !== undefined ? { ttlMs: options.ttlMs } : undefined;\n\n return {\n async run(streamId, makeStream) {\n const role = await store.acquire(streamId, acquireOptions);\n onAcquire?.(streamId, role);\n if (role === \"producer\") {\n startProducerTask(store, streamId, makeStream, {\n waitUntil,\n onAppend,\n onFinalize,\n onError,\n });\n }\n return readFromStore(store, streamId);\n },\n\n async resume(streamId) {\n const status = await store.status(streamId);\n if (status === \"missing\") return null;\n return readFromStore(store, streamId);\n },\n\n async requireResume(streamId) {\n const status = await store.status(streamId);\n if (status === \"missing\") {\n throw new ResumableStreamError(\n \"missing\",\n `resumable stream not found: ${streamId}`,\n );\n }\n return readFromStore(store, streamId);\n },\n\n async status(streamId) {\n return store.status(streamId);\n },\n\n async delete(streamId) {\n await store.delete(streamId);\n },\n };\n}\n\ntype ProducerHooks = {\n readonly waitUntil: ((promise: Promise<unknown>) => void) | undefined;\n readonly onAppend:\n | ((streamId: string, byteLength: number) => void)\n | undefined;\n readonly onFinalize:\n | ((streamId: string, status: \"done\" | \"error\", error?: string) => void)\n | undefined;\n readonly onError: ((streamId: string, error: unknown) => void) | undefined;\n};\n\nfunction startProducerTask(\n store: ResumableStreamStore,\n streamId: string,\n makeStream: () => ReadableStream<Uint8Array>,\n hooks: ProducerHooks,\n): void {\n const { waitUntil, onAppend, onFinalize, onError } = hooks;\n const task = (async () => {\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let cancelled = false;\n try {\n reader = makeStream().getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n await store.append(streamId, value);\n onAppend?.(streamId, value.byteLength);\n }\n await store.finalize(streamId, \"done\");\n onFinalize?.(streamId, \"done\");\n } catch (err) {\n cancelled = true;\n onError?.(streamId, err);\n const message = err instanceof Error ? err.message : String(err);\n try {\n await reader?.cancel(err);\n } catch (cancelErr) {\n console.error(\"resumable stream reader cancel failed:\", cancelErr);\n }\n try {\n await store.finalize(streamId, \"error\", message);\n onFinalize?.(streamId, \"error\", message);\n } catch (finalizeErr) {\n console.error(\"resumable stream finalize failed:\", finalizeErr);\n }\n } finally {\n if (!cancelled) reader?.releaseLock();\n }\n })();\n\n if (waitUntil) waitUntil(task);\n task.catch((err) => {\n console.error(\"resumable producer task failed:\", err);\n });\n}\n\nfunction readFromStore(\n store: ResumableStreamStore,\n streamId: string,\n): ReadableStream<Uint8Array> {\n const ac = new AbortController();\n let iterator: AsyncIterator<{ chunk: Uint8Array }> | undefined;\n\n return new ReadableStream<Uint8Array>({\n start() {\n iterator = store.read(streamId, \"\", ac.signal)[Symbol.asyncIterator]();\n },\n async pull(controller) {\n try {\n if (!iterator) return;\n const { done, value } = await iterator.next();\n if (done) {\n controller.close();\n return;\n }\n controller.enqueue(value.chunk);\n } catch (err) {\n // the platform never calls cancel() on errored streams, so unwind\n // the store iterator and abort the signal explicitly.\n ac.abort();\n try {\n await iterator?.return?.();\n } catch {}\n controller.error(err);\n }\n },\n cancel() {\n ac.abort();\n iterator?.return?.().catch(() => {});\n },\n });\n}\n"],"mappings":";;AA4CA,SAAgB,6BACd,SACwB;CACxB,MAAM,EAAE,OAAO,WAAW,WAAW,UAAU,YAAY,YACzD;CACF,MAAM,iBACJ,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,KAAA;CAE3D,OAAO;EACL,MAAM,IAAI,UAAU,YAAY;GAC9B,MAAM,OAAO,MAAM,MAAM,QAAQ,UAAU,cAAc;GACzD,YAAY,UAAU,IAAI;GAC1B,IAAI,SAAS,YACX,kBAAkB,OAAO,UAAU,YAAY;IAC7C;IACA;IACA;IACA;GACF,CAAC;GAEH,OAAO,cAAc,OAAO,QAAQ;EACtC;EAEA,MAAM,OAAO,UAAU;GAErB,IAAI,MADiB,MAAM,OAAO,QAAQ,MAC3B,WAAW,OAAO;GACjC,OAAO,cAAc,OAAO,QAAQ;EACtC;EAEA,MAAM,cAAc,UAAU;GAE5B,IAAI,MADiB,MAAM,OAAO,QAAQ,MAC3B,WACb,MAAM,IAAI,qBACR,WACA,+BAA+B,UACjC;GAEF,OAAO,cAAc,OAAO,QAAQ;EACtC;EAEA,MAAM,OAAO,UAAU;GACrB,OAAO,MAAM,OAAO,QAAQ;EAC9B;EAEA,MAAM,OAAO,UAAU;GACrB,MAAM,MAAM,OAAO,QAAQ;EAC7B;CACF;AACF;AAaA,SAAS,kBACP,OACA,UACA,YACA,OACM;CACN,MAAM,EAAE,WAAW,UAAU,YAAY,YAAY;CACrD,MAAM,QAAQ,YAAY;EACxB,IAAI;EACJ,IAAI,YAAY;EAChB,IAAI;GACF,SAAS,WAAW,
|
|
1
|
+
{"version":3,"file":"ResumableStreamContext.js","names":[],"sources":["../../src/resumable/ResumableStreamContext.ts"],"sourcesContent":["import { ResumableStreamError } from \"./errors\";\nimport type {\n ResumableStreamRole,\n ResumableStreamStatus,\n ResumableStreamStore,\n} from \"./types\";\n\nexport type ResumableStreamContextOptions = {\n readonly store: ResumableStreamStore;\n readonly ttlMs?: number;\n /**\n * Required on serverless runtimes that terminate background work when the\n * request handler returns (Vercel, Cloudflare). Pass `after` from\n * `next/server` so the producer task outlives the response.\n */\n readonly waitUntil?: (promise: Promise<unknown>) => void;\n readonly onAcquire?: (streamId: string, role: ResumableStreamRole) => void;\n readonly onAppend?: (streamId: string, byteLength: number) => void;\n readonly onFinalize?: (\n streamId: string,\n status: \"done\" | \"error\",\n error?: string,\n ) => void;\n readonly onError?: (streamId: string, error: unknown) => void;\n};\n\nexport interface ResumableStreamContext {\n /** Producer or consumer entrypoint. Atomically elects the role. */\n run(\n streamId: string,\n makeStream: () => ReadableStream<Uint8Array>,\n ): Promise<ReadableStream<Uint8Array>>;\n\n /** Returns `null` when the stream does not exist. */\n resume(streamId: string): Promise<ReadableStream<Uint8Array> | null>;\n\n /** Throws `ResumableStreamError(\"missing\")` when the stream does not exist. */\n requireResume(streamId: string): Promise<ReadableStream<Uint8Array>>;\n\n status(streamId: string): Promise<ResumableStreamStatus>;\n\n delete(streamId: string): Promise<void>;\n}\n\nexport function createResumableStreamContext(\n options: ResumableStreamContextOptions,\n): ResumableStreamContext {\n const { store, waitUntil, onAcquire, onAppend, onFinalize, onError } =\n options;\n const acquireOptions =\n options.ttlMs !== undefined ? { ttlMs: options.ttlMs } : undefined;\n\n return {\n async run(streamId, makeStream) {\n const role = await store.acquire(streamId, acquireOptions);\n onAcquire?.(streamId, role);\n if (role === \"producer\") {\n startProducerTask(store, streamId, makeStream, {\n waitUntil,\n onAppend,\n onFinalize,\n onError,\n });\n }\n return readFromStore(store, streamId);\n },\n\n async resume(streamId) {\n const status = await store.status(streamId);\n if (status === \"missing\") return null;\n return readFromStore(store, streamId);\n },\n\n async requireResume(streamId) {\n const status = await store.status(streamId);\n if (status === \"missing\") {\n throw new ResumableStreamError(\n \"missing\",\n `resumable stream not found: ${streamId}`,\n );\n }\n return readFromStore(store, streamId);\n },\n\n async status(streamId) {\n return store.status(streamId);\n },\n\n async delete(streamId) {\n await store.delete(streamId);\n },\n };\n}\n\ntype ProducerHooks = {\n readonly waitUntil: ((promise: Promise<unknown>) => void) | undefined;\n readonly onAppend:\n | ((streamId: string, byteLength: number) => void)\n | undefined;\n readonly onFinalize:\n | ((streamId: string, status: \"done\" | \"error\", error?: string) => void)\n | undefined;\n readonly onError: ((streamId: string, error: unknown) => void) | undefined;\n};\n\nfunction startProducerTask(\n store: ResumableStreamStore,\n streamId: string,\n makeStream: () => ReadableStream<Uint8Array>,\n hooks: ProducerHooks,\n): void {\n const { waitUntil, onAppend, onFinalize, onError } = hooks;\n const task = (async () => {\n let reader: ReadableStreamDefaultReader<Uint8Array> | undefined;\n let cancelled = false;\n try {\n reader = makeStream().getReader();\n while (true) {\n const { done, value } = await reader.read();\n if (done) break;\n await store.append(streamId, value);\n onAppend?.(streamId, value.byteLength);\n }\n await store.finalize(streamId, \"done\");\n onFinalize?.(streamId, \"done\");\n } catch (err) {\n cancelled = true;\n onError?.(streamId, err);\n const message = err instanceof Error ? err.message : String(err);\n try {\n await reader?.cancel(err);\n } catch (cancelErr) {\n console.error(\"resumable stream reader cancel failed:\", cancelErr);\n }\n try {\n await store.finalize(streamId, \"error\", message);\n onFinalize?.(streamId, \"error\", message);\n } catch (finalizeErr) {\n console.error(\"resumable stream finalize failed:\", finalizeErr);\n }\n } finally {\n if (!cancelled) reader?.releaseLock();\n }\n })();\n\n if (waitUntil) waitUntil(task);\n task.catch((err) => {\n console.error(\"resumable producer task failed:\", err);\n });\n}\n\nfunction readFromStore(\n store: ResumableStreamStore,\n streamId: string,\n): ReadableStream<Uint8Array> {\n const ac = new AbortController();\n let iterator: AsyncIterator<{ chunk: Uint8Array }> | undefined;\n\n return new ReadableStream<Uint8Array>({\n start() {\n iterator = store.read(streamId, \"\", ac.signal)[Symbol.asyncIterator]();\n },\n async pull(controller) {\n try {\n if (!iterator) return;\n const { done, value } = await iterator.next();\n if (done) {\n controller.close();\n return;\n }\n controller.enqueue(value.chunk);\n } catch (err) {\n // the platform never calls cancel() on errored streams, so unwind\n // the store iterator and abort the signal explicitly.\n ac.abort();\n try {\n await iterator?.return?.();\n } catch {}\n controller.error(err);\n }\n },\n cancel() {\n ac.abort();\n iterator?.return?.().catch(() => {});\n },\n });\n}\n"],"mappings":";;AA4CA,SAAgB,6BACd,SACwB;CACxB,MAAM,EAAE,OAAO,WAAW,WAAW,UAAU,YAAY,YACzD;CACF,MAAM,iBACJ,QAAQ,UAAU,KAAA,IAAY,EAAE,OAAO,QAAQ,MAAM,IAAI,KAAA;CAE3D,OAAO;EACL,MAAM,IAAI,UAAU,YAAY;GAC9B,MAAM,OAAO,MAAM,MAAM,QAAQ,UAAU,cAAc;GACzD,YAAY,UAAU,IAAI;GAC1B,IAAI,SAAS,YACX,kBAAkB,OAAO,UAAU,YAAY;IAC7C;IACA;IACA;IACA;GACF,CAAC;GAEH,OAAO,cAAc,OAAO,QAAQ;EACtC;EAEA,MAAM,OAAO,UAAU;GAErB,IAAI,MADiB,MAAM,OAAO,QAAQ,MAC3B,WAAW,OAAO;GACjC,OAAO,cAAc,OAAO,QAAQ;EACtC;EAEA,MAAM,cAAc,UAAU;GAE5B,IAAI,MADiB,MAAM,OAAO,QAAQ,MAC3B,WACb,MAAM,IAAI,qBACR,WACA,+BAA+B,UACjC;GAEF,OAAO,cAAc,OAAO,QAAQ;EACtC;EAEA,MAAM,OAAO,UAAU;GACrB,OAAO,MAAM,OAAO,QAAQ;EAC9B;EAEA,MAAM,OAAO,UAAU;GACrB,MAAM,MAAM,OAAO,QAAQ;EAC7B;CACF;AACF;AAaA,SAAS,kBACP,OACA,UACA,YACA,OACM;CACN,MAAM,EAAE,WAAW,UAAU,YAAY,YAAY;CACrD,MAAM,QAAQ,YAAY;EACxB,IAAI;EACJ,IAAI,YAAY;EAChB,IAAI;GACF,SAAS,WAAW,CAAC,CAAC,UAAU;GAChC,OAAO,MAAM;IACX,MAAM,EAAE,MAAM,UAAU,MAAM,OAAO,KAAK;IAC1C,IAAI,MAAM;IACV,MAAM,MAAM,OAAO,UAAU,KAAK;IAClC,WAAW,UAAU,MAAM,UAAU;GACvC;GACA,MAAM,MAAM,SAAS,UAAU,MAAM;GACrC,aAAa,UAAU,MAAM;EAC/B,SAAS,KAAK;GACZ,YAAY;GACZ,UAAU,UAAU,GAAG;GACvB,MAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;GAC/D,IAAI;IACF,MAAM,QAAQ,OAAO,GAAG;GAC1B,SAAS,WAAW;IAClB,QAAQ,MAAM,0CAA0C,SAAS;GACnE;GACA,IAAI;IACF,MAAM,MAAM,SAAS,UAAU,SAAS,OAAO;IAC/C,aAAa,UAAU,SAAS,OAAO;GACzC,SAAS,aAAa;IACpB,QAAQ,MAAM,qCAAqC,WAAW;GAChE;EACF,UAAU;GACR,IAAI,CAAC,WAAW,QAAQ,YAAY;EACtC;CACF,EAAA,CAAG;CAEH,IAAI,WAAW,UAAU,IAAI;CAC7B,KAAK,OAAO,QAAQ;EAClB,QAAQ,MAAM,mCAAmC,GAAG;CACtD,CAAC;AACH;AAEA,SAAS,cACP,OACA,UAC4B;CAC5B,MAAM,KAAK,IAAI,gBAAgB;CAC/B,IAAI;CAEJ,OAAO,IAAI,eAA2B;EACpC,QAAQ;GACN,WAAW,MAAM,KAAK,UAAU,IAAI,GAAG,MAAM,CAAC,CAAC,OAAO,cAAc,CAAC;EACvE;EACA,MAAM,KAAK,YAAY;GACrB,IAAI;IACF,IAAI,CAAC,UAAU;IACf,MAAM,EAAE,MAAM,UAAU,MAAM,SAAS,KAAK;IAC5C,IAAI,MAAM;KACR,WAAW,MAAM;KACjB;IACF;IACA,WAAW,QAAQ,MAAM,KAAK;GAChC,SAAS,KAAK;IAGZ,GAAG,MAAM;IACT,IAAI;KACF,MAAM,UAAU,SAAS;IAC3B,QAAQ,CAAC;IACT,WAAW,MAAM,GAAG;GACtB;EACF;EACA,SAAS;GACP,GAAG,MAAM;GACT,UAAU,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC;EACrC;CACF,CAAC;AACH"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createResumableAssistantStreamResponse.js","names":[],"sources":["../../src/resumable/createResumableAssistantStreamResponse.ts"],"sourcesContent":["import type { AssistantStreamEncoder } from \"../core/AssistantStream\";\nimport {\n createAssistantStream,\n type AssistantStreamController,\n} from \"../core/modules/assistant-stream\";\nimport { DataStreamEncoder } from \"../core/serialization/data-stream/DataStream\";\nimport type { ResumableStreamContext } from \"./ResumableStreamContext\";\n\nexport const RESUMABLE_STREAM_ID_HEADER = \"x-resumable-stream-id\";\n\nexport type CreateResumableAssistantStreamResponseOptions = {\n readonly context: ResumableStreamContext;\n readonly streamId: string;\n readonly callback: (\n controller: AssistantStreamController,\n ) => PromiseLike<void> | void;\n /** Defaults to `DataStreamEncoder`. Also consulted for response headers. */\n readonly encoder?: () => AssistantStreamEncoder;\n readonly headers?: HeadersInit;\n};\n\nexport async function createResumableAssistantStreamResponse(\n options: CreateResumableAssistantStreamResponseOptions,\n): Promise<Response> {\n const encoder = (options.encoder ?? (() => new DataStreamEncoder()))();\n\n const stream = await options.context.run(options.streamId, () => {\n const aStream = createAssistantStream(options.callback);\n return aStream.pipeThrough(encoder);\n });\n\n return new Response(stream, {\n headers: mergeHeaders(encoder.headers, options.headers, options.streamId),\n });\n}\n\nexport type CreateResumeAssistantStreamResponseOptions = {\n readonly context: ResumableStreamContext;\n readonly streamId: string;\n /** Read for `headers` only; the encoder transform is not invoked on resume. */\n readonly encoder?: () => AssistantStreamEncoder;\n readonly headers?: HeadersInit;\n /** Defaults to a 404 JSON response. */\n readonly missingResponse?: () => Response;\n};\n\nexport async function createResumeAssistantStreamResponse(\n options: CreateResumeAssistantStreamResponseOptions,\n): Promise<Response> {\n const stream = await options.context.resume(options.streamId);\n if (!stream) {\n return options.missingResponse?.() ?? defaultMissingResponse();\n }\n const encoder = (options.encoder ?? (() => new DataStreamEncoder()))();\n return new Response(stream, {\n headers: mergeHeaders(encoder.headers, options.headers, options.streamId),\n });\n}\n\nfunction defaultMissingResponse(): Response {\n return new Response(JSON.stringify({ error: \"stream not found\" }), {\n status: 404,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction mergeHeaders(\n encoderHeaders: Headers | undefined,\n extra: HeadersInit | undefined,\n streamId: string,\n): Headers {\n const merged = new Headers(encoderHeaders ?? {});\n if (extra) {\n for (const [key, value] of new Headers(extra)) {\n merged.set(key, value);\n }\n }\n merged.set(RESUMABLE_STREAM_ID_HEADER, streamId);\n return merged;\n}\n"],"mappings":";;;AAQA,MAAa,6BAA6B;AAa1C,eAAsB,uCACpB,SACmB;CACnB,MAAM,WAAW,QAAQ,kBAAkB,IAAI,kBAAkB,
|
|
1
|
+
{"version":3,"file":"createResumableAssistantStreamResponse.js","names":[],"sources":["../../src/resumable/createResumableAssistantStreamResponse.ts"],"sourcesContent":["import type { AssistantStreamEncoder } from \"../core/AssistantStream\";\nimport {\n createAssistantStream,\n type AssistantStreamController,\n} from \"../core/modules/assistant-stream\";\nimport { DataStreamEncoder } from \"../core/serialization/data-stream/DataStream\";\nimport type { ResumableStreamContext } from \"./ResumableStreamContext\";\n\nexport const RESUMABLE_STREAM_ID_HEADER = \"x-resumable-stream-id\";\n\nexport type CreateResumableAssistantStreamResponseOptions = {\n readonly context: ResumableStreamContext;\n readonly streamId: string;\n readonly callback: (\n controller: AssistantStreamController,\n ) => PromiseLike<void> | void;\n /** Defaults to `DataStreamEncoder`. Also consulted for response headers. */\n readonly encoder?: () => AssistantStreamEncoder;\n readonly headers?: HeadersInit;\n};\n\nexport async function createResumableAssistantStreamResponse(\n options: CreateResumableAssistantStreamResponseOptions,\n): Promise<Response> {\n const encoder = (options.encoder ?? (() => new DataStreamEncoder()))();\n\n const stream = await options.context.run(options.streamId, () => {\n const aStream = createAssistantStream(options.callback);\n return aStream.pipeThrough(encoder);\n });\n\n return new Response(stream, {\n headers: mergeHeaders(encoder.headers, options.headers, options.streamId),\n });\n}\n\nexport type CreateResumeAssistantStreamResponseOptions = {\n readonly context: ResumableStreamContext;\n readonly streamId: string;\n /** Read for `headers` only; the encoder transform is not invoked on resume. */\n readonly encoder?: () => AssistantStreamEncoder;\n readonly headers?: HeadersInit;\n /** Defaults to a 404 JSON response. */\n readonly missingResponse?: () => Response;\n};\n\nexport async function createResumeAssistantStreamResponse(\n options: CreateResumeAssistantStreamResponseOptions,\n): Promise<Response> {\n const stream = await options.context.resume(options.streamId);\n if (!stream) {\n return options.missingResponse?.() ?? defaultMissingResponse();\n }\n const encoder = (options.encoder ?? (() => new DataStreamEncoder()))();\n return new Response(stream, {\n headers: mergeHeaders(encoder.headers, options.headers, options.streamId),\n });\n}\n\nfunction defaultMissingResponse(): Response {\n return new Response(JSON.stringify({ error: \"stream not found\" }), {\n status: 404,\n headers: { \"Content-Type\": \"application/json\" },\n });\n}\n\nfunction mergeHeaders(\n encoderHeaders: Headers | undefined,\n extra: HeadersInit | undefined,\n streamId: string,\n): Headers {\n const merged = new Headers(encoderHeaders ?? {});\n if (extra) {\n for (const [key, value] of new Headers(extra)) {\n merged.set(key, value);\n }\n }\n merged.set(RESUMABLE_STREAM_ID_HEADER, streamId);\n return merged;\n}\n"],"mappings":";;;AAQA,MAAa,6BAA6B;AAa1C,eAAsB,uCACpB,SACmB;CACnB,MAAM,WAAW,QAAQ,kBAAkB,IAAI,kBAAkB,GAAA,CAAI;CAErE,MAAM,SAAS,MAAM,QAAQ,QAAQ,IAAI,QAAQ,gBAAgB;EAE/D,OADgB,sBAAsB,QAAQ,QACjC,CAAC,CAAC,YAAY,OAAO;CACpC,CAAC;CAED,OAAO,IAAI,SAAS,QAAQ,EAC1B,SAAS,aAAa,QAAQ,SAAS,QAAQ,SAAS,QAAQ,QAAQ,EAC1E,CAAC;AACH;AAYA,eAAsB,oCACpB,SACmB;CACnB,MAAM,SAAS,MAAM,QAAQ,QAAQ,OAAO,QAAQ,QAAQ;CAC5D,IAAI,CAAC,QACH,OAAO,QAAQ,kBAAkB,KAAK,uBAAuB;CAE/D,MAAM,WAAW,QAAQ,kBAAkB,IAAI,kBAAkB,GAAA,CAAI;CACrE,OAAO,IAAI,SAAS,QAAQ,EAC1B,SAAS,aAAa,QAAQ,SAAS,QAAQ,SAAS,QAAQ,QAAQ,EAC1E,CAAC;AACH;AAEA,SAAS,yBAAmC;CAC1C,OAAO,IAAI,SAAS,KAAK,UAAU,EAAE,OAAO,mBAAmB,CAAC,GAAG;EACjE,QAAQ;EACR,SAAS,EAAE,gBAAgB,mBAAmB;CAChD,CAAC;AACH;AAEA,SAAS,aACP,gBACA,OACA,UACS;CACT,MAAM,SAAS,IAAI,QAAQ,kBAAkB,CAAC,CAAC;CAC/C,IAAI,OACF,KAAK,MAAM,CAAC,KAAK,UAAU,IAAI,QAAQ,KAAK,GAC1C,OAAO,IAAI,KAAK,KAAK;CAGzB,OAAO,IAAI,4BAA4B,QAAQ;CAC/C,OAAO;AACT"}
|