@tanstack/ai 0.63.0 → 0.64.0

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.
Files changed (61) hide show
  1. package/dist/esm/activities/chat/agents/spawn.js +2 -28
  2. package/dist/esm/activities/chat/agents/spawn.js.map +1 -1
  3. package/dist/esm/activities/chat/index.d.ts +2 -0
  4. package/dist/esm/activities/chat/index.js +10 -3
  5. package/dist/esm/activities/chat/index.js.map +1 -1
  6. package/dist/esm/activities/chat/messages.js +13 -4
  7. package/dist/esm/activities/chat/messages.js.map +1 -1
  8. package/dist/esm/activities/chat/stream/message-updaters.js +4 -1
  9. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  10. package/dist/esm/activities/chat/tools/schema-converter.d.ts +8 -0
  11. package/dist/esm/activities/chat/tools/schema-converter.js +6 -5
  12. package/dist/esm/activities/chat/tools/schema-converter.js.map +1 -1
  13. package/dist/esm/activities/chat/tools/tool-calls.d.ts +5 -2
  14. package/dist/esm/activities/chat/tools/tool-calls.js +73 -22
  15. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  16. package/dist/esm/activities/generateSpeech/index.d.ts +1 -1
  17. package/dist/esm/activities/generateSpeech/index.js +1 -1
  18. package/dist/esm/activities/generateSpeech/index.js.map +1 -1
  19. package/dist/esm/activities/generateVideo/adapter.d.ts +14 -6
  20. package/dist/esm/activities/generateVideo/adapter.js +6 -3
  21. package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
  22. package/dist/esm/activities/generateVideo/index.d.ts +5 -4
  23. package/dist/esm/activities/generateVideo/index.js.map +1 -1
  24. package/dist/esm/activities/generateVideo/snap.d.ts +12 -3
  25. package/dist/esm/activities/generateVideo/snap.js +47 -8
  26. package/dist/esm/activities/generateVideo/snap.js.map +1 -1
  27. package/dist/esm/activities/generateVoice/index.d.ts +1 -1
  28. package/dist/esm/activities/generateVoice/index.js +1 -1
  29. package/dist/esm/activities/generateVoice/index.js.map +1 -1
  30. package/dist/esm/activities/index.d.ts +2 -2
  31. package/dist/esm/activities/index.js +2 -2
  32. package/dist/esm/adapter-internals.d.ts +1 -0
  33. package/dist/esm/adapter-internals.js +2 -1
  34. package/dist/esm/types.d.ts +28 -3
  35. package/dist/esm/utilities/ag-ui-wire.js +3 -1
  36. package/dist/esm/utilities/ag-ui-wire.js.map +1 -1
  37. package/dist/esm/utilities/merge-streams.d.ts +6 -0
  38. package/dist/esm/utilities/merge-streams.js +37 -0
  39. package/dist/esm/utilities/merge-streams.js.map +1 -0
  40. package/dist/esm/utilities/reasoning-encrypted-value.d.ts +8 -0
  41. package/dist/esm/utilities/reasoning-encrypted-value.js +11 -1
  42. package/dist/esm/utilities/reasoning-encrypted-value.js.map +1 -1
  43. package/package.json +1 -1
  44. package/skills/ai-core/media-generation/SKILL.md +3 -3
  45. package/src/activities/chat/agents/spawn.ts +2 -31
  46. package/src/activities/chat/index.ts +13 -3
  47. package/src/activities/chat/messages.ts +14 -2
  48. package/src/activities/chat/stream/message-updaters.ts +5 -0
  49. package/src/activities/chat/tools/schema-converter.ts +17 -5
  50. package/src/activities/chat/tools/tool-calls.ts +121 -63
  51. package/src/activities/generateSpeech/index.ts +1 -1
  52. package/src/activities/generateVideo/adapter.ts +21 -7
  53. package/src/activities/generateVideo/index.ts +5 -4
  54. package/src/activities/generateVideo/snap.ts +64 -6
  55. package/src/activities/generateVoice/index.ts +1 -1
  56. package/src/activities/index.ts +2 -1
  57. package/src/adapter-internals.ts +1 -0
  58. package/src/types.ts +28 -4
  59. package/src/utilities/ag-ui-wire.ts +5 -1
  60. package/src/utilities/merge-streams.ts +34 -0
  61. package/src/utilities/reasoning-encrypted-value.ts +12 -0
