@tanstack/ai 0.15.0 → 0.17.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 (54) hide show
  1. package/dist/esm/activities/chat/adapter.d.ts +20 -3
  2. package/dist/esm/activities/chat/adapter.js.map +1 -1
  3. package/dist/esm/activities/chat/index.d.ts +16 -6
  4. package/dist/esm/activities/chat/index.js +235 -9
  5. package/dist/esm/activities/chat/index.js.map +1 -1
  6. package/dist/esm/activities/chat/messages.js +4 -2
  7. package/dist/esm/activities/chat/messages.js.map +1 -1
  8. package/dist/esm/activities/chat/stream/message-updaters.d.ts +1 -0
  9. package/dist/esm/activities/chat/stream/message-updaters.js +3 -1
  10. package/dist/esm/activities/chat/stream/message-updaters.js.map +1 -1
  11. package/dist/esm/activities/chat/stream/processor.js +12 -4
  12. package/dist/esm/activities/chat/stream/processor.js.map +1 -1
  13. package/dist/esm/activities/chat/stream/types.d.ts +5 -0
  14. package/dist/esm/activities/chat/tools/tool-calls.js +1 -3
  15. package/dist/esm/activities/chat/tools/tool-calls.js.map +1 -1
  16. package/dist/esm/activities/error-payload.d.ts +0 -8
  17. package/dist/esm/activities/error-payload.js +20 -2
  18. package/dist/esm/activities/error-payload.js.map +1 -1
  19. package/dist/esm/activities/generateImage/adapter.d.ts +2 -2
  20. package/dist/esm/activities/generateImage/adapter.js.map +1 -1
  21. package/dist/esm/activities/generateVideo/adapter.d.ts +2 -2
  22. package/dist/esm/activities/generateVideo/adapter.js.map +1 -1
  23. package/dist/esm/activities/index.d.ts +1 -0
  24. package/dist/esm/activities/index.js +2 -0
  25. package/dist/esm/activities/index.js.map +1 -1
  26. package/dist/esm/activities/stream-generation-result.js +0 -2
  27. package/dist/esm/activities/stream-generation-result.js.map +1 -1
  28. package/dist/esm/activities/summarize/adapter.d.ts +4 -4
  29. package/dist/esm/activities/summarize/adapter.js.map +1 -1
  30. package/dist/esm/activities/summarize/chat-stream-summarize.d.ts +45 -0
  31. package/dist/esm/activities/summarize/chat-stream-summarize.js +148 -0
  32. package/dist/esm/activities/summarize/chat-stream-summarize.js.map +1 -0
  33. package/dist/esm/activities/summarize/index.d.ts +1 -0
  34. package/dist/esm/activities/summarize/index.js +4 -2
  35. package/dist/esm/activities/summarize/index.js.map +1 -1
  36. package/dist/esm/types.d.ts +109 -10
  37. package/package.json +2 -2
  38. package/skills/ai-core/structured-outputs/SKILL.md +92 -1
  39. package/src/activities/chat/adapter.ts +25 -2
  40. package/src/activities/chat/index.ts +368 -26
  41. package/src/activities/chat/messages.ts +6 -0
  42. package/src/activities/chat/stream/message-updaters.ts +8 -0
  43. package/src/activities/chat/stream/processor.ts +12 -0
  44. package/src/activities/chat/stream/types.ts +5 -0
  45. package/src/activities/chat/tools/tool-calls.ts +1 -3
  46. package/src/activities/error-payload.ts +31 -2
  47. package/src/activities/generateImage/adapter.ts +8 -2
  48. package/src/activities/generateVideo/adapter.ts +8 -2
  49. package/src/activities/index.ts +5 -0
  50. package/src/activities/stream-generation-result.ts +4 -6
  51. package/src/activities/summarize/adapter.ts +8 -4
  52. package/src/activities/summarize/chat-stream-summarize.ts +238 -0
  53. package/src/activities/summarize/index.ts +12 -9
  54. package/src/types.ts +122 -10
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sources":["../../../../src/activities/chat/index.ts"],"sourcesContent":["/**\n * Text Activity\n *\n * Handles agentic text generation, one-shot text generation, and agentic structured output.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { devtoolsMiddleware } from '@tanstack/ai-event-client'\nimport { stripToSpecMiddleware } from '../../strip-to-spec-middleware'\nimport { streamToText } from '../../stream-to-response.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport { LazyToolManager } from './tools/lazy-tool-manager'\nimport {\n MiddlewareAbortError,\n ToolCallManager,\n executeToolCalls,\n} from './tools/tool-calls'\nimport {\n convertSchemaToJsonSchema,\n isStandardSchema,\n parseWithStandardSchema,\n} from './tools/schema-converter'\nimport { maxIterations as maxIterationsStrategy } from './agent-loop-strategies'\nimport { convertMessagesToModelMessages } from './messages'\nimport { MiddlewareRunner } from './middleware/compose'\nimport type {\n ApprovalRequest,\n ClientToolRequest,\n ToolResult,\n} from './tools/tool-calls'\nimport type { AnyTextAdapter } from './adapter'\nimport type {\n AgentLoopStrategy,\n ConstrainedModelMessage,\n CustomEvent,\n InferSchemaType,\n ModelMessage,\n RunFinishedEvent,\n SchemaInput,\n StreamChunk,\n TextMessageContentEvent,\n TextOptions,\n Tool,\n ToolCall,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallStartEvent,\n} from '../../types'\nimport type {\n ChatMiddleware,\n ChatMiddlewareConfig,\n ChatMiddlewareContext,\n ChatMiddlewarePhase,\n} from './middleware/types'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { ProviderTool } from '../../tools/provider-tool'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'text' as const\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the text activity.\n * Types are extracted directly from the adapter (which has pre-resolved generics).\n *\n * @template TAdapter - The text adapter type (created by a provider function)\n * @template TSchema - Optional Standard Schema for structured output\n * @template TStream - Whether to stream the output (default: true)\n */\nexport interface TextActivityOptions<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined,\n TStream extends boolean,\n> {\n /** The text adapter to use (created by a provider function like openaiText('gpt-4o')) */\n adapter: TAdapter\n /** Conversation messages - content types are constrained by the adapter's input modalities and metadata */\n messages?: Array<\n ConstrainedModelMessage<{\n inputModalities: TAdapter['~types']['inputModalities']\n messageMetadataByModality: TAdapter['~types']['messageMetadataByModality']\n }>\n >\n /** System prompts to prepend to the conversation */\n systemPrompts?: TextOptions['systemPrompts']\n /**\n * Tools for function calling (auto-executed when called).\n *\n * Accepts two shapes:\n * - User-defined tools via `toolDefinition()` — plain `Tool`, always assignable.\n * - Provider tools from `@tanstack/ai-<provider>/tools` (e.g. `webSearchTool`)\n * — branded and type-checked against the selected model's\n * `supports.tools` list. Passing an unsupported tool produces a\n * compile-time error on the array element.\n */\n tools?: Array<\n | (Tool & { readonly '~toolKind'?: never })\n | ProviderTool<string, TAdapter['~types']['toolCapabilities'][number]>\n >\n /** Controls the randomness of the output. Higher values make output more random. Range: [0.0, 2.0] */\n temperature?: TextOptions['temperature']\n /** Nucleus sampling parameter. The model considers tokens with topP probability mass. */\n topP?: TextOptions['topP']\n /** The maximum number of tokens to generate in the response. */\n maxTokens?: TextOptions['maxTokens']\n /** Additional metadata to attach to the request. */\n metadata?: TextOptions['metadata']\n /** Model-specific provider options (type comes from adapter) */\n modelOptions?: TAdapter['~types']['providerOptions']\n /** AbortController for cancellation */\n abortController?: TextOptions['abortController']\n /** Strategy for controlling the agent loop */\n agentLoopStrategy?: TextOptions['agentLoopStrategy']\n /** Unique conversation identifier for tracking */\n conversationId?: TextOptions['conversationId']\n /** Thread/conversation ID for AG-UI protocol. Auto-generated if not provided. */\n threadId?: TextOptions['threadId']\n /** Run ID override for AG-UI protocol. Auto-generated by adapter if not provided. */\n runId?: TextOptions['runId']\n /**\n * Optional Standard Schema for structured output.\n * When provided, the activity will:\n * 1. Run the full agentic loop (executing tools as needed)\n * 2. Once complete, return a Promise with the parsed output matching the schema\n *\n * Supports any Standard Schema compliant library (Zod v4+, ArkType, Valibot, etc.)\n *\n * @example\n * ```ts\n * const result = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Generate a person' }],\n * outputSchema: z.object({ name: z.string(), age: z.number() })\n * })\n * // result is { name: string, age: number }\n * ```\n */\n outputSchema?: TSchema\n /**\n * Whether to stream the text result.\n * When true (default), returns an AsyncIterable<StreamChunk> for streaming output.\n * When false, returns a Promise<string> with the collected text content.\n *\n * Note: If outputSchema is provided, this option is ignored and the result\n * is always a Promise<InferSchemaType<TSchema>>.\n *\n * @default true\n *\n * @example Non-streaming text\n * ```ts\n * const text = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Hello!' }],\n * stream: false\n * })\n * // text is a string with the full response\n * ```\n */\n stream?: TStream\n /**\n * Optional middleware array for observing/transforming chat behavior.\n * Middleware hooks are called in array order. See {@link ChatMiddleware} for available hooks.\n *\n * @example\n * ```ts\n * const stream = chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [...],\n * middleware: [loggingMiddleware, redactionMiddleware],\n * })\n * ```\n */\n middleware?: Array<ChatMiddleware>\n /**\n * Opaque user-provided context value passed to middleware hooks.\n * Can be used to pass request-scoped data (e.g., user ID, request context).\n */\n context?: unknown\n /**\n * Enable debug logging. Pass `true` to enable all categories with the default\n * console logger, `false` to silence everything, or a `DebugConfig` object for\n * granular control and/or a custom `Logger`. Defaults to `undefined`, which\n * means only the `errors` category is active.\n */\n debug?: DebugOption\n}\n\n// ===========================\n// Chat Options Helper\n// ===========================\n\n/**\n * Create typed options for the chat() function without executing.\n * This is useful for pre-defining configurations with full type inference.\n *\n * @example\n * ```ts\n * const chatOptions = createChatOptions({\n * adapter: anthropicText('claude-sonnet-4-5'),\n * })\n *\n * const stream = chat({ ...chatOptions, messages })\n * ```\n */\nexport function createChatOptions<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined = undefined,\n TStream extends boolean = true,\n>(\n options: TextActivityOptions<TAdapter, TSchema, TStream>,\n): TextActivityOptions<TAdapter, TSchema, TStream> {\n return options\n}\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the text activity.\n * - If outputSchema is provided: Promise<InferSchemaType<TSchema>>\n * - If stream is false: Promise<string>\n * - Otherwise (stream is true, default): AsyncIterable<StreamChunk>\n */\nexport type TextActivityResult<\n TSchema extends SchemaInput | undefined,\n TStream extends boolean = true,\n> = TSchema extends SchemaInput\n ? Promise<InferSchemaType<TSchema>>\n : TStream extends false\n ? Promise<string>\n : AsyncIterable<StreamChunk>\n\n// ===========================\n// ChatEngine Implementation\n// ===========================\n\ninterface TextEngineConfig<\n TAdapter extends AnyTextAdapter,\n TParams extends TextOptions<any, any> = TextOptions<any>,\n> {\n adapter: TAdapter\n systemPrompts?: Array<string>\n params: TParams\n middleware?: Array<ChatMiddleware>\n context?: unknown\n}\n\ntype ToolPhaseResult = 'continue' | 'stop' | 'wait'\ntype CyclePhase = 'processText' | 'executeToolCalls'\n\nclass TextEngine<\n TAdapter extends AnyTextAdapter,\n TParams extends TextOptions<any, any> = TextOptions<any>,\n> {\n private readonly adapter: TAdapter\n private params: TParams\n private systemPrompts: Array<string>\n private tools: Array<Tool>\n private readonly loopStrategy: AgentLoopStrategy\n private toolCallManager: ToolCallManager\n private readonly lazyToolManager: LazyToolManager\n private readonly initialMessageCount: number\n private readonly requestId: string\n private readonly streamId: string\n private readonly effectiveRequest?: Request | RequestInit\n private readonly effectiveSignal?: AbortSignal\n\n private messages: Array<ModelMessage>\n private iterationCount = 0\n private lastFinishReason: string | null = null\n private streamStartTime = 0\n private totalChunkCount = 0\n private currentMessageId: string | null = null\n private accumulatedContent = ''\n private accumulatedThinking: Array<{ content: string; signature?: string }> =\n []\n private currentThinkingContent = ''\n private currentThinkingSignature = ''\n private eventOptions?: Record<string, unknown>\n private eventToolNames?: Array<string>\n private finishedEvent: RunFinishedEvent | null = null\n private earlyTermination = false\n private toolPhase: ToolPhaseResult = 'continue'\n private cyclePhase: CyclePhase = 'processText'\n // Client state extracted from initial messages (before conversion to ModelMessage)\n private readonly initialApprovals: Map<string, boolean>\n private readonly initialClientToolResults: Map<string, any>\n\n // AG-UI protocol IDs\n private threadId: string\n private runIdOverride?: string\n\n // Middleware support\n private readonly middlewareRunner: MiddlewareRunner\n private readonly middlewareCtx: ChatMiddlewareContext\n private readonly deferredPromises: Array<Promise<unknown>> = []\n private abortReason?: string\n private middlewareAbortController?: AbortController\n private terminalHookCalled = false\n\n private readonly logger: InternalLogger\n\n constructor(\n config: TextEngineConfig<TAdapter, TParams>,\n logger: InternalLogger,\n ) {\n this.logger = logger\n this.adapter = config.adapter\n this.params = config.params\n this.systemPrompts = config.params.systemPrompts || []\n this.loopStrategy =\n config.params.agentLoopStrategy || maxIterationsStrategy(5)\n this.initialMessageCount = config.params.messages.length\n\n // Extract client state (approvals, client tool results) from original messages BEFORE conversion\n // This preserves UIMessage parts data that would be lost during conversion to ModelMessage\n const { approvals, clientToolResults } =\n this.extractClientStateFromOriginalMessages(\n config.params.messages as Array<any>,\n )\n this.initialApprovals = approvals\n this.initialClientToolResults = clientToolResults\n\n // Convert messages to ModelMessage format (handles both UIMessage and ModelMessage input)\n // This ensures consistent internal format regardless of what the client sends\n this.messages = convertMessagesToModelMessages(\n config.params.messages as Array<any>,\n )\n\n // Initialize lazy tool manager after messages are converted (needs message history for scanning)\n this.lazyToolManager = new LazyToolManager(\n config.params.tools || [],\n this.messages,\n )\n this.tools = this.lazyToolManager.getActiveTools()\n this.toolCallManager = new ToolCallManager(this.tools)\n this.requestId = this.createId('chat')\n this.streamId = this.createId('stream')\n this.effectiveRequest = config.params.abortController\n ? { signal: config.params.abortController.signal }\n : undefined\n this.effectiveSignal = config.params.abortController?.signal\n this.threadId = config.params.threadId || this.createId('thread')\n this.runIdOverride = config.params.runId\n\n // Initialize middleware — devtools first, strip-to-spec always last.\n // handleStreamChunk processes raw chunks BEFORE middleware, so internal\n // state management sees extended fields (finishReason, delta, toolCallName, etc.).\n // The strip middleware ensures the yielded public stream is AG-UI spec-compliant.\n const allMiddleware = [\n devtoolsMiddleware(),\n ...(config.middleware || []),\n stripToSpecMiddleware(),\n ]\n this.middlewareRunner = new MiddlewareRunner(allMiddleware, logger)\n this.middlewareAbortController = new AbortController()\n this.middlewareCtx = {\n requestId: this.requestId,\n streamId: this.streamId,\n conversationId: config.params.conversationId,\n phase: 'init' as ChatMiddlewarePhase,\n iteration: 0,\n chunkIndex: 0,\n signal: this.effectiveSignal,\n abort: (reason?: string) => {\n this.abortReason = reason\n this.middlewareAbortController?.abort(reason)\n },\n context: config.context,\n defer: (promise: Promise<unknown>) => {\n this.deferredPromises.push(promise)\n },\n // Provider / adapter info\n provider: config.adapter.name,\n model: config.params.model,\n source: 'server',\n streaming: true,\n // Config-derived (updated in beforeRun and applyMiddlewareConfig)\n systemPrompts: this.systemPrompts,\n toolNames: undefined,\n options: undefined,\n modelOptions: config.params.modelOptions,\n // Computed\n messageCount: this.initialMessageCount,\n hasTools: this.tools.length > 0,\n // Mutable per-iteration\n currentMessageId: null,\n accumulatedContent: '',\n // References\n messages: this.messages,\n createId: (prefix: string) => this.createId(prefix),\n }\n }\n\n /** Get the accumulated content after the chat loop completes */\n getAccumulatedContent(): string {\n return this.accumulatedContent\n }\n\n /** Get the final messages array after the chat loop completes */\n getMessages(): Array<ModelMessage> {\n return this.messages\n }\n\n async *run(): AsyncGenerator<StreamChunk> {\n this.beforeRun()\n this.logger.agentLoop('run started', {\n conversationId: this.middlewareCtx.conversationId,\n })\n\n try {\n // Run initial onConfig (phase = init)\n this.middlewareCtx.phase = 'init'\n const initialConfig = this.buildMiddlewareConfig()\n const transformedConfig = await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n initialConfig,\n )\n this.applyMiddlewareConfig(transformedConfig)\n\n // Run onStart (devtools middleware emits text:request:started and initial messages here)\n await this.middlewareRunner.runOnStart(this.middlewareCtx)\n\n const pendingPhase = yield* this.checkForPendingToolCalls()\n if (pendingPhase === 'wait') {\n return\n }\n\n do {\n if (this.earlyTermination || this.isCancelled()) {\n return\n }\n\n this.logger.agentLoop(`iteration=${this.middlewareCtx.iteration}`, {\n iteration: this.middlewareCtx.iteration,\n })\n\n await this.beginCycle()\n\n if (this.cyclePhase === 'processText') {\n // Run onConfig before each model call (phase = beforeModel)\n this.middlewareCtx.phase = 'beforeModel'\n this.middlewareCtx.iteration = this.iterationCount\n const iterConfig = this.buildMiddlewareConfig()\n const transformedConfig = await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n iterConfig,\n )\n this.applyMiddlewareConfig(transformedConfig)\n\n yield* this.streamModelResponse()\n } else {\n yield* this.processToolCalls()\n }\n\n this.endCycle()\n } while (this.shouldContinue())\n\n this.logger.agentLoop('run finished', {\n finishReason: this.lastFinishReason,\n })\n\n // Call terminal onFinish hook (skip when waiting for client — stream is paused, not finished)\n if (!this.terminalHookCalled && this.toolPhase !== 'wait') {\n this.terminalHookCalled = true\n await this.middlewareRunner.runOnFinish(this.middlewareCtx, {\n finishReason: this.lastFinishReason,\n duration: Date.now() - this.streamStartTime,\n content: this.accumulatedContent,\n usage: this.finishedEvent?.usage,\n })\n }\n } catch (error: unknown) {\n if (!this.terminalHookCalled) {\n this.terminalHookCalled = true\n if (error instanceof MiddlewareAbortError) {\n // Middleware abort decision — call onAbort, not onError\n this.abortReason = error.message\n await this.middlewareRunner.runOnAbort(this.middlewareCtx, {\n reason: error.message,\n duration: Date.now() - this.streamStartTime,\n })\n } else {\n // Genuine error — call onError\n this.logger.errors('chat run failed', {\n error,\n conversationId: this.middlewareCtx.conversationId,\n })\n await this.middlewareRunner.runOnError(this.middlewareCtx, {\n error,\n duration: Date.now() - this.streamStartTime,\n })\n }\n }\n // Don't rethrow middleware abort errors — the run just stops gracefully\n if (!(error instanceof MiddlewareAbortError)) {\n throw error\n }\n } finally {\n // Check for abort terminal hook\n if (!this.terminalHookCalled && this.isCancelled()) {\n this.terminalHookCalled = true\n await this.middlewareRunner.runOnAbort(this.middlewareCtx, {\n reason: this.abortReason,\n duration: Date.now() - this.streamStartTime,\n })\n }\n\n // Await deferred promises (non-blocking side effects)\n if (this.deferredPromises.length > 0) {\n await Promise.allSettled(this.deferredPromises)\n }\n }\n }\n\n private beforeRun(): void {\n this.streamStartTime = Date.now()\n const { tools, temperature, topP, maxTokens, metadata } = this.params\n\n // Gather flattened options into an object for context\n const options: Record<string, unknown> = {}\n if (temperature !== undefined) options.temperature = temperature\n if (topP !== undefined) options.topP = topP\n if (maxTokens !== undefined) options.maxTokens = maxTokens\n if (metadata !== undefined) options.metadata = metadata\n\n this.eventOptions = Object.keys(options).length > 0 ? options : undefined\n this.eventToolNames = tools?.map((t) => t.name)\n\n // Update middleware context with computed fields\n this.middlewareCtx.options = this.eventOptions\n this.middlewareCtx.toolNames = this.eventToolNames\n }\n\n private async beginCycle(): Promise<void> {\n if (this.cyclePhase === 'processText') {\n await this.beginIteration()\n }\n }\n\n private endCycle(): void {\n if (this.cyclePhase === 'processText') {\n this.cyclePhase = 'executeToolCalls'\n return\n }\n\n this.cyclePhase = 'processText'\n this.iterationCount++\n }\n\n private async beginIteration(): Promise<void> {\n this.currentMessageId = this.createId('msg')\n this.accumulatedContent = ''\n this.accumulatedThinking = []\n this.currentThinkingContent = ''\n this.currentThinkingSignature = ''\n this.finishedEvent = null\n\n // Update mutable context fields\n this.middlewareCtx.currentMessageId = this.currentMessageId\n this.middlewareCtx.accumulatedContent = ''\n\n // Notify middleware of new iteration (devtools emits assistant message:created here)\n await this.middlewareRunner.runOnIteration(this.middlewareCtx, {\n iteration: this.iterationCount,\n messageId: this.currentMessageId,\n })\n }\n\n private async *streamModelResponse(): AsyncGenerator<StreamChunk> {\n const { temperature, topP, maxTokens, metadata, modelOptions } = this.params\n const tools = this.tools\n\n // Convert tool schemas to JSON Schema before passing to adapter\n const toolsWithJsonSchemas = tools.map((tool) => ({\n ...tool,\n inputSchema: tool.inputSchema\n ? convertSchemaToJsonSchema(tool.inputSchema)\n : undefined,\n outputSchema: tool.outputSchema\n ? convertSchemaToJsonSchema(tool.outputSchema)\n : undefined,\n }))\n\n this.middlewareCtx.phase = 'modelStream'\n\n const providerName =\n (this.adapter as { provider?: string }).provider ?? this.adapter.name\n this.logger.request(\n `activity=chat provider=${providerName} model=${this.params.model} messages=${this.messages.length} tools=${this.tools.length} stream=true`,\n {\n provider: providerName,\n model: this.params.model,\n messageCount: this.messages.length,\n toolCount: this.tools.length,\n },\n )\n\n for await (const chunk of this.adapter.chatStream({\n model: this.params.model,\n messages: this.messages,\n tools: toolsWithJsonSchemas,\n temperature,\n topP,\n maxTokens,\n metadata,\n request: this.effectiveRequest,\n modelOptions,\n systemPrompts: this.systemPrompts,\n logger: this.logger,\n threadId: this.threadId,\n runId: this.runIdOverride,\n })) {\n if (this.isCancelled()) {\n break\n }\n\n this.totalChunkCount++\n\n // Process the original (unstripped) chunk for internal state management\n // BEFORE middleware, so fields like finishReason, delta, etc. are available\n this.handleStreamChunk(chunk)\n\n // Pipe chunk through middleware (devtools middleware observes; strip-to-spec cleans)\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n chunk,\n )\n for (const outputChunk of outputChunks) {\n this.logger.output(`type=${outputChunk.type}`, { chunk: outputChunk })\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n\n // Handle usage via middleware\n if (chunk.type === 'RUN_FINISHED' && chunk.usage) {\n await this.middlewareRunner.runOnUsage(this.middlewareCtx, chunk.usage)\n }\n\n if (this.earlyTermination) {\n break\n }\n }\n }\n\n private handleStreamChunk(chunk: StreamChunk): void {\n switch (chunk.type) {\n // AG-UI Events\n case 'TEXT_MESSAGE_CONTENT':\n this.handleTextMessageContentEvent(chunk)\n break\n case 'TOOL_CALL_START':\n this.handleToolCallStartEvent(chunk)\n break\n case 'TOOL_CALL_ARGS':\n this.handleToolCallArgsEvent(chunk)\n break\n case 'TOOL_CALL_END':\n this.handleToolCallEndEvent(chunk)\n break\n case 'RUN_FINISHED':\n this.handleRunFinishedEvent(chunk)\n break\n case 'RUN_ERROR':\n this.handleRunErrorEvent(chunk)\n break\n case 'STEP_STARTED':\n this.handleStepStartedEvent()\n break\n case 'STEP_FINISHED':\n this.handleStepFinishedEvent(chunk)\n break\n\n case 'TOOL_CALL_RESULT':\n // Tool result is already added to messages in buildToolResultChunks\n break\n\n case 'REASONING_START':\n case 'REASONING_MESSAGE_START':\n case 'REASONING_MESSAGE_CONTENT':\n case 'REASONING_MESSAGE_END':\n case 'REASONING_END':\n // Reasoning events are handled by StreamProcessor\n break\n\n default:\n // RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_END,\n // STATE_SNAPSHOT, STATE_DELTA, CUSTOM\n // - no special handling needed in chat activity\n break\n }\n }\n\n // ===========================\n // AG-UI Event Handlers\n // ===========================\n\n private handleTextMessageContentEvent(chunk: TextMessageContentEvent): void {\n if (chunk.content) {\n this.accumulatedContent = chunk.content\n } else {\n this.accumulatedContent += chunk.delta\n }\n this.middlewareCtx.accumulatedContent = this.accumulatedContent\n }\n\n private handleToolCallStartEvent(chunk: ToolCallStartEvent): void {\n this.toolCallManager.addToolCallStartEvent(chunk)\n }\n\n private handleToolCallArgsEvent(chunk: ToolCallArgsEvent): void {\n this.toolCallManager.addToolCallArgsEvent(chunk)\n }\n\n private handleToolCallEndEvent(chunk: ToolCallEndEvent): void {\n this.toolCallManager.completeToolCall(chunk)\n }\n\n private handleRunFinishedEvent(chunk: RunFinishedEvent): void {\n this.finishedEvent = chunk\n this.lastFinishReason = chunk.finishReason ?? null\n }\n\n private handleRunErrorEvent(\n _chunk: Extract<StreamChunk, { type: 'RUN_ERROR' }>,\n ): void {\n this.earlyTermination = true\n }\n\n private finalizeCurrentThinkingStep(): void {\n if (this.currentThinkingContent) {\n this.accumulatedThinking.push({\n content: this.currentThinkingContent,\n ...(this.currentThinkingSignature && {\n signature: this.currentThinkingSignature,\n }),\n })\n this.currentThinkingContent = ''\n this.currentThinkingSignature = ''\n }\n }\n\n private handleStepStartedEvent(): void {\n this.finalizeCurrentThinkingStep()\n }\n\n private handleStepFinishedEvent(\n chunk: Extract<StreamChunk, { type: 'STEP_FINISHED' }>,\n ): void {\n if (chunk.delta) {\n this.currentThinkingContent += chunk.delta\n }\n if (chunk.signature) {\n this.currentThinkingSignature = chunk.signature\n }\n }\n\n private async *checkForPendingToolCalls(): AsyncGenerator<\n StreamChunk,\n ToolPhaseResult,\n void\n > {\n const pendingToolCalls = this.getPendingToolCallsFromMessages()\n if (pendingToolCalls.length === 0) {\n return 'continue'\n }\n\n const finishEvent = this.createSyntheticFinishedEvent()\n\n // Handle undiscovered lazy tool calls with self-correcting error messages\n const undiscoveredLazyResults: Array<ToolResult> = []\n const executablePendingCalls = pendingToolCalls.filter((tc) => {\n if (this.lazyToolManager.isUndiscoveredLazyTool(tc.function.name)) {\n undiscoveredLazyResults.push({\n toolCallId: tc.id,\n toolName: tc.function.name,\n result: {\n error: this.lazyToolManager.getUndiscoveredToolError(\n tc.function.name,\n ),\n },\n state: 'output-error',\n })\n return false\n }\n return true\n })\n\n if (undiscoveredLazyResults.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n undiscoveredLazyResults,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n if (executablePendingCalls.length === 0) {\n return 'continue'\n }\n\n const { approvals, clientToolResults } = this.collectClientState()\n\n const generator = executeToolCalls(\n executablePendingCalls,\n this.tools,\n approvals,\n clientToolResults,\n (eventName, data) => this.createCustomEventChunk(eventName, data),\n {\n onBeforeToolCall: async (toolCall, tool, args) => {\n this.logger.tools(`phase=before name=${toolCall.function.name}`, {\n name: toolCall.function.name,\n args,\n })\n const hookCtx = {\n toolCall,\n tool,\n args,\n toolName: toolCall.function.name,\n toolCallId: toolCall.id,\n }\n return this.middlewareRunner.runOnBeforeToolCall(\n this.middlewareCtx,\n hookCtx,\n )\n },\n onAfterToolCall: async (info) => {\n this.logger.tools(`phase=after name=${info.toolName}`, {\n name: info.toolName,\n result: info.result,\n })\n await this.middlewareRunner.runOnAfterToolCall(\n this.middlewareCtx,\n info,\n )\n },\n },\n )\n\n // Consume the async generator, yielding custom events and collecting the return value\n const executionResult = yield* this.drainToolCallGenerator(generator)\n\n // Check if middleware aborted during pending tool execution\n if (this.isMiddlewareAborted()) {\n this.setToolPhase('stop')\n return 'stop'\n }\n\n // Notify middleware of tool phase completion (devtools emits aggregate events here)\n await this.middlewareRunner.runOnToolPhaseComplete(this.middlewareCtx, {\n toolCalls: pendingToolCalls,\n results: executionResult.results,\n needsApproval: executionResult.needsApproval,\n needsClientExecution: executionResult.needsClientExecution,\n })\n\n // Build args lookup so buildToolResultChunks can emit TOOL_CALL_START +\n // TOOL_CALL_ARGS before TOOL_CALL_END during continuation re-executions.\n const argsMap = new Map<string, string>()\n for (const tc of pendingToolCalls) {\n argsMap.set(tc.id, tc.function.arguments)\n }\n\n if (\n executionResult.needsApproval.length > 0 ||\n executionResult.needsClientExecution.length > 0\n ) {\n if (executionResult.results.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n argsMap,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n for (const chunk of this.buildApprovalChunks(\n executionResult.needsApproval,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n for (const chunk of this.buildClientToolChunks(\n executionResult.needsClientExecution,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n this.setToolPhase('wait')\n return 'wait'\n }\n\n const toolResultChunks = this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n argsMap,\n )\n\n for (const chunk of toolResultChunks) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n return 'continue'\n }\n\n private async *processToolCalls(): AsyncGenerator<StreamChunk, void, void> {\n if (!this.shouldExecuteToolPhase()) {\n this.setToolPhase('stop')\n return\n }\n\n const toolCalls = this.toolCallManager.getToolCalls()\n const finishEvent = this.finishedEvent\n\n if (!finishEvent || toolCalls.length === 0) {\n this.setToolPhase('stop')\n return\n }\n\n this.addAssistantToolCallMessage(toolCalls)\n\n // Handle undiscovered lazy tool calls with self-correcting error messages\n const undiscoveredLazyResults: Array<ToolResult> = []\n const executableToolCalls = toolCalls.filter((tc) => {\n if (this.lazyToolManager.isUndiscoveredLazyTool(tc.function.name)) {\n undiscoveredLazyResults.push({\n toolCallId: tc.id,\n toolName: tc.function.name,\n result: {\n error: this.lazyToolManager.getUndiscoveredToolError(\n tc.function.name,\n ),\n },\n state: 'output-error',\n })\n return false\n }\n return true\n })\n\n if (undiscoveredLazyResults.length > 0) {\n const finishEvt = this.finishedEvent!\n for (const chunk of this.buildToolResultChunks(\n undiscoveredLazyResults,\n finishEvt,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n if (executableToolCalls.length === 0) {\n // All tool calls were undiscovered lazy tools — errors emitted, continue loop\n this.toolCallManager.clear()\n this.setToolPhase('continue')\n return\n }\n this.middlewareCtx.phase = 'beforeTools'\n\n const { approvals, clientToolResults } = this.collectClientState()\n\n const generator = executeToolCalls(\n executableToolCalls,\n this.tools,\n approvals,\n clientToolResults,\n (eventName, data) => this.createCustomEventChunk(eventName, data),\n {\n onBeforeToolCall: async (toolCall, tool, args) => {\n this.logger.tools(`phase=before name=${toolCall.function.name}`, {\n name: toolCall.function.name,\n args,\n })\n const hookCtx = {\n toolCall,\n tool,\n args,\n toolName: toolCall.function.name,\n toolCallId: toolCall.id,\n }\n return this.middlewareRunner.runOnBeforeToolCall(\n this.middlewareCtx,\n hookCtx,\n )\n },\n onAfterToolCall: async (info) => {\n this.logger.tools(`phase=after name=${info.toolName}`, {\n name: info.toolName,\n result: info.result,\n })\n await this.middlewareRunner.runOnAfterToolCall(\n this.middlewareCtx,\n info,\n )\n },\n },\n )\n\n // Consume the async generator, yielding custom events and collecting the return value\n const executionResult = yield* this.drainToolCallGenerator(generator)\n\n this.middlewareCtx.phase = 'afterTools'\n\n // Check if middleware aborted during tool execution\n if (this.isMiddlewareAborted()) {\n this.setToolPhase('stop')\n return\n }\n\n // Notify middleware of tool phase completion (devtools emits aggregate events here)\n await this.middlewareRunner.runOnToolPhaseComplete(this.middlewareCtx, {\n toolCalls,\n results: executionResult.results,\n needsApproval: executionResult.needsApproval,\n needsClientExecution: executionResult.needsClientExecution,\n })\n\n if (\n executionResult.needsApproval.length > 0 ||\n executionResult.needsClientExecution.length > 0\n ) {\n if (executionResult.results.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n for (const chunk of this.buildApprovalChunks(\n executionResult.needsApproval,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n for (const chunk of this.buildClientToolChunks(\n executionResult.needsClientExecution,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n this.setToolPhase('wait')\n return\n }\n\n const toolResultChunks = this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n )\n\n for (const chunk of toolResultChunks) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n // Refresh tools if lazy tools were discovered in this batch\n if (this.lazyToolManager.hasNewlyDiscoveredTools()) {\n this.tools = this.lazyToolManager.getActiveTools()\n this.toolCallManager = new ToolCallManager(this.tools)\n this.setToolPhase('continue')\n return\n }\n\n this.toolCallManager.clear()\n\n this.setToolPhase('continue')\n }\n\n private shouldExecuteToolPhase(): boolean {\n return (\n this.finishedEvent?.finishReason === 'tool_calls' &&\n this.tools.length > 0 &&\n this.toolCallManager.hasToolCalls()\n )\n }\n\n private addAssistantToolCallMessage(toolCalls: Array<ToolCall>): void {\n this.finalizeCurrentThinkingStep()\n\n this.messages = [\n ...this.messages,\n {\n role: 'assistant',\n content: this.accumulatedContent || null,\n toolCalls,\n ...(this.accumulatedThinking.length > 0 && {\n thinking: this.accumulatedThinking,\n }),\n },\n ]\n }\n\n /**\n * Extract client state (approvals and client tool results) from original messages.\n * This is called in the constructor BEFORE converting to ModelMessage format,\n * because the parts array (which contains approval state) is lost during conversion.\n */\n private extractClientStateFromOriginalMessages(\n originalMessages: Array<any>,\n ): {\n approvals: Map<string, boolean>\n clientToolResults: Map<string, any>\n } {\n const approvals = new Map<string, boolean>()\n const clientToolResults = new Map<string, any>()\n\n for (const message of originalMessages) {\n // Check for UIMessage format (parts array) - extract client tool results and approvals\n if (message.role === 'assistant' && message.parts) {\n for (const part of message.parts) {\n if (part.type === 'tool-call') {\n // Extract client tool results (tools without approval that have output)\n if (part.output !== undefined && !part.approval) {\n clientToolResults.set(part.id, part.output)\n }\n // Extract approval responses from UIMessage format parts\n if (\n part.approval?.id &&\n part.approval?.approved !== undefined &&\n part.state === 'approval-responded'\n ) {\n approvals.set(part.approval.id, part.approval.approved)\n }\n }\n }\n }\n }\n\n return { approvals, clientToolResults }\n }\n\n private collectClientState(): {\n approvals: Map<string, boolean>\n clientToolResults: Map<string, any>\n } {\n // Start with the initial client state extracted from original messages\n const approvals = new Map(this.initialApprovals)\n const clientToolResults = new Map(this.initialClientToolResults)\n\n // Also check current messages for any additional tool results (from server tools)\n for (const message of this.messages) {\n // Check for ModelMessage format (role: 'tool' messages contain tool results)\n // This handles results sent back from the client after executing client-side tools\n if (message.role === 'tool' && message.toolCallId) {\n // Parse content back to original output (was stringified by uiMessageToModelMessages)\n let output: unknown\n try {\n output = JSON.parse(message.content as string)\n } catch {\n output = message.content\n }\n // Skip approval response messages (they have pendingExecution marker)\n // These are NOT real client tool results — they are synthetic tool messages\n // created by uiMessageToModelMessages for approved-but-not-yet-executed tools.\n // Treating them as results would prevent the server from requesting actual\n // client-side execution after approval (see GitHub issue #225).\n if (\n output &&\n typeof output === 'object' &&\n (output as any).pendingExecution === true\n ) {\n continue\n }\n clientToolResults.set(message.toolCallId, output)\n }\n }\n\n return { approvals, clientToolResults }\n }\n\n private buildApprovalChunks(\n approvals: Array<ApprovalRequest>,\n finishEvent: RunFinishedEvent,\n ): Array<StreamChunk> {\n const chunks: Array<StreamChunk> = []\n\n for (const approval of approvals) {\n chunks.push({\n type: 'CUSTOM',\n timestamp: Date.now(),\n model: finishEvent.model,\n name: 'approval-requested',\n value: {\n toolCallId: approval.toolCallId,\n toolName: approval.toolName,\n input: approval.input,\n approval: {\n id: approval.approvalId,\n needsApproval: true,\n },\n },\n } as StreamChunk)\n }\n\n return chunks\n }\n\n private buildClientToolChunks(\n clientRequests: Array<ClientToolRequest>,\n finishEvent: RunFinishedEvent,\n ): Array<StreamChunk> {\n const chunks: Array<StreamChunk> = []\n\n for (const clientTool of clientRequests) {\n chunks.push({\n type: 'CUSTOM',\n timestamp: Date.now(),\n model: finishEvent.model,\n name: 'tool-input-available',\n value: {\n toolCallId: clientTool.toolCallId,\n toolName: clientTool.toolName,\n input: clientTool.input,\n },\n } as StreamChunk)\n }\n\n return chunks\n }\n\n private buildToolResultChunks(\n results: Array<ToolResult>,\n finishEvent: RunFinishedEvent,\n argsMap?: Map<string, string>,\n ): Array<StreamChunk> {\n const chunks: Array<StreamChunk> = []\n\n for (const result of results) {\n const content = JSON.stringify(result.result)\n\n // Emit TOOL_CALL_START + TOOL_CALL_ARGS before TOOL_CALL_END so that\n // the client can reconstruct the full tool call during continuations.\n if (argsMap) {\n chunks.push({\n type: 'TOOL_CALL_START',\n timestamp: Date.now(),\n model: finishEvent.model,\n toolCallId: result.toolCallId,\n toolCallName: result.toolName,\n toolName: result.toolName,\n } as StreamChunk)\n\n const args = argsMap.get(result.toolCallId) ?? '{}'\n chunks.push({\n type: 'TOOL_CALL_ARGS',\n timestamp: Date.now(),\n model: finishEvent.model,\n toolCallId: result.toolCallId,\n delta: args,\n args,\n } as StreamChunk)\n }\n\n chunks.push({\n type: 'TOOL_CALL_END',\n timestamp: Date.now(),\n model: finishEvent.model,\n toolCallId: result.toolCallId,\n toolCallName: result.toolName,\n toolName: result.toolName,\n result: content,\n } as StreamChunk)\n\n // AG-UI spec TOOL_CALL_RESULT event\n chunks.push({\n type: 'TOOL_CALL_RESULT',\n timestamp: Date.now(),\n model: finishEvent.model,\n messageId: this.createId('tool-result'),\n toolCallId: result.toolCallId,\n content,\n role: 'tool',\n } as StreamChunk)\n\n // If a placeholder tool message exists for this toolCallId (created by\n // uiMessageToModelMessages for an approval-responded part with no\n // output yet), replace it with the real result. Otherwise the LLM sees\n // both messages — and since the Anthropic adapter dedupes tool_result\n // blocks by tool_use_id keeping the first match, the placeholder wins\n // and the real result is dropped (see issue #532).\n const placeholderIdx = this.messages.findIndex((m) => {\n if (m.role !== 'tool' || m.toolCallId !== result.toolCallId) {\n return false\n }\n if (typeof m.content !== 'string') return false\n try {\n return JSON.parse(m.content)?.pendingExecution === true\n } catch {\n return false\n }\n })\n\n const newToolMessage: ModelMessage = {\n role: 'tool',\n content,\n toolCallId: result.toolCallId,\n }\n\n if (placeholderIdx >= 0) {\n this.messages = [\n ...this.messages.slice(0, placeholderIdx),\n newToolMessage,\n ...this.messages.slice(placeholderIdx + 1),\n ]\n } else {\n this.messages = [...this.messages, newToolMessage]\n }\n }\n\n return chunks\n }\n\n private getPendingToolCallsFromMessages(): Array<ToolCall> {\n // Build a set of completed tool IDs, but exclude tools with pendingExecution marker\n // (these are approved tools that still need to execute)\n const completedToolIds = new Set<string>()\n\n for (const message of this.messages) {\n if (message.role === 'tool' && message.toolCallId) {\n // Check if this is an approval response with pendingExecution marker\n let hasPendingExecution = false\n if (typeof message.content === 'string') {\n try {\n const parsed = JSON.parse(message.content)\n if (parsed.pendingExecution === true) {\n hasPendingExecution = true\n }\n } catch {\n // Not JSON, treat as regular tool result\n }\n }\n\n // Only mark as complete if NOT pending execution\n if (!hasPendingExecution) {\n completedToolIds.add(message.toolCallId)\n }\n }\n }\n\n const pending: Array<ToolCall> = []\n\n for (const message of this.messages) {\n if (message.role === 'assistant' && message.toolCalls) {\n for (const toolCall of message.toolCalls) {\n if (!completedToolIds.has(toolCall.id)) {\n pending.push(toolCall)\n }\n }\n }\n }\n\n return pending\n }\n\n private createSyntheticFinishedEvent(): RunFinishedEvent {\n return {\n type: 'RUN_FINISHED',\n runId: this.createId('pending'),\n threadId: this.threadId,\n model: this.params.model,\n timestamp: Date.now(),\n finishReason: 'tool_calls',\n } as RunFinishedEvent\n }\n\n private shouldContinue(): boolean {\n if (this.cyclePhase === 'executeToolCalls') {\n return true\n }\n\n return (\n this.loopStrategy({\n iterationCount: this.iterationCount,\n messages: this.messages,\n finishReason: this.lastFinishReason,\n }) && this.toolPhase === 'continue'\n )\n }\n\n private isAborted(): boolean {\n return !!this.effectiveSignal?.aborted\n }\n\n private isMiddlewareAborted(): boolean {\n return !!this.middlewareAbortController?.signal.aborted\n }\n\n private isCancelled(): boolean {\n return this.isAborted() || this.isMiddlewareAborted()\n }\n\n private buildMiddlewareConfig(): ChatMiddlewareConfig {\n return {\n messages: this.messages,\n systemPrompts: [...this.systemPrompts],\n tools: [...this.tools],\n temperature: this.params.temperature,\n topP: this.params.topP,\n maxTokens: this.params.maxTokens,\n metadata: this.params.metadata,\n modelOptions: this.params.modelOptions,\n }\n }\n\n private applyMiddlewareConfig(config: ChatMiddlewareConfig): void {\n this.messages = config.messages\n this.systemPrompts = config.systemPrompts\n this.tools = config.tools\n this.params = {\n ...this.params,\n temperature: config.temperature,\n topP: config.topP,\n maxTokens: config.maxTokens,\n metadata: config.metadata,\n modelOptions: config.modelOptions,\n }\n\n // Sync context fields that depend on config\n this.middlewareCtx.messages = this.messages\n this.middlewareCtx.systemPrompts = this.systemPrompts\n this.middlewareCtx.hasTools = this.tools.length > 0\n this.middlewareCtx.toolNames = this.tools.map((t) => t.name)\n this.middlewareCtx.modelOptions = config.modelOptions\n }\n\n private setToolPhase(phase: ToolPhaseResult): void {\n this.toolPhase = phase\n }\n\n /**\n * Pipe a single chunk through the middleware pipeline (strip-to-spec, devtools, etc.)\n * and yield all resulting output chunks.\n */\n private async *pipeThroughMiddleware(\n chunk: StreamChunk,\n ): AsyncGenerator<StreamChunk, void, void> {\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n chunk,\n )\n for (const outputChunk of outputChunks) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n /**\n * Drain an executeToolCalls async generator, yielding any CustomEvent chunks\n * through the middleware pipeline and returning the final ExecuteToolCallsResult.\n */\n private async *drainToolCallGenerator(\n generator: AsyncGenerator<\n CustomEvent,\n {\n results: Array<ToolResult>\n needsApproval: Array<ApprovalRequest>\n needsClientExecution: Array<ClientToolRequest>\n },\n void\n >,\n ): AsyncGenerator<\n StreamChunk,\n {\n results: Array<ToolResult>\n needsApproval: Array<ApprovalRequest>\n needsClientExecution: Array<ClientToolRequest>\n },\n void\n > {\n let next = await generator.next()\n while (!next.done) {\n yield* this.pipeThroughMiddleware(next.value)\n next = await generator.next()\n }\n return next.value\n }\n\n private createCustomEventChunk(\n eventName: string,\n value: Record<string, any>,\n ): CustomEvent {\n return {\n type: 'CUSTOM',\n timestamp: Date.now(),\n model: this.params.model,\n name: eventName,\n value,\n } as CustomEvent\n }\n\n private createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n }\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * Text activity - handles agentic text generation, one-shot text generation, and agentic structured output.\n *\n * This activity supports four modes:\n * 1. **Streaming agentic text**: Stream responses with automatic tool execution\n * 2. **Streaming one-shot text**: Simple streaming request/response without tools\n * 3. **Non-streaming text**: Returns collected text as a string (stream: false)\n * 4. **Agentic structured output**: Run tools, then return structured data\n *\n * @example Full agentic text (streaming with tools)\n * ```ts\n * import { chat } from '@tanstack/ai'\n * import { openaiText } from '@tanstack/ai-openai'\n *\n * for await (const chunk of chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'What is the weather?' }],\n * tools: [weatherTool]\n * })) {\n * if (chunk.type === 'content') {\n * console.log(chunk.delta)\n * }\n * }\n * ```\n *\n * @example One-shot text (streaming without tools)\n * ```ts\n * for await (const chunk of chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Hello!' }]\n * })) {\n * console.log(chunk)\n * }\n * ```\n *\n * @example Non-streaming text (stream: false)\n * ```ts\n * const text = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Hello!' }],\n * stream: false\n * })\n * // text is a string with the full response\n * ```\n *\n * @example Agentic structured output (tools + structured response)\n * ```ts\n * import { z } from 'zod'\n *\n * const result = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Research and summarize the topic' }],\n * tools: [researchTool, analyzeTool],\n * outputSchema: z.object({\n * summary: z.string(),\n * keyPoints: z.array(z.string())\n * })\n * })\n * // result is { summary: string, keyPoints: string[] }\n * ```\n */\nexport function chat<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined = undefined,\n TStream extends boolean = true,\n>(\n options: TextActivityOptions<TAdapter, TSchema, TStream>,\n): TextActivityResult<TSchema, TStream> {\n const { outputSchema, stream } = options\n\n // If outputSchema is provided, run agentic structured output\n if (outputSchema) {\n return runAgenticStructuredOutput(\n options as unknown as TextActivityOptions<\n AnyTextAdapter,\n SchemaInput,\n boolean\n >,\n ) as TextActivityResult<TSchema, TStream>\n }\n\n // If stream is explicitly false, run non-streaming text\n if (stream === false) {\n return runNonStreamingText(\n options as unknown as TextActivityOptions<\n AnyTextAdapter,\n undefined,\n false\n >,\n ) as TextActivityResult<TSchema, TStream>\n }\n\n // Otherwise, run streaming text (default)\n return runStreamingText(\n options as unknown as TextActivityOptions<AnyTextAdapter, undefined, true>,\n ) as TextActivityResult<TSchema, TStream>\n}\n\n/**\n * Run streaming text (agentic or one-shot depending on tools)\n */\nasync function* runStreamingText(\n options: TextActivityOptions<AnyTextAdapter, undefined, true>,\n): AsyncIterable<StreamChunk> {\n const { adapter, middleware, context, debug, ...textOptions } = options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, any>,\n Record<string, any>\n >,\n middleware,\n context,\n },\n logger,\n )\n\n for await (const chunk of engine.run()) {\n yield chunk\n }\n}\n\n/**\n * Run non-streaming text - collects all content and returns as a string.\n * Runs the full agentic loop (if tools are provided) but returns collected text.\n */\nfunction runNonStreamingText(\n options: TextActivityOptions<AnyTextAdapter, undefined, false>,\n): Promise<string> {\n // Run the streaming text and collect all text using streamToText\n const stream = runStreamingText(\n options as unknown as TextActivityOptions<AnyTextAdapter, undefined, true>,\n )\n\n return streamToText(stream)\n}\n\n/**\n * Run agentic structured output:\n * 1. Execute the full agentic loop (with tools)\n * 2. Once complete, call adapter.structuredOutput with the conversation context\n * 3. Validate and return the structured result\n */\nasync function runAgenticStructuredOutput<TSchema extends SchemaInput>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, boolean>,\n): Promise<InferSchemaType<TSchema>> {\n const { adapter, outputSchema, middleware, context, debug, ...textOptions } =\n options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n if (!outputSchema) {\n throw new Error('outputSchema is required for structured output')\n }\n\n // Create the engine and run the agentic loop\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n middleware,\n context,\n },\n logger,\n )\n\n // Consume the stream to run the agentic loop\n for await (const _chunk of engine.run()) {\n // Just consume the stream to execute the agentic loop\n }\n\n // Get the final messages from the engine (includes tool results)\n const finalMessages = engine.getMessages()\n\n // Build text options for structured output, excluding tools since\n // the agentic loop is complete and we only need the final response\n const {\n tools: _tools,\n agentLoopStrategy: _als,\n ...structuredTextOptions\n } = textOptions\n\n // Convert the schema to JSON Schema before passing to the adapter\n const jsonSchema = convertSchemaToJsonSchema(outputSchema)\n if (!jsonSchema) {\n throw new Error('Failed to convert output schema to JSON Schema')\n }\n\n const providerName =\n (adapter as { provider?: string }).provider ?? adapter.name\n logger.request(\n `activity=chat-structured provider=${providerName} model=${model} messages=${finalMessages.length}`,\n {\n provider: providerName,\n model,\n messageCount: finalMessages.length,\n },\n )\n\n // Call the adapter's structured output method with the conversation context\n // The adapter receives JSON Schema and can apply vendor-specific patches\n const result = await adapter.structuredOutput({\n chatOptions: {\n ...structuredTextOptions,\n model,\n messages: finalMessages,\n logger,\n },\n outputSchema: jsonSchema,\n })\n\n // Validate the result against the schema if it's a Standard Schema\n if (isStandardSchema(outputSchema)) {\n return parseWithStandardSchema<InferSchemaType<TSchema>>(\n outputSchema,\n result.data,\n )\n }\n\n // For plain JSON Schema, return the data as-is\n return result.data as InferSchemaType<TSchema>\n}\n\n// Re-export adapter types\nexport type {\n TextAdapter,\n TextAdapterConfig,\n StructuredOutputOptions,\n StructuredOutputResult,\n} from './adapter'\nexport { BaseTextAdapter } from './adapter'\n"],"names":["maxIterationsStrategy","transformedConfig"],"mappings":";;;;;;;;;;AA+DO,MAAM,OAAO;AAqJb,SAAS,kBAKd,SACiD;AACjD,SAAO;AACT;AAuCA,MAAM,WAGJ;AAAA,EAiDA,YACE,QACA,QACA;AArCF,SAAQ,iBAAiB;AACzB,SAAQ,mBAAkC;AAC1C,SAAQ,kBAAkB;AAC1B,SAAQ,kBAAkB;AAC1B,SAAQ,mBAAkC;AAC1C,SAAQ,qBAAqB;AAC7B,SAAQ,sBACN,CAAA;AACF,SAAQ,yBAAyB;AACjC,SAAQ,2BAA2B;AAGnC,SAAQ,gBAAyC;AACjD,SAAQ,mBAAmB;AAC3B,SAAQ,YAA6B;AACrC,SAAQ,aAAyB;AAYjC,SAAiB,mBAA4C,CAAA;AAG7D,SAAQ,qBAAqB;AAQ3B,SAAK,SAAS;AACd,SAAK,UAAU,OAAO;AACtB,SAAK,SAAS,OAAO;AACrB,SAAK,gBAAgB,OAAO,OAAO,iBAAiB,CAAA;AACpD,SAAK,eACH,OAAO,OAAO,qBAAqBA,cAAsB,CAAC;AAC5D,SAAK,sBAAsB,OAAO,OAAO,SAAS;AAIlD,UAAM,EAAE,WAAW,kBAAA,IACjB,KAAK;AAAA,MACH,OAAO,OAAO;AAAA,IAAA;AAElB,SAAK,mBAAmB;AACxB,SAAK,2BAA2B;AAIhC,SAAK,WAAW;AAAA,MACd,OAAO,OAAO;AAAA,IAAA;AAIhB,SAAK,kBAAkB,IAAI;AAAA,MACzB,OAAO,OAAO,SAAS,CAAA;AAAA,MACvB,KAAK;AAAA,IAAA;AAEP,SAAK,QAAQ,KAAK,gBAAgB,eAAA;AAClC,SAAK,kBAAkB,IAAI,gBAAgB,KAAK,KAAK;AACrD,SAAK,YAAY,KAAK,SAAS,MAAM;AACrC,SAAK,WAAW,KAAK,SAAS,QAAQ;AACtC,SAAK,mBAAmB,OAAO,OAAO,kBAClC,EAAE,QAAQ,OAAO,OAAO,gBAAgB,OAAA,IACxC;AACJ,SAAK,kBAAkB,OAAO,OAAO,iBAAiB;AACtD,SAAK,WAAW,OAAO,OAAO,YAAY,KAAK,SAAS,QAAQ;AAChE,SAAK,gBAAgB,OAAO,OAAO;AAMnC,UAAM,gBAAgB;AAAA,MACpB,mBAAA;AAAA,MACA,GAAI,OAAO,cAAc,CAAA;AAAA,MACzB,sBAAA;AAAA,IAAsB;AAExB,SAAK,mBAAmB,IAAI,iBAAiB,eAAe,MAAM;AAClE,SAAK,4BAA4B,IAAI,gBAAA;AACrC,SAAK,gBAAgB;AAAA,MACnB,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,gBAAgB,OAAO,OAAO;AAAA,MAC9B,OAAO;AAAA,MACP,WAAW;AAAA,MACX,YAAY;AAAA,MACZ,QAAQ,KAAK;AAAA,MACb,OAAO,CAAC,WAAoB;AAC1B,aAAK,cAAc;AACnB,aAAK,2BAA2B,MAAM,MAAM;AAAA,MAC9C;AAAA,MACA,SAAS,OAAO;AAAA,MAChB,OAAO,CAAC,YAA8B;AACpC,aAAK,iBAAiB,KAAK,OAAO;AAAA,MACpC;AAAA;AAAA,MAEA,UAAU,OAAO,QAAQ;AAAA,MACzB,OAAO,OAAO,OAAO;AAAA,MACrB,QAAQ;AAAA,MACR,WAAW;AAAA;AAAA,MAEX,eAAe,KAAK;AAAA,MACpB,WAAW;AAAA,MACX,SAAS;AAAA,MACT,cAAc,OAAO,OAAO;AAAA;AAAA,MAE5B,cAAc,KAAK;AAAA,MACnB,UAAU,KAAK,MAAM,SAAS;AAAA;AAAA,MAE9B,kBAAkB;AAAA,MAClB,oBAAoB;AAAA;AAAA,MAEpB,UAAU,KAAK;AAAA,MACf,UAAU,CAAC,WAAmB,KAAK,SAAS,MAAM;AAAA,IAAA;AAAA,EAEtD;AAAA;AAAA,EAGA,wBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,cAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,MAAmC;AACxC,SAAK,UAAA;AACL,SAAK,OAAO,UAAU,eAAe;AAAA,MACnC,gBAAgB,KAAK,cAAc;AAAA,IAAA,CACpC;AAED,QAAI;AAEF,WAAK,cAAc,QAAQ;AAC3B,YAAM,gBAAgB,KAAK,sBAAA;AAC3B,YAAM,oBAAoB,MAAM,KAAK,iBAAiB;AAAA,QACpD,KAAK;AAAA,QACL;AAAA,MAAA;AAEF,WAAK,sBAAsB,iBAAiB;AAG5C,YAAM,KAAK,iBAAiB,WAAW,KAAK,aAAa;AAEzD,YAAM,eAAe,OAAO,KAAK,yBAAA;AACjC,UAAI,iBAAiB,QAAQ;AAC3B;AAAA,MACF;AAEA,SAAG;AACD,YAAI,KAAK,oBAAoB,KAAK,YAAA,GAAe;AAC/C;AAAA,QACF;AAEA,aAAK,OAAO,UAAU,aAAa,KAAK,cAAc,SAAS,IAAI;AAAA,UACjE,WAAW,KAAK,cAAc;AAAA,QAAA,CAC/B;AAED,cAAM,KAAK,WAAA;AAEX,YAAI,KAAK,eAAe,eAAe;AAErC,eAAK,cAAc,QAAQ;AAC3B,eAAK,cAAc,YAAY,KAAK;AACpC,gBAAM,aAAa,KAAK,sBAAA;AACxB,gBAAMC,qBAAoB,MAAM,KAAK,iBAAiB;AAAA,YACpD,KAAK;AAAA,YACL;AAAA,UAAA;AAEF,eAAK,sBAAsBA,kBAAiB;AAE5C,iBAAO,KAAK,oBAAA;AAAA,QACd,OAAO;AACL,iBAAO,KAAK,iBAAA;AAAA,QACd;AAEA,aAAK,SAAA;AAAA,MACP,SAAS,KAAK,eAAA;AAEd,WAAK,OAAO,UAAU,gBAAgB;AAAA,QACpC,cAAc,KAAK;AAAA,MAAA,CACpB;AAGD,UAAI,CAAC,KAAK,sBAAsB,KAAK,cAAc,QAAQ;AACzD,aAAK,qBAAqB;AAC1B,cAAM,KAAK,iBAAiB,YAAY,KAAK,eAAe;AAAA,UAC1D,cAAc,KAAK;AAAA,UACnB,UAAU,KAAK,IAAA,IAAQ,KAAK;AAAA,UAC5B,SAAS,KAAK;AAAA,UACd,OAAO,KAAK,eAAe;AAAA,QAAA,CAC5B;AAAA,MACH;AAAA,IACF,SAAS,OAAgB;AACvB,UAAI,CAAC,KAAK,oBAAoB;AAC5B,aAAK,qBAAqB;AAC1B,YAAI,iBAAiB,sBAAsB;AAEzC,eAAK,cAAc,MAAM;AACzB,gBAAM,KAAK,iBAAiB,WAAW,KAAK,eAAe;AAAA,YACzD,QAAQ,MAAM;AAAA,YACd,UAAU,KAAK,IAAA,IAAQ,KAAK;AAAA,UAAA,CAC7B;AAAA,QACH,OAAO;AAEL,eAAK,OAAO,OAAO,mBAAmB;AAAA,YACpC;AAAA,YACA,gBAAgB,KAAK,cAAc;AAAA,UAAA,CACpC;AACD,gBAAM,KAAK,iBAAiB,WAAW,KAAK,eAAe;AAAA,YACzD;AAAA,YACA,UAAU,KAAK,IAAA,IAAQ,KAAK;AAAA,UAAA,CAC7B;AAAA,QACH;AAAA,MACF;AAEA,UAAI,EAAE,iBAAiB,uBAAuB;AAC5C,cAAM;AAAA,MACR;AAAA,IACF,UAAA;AAEE,UAAI,CAAC,KAAK,sBAAsB,KAAK,eAAe;AAClD,aAAK,qBAAqB;AAC1B,cAAM,KAAK,iBAAiB,WAAW,KAAK,eAAe;AAAA,UACzD,QAAQ,KAAK;AAAA,UACb,UAAU,KAAK,IAAA,IAAQ,KAAK;AAAA,QAAA,CAC7B;AAAA,MACH;AAGA,UAAI,KAAK,iBAAiB,SAAS,GAAG;AACpC,cAAM,QAAQ,WAAW,KAAK,gBAAgB;AAAA,MAChD;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,YAAkB;AACxB,SAAK,kBAAkB,KAAK,IAAA;AAC5B,UAAM,EAAE,OAAO,aAAa,MAAM,WAAW,SAAA,IAAa,KAAK;AAG/D,UAAM,UAAmC,CAAA;AACzC,QAAI,gBAAgB,OAAW,SAAQ,cAAc;AACrD,QAAI,SAAS,OAAW,SAAQ,OAAO;AACvC,QAAI,cAAc,OAAW,SAAQ,YAAY;AACjD,QAAI,aAAa,OAAW,SAAQ,WAAW;AAE/C,SAAK,eAAe,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,UAAU;AAChE,SAAK,iBAAiB,OAAO,IAAI,CAAC,MAAM,EAAE,IAAI;AAG9C,SAAK,cAAc,UAAU,KAAK;AAClC,SAAK,cAAc,YAAY,KAAK;AAAA,EACtC;AAAA,EAEA,MAAc,aAA4B;AACxC,QAAI,KAAK,eAAe,eAAe;AACrC,YAAM,KAAK,eAAA;AAAA,IACb;AAAA,EACF;AAAA,EAEQ,WAAiB;AACvB,QAAI,KAAK,eAAe,eAAe;AACrC,WAAK,aAAa;AAClB;AAAA,IACF;AAEA,SAAK,aAAa;AAClB,SAAK;AAAA,EACP;AAAA,EAEA,MAAc,iBAAgC;AAC5C,SAAK,mBAAmB,KAAK,SAAS,KAAK;AAC3C,SAAK,qBAAqB;AAC1B,SAAK,sBAAsB,CAAA;AAC3B,SAAK,yBAAyB;AAC9B,SAAK,2BAA2B;AAChC,SAAK,gBAAgB;AAGrB,SAAK,cAAc,mBAAmB,KAAK;AAC3C,SAAK,cAAc,qBAAqB;AAGxC,UAAM,KAAK,iBAAiB,eAAe,KAAK,eAAe;AAAA,MAC7D,WAAW,KAAK;AAAA,MAChB,WAAW,KAAK;AAAA,IAAA,CACjB;AAAA,EACH;AAAA,EAEA,OAAe,sBAAmD;AAChE,UAAM,EAAE,aAAa,MAAM,WAAW,UAAU,aAAA,IAAiB,KAAK;AACtE,UAAM,QAAQ,KAAK;AAGnB,UAAM,uBAAuB,MAAM,IAAI,CAAC,UAAU;AAAA,MAChD,GAAG;AAAA,MACH,aAAa,KAAK,cACd,0BAA0B,KAAK,WAAW,IAC1C;AAAA,MACJ,cAAc,KAAK,eACf,0BAA0B,KAAK,YAAY,IAC3C;AAAA,IAAA,EACJ;AAEF,SAAK,cAAc,QAAQ;AAE3B,UAAM,eACH,KAAK,QAAkC,YAAY,KAAK,QAAQ;AACnE,SAAK,OAAO;AAAA,MACV,0BAA0B,YAAY,UAAU,KAAK,OAAO,KAAK,aAAa,KAAK,SAAS,MAAM,UAAU,KAAK,MAAM,MAAM;AAAA,MAC7H;AAAA,QACE,UAAU;AAAA,QACV,OAAO,KAAK,OAAO;AAAA,QACnB,cAAc,KAAK,SAAS;AAAA,QAC5B,WAAW,KAAK,MAAM;AAAA,MAAA;AAAA,IACxB;AAGF,qBAAiB,SAAS,KAAK,QAAQ,WAAW;AAAA,MAChD,OAAO,KAAK,OAAO;AAAA,MACnB,UAAU,KAAK;AAAA,MACf,OAAO;AAAA,MACP;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,SAAS,KAAK;AAAA,MACd;AAAA,MACA,eAAe,KAAK;AAAA,MACpB,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,IAAA,CACb,GAAG;AACF,UAAI,KAAK,eAAe;AACtB;AAAA,MACF;AAEA,WAAK;AAIL,WAAK,kBAAkB,KAAK;AAG5B,YAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,QAC/C,KAAK;AAAA,QACL;AAAA,MAAA;AAEF,iBAAW,eAAe,cAAc;AACtC,aAAK,OAAO,OAAO,QAAQ,YAAY,IAAI,IAAI,EAAE,OAAO,aAAa;AACrE,cAAM;AACN,aAAK,cAAc;AAAA,MACrB;AAGA,UAAI,MAAM,SAAS,kBAAkB,MAAM,OAAO;AAChD,cAAM,KAAK,iBAAiB,WAAW,KAAK,eAAe,MAAM,KAAK;AAAA,MACxE;AAEA,UAAI,KAAK,kBAAkB;AACzB;AAAA,MACF;AAAA,IACF;AAAA,EACF;AAAA,EAEQ,kBAAkB,OAA0B;AAClD,YAAQ,MAAM,MAAA;AAAA;AAAA,MAEZ,KAAK;AACH,aAAK,8BAA8B,KAAK;AACxC;AAAA,MACF,KAAK;AACH,aAAK,yBAAyB,KAAK;AACnC;AAAA,MACF,KAAK;AACH,aAAK,wBAAwB,KAAK;AAClC;AAAA,MACF,KAAK;AACH,aAAK,uBAAuB,KAAK;AACjC;AAAA,MACF,KAAK;AACH,aAAK,uBAAuB,KAAK;AACjC;AAAA,MACF,KAAK;AACH,aAAK,oBAAoB,KAAK;AAC9B;AAAA,MACF,KAAK;AACH,aAAK,uBAAA;AACL;AAAA,MACF,KAAK;AACH,aAAK,wBAAwB,KAAK;AAClC;AAAA,IAkBA;AAAA,EAEN;AAAA;AAAA;AAAA;AAAA,EAMQ,8BAA8B,OAAsC;AAC1E,QAAI,MAAM,SAAS;AACjB,WAAK,qBAAqB,MAAM;AAAA,IAClC,OAAO;AACL,WAAK,sBAAsB,MAAM;AAAA,IACnC;AACA,SAAK,cAAc,qBAAqB,KAAK;AAAA,EAC/C;AAAA,EAEQ,yBAAyB,OAAiC;AAChE,SAAK,gBAAgB,sBAAsB,KAAK;AAAA,EAClD;AAAA,EAEQ,wBAAwB,OAAgC;AAC9D,SAAK,gBAAgB,qBAAqB,KAAK;AAAA,EACjD;AAAA,EAEQ,uBAAuB,OAA+B;AAC5D,SAAK,gBAAgB,iBAAiB,KAAK;AAAA,EAC7C;AAAA,EAEQ,uBAAuB,OAA+B;AAC5D,SAAK,gBAAgB;AACrB,SAAK,mBAAmB,MAAM,gBAAgB;AAAA,EAChD;AAAA,EAEQ,oBACN,QACM;AACN,SAAK,mBAAmB;AAAA,EAC1B;AAAA,EAEQ,8BAAoC;AAC1C,QAAI,KAAK,wBAAwB;AAC/B,WAAK,oBAAoB,KAAK;AAAA,QAC5B,SAAS,KAAK;AAAA,QACd,GAAI,KAAK,4BAA4B;AAAA,UACnC,WAAW,KAAK;AAAA,QAAA;AAAA,MAClB,CACD;AACD,WAAK,yBAAyB;AAC9B,WAAK,2BAA2B;AAAA,IAClC;AAAA,EACF;AAAA,EAEQ,yBAA+B;AACrC,SAAK,4BAAA;AAAA,EACP;AAAA,EAEQ,wBACN,OACM;AACN,QAAI,MAAM,OAAO;AACf,WAAK,0BAA0B,MAAM;AAAA,IACvC;AACA,QAAI,MAAM,WAAW;AACnB,WAAK,2BAA2B,MAAM;AAAA,IACxC;AAAA,EACF;AAAA,EAEA,OAAe,2BAIb;AACA,UAAM,mBAAmB,KAAK,gCAAA;AAC9B,QAAI,iBAAiB,WAAW,GAAG;AACjC,aAAO;AAAA,IACT;AAEA,UAAM,cAAc,KAAK,6BAAA;AAGzB,UAAM,0BAA6C,CAAA;AACnD,UAAM,yBAAyB,iBAAiB,OAAO,CAAC,OAAO;AAC7D,UAAI,KAAK,gBAAgB,uBAAuB,GAAG,SAAS,IAAI,GAAG;AACjE,gCAAwB,KAAK;AAAA,UAC3B,YAAY,GAAG;AAAA,UACf,UAAU,GAAG,SAAS;AAAA,UACtB,QAAQ;AAAA,YACN,OAAO,KAAK,gBAAgB;AAAA,cAC1B,GAAG,SAAS;AAAA,YAAA;AAAA,UACd;AAAA,UAEF,OAAO;AAAA,QAAA,CACR;AACD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,CAAC;AAED,QAAI,wBAAwB,SAAS,GAAG;AACtC,iBAAW,SAAS,KAAK;AAAA,QACvB;AAAA,QACA;AAAA,MAAA,GACC;AACD,eAAO,KAAK,sBAAsB,KAAK;AAAA,MACzC;AAAA,IACF;AAEA,QAAI,uBAAuB,WAAW,GAAG;AACvC,aAAO;AAAA,IACT;AAEA,UAAM,EAAE,WAAW,sBAAsB,KAAK,mBAAA;AAE9C,UAAM,YAAY;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,CAAC,WAAW,SAAS,KAAK,uBAAuB,WAAW,IAAI;AAAA,MAChE;AAAA,QACE,kBAAkB,OAAO,UAAU,MAAM,SAAS;AAChD,eAAK,OAAO,MAAM,qBAAqB,SAAS,SAAS,IAAI,IAAI;AAAA,YAC/D,MAAM,SAAS,SAAS;AAAA,YACxB;AAAA,UAAA,CACD;AACD,gBAAM,UAAU;AAAA,YACd;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU,SAAS,SAAS;AAAA,YAC5B,YAAY,SAAS;AAAA,UAAA;AAEvB,iBAAO,KAAK,iBAAiB;AAAA,YAC3B,KAAK;AAAA,YACL;AAAA,UAAA;AAAA,QAEJ;AAAA,QACA,iBAAiB,OAAO,SAAS;AAC/B,eAAK,OAAO,MAAM,oBAAoB,KAAK,QAAQ,IAAI;AAAA,YACrD,MAAM,KAAK;AAAA,YACX,QAAQ,KAAK;AAAA,UAAA,CACd;AACD,gBAAM,KAAK,iBAAiB;AAAA,YAC1B,KAAK;AAAA,YACL;AAAA,UAAA;AAAA,QAEJ;AAAA,MAAA;AAAA,IACF;AAIF,UAAM,kBAAkB,OAAO,KAAK,uBAAuB,SAAS;AAGpE,QAAI,KAAK,uBAAuB;AAC9B,WAAK,aAAa,MAAM;AACxB,aAAO;AAAA,IACT;AAGA,UAAM,KAAK,iBAAiB,uBAAuB,KAAK,eAAe;AAAA,MACrE,WAAW;AAAA,MACX,SAAS,gBAAgB;AAAA,MACzB,eAAe,gBAAgB;AAAA,MAC/B,sBAAsB,gBAAgB;AAAA,IAAA,CACvC;AAID,UAAM,8BAAc,IAAA;AACpB,eAAW,MAAM,kBAAkB;AACjC,cAAQ,IAAI,GAAG,IAAI,GAAG,SAAS,SAAS;AAAA,IAC1C;AAEA,QACE,gBAAgB,cAAc,SAAS,KACvC,gBAAgB,qBAAqB,SAAS,GAC9C;AACA,UAAI,gBAAgB,QAAQ,SAAS,GAAG;AACtC,mBAAW,SAAS,KAAK;AAAA,UACvB,gBAAgB;AAAA,UAChB;AAAA,UACA;AAAA,QAAA,GACC;AACD,iBAAO,KAAK,sBAAsB,KAAK;AAAA,QACzC;AAAA,MACF;AAEA,iBAAW,SAAS,KAAK;AAAA,QACvB,gBAAgB;AAAA,QAChB;AAAA,MAAA,GACC;AACD,eAAO,KAAK,sBAAsB,KAAK;AAAA,MACzC;AAEA,iBAAW,SAAS,KAAK;AAAA,QACvB,gBAAgB;AAAA,QAChB;AAAA,MAAA,GACC;AACD,eAAO,KAAK,sBAAsB,KAAK;AAAA,MACzC;AAEA,WAAK,aAAa,MAAM;AACxB,aAAO;AAAA,IACT;AAEA,UAAM,mBAAmB,KAAK;AAAA,MAC5B,gBAAgB;AAAA,MAChB;AAAA,MACA;AAAA,IAAA;AAGF,eAAW,SAAS,kBAAkB;AACpC,aAAO,KAAK,sBAAsB,KAAK;AAAA,IACzC;AAEA,WAAO;AAAA,EACT;AAAA,EAEA,OAAe,mBAA4D;AACzE,QAAI,CAAC,KAAK,0BAA0B;AAClC,WAAK,aAAa,MAAM;AACxB;AAAA,IACF;AAEA,UAAM,YAAY,KAAK,gBAAgB,aAAA;AACvC,UAAM,cAAc,KAAK;AAEzB,QAAI,CAAC,eAAe,UAAU,WAAW,GAAG;AAC1C,WAAK,aAAa,MAAM;AACxB;AAAA,IACF;AAEA,SAAK,4BAA4B,SAAS;AAG1C,UAAM,0BAA6C,CAAA;AACnD,UAAM,sBAAsB,UAAU,OAAO,CAAC,OAAO;AACnD,UAAI,KAAK,gBAAgB,uBAAuB,GAAG,SAAS,IAAI,GAAG;AACjE,gCAAwB,KAAK;AAAA,UAC3B,YAAY,GAAG;AAAA,UACf,UAAU,GAAG,SAAS;AAAA,UACtB,QAAQ;AAAA,YACN,OAAO,KAAK,gBAAgB;AAAA,cAC1B,GAAG,SAAS;AAAA,YAAA;AAAA,UACd;AAAA,UAEF,OAAO;AAAA,QAAA,CACR;AACD,eAAO;AAAA,MACT;AACA,aAAO;AAAA,IACT,CAAC;AAED,QAAI,wBAAwB,SAAS,GAAG;AACtC,YAAM,YAAY,KAAK;AACvB,iBAAW,SAAS,KAAK;AAAA,QACvB;AAAA,QACA;AAAA,MAAA,GACC;AACD,eAAO,KAAK,sBAAsB,KAAK;AAAA,MACzC;AAAA,IACF;AAEA,QAAI,oBAAoB,WAAW,GAAG;AAEpC,WAAK,gBAAgB,MAAA;AACrB,WAAK,aAAa,UAAU;AAC5B;AAAA,IACF;AACA,SAAK,cAAc,QAAQ;AAE3B,UAAM,EAAE,WAAW,sBAAsB,KAAK,mBAAA;AAE9C,UAAM,YAAY;AAAA,MAChB;AAAA,MACA,KAAK;AAAA,MACL;AAAA,MACA;AAAA,MACA,CAAC,WAAW,SAAS,KAAK,uBAAuB,WAAW,IAAI;AAAA,MAChE;AAAA,QACE,kBAAkB,OAAO,UAAU,MAAM,SAAS;AAChD,eAAK,OAAO,MAAM,qBAAqB,SAAS,SAAS,IAAI,IAAI;AAAA,YAC/D,MAAM,SAAS,SAAS;AAAA,YACxB;AAAA,UAAA,CACD;AACD,gBAAM,UAAU;AAAA,YACd;AAAA,YACA;AAAA,YACA;AAAA,YACA,UAAU,SAAS,SAAS;AAAA,YAC5B,YAAY,SAAS;AAAA,UAAA;AAEvB,iBAAO,KAAK,iBAAiB;AAAA,YAC3B,KAAK;AAAA,YACL;AAAA,UAAA;AAAA,QAEJ;AAAA,QACA,iBAAiB,OAAO,SAAS;AAC/B,eAAK,OAAO,MAAM,oBAAoB,KAAK,QAAQ,IAAI;AAAA,YACrD,MAAM,KAAK;AAAA,YACX,QAAQ,KAAK;AAAA,UAAA,CACd;AACD,gBAAM,KAAK,iBAAiB;AAAA,YAC1B,KAAK;AAAA,YACL;AAAA,UAAA;AAAA,QAEJ;AAAA,MAAA;AAAA,IACF;AAIF,UAAM,kBAAkB,OAAO,KAAK,uBAAuB,SAAS;AAEpE,SAAK,cAAc,QAAQ;AAG3B,QAAI,KAAK,uBAAuB;AAC9B,WAAK,aAAa,MAAM;AACxB;AAAA,IACF;AAGA,UAAM,KAAK,iBAAiB,uBAAuB,KAAK,eAAe;AAAA,MACrE;AAAA,MACA,SAAS,gBAAgB;AAAA,MACzB,eAAe,gBAAgB;AAAA,MAC/B,sBAAsB,gBAAgB;AAAA,IAAA,CACvC;AAED,QACE,gBAAgB,cAAc,SAAS,KACvC,gBAAgB,qBAAqB,SAAS,GAC9C;AACA,UAAI,gBAAgB,QAAQ,SAAS,GAAG;AACtC,mBAAW,SAAS,KAAK;AAAA,UACvB,gBAAgB;AAAA,UAChB;AAAA,QAAA,GACC;AACD,iBAAO,KAAK,sBAAsB,KAAK;AAAA,QACzC;AAAA,MACF;AAEA,iBAAW,SAAS,KAAK;AAAA,QACvB,gBAAgB;AAAA,QAChB;AAAA,MAAA,GACC;AACD,eAAO,KAAK,sBAAsB,KAAK;AAAA,MACzC;AAEA,iBAAW,SAAS,KAAK;AAAA,QACvB,gBAAgB;AAAA,QAChB;AAAA,MAAA,GACC;AACD,eAAO,KAAK,sBAAsB,KAAK;AAAA,MACzC;AAEA,WAAK,aAAa,MAAM;AACxB;AAAA,IACF;AAEA,UAAM,mBAAmB,KAAK;AAAA,MAC5B,gBAAgB;AAAA,MAChB;AAAA,IAAA;AAGF,eAAW,SAAS,kBAAkB;AACpC,aAAO,KAAK,sBAAsB,KAAK;AAAA,IACzC;AAGA,QAAI,KAAK,gBAAgB,2BAA2B;AAClD,WAAK,QAAQ,KAAK,gBAAgB,eAAA;AAClC,WAAK,kBAAkB,IAAI,gBAAgB,KAAK,KAAK;AACrD,WAAK,aAAa,UAAU;AAC5B;AAAA,IACF;AAEA,SAAK,gBAAgB,MAAA;AAErB,SAAK,aAAa,UAAU;AAAA,EAC9B;AAAA,EAEQ,yBAAkC;AACxC,WACE,KAAK,eAAe,iBAAiB,gBACrC,KAAK,MAAM,SAAS,KACpB,KAAK,gBAAgB,aAAA;AAAA,EAEzB;AAAA,EAEQ,4BAA4B,WAAkC;AACpE,SAAK,4BAAA;AAEL,SAAK,WAAW;AAAA,MACd,GAAG,KAAK;AAAA,MACR;AAAA,QACE,MAAM;AAAA,QACN,SAAS,KAAK,sBAAsB;AAAA,QACpC;AAAA,QACA,GAAI,KAAK,oBAAoB,SAAS,KAAK;AAAA,UACzC,UAAU,KAAK;AAAA,QAAA;AAAA,MACjB;AAAA,IACF;AAAA,EAEJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOQ,uCACN,kBAIA;AACA,UAAM,gCAAgB,IAAA;AACtB,UAAM,wCAAwB,IAAA;AAE9B,eAAW,WAAW,kBAAkB;AAEtC,UAAI,QAAQ,SAAS,eAAe,QAAQ,OAAO;AACjD,mBAAW,QAAQ,QAAQ,OAAO;AAChC,cAAI,KAAK,SAAS,aAAa;AAE7B,gBAAI,KAAK,WAAW,UAAa,CAAC,KAAK,UAAU;AAC/C,gCAAkB,IAAI,KAAK,IAAI,KAAK,MAAM;AAAA,YAC5C;AAEA,gBACE,KAAK,UAAU,MACf,KAAK,UAAU,aAAa,UAC5B,KAAK,UAAU,sBACf;AACA,wBAAU,IAAI,KAAK,SAAS,IAAI,KAAK,SAAS,QAAQ;AAAA,YACxD;AAAA,UACF;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO,EAAE,WAAW,kBAAA;AAAA,EACtB;AAAA,EAEQ,qBAGN;AAEA,UAAM,YAAY,IAAI,IAAI,KAAK,gBAAgB;AAC/C,UAAM,oBAAoB,IAAI,IAAI,KAAK,wBAAwB;AAG/D,eAAW,WAAW,KAAK,UAAU;AAGnC,UAAI,QAAQ,SAAS,UAAU,QAAQ,YAAY;AAEjD,YAAI;AACJ,YAAI;AACF,mBAAS,KAAK,MAAM,QAAQ,OAAiB;AAAA,QAC/C,QAAQ;AACN,mBAAS,QAAQ;AAAA,QACnB;AAMA,YACE,UACA,OAAO,WAAW,YACjB,OAAe,qBAAqB,MACrC;AACA;AAAA,QACF;AACA,0BAAkB,IAAI,QAAQ,YAAY,MAAM;AAAA,MAClD;AAAA,IACF;AAEA,WAAO,EAAE,WAAW,kBAAA;AAAA,EACtB;AAAA,EAEQ,oBACN,WACA,aACoB;AACpB,UAAM,SAA6B,CAAA;AAEnC,eAAW,YAAY,WAAW;AAChC,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,KAAK,IAAA;AAAA,QAChB,OAAO,YAAY;AAAA,QACnB,MAAM;AAAA,QACN,OAAO;AAAA,UACL,YAAY,SAAS;AAAA,UACrB,UAAU,SAAS;AAAA,UACnB,OAAO,SAAS;AAAA,UAChB,UAAU;AAAA,YACR,IAAI,SAAS;AAAA,YACb,eAAe;AAAA,UAAA;AAAA,QACjB;AAAA,MACF,CACc;AAAA,IAClB;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,sBACN,gBACA,aACoB;AACpB,UAAM,SAA6B,CAAA;AAEnC,eAAW,cAAc,gBAAgB;AACvC,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,KAAK,IAAA;AAAA,QAChB,OAAO,YAAY;AAAA,QACnB,MAAM;AAAA,QACN,OAAO;AAAA,UACL,YAAY,WAAW;AAAA,UACvB,UAAU,WAAW;AAAA,UACrB,OAAO,WAAW;AAAA,QAAA;AAAA,MACpB,CACc;AAAA,IAClB;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,sBACN,SACA,aACA,SACoB;AACpB,UAAM,SAA6B,CAAA;AAEnC,eAAW,UAAU,SAAS;AAC5B,YAAM,UAAU,KAAK,UAAU,OAAO,MAAM;AAI5C,UAAI,SAAS;AACX,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,WAAW,KAAK,IAAA;AAAA,UAChB,OAAO,YAAY;AAAA,UACnB,YAAY,OAAO;AAAA,UACnB,cAAc,OAAO;AAAA,UACrB,UAAU,OAAO;AAAA,QAAA,CACH;AAEhB,cAAM,OAAO,QAAQ,IAAI,OAAO,UAAU,KAAK;AAC/C,eAAO,KAAK;AAAA,UACV,MAAM;AAAA,UACN,WAAW,KAAK,IAAA;AAAA,UAChB,OAAO,YAAY;AAAA,UACnB,YAAY,OAAO;AAAA,UACnB,OAAO;AAAA,UACP;AAAA,QAAA,CACc;AAAA,MAClB;AAEA,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,KAAK,IAAA;AAAA,QAChB,OAAO,YAAY;AAAA,QACnB,YAAY,OAAO;AAAA,QACnB,cAAc,OAAO;AAAA,QACrB,UAAU,OAAO;AAAA,QACjB,QAAQ;AAAA,MAAA,CACM;AAGhB,aAAO,KAAK;AAAA,QACV,MAAM;AAAA,QACN,WAAW,KAAK,IAAA;AAAA,QAChB,OAAO,YAAY;AAAA,QACnB,WAAW,KAAK,SAAS,aAAa;AAAA,QACtC,YAAY,OAAO;AAAA,QACnB;AAAA,QACA,MAAM;AAAA,MAAA,CACQ;AAQhB,YAAM,iBAAiB,KAAK,SAAS,UAAU,CAAC,MAAM;AACpD,YAAI,EAAE,SAAS,UAAU,EAAE,eAAe,OAAO,YAAY;AAC3D,iBAAO;AAAA,QACT;AACA,YAAI,OAAO,EAAE,YAAY,SAAU,QAAO;AAC1C,YAAI;AACF,iBAAO,KAAK,MAAM,EAAE,OAAO,GAAG,qBAAqB;AAAA,QACrD,QAAQ;AACN,iBAAO;AAAA,QACT;AAAA,MACF,CAAC;AAED,YAAM,iBAA+B;AAAA,QACnC,MAAM;AAAA,QACN;AAAA,QACA,YAAY,OAAO;AAAA,MAAA;AAGrB,UAAI,kBAAkB,GAAG;AACvB,aAAK,WAAW;AAAA,UACd,GAAG,KAAK,SAAS,MAAM,GAAG,cAAc;AAAA,UACxC;AAAA,UACA,GAAG,KAAK,SAAS,MAAM,iBAAiB,CAAC;AAAA,QAAA;AAAA,MAE7C,OAAO;AACL,aAAK,WAAW,CAAC,GAAG,KAAK,UAAU,cAAc;AAAA,MACnD;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,kCAAmD;AAGzD,UAAM,uCAAuB,IAAA;AAE7B,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI,QAAQ,SAAS,UAAU,QAAQ,YAAY;AAEjD,YAAI,sBAAsB;AAC1B,YAAI,OAAO,QAAQ,YAAY,UAAU;AACvC,cAAI;AACF,kBAAM,SAAS,KAAK,MAAM,QAAQ,OAAO;AACzC,gBAAI,OAAO,qBAAqB,MAAM;AACpC,oCAAsB;AAAA,YACxB;AAAA,UACF,QAAQ;AAAA,UAER;AAAA,QACF;AAGA,YAAI,CAAC,qBAAqB;AACxB,2BAAiB,IAAI,QAAQ,UAAU;AAAA,QACzC;AAAA,MACF;AAAA,IACF;AAEA,UAAM,UAA2B,CAAA;AAEjC,eAAW,WAAW,KAAK,UAAU;AACnC,UAAI,QAAQ,SAAS,eAAe,QAAQ,WAAW;AACrD,mBAAW,YAAY,QAAQ,WAAW;AACxC,cAAI,CAAC,iBAAiB,IAAI,SAAS,EAAE,GAAG;AACtC,oBAAQ,KAAK,QAAQ;AAAA,UACvB;AAAA,QACF;AAAA,MACF;AAAA,IACF;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,+BAAiD;AACvD,WAAO;AAAA,MACL,MAAM;AAAA,MACN,OAAO,KAAK,SAAS,SAAS;AAAA,MAC9B,UAAU,KAAK;AAAA,MACf,OAAO,KAAK,OAAO;AAAA,MACnB,WAAW,KAAK,IAAA;AAAA,MAChB,cAAc;AAAA,IAAA;AAAA,EAElB;AAAA,EAEQ,iBAA0B;AAChC,QAAI,KAAK,eAAe,oBAAoB;AAC1C,aAAO;AAAA,IACT;AAEA,WACE,KAAK,aAAa;AAAA,MAChB,gBAAgB,KAAK;AAAA,MACrB,UAAU,KAAK;AAAA,MACf,cAAc,KAAK;AAAA,IAAA,CACpB,KAAK,KAAK,cAAc;AAAA,EAE7B;AAAA,EAEQ,YAAqB;AAC3B,WAAO,CAAC,CAAC,KAAK,iBAAiB;AAAA,EACjC;AAAA,EAEQ,sBAA+B;AACrC,WAAO,CAAC,CAAC,KAAK,2BAA2B,OAAO;AAAA,EAClD;AAAA,EAEQ,cAAuB;AAC7B,WAAO,KAAK,eAAe,KAAK,oBAAA;AAAA,EAClC;AAAA,EAEQ,wBAA8C;AACpD,WAAO;AAAA,MACL,UAAU,KAAK;AAAA,MACf,eAAe,CAAC,GAAG,KAAK,aAAa;AAAA,MACrC,OAAO,CAAC,GAAG,KAAK,KAAK;AAAA,MACrB,aAAa,KAAK,OAAO;AAAA,MACzB,MAAM,KAAK,OAAO;AAAA,MAClB,WAAW,KAAK,OAAO;AAAA,MACvB,UAAU,KAAK,OAAO;AAAA,MACtB,cAAc,KAAK,OAAO;AAAA,IAAA;AAAA,EAE9B;AAAA,EAEQ,sBAAsB,QAAoC;AAChE,SAAK,WAAW,OAAO;AACvB,SAAK,gBAAgB,OAAO;AAC5B,SAAK,QAAQ,OAAO;AACpB,SAAK,SAAS;AAAA,MACZ,GAAG,KAAK;AAAA,MACR,aAAa,OAAO;AAAA,MACpB,MAAM,OAAO;AAAA,MACb,WAAW,OAAO;AAAA,MAClB,UAAU,OAAO;AAAA,MACjB,cAAc,OAAO;AAAA,IAAA;AAIvB,SAAK,cAAc,WAAW,KAAK;AACnC,SAAK,cAAc,gBAAgB,KAAK;AACxC,SAAK,cAAc,WAAW,KAAK,MAAM,SAAS;AAClD,SAAK,cAAc,YAAY,KAAK,MAAM,IAAI,CAAC,MAAM,EAAE,IAAI;AAC3D,SAAK,cAAc,eAAe,OAAO;AAAA,EAC3C;AAAA,EAEQ,aAAa,OAA8B;AACjD,SAAK,YAAY;AAAA,EACnB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,sBACb,OACyC;AACzC,UAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,MAC/C,KAAK;AAAA,MACL;AAAA,IAAA;AAEF,eAAW,eAAe,cAAc;AACtC,YAAM;AACN,WAAK,cAAc;AAAA,IACrB;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,OAAe,uBACb,WAiBA;AACA,QAAI,OAAO,MAAM,UAAU,KAAA;AAC3B,WAAO,CAAC,KAAK,MAAM;AACjB,aAAO,KAAK,sBAAsB,KAAK,KAAK;AAC5C,aAAO,MAAM,UAAU,KAAA;AAAA,IACzB;AACA,WAAO,KAAK;AAAA,EACd;AAAA,EAEQ,uBACN,WACA,OACa;AACb,WAAO;AAAA,MACL,MAAM;AAAA,MACN,WAAW,KAAK,IAAA;AAAA,MAChB,OAAO,KAAK,OAAO;AAAA,MACnB,MAAM;AAAA,MACN;AAAA,IAAA;AAAA,EAEJ;AAAA,EAEQ,SAAS,QAAwB;AACvC,WAAO,GAAG,MAAM,IAAI,KAAK,IAAA,CAAK,IAAI,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;AAAA,EAC1E;AACF;AAmEO,SAAS,KAKd,SACsC;AACtC,QAAM,EAAE,cAAc,OAAA,IAAW;AAGjC,MAAI,cAAc;AAChB,WAAO;AAAA,MACL;AAAA,IAAA;AAAA,EAMJ;AAGA,MAAI,WAAW,OAAO;AACpB,WAAO;AAAA,MACL;AAAA,IAAA;AAAA,EAMJ;AAGA,SAAO;AAAA,IACL;AAAA,EAAA;AAEJ;AAKA,gBAAgB,iBACd,SAC4B;AAC5B,QAAM,EAAE,SAAS,YAAY,SAAS,OAAO,GAAG,gBAAgB;AAChE,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,mBAAmB,KAAK;AAEvC,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE;AAAA,MACA,QAAQ,EAAE,GAAG,aAAa,OAAO,OAAA;AAAA,MAIjC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF;AAAA,EAAA;AAGF,mBAAiB,SAAS,OAAO,OAAO;AACtC,UAAM;AAAA,EACR;AACF;AAMA,SAAS,oBACP,SACiB;AAEjB,QAAM,SAAS;AAAA,IACb;AAAA,EAAA;AAGF,SAAO,aAAa,MAAM;AAC5B;AAQA,eAAe,2BACb,SACmC;AACnC,QAAM,EAAE,SAAS,cAAc,YAAY,SAAS,OAAO,GAAG,gBAC5D;AACF,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,mBAAmB,KAAK;AAEvC,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAGA,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE;AAAA,MACA,QAAQ,EAAE,GAAG,aAAa,OAAO,OAAA;AAAA,MAIjC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF;AAAA,EAAA;AAIF,mBAAiB,UAAU,OAAO,OAAO;AAAA,EAEzC;AAGA,QAAM,gBAAgB,OAAO,YAAA;AAI7B,QAAM;AAAA,IACJ,OAAO;AAAA,IACP,mBAAmB;AAAA,IACnB,GAAG;AAAA,EAAA,IACD;AAGJ,QAAM,aAAa,0BAA0B,YAAY;AACzD,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAEA,QAAM,eACH,QAAkC,YAAY,QAAQ;AACzD,SAAO;AAAA,IACL,qCAAqC,YAAY,UAAU,KAAK,aAAa,cAAc,MAAM;AAAA,IACjG;AAAA,MACE,UAAU;AAAA,MACV;AAAA,MACA,cAAc,cAAc;AAAA,IAAA;AAAA,EAC9B;AAKF,QAAM,SAAS,MAAM,QAAQ,iBAAiB;AAAA,IAC5C,aAAa;AAAA,MACX,GAAG;AAAA,MACH;AAAA,MACA,UAAU;AAAA,MACV;AAAA,IAAA;AAAA,IAEF,cAAc;AAAA,EAAA,CACf;AAGD,MAAI,iBAAiB,YAAY,GAAG;AAClC,WAAO;AAAA,MACL;AAAA,MACA,OAAO;AAAA,IAAA;AAAA,EAEX;AAGA,SAAO,OAAO;AAChB;"}
1
+ {"version":3,"file":"index.js","sources":["../../../../src/activities/chat/index.ts"],"sourcesContent":["/**\n * Text Activity\n *\n * Handles agentic text generation, one-shot text generation, and agentic structured output.\n * This is a self-contained module with implementation, types, and JSDoc.\n */\n\nimport { devtoolsMiddleware } from '@tanstack/ai-event-client'\nimport { stripToSpecMiddleware } from '../../strip-to-spec-middleware'\nimport { streamToText } from '../../stream-to-response.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport { EventType } from '../../types'\nimport { LazyToolManager } from './tools/lazy-tool-manager'\nimport {\n MiddlewareAbortError,\n ToolCallManager,\n executeToolCalls,\n} from './tools/tool-calls'\nimport {\n convertSchemaToJsonSchema,\n isStandardSchema,\n parseWithStandardSchema,\n} from './tools/schema-converter'\nimport { maxIterations as maxIterationsStrategy } from './agent-loop-strategies'\nimport { convertMessagesToModelMessages } from './messages'\nimport { MiddlewareRunner } from './middleware/compose'\nimport type {\n ApprovalRequest,\n ClientToolRequest,\n ToolResult,\n} from './tools/tool-calls'\nimport type { AnyTextAdapter, StructuredOutputOptions } from './adapter'\nimport type {\n AgentLoopStrategy,\n ConstrainedModelMessage,\n CustomEvent,\n InferSchemaType,\n ModelMessage,\n RunFinishedEvent,\n SchemaInput,\n StreamChunk,\n StructuredOutputCompleteEvent,\n StructuredOutputStream,\n TextMessageContentEvent,\n TextOptions,\n Tool,\n ToolCall,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallStartEvent,\n} from '../../types'\nimport type {\n ChatMiddleware,\n ChatMiddlewareConfig,\n ChatMiddlewareContext,\n ChatMiddlewarePhase,\n} from './middleware/types'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { ProviderTool } from '../../tools/provider-tool'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'text' as const\n\n// ===========================\n// Activity Options Type\n// ===========================\n\n/**\n * Options for the text activity.\n * Types are extracted directly from the adapter (which has pre-resolved generics).\n *\n * @template TAdapter - The text adapter type (created by a provider function)\n * @template TSchema - Optional Standard Schema for structured output\n * @template TStream - Whether to stream the output (default: true)\n */\nexport interface TextActivityOptions<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined,\n TStream extends boolean,\n> {\n /** The text adapter to use (created by a provider function like openaiText('gpt-4o')) */\n adapter: TAdapter\n /** Conversation messages - content types are constrained by the adapter's input modalities and metadata */\n messages?: Array<\n ConstrainedModelMessage<{\n inputModalities: TAdapter['~types']['inputModalities']\n messageMetadataByModality: TAdapter['~types']['messageMetadataByModality']\n }>\n >\n /** System prompts to prepend to the conversation */\n systemPrompts?: TextOptions['systemPrompts']\n /**\n * Tools for function calling (auto-executed when called).\n *\n * Accepts two shapes:\n * - User-defined tools via `toolDefinition()` — plain `Tool`, always assignable.\n * - Provider tools from `@tanstack/ai-<provider>/tools` (e.g. `webSearchTool`)\n * — branded and type-checked against the selected model's\n * `supports.tools` list. Passing an unsupported tool produces a\n * compile-time error on the array element.\n */\n tools?: Array<\n | (Tool & { readonly '~toolKind'?: never })\n | ProviderTool<string, TAdapter['~types']['toolCapabilities'][number]>\n >\n /** Controls the randomness of the output. Higher values make output more random. Range: [0.0, 2.0] */\n temperature?: TextOptions['temperature']\n /** Nucleus sampling parameter. The model considers tokens with topP probability mass. */\n topP?: TextOptions['topP']\n /** The maximum number of tokens to generate in the response. */\n maxTokens?: TextOptions['maxTokens']\n /** Additional metadata to attach to the request. */\n metadata?: TextOptions['metadata']\n /** Model-specific provider options (type comes from adapter) */\n modelOptions?: TAdapter['~types']['providerOptions']\n /** AbortController for cancellation */\n abortController?: TextOptions['abortController']\n /** Strategy for controlling the agent loop */\n agentLoopStrategy?: TextOptions['agentLoopStrategy']\n /** Unique conversation identifier for tracking */\n conversationId?: TextOptions['conversationId']\n /** Thread/conversation ID for AG-UI protocol. Auto-generated if not provided. */\n threadId?: TextOptions['threadId']\n /** Run ID override for AG-UI protocol. Auto-generated by adapter if not provided. */\n runId?: TextOptions['runId']\n /**\n * Optional Standard Schema for structured output.\n * When provided, the activity will:\n * 1. Run the full agentic loop (executing tools as needed)\n * 2. Once complete, return a Promise with the parsed output matching the schema\n *\n * Supports any Standard Schema compliant library (Zod v4+, ArkType, Valibot, etc.)\n *\n * @example\n * ```ts\n * const result = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Generate a person' }],\n * outputSchema: z.object({ name: z.string(), age: z.number() })\n * })\n * // result is { name: string, age: number }\n * ```\n */\n outputSchema?: TSchema\n /**\n * Whether to stream the text result.\n * When true (default), returns an AsyncIterable<StreamChunk> for streaming output.\n * When false, returns a Promise<string> with the collected text content.\n *\n * Note: If outputSchema is provided, this option is ignored and the result\n * is always a Promise<InferSchemaType<TSchema>>.\n *\n * @default true\n *\n * @example Non-streaming text\n * ```ts\n * const text = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Hello!' }],\n * stream: false\n * })\n * // text is a string with the full response\n * ```\n */\n stream?: TStream\n /**\n * Optional middleware array for observing/transforming chat behavior.\n * Middleware hooks are called in array order. See {@link ChatMiddleware} for available hooks.\n *\n * @example\n * ```ts\n * const stream = chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [...],\n * middleware: [loggingMiddleware, redactionMiddleware],\n * })\n * ```\n */\n middleware?: Array<ChatMiddleware>\n /**\n * Opaque user-provided context value passed to middleware hooks.\n * Can be used to pass request-scoped data (e.g., user ID, request context).\n */\n context?: unknown\n /**\n * Enable debug logging. Pass `true` to enable all categories with the default\n * console logger, `false` to silence everything, or a `DebugConfig` object for\n * granular control and/or a custom `Logger`. Defaults to `undefined`, which\n * means only the `errors` category is active.\n */\n debug?: DebugOption\n}\n\n// ===========================\n// Chat Options Helper\n// ===========================\n\n/**\n * Create typed options for the chat() function without executing.\n * This is useful for pre-defining configurations with full type inference.\n *\n * @example\n * ```ts\n * const chatOptions = createChatOptions({\n * adapter: anthropicText('claude-sonnet-4-5'),\n * })\n *\n * const stream = chat({ ...chatOptions, messages })\n * ```\n */\nexport function createChatOptions<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined = undefined,\n TStream extends boolean = true,\n>(\n options: TextActivityOptions<TAdapter, TSchema, TStream>,\n): TextActivityOptions<TAdapter, TSchema, TStream> {\n return options\n}\n\n// ===========================\n// Activity Result Type\n// ===========================\n\n/**\n * Result type for the text activity.\n * - If outputSchema is provided AND stream is explicitly true:\n * StructuredOutputStream<InferSchemaType<TSchema>> — yields raw JSON deltas\n * via TEXT_MESSAGE_CONTENT plus a terminal StructuredOutputCompleteEvent\n * carrying the validated object.\n * - If outputSchema is provided without explicit stream:true:\n * Promise<InferSchemaType<TSchema>>.\n * - If stream is explicitly false (no schema): Promise<string>.\n * - Otherwise (default): AsyncIterable<StreamChunk>.\n *\n * `[TStream] extends [true]` is used (not `TStream extends true`) so that the\n * default `boolean` value of `TStream` does *not* match the streaming branch.\n * Without this, plain `chat({ outputSchema })` would type as a stream while\n * the runtime returns a Promise — see issue #526.\n */\nexport type TextActivityResult<\n TSchema extends SchemaInput | undefined,\n TStream extends boolean = boolean,\n> = TSchema extends SchemaInput\n ? [TStream] extends [true]\n ? StructuredOutputStream<InferSchemaType<TSchema>>\n : Promise<InferSchemaType<TSchema>>\n : [TStream] extends [false]\n ? Promise<string>\n : AsyncIterable<StreamChunk>\n\n// ===========================\n// ChatEngine Implementation\n// ===========================\n\ninterface TextEngineConfig<\n TAdapter extends AnyTextAdapter,\n TParams extends TextOptions<any, any> = TextOptions<any>,\n> {\n adapter: TAdapter\n systemPrompts?: Array<string>\n params: TParams\n middleware?: Array<ChatMiddleware>\n context?: unknown\n}\n\ntype ToolPhaseResult = 'continue' | 'stop' | 'wait'\ntype CyclePhase = 'processText' | 'executeToolCalls'\n\nclass TextEngine<\n TAdapter extends AnyTextAdapter,\n TParams extends TextOptions<any, any> = TextOptions<any>,\n> {\n private readonly adapter: TAdapter\n private params: TParams\n private systemPrompts: Array<string>\n private tools: Array<Tool>\n private readonly loopStrategy: AgentLoopStrategy\n private toolCallManager: ToolCallManager\n private readonly lazyToolManager: LazyToolManager\n private readonly initialMessageCount: number\n private readonly requestId: string\n private readonly streamId: string\n private readonly effectiveRequest?: Request | RequestInit\n private readonly effectiveSignal?: AbortSignal\n\n private messages: Array<ModelMessage>\n private iterationCount = 0\n private lastFinishReason: string | null = null\n private streamStartTime = 0\n private totalChunkCount = 0\n private currentMessageId: string | null = null\n private accumulatedContent = ''\n private accumulatedThinking: Array<{ content: string; signature?: string }> =\n []\n private currentThinkingContent = ''\n private currentThinkingSignature = ''\n private eventOptions?: Record<string, unknown>\n private eventToolNames?: Array<string>\n private finishedEvent: RunFinishedEvent | null = null\n private earlyTermination = false\n private toolPhase: ToolPhaseResult = 'continue'\n private cyclePhase: CyclePhase = 'processText'\n // Client state extracted from initial messages (before conversion to ModelMessage)\n private readonly initialApprovals: Map<string, boolean>\n private readonly initialClientToolResults: Map<string, any>\n\n // AG-UI protocol IDs\n private threadId: string\n private runIdOverride?: string\n\n // Middleware support\n private readonly middlewareRunner: MiddlewareRunner\n private readonly middlewareCtx: ChatMiddlewareContext\n private readonly deferredPromises: Array<Promise<unknown>> = []\n private abortReason?: string\n private middlewareAbortController?: AbortController\n private terminalHookCalled = false\n\n private readonly logger: InternalLogger\n\n constructor(\n config: TextEngineConfig<TAdapter, TParams>,\n logger: InternalLogger,\n ) {\n this.logger = logger\n this.adapter = config.adapter\n this.params = config.params\n this.systemPrompts = config.params.systemPrompts || []\n this.loopStrategy =\n config.params.agentLoopStrategy || maxIterationsStrategy(5)\n this.initialMessageCount = config.params.messages.length\n\n // Extract client state (approvals, client tool results) from original messages BEFORE conversion\n // This preserves UIMessage parts data that would be lost during conversion to ModelMessage\n const { approvals, clientToolResults } =\n this.extractClientStateFromOriginalMessages(\n config.params.messages as Array<any>,\n )\n this.initialApprovals = approvals\n this.initialClientToolResults = clientToolResults\n\n // Convert messages to ModelMessage format (handles both UIMessage and ModelMessage input)\n // This ensures consistent internal format regardless of what the client sends\n this.messages = convertMessagesToModelMessages(\n config.params.messages as Array<any>,\n )\n\n // Initialize lazy tool manager after messages are converted (needs message history for scanning)\n this.lazyToolManager = new LazyToolManager(\n config.params.tools || [],\n this.messages,\n )\n this.tools = this.lazyToolManager.getActiveTools()\n this.toolCallManager = new ToolCallManager(this.tools)\n this.requestId = this.createId('chat')\n this.streamId = this.createId('stream')\n this.effectiveRequest = config.params.abortController\n ? { signal: config.params.abortController.signal }\n : undefined\n this.effectiveSignal = config.params.abortController?.signal\n this.threadId = config.params.threadId || this.createId('thread')\n this.runIdOverride = config.params.runId\n\n // Initialize middleware — devtools first, strip-to-spec always last.\n // handleStreamChunk processes raw chunks BEFORE middleware, so internal\n // state management sees extended fields (finishReason, delta, toolCallName, etc.).\n // The strip middleware ensures the yielded public stream is AG-UI spec-compliant.\n const allMiddleware = [\n devtoolsMiddleware(),\n ...(config.middleware || []),\n stripToSpecMiddleware(),\n ]\n this.middlewareRunner = new MiddlewareRunner(allMiddleware, logger)\n this.middlewareAbortController = new AbortController()\n this.middlewareCtx = {\n requestId: this.requestId,\n streamId: this.streamId,\n conversationId: config.params.conversationId,\n phase: 'init' as ChatMiddlewarePhase,\n iteration: 0,\n chunkIndex: 0,\n signal: this.effectiveSignal,\n abort: (reason?: string) => {\n this.abortReason = reason\n this.middlewareAbortController?.abort(reason)\n },\n context: config.context,\n defer: (promise: Promise<unknown>) => {\n this.deferredPromises.push(promise)\n },\n // Provider / adapter info\n provider: config.adapter.name,\n model: config.params.model,\n source: 'server',\n streaming: true,\n // Config-derived (updated in beforeRun and applyMiddlewareConfig)\n systemPrompts: this.systemPrompts,\n toolNames: undefined,\n options: undefined,\n modelOptions: config.params.modelOptions,\n // Computed\n messageCount: this.initialMessageCount,\n hasTools: this.tools.length > 0,\n // Mutable per-iteration\n currentMessageId: null,\n accumulatedContent: '',\n // References\n messages: this.messages,\n createId: (prefix: string) => this.createId(prefix),\n }\n }\n\n /** Get the accumulated content after the chat loop completes */\n getAccumulatedContent(): string {\n return this.accumulatedContent\n }\n\n /** Get the final messages array after the chat loop completes */\n getMessages(): Array<ModelMessage> {\n return this.messages\n }\n\n async *run(): AsyncGenerator<StreamChunk> {\n this.beforeRun()\n this.logger.agentLoop('run started', {\n conversationId: this.middlewareCtx.conversationId,\n })\n\n try {\n // Run initial onConfig (phase = init)\n this.middlewareCtx.phase = 'init'\n const initialConfig = this.buildMiddlewareConfig()\n const transformedConfig = await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n initialConfig,\n )\n this.applyMiddlewareConfig(transformedConfig)\n\n // Run onStart (devtools middleware emits text:request:started and initial messages here)\n await this.middlewareRunner.runOnStart(this.middlewareCtx)\n\n const pendingPhase = yield* this.checkForPendingToolCalls()\n if (pendingPhase === 'wait') {\n return\n }\n\n do {\n if (this.earlyTermination || this.isCancelled()) {\n return\n }\n\n this.logger.agentLoop(`iteration=${this.middlewareCtx.iteration}`, {\n iteration: this.middlewareCtx.iteration,\n })\n\n await this.beginCycle()\n\n if (this.cyclePhase === 'processText') {\n // Run onConfig before each model call (phase = beforeModel)\n this.middlewareCtx.phase = 'beforeModel'\n this.middlewareCtx.iteration = this.iterationCount\n const iterConfig = this.buildMiddlewareConfig()\n const transformedConfig = await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n iterConfig,\n )\n this.applyMiddlewareConfig(transformedConfig)\n\n yield* this.streamModelResponse()\n } else {\n yield* this.processToolCalls()\n }\n\n this.endCycle()\n } while (this.shouldContinue())\n\n this.logger.agentLoop('run finished', {\n finishReason: this.lastFinishReason,\n })\n\n // Call terminal onFinish hook (skip when waiting for client — stream is paused, not finished)\n if (!this.terminalHookCalled && this.toolPhase !== 'wait') {\n this.terminalHookCalled = true\n await this.middlewareRunner.runOnFinish(this.middlewareCtx, {\n finishReason: this.lastFinishReason,\n duration: Date.now() - this.streamStartTime,\n content: this.accumulatedContent,\n usage: this.finishedEvent?.usage,\n })\n }\n } catch (error: unknown) {\n if (!this.terminalHookCalled) {\n this.terminalHookCalled = true\n if (error instanceof MiddlewareAbortError) {\n // Middleware abort decision — call onAbort, not onError\n this.abortReason = error.message\n await this.middlewareRunner.runOnAbort(this.middlewareCtx, {\n reason: error.message,\n duration: Date.now() - this.streamStartTime,\n })\n } else {\n // Genuine error — call onError\n this.logger.errors('chat run failed', {\n error,\n conversationId: this.middlewareCtx.conversationId,\n })\n await this.middlewareRunner.runOnError(this.middlewareCtx, {\n error,\n duration: Date.now() - this.streamStartTime,\n })\n }\n }\n // Don't rethrow middleware abort errors — the run just stops gracefully\n if (!(error instanceof MiddlewareAbortError)) {\n throw error\n }\n } finally {\n // Check for abort terminal hook\n if (!this.terminalHookCalled && this.isCancelled()) {\n this.terminalHookCalled = true\n await this.middlewareRunner.runOnAbort(this.middlewareCtx, {\n reason: this.abortReason,\n duration: Date.now() - this.streamStartTime,\n })\n }\n\n // Await deferred promises (non-blocking side effects)\n if (this.deferredPromises.length > 0) {\n await Promise.allSettled(this.deferredPromises)\n }\n }\n }\n\n private beforeRun(): void {\n this.streamStartTime = Date.now()\n const { tools, temperature, topP, maxTokens, metadata } = this.params\n\n // Gather flattened options into an object for context\n const options: Record<string, unknown> = {}\n if (temperature !== undefined) options.temperature = temperature\n if (topP !== undefined) options.topP = topP\n if (maxTokens !== undefined) options.maxTokens = maxTokens\n if (metadata !== undefined) options.metadata = metadata\n\n this.eventOptions = Object.keys(options).length > 0 ? options : undefined\n this.eventToolNames = tools?.map((t) => t.name)\n\n // Update middleware context with computed fields\n this.middlewareCtx.options = this.eventOptions\n this.middlewareCtx.toolNames = this.eventToolNames\n }\n\n private async beginCycle(): Promise<void> {\n if (this.cyclePhase === 'processText') {\n await this.beginIteration()\n }\n }\n\n private endCycle(): void {\n if (this.cyclePhase === 'processText') {\n this.cyclePhase = 'executeToolCalls'\n return\n }\n\n this.cyclePhase = 'processText'\n this.iterationCount++\n }\n\n private async beginIteration(): Promise<void> {\n this.currentMessageId = this.createId('msg')\n this.accumulatedContent = ''\n this.accumulatedThinking = []\n this.currentThinkingContent = ''\n this.currentThinkingSignature = ''\n this.finishedEvent = null\n\n // Update mutable context fields\n this.middlewareCtx.currentMessageId = this.currentMessageId\n this.middlewareCtx.accumulatedContent = ''\n\n // Notify middleware of new iteration (devtools emits assistant message:created here)\n await this.middlewareRunner.runOnIteration(this.middlewareCtx, {\n iteration: this.iterationCount,\n messageId: this.currentMessageId,\n })\n }\n\n private async *streamModelResponse(): AsyncGenerator<StreamChunk> {\n const { temperature, topP, maxTokens, metadata, modelOptions } = this.params\n const tools = this.tools\n\n // Convert tool schemas to JSON Schema before passing to adapter\n const toolsWithJsonSchemas = tools.map((tool) => ({\n ...tool,\n inputSchema: tool.inputSchema\n ? convertSchemaToJsonSchema(tool.inputSchema)\n : undefined,\n outputSchema: tool.outputSchema\n ? convertSchemaToJsonSchema(tool.outputSchema)\n : undefined,\n }))\n\n this.middlewareCtx.phase = 'modelStream'\n\n const providerName =\n (this.adapter as { provider?: string }).provider ?? this.adapter.name\n this.logger.request(\n `activity=chat provider=${providerName} model=${this.params.model} messages=${this.messages.length} tools=${this.tools.length} stream=true`,\n {\n provider: providerName,\n model: this.params.model,\n messageCount: this.messages.length,\n toolCount: this.tools.length,\n },\n )\n\n for await (const chunk of this.adapter.chatStream({\n model: this.params.model,\n messages: this.messages,\n tools: toolsWithJsonSchemas,\n temperature,\n topP,\n maxTokens,\n metadata,\n request: this.effectiveRequest,\n modelOptions,\n systemPrompts: this.systemPrompts,\n logger: this.logger,\n threadId: this.threadId,\n runId: this.runIdOverride,\n })) {\n if (this.isCancelled()) {\n break\n }\n\n this.totalChunkCount++\n\n // Process the original (unstripped) chunk for internal state management\n // BEFORE middleware, so fields like finishReason, delta, etc. are available\n this.handleStreamChunk(chunk)\n\n // Pipe chunk through middleware (devtools middleware observes; strip-to-spec cleans)\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n chunk,\n )\n for (const outputChunk of outputChunks) {\n this.logger.output(`type=${outputChunk.type}`, { chunk: outputChunk })\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n\n // Handle usage via middleware\n if (chunk.type === 'RUN_FINISHED' && chunk.usage) {\n await this.middlewareRunner.runOnUsage(this.middlewareCtx, chunk.usage)\n }\n\n if (this.earlyTermination) {\n break\n }\n }\n }\n\n private handleStreamChunk(chunk: StreamChunk): void {\n switch (chunk.type) {\n // AG-UI Events\n case 'TEXT_MESSAGE_CONTENT':\n this.handleTextMessageContentEvent(chunk)\n break\n case 'TOOL_CALL_START':\n this.handleToolCallStartEvent(chunk)\n break\n case 'TOOL_CALL_ARGS':\n this.handleToolCallArgsEvent(chunk)\n break\n case 'TOOL_CALL_END':\n this.handleToolCallEndEvent(chunk)\n break\n case 'RUN_FINISHED':\n this.handleRunFinishedEvent(chunk)\n break\n case 'RUN_ERROR':\n this.handleRunErrorEvent(chunk)\n break\n case 'STEP_STARTED':\n this.handleStepStartedEvent()\n break\n case 'STEP_FINISHED':\n this.handleStepFinishedEvent(chunk)\n break\n\n case 'TOOL_CALL_RESULT':\n // Tool result is already added to messages in buildToolResultChunks\n break\n\n case 'REASONING_START':\n case 'REASONING_MESSAGE_START':\n case 'REASONING_MESSAGE_CONTENT':\n case 'REASONING_MESSAGE_END':\n case 'REASONING_END':\n // Reasoning events are handled by StreamProcessor\n break\n\n default:\n // RUN_STARTED, TEXT_MESSAGE_START, TEXT_MESSAGE_END,\n // STATE_SNAPSHOT, STATE_DELTA, CUSTOM\n // - no special handling needed in chat activity\n break\n }\n }\n\n // ===========================\n // AG-UI Event Handlers\n // ===========================\n\n private handleTextMessageContentEvent(chunk: TextMessageContentEvent): void {\n if (chunk.content) {\n this.accumulatedContent = chunk.content\n } else {\n this.accumulatedContent += chunk.delta\n }\n this.middlewareCtx.accumulatedContent = this.accumulatedContent\n }\n\n private handleToolCallStartEvent(chunk: ToolCallStartEvent): void {\n this.toolCallManager.addToolCallStartEvent(chunk)\n }\n\n private handleToolCallArgsEvent(chunk: ToolCallArgsEvent): void {\n this.toolCallManager.addToolCallArgsEvent(chunk)\n }\n\n private handleToolCallEndEvent(chunk: ToolCallEndEvent): void {\n this.toolCallManager.completeToolCall(chunk)\n }\n\n private handleRunFinishedEvent(chunk: RunFinishedEvent): void {\n this.finishedEvent = chunk\n this.lastFinishReason = chunk.finishReason ?? null\n }\n\n private handleRunErrorEvent(\n _chunk: Extract<StreamChunk, { type: 'RUN_ERROR' }>,\n ): void {\n this.earlyTermination = true\n }\n\n private finalizeCurrentThinkingStep(): void {\n if (this.currentThinkingContent) {\n this.accumulatedThinking.push({\n content: this.currentThinkingContent,\n ...(this.currentThinkingSignature && {\n signature: this.currentThinkingSignature,\n }),\n })\n this.currentThinkingContent = ''\n this.currentThinkingSignature = ''\n }\n }\n\n private handleStepStartedEvent(): void {\n this.finalizeCurrentThinkingStep()\n }\n\n private handleStepFinishedEvent(\n chunk: Extract<StreamChunk, { type: 'STEP_FINISHED' }>,\n ): void {\n if (chunk.delta) {\n this.currentThinkingContent += chunk.delta\n }\n if (chunk.signature) {\n this.currentThinkingSignature = chunk.signature\n }\n }\n\n private async *checkForPendingToolCalls(): AsyncGenerator<\n StreamChunk,\n ToolPhaseResult,\n void\n > {\n const pendingToolCalls = this.getPendingToolCallsFromMessages()\n if (pendingToolCalls.length === 0) {\n return 'continue'\n }\n\n const finishEvent = this.createSyntheticFinishedEvent()\n\n // Handle undiscovered lazy tool calls with self-correcting error messages\n const undiscoveredLazyResults: Array<ToolResult> = []\n const executablePendingCalls = pendingToolCalls.filter((tc) => {\n if (this.lazyToolManager.isUndiscoveredLazyTool(tc.function.name)) {\n undiscoveredLazyResults.push({\n toolCallId: tc.id,\n toolName: tc.function.name,\n result: {\n error: this.lazyToolManager.getUndiscoveredToolError(\n tc.function.name,\n ),\n },\n state: 'output-error',\n })\n return false\n }\n return true\n })\n\n if (undiscoveredLazyResults.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n undiscoveredLazyResults,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n if (executablePendingCalls.length === 0) {\n return 'continue'\n }\n\n const { approvals, clientToolResults } = this.collectClientState()\n\n const generator = executeToolCalls(\n executablePendingCalls,\n this.tools,\n approvals,\n clientToolResults,\n (eventName, data) => this.createCustomEventChunk(eventName, data),\n {\n onBeforeToolCall: async (toolCall, tool, args) => {\n this.logger.tools(`phase=before name=${toolCall.function.name}`, {\n name: toolCall.function.name,\n args,\n })\n const hookCtx = {\n toolCall,\n tool,\n args,\n toolName: toolCall.function.name,\n toolCallId: toolCall.id,\n }\n return this.middlewareRunner.runOnBeforeToolCall(\n this.middlewareCtx,\n hookCtx,\n )\n },\n onAfterToolCall: async (info) => {\n this.logger.tools(`phase=after name=${info.toolName}`, {\n name: info.toolName,\n result: info.result,\n })\n await this.middlewareRunner.runOnAfterToolCall(\n this.middlewareCtx,\n info,\n )\n },\n },\n )\n\n // Consume the async generator, yielding custom events and collecting the return value\n const executionResult = yield* this.drainToolCallGenerator(generator)\n\n // Check if middleware aborted during pending tool execution\n if (this.isMiddlewareAborted()) {\n this.setToolPhase('stop')\n return 'stop'\n }\n\n // Notify middleware of tool phase completion (devtools emits aggregate events here)\n await this.middlewareRunner.runOnToolPhaseComplete(this.middlewareCtx, {\n toolCalls: pendingToolCalls,\n results: executionResult.results,\n needsApproval: executionResult.needsApproval,\n needsClientExecution: executionResult.needsClientExecution,\n })\n\n // Build args lookup so buildToolResultChunks can emit TOOL_CALL_START +\n // TOOL_CALL_ARGS before TOOL_CALL_END during continuation re-executions.\n const argsMap = new Map<string, string>()\n for (const tc of pendingToolCalls) {\n argsMap.set(tc.id, tc.function.arguments)\n }\n\n if (\n executionResult.needsApproval.length > 0 ||\n executionResult.needsClientExecution.length > 0\n ) {\n if (executionResult.results.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n argsMap,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n for (const chunk of this.buildApprovalChunks(\n executionResult.needsApproval,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n for (const chunk of this.buildClientToolChunks(\n executionResult.needsClientExecution,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n this.setToolPhase('wait')\n return 'wait'\n }\n\n const toolResultChunks = this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n argsMap,\n )\n\n for (const chunk of toolResultChunks) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n return 'continue'\n }\n\n private async *processToolCalls(): AsyncGenerator<StreamChunk, void, void> {\n if (!this.shouldExecuteToolPhase()) {\n this.setToolPhase('stop')\n return\n }\n\n const toolCalls = this.toolCallManager.getToolCalls()\n const finishEvent = this.finishedEvent\n\n if (!finishEvent || toolCalls.length === 0) {\n this.setToolPhase('stop')\n return\n }\n\n this.addAssistantToolCallMessage(toolCalls)\n\n // Handle undiscovered lazy tool calls with self-correcting error messages\n const undiscoveredLazyResults: Array<ToolResult> = []\n const executableToolCalls = toolCalls.filter((tc) => {\n if (this.lazyToolManager.isUndiscoveredLazyTool(tc.function.name)) {\n undiscoveredLazyResults.push({\n toolCallId: tc.id,\n toolName: tc.function.name,\n result: {\n error: this.lazyToolManager.getUndiscoveredToolError(\n tc.function.name,\n ),\n },\n state: 'output-error',\n })\n return false\n }\n return true\n })\n\n if (undiscoveredLazyResults.length > 0) {\n const finishEvt = this.finishedEvent!\n for (const chunk of this.buildToolResultChunks(\n undiscoveredLazyResults,\n finishEvt,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n if (executableToolCalls.length === 0) {\n // All tool calls were undiscovered lazy tools — errors emitted, continue loop\n this.toolCallManager.clear()\n this.setToolPhase('continue')\n return\n }\n this.middlewareCtx.phase = 'beforeTools'\n\n const { approvals, clientToolResults } = this.collectClientState()\n\n const generator = executeToolCalls(\n executableToolCalls,\n this.tools,\n approvals,\n clientToolResults,\n (eventName, data) => this.createCustomEventChunk(eventName, data),\n {\n onBeforeToolCall: async (toolCall, tool, args) => {\n this.logger.tools(`phase=before name=${toolCall.function.name}`, {\n name: toolCall.function.name,\n args,\n })\n const hookCtx = {\n toolCall,\n tool,\n args,\n toolName: toolCall.function.name,\n toolCallId: toolCall.id,\n }\n return this.middlewareRunner.runOnBeforeToolCall(\n this.middlewareCtx,\n hookCtx,\n )\n },\n onAfterToolCall: async (info) => {\n this.logger.tools(`phase=after name=${info.toolName}`, {\n name: info.toolName,\n result: info.result,\n })\n await this.middlewareRunner.runOnAfterToolCall(\n this.middlewareCtx,\n info,\n )\n },\n },\n )\n\n // Consume the async generator, yielding custom events and collecting the return value\n const executionResult = yield* this.drainToolCallGenerator(generator)\n\n this.middlewareCtx.phase = 'afterTools'\n\n // Check if middleware aborted during tool execution\n if (this.isMiddlewareAborted()) {\n this.setToolPhase('stop')\n return\n }\n\n // Notify middleware of tool phase completion (devtools emits aggregate events here)\n await this.middlewareRunner.runOnToolPhaseComplete(this.middlewareCtx, {\n toolCalls,\n results: executionResult.results,\n needsApproval: executionResult.needsApproval,\n needsClientExecution: executionResult.needsClientExecution,\n })\n\n if (\n executionResult.needsApproval.length > 0 ||\n executionResult.needsClientExecution.length > 0\n ) {\n if (executionResult.results.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n\n for (const chunk of this.buildApprovalChunks(\n executionResult.needsApproval,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n for (const chunk of this.buildClientToolChunks(\n executionResult.needsClientExecution,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n this.setToolPhase('wait')\n return\n }\n\n const toolResultChunks = this.buildToolResultChunks(\n executionResult.results,\n finishEvent,\n )\n\n for (const chunk of toolResultChunks) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n\n // Refresh tools if lazy tools were discovered in this batch\n if (this.lazyToolManager.hasNewlyDiscoveredTools()) {\n this.tools = this.lazyToolManager.getActiveTools()\n this.toolCallManager = new ToolCallManager(this.tools)\n this.setToolPhase('continue')\n return\n }\n\n this.toolCallManager.clear()\n\n this.setToolPhase('continue')\n }\n\n private shouldExecuteToolPhase(): boolean {\n return (\n this.finishedEvent?.finishReason === 'tool_calls' &&\n this.tools.length > 0 &&\n this.toolCallManager.hasToolCalls()\n )\n }\n\n private addAssistantToolCallMessage(toolCalls: Array<ToolCall>): void {\n this.finalizeCurrentThinkingStep()\n\n this.messages = [\n ...this.messages,\n {\n role: 'assistant',\n content: this.accumulatedContent || null,\n toolCalls,\n ...(this.accumulatedThinking.length > 0 && {\n thinking: this.accumulatedThinking,\n }),\n },\n ]\n }\n\n /**\n * Extract client state (approvals and client tool results) from original messages.\n * This is called in the constructor BEFORE converting to ModelMessage format,\n * because the parts array (which contains approval state) is lost during conversion.\n */\n private extractClientStateFromOriginalMessages(\n originalMessages: Array<any>,\n ): {\n approvals: Map<string, boolean>\n clientToolResults: Map<string, any>\n } {\n const approvals = new Map<string, boolean>()\n const clientToolResults = new Map<string, any>()\n\n for (const message of originalMessages) {\n // Check for UIMessage format (parts array) - extract client tool results and approvals\n if (message.role === 'assistant' && message.parts) {\n for (const part of message.parts) {\n if (part.type === 'tool-call') {\n // Extract client tool results (tools without approval that have output)\n if (part.output !== undefined && !part.approval) {\n clientToolResults.set(part.id, part.output)\n }\n // Extract approval responses from UIMessage format parts\n if (\n part.approval?.id &&\n part.approval?.approved !== undefined &&\n part.state === 'approval-responded'\n ) {\n approvals.set(part.approval.id, part.approval.approved)\n }\n }\n }\n }\n }\n\n return { approvals, clientToolResults }\n }\n\n private collectClientState(): {\n approvals: Map<string, boolean>\n clientToolResults: Map<string, any>\n } {\n // Start with the initial client state extracted from original messages\n const approvals = new Map(this.initialApprovals)\n const clientToolResults = new Map(this.initialClientToolResults)\n\n // Also check current messages for any additional tool results (from server tools)\n for (const message of this.messages) {\n // Check for ModelMessage format (role: 'tool' messages contain tool results)\n // This handles results sent back from the client after executing client-side tools\n if (message.role === 'tool' && message.toolCallId) {\n // Parse content back to original output (was stringified by uiMessageToModelMessages)\n let output: unknown\n try {\n output = JSON.parse(message.content as string)\n } catch {\n output = message.content\n }\n // Skip approval response messages (they have pendingExecution marker)\n // These are NOT real client tool results — they are synthetic tool messages\n // created by uiMessageToModelMessages for approved-but-not-yet-executed tools.\n // Treating them as results would prevent the server from requesting actual\n // client-side execution after approval (see GitHub issue #225).\n if (\n output &&\n typeof output === 'object' &&\n (output as any).pendingExecution === true\n ) {\n continue\n }\n clientToolResults.set(message.toolCallId, output)\n }\n }\n\n return { approvals, clientToolResults }\n }\n\n private buildApprovalChunks(\n approvals: Array<ApprovalRequest>,\n finishEvent: RunFinishedEvent,\n ): Array<StreamChunk> {\n const chunks: Array<StreamChunk> = []\n\n for (const approval of approvals) {\n chunks.push({\n type: 'CUSTOM',\n timestamp: Date.now(),\n model: finishEvent.model,\n name: 'approval-requested',\n value: {\n toolCallId: approval.toolCallId,\n toolName: approval.toolName,\n input: approval.input,\n approval: {\n id: approval.approvalId,\n needsApproval: true,\n },\n },\n } as StreamChunk)\n }\n\n return chunks\n }\n\n private buildClientToolChunks(\n clientRequests: Array<ClientToolRequest>,\n finishEvent: RunFinishedEvent,\n ): Array<StreamChunk> {\n const chunks: Array<StreamChunk> = []\n\n for (const clientTool of clientRequests) {\n chunks.push({\n type: 'CUSTOM',\n timestamp: Date.now(),\n model: finishEvent.model,\n name: 'tool-input-available',\n value: {\n toolCallId: clientTool.toolCallId,\n toolName: clientTool.toolName,\n input: clientTool.input,\n },\n } as StreamChunk)\n }\n\n return chunks\n }\n\n private buildToolResultChunks(\n results: Array<ToolResult>,\n finishEvent: RunFinishedEvent,\n argsMap?: Map<string, string>,\n ): Array<StreamChunk> {\n const chunks: Array<StreamChunk> = []\n\n for (const result of results) {\n const content = JSON.stringify(result.result)\n\n // Emit TOOL_CALL_START + TOOL_CALL_ARGS before TOOL_CALL_END so that\n // the client can reconstruct the full tool call during continuations.\n if (argsMap) {\n chunks.push({\n type: 'TOOL_CALL_START',\n timestamp: Date.now(),\n model: finishEvent.model,\n toolCallId: result.toolCallId,\n toolCallName: result.toolName,\n toolName: result.toolName,\n } as StreamChunk)\n\n const args = argsMap.get(result.toolCallId) ?? '{}'\n chunks.push({\n type: 'TOOL_CALL_ARGS',\n timestamp: Date.now(),\n model: finishEvent.model,\n toolCallId: result.toolCallId,\n delta: args,\n args,\n } as StreamChunk)\n }\n\n chunks.push({\n type: 'TOOL_CALL_END',\n timestamp: Date.now(),\n model: finishEvent.model,\n toolCallId: result.toolCallId,\n toolCallName: result.toolName,\n toolName: result.toolName,\n result: content,\n } as StreamChunk)\n\n // AG-UI spec TOOL_CALL_RESULT event\n chunks.push({\n type: 'TOOL_CALL_RESULT',\n timestamp: Date.now(),\n model: finishEvent.model,\n messageId: this.createId('tool-result'),\n toolCallId: result.toolCallId,\n content,\n role: 'tool',\n } as StreamChunk)\n\n // If a placeholder tool message exists for this toolCallId (created by\n // uiMessageToModelMessages for an approval-responded part with no\n // output yet), replace it with the real result. Otherwise the LLM sees\n // both messages — and since the Anthropic adapter dedupes tool_result\n // blocks by tool_use_id keeping the first match, the placeholder wins\n // and the real result is dropped (see issue #532).\n const placeholderIdx = this.messages.findIndex((m) => {\n if (m.role !== 'tool' || m.toolCallId !== result.toolCallId) {\n return false\n }\n if (typeof m.content !== 'string') return false\n try {\n return JSON.parse(m.content)?.pendingExecution === true\n } catch {\n return false\n }\n })\n\n const newToolMessage: ModelMessage = {\n role: 'tool',\n content,\n toolCallId: result.toolCallId,\n }\n\n if (placeholderIdx >= 0) {\n this.messages = [\n ...this.messages.slice(0, placeholderIdx),\n newToolMessage,\n ...this.messages.slice(placeholderIdx + 1),\n ]\n } else {\n this.messages = [...this.messages, newToolMessage]\n }\n }\n\n return chunks\n }\n\n private getPendingToolCallsFromMessages(): Array<ToolCall> {\n // Build a set of completed tool IDs, but exclude tools with pendingExecution marker\n // (these are approved tools that still need to execute)\n const completedToolIds = new Set<string>()\n\n for (const message of this.messages) {\n if (message.role === 'tool' && message.toolCallId) {\n // Check if this is an approval response with pendingExecution marker\n let hasPendingExecution = false\n if (typeof message.content === 'string') {\n try {\n const parsed = JSON.parse(message.content)\n if (parsed.pendingExecution === true) {\n hasPendingExecution = true\n }\n } catch {\n // Not JSON, treat as regular tool result\n }\n }\n\n // Only mark as complete if NOT pending execution\n if (!hasPendingExecution) {\n completedToolIds.add(message.toolCallId)\n }\n }\n }\n\n const pending: Array<ToolCall> = []\n\n for (const message of this.messages) {\n if (message.role === 'assistant' && message.toolCalls) {\n for (const toolCall of message.toolCalls) {\n if (!completedToolIds.has(toolCall.id)) {\n pending.push(toolCall)\n }\n }\n }\n }\n\n return pending\n }\n\n private createSyntheticFinishedEvent(): RunFinishedEvent {\n return {\n type: 'RUN_FINISHED',\n runId: this.createId('pending'),\n threadId: this.threadId,\n model: this.params.model,\n timestamp: Date.now(),\n finishReason: 'tool_calls',\n } as RunFinishedEvent\n }\n\n private shouldContinue(): boolean {\n if (this.cyclePhase === 'executeToolCalls') {\n return true\n }\n\n return (\n this.loopStrategy({\n iterationCount: this.iterationCount,\n messages: this.messages,\n finishReason: this.lastFinishReason,\n }) && this.toolPhase === 'continue'\n )\n }\n\n private isAborted(): boolean {\n return !!this.effectiveSignal?.aborted\n }\n\n private isMiddlewareAborted(): boolean {\n return !!this.middlewareAbortController?.signal.aborted\n }\n\n private isCancelled(): boolean {\n return this.isAborted() || this.isMiddlewareAborted()\n }\n\n private buildMiddlewareConfig(): ChatMiddlewareConfig {\n return {\n messages: this.messages,\n systemPrompts: [...this.systemPrompts],\n tools: [...this.tools],\n temperature: this.params.temperature,\n topP: this.params.topP,\n maxTokens: this.params.maxTokens,\n metadata: this.params.metadata,\n modelOptions: this.params.modelOptions,\n }\n }\n\n private applyMiddlewareConfig(config: ChatMiddlewareConfig): void {\n this.messages = config.messages\n this.systemPrompts = config.systemPrompts\n this.tools = config.tools\n this.params = {\n ...this.params,\n temperature: config.temperature,\n topP: config.topP,\n maxTokens: config.maxTokens,\n metadata: config.metadata,\n modelOptions: config.modelOptions,\n }\n\n // Sync context fields that depend on config\n this.middlewareCtx.messages = this.messages\n this.middlewareCtx.systemPrompts = this.systemPrompts\n this.middlewareCtx.hasTools = this.tools.length > 0\n this.middlewareCtx.toolNames = this.tools.map((t) => t.name)\n this.middlewareCtx.modelOptions = config.modelOptions\n }\n\n private setToolPhase(phase: ToolPhaseResult): void {\n this.toolPhase = phase\n }\n\n /**\n * Pipe a single chunk through the middleware pipeline (strip-to-spec, devtools, etc.)\n * and yield all resulting output chunks.\n */\n private async *pipeThroughMiddleware(\n chunk: StreamChunk,\n ): AsyncGenerator<StreamChunk, void, void> {\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n chunk,\n )\n for (const outputChunk of outputChunks) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n /**\n * Drain an executeToolCalls async generator, yielding any CustomEvent chunks\n * through the middleware pipeline and returning the final ExecuteToolCallsResult.\n */\n private async *drainToolCallGenerator(\n generator: AsyncGenerator<\n CustomEvent,\n {\n results: Array<ToolResult>\n needsApproval: Array<ApprovalRequest>\n needsClientExecution: Array<ClientToolRequest>\n },\n void\n >,\n ): AsyncGenerator<\n StreamChunk,\n {\n results: Array<ToolResult>\n needsApproval: Array<ApprovalRequest>\n needsClientExecution: Array<ClientToolRequest>\n },\n void\n > {\n let next = await generator.next()\n while (!next.done) {\n yield* this.pipeThroughMiddleware(next.value)\n next = await generator.next()\n }\n return next.value\n }\n\n private createCustomEventChunk(\n eventName: string,\n value: Record<string, any>,\n ): CustomEvent {\n return {\n type: 'CUSTOM',\n timestamp: Date.now(),\n model: this.params.model,\n name: eventName,\n value,\n } as CustomEvent\n }\n\n private createId(prefix: string): string {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).slice(2, 9)}`\n }\n}\n\n// ===========================\n// Activity Implementation\n// ===========================\n\n/**\n * Text activity - handles agentic text generation, one-shot text generation, and agentic structured output.\n *\n * This activity supports four modes:\n * 1. **Streaming agentic text**: Stream responses with automatic tool execution\n * 2. **Streaming one-shot text**: Simple streaming request/response without tools\n * 3. **Non-streaming text**: Returns collected text as a string (stream: false)\n * 4. **Agentic structured output**: Run tools, then return structured data\n *\n * @example Full agentic text (streaming with tools)\n * ```ts\n * import { chat } from '@tanstack/ai'\n * import { openaiText } from '@tanstack/ai-openai'\n *\n * for await (const chunk of chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'What is the weather?' }],\n * tools: [weatherTool]\n * })) {\n * if (chunk.type === 'content') {\n * console.log(chunk.delta)\n * }\n * }\n * ```\n *\n * @example One-shot text (streaming without tools)\n * ```ts\n * for await (const chunk of chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Hello!' }]\n * })) {\n * console.log(chunk)\n * }\n * ```\n *\n * @example Non-streaming text (stream: false)\n * ```ts\n * const text = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Hello!' }],\n * stream: false\n * })\n * // text is a string with the full response\n * ```\n *\n * @example Agentic structured output (tools + structured response)\n * ```ts\n * import { z } from 'zod'\n *\n * const result = await chat({\n * adapter: openaiText('gpt-4o'),\n * messages: [{ role: 'user', content: 'Research and summarize the topic' }],\n * tools: [researchTool, analyzeTool],\n * outputSchema: z.object({\n * summary: z.string(),\n * keyPoints: z.array(z.string())\n * })\n * })\n * // result is { summary: string, keyPoints: string[] }\n * ```\n */\nexport function chat<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined = undefined,\n TStream extends boolean = boolean,\n>(\n options: TextActivityOptions<TAdapter, TSchema, TStream>,\n): TextActivityResult<TSchema, TStream> {\n const { outputSchema, stream } = options\n\n // outputSchema + stream:true is the only branch that streams structured\n // output. Without an explicit `stream: true`, schema-bearing calls run the\n // agent loop and resolve to a typed Promise<InferSchemaType<TSchema>>.\n if (outputSchema && stream === true) {\n return runStreamingStructuredOutput({\n ...options,\n outputSchema,\n stream,\n }) as TextActivityResult<TSchema, TStream>\n }\n\n // If outputSchema is provided, run agentic structured output (Promise<T>)\n if (outputSchema) {\n return runAgenticStructuredOutput({\n ...options,\n outputSchema,\n }) as TextActivityResult<TSchema, TStream>\n }\n\n // If stream is explicitly false, run non-streaming text\n if (stream === false) {\n return runNonStreamingText({\n ...options,\n outputSchema: undefined,\n stream,\n }) as TextActivityResult<TSchema, TStream>\n }\n\n // Otherwise, run streaming text (default)\n return runStreamingText({\n ...options,\n outputSchema: undefined,\n stream,\n }) as TextActivityResult<TSchema, TStream>\n}\n\n/**\n * Run streaming text (agentic or one-shot depending on tools)\n */\nasync function* runStreamingText(\n options: TextActivityOptions<AnyTextAdapter, undefined, true>,\n): AsyncIterable<StreamChunk> {\n const { adapter, middleware, context, debug, ...textOptions } = options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, any>,\n Record<string, any>\n >,\n middleware,\n context,\n },\n logger,\n )\n\n for await (const chunk of engine.run()) {\n yield chunk\n }\n}\n\n/**\n * Run non-streaming text - collects all content and returns as a string.\n * Runs the full agentic loop (if tools are provided) but returns collected text.\n */\nfunction runNonStreamingText(\n options: TextActivityOptions<AnyTextAdapter, undefined, false>,\n): Promise<string> {\n // Run the streaming text and collect all text using streamToText\n const stream = runStreamingText(\n options as unknown as TextActivityOptions<AnyTextAdapter, undefined, true>,\n )\n\n return streamToText(stream)\n}\n\n/**\n * Run agentic structured output:\n * 1. Execute the full agentic loop (with tools)\n * 2. Once complete, call adapter.structuredOutput with the conversation context\n * 3. Validate and return the structured result\n */\nasync function runAgenticStructuredOutput<TSchema extends SchemaInput>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, boolean>,\n): Promise<InferSchemaType<TSchema>> {\n const { adapter, outputSchema, middleware, context, debug, ...textOptions } =\n options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n if (!outputSchema) {\n throw new Error('outputSchema is required for structured output')\n }\n\n // Create the engine and run the agentic loop\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, unknown>,\n Record<string, unknown>\n >,\n middleware,\n context,\n },\n logger,\n )\n\n // Consume the stream to run the agentic loop\n for await (const _chunk of engine.run()) {\n // Just consume the stream to execute the agentic loop\n }\n\n // Get the final messages from the engine (includes tool results)\n const finalMessages = engine.getMessages()\n\n // Build text options for structured output, excluding tools since\n // the agentic loop is complete and we only need the final response\n const {\n tools: _tools,\n agentLoopStrategy: _als,\n ...structuredTextOptions\n } = textOptions\n\n // Convert the schema to JSON Schema before passing to the adapter\n const jsonSchema = convertSchemaToJsonSchema(outputSchema)\n if (!jsonSchema) {\n throw new Error('Failed to convert output schema to JSON Schema')\n }\n\n const providerName =\n (adapter as { provider?: string }).provider ?? adapter.name\n logger.request(\n `activity=chat-structured provider=${providerName} model=${model} messages=${finalMessages.length}`,\n {\n provider: providerName,\n model,\n messageCount: finalMessages.length,\n },\n )\n\n // Call the adapter's structured output method with the conversation context\n // The adapter receives JSON Schema and can apply vendor-specific patches\n const result = await adapter.structuredOutput({\n chatOptions: {\n ...structuredTextOptions,\n model,\n messages: finalMessages,\n logger,\n },\n outputSchema: jsonSchema,\n })\n\n // Validate the result against the schema if it's a Standard Schema\n if (isStandardSchema(outputSchema)) {\n return parseWithStandardSchema<InferSchemaType<TSchema>>(\n outputSchema,\n result.data,\n )\n }\n\n // For plain JSON Schema, return the data as-is\n return result.data as InferSchemaType<TSchema>\n}\n\n/**\n * Synthesize a streaming structured-output stream by wrapping a non-streaming\n * `structuredOutput` call. Used when an adapter doesn't implement\n * `structuredOutputStream` natively.\n */\nasync function* fallbackStructuredOutputStream(\n adapter: AnyTextAdapter,\n options: StructuredOutputOptions<Record<string, unknown>>,\n): AsyncIterable<StreamChunk> {\n const { chatOptions } = options\n const runId = chatOptions.runId ?? `mock-${Date.now()}`\n const threadId = chatOptions.threadId ?? `mock-${Date.now()}`\n const messageId = `mock-${Date.now()}-${Math.random().toString(36).slice(2)}`\n const model = chatOptions.model\n const timestamp = Date.now()\n\n yield {\n type: EventType.RUN_STARTED,\n runId,\n threadId,\n model,\n timestamp,\n }\n\n let result: { data: unknown; rawText: string }\n try {\n result = await adapter.structuredOutput(options)\n } catch (error) {\n const message = error instanceof Error ? error.message : 'Unknown error'\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model,\n timestamp,\n message,\n error: { message },\n }\n return\n }\n\n yield {\n type: EventType.TEXT_MESSAGE_START,\n messageId,\n role: 'assistant',\n model,\n timestamp,\n }\n\n yield {\n type: EventType.TEXT_MESSAGE_CONTENT,\n messageId,\n delta: result.rawText,\n model,\n timestamp,\n }\n\n yield {\n type: EventType.TEXT_MESSAGE_END,\n messageId,\n model,\n timestamp,\n }\n\n yield {\n type: EventType.CUSTOM,\n name: 'structured-output.complete',\n value: { object: result.data, raw: result.rawText },\n model,\n timestamp,\n }\n\n yield {\n type: EventType.RUN_FINISHED,\n runId,\n threadId,\n model,\n timestamp,\n finishReason: 'stop',\n }\n}\n\n/**\n * Run streaming structured output:\n * - Without tools: call adapter.structuredOutputStream directly (single\n * provider request emitting JSON deltas + a final CUSTOM event).\n * - With tools: run the agent loop, yield its non-terminal chunks, then call\n * structuredOutputStream on the final messages so the structured stream's\n * own RUN_STARTED/RUN_FINISHED bracket the run.\n *\n * Validates the parsed object against the original Standard Schema (if\n * applicable) when forwarding the final `structured-output.complete` event.\n *\n * Pre-flight validation (missing schema, unconvertible schema) throws\n * synchronously at call time rather than as a yielded RUN_ERROR mid-stream —\n * those are programmer errors, not runtime conditions.\n */\nfunction runStreamingStructuredOutput<TSchema extends SchemaInput>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, true>,\n): StructuredOutputStream<InferSchemaType<TSchema>> {\n const { outputSchema } = options\n\n if (!outputSchema) {\n throw new Error('outputSchema is required for streaming structured output')\n }\n\n // forStructuredOutput strict-converts the schema once at the activity\n // boundary. Adapters can re-convert if their wire format diverges, but the\n // default flow hands them a strict-ready schema.\n const jsonSchema = convertSchemaToJsonSchema(outputSchema, {\n forStructuredOutput: true,\n })\n if (!jsonSchema) {\n throw new Error('Failed to convert output schema to JSON Schema')\n }\n\n // The implementation generator yields the broader internal type\n // (`StreamChunk | StructuredOutputCompleteEvent<T>`) so agent-loop\n // CustomEvents can flow through; the public-facing type narrows to\n // `Exclude<StreamChunk, CustomEvent> | StructuredOutputCompleteEvent<T>`\n // which lets consumers narrow `chunk.value` cleanly. The widen→narrow\n // is contained here so consumers see only the strict type.\n return runStreamingStructuredOutputImpl(\n options,\n jsonSchema,\n ) as StructuredOutputStream<InferSchemaType<TSchema>>\n}\n\n/**\n * Internal generator return type — broader than the public\n * `StructuredOutputStream<T>`. The public type pins three tagged `CUSTOM`\n * events (`structured-output.complete`, `approval-requested`,\n * `tool-input-available`) so consumers can narrow `chunk.value` cleanly by\n * literal `name`. At runtime, tools can also emit arbitrary user-defined\n * `CustomEvent`s through the `emitCustomEvent` context API; those flow\n * through this generator with `name: string` and are widened out at the\n * public boundary because keeping them would collapse the typed narrow back\n * to `any`. The cast inside `runStreamingStructuredOutput` is where that\n * widening happens.\n */\ntype StructuredOutputStreamInternal<T> = AsyncIterable<\n StreamChunk | StructuredOutputCompleteEvent<T>\n>\n\nasync function* runStreamingStructuredOutputImpl<TSchema extends SchemaInput>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, true>,\n jsonSchema: NonNullable<ReturnType<typeof convertSchemaToJsonSchema>>,\n): StructuredOutputStreamInternal<InferSchemaType<TSchema>> {\n const { adapter, outputSchema, middleware, context, debug, ...textOptions } =\n options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n const runId = textOptions.runId\n\n // Inputs may be UIMessages (from useChat) or ModelMessages (from server-side\n // callers). The agent-loop branch converts via TextEngine; the no-tools\n // branch must convert here so the adapter sees a uniform ModelMessage shape.\n let finalMessages = convertMessagesToModelMessages(textOptions.messages ?? [])\n\n if (textOptions.tools?.length) {\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger, messages: finalMessages },\n middleware,\n context,\n },\n logger,\n )\n\n // The structured-output stream emits its own RUN_STARTED + RUN_FINISHED\n // pair to bracket the run — drop both from the engine's output so\n // consumers see exactly one terminal lifecycle pair.\n let agentLoopErrored = false\n try {\n for await (const chunk of engine.run()) {\n if (chunk.type === 'RUN_STARTED' || chunk.type === 'RUN_FINISHED') {\n continue\n }\n if (chunk.type === 'RUN_ERROR') {\n // The engine yielded RUN_ERROR without throwing (provider error mid\n // agent loop). Forward it once and short-circuit before invoking\n // structuredOutputStream — otherwise consumers would see a confusing\n // RUN_ERROR → RUN_STARTED → structured-output.complete sequence and\n // we would bill another provider call after a failed run.\n agentLoopErrored = true\n yield chunk\n continue\n }\n yield chunk\n }\n } catch (engineError) {\n const message = (engineError as Error).message || 'Agent loop failed'\n logger.errors('runStreamingStructuredOutput agent loop failed', {\n error: engineError,\n source: 'runStreamingStructuredOutput',\n })\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model,\n timestamp: Date.now(),\n message,\n code: 'agent-loop-failed',\n error: { message, code: 'agent-loop-failed' },\n }\n return\n }\n\n if (agentLoopErrored) {\n return\n }\n\n finalMessages = engine.getMessages()\n }\n\n const {\n tools: _tools,\n agentLoopStrategy: _als,\n ...structuredTextOptions\n } = textOptions\n\n logger.request(\n `activity=chat-structured-stream provider=${adapter.name} model=${model} messages=${finalMessages.length}`,\n {\n provider: adapter.name,\n model,\n messageCount: finalMessages.length,\n },\n )\n\n // Adapters consume the abort signal via `chatOptions.request?.signal` and\n // pass it to the underlying network call. Without this, aborting the SSE\n // response never cancels the upstream provider request and a terminal\n // structured-output.complete event still gets yielded after stop.\n const structuredChatOptions = {\n ...structuredTextOptions,\n model,\n messages: finalMessages,\n logger,\n request: textOptions.abortController\n ? { signal: textOptions.abortController.signal }\n : undefined,\n }\n\n // Adapters that don't implement structuredOutputStream natively fall back\n // to wrapping the non-streaming `structuredOutput` — `fallbackStructuredOutputStream`\n // synthesizes the AG-UI lifecycle events around it.\n const stream = adapter.structuredOutputStream\n ? adapter.structuredOutputStream({\n chatOptions: structuredChatOptions,\n outputSchema: jsonSchema,\n })\n : fallbackStructuredOutputStream(adapter, {\n chatOptions: structuredChatOptions,\n outputSchema: jsonSchema,\n })\n\n for await (const chunk of stream) {\n if (\n chunk.type === EventType.CUSTOM &&\n chunk.name === 'structured-output.complete'\n ) {\n const value = chunk.value as {\n object: unknown\n raw: string\n reasoning?: string\n }\n if (isStandardSchema(outputSchema)) {\n try {\n const validated = parseWithStandardSchema<InferSchemaType<TSchema>>(\n outputSchema,\n value.object,\n )\n yield {\n ...chunk,\n // Forward `reasoning` through schema validation so consumers that\n // only listen for the terminal event don't lose chain-of-thought.\n value: {\n object: validated,\n raw: value.raw,\n ...(value.reasoning ? { reasoning: value.reasoning } : {}),\n },\n }\n continue\n } catch (err) {\n const message = (err as Error).message || 'Schema validation failed'\n logger.errors(\n 'runStreamingStructuredOutput schema validation failed',\n {\n error: err,\n source: 'runStreamingStructuredOutput',\n // Include reasoning in error meta so post-mortems can recover\n // what the model thought through before producing invalid JSON.\n ...(value.reasoning ? { reasoning: value.reasoning } : {}),\n },\n )\n yield {\n type: EventType.RUN_ERROR,\n runId,\n model: chunk.model ?? model,\n timestamp: chunk.timestamp ?? Date.now(),\n message,\n code: 'schema-validation',\n error: {\n message,\n code: 'schema-validation',\n ...(value.reasoning ? { reasoning: value.reasoning } : {}),\n },\n }\n return\n }\n }\n yield chunk\n continue\n }\n yield chunk\n }\n}\n\n// Re-export adapter types\nexport type {\n TextAdapter,\n TextAdapterConfig,\n StructuredOutputOptions,\n StructuredOutputResult,\n} from './adapter'\nexport { BaseTextAdapter } from './adapter'\n"],"names":["maxIterationsStrategy","transformedConfig"],"mappings":"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"}
@@ -90,7 +90,8 @@ function buildAssistantMessages(uiMessage) {
90
90
  function: {
91
91
  name: part.name,
92
92
  arguments: part.arguments
93
- }
93
+ },
94
+ ...part.metadata !== void 0 && { metadata: part.metadata }
94
95
  });