@@ -38,7 +38,7 @@ function createId(prefix) {
38
38
  * if (!preview) throw new Error('No voice candidates returned')
39
39
  *
40
40
  * const speech = await generateSpeech({
41
- * adapter: elevenlabsSpeech('eleven_v3'),
41
+ * adapter: elevenlabsSpeech('eleven_v4'),
42
42
  * text: 'Once upon a time...',
43
43
  * voice: preview.voiceId,
44
44
  * })
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","names":[],"sources":["../../../../src/activities/generateVoice/index.ts"],"sourcesContent":["/**\n * Voice Activity\n *\n * Creates a reusable voice — either designed from a text description or cloned\n * from reference audio — and returns voice ids that `generateSpeech()` accepts.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { aiEventClient } from '@tanstack/ai-event-client'\nimport { streamGenerationResult } from '../stream-generation-result.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport {\n applyGenerationResultTransforms,\n createGenerationContext,\n runGenerationAbort,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport {\n abortReasonMessage,\n createActivityAbortControls,\n isActivityAbortError,\n raceWithAbort,\n} from '../../utilities/activity-abort'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { VoiceAdapter } from './adapter'\nimport type { StreamChunk, VoiceResult } from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'voice' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract provider options from a VoiceAdapter via ~types.\n */\nexport type VoiceProviderOptions<TAdapter> = TAdapter extends {\n '~types': { providerOptions: infer P extends object }\n}\n ? P\n : object\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the voice activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The voice adapter type\n * @template TStream - Whether to stream the output\n */\nexport interface VoiceActivityOptions<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n> {\n /** The voice adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /**\n * Text description of the voice to create, for design-capable models\n * (e.g. `'A warm, gravelly narrator in his sixties'`).\n */\n prompt?: string\n /**\n * Reference audio of the speaker to clone, for clone-capable models.\n * Accepts a base64 string, base64 data URL, File, Blob, or ArrayBuffer.\n * Remote URLs are not accepted; read the file and pass the bytes.\n */\n referenceAudio?: string | File | Blob | ArrayBuffer\n /**\n * Name to store the voice under in the provider's voice library. Check\n * `saved` on each returned voice to see whether it was actually persisted.\n */\n name?: string\n /** Human-readable description stored alongside the voice */\n description?: string\n /** Provider-specific options for voice creation */\n modelOptions?: VoiceProviderOptions<TAdapter>\n /**\n * Whether to stream the generation result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<VoiceResult>.\n *\n * @default false\n */\n stream?: TStream\n /**\n * Enable debug logging. Pass `true` to enable all categories, `false` to\n * silence everything including errors, or a `DebugConfig` object for granular\n * control and/or a custom `Logger`.\n */\n debug?: DebugOption\n /**\n * Observe-only middleware notified on start, usage, success, and error. Pass\n * `otelMiddleware()` to emit OpenTelemetry spans, or implement the\n * `GenerationMiddleware` contract for a custom backend.\n */\n middleware?: Array<GenerationMiddleware>\n /** Stable conversation/thread id for correlating this run when persisted. */\n threadId?: string\n /** Stable run id for correlating this run when persisted. */\n runId?: string\n /**\n * Maximum duration of this activity invocation in milliseconds.\n * No SDK-wide default — choose a value suitable for the provider and job.\n * Composed with {@link abortSignal}; the first abort wins.\n */\n timeout?: number\n /**\n * Caller cancellation signal (request disconnects, job/runtime cancellation).\n * Composed with {@link timeout} into an effective signal forwarded to the\n * adapter. Request-specific — not stored on global provider client config.\n */\n abortSignal?: AbortSignal\n}\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the voice activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<VoiceResult>\n */\nexport type VoiceActivityResult<TStream extends boolean = false> =\n TStream extends true ? AsyncIterable<StreamChunk> : Promise<VoiceResult>\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * Voice activity - creates a reusable voice.\n *\n * Providers create voices in one of two ways, and some support both: design a\n * new voice from a text description, or clone one from reference audio. Either\n * way the result carries voice ids you pass back to `generateSpeech()`.\n *\n * @example Design a voice from a description\n * ```ts\n * import { generateVoice, generateSpeech } from '@tanstack/ai'\n * import { elevenlabsVoiceDesign, elevenlabsSpeech } from '@tanstack/ai-elevenlabs'\n *\n * const designed = await generateVoice({\n * adapter: elevenlabsVoiceDesign('eleven_ttv_v3'),\n * prompt: 'A warm, gravelly narrator in his sixties with a slight Irish lilt',\n * })\n *\n * const [preview] = designed.voices\n * if (!preview) throw new Error('No voice candidates returned')\n *\n * const speech = await generateSpeech({\n * adapter: elevenlabsSpeech('eleven_v3'),\n * text: 'Once upon a time...',\n * voice: preview.voiceId,\n * })\n * ```\n *\n * @example Save the voice to the provider's library\n * ```ts\n * const saved = await generateVoice({\n * adapter: elevenlabsVoiceDesign('eleven_ttv_v3'),\n * prompt: 'A bright, upbeat product demo host',\n * name: 'Demo Host',\n * description: 'Bright, upbeat, mid-30s',\n * })\n * ```\n */\nexport function generateVoice<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(\n options: VoiceActivityOptions<TAdapter, TStream>,\n): VoiceActivityResult<TStream> {\n if (options.stream) {\n return streamGenerationResult(\n // Only `runId` is taken from the resolved wire identity — see the\n // matching note in `generateSpeech`.\n (resolved) => runGenerateVoice({ ...options, runId: resolved.runId }),\n options,\n ) as VoiceActivityResult<TStream>\n }\n return runGenerateVoice(options) as VoiceActivityResult<TStream>\n}\n\n/**\n * Run the core voice generation logic (non-streaming).\n */\nasync function runGenerateVoice<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n>(options: VoiceActivityOptions<TAdapter, boolean>): Promise<VoiceResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n threadId,\n runId,\n timeout,\n abortSignal: callerAbortSignal,\n ...rest\n } = options\n\n if (rest.prompt == null && rest.referenceAudio == null) {\n throw new Error(\n 'generateVoice() requires `prompt` (design a new voice) or `referenceAudio` (clone an existing one).',\n )\n }\n\n const model = adapter.model\n const requestId = createId('voice')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\n const abortControls = createActivityAbortControls({\n timeout,\n abortSignal: callerAbortSignal,\n })\n\n const mwCtx = createGenerationContext({\n requestId,\n activity: 'voice',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n artifactInputs: {\n prompt: rest.prompt,\n name: rest.name,\n description: rest.description,\n },\n threadId,\n runId,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n aiEventClient.emit('voice:request:started', {\n requestId,\n provider: adapter.name,\n model,\n prompt: rest.prompt,\n name: rest.name,\n description: rest.description,\n hasReferenceAudio: rest.referenceAudio != null,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateVoice provider=${adapter.name}`, {\n provider: adapter.name,\n model,\n })\n\n try {\n const rawResult = await raceWithAbort(\n adapter.generateVoice({\n ...rest,\n model,\n logger,\n ...(abortControls.signal ? { abortSignal: abortControls.signal } : {}),\n }),\n abortControls.signal,\n )\n abortControls.clear()\n const result = await applyGenerationResultTransforms(mwCtx, rawResult)\n const duration = Date.now() - startTime\n\n aiEventClient.emit('voice:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n voiceIds: result.voices.map((voice) => voice.voiceId),\n voiceCount: result.voices.length,\n previewText: result.previewText,\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n\n if (result.usage) {\n aiEventClient.emit('voice:usage', {\n requestId,\n model,\n usage: result.usage,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n }\n\n logger.output(`activity=generateVoice voices=${result.voices.length}`, {\n voices: result.voices.length,\n })\n\n if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage)\n await runGenerationFinish(middleware, mwCtx, {\n duration,\n usage: result.usage,\n })\n\n return result\n } catch (error) {\n abortControls.clear()\n const duration = Date.now() - startTime\n const err = error as Error\n aiEventClient.emit('voice:request:error', {\n requestId,\n provider: adapter.name,\n model,\n error: { message: err.message, name: err.name },\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n if (isActivityAbortError(error, abortControls.signal)) {\n await runGenerationAbort(middleware, mwCtx, {\n reason: abortReasonMessage(error, abortControls.signal),\n duration,\n })\n } else {\n await runGenerationError(middleware, mwCtx, {\n error,\n duration,\n })\n }\n logger.errors('generateVoice activity failed', {\n error,\n source: 'generateVoice',\n })\n throw error\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateVoice() function without executing.\n */\nexport function createVoiceOptions<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(\n options: VoiceActivityOptions<TAdapter, TStream>,\n): VoiceActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n VoiceAdapter,\n VoiceAdapterConfig,\n AnyVoiceAdapter,\n} from './adapter'\nexport { BaseVoiceAdapter } from './adapter'\n"],"mappings":"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"}
1
+ {"version":3,"file":"index.js","names":[],"sources":["../../../../src/activities/generateVoice/index.ts"],"sourcesContent":["/**\n * Voice Activity\n *\n * Creates a reusable voice — either designed from a text description or cloned\n * from reference audio — and returns voice ids that `generateSpeech()` accepts.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { aiEventClient } from '@tanstack/ai-event-client'\nimport { streamGenerationResult } from '../stream-generation-result.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport {\n applyGenerationResultTransforms,\n createGenerationContext,\n runGenerationAbort,\n runGenerationError,\n runGenerationFinish,\n runGenerationStart,\n runGenerationUsage,\n} from '../middleware/run'\nimport {\n abortReasonMessage,\n createActivityAbortControls,\n isActivityAbortError,\n raceWithAbort,\n} from '../../utilities/activity-abort'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { GenerationMiddleware } from '../middleware/types'\nimport type { VoiceAdapter } from './adapter'\nimport type { StreamChunk, VoiceResult } from '../../types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'voice' as const\n\n// ===========================\n// Type Extraction Helpers\n// ===========================\n\n/**\n * Extract provider options from a VoiceAdapter via ~types.\n */\nexport type VoiceProviderOptions<TAdapter> = TAdapter extends {\n '~types': { providerOptions: infer P extends object }\n}\n ? P\n : object\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the voice activity.\n * The model is extracted from the adapter's model property.\n *\n * @template TAdapter - The voice adapter type\n * @template TStream - Whether to stream the output\n */\nexport interface VoiceActivityOptions<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n> {\n /** The voice adapter to use (must be created with a model) */\n adapter: TAdapter & { kind: typeof kind }\n /**\n * Text description of the voice to create, for design-capable models\n * (e.g. `'A warm, gravelly narrator in his sixties'`).\n */\n prompt?: string\n /**\n * Reference audio of the speaker to clone, for clone-capable models.\n * Accepts a base64 string, base64 data URL, File, Blob, or ArrayBuffer.\n * Remote URLs are not accepted; read the file and pass the bytes.\n */\n referenceAudio?: string | File | Blob | ArrayBuffer\n /**\n * Name to store the voice under in the provider's voice library. Check\n * `saved` on each returned voice to see whether it was actually persisted.\n */\n name?: string\n /** Human-readable description stored alongside the voice */\n description?: string\n /** Provider-specific options for voice creation */\n modelOptions?: VoiceProviderOptions<TAdapter>\n /**\n * Whether to stream the generation result.\n * When true, returns an AsyncIterable<StreamChunk> for streaming transport.\n * When false or not provided, returns a Promise<VoiceResult>.\n *\n * @default false\n */\n stream?: TStream\n /**\n * Enable debug logging. Pass `true` to enable all categories, `false` to\n * silence everything including errors, or a `DebugConfig` object for granular\n * control and/or a custom `Logger`.\n */\n debug?: DebugOption\n /**\n * Observe-only middleware notified on start, usage, success, and error. Pass\n * `otelMiddleware()` to emit OpenTelemetry spans, or implement the\n * `GenerationMiddleware` contract for a custom backend.\n */\n middleware?: Array<GenerationMiddleware>\n /** Stable conversation/thread id for correlating this run when persisted. */\n threadId?: string\n /** Stable run id for correlating this run when persisted. */\n runId?: string\n /**\n * Maximum duration of this activity invocation in milliseconds.\n * No SDK-wide default — choose a value suitable for the provider and job.\n * Composed with {@link abortSignal}; the first abort wins.\n */\n timeout?: number\n /**\n * Caller cancellation signal (request disconnects, job/runtime cancellation).\n * Composed with {@link timeout} into an effective signal forwarded to the\n * adapter. Request-specific — not stored on global provider client config.\n */\n abortSignal?: AbortSignal\n}\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the voice activity.\n * - If stream is true: AsyncIterable<StreamChunk>\n * - Otherwise: Promise<VoiceResult>\n */\nexport type VoiceActivityResult<TStream extends boolean = false> =\n TStream extends true ? AsyncIterable<StreamChunk> : Promise<VoiceResult>\n\nfunction createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * Voice activity - creates a reusable voice.\n *\n * Providers create voices in one of two ways, and some support both: design a\n * new voice from a text description, or clone one from reference audio. Either\n * way the result carries voice ids you pass back to `generateSpeech()`.\n *\n * @example Design a voice from a description\n * ```ts\n * import { generateVoice, generateSpeech } from '@tanstack/ai'\n * import { elevenlabsVoiceDesign, elevenlabsSpeech } from '@tanstack/ai-elevenlabs'\n *\n * const designed = await generateVoice({\n * adapter: elevenlabsVoiceDesign('eleven_ttv_v3'),\n * prompt: 'A warm, gravelly narrator in his sixties with a slight Irish lilt',\n * })\n *\n * const [preview] = designed.voices\n * if (!preview) throw new Error('No voice candidates returned')\n *\n * const speech = await generateSpeech({\n * adapter: elevenlabsSpeech('eleven_v4'),\n * text: 'Once upon a time...',\n * voice: preview.voiceId,\n * })\n * ```\n *\n * @example Save the voice to the provider's library\n * ```ts\n * const saved = await generateVoice({\n * adapter: elevenlabsVoiceDesign('eleven_ttv_v3'),\n * prompt: 'A bright, upbeat product demo host',\n * name: 'Demo Host',\n * description: 'Bright, upbeat, mid-30s',\n * })\n * ```\n */\nexport function generateVoice<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(\n options: VoiceActivityOptions<TAdapter, TStream>,\n): VoiceActivityResult<TStream> {\n if (options.stream) {\n return streamGenerationResult(\n // Only `runId` is taken from the resolved wire identity — see the\n // matching note in `generateSpeech`.\n (resolved) => runGenerateVoice({ ...options, runId: resolved.runId }),\n options,\n ) as VoiceActivityResult<TStream>\n }\n return runGenerateVoice(options) as VoiceActivityResult<TStream>\n}\n\n/**\n * Run the core voice generation logic (non-streaming).\n */\nasync function runGenerateVoice<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n>(options: VoiceActivityOptions<TAdapter, boolean>): Promise<VoiceResult> {\n const {\n adapter,\n stream: _stream,\n debug: _debug,\n middleware,\n threadId,\n runId,\n timeout,\n abortSignal: callerAbortSignal,\n ...rest\n } = options\n\n if (rest.prompt == null && rest.referenceAudio == null) {\n throw new Error(\n 'generateVoice() requires `prompt` (design a new voice) or `referenceAudio` (clone an existing one).',\n )\n }\n\n const model = adapter.model\n const requestId = createId('voice')\n const startTime = Date.now()\n const logger: InternalLogger = resolveDebugOption(options.debug)\n const abortControls = createActivityAbortControls({\n timeout,\n abortSignal: callerAbortSignal,\n })\n\n const mwCtx = createGenerationContext({\n requestId,\n activity: 'voice',\n provider: adapter.name,\n model,\n modelOptions: rest.modelOptions,\n artifactInputs: {\n prompt: rest.prompt,\n name: rest.name,\n description: rest.description,\n },\n threadId,\n runId,\n createId,\n })\n\n await runGenerationStart(middleware, mwCtx)\n\n aiEventClient.emit('voice:request:started', {\n requestId,\n provider: adapter.name,\n model,\n prompt: rest.prompt,\n name: rest.name,\n description: rest.description,\n hasReferenceAudio: rest.referenceAudio != null,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: startTime,\n })\n\n logger.request(`activity=generateVoice provider=${adapter.name}`, {\n provider: adapter.name,\n model,\n })\n\n try {\n const rawResult = await raceWithAbort(\n adapter.generateVoice({\n ...rest,\n model,\n logger,\n ...(abortControls.signal ? { abortSignal: abortControls.signal } : {}),\n }),\n abortControls.signal,\n )\n abortControls.clear()\n const result = await applyGenerationResultTransforms(mwCtx, rawResult)\n const duration = Date.now() - startTime\n\n aiEventClient.emit('voice:request:completed', {\n requestId,\n provider: adapter.name,\n model,\n voiceIds: result.voices.map((voice) => voice.voiceId),\n voiceCount: result.voices.length,\n previewText: result.previewText,\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n\n if (result.usage) {\n aiEventClient.emit('voice:usage', {\n requestId,\n model,\n usage: result.usage,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n }\n\n logger.output(`activity=generateVoice voices=${result.voices.length}`, {\n voices: result.voices.length,\n })\n\n if (result.usage) await runGenerationUsage(middleware, mwCtx, result.usage)\n await runGenerationFinish(middleware, mwCtx, {\n duration,\n usage: result.usage,\n })\n\n return result\n } catch (error) {\n abortControls.clear()\n const duration = Date.now() - startTime\n const err = error as Error\n aiEventClient.emit('voice:request:error', {\n requestId,\n provider: adapter.name,\n model,\n error: { message: err.message, name: err.name },\n duration,\n modelOptions: rest.modelOptions as Record<string, unknown> | undefined,\n timestamp: Date.now(),\n })\n if (isActivityAbortError(error, abortControls.signal)) {\n await runGenerationAbort(middleware, mwCtx, {\n reason: abortReasonMessage(error, abortControls.signal),\n duration,\n })\n } else {\n await runGenerationError(middleware, mwCtx, {\n error,\n duration,\n })\n }\n logger.errors('generateVoice activity failed', {\n error,\n source: 'generateVoice',\n })\n throw error\n }\n}\n\n// ===========================\n// Options Factory\n// ===========================\n\n/**\n * Create typed options for the generateVoice() function without executing.\n */\nexport function createVoiceOptions<\n TAdapter extends VoiceAdapter<string, VoiceProviderOptions<TAdapter>>,\n TStream extends boolean = false,\n>(\n options: VoiceActivityOptions<TAdapter, TStream>,\n): VoiceActivityOptions<TAdapter, TStream> {\n return options\n}\n\n// Re-export adapter types\nexport type {\n VoiceAdapter,\n VoiceAdapterConfig,\n AnyVoiceAdapter,\n} from './adapter'\nexport { BaseVoiceAdapter } from './adapter'\n"],"mappings":"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"}
@@ -29,8 +29,8 @@ export { BaseImageAdapter, type ImageAdapter, type ImageAdapterConfig, type AnyI
29
29
  export { kind as audioKind, generateAudio, type AudioActivityOptions, type AudioActivityResult, type AudioProviderOptions, } from './generateAudio/index.js';
30
30
  export { BaseAudioAdapter, type AudioAdapter, type AudioAdapterConfig, type AnyAudioAdapter, } from './generateAudio/adapter.js';
31
31
  export { kind as videoKind, generateVideo, getVideoJobStatus, type VideoActivityOptions, type VideoActivityResult, type VideoProviderOptions, type VideoCreateOptions, type VideoStatusOptions, type VideoUrlOptions, type VideoDurationForAdapter, } from './generateVideo/index.js';
32
- export { BaseVideoAdapter, type VideoAdapter, type VideoAdapterConfig, type AnyVideoAdapter, type DurationOptions, } from './generateVideo/adapter.js';
33
- export { snapToDurationOption } from './generateVideo/snap.js';
32
+ export { BaseVideoAdapter, type VideoAdapter, type VideoAdapterConfig, type AnyVideoAdapter, type DurationOptions, type VideoDurationSpell, } from './generateVideo/adapter.js';
33
+ export { durationToSeconds, snapToDurationOption } from './generateVideo/snap.js';
34
34
  export { kind as ttsKind, generateSpeech, listVoices, type ListVoicesActivityOptions, type TTSActivityOptions, type TTSActivityResult, type TTSProviderOptions, } from './generateSpeech/index.js';
35
35
  export { BaseTTSAdapter, type TTSAdapter, type TTSAdapterConfig, type TTSCapabilities, type AnyTTSAdapter, } from './generateSpeech/adapter.js';
36
36
  export { kind as voiceKind, generateVoice, createVoiceOptions, type VoiceActivityOptions, type VoiceActivityResult, type VoiceProviderOptions, } from './generateVoice/index.js';
@@ -13,9 +13,9 @@ import { BaseImageAdapter } from "./generateImage/adapter.js";
13
13
  import { generateImage, kind as kind$4 } from "./generateImage/index.js";
14
14
  import { BaseAudioAdapter } from "./generateAudio/adapter.js";
15
15
  import { generateAudio, kind } from "./generateAudio/index.js";
16
+ import { durationToSeconds, snapToDurationOption } from "./generateVideo/snap.js";
16
17
  import { BaseVideoAdapter } from "./generateVideo/adapter.js";
17
18
  import { generateVideo, getVideoJobStatus, kind as kind$11 } from "./generateVideo/index.js";
18
- import { snapToDurationOption } from "./generateVideo/snap.js";
19
19
  import { BaseTTSAdapter } from "./generateSpeech/adapter.js";
20
20
  import { generateSpeech, kind as kind$10, listVoices } from "./generateSpeech/index.js";
21
21
  import { BaseVoiceAdapter } from "./generateVoice/adapter.js";
@@ -30,4 +30,4 @@ import { BaseLiveVideoAdapter } from "./generateLiveVideo/adapter.js";
30
30
  import { generateLiveVideo, kind as kind$5 } from "./generateLiveVideo/index.js";
31
31
  import { deleteFile, fileSourceFromHandle, getFile, kind as kind$3, uploadFile } from "./files/index.js";
32
32
  import { BaseFilesAdapter, normalizeFileUploadInput } from "./files/adapter.js";
33
- export { BaseAudioAdapter, BaseEmbeddingAdapter, BaseEvaluateAdapter, BaseFilesAdapter, BaseImageAdapter, BaseLiveVideoAdapter, BaseRerankAdapter, BaseSummarizeAdapter, BaseTTSAdapter, BaseTextAdapter, BaseTranscriptionAdapter, BaseVideoAdapter, BaseVoiceAdapter, BaseWorldAdapter, ChatStreamSummarizeAdapter, kind as audioKind, boolean, chat, choice, createRerankOptions, createVoiceOptions, decide, defineAgent, deleteFile, embed, kind$1 as embeddingKind, kind$2 as evaluateKind, fileSourceFromHandle, kind$3 as filesKind, generateAudio, generateImage, generateLiveVideo, generateSpeech, generateTranscription, generateVideo, generateVoice, generateWorld, getFile, getVideoJobStatus, kind$4 as imageKind, listVoices, kind$5 as liveVideoKind, normalizeFileUploadInput, rerank, kind$6 as rerankKind, score, snapToDurationOption, subagentRoute, summarize, kind$7 as summarizeKind, kind$8 as textKind, kind$9 as transcriptionKind, kind$10 as ttsKind, uploadFile, kind$11 as videoKind, kind$12 as voiceKind, kind$13 as worldKind };
33
+ export { BaseAudioAdapter, BaseEmbeddingAdapter, BaseEvaluateAdapter, BaseFilesAdapter, BaseImageAdapter, BaseLiveVideoAdapter, BaseRerankAdapter, BaseSummarizeAdapter, BaseTTSAdapter, BaseTextAdapter, BaseTranscriptionAdapter, BaseVideoAdapter, BaseVoiceAdapter, BaseWorldAdapter, ChatStreamSummarizeAdapter, kind as audioKind, boolean, chat, choice, createRerankOptions, createVoiceOptions, decide, defineAgent, deleteFile, durationToSeconds, embed, kind$1 as embeddingKind, kind$2 as evaluateKind, fileSourceFromHandle, kind$3 as filesKind, generateAudio, generateImage, generateLiveVideo, generateSpeech, generateTranscription, generateVideo, generateVoice, generateWorld, getFile, getVideoJobStatus, kind$4 as imageKind, listVoices, kind$5 as liveVideoKind, normalizeFileUploadInput, rerank, kind$6 as rerankKind, score, snapToDurationOption, subagentRoute, summarize, kind$7 as summarizeKind, kind$8 as textKind, kind$9 as transcriptionKind, kind$10 as ttsKind, uploadFile, kind$11 as videoKind, kind$12 as voiceKind, kind$13 as worldKind };
@@ -17,3 +17,4 @@ export { appendOutputSchemaInstruction, parseJsonFromAssistantText, } from './ut
17
17
  export { structuredOutputCompleteChunk, structuredOutputStartChunk, } from './utilities/structured-output-events.js';
18
18
  export { tanstackMetadata } from './utilities/merge-metadata.js';
19
19
  export { isSpecTopLevelKey } from './utilities/spec-event-keys.js';
20
+ export { REDACTED_THINKING_ID_PREFIX } from './utilities/reasoning-encrypted-value.js';
@@ -1,5 +1,6 @@
1
1
  import { toRunErrorPayload, toRunErrorRawEvent } from "./activities/error-payload.js";
2
2
  import { tanstackMetadata } from "./utilities/merge-metadata.js";
3
+ import { REDACTED_THINKING_ID_PREFIX } from "./utilities/reasoning-encrypted-value.js";
3
4
  import { isSpecTopLevelKey } from "./utilities/spec-event-keys.js";
4
5
  import { InternalLogger } from "./logger/internal-logger.js";
5
6
  import { resolveDebugOption } from "./logger/resolve.js";
@@ -12,4 +13,4 @@ import { GenericInterruptDefinitionRegistryCapability, getGenericInterruptDefini
12
13
  import { PendingTurnCapability, getPendingTurn, providePendingTurn } from "./activities/chat/middleware/pending-turn.js";
13
14
  import { appendOutputSchemaInstruction, parseJsonFromAssistantText } from "./utilities/structured-output-text.js";
14
15
  import { structuredOutputCompleteChunk, structuredOutputStartChunk } from "./utilities/structured-output-events.js";
15
- export { DuplicateToolNameError, GenericInterruptDefinitionRegistryCapability, InternalLogger, PendingTurnCapability, RunDisconnectCapability, SandboxRuntimeCapability, appendOutputSchemaInstruction, assertUniqueToolNames, createInterruptBinding, getGenericInterruptDefinitionRegistry, getInterruptRequestInput, getPendingTurn, getRunDisconnect, getSandboxRuntime, isSpecTopLevelKey, parseJsonFromAssistantText, provideGenericInterruptDefinitionRegistry, providePendingTurn, provideRunDisconnect, provideSandboxRuntime, readInterruptBinding, rehydrateInterruptRequest, resolveDebugOption, structuredOutputCompleteChunk, structuredOutputStartChunk, tanstackMetadata, toRunErrorPayload, toRunErrorRawEvent, validateInterruptResumeBatch };
16
+ export { DuplicateToolNameError, GenericInterruptDefinitionRegistryCapability, InternalLogger, PendingTurnCapability, REDACTED_THINKING_ID_PREFIX, RunDisconnectCapability, SandboxRuntimeCapability, appendOutputSchemaInstruction, assertUniqueToolNames, createInterruptBinding, getGenericInterruptDefinitionRegistry, getInterruptRequestInput, getPendingTurn, getRunDisconnect, getSandboxRuntime, isSpecTopLevelKey, parseJsonFromAssistantText, provideGenericInterruptDefinitionRegistry, providePendingTurn, provideRunDisconnect, provideSandboxRuntime, readInterruptBinding, rehydrateInterruptRequest, resolveDebugOption, structuredOutputCompleteChunk, structuredOutputStartChunk, tanstackMetadata, toRunErrorPayload, toRunErrorRawEvent, validateInterruptResumeBatch };
@@ -226,9 +226,15 @@ export interface ModelMessage<TContent extends string | null | Array<ContentPart
226
226
  name?: string;
227
227
  toolCalls?: Array<ToolCall>;
228
228
  toolCallId?: string;
229
+ /**
230
+ * Signed thinking to send back to the provider. `redacted: true` marks a
231
+ * block the provider encrypted: `content` is empty and `signature` holds its
232
+ * opaque data. See `ThinkingPart.signature` for the planned rename.
233
+ */
229
234
  thinking?: Array<{
230
235
  content: string;
231
236
  signature?: string;
237
+ redacted?: boolean;
232
238
  }>;
233
239
  /** Error reported by an AG-UI tool message. */
234
240
  error?: string;
@@ -309,7 +315,20 @@ export interface ThinkingPart {
309
315
  type: 'thinking';
310
316
  content: string;
311
317
  stepId?: string;
318
+ /**
319
+ * The provider's opaque reasoning artefact, sent back unchanged: an
320
+ * Anthropic signature, Anthropic redacted data, or OpenAI encrypted content.
321
+ * TODO(#1581): rename to `encryptedValue` to match AG-UI's `ReasoningMessage`.
322
+ * Renaming breaks stored messages, so it needs a read shim for `signature`.
323
+ */
312
324
  signature?: string;
325
+ /**
326
+ * The provider encrypted this thinking block (Anthropic `redacted_thinking`).
327
+ * `content` is empty, and `signature` holds the opaque data that goes back
328
+ * to the provider unchanged. On the AG-UI wire, the reasoning message id
329
+ * starts with `redacted_thinking-` instead.
330
+ */
331
+ redacted?: boolean;
313
332
  }
314
333
  /**
315
334
  * Recursive `Partial` — every nested field becomes optional. Used as the
@@ -851,6 +870,11 @@ export interface TextOptions<TProviderOptionsSuperset extends Record<string, any
851
870
  */
852
871
  systemPrompts?: Array<SystemPrompt>;
853
872
  agentLoopStrategy?: AgentLoopStrategy;
873
+ /**
874
+ * How the server tools of one model turn run. `'parallel'` (the default)
875
+ * starts them together, and `'sequential'` runs them one at a time.
876
+ */
877
+ toolExecution?: 'parallel' | 'sequential';
854
878
  /**
855
879
  * Optional configuration for lazy-tool discovery (tools marked `lazy: true`).
856
880
  * Tunes how much of each lazy tool's description appears in the discovery
@@ -1886,9 +1910,10 @@ export interface VideoGenerationOptions<TProviderOptions extends object = object
1886
1910
  /** Video size — format depends on the provider (e.g., "16:9", "1280x720") */
1887
1911
  size?: TSize;
1888
1912
  /**
1889
- * Video duration in seconds. Adapters that declare a per-model duration
1890
- * map narrow this to the model's valid union; use
1891
- * `adapter.snapDuration(seconds)` to coerce raw seconds to a valid value.
1913
+ * Video duration. Adapters that declare a per-model duration map narrow
1914
+ * this to that model's union (a number, `"8"`, or `"8s"`). Use
1915
+ * `adapter.snapDuration(input)` to coerce a raw value. `input` may be
1916
+ * seconds, a `"6s"` template, or `"auto"` when the model lists it.
1892
1917
  */
1893
1918
  duration?: TDuration;
1894
1919
  /** Model-specific options for video generation */
@@ -1,4 +1,5 @@
1
1
  import { tanstackMetadata } from "./merge-metadata.js";
2
+ import { REDACTED_THINKING_ID_PREFIX } from "./reasoning-encrypted-value.js";
2
3
  import { isProviderExecutedToolCall } from "./provider-executed.js";
3
4
  import { normalizeToolResult } from "./tool-result.js";
4
5
  import { wireSubagentInfo, wireSubagentRunId } from "./subagent-wire.js";
@@ -287,7 +288,8 @@ function collectToolCalls(parts) {
287
288
  return calls.length > 0 ? calls : void 0;
288
289
  }
289
290
  function deriveReasoningId(messageId, part) {
290
- return `${messageId}-reasoning-${part.id ?? hashContent(part.content)}`;
291
+ const id = `${messageId}-reasoning-${part.id ?? hashContent(part.content)}`;
292
+ return part.type === "thinking" && part.redacted ? `${REDACTED_THINKING_ID_PREFIX}${id}` : id;
291
293
  }
292
294
  function deriveToolMessageId(toolCallId) {
293
295
  return `tool-${toolCallId}`;
@@ -1 +1 @@
1
- {"version":3,"file":"ag-ui-wire.js","names":[],"sources":["../../../src/utilities/ag-ui-wire.ts"],"sourcesContent":["import type {\n AssistantMessage,\n InputContent,\n ReasoningMessage,\n SystemMessage,\n ToolCall,\n ToolMessage,\n UserMessage,\n} from '@ag-ui/core'\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n StructuredOutputPart,\n SubagentPart,\n TanStackMessageMetadata,\n ToolResultOutcome,\n UIMessage,\n UIResourcePart,\n} from '../types'\nimport type { MetadataRecord } from './merge-metadata'\nimport { tanstackMetadata } from './merge-metadata'\nimport { isProviderExecutedToolCall } from './provider-executed'\nimport { normalizeToolResult } from './tool-result'\nimport { wireSubagentInfo, wireSubagentRunId } from './subagent-wire'\nimport type { SubagentWireInfo } from './subagent-wire'\nimport {\n coerceCreatedAt,\n modelMessageToUIMessage,\n} from '../activities/chat/messages'\n\ntype WithMetadata<T> = T & { metadata?: MetadataRecord }\ntype WireSystemMessage = WithMetadata<SystemMessage>\ntype WireUserMessage = WithMetadata<UserMessage>\ntype WireAssistantMessage = WithMetadata<AssistantMessage>\ntype WireToolMessage = WithMetadata<\n ToolMessage & {\n name?: string\n }\n>\ntype WireReasoningMessage = WithMetadata<ReasoningMessage>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction rebuiltToolMetadata(\n metadata: unknown,\n createdAt: unknown,\n id: string | undefined,\n content: string | null | Array<ContentPart>,\n anchorOwnsUiResources = false,\n outcome?: ToolResultOutcome,\n): MetadataRecord | undefined {\n const source: MetadataRecord = isRecord(metadata) ? metadata : {}\n const tanstack = isRecord(source.tanstack) ? { ...source.tanstack } : {}\n if (anchorOwnsUiResources) delete tanstack.uiResources\n const date = coerceCreatedAt(createdAt)\n const toolResult: NonNullable<TanStackMessageMetadata['toolResult']> = {\n ...(id !== undefined ? { id } : {}),\n ...(date && { createdAt: date.toISOString() }),\n ...(Array.isArray(content) && { content }),\n }\n const result = {\n ...source,\n tanstack: {\n ...tanstack,\n ...(outcome !== undefined && { toolResultOutcome: outcome }),\n toolResult,\n },\n }\n return Object.keys(result).length ? result : undefined\n}\n\nexport type WireMessage =\n | WireSystemMessage\n | WireUserMessage\n | WireAssistantMessage\n | WireToolMessage\n | WireReasoningMessage\n\n/**\n * Serialize TanStack `UIMessage`s and `ModelMessage`s into the AG-UI\n * `RunAgentInput.messages` wire shape. Anchors are spec-only (`id`, `role`,\n * `name`, `content`, `toolCalls`, `metadata`). Tool results and thinking parts\n * on assistant messages are additionally emitted as fan-out\n * `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI\n * server consumers. Set `includeSnapshotStructuredOutput` to retain complete\n * structured-output metadata for UI snapshots.\n */\nexport function uiMessagesToWire(\n messages: Array<UIMessage | ModelMessage>,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const wire: Array<WireMessage> = []\n const usedWireIds = new Set<string>(\n messages.flatMap((message) =>\n 'id' in message && message.id && message.role !== 'tool'\n ? [message.id]\n : [],\n ),\n )\n const includeSnapshotStructuredOutput =\n options?.includeSnapshotStructuredOutput ?? false\n\n const assistantIds = new Set<string>()\n for (const msg of messages) {\n if (msg.role === 'assistant' && msg.id !== undefined) {\n assistantIds.add(msg.id)\n }\n }\n\n for (const msg of messages) {\n if (!('parts' in msg) && msg.role === 'tool' && msg.toolCallId) {\n const id = uniqueToolWireId(\n toolWireId(msg.id, msg.toolCallId, assistantIds),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n msg.metadata,\n msg.createdAt,\n msg.id,\n msg.content,\n )\n wire.push({\n role: 'tool',\n id,\n ...(msg.name !== undefined && { name: msg.name }),\n toolCallId: msg.toolCallId,\n content:\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content),\n ...(msg.error !== undefined && { error: msg.error }),\n ...(metadata !== undefined && { metadata }),\n })\n continue\n }\n\n const uiMessage: UIMessage =\n 'parts' in msg ? msg : modelMessageToUIMessage(msg, msg.id)\n const parts: ReadonlyArray<MessagePart> = uiMessage.parts\n usedWireIds.add(uiMessage.id)\n\n if (msg.role === 'system') {\n wire.push(\n toAnchor(\n uiMessage,\n 'system',\n {\n content:\n parts.length > 0\n ? collectText(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n if (msg.role === 'user') {\n wire.push(\n toAnchor(\n uiMessage,\n 'user',\n {\n content:\n parts.length > 0\n ? collectUserContent(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n // assistant: reasoning fan-outs, then anchor, then tool fan-outs.\n //\n // Provider-executed tools (Anthropic web_search / web_fetch) run inside one\n // provider response, and the provider signs every thinking block against\n // the blocks before it. Emitting all reasoning first and a single anchor\n // with the joined text and every tool call turns\n // \"thinking, tool, thinking, text, tool\" into\n // \"thinking, thinking, text, tool, tool\", and the provider rejects the next\n // turn (\"thinking blocks in the latest assistant message cannot be\n // modified\"). Split the message into ordered segments at each thinking\n // part that follows a provider-executed tool call, the same rule\n // buildAssistantMessages applies, so the wire keeps the signed order.\n // Segments after the first get derived anchor ids; strict AG-UI consumers\n // still see plain anchors.\n type Segment = {\n thinking: Array<Extract<MessagePart, { type: 'thinking' }>>\n parts: Array<MessagePart>\n }\n let current: Segment = { thinking: [], parts: [] }\n const segments: Array<Segment> = [current]\n for (const part of parts) {\n if (part.type === 'thinking') {\n if (\n current.parts.some(\n (p) => p.type === 'tool-call' && isProviderExecutedToolCall(p),\n )\n ) {\n current = { thinking: [part], parts: [] }\n segments.push(current)\n } else {\n current.thinking.push(part)\n }\n } else {\n current.parts.push(part)\n }\n }\n\n segments.forEach((segment, index) => {\n for (const part of segment.thinking) {\n const reasoning: WireReasoningMessage = {\n role: 'reasoning',\n id: uniqueWireId(deriveReasoningId(uiMessage.id, part), usedWireIds),\n content: part.content,\n }\n if (part.signature) {\n reasoning.encryptedValue = part.signature\n }\n wire.push(reasoning)\n }\n\n const text = collectText(segment.parts)\n const toolCalls = collectToolCalls(segment.parts)\n const anchorMessage: UIMessage =\n index === 0\n ? uiMessage\n : {\n ...uiMessage,\n id: uniqueWireId(`${uiMessage.id}-segment-${index}`, usedWireIds),\n }\n wire.push(\n toAnchor(\n anchorMessage,\n 'assistant',\n {\n ...(text !== '' && { content: text }),\n ...(toolCalls && { toolCalls }),\n },\n segment.parts,\n includeSnapshotStructuredOutput,\n ),\n )\n })\n\n const explicitToolResults = new Set(\n parts.flatMap((part) =>\n part.type === 'tool-result' ? [part.toolCallId] : [],\n ),\n )\n for (const part of parts) {\n if (part.type === 'tool-result') {\n const id = uniqueToolWireId(\n part.id ?? deriveToolMessageId(part.toolCallId),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n part.metadata,\n part.createdAt,\n part.id,\n part.content,\n true,\n part.outcome,\n )\n wire.push({\n role: 'tool',\n id,\n toolCallId: part.toolCallId,\n ...(part.name !== undefined && { name: part.name }),\n content:\n typeof part.content === 'string'\n ? part.content\n : JSON.stringify(part.content),\n ...(part.error !== undefined && { error: part.error }),\n ...(metadata !== undefined && { metadata }),\n })\n } else if (part.type === 'tool-call') {\n const approved = part.approval?.approved\n if (\n explicitToolResults.has(part.id) ||\n (part.output === undefined &&\n (part.state !== 'approval-responded' || approved === undefined))\n ) {\n continue\n }\n const result =\n part.output !== undefined\n ? normalizeToolResult(part.output)\n : JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n })\n const content =\n typeof result === 'string' ? result : JSON.stringify(result)\n wire.push({\n role: 'tool',\n id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),\n toolCallId: part.id,\n content,\n metadata: rebuiltToolMetadata(\n undefined,\n undefined,\n undefined,\n result,\n false,\n part.approval?.approved === false ? 'denied' : undefined,\n ),\n })\n }\n }\n\n for (const part of parts) {\n if (part.type === 'subagent') wire.push(...subagentToWire(part, options))\n }\n }\n\n return wire\n}\n\nfunction toAnchor(\n msg: UIMessage,\n role: 'system',\n extras: { content: string },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'user',\n extras: { content: string | Array<InputContent> },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireUserMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'assistant',\n extras: {\n content?: string\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireAssistantMessage\nfunction toAnchor(\n msg: UIMessage,\n role: UIMessage['role'],\n extras: {\n content?: string | Array<InputContent>\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage | WireUserMessage | WireAssistantMessage {\n const metadata = messageMetadata(msg, parts, includeSnapshotStructuredOutput)\n const base = {\n id: msg.id,\n ...(msg.name !== undefined && { name: msg.name }),\n ...(metadata !== undefined && { metadata }),\n }\n if (role === 'system') {\n return { ...base, role, content: String(extras.content ?? '') }\n }\n if (role === 'user') {\n return { ...base, role, content: extras.content ?? '' }\n }\n return {\n ...base,\n role,\n ...(typeof extras.content === 'string' && { content: extras.content }),\n ...(extras.toolCalls !== undefined && { toolCalls: extras.toolCalls }),\n }\n}\n\nfunction messageMetadata(\n msg: UIMessage,\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): MetadataRecord | undefined {\n const base: MetadataRecord = { ...(msg.metadata ?? {}) }\n const previousTanstack = tanstackMetadata(msg)\n const tanstack: TanStackMessageMetadata = {}\n if (previousTanstack?.model !== undefined)\n tanstack.model = previousTanstack.model\n if (previousTanstack?.runId !== undefined)\n tanstack.runId = previousTanstack.runId\n if (previousTanstack?.run?.id !== undefined)\n tanstack.run = { id: previousTanstack.run.id }\n if (previousTanstack?.signature !== undefined)\n tanstack.signature = previousTanstack.signature\n const createdAt = coerceCreatedAt(msg.createdAt)\n if (createdAt !== undefined) tanstack.createdAt = createdAt.toISOString()\n\n const structuredOutput = serializedStructuredOutput(\n parts,\n includeSnapshotStructuredOutput,\n )\n if (structuredOutput) tanstack.structuredOutput = structuredOutput\n\n const toolCallMetadata: Record<string, unknown> = {}\n for (const part of parts) {\n if (part.type === 'tool-call' && part.metadata !== undefined) {\n toolCallMetadata[part.id] = part.metadata\n }\n }\n if (Object.keys(toolCallMetadata).length > 0) {\n tanstack.toolCallMetadata = toolCallMetadata\n }\n\n const uiResources = parts.filter(\n (p): p is UIResourcePart => p.type === 'ui-resource',\n )\n if (uiResources.length > 0) tanstack.uiResources = uiResources\n\n if (Object.keys(tanstack).length > 0) base.tanstack = tanstack\n else delete base.tanstack\n return Object.keys(base).length > 0 ? base : undefined\n}\n\nfunction serializedStructuredOutput(\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): TanStackMessageMetadata['structuredOutput'] | undefined {\n for (const p of parts) {\n if (\n p.type === 'structured-output' &&\n (includeSnapshotStructuredOutput || p.status !== 'complete')\n ) {\n return structuredOutputMetadata(p, includeSnapshotStructuredOutput)\n }\n }\n return undefined\n}\n\nfunction structuredOutputMetadata(\n part: StructuredOutputPart,\n includeSnapshotStructuredOutput: boolean,\n): NonNullable<TanStackMessageMetadata['structuredOutput']> {\n return {\n status: part.status,\n raw: part.raw,\n ...(includeSnapshotStructuredOutput && part.partial !== undefined\n ? { partial: part.partial }\n : {}),\n ...(includeSnapshotStructuredOutput && part.data !== undefined\n ? { data: part.data }\n : {}),\n ...(includeSnapshotStructuredOutput && part.reasoning\n ? { reasoning: part.reasoning }\n : {}),\n ...(part.errorMessage !== undefined && { errorMessage: part.errorMessage }),\n }\n}\n\nfunction collectText(parts: ReadonlyArray<MessagePart>): string {\n // The streamed JSON of a completed structured-output part is the source of\n // truth for multi-turn coherence — emitting it back as assistant content\n // lets the LLM see its own prior structured response. Streaming/errored\n // parts are skipped: they'd ship malformed JSON fragments and confuse the\n // model. `completeStructuredOutputPart` tries hard to populate `raw`\n // (caller → existing buffer → `JSON.stringify(data)`), but the stringify\n // fallback can leave it empty when `data` is unserializable (BigInt,\n // circular). The `p.raw !== ''` guard below is what enforces \"no malformed\n // round-trip\" in that case — without it we'd ship `''` and the model would\n // see an empty assistant turn.\n const out: Array<string> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push(p.content)\n } else if (\n p.type === 'structured-output' &&\n p.status === 'complete' &&\n p.raw !== ''\n ) {\n out.push(p.raw)\n }\n }\n return out.join('')\n}\n\n/**\n * A child's messages, tagged with its AG-UI `subagentRunId`. The card data\n * rides in `metadata.tanstack.subagent`, so the other side can rebuild the\n * card and continue a suspended child.\n */\nfunction subagentToWire(\n part: SubagentPart,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const { subagent } = part\n const info: SubagentWireInfo = {\n name: subagent.name,\n status: subagent.status,\n ...(subagent.description !== undefined && {\n description: subagent.description,\n }),\n ...(subagent.error !== undefined && { error: subagent.error }),\n ...(subagent.interruptIds !== undefined && {\n interruptIds: subagent.interruptIds,\n }),\n ...(subagent.parentSubagentRunId !== undefined && {\n parentSubagentRunId: subagent.parentSubagentRunId,\n }),\n ...(subagent.parentToolCallId !== undefined && {\n parentToolCallId: subagent.parentToolCallId,\n }),\n ...(subagent.metadata !== undefined && { metadata: subagent.metadata }),\n }\n const child = uiMessagesToWire(subagent.messages, options)\n const own = child.some((message) => wireSubagentRunId(message) === undefined)\n const messages: Array<WireMessage> = own\n ? child\n : [{ id: `subagent:${subagent.id}`, role: 'assistant' }, ...child]\n return messages.map((message, index) => {\n const nestedId = wireSubagentRunId(message)\n if (nestedId !== undefined) {\n const nested = wireSubagentInfo(message)\n if (!nested || nested.parentSubagentRunId !== undefined) return message\n return withSubagentInfo(message, nestedId, {\n ...nested,\n parentSubagentRunId: subagent.id,\n })\n }\n return withSubagentInfo(\n message,\n subagent.id,\n !own && index === 0 ? { ...info, placeholder: true } : info,\n )\n })\n}\n\nfunction withSubagentInfo(\n message: WireMessage,\n subagentRunId: string,\n info: SubagentWireInfo,\n): WireMessage {\n const metadata = isRecord(message.metadata) ? message.metadata : {}\n const tanstack = isRecord(metadata.tanstack) ? metadata.tanstack : {}\n return {\n ...message,\n subagentRunId,\n metadata: { ...metadata, tanstack: { ...tanstack, subagent: info } },\n }\n}\n\nfunction collectUserContent(\n parts: ReadonlyArray<MessagePart>,\n): string | Array<InputContent> {\n const hasMultimodal = parts.some(\n (p) =>\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document',\n )\n if (!hasMultimodal) {\n return collectText(parts)\n }\n const out: Array<InputContent> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push({ type: 'text', text: p.content })\n } else if (\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document'\n ) {\n out.push(p)\n }\n }\n return out\n}\n\nfunction thoughtSignatureFromMetadata(metadata: unknown): string | undefined {\n if (\n metadata == null ||\n typeof metadata !== 'object' ||\n Array.isArray(metadata)\n ) {\n return undefined\n }\n if (!('thoughtSignature' in metadata)) return undefined\n const value = metadata.thoughtSignature\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction collectToolCalls(\n parts: ReadonlyArray<MessagePart>,\n): Array<ToolCall> | undefined {\n const calls: Array<ToolCall> = []\n for (const p of parts) {\n if (p.type === 'tool-call') {\n const encryptedValue = thoughtSignatureFromMetadata(p.metadata)\n calls.push({\n id: p.id,\n type: 'function',\n function: { name: p.name, arguments: p.arguments },\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n })\n }\n }\n return calls.length > 0 ? calls : undefined\n}\n\nfunction deriveReasoningId(messageId: string, part: MessagePart): string {\n return `${messageId}-reasoning-${(part as { id?: string }).id ?? hashContent((part as { content: string }).content)}`\n}\n\nfunction deriveToolMessageId(toolCallId: string): string {\n return `tool-${toolCallId}`\n}\n\nfunction uniqueToolWireId(id: string, used: Set<string>): string {\n return uniqueWireId(id, used)\n}\n\nfunction uniqueWireId(id: string, used: Set<string>): string {\n if (!used.has(id)) {\n used.add(id)\n return id\n }\n let suffix = 2\n while (used.has(`${id}-${suffix}`)) suffix++\n const unique = `${id}-${suffix}`\n used.add(unique)\n return unique\n}\n\nfunction toolWireId(\n id: string | undefined,\n toolCallId: string,\n assistantIds: ReadonlySet<string>,\n): string {\n const derived = deriveToolMessageId(toolCallId)\n if (id === undefined || assistantIds.has(id)) return derived\n return id\n}\n\nfunction hashContent(s: string): string {\n // Cheap deterministic id suffix; collisions are tolerable since\n // reasoning ids only matter for AG-UI server consumers, not for our\n // own server's dedup logic (which keys on toolCallId, not reasoning id).\n let h = 0\n for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0\n return Math.abs(h).toString(36)\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"ag-ui-wire.js","names":[],"sources":["../../../src/utilities/ag-ui-wire.ts"],"sourcesContent":["import type {\n AssistantMessage,\n InputContent,\n ReasoningMessage,\n SystemMessage,\n ToolCall,\n ToolMessage,\n UserMessage,\n} from '@ag-ui/core'\nimport type {\n ContentPart,\n MessagePart,\n ModelMessage,\n StructuredOutputPart,\n SubagentPart,\n TanStackMessageMetadata,\n ToolResultOutcome,\n UIMessage,\n UIResourcePart,\n} from '../types'\nimport type { MetadataRecord } from './merge-metadata'\nimport { tanstackMetadata } from './merge-metadata'\nimport { isProviderExecutedToolCall } from './provider-executed'\nimport { REDACTED_THINKING_ID_PREFIX } from './reasoning-encrypted-value'\nimport { normalizeToolResult } from './tool-result'\nimport { wireSubagentInfo, wireSubagentRunId } from './subagent-wire'\nimport type { SubagentWireInfo } from './subagent-wire'\nimport {\n coerceCreatedAt,\n modelMessageToUIMessage,\n} from '../activities/chat/messages'\n\ntype WithMetadata<T> = T & { metadata?: MetadataRecord }\ntype WireSystemMessage = WithMetadata<SystemMessage>\ntype WireUserMessage = WithMetadata<UserMessage>\ntype WireAssistantMessage = WithMetadata<AssistantMessage>\ntype WireToolMessage = WithMetadata<\n ToolMessage & {\n name?: string\n }\n>\ntype WireReasoningMessage = WithMetadata<ReasoningMessage>\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null && !Array.isArray(value)\n}\n\nfunction rebuiltToolMetadata(\n metadata: unknown,\n createdAt: unknown,\n id: string | undefined,\n content: string | null | Array<ContentPart>,\n anchorOwnsUiResources = false,\n outcome?: ToolResultOutcome,\n): MetadataRecord | undefined {\n const source: MetadataRecord = isRecord(metadata) ? metadata : {}\n const tanstack = isRecord(source.tanstack) ? { ...source.tanstack } : {}\n if (anchorOwnsUiResources) delete tanstack.uiResources\n const date = coerceCreatedAt(createdAt)\n const toolResult: NonNullable<TanStackMessageMetadata['toolResult']> = {\n ...(id !== undefined ? { id } : {}),\n ...(date && { createdAt: date.toISOString() }),\n ...(Array.isArray(content) && { content }),\n }\n const result = {\n ...source,\n tanstack: {\n ...tanstack,\n ...(outcome !== undefined && { toolResultOutcome: outcome }),\n toolResult,\n },\n }\n return Object.keys(result).length ? result : undefined\n}\n\nexport type WireMessage =\n | WireSystemMessage\n | WireUserMessage\n | WireAssistantMessage\n | WireToolMessage\n | WireReasoningMessage\n\n/**\n * Serialize TanStack `UIMessage`s and `ModelMessage`s into the AG-UI\n * `RunAgentInput.messages` wire shape. Anchors are spec-only (`id`, `role`,\n * `name`, `content`, `toolCalls`, `metadata`). Tool results and thinking parts\n * on assistant messages are additionally emitted as fan-out\n * `{role:'tool',...}` and `{role:'reasoning',...}` entries for strict AG-UI\n * server consumers. Set `includeSnapshotStructuredOutput` to retain complete\n * structured-output metadata for UI snapshots.\n */\nexport function uiMessagesToWire(\n messages: Array<UIMessage | ModelMessage>,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const wire: Array<WireMessage> = []\n const usedWireIds = new Set<string>(\n messages.flatMap((message) =>\n 'id' in message && message.id && message.role !== 'tool'\n ? [message.id]\n : [],\n ),\n )\n const includeSnapshotStructuredOutput =\n options?.includeSnapshotStructuredOutput ?? false\n\n const assistantIds = new Set<string>()\n for (const msg of messages) {\n if (msg.role === 'assistant' && msg.id !== undefined) {\n assistantIds.add(msg.id)\n }\n }\n\n for (const msg of messages) {\n if (!('parts' in msg) && msg.role === 'tool' && msg.toolCallId) {\n const id = uniqueToolWireId(\n toolWireId(msg.id, msg.toolCallId, assistantIds),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n msg.metadata,\n msg.createdAt,\n msg.id,\n msg.content,\n )\n wire.push({\n role: 'tool',\n id,\n ...(msg.name !== undefined && { name: msg.name }),\n toolCallId: msg.toolCallId,\n content:\n typeof msg.content === 'string'\n ? msg.content\n : JSON.stringify(msg.content),\n ...(msg.error !== undefined && { error: msg.error }),\n ...(metadata !== undefined && { metadata }),\n })\n continue\n }\n\n const uiMessage: UIMessage =\n 'parts' in msg ? msg : modelMessageToUIMessage(msg, msg.id)\n const parts: ReadonlyArray<MessagePart> = uiMessage.parts\n usedWireIds.add(uiMessage.id)\n\n if (msg.role === 'system') {\n wire.push(\n toAnchor(\n uiMessage,\n 'system',\n {\n content:\n parts.length > 0\n ? collectText(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n if (msg.role === 'user') {\n wire.push(\n toAnchor(\n uiMessage,\n 'user',\n {\n content:\n parts.length > 0\n ? collectUserContent(parts)\n : ((msg as { content?: string }).content ?? ''),\n },\n parts,\n includeSnapshotStructuredOutput,\n ),\n )\n continue\n }\n\n // assistant: reasoning fan-outs, then anchor, then tool fan-outs.\n //\n // Provider-executed tools (Anthropic web_search / web_fetch) run inside one\n // provider response, and the provider signs every thinking block against\n // the blocks before it. Emitting all reasoning first and a single anchor\n // with the joined text and every tool call turns\n // \"thinking, tool, thinking, text, tool\" into\n // \"thinking, thinking, text, tool, tool\", and the provider rejects the next\n // turn (\"thinking blocks in the latest assistant message cannot be\n // modified\"). Split the message into ordered segments at each thinking\n // part that follows a provider-executed tool call, the same rule\n // buildAssistantMessages applies, so the wire keeps the signed order.\n // Segments after the first get derived anchor ids; strict AG-UI consumers\n // still see plain anchors.\n type Segment = {\n thinking: Array<Extract<MessagePart, { type: 'thinking' }>>\n parts: Array<MessagePart>\n }\n let current: Segment = { thinking: [], parts: [] }\n const segments: Array<Segment> = [current]\n for (const part of parts) {\n if (part.type === 'thinking') {\n if (\n current.parts.some(\n (p) => p.type === 'tool-call' && isProviderExecutedToolCall(p),\n )\n ) {\n current = { thinking: [part], parts: [] }\n segments.push(current)\n } else {\n current.thinking.push(part)\n }\n } else {\n current.parts.push(part)\n }\n }\n\n segments.forEach((segment, index) => {\n for (const part of segment.thinking) {\n const reasoning: WireReasoningMessage = {\n role: 'reasoning',\n id: uniqueWireId(deriveReasoningId(uiMessage.id, part), usedWireIds),\n content: part.content,\n }\n if (part.signature) {\n reasoning.encryptedValue = part.signature\n }\n wire.push(reasoning)\n }\n\n const text = collectText(segment.parts)\n const toolCalls = collectToolCalls(segment.parts)\n const anchorMessage: UIMessage =\n index === 0\n ? uiMessage\n : {\n ...uiMessage,\n id: uniqueWireId(`${uiMessage.id}-segment-${index}`, usedWireIds),\n }\n wire.push(\n toAnchor(\n anchorMessage,\n 'assistant',\n {\n ...(text !== '' && { content: text }),\n ...(toolCalls && { toolCalls }),\n },\n segment.parts,\n includeSnapshotStructuredOutput,\n ),\n )\n })\n\n const explicitToolResults = new Set(\n parts.flatMap((part) =>\n part.type === 'tool-result' ? [part.toolCallId] : [],\n ),\n )\n for (const part of parts) {\n if (part.type === 'tool-result') {\n const id = uniqueToolWireId(\n part.id ?? deriveToolMessageId(part.toolCallId),\n usedWireIds,\n )\n const metadata = rebuiltToolMetadata(\n part.metadata,\n part.createdAt,\n part.id,\n part.content,\n true,\n part.outcome,\n )\n wire.push({\n role: 'tool',\n id,\n toolCallId: part.toolCallId,\n ...(part.name !== undefined && { name: part.name }),\n content:\n typeof part.content === 'string'\n ? part.content\n : JSON.stringify(part.content),\n ...(part.error !== undefined && { error: part.error }),\n ...(metadata !== undefined && { metadata }),\n })\n } else if (part.type === 'tool-call') {\n const approved = part.approval?.approved\n if (\n explicitToolResults.has(part.id) ||\n (part.output === undefined &&\n (part.state !== 'approval-responded' || approved === undefined))\n ) {\n continue\n }\n const result =\n part.output !== undefined\n ? normalizeToolResult(part.output)\n : JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n })\n const content =\n typeof result === 'string' ? result : JSON.stringify(result)\n wire.push({\n role: 'tool',\n id: uniqueToolWireId(deriveToolMessageId(part.id), usedWireIds),\n toolCallId: part.id,\n content,\n metadata: rebuiltToolMetadata(\n undefined,\n undefined,\n undefined,\n result,\n false,\n part.approval?.approved === false ? 'denied' : undefined,\n ),\n })\n }\n }\n\n for (const part of parts) {\n if (part.type === 'subagent') wire.push(...subagentToWire(part, options))\n }\n }\n\n return wire\n}\n\nfunction toAnchor(\n msg: UIMessage,\n role: 'system',\n extras: { content: string },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'user',\n extras: { content: string | Array<InputContent> },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireUserMessage\nfunction toAnchor(\n msg: UIMessage,\n role: 'assistant',\n extras: {\n content?: string\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireAssistantMessage\nfunction toAnchor(\n msg: UIMessage,\n role: UIMessage['role'],\n extras: {\n content?: string | Array<InputContent>\n toolCalls?: Array<ToolCall>\n },\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): WireSystemMessage | WireUserMessage | WireAssistantMessage {\n const metadata = messageMetadata(msg, parts, includeSnapshotStructuredOutput)\n const base = {\n id: msg.id,\n ...(msg.name !== undefined && { name: msg.name }),\n ...(metadata !== undefined && { metadata }),\n }\n if (role === 'system') {\n return { ...base, role, content: String(extras.content ?? '') }\n }\n if (role === 'user') {\n return { ...base, role, content: extras.content ?? '' }\n }\n return {\n ...base,\n role,\n ...(typeof extras.content === 'string' && { content: extras.content }),\n ...(extras.toolCalls !== undefined && { toolCalls: extras.toolCalls }),\n }\n}\n\nfunction messageMetadata(\n msg: UIMessage,\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): MetadataRecord | undefined {\n const base: MetadataRecord = { ...(msg.metadata ?? {}) }\n const previousTanstack = tanstackMetadata(msg)\n const tanstack: TanStackMessageMetadata = {}\n if (previousTanstack?.model !== undefined)\n tanstack.model = previousTanstack.model\n if (previousTanstack?.runId !== undefined)\n tanstack.runId = previousTanstack.runId\n if (previousTanstack?.run?.id !== undefined)\n tanstack.run = { id: previousTanstack.run.id }\n if (previousTanstack?.signature !== undefined)\n tanstack.signature = previousTanstack.signature\n const createdAt = coerceCreatedAt(msg.createdAt)\n if (createdAt !== undefined) tanstack.createdAt = createdAt.toISOString()\n\n const structuredOutput = serializedStructuredOutput(\n parts,\n includeSnapshotStructuredOutput,\n )\n if (structuredOutput) tanstack.structuredOutput = structuredOutput\n\n const toolCallMetadata: Record<string, unknown> = {}\n for (const part of parts) {\n if (part.type === 'tool-call' && part.metadata !== undefined) {\n toolCallMetadata[part.id] = part.metadata\n }\n }\n if (Object.keys(toolCallMetadata).length > 0) {\n tanstack.toolCallMetadata = toolCallMetadata\n }\n\n const uiResources = parts.filter(\n (p): p is UIResourcePart => p.type === 'ui-resource',\n )\n if (uiResources.length > 0) tanstack.uiResources = uiResources\n\n if (Object.keys(tanstack).length > 0) base.tanstack = tanstack\n else delete base.tanstack\n return Object.keys(base).length > 0 ? base : undefined\n}\n\nfunction serializedStructuredOutput(\n parts: ReadonlyArray<MessagePart>,\n includeSnapshotStructuredOutput: boolean,\n): TanStackMessageMetadata['structuredOutput'] | undefined {\n for (const p of parts) {\n if (\n p.type === 'structured-output' &&\n (includeSnapshotStructuredOutput || p.status !== 'complete')\n ) {\n return structuredOutputMetadata(p, includeSnapshotStructuredOutput)\n }\n }\n return undefined\n}\n\nfunction structuredOutputMetadata(\n part: StructuredOutputPart,\n includeSnapshotStructuredOutput: boolean,\n): NonNullable<TanStackMessageMetadata['structuredOutput']> {\n return {\n status: part.status,\n raw: part.raw,\n ...(includeSnapshotStructuredOutput && part.partial !== undefined\n ? { partial: part.partial }\n : {}),\n ...(includeSnapshotStructuredOutput && part.data !== undefined\n ? { data: part.data }\n : {}),\n ...(includeSnapshotStructuredOutput && part.reasoning\n ? { reasoning: part.reasoning }\n : {}),\n ...(part.errorMessage !== undefined && { errorMessage: part.errorMessage }),\n }\n}\n\nfunction collectText(parts: ReadonlyArray<MessagePart>): string {\n // The streamed JSON of a completed structured-output part is the source of\n // truth for multi-turn coherence — emitting it back as assistant content\n // lets the LLM see its own prior structured response. Streaming/errored\n // parts are skipped: they'd ship malformed JSON fragments and confuse the\n // model. `completeStructuredOutputPart` tries hard to populate `raw`\n // (caller → existing buffer → `JSON.stringify(data)`), but the stringify\n // fallback can leave it empty when `data` is unserializable (BigInt,\n // circular). The `p.raw !== ''` guard below is what enforces \"no malformed\n // round-trip\" in that case — without it we'd ship `''` and the model would\n // see an empty assistant turn.\n const out: Array<string> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push(p.content)\n } else if (\n p.type === 'structured-output' &&\n p.status === 'complete' &&\n p.raw !== ''\n ) {\n out.push(p.raw)\n }\n }\n return out.join('')\n}\n\n/**\n * A child's messages, tagged with its AG-UI `subagentRunId`. The card data\n * rides in `metadata.tanstack.subagent`, so the other side can rebuild the\n * card and continue a suspended child.\n */\nfunction subagentToWire(\n part: SubagentPart,\n options?: { includeSnapshotStructuredOutput: boolean },\n): Array<WireMessage> {\n const { subagent } = part\n const info: SubagentWireInfo = {\n name: subagent.name,\n status: subagent.status,\n ...(subagent.description !== undefined && {\n description: subagent.description,\n }),\n ...(subagent.error !== undefined && { error: subagent.error }),\n ...(subagent.interruptIds !== undefined && {\n interruptIds: subagent.interruptIds,\n }),\n ...(subagent.parentSubagentRunId !== undefined && {\n parentSubagentRunId: subagent.parentSubagentRunId,\n }),\n ...(subagent.parentToolCallId !== undefined && {\n parentToolCallId: subagent.parentToolCallId,\n }),\n ...(subagent.metadata !== undefined && { metadata: subagent.metadata }),\n }\n const child = uiMessagesToWire(subagent.messages, options)\n const own = child.some((message) => wireSubagentRunId(message) === undefined)\n const messages: Array<WireMessage> = own\n ? child\n : [{ id: `subagent:${subagent.id}`, role: 'assistant' }, ...child]\n return messages.map((message, index) => {\n const nestedId = wireSubagentRunId(message)\n if (nestedId !== undefined) {\n const nested = wireSubagentInfo(message)\n if (!nested || nested.parentSubagentRunId !== undefined) return message\n return withSubagentInfo(message, nestedId, {\n ...nested,\n parentSubagentRunId: subagent.id,\n })\n }\n return withSubagentInfo(\n message,\n subagent.id,\n !own && index === 0 ? { ...info, placeholder: true } : info,\n )\n })\n}\n\nfunction withSubagentInfo(\n message: WireMessage,\n subagentRunId: string,\n info: SubagentWireInfo,\n): WireMessage {\n const metadata = isRecord(message.metadata) ? message.metadata : {}\n const tanstack = isRecord(metadata.tanstack) ? metadata.tanstack : {}\n return {\n ...message,\n subagentRunId,\n metadata: { ...metadata, tanstack: { ...tanstack, subagent: info } },\n }\n}\n\nfunction collectUserContent(\n parts: ReadonlyArray<MessagePart>,\n): string | Array<InputContent> {\n const hasMultimodal = parts.some(\n (p) =>\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document',\n )\n if (!hasMultimodal) {\n return collectText(parts)\n }\n const out: Array<InputContent> = []\n for (const p of parts) {\n if (p.type === 'text') {\n out.push({ type: 'text', text: p.content })\n } else if (\n p.type === 'image' ||\n p.type === 'audio' ||\n p.type === 'video' ||\n p.type === 'document'\n ) {\n out.push(p)\n }\n }\n return out\n}\n\nfunction thoughtSignatureFromMetadata(metadata: unknown): string | undefined {\n if (\n metadata == null ||\n typeof metadata !== 'object' ||\n Array.isArray(metadata)\n ) {\n return undefined\n }\n if (!('thoughtSignature' in metadata)) return undefined\n const value = metadata.thoughtSignature\n return typeof value === 'string' && value !== '' ? value : undefined\n}\n\nfunction collectToolCalls(\n parts: ReadonlyArray<MessagePart>,\n): Array<ToolCall> | undefined {\n const calls: Array<ToolCall> = []\n for (const p of parts) {\n if (p.type === 'tool-call') {\n const encryptedValue = thoughtSignatureFromMetadata(p.metadata)\n calls.push({\n id: p.id,\n type: 'function',\n function: { name: p.name, arguments: p.arguments },\n ...(encryptedValue !== undefined ? { encryptedValue } : {}),\n })\n }\n }\n return calls.length > 0 ? calls : undefined\n}\n\nfunction deriveReasoningId(messageId: string, part: MessagePart): string {\n const id = `${messageId}-reasoning-${(part as { id?: string }).id ?? hashContent((part as { content: string }).content)}`\n return part.type === 'thinking' && part.redacted\n ? `${REDACTED_THINKING_ID_PREFIX}${id}`\n : id\n}\n\nfunction deriveToolMessageId(toolCallId: string): string {\n return `tool-${toolCallId}`\n}\n\nfunction uniqueToolWireId(id: string, used: Set<string>): string {\n return uniqueWireId(id, used)\n}\n\nfunction uniqueWireId(id: string, used: Set<string>): string {\n if (!used.has(id)) {\n used.add(id)\n return id\n }\n let suffix = 2\n while (used.has(`${id}-${suffix}`)) suffix++\n const unique = `${id}-${suffix}`\n used.add(unique)\n return unique\n}\n\nfunction toolWireId(\n id: string | undefined,\n toolCallId: string,\n assistantIds: ReadonlySet<string>,\n): string {\n const derived = deriveToolMessageId(toolCallId)\n if (id === undefined || assistantIds.has(id)) return derived\n return id\n}\n\nfunction hashContent(s: string): string {\n // Cheap deterministic id suffix; collisions are tolerable since\n // reasoning ids only matter for AG-UI server consumers, not for our\n // own server's dedup logic (which keys on toolCallId, not reasoning id).\n let h = 0\n for (let i = 0; i < s.length; i++) h = (h * 31 + s.charCodeAt(i)) | 0\n return Math.abs(h).toString(36)\n}\n"],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Yield the items of several async streams as they arrive. If the reader
3
+ * stops early, every stream that is still open is closed, so its `finally`
4
+ * runs.
5
+ */
6
+ export declare function mergeStreams<T>(streams: Array<AsyncIterable<T>>): AsyncGenerator<Awaited<T>, void, unknown>;
@@ -0,0 +1,37 @@
1
+ //#region src/utilities/merge-streams.ts
2
+ /**
3
+ * Yield the items of several async streams as they arrive. If the reader
4
+ * stops early, every stream that is still open is closed, so its `finally`
5
+ * runs.
6
+ */
7
+ async function* mergeStreams(streams) {
8
+ const readers = streams.map((stream) => {
9
+ const iterator = stream[Symbol.asyncIterator]();
10
+ return {
11
+ iterator,
12
+ next: iterator.next()
13
+ };
14
+ });
15
+ try {
16
+ while (readers.length > 0) {
17
+ const indexed = readers.map((reader, index) => reader.next.then((result) => ({
18
+ index,
19
+ result,
20
+ reader
21
+ })));
22
+ const winner = await Promise.race(indexed);
23
+ if (winner.result.done) {
24
+ readers.splice(winner.index, 1);
25
+ continue;
26
+ }
27
+ yield winner.result.value;
28
+ winner.reader.next = winner.reader.iterator.next();
29
+ }
30
+ } finally {
31
+ for (const reader of readers) reader.iterator.return?.().catch(() => {});
32
+ }
33
+ }
34
+ //#endregion
35
+ export { mergeStreams };
36
+
37
+ //# sourceMappingURL=merge-streams.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"merge-streams.js","names":[],"sources":["../../../src/utilities/merge-streams.ts"],"sourcesContent":["/**\n * Yield the items of several async streams as they arrive. If the reader\n * stops early, every stream that is still open is closed, so its `finally`\n * runs.\n */\nexport async function* mergeStreams<T>(streams: Array<AsyncIterable<T>>) {\n const readers = streams.map((stream) => {\n const iterator = stream[Symbol.asyncIterator]()\n return {\n iterator,\n next: iterator.next(),\n }\n })\n\n try {\n while (readers.length > 0) {\n const indexed = readers.map((reader, index) =>\n reader.next.then((result) => ({ index, result, reader })),\n )\n const winner = await Promise.race(indexed)\n if (winner.result.done) {\n readers.splice(winner.index, 1)\n continue\n }\n yield winner.result.value\n winner.reader.next = winner.reader.iterator.next()\n }\n } finally {\n // The reader stopped early. Close every stream so its finally runs.\n for (const reader of readers) {\n void reader.iterator.return?.().catch(() => {})\n }\n }\n}\n"],"mappings":";;;;;;AAKA,gBAAuB,aAAgB,SAAkC;CACvE,MAAM,UAAU,QAAQ,KAAK,WAAW;EACtC,MAAM,WAAW,OAAO,OAAO,cAAc,CAAC;EAC9C,OAAO;GACL;GACA,MAAM,SAAS,KAAK;EACtB;CACF,CAAC;CAED,IAAI;EACF,OAAO,QAAQ,SAAS,GAAG;GACzB,MAAM,UAAU,QAAQ,KAAK,QAAQ,UACnC,OAAO,KAAK,MAAM,YAAY;IAAE;IAAO;IAAQ;GAAO,EAAE,CAC1D;GACA,MAAM,SAAS,MAAM,QAAQ,KAAK,OAAO;GACzC,IAAI,OAAO,OAAO,MAAM;IACtB,QAAQ,OAAO,OAAO,OAAO,CAAC;IAC9B;GACF;GACA,MAAM,OAAO,OAAO;GACpB,OAAO,OAAO,OAAO,OAAO,OAAO,SAAS,KAAK;EACnD;CACF,UAAU;EAER,KAAK,MAAM,UAAU,SACnB,OAAY,SAAS,SAAS,CAAC,CAAC,YAAY,CAAC,CAAC;CAElD;AACF"}
@@ -6,3 +6,11 @@ export declare function reasoningEncryptedValue(opts: {
6
6
  encryptedValue: string;
7
7
  timestamp?: number;
8
8
  }): ReasoningEncryptedValueEvent;
9
+ /**
10
+ * Id prefix for the reasoning message of a redacted thinking block (Anthropic
11
+ * `redacted_thinking`). AG-UI's `encryptedValue` does not say what kind of
12
+ * bytes it holds (ag-ui-protocol/ag-ui#2884), so the id that `entityId` points
13
+ * to says it. AG-UI clients keep message ids, but they drop event metadata.
14
+ */
15
+ export declare const REDACTED_THINKING_ID_PREFIX = "redacted_thinking-";
16
+ export declare function isRedactedThinkingId(id: unknown): boolean;
@@ -10,7 +10,17 @@ function reasoningEncryptedValue(opts) {
10
10
  ...opts.timestamp !== void 0 ? { timestamp: opts.timestamp } : {}
11
11
  };
12
12
  }
13
+ /**
14
+ * Id prefix for the reasoning message of a redacted thinking block (Anthropic
15
+ * `redacted_thinking`). AG-UI's `encryptedValue` does not say what kind of
16
+ * bytes it holds (ag-ui-protocol/ag-ui#2884), so the id that `entityId` points
17
+ * to says it. AG-UI clients keep message ids, but they drop event metadata.
18
+ */
19
+ var REDACTED_THINKING_ID_PREFIX = "redacted_thinking-";
20
+ function isRedactedThinkingId(id) {
21
+ return typeof id === "string" && id.startsWith("redacted_thinking-");
22
+ }
13
23
  //#endregion
14
- export { reasoningEncryptedValue };
24
+ export { REDACTED_THINKING_ID_PREFIX, isRedactedThinkingId, reasoningEncryptedValue };
15
25
 
16
26
  //# sourceMappingURL=reasoning-encrypted-value.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"reasoning-encrypted-value.js","names":[],"sources":["../../../src/utilities/reasoning-encrypted-value.ts"],"sourcesContent":["import { EventType } from '../types'\nimport type { ReasoningEncryptedValueEvent } from '../types'\n\n/** Spec event that carries a provider thinking / tool-call signature blob. */\nexport function reasoningEncryptedValue(opts: {\n subtype: 'message' | 'tool-call'\n entityId: string\n encryptedValue: string\n timestamp?: number\n}): ReasoningEncryptedValueEvent {\n return {\n type: EventType.REASONING_ENCRYPTED_VALUE,\n subtype: opts.subtype,\n entityId: opts.entityId,\n encryptedValue: opts.encryptedValue,\n ...(opts.timestamp !== undefined ? { timestamp: opts.timestamp } : {}),\n }\n}\n"],"mappings":";;;AAIA,SAAgB,wBAAwB,MAKP;CAC/B,OAAO;EACL,MAAM,UAAU;EAChB,SAAS,KAAK;EACd,UAAU,KAAK;EACf,gBAAgB,KAAK;EACrB,GAAI,KAAK,cAAc,KAAA,IAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;CACtE;AACF"}
1
+ {"version":3,"file":"reasoning-encrypted-value.js","names":[],"sources":["../../../src/utilities/reasoning-encrypted-value.ts"],"sourcesContent":["import { EventType } from '../types'\nimport type { ReasoningEncryptedValueEvent } from '../types'\n\n/** Spec event that carries a provider thinking / tool-call signature blob. */\nexport function reasoningEncryptedValue(opts: {\n subtype: 'message' | 'tool-call'\n entityId: string\n encryptedValue: string\n timestamp?: number\n}): ReasoningEncryptedValueEvent {\n return {\n type: EventType.REASONING_ENCRYPTED_VALUE,\n subtype: opts.subtype,\n entityId: opts.entityId,\n encryptedValue: opts.encryptedValue,\n ...(opts.timestamp !== undefined ? { timestamp: opts.timestamp } : {}),\n }\n}\n\n/**\n * Id prefix for the reasoning message of a redacted thinking block (Anthropic\n * `redacted_thinking`). AG-UI's `encryptedValue` does not say what kind of\n * bytes it holds (ag-ui-protocol/ag-ui#2884), so the id that `entityId` points\n * to says it. AG-UI clients keep message ids, but they drop event metadata.\n */\nexport const REDACTED_THINKING_ID_PREFIX = 'redacted_thinking-'\n\nexport function isRedactedThinkingId(id: unknown): boolean {\n return typeof id === 'string' && id.startsWith(REDACTED_THINKING_ID_PREFIX)\n}\n"],"mappings":";;;AAIA,SAAgB,wBAAwB,MAKP;CAC/B,OAAO;EACL,MAAM,UAAU;EAChB,SAAS,KAAK;EACd,UAAU,KAAK;EACf,gBAAgB,KAAK;EACrB,GAAI,KAAK,cAAc,KAAA,IAAY,EAAE,WAAW,KAAK,UAAU,IAAI,CAAC;CACtE;AACF;;;;;;;AAQA,IAAa,8BAA8B;AAE3C,SAAgB,qBAAqB,IAAsB;CACzD,OAAO,OAAO,OAAO,YAAY,GAAG,WAAA,oBAAsC;AAC5E"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/ai",
3
- "version": "0.63.0",
3
+ "version": "0.64.0",
4
4
  "description": "Type-safe TypeScript AI SDK for streaming chat, tool calling, agents, structured outputs, and multimodal generation.",
5
5
  "author": "Tanner Linsley",
6
6
  "license": "MIT",
@@ -365,7 +365,7 @@ const { generate, result, isLoading } = useGenerateAudio({
365
365
  ### 3. Text-to-Speech
366
366
 
367
367
  Adapters include `openaiSpeech` (tts-1, tts-1-hd, gpt-4o-audio-preview),
368
- `byteplusSpeech` (`seed-audio-1.0`), and `elevenlabsSpeech` (`eleven_v3`).
368
+ `byteplusSpeech` (`seed-audio-1.0`), and `elevenlabsSpeech` (`eleven_v4`).
369
369
 
370
370
  `elevenlabsSpeech` accepts `format: 'mp3' | 'pcm' | 'opus' | 'wav'`.
371
371
  WAV output contains 44.1 kHz, 16-bit mono PCM with a RIFF header.
@@ -492,7 +492,7 @@ if (!voice) throw new Error('The provider returned no voices.')
492
492
  // voice.status -> 'ready' on every adapter today
493
493
 
494
494
  const speech = await generateSpeech({
495
- adapter: elevenlabsSpeech('eleven_v3'),
495
+ adapter: elevenlabsSpeech('eleven_v4'),
496
496
  text: 'Once upon a time...',
497
497
  voice: voice.voiceId,
498
498
  })
@@ -513,7 +513,7 @@ import { listVoices } from '@tanstack/ai'
513
513
  import { elevenlabsSpeech } from '@tanstack/ai-elevenlabs'
514
514
 
515
515
  const { voices } = await listVoices({
516
- adapter: elevenlabsSpeech('eleven_v3'),
516
+ adapter: elevenlabsSpeech('eleven_v4'),
517
517
  origins: ['generated', 'cloned'],
518
518
  })
519
519
  ```
@@ -9,6 +9,7 @@ import {
9
9
  tanstackMetadata,
10
10
  withTanstackMetadata,
11
11
  } from '../../../utilities/merge-metadata'
12
+ import { mergeStreams } from '../../../utilities/merge-streams'
12
13
  import { INTERRUPT_BINDING_METADATA_KEY } from '../../../interrupt-resume'
13
14
  import { EMIT_STREAM_CHUNK, SUBAGENT_TOOL } from '../tools/tool-calls'
14
15
  import type { SubagentToolOutcome } from '../tools/tool-calls'
@@ -525,36 +526,6 @@ export async function* spawnAgentStream(
525
526
  }
526
527
  }
527
528
 
528
- async function* mergeAgentStreams(streams: Array<AsyncIterable<StreamChunk>>) {
529
- const readers = streams.map((stream) => {
530
- const iterator = stream[Symbol.asyncIterator]()
531
- return {
532
- iterator,
533
- next: iterator.next(),
534
- }
535
- })
536
-
537
- try {
538
- while (readers.length > 0) {
539
- const indexed = readers.map((reader, index) =>
540
- reader.next.then((result) => ({ index, result, reader })),
541
- )
542
- const winner = await Promise.race(indexed)
543
- if (winner.result.done) {
544
- readers.splice(winner.index, 1)
545
- continue
546
- }
547
- yield winner.result.value
548
- winner.reader.next = winner.reader.iterator.next()
549
- }
550
- } finally {
551
- // The reader stopped early. Close every child so its finally runs.
552
- for (const reader of readers) {
553
- void reader.iterator.return?.().catch(() => {})
554
- }
555
- }
556
- }
557
-
558
529
  /** True when a child in these chunks failed or stopped for outside input. */
559
530
  function stopsSequence(chunks: ReadonlyArray<StreamChunk>, id: string) {
560
531
  return chunks.some(
@@ -620,7 +591,7 @@ export async function* spawnNamedAgents(
620
591
  yield* onlyStream
621
592
  return
622
593
  }
623
- yield* mergeAgentStreams(streams)
594
+ yield* mergeStreams(streams)
624
595
  } finally {
625
596
  group.controller.abort()
626
597
  group.dispose()