95
96
  }
96
97
  break;
@@ -187,8 +188,9 @@ function modelMessageToUIMessage(modelMessage, id) {
187
188
  id: toolCall.id,
188
189
  name: toolCall.function.name,
189
190
  arguments: toolCall.function.arguments,
190
- state: "input-complete"
191
+ state: "input-complete",
191
192
  // Model messages have complete arguments
193
+ ...toolCall.metadata !== void 0 && { metadata: toolCall.metadata }
192
194
  });
193
195
  }
194
196
  }
@@ -1 +1 @@
1
- {"version":3,"file":"messages.js","sources":["../../../../src/activities/chat/messages.ts"],"sourcesContent":["import type {\n ContentPart,\n MessagePart,\n ModelMessage,\n TextPart,\n ToolCallPart,\n UIMessage,\n} from '../../types'\n// ===========================\n// Message Converters\n// ===========================\n\n/**\n * Check if a MessagePart is a content part (text, image, audio, video, document)\n * that maps directly to a ModelMessage ContentPart.\n */\nfunction isContentPart(part: MessagePart): part is ContentPart {\n return (\n part.type === 'text' ||\n part.type === 'image' ||\n part.type === 'audio' ||\n part.type === 'video' ||\n part.type === 'document'\n )\n}\n\n/**\n * Collapse an array of ContentParts into the most compact ModelMessage content:\n * - Empty array → null\n * - All text parts → joined string (or null if empty)\n * - Mixed content → ContentPart array as-is\n */\nfunction collapseContentParts(\n parts: Array<ContentPart>,\n): string | null | Array<ContentPart> {\n if (parts.length === 0) return null\n\n const allText = parts.every((p) => p.type === 'text')\n if (allText) {\n const joined = parts.map((p) => p.content).join('')\n return joined || null\n }\n\n return parts\n}\n\n/**\n * Extract text content from ModelMessage content (string, null, or ContentPart array).\n * Used when only the text portion is needed (e.g., tool result content).\n */\nfunction getTextContent(content: string | null | Array<ContentPart>): string {\n if (content === null) return ''\n if (typeof content === 'string') return content\n return content\n .filter((part): part is TextPart => part.type === 'text')\n .map((part) => part.content)\n .join('')\n}\n\n/**\n * Convert UIMessages or ModelMessages to ModelMessages\n */\nexport function convertMessagesToModelMessages(\n messages: Array<UIMessage | ModelMessage>,\n): Array<ModelMessage> {\n const modelMessages: Array<ModelMessage> = []\n for (const msg of messages) {\n if ('parts' in msg) {\n // UIMessage - convert to ModelMessages\n modelMessages.push(...uiMessageToModelMessages(msg))\n } else {\n // Already ModelMessage\n modelMessages.push(msg)\n }\n }\n return modelMessages\n}\n\n/**\n * Convert a UIMessage to ModelMessage(s)\n *\n * Walks the parts array IN ORDER to preserve the interleaving of text,\n * tool calls, and tool results. This is critical for multi-round tool\n * flows where the model generates text, calls a tool, gets the result,\n * then generates more text and calls another tool.\n *\n * The output preserves the sequential structure:\n * text1 → toolCall1 → toolResult1 → text2 → toolCall2 → toolResult2\n * becomes:\n * assistant: {content: \"text1\", toolCalls: [toolCall1]}\n * tool: toolResult1\n * assistant: {content: \"text2\", toolCalls: [toolCall2]}\n * tool: toolResult2\n *\n * @param uiMessage - The UIMessage to convert\n * @returns An array of ModelMessages preserving part ordering\n */\nexport function uiMessageToModelMessages(\n uiMessage: UIMessage,\n): Array<ModelMessage> {\n // Skip system messages - they're handled via systemPrompts, not ModelMessages\n if (uiMessage.role === 'system') {\n return []\n }\n\n // For non-assistant messages (user), use the simpler path since they\n // don't have tool calls or tool results to interleave\n if (uiMessage.role !== 'assistant') {\n return [buildUserOrToolMessage(uiMessage)]\n }\n\n // For assistant messages, walk parts in order to preserve interleaving\n return buildAssistantMessages(uiMessage)\n}\n\n/**\n * Build a single ModelMessage for user messages (simple path).\n * Preserves ordering of text and multimodal content parts.\n */\nfunction buildUserOrToolMessage(uiMessage: UIMessage): ModelMessage {\n const contentParts: Array<ContentPart> = []\n for (const part of uiMessage.parts) {\n if (isContentPart(part)) {\n contentParts.push(part)\n }\n }\n\n return {\n role: uiMessage.role as 'user' | 'assistant' | 'tool',\n content: collapseContentParts(contentParts),\n }\n}\n\n// Accumulator for building an assistant segment (content + tool calls)\ninterface AssistantSegment {\n contentParts: Array<ContentPart>\n toolCalls: Array<{\n id: string\n type: 'function'\n function: { name: string; arguments: string }\n }>\n}\n\nfunction createSegment(): AssistantSegment {\n return { contentParts: [], toolCalls: [] }\n}\n\nfunction isToolCallIncluded(part: ToolCallPart): boolean {\n return (\n part.state === 'input-complete' ||\n part.state === 'approval-responded' ||\n part.output !== undefined\n )\n}\n\n/**\n * Build ModelMessages for an assistant UIMessage, preserving the\n * sequential interleaving of text, tool calls, and tool results.\n *\n * Walks parts in order. Text and tool-call parts accumulate into the\n * current \"segment\". When a tool-result part is encountered, the\n * current segment is flushed as an assistant message, then the tool\n * result is emitted as a tool message.\n */\nfunction buildAssistantMessages(uiMessage: UIMessage): Array<ModelMessage> {\n const messageList: Array<ModelMessage> = []\n let current = createSegment()\n let pendingThinking: Array<{ content: string; signature?: string }> = []\n\n // Track emitted tool result IDs to avoid duplicates.\n // A tool call can have BOTH an explicit tool-result part AND an output\n // field on the tool-call part. We only want one per tool call ID.\n const emittedToolResultIds = new Set<string>()\n\n function flushSegment(): void {\n const content = collapseContentParts(current.contentParts)\n const hasContent = content !== null\n const hasToolCalls = current.toolCalls.length > 0\n\n if (hasContent || hasToolCalls) {\n messageList.push({\n role: 'assistant',\n content,\n ...(hasToolCalls && { toolCalls: current.toolCalls }),\n ...(pendingThinking.length > 0 && { thinking: pendingThinking }),\n })\n pendingThinking = []\n }\n current = createSegment()\n }\n\n for (const part of uiMessage.parts) {\n switch (part.type) {\n case 'text':\n case 'image':\n case 'audio':\n case 'video':\n case 'document':\n current.contentParts.push(part)\n break\n\n case 'tool-call':\n if (isToolCallIncluded(part)) {\n current.toolCalls.push({\n id: part.id,\n type: 'function' as const,\n function: {\n name: part.name,\n arguments: part.arguments,\n },\n })\n }\n break\n\n case 'tool-result':\n // Flush the current assistant segment before emitting the tool result\n flushSegment()\n\n // Emit the tool result\n if (\n (part.state === 'complete' || part.state === 'error') &&\n !emittedToolResultIds.has(part.toolCallId)\n ) {\n messageList.push({\n role: 'tool',\n content: part.content,\n toolCallId: part.toolCallId,\n })\n emittedToolResultIds.add(part.toolCallId)\n }\n break\n\n case 'thinking':\n if (part.content) {\n pendingThinking.push({\n content: part.content,\n ...(part.signature && { signature: part.signature }),\n })\n }\n break\n\n default:\n break\n }\n }\n\n // Flush any remaining accumulated content\n flushSegment()\n\n // Emit tool results from client tool-call parts with output or approval,\n // but only if not already covered by an explicit tool-result part above.\n // These are appended at the end since they don't have explicit tool-result\n // parts in the parts array to trigger inline emission.\n for (const part of uiMessage.parts) {\n if (part.type !== 'tool-call') continue\n\n // Output takes priority — if the tool has already produced a result,\n // emit the concrete output regardless of approval metadata.\n if (part.output !== undefined && !emittedToolResultIds.has(part.id)) {\n messageList.push({\n role: 'tool',\n content: JSON.stringify(part.output),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n\n // Approval response without output — emit approval status for iteration tracking\n if (\n part.output === undefined &&\n part.state === 'approval-responded' &&\n part.approval?.approved !== undefined &&\n !emittedToolResultIds.has(part.id)\n ) {\n const approved = part.approval.approved\n messageList.push({\n role: 'tool',\n content: JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n }),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n }\n\n // If no messages were produced (e.g., empty parts), emit a minimal assistant message\n if (messageList.length === 0) {\n messageList.push({\n role: 'assistant',\n content: null,\n })\n }\n\n return messageList\n}\n\n/**\n * Convert a ModelMessage to UIMessage\n *\n * This conversion creates a parts-based structure:\n * - content field → TextPart\n * - toolCalls array → ToolCallPart[]\n * - role=\"tool\" messages should be converted separately and merged\n *\n * @param modelMessage - The ModelMessage to convert\n * @param id - Optional ID for the UIMessage (generated if not provided)\n * @returns A UIMessage with parts\n */\nexport function modelMessageToUIMessage(\n modelMessage: ModelMessage,\n id?: string,\n): UIMessage {\n const parts: Array<MessagePart> = []\n\n if (modelMessage.role === 'assistant' && modelMessage.thinking?.length) {\n for (const thinking of modelMessage.thinking) {\n if (!thinking.content) continue\n parts.push({\n type: 'thinking',\n content: thinking.content,\n ...(thinking.signature && { signature: thinking.signature }),\n })\n }\n }\n\n // Handle tool results (when role is \"tool\") - only produce tool-result part,\n // not a text part (the content IS the tool result, not display text)\n if (modelMessage.role === 'tool' && modelMessage.toolCallId) {\n parts.push({\n type: 'tool-result',\n toolCallId: modelMessage.toolCallId,\n content: getTextContent(modelMessage.content),\n state: 'complete',\n })\n } else if (Array.isArray(modelMessage.content)) {\n // Multimodal content - preserve all content parts as MessageParts\n for (const part of modelMessage.content) {\n parts.push(part)\n }\n } else {\n // String or null content\n const textContent = getTextContent(modelMessage.content)\n if (textContent) {\n parts.push({\n type: 'text',\n content: textContent,\n })\n }\n }\n\n // Handle tool calls\n if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) {\n for (const toolCall of modelMessage.toolCalls) {\n parts.push({\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n state: 'input-complete', // Model messages have complete arguments\n })\n }\n }\n\n return {\n id: id || generateMessageId(),\n role: modelMessage.role === 'tool' ? 'assistant' : modelMessage.role,\n parts,\n }\n}\n\n/**\n * Convert an array of ModelMessages to UIMessages\n *\n * This handles merging tool result messages with their corresponding assistant messages\n *\n * @param modelMessages - Array of ModelMessages to convert\n * @returns Array of UIMessages\n */\nexport function modelMessagesToUIMessages(\n modelMessages: Array<ModelMessage>,\n): Array<UIMessage> {\n const uiMessages: Array<UIMessage> = []\n let currentAssistantMessage: UIMessage | null = null\n\n for (const msg of modelMessages) {\n if (msg.role === 'tool') {\n // Tool result - merge into the last assistant message if possible\n if (\n currentAssistantMessage &&\n currentAssistantMessage.role === 'assistant'\n ) {\n currentAssistantMessage.parts.push({\n type: 'tool-result',\n toolCallId: msg.toolCallId!,\n content: getTextContent(msg.content),\n state: 'complete',\n })\n } else {\n // No assistant message to merge into, create a standalone one\n const toolResultUIMessage = modelMessageToUIMessage(msg)\n uiMessages.push(toolResultUIMessage)\n }\n } else {\n // Regular message\n const uiMessage = modelMessageToUIMessage(msg)\n uiMessages.push(uiMessage)\n\n // Track assistant messages for potential tool result merging\n if (msg.role === 'assistant') {\n currentAssistantMessage = uiMessage\n } else {\n currentAssistantMessage = null\n }\n }\n }\n\n return uiMessages\n}\n\n/**\n * Normalize a message (UIMessage or ModelMessage) to a UIMessage\n * Ensures the message has an ID and createdAt timestamp\n *\n * @param message - Either a UIMessage or ModelMessage\n * @param generateId - Function to generate a message ID if needed\n * @returns A UIMessage with guaranteed id and createdAt\n */\nexport function normalizeToUIMessage(\n message: UIMessage | ModelMessage,\n generateId: () => string,\n): UIMessage {\n if ('parts' in message) {\n // Already a UIMessage\n return {\n ...message,\n id: message.id || generateId(),\n createdAt: message.createdAt || new Date(),\n }\n } else {\n // ModelMessage - convert to UIMessage\n return {\n ...modelMessageToUIMessage(message, generateId()),\n createdAt: new Date(),\n }\n }\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`\n}\n"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"messages.js","sources":["../../../../src/activities/chat/messages.ts"],"sourcesContent":["import type {\n ContentPart,\n MessagePart,\n ModelMessage,\n TextPart,\n ToolCallPart,\n UIMessage,\n} from '../../types'\n// ===========================\n// Message Converters\n// ===========================\n\n/**\n * Check if a MessagePart is a content part (text, image, audio, video, document)\n * that maps directly to a ModelMessage ContentPart.\n */\nfunction isContentPart(part: MessagePart): part is ContentPart {\n return (\n part.type === 'text' ||\n part.type === 'image' ||\n part.type === 'audio' ||\n part.type === 'video' ||\n part.type === 'document'\n )\n}\n\n/**\n * Collapse an array of ContentParts into the most compact ModelMessage content:\n * - Empty array → null\n * - All text parts → joined string (or null if empty)\n * - Mixed content → ContentPart array as-is\n */\nfunction collapseContentParts(\n parts: Array<ContentPart>,\n): string | null | Array<ContentPart> {\n if (parts.length === 0) return null\n\n const allText = parts.every((p) => p.type === 'text')\n if (allText) {\n const joined = parts.map((p) => p.content).join('')\n return joined || null\n }\n\n return parts\n}\n\n/**\n * Extract text content from ModelMessage content (string, null, or ContentPart array).\n * Used when only the text portion is needed (e.g., tool result content).\n */\nfunction getTextContent(content: string | null | Array<ContentPart>): string {\n if (content === null) return ''\n if (typeof content === 'string') return content\n return content\n .filter((part): part is TextPart => part.type === 'text')\n .map((part) => part.content)\n .join('')\n}\n\n/**\n * Convert UIMessages or ModelMessages to ModelMessages\n */\nexport function convertMessagesToModelMessages(\n messages: Array<UIMessage | ModelMessage>,\n): Array<ModelMessage> {\n const modelMessages: Array<ModelMessage> = []\n for (const msg of messages) {\n if ('parts' in msg) {\n // UIMessage - convert to ModelMessages\n modelMessages.push(...uiMessageToModelMessages(msg))\n } else {\n // Already ModelMessage\n modelMessages.push(msg)\n }\n }\n return modelMessages\n}\n\n/**\n * Convert a UIMessage to ModelMessage(s)\n *\n * Walks the parts array IN ORDER to preserve the interleaving of text,\n * tool calls, and tool results. This is critical for multi-round tool\n * flows where the model generates text, calls a tool, gets the result,\n * then generates more text and calls another tool.\n *\n * The output preserves the sequential structure:\n * text1 → toolCall1 → toolResult1 → text2 → toolCall2 → toolResult2\n * becomes:\n * assistant: {content: \"text1\", toolCalls: [toolCall1]}\n * tool: toolResult1\n * assistant: {content: \"text2\", toolCalls: [toolCall2]}\n * tool: toolResult2\n *\n * @param uiMessage - The UIMessage to convert\n * @returns An array of ModelMessages preserving part ordering\n */\nexport function uiMessageToModelMessages(\n uiMessage: UIMessage,\n): Array<ModelMessage> {\n // Skip system messages - they're handled via systemPrompts, not ModelMessages\n if (uiMessage.role === 'system') {\n return []\n }\n\n // For non-assistant messages (user), use the simpler path since they\n // don't have tool calls or tool results to interleave\n if (uiMessage.role !== 'assistant') {\n return [buildUserOrToolMessage(uiMessage)]\n }\n\n // For assistant messages, walk parts in order to preserve interleaving\n return buildAssistantMessages(uiMessage)\n}\n\n/**\n * Build a single ModelMessage for user messages (simple path).\n * Preserves ordering of text and multimodal content parts.\n */\nfunction buildUserOrToolMessage(uiMessage: UIMessage): ModelMessage {\n const contentParts: Array<ContentPart> = []\n for (const part of uiMessage.parts) {\n if (isContentPart(part)) {\n contentParts.push(part)\n }\n }\n\n return {\n role: uiMessage.role as 'user' | 'assistant' | 'tool',\n content: collapseContentParts(contentParts),\n }\n}\n\n// Accumulator for building an assistant segment (content + tool calls)\ninterface AssistantSegment {\n contentParts: Array<ContentPart>\n toolCalls: Array<{\n id: string\n type: 'function'\n function: { name: string; arguments: string }\n /** Provider-specific metadata that round-trips with the tool call.\n * Untyped at this framework layer; adapters narrow it via their\n * `TToolCallMetadata` generic. */\n metadata?: unknown\n }>\n}\n\nfunction createSegment(): AssistantSegment {\n return { contentParts: [], toolCalls: [] }\n}\n\nfunction isToolCallIncluded(part: ToolCallPart): boolean {\n return (\n part.state === 'input-complete' ||\n part.state === 'approval-responded' ||\n part.output !== undefined\n )\n}\n\n/**\n * Build ModelMessages for an assistant UIMessage, preserving the\n * sequential interleaving of text, tool calls, and tool results.\n *\n * Walks parts in order. Text and tool-call parts accumulate into the\n * current \"segment\". When a tool-result part is encountered, the\n * current segment is flushed as an assistant message, then the tool\n * result is emitted as a tool message.\n */\nfunction buildAssistantMessages(uiMessage: UIMessage): Array<ModelMessage> {\n const messageList: Array<ModelMessage> = []\n let current = createSegment()\n let pendingThinking: Array<{ content: string; signature?: string }> = []\n\n // Track emitted tool result IDs to avoid duplicates.\n // A tool call can have BOTH an explicit tool-result part AND an output\n // field on the tool-call part. We only want one per tool call ID.\n const emittedToolResultIds = new Set<string>()\n\n function flushSegment(): void {\n const content = collapseContentParts(current.contentParts)\n const hasContent = content !== null\n const hasToolCalls = current.toolCalls.length > 0\n\n if (hasContent || hasToolCalls) {\n messageList.push({\n role: 'assistant',\n content,\n ...(hasToolCalls && { toolCalls: current.toolCalls }),\n ...(pendingThinking.length > 0 && { thinking: pendingThinking }),\n })\n pendingThinking = []\n }\n current = createSegment()\n }\n\n for (const part of uiMessage.parts) {\n switch (part.type) {\n case 'text':\n case 'image':\n case 'audio':\n case 'video':\n case 'document':\n current.contentParts.push(part)\n break\n\n case 'tool-call':\n if (isToolCallIncluded(part)) {\n current.toolCalls.push({\n id: part.id,\n type: 'function' as const,\n function: {\n name: part.name,\n arguments: part.arguments,\n },\n ...(part.metadata !== undefined && { metadata: part.metadata }),\n })\n }\n break\n\n case 'tool-result':\n // Flush the current assistant segment before emitting the tool result\n flushSegment()\n\n // Emit the tool result\n if (\n (part.state === 'complete' || part.state === 'error') &&\n !emittedToolResultIds.has(part.toolCallId)\n ) {\n messageList.push({\n role: 'tool',\n content: part.content,\n toolCallId: part.toolCallId,\n })\n emittedToolResultIds.add(part.toolCallId)\n }\n break\n\n case 'thinking':\n if (part.content) {\n pendingThinking.push({\n content: part.content,\n ...(part.signature && { signature: part.signature }),\n })\n }\n break\n\n default:\n break\n }\n }\n\n // Flush any remaining accumulated content\n flushSegment()\n\n // Emit tool results from client tool-call parts with output or approval,\n // but only if not already covered by an explicit tool-result part above.\n // These are appended at the end since they don't have explicit tool-result\n // parts in the parts array to trigger inline emission.\n for (const part of uiMessage.parts) {\n if (part.type !== 'tool-call') continue\n\n // Output takes priority — if the tool has already produced a result,\n // emit the concrete output regardless of approval metadata.\n if (part.output !== undefined && !emittedToolResultIds.has(part.id)) {\n messageList.push({\n role: 'tool',\n content: JSON.stringify(part.output),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n\n // Approval response without output — emit approval status for iteration tracking\n if (\n part.output === undefined &&\n part.state === 'approval-responded' &&\n part.approval?.approved !== undefined &&\n !emittedToolResultIds.has(part.id)\n ) {\n const approved = part.approval.approved\n messageList.push({\n role: 'tool',\n content: JSON.stringify({\n approved,\n ...(approved && { pendingExecution: true }),\n message: approved\n ? 'User approved this action'\n : 'User denied this action',\n }),\n toolCallId: part.id,\n })\n emittedToolResultIds.add(part.id)\n }\n }\n\n // If no messages were produced (e.g., empty parts), emit a minimal assistant message\n if (messageList.length === 0) {\n messageList.push({\n role: 'assistant',\n content: null,\n })\n }\n\n return messageList\n}\n\n/**\n * Convert a ModelMessage to UIMessage\n *\n * This conversion creates a parts-based structure:\n * - content field → TextPart\n * - toolCalls array → ToolCallPart[]\n * - role=\"tool\" messages should be converted separately and merged\n *\n * @param modelMessage - The ModelMessage to convert\n * @param id - Optional ID for the UIMessage (generated if not provided)\n * @returns A UIMessage with parts\n */\nexport function modelMessageToUIMessage(\n modelMessage: ModelMessage,\n id?: string,\n): UIMessage {\n const parts: Array<MessagePart> = []\n\n if (modelMessage.role === 'assistant' && modelMessage.thinking?.length) {\n for (const thinking of modelMessage.thinking) {\n if (!thinking.content) continue\n parts.push({\n type: 'thinking',\n content: thinking.content,\n ...(thinking.signature && { signature: thinking.signature }),\n })\n }\n }\n\n // Handle tool results (when role is \"tool\") - only produce tool-result part,\n // not a text part (the content IS the tool result, not display text)\n if (modelMessage.role === 'tool' && modelMessage.toolCallId) {\n parts.push({\n type: 'tool-result',\n toolCallId: modelMessage.toolCallId,\n content: getTextContent(modelMessage.content),\n state: 'complete',\n })\n } else if (Array.isArray(modelMessage.content)) {\n // Multimodal content - preserve all content parts as MessageParts\n for (const part of modelMessage.content) {\n parts.push(part)\n }\n } else {\n // String or null content\n const textContent = getTextContent(modelMessage.content)\n if (textContent) {\n parts.push({\n type: 'text',\n content: textContent,\n })\n }\n }\n\n // Handle tool calls\n if (modelMessage.toolCalls && modelMessage.toolCalls.length > 0) {\n for (const toolCall of modelMessage.toolCalls) {\n parts.push({\n type: 'tool-call',\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: toolCall.function.arguments,\n state: 'input-complete', // Model messages have complete arguments\n ...(toolCall.metadata !== undefined && { metadata: toolCall.metadata }),\n })\n }\n }\n\n return {\n id: id || generateMessageId(),\n role: modelMessage.role === 'tool' ? 'assistant' : modelMessage.role,\n parts,\n }\n}\n\n/**\n * Convert an array of ModelMessages to UIMessages\n *\n * This handles merging tool result messages with their corresponding assistant messages\n *\n * @param modelMessages - Array of ModelMessages to convert\n * @returns Array of UIMessages\n */\nexport function modelMessagesToUIMessages(\n modelMessages: Array<ModelMessage>,\n): Array<UIMessage> {\n const uiMessages: Array<UIMessage> = []\n let currentAssistantMessage: UIMessage | null = null\n\n for (const msg of modelMessages) {\n if (msg.role === 'tool') {\n // Tool result - merge into the last assistant message if possible\n if (\n currentAssistantMessage &&\n currentAssistantMessage.role === 'assistant'\n ) {\n currentAssistantMessage.parts.push({\n type: 'tool-result',\n toolCallId: msg.toolCallId!,\n content: getTextContent(msg.content),\n state: 'complete',\n })\n } else {\n // No assistant message to merge into, create a standalone one\n const toolResultUIMessage = modelMessageToUIMessage(msg)\n uiMessages.push(toolResultUIMessage)\n }\n } else {\n // Regular message\n const uiMessage = modelMessageToUIMessage(msg)\n uiMessages.push(uiMessage)\n\n // Track assistant messages for potential tool result merging\n if (msg.role === 'assistant') {\n currentAssistantMessage = uiMessage\n } else {\n currentAssistantMessage = null\n }\n }\n }\n\n return uiMessages\n}\n\n/**\n * Normalize a message (UIMessage or ModelMessage) to a UIMessage\n * Ensures the message has an ID and createdAt timestamp\n *\n * @param message - Either a UIMessage or ModelMessage\n * @param generateId - Function to generate a message ID if needed\n * @returns A UIMessage with guaranteed id and createdAt\n */\nexport function normalizeToUIMessage(\n message: UIMessage | ModelMessage,\n generateId: () => string,\n): UIMessage {\n if ('parts' in message) {\n // Already a UIMessage\n return {\n ...message,\n id: message.id || generateId(),\n createdAt: message.createdAt || new Date(),\n }\n } else {\n // ModelMessage - convert to UIMessage\n return {\n ...modelMessageToUIMessage(message, generateId()),\n createdAt: new Date(),\n }\n }\n}\n\n/**\n * Generate a unique message ID\n */\nexport function generateMessageId(): string {\n return `msg-${Date.now()}-${Math.random().toString(36).substring(7)}`\n}\n"],"names":[],"mappings":"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"}
@@ -15,6 +15,7 @@ export declare function updateToolCallPart(messages: Array<UIMessage>, messageId
15
15
  name: string;
16
16
  arguments: string;
17
17
  state: ToolCallState;
18
+ metadata?: Record<string, unknown>;
18
19
  }): Array<UIMessage>;
19
20
  /**
20
21
  * Update or add a tool result part to a message.
@@ -22,6 +22,7 @@ function updateToolCallPart(messages, messageId, toolCall) {
22
22
  const existing = parts.find(
23
23
  (p) => p.type === "tool-call" && p.id === toolCall.id
24
24
  );
25
+ const metadata = toolCall.metadata ?? existing?.metadata;
25
26
  const toolCallPart = {
26
27
  type: "tool-call",
27
28
  id: toolCall.id,
@@ -30,7 +31,8 @@ function updateToolCallPart(messages, messageId, toolCall) {
30
31
  state: toolCall.state,
31
32
  // Carry forward approval and output from the existing part
32
33
  ...existing?.approval && { approval: { ...existing.approval } },
33
- ...existing?.output !== void 0 && { output: existing.output }
34
+ ...existing?.output !== void 0 && { output: existing.output },
35
+ ...metadata !== void 0 && { metadata }
34
36
  };
35
37
  if (existing) {
36
38
  parts[parts.indexOf(existing)] = toolCallPart;