@tanstack/ai 0.41.0 → 0.42.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.
@@ -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 { undoNullWidening } from '@tanstack/ai-utils'\nimport { stripToSpecMiddleware } from '../../strip-to-spec-middleware'\nimport { streamToText } from '../../stream-to-response.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport { EventType } from '../../types'\nimport { normalizeToolResult } from '../../utilities/tool-result'\nimport { isProviderExecutedToolCall } from '../../utilities/provider-executed'\nimport { LazyToolManager } from './tools/lazy-tool-manager'\nimport {\n MiddlewareAbortError,\n ToolCallManager,\n executeToolCalls,\n} from './tools/tool-calls'\nimport {\n convertSchemaForStructuredOutput,\n convertSchemaToJsonSchema,\n isStandardSchema,\n parseWithStandardSchema,\n} from './tools/schema-converter'\nimport { maxIterations as maxIterationsStrategy } from './agent-loop-strategies'\nimport { convertMessagesToModelMessages, generateMessageId } from './messages'\nimport { MiddlewareRunner } from './middleware/compose'\nimport { provideSandboxRuntime } from './middleware/sandbox-runtime'\nimport { CapabilityRegistry } from './middleware/capabilities'\nimport { validateCapabilities } from './middleware/validate'\nimport { MCPManager } from './mcp/manager'\nimport type {\n ApprovalRequest,\n ClientToolRequest,\n ToolResult,\n} from './tools/tool-calls'\nimport type {\n AnyTextAdapter,\n StructuredOutputOptions,\n StructuredOutputResult,\n} from './adapter'\nimport type {\n AgentLoopStrategy,\n AnyTool,\n ChatStream,\n ConstrainedModelMessage,\n CustomEvent,\n InferSchemaType,\n JSONSchema,\n LazyToolsConfig,\n ModelMessage,\n RunFinishedEvent,\n SchemaInput,\n StreamChunk,\n StructuredOutputCompleteEvent,\n StructuredOutputStream,\n TextMessageContentEvent,\n TextOptions,\n ToolCall,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallStartEvent,\n UIMessage,\n} from '../../types'\nimport type {\n AnyChatMiddleware,\n ChatMiddleware,\n ChatMiddlewareConfig,\n ChatMiddlewareContext,\n SandboxFileHookEvent,\n StructuredOutputMiddlewareConfig,\n} from './middleware/types'\nimport type { CheckCoverage } from './middleware/builder'\nimport type { SystemPrompt } from '../../system-prompts'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { ProviderTool } from '../../tools/provider-tool'\nimport type {\n ContextFromMiddleware,\n ContextFromTool,\n DefinedContext,\n MergeContext,\n UnionToIntersection,\n} from './runtime-context-types'\nimport type { ChatMCPOptions } from './mcp/types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'text' as const\n\ntype AnyRuntimeTool = AnyTool\n\n// The leaf context-inference primitives (KnownContext, MergeContext,\n// UnionToIntersection, DefinedContext, ContextFromTool, ContextFromMiddleware)\n// are shared with the tool execution layer — see ./runtime-context-types.\ntype ContextFromConsumer<T> = ContextFromTool<T> | ContextFromMiddleware<T>\n\ntype RequiredContextFromConsumerUnion<T> = T extends unknown\n ? undefined extends ContextFromConsumer<T>\n ? never\n : ContextFromConsumer<T>\n : never\n\ntype ContextFromConsumerUnion<T> = [\n UnionToIntersection<DefinedContext<ContextFromConsumer<T>>>,\n] extends [never]\n ? never\n : [RequiredContextFromConsumerUnion<T>] extends [never]\n ? UnionToIntersection<DefinedContext<ContextFromConsumer<T>>> | undefined\n : UnionToIntersection<DefinedContext<ContextFromConsumer<T>>>\n\ntype ContextFromArray<T> = T extends readonly [infer THead, ...infer TTail]\n ? MergeContext<ContextFromConsumer<THead>, ContextFromArray<TTail>>\n : T extends ReadonlyArray<infer TItem>\n ? ContextFromConsumerUnion<TItem>\n : never\n\ntype ContextFromInputs<TTools, TMiddleware> = MergeContext<\n ContextFromArray<NonNullable<TTools>>,\n ContextFromArray<NonNullable<TMiddleware>>\n>\n\ntype InferredContext<TTools, TMiddleware> = [\n ContextFromInputs<TTools, TMiddleware>,\n] extends [never]\n ? unknown\n : ContextFromInputs<TTools, TMiddleware>\n\ntype RequiredContextFromInputs<TTools, TMiddleware> = [\n ContextFromInputs<TTools, TMiddleware>,\n] extends [never]\n ? { context?: unknown }\n : undefined extends ContextFromInputs<TTools, TMiddleware>\n ? { context?: ContextFromInputs<TTools, TMiddleware> }\n : { context: ContextFromInputs<TTools, TMiddleware> }\n\ntype TextActivityOptionsWithContext<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined,\n TStream extends boolean,\n TTools extends TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'],\n TMiddleware extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'],\n> = Omit<\n TextActivityOptions<TAdapter, TSchema, TStream, any>,\n 'tools' | 'middleware' | 'context'\n> & {\n tools?: TTools\n middleware?: TMiddleware &\n CheckCoverage<Extract<TMiddleware, ReadonlyArray<AnyChatMiddleware>>>\n} & RequiredContextFromInputs<TTools, TMiddleware>\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 TContext = unknown,\n> {\n /** The text adapter to use (created by a provider function like openaiText('gpt-4o')) */\n adapter: TAdapter\n /**\n * Conversation messages. Accepts:\n * - `ConstrainedModelMessage` — content types constrained by the adapter's input modalities.\n * - `ModelMessage` — unconstrained model message (e.g., forwarded from an AG-UI wire payload).\n * - `UIMessage` — parts-based UI representation; converted internally via `convertMessagesToModelMessages`.\n *\n * The three shapes can be mixed in a single array (e.g., when forwarding a wire payload that includes both anchor UIMessages and AG-UI fan-out ModelMessages).\n */\n messages?:\n | Array<\n | UIMessage\n | ModelMessage\n | ConstrainedModelMessage<{\n inputModalities: TAdapter['~types']['inputModalities']\n messageMetadataByModality: TAdapter['~types']['messageMetadataByModality']\n }>\n >\n | undefined\n /**\n * System prompts to prepend to the conversation.\n *\n * Accepts plain strings or `{ content, metadata }` objects. The `metadata`\n * field is typed by the adapter — Anthropic narrows it to\n * `AnthropicSystemPromptMetadata` (with `cache_control` for prompt\n * caching), providers without per-prompt metadata reject the field\n * entirely.\n */\n systemPrompts?:\n | Array<SystemPrompt<TAdapter['~types']['systemPromptMetadata']>>\n | undefined\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?:\n | Array<\n | (AnyRuntimeTool & { readonly '~toolKind'?: never })\n | ProviderTool<string, TAdapter['~types']['toolCapabilities'][number]>\n >\n | undefined\n /**\n * Hand MCP clients/pools to chat(): their tools are discovered at run start\n * and merged into the run; `connection` controls whether chat() closes them\n * when the run ends. See docs/tools/mcp.md \"Managing MCP clients with chat()\".\n */\n mcp?: ChatMCPOptions\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 /**\n * Optional configuration for lazy-tool discovery (tools marked `lazy: true`).\n * Tunes how much of each lazy tool's description appears in the discovery\n * catalog. Optional — defaults to `{ includeDescription: 'none' }`.\n */\n lazyToolsConfig?: LazyToolsConfig\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 /** Parent run ID for AG-UI protocol nested run correlation. */\n parentRunId?: TextOptions['parentRunId']\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<TContext>>\n /**\n * Runtime context value passed to middleware hooks and server tools.\n */\n context?: TContext\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 const TTools extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['tools'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'],\n const TMiddleware extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'] = TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'],\n>(\n options: TextActivityOptionsWithContext<\n TAdapter,\n TSchema,\n TStream,\n TTools,\n TMiddleware\n >,\n): TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n InferredContext<TTools, TMiddleware>\n> {\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 : ChatStream\n\n// ===========================\n// ChatEngine Implementation\n// ===========================\n\ninterface TextEngineConfig<\n TAdapter extends AnyTextAdapter,\n TContext = unknown,\n TParams extends TextOptions<any, any, TContext> = TextOptions<\n any,\n any,\n TContext\n >,\n> {\n adapter: TAdapter\n systemPrompts?: Array<SystemPrompt>\n params: TParams\n middleware?: Array<ChatMiddleware<TContext>>\n context?: TContext\n /**\n * If set, after the agent loop finishes the engine runs a\n * structured-output finalization step through the same middleware\n * pipeline. See `runStructuredFinalization` for the flow.\n *\n * - jsonSchema: the JSON Schema to send to the provider\n * - yieldChunks: when true, finalization chunks are yielded to the caller\n * (used by runStreamingStructuredOutput). When false, chunks are\n * consumed internally for middleware visibility but not yielded\n * (used by runAgenticStructuredOutput).\n * - normalize: optional schema-aware transform applied to the captured\n * structured-output object the moment it enters the engine — BEFORE it is\n * stored, validated, or yielded. Used to undo strict-mode null-widening\n * (`undoNullWidening`): strict schemas widen optional fields to\n * `required` + nullable so the provider returns `null` for an absent\n * optional, and this strips exactly those synthesized nulls while keeping\n * the ones a `.nullable()` field genuinely allows. Applied here (not in\n * the adapter) because the engine is the only layer holding the original\n * schema's null-widening map, and applying it at capture fixes BOTH the\n * streaming chunk and the Promise<T> result with one transform.\n * - validate: optional callback invoked AFTER `normalize` and AFTER the\n * structured-output result is captured, but BEFORE the terminal hook\n * fires. If it throws, the engine records a `finalizationError` and fires\n * `onError` instead of `onFinish` (per spec §7.3). On success, the\n * returned value is stored as the validated result and retrievable via\n * `getValidatedStructuredOutput()`. Used by `runAgenticStructuredOutput`\n * to perform Standard Schema validation inside the engine.\n * - nativeCombined: when true, the adapter declared\n * `supportsCombinedToolsAndSchema()` and the engine wires `jsonSchema`\n * into the regular `chatStream` call instead of running a separate\n * finalization round-trip. The agent loop's final-turn text is the\n * schema-constrained JSON; the engine parses it from accumulated\n * content. The `'structuredOutput'` middleware phase does NOT fire on\n * this path — middleware sees the run through `beforeModel` /\n * `modelStream` as usual.\n */\n finalStructuredOutput?: {\n jsonSchema: JSONSchema\n yieldChunks: boolean\n normalize?: (data: unknown) => unknown\n validate?: (data: unknown) => unknown\n nativeCombined?: boolean\n }\n}\n\ntype ToolPhaseResult = 'continue' | 'stop' | 'wait'\ntype CyclePhase = 'processText' | 'executeToolCalls'\n\n/**\n * Combine two optional AbortSignals into one that aborts when either does.\n * Returns the other signal directly when one is absent or already aborted.\n * (Manual implementation — `AbortSignal.any` requires Node >= 20.3.)\n */\nfunction combineAbortSignals(\n a: AbortSignal | undefined,\n b: AbortSignal | undefined,\n): AbortSignal | undefined {\n if (!a) return b\n if (!b) return a\n if (a.aborted) return a\n if (b.aborted) return b\n const controller = new AbortController()\n const onAbort = (source: AbortSignal) => () => {\n controller.abort(source.reason)\n }\n a.addEventListener('abort', onAbort(a), { once: true })\n b.addEventListener('abort', onAbort(b), { once: true })\n return controller.signal\n}\n\nclass TextEngine<\n TAdapter extends AnyTextAdapter,\n TContext = unknown,\n TParams extends TextOptions<any, any, TContext> = TextOptions<\n any,\n any,\n TContext\n >,\n> {\n private readonly adapter: TAdapter\n private params: TParams\n private systemPrompts: Array<SystemPrompt>\n private tools: Array<AnyRuntimeTool>\n private readonly loopStrategy: AgentLoopStrategy\n private toolCallManager: ToolCallManager<ReadonlyArray<AnyTool>, TContext>\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> | undefined\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 readonly threadId: string\n private readonly runIdOverride?: string\n private readonly parentRunIdOverride?: string\n\n // Middleware support\n private readonly middlewareRunner: MiddlewareRunner<TContext>\n private readonly middlewareCtx: ChatMiddlewareContext<TContext>\n private readonly sandboxFileQueue: Array<StreamChunk> = []\n private readonly deferredPromises: Array<Promise<unknown>> = []\n private abortReason?: string\n private readonly middlewareAbortController?: AbortController\n // Combines the caller's signal with middleware abort() so running tools\n // observe both cancellation sources via ctx.abortSignal.\n private readonly toolAbortSignal?: AbortSignal\n private terminalHookCalled = false\n\n private readonly logger: InternalLogger\n\n // Structured-output finalization state (populated by runStructuredFinalization)\n private structuredOutputResult: { data: unknown; rawText: string } | null =\n null\n // Native combined mode: tracks whether we've already emitted the synthetic\n // `structured-output.start` event before the schema-constrained final-turn\n // text begins streaming. The event must precede the first\n // TEXT_MESSAGE_START so the client-side StreamProcessor routes the JSON\n // deltas into a StructuredOutputPart instead of a plain TextPart.\n private combinedStartEmitted = false\n // Native combined mode: messageId we want the synthetic\n // `structured-output.start` (and any error emitted before deltas arrive)\n // to carry, so the client matches it to the streaming text deltas.\n private combinedStructuredMessageId: string | null = null\n // Holds the validated value when `finalStructuredOutput.validate` is provided\n // and succeeds. Distinct from `structuredOutputResult.data` (the normalized\n // but unvalidated payload from the structured-output.complete chunk).\n private validatedStructuredOutput: unknown = undefined\n private hasValidatedStructuredOutput = false\n private finalizationError: {\n message: string\n code?: string\n cause?: unknown\n } | null = null\n private readonly finalStructuredOutput?: {\n jsonSchema: JSONSchema\n yieldChunks: boolean\n normalize?: (data: unknown) => unknown\n validate?: (data: unknown) => unknown\n nativeCombined?: boolean\n }\n\n constructor(\n config: TextEngineConfig<TAdapter, TContext, TParams>,\n logger: InternalLogger,\n ) {\n this.logger = logger\n this.adapter = config.adapter\n this.finalStructuredOutput = config.finalStructuredOutput\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(config.params.messages)\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 config.params.lazyToolsConfig,\n )\n this.tools = this.lazyToolManager.getActiveTools()\n this.toolCallManager = new ToolCallManager<\n ReadonlyArray<AnyTool>,\n TContext\n >(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 // `conversationId` is the legacy alias of `threadId` — accept it\n // as a fallback so `chat({ conversationId })` keeps working, with\n // explicit `threadId` winning when both are set.\n this.threadId =\n config.params.threadId ||\n config.params.conversationId ||\n this.createId('thread')\n this.runIdOverride = config.params.runId\n this.parentRunIdOverride = config.params.parentRunId\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: Array<ChatMiddleware<TContext>> = [\n devtoolsMiddleware(),\n ...(config.middleware || []),\n stripToSpecMiddleware(),\n ]\n this.middlewareRunner = new MiddlewareRunner(allMiddleware, logger)\n this.middlewareAbortController = new AbortController()\n this.toolAbortSignal = combineAbortSignals(\n this.effectiveSignal,\n this.middlewareAbortController.signal,\n )\n this.middlewareCtx = {\n requestId: this.requestId,\n streamId: this.streamId,\n runId: this.runIdOverride ?? this.requestId,\n threadId: this.threadId,\n // Legacy alias kept on the ctx so middleware that reads\n // `ctx.conversationId` keeps working. Always equals `threadId`.\n conversationId: this.threadId,\n phase: 'init',\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 as TContext,\n defer: (promise: Promise<unknown>) => {\n this.deferredPromises.push(promise)\n },\n // Provider / adapter info\n activity: 'chat',\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 // Capability bookkeeping for this request (populated by middleware setup)\n capabilities: new CapabilityRegistry(),\n // Convenience accessors that delegate to a capability handle's own\n // tuple getter/provider, keyed by this context. `getX(ctx)` and\n // `ctx.get(X)` are interchangeable.\n get: (capability) => capability[0](this.middlewareCtx),\n getOptional: (capability) =>\n capability[0](this.middlewareCtx, { optional: true }),\n provide: (capability, value) => capability[1](this.middlewareCtx, value),\n }\n\n // Provide the internal SandboxRuntime capability so harness adapters and\n // sandbox middleware can emit file events. The sink logs, fans the event\n // out through the middleware `onFile*` hooks (fire-and-forget), and queues\n // a `sandbox.file` custom chunk to be drained into the public stream.\n provideSandboxRuntime(this.middlewareCtx, {\n logger: this.logger,\n emit: (event: SandboxFileHookEvent) => {\n this.logger.sandbox(`file ${event.type} ${event.path}`, {\n event: {\n type: event.type,\n path: event.path,\n timestamp: event.timestamp,\n },\n })\n void this.middlewareRunner\n .runSandboxFile(this.middlewareCtx, event)\n .catch((err: unknown) => {\n this.logger.errors('sandbox file hook failed', { error: err })\n })\n this.sandboxFileQueue.push(\n this.createCustomEventChunk('sandbox.file', {\n type: event.type,\n path: event.path,\n timestamp: event.timestamp,\n }),\n )\n },\n emitFileDiff: (value: { path: string; diff: string }) => {\n this.sandboxFileQueue.push(\n this.createCustomEventChunk('sandbox.file.diff', value),\n )\n },\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 /** Returns the structured-output result if finalization ran successfully. */\n getStructuredOutputResult(): { data: unknown; rawText: string } | null {\n return this.structuredOutputResult\n }\n\n /**\n * Returns the validated structured-output value (the result of running\n * `finalStructuredOutput.validate` against the raw structured-output data)\n * wrapped in a `{ value }` object so callers can distinguish \"no validation\n * happened\" from \"validation produced undefined\". Returns `null` when no\n * validator was configured or validation hasn't been performed yet.\n */\n getValidatedStructuredOutput(): { value: unknown } | null {\n return this.hasValidatedStructuredOutput\n ? { value: this.validatedStructuredOutput }\n : null\n }\n\n /** Returns the recorded finalization error, if any. */\n getFinalizationError(): {\n message: string\n code?: string\n cause?: unknown\n } | null {\n return this.finalizationError\n }\n\n async *run(): AsyncGenerator<StreamChunk> {\n this.beforeRun()\n this.logger.agentLoop('run started', {\n threadId: this.middlewareCtx.threadId,\n })\n\n try {\n // Provision capabilities before any consumer (onConfig onward) can read them\n await this.middlewareRunner.runSetup(this.middlewareCtx)\n\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 // Skip the agent loop entirely when there are no tools AND a separate\n // structured-output finalization will run. Without tools the model has\n // nothing to do in the loop, so executing one iteration would burn an\n // extra provider call before the finalization request.\n //\n // Native combined mode does NOT skip — the agent loop itself produces\n // the schema-constrained final answer in one pass (model emits the\n // schema-constrained text on its natural final turn). Even with zero\n // tools, the single chatStream call IS the structured-output call.\n const skipAgentLoop =\n !!this.finalStructuredOutput &&\n this.tools.length === 0 &&\n this.finalStructuredOutput.nativeCombined !== true\n\n if (!skipAgentLoop) {\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 iterTransformedConfig =\n await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n iterConfig,\n )\n this.applyMiddlewareConfig(iterTransformedConfig)\n\n yield* this.streamModelResponse()\n } else {\n yield* this.processToolCalls()\n }\n\n this.endCycle()\n } while (this.shouldContinue())\n }\n\n this.logger.agentLoop('run finished', {\n finishReason: this.lastFinishReason,\n })\n\n // After the agent loop ends, if a structured-output finalization was\n // requested AND the run hasn't already errored/aborted, run it through\n // the middleware pipeline. The terminal hook fires once at the very\n // end (after finalization), not after the agent loop.\n //\n // Native combined mode takes a different path: the agent loop's final-\n // turn text IS the schema-constrained JSON, so we harvest it from\n // `accumulatedContent` instead of issuing a second provider call.\n if (\n this.finalStructuredOutput &&\n !this.isCancelled() &&\n !this.finalizationError\n ) {\n if (this.finalStructuredOutput.nativeCombined === true) {\n yield* this.harvestCombinedStructuredOutput()\n } else {\n yield* this.runStructuredFinalization()\n }\n }\n\n // Call terminal hook (skip when waiting for client — stream is paused, not finished).\n // Priority: finalizationError → onError; otherwise normal onFinish.\n // Skip on cancellation — the finally block routes aborts to onAbort.\n if (\n !this.terminalHookCalled &&\n this.toolPhase !== 'wait' &&\n !this.isCancelled()\n ) {\n if (this.finalizationError) {\n this.terminalHookCalled = true\n const errForHook = new Error(\n this.finalizationError.message,\n this.finalizationError.cause !== undefined\n ? { cause: this.finalizationError.cause }\n : undefined,\n )\n if (this.finalizationError.code !== undefined) {\n Object.defineProperty(errForHook, 'code', {\n value: this.finalizationError.code,\n enumerable: true,\n })\n }\n await this.middlewareRunner.runOnError(this.middlewareCtx, {\n error: errForHook,\n duration: Date.now() - this.streamStartTime,\n })\n } else {\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 }\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 threadId: this.middlewareCtx.threadId,\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, metadata } = this.params\n\n // Gather flattened options into an object for context\n const options: Record<string, unknown> = {}\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 { 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 // When the adapter declared `supportsCombinedToolsAndSchema()`, the\n // activity layer set `nativeCombined: true` and we forward the\n // pre-converted JSON Schema into the regular chatStream call. The\n // adapter wires it into the upstream request (e.g. `response_format`,\n // `text.format`, `output_format`) so the model's final-turn text is\n // schema-constrained and the engine can harvest it from the agent loop\n // without a separate finalization round-trip.\n const combinedSchema =\n this.finalStructuredOutput?.nativeCombined === true\n ? this.finalStructuredOutput.jsonSchema\n : undefined\n\n for await (const chunk of this.adapter.chatStream({\n model: this.params.model,\n messages: this.messages,\n tools: toolsWithJsonSchemas,\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 parentRunId: this.parentRunIdOverride,\n // Expose provided capabilities (e.g. sandbox) to harness adapters.\n capabilities: this.middlewareCtx,\n // Client approval decisions, for harness interactive-approval resolution.\n approvals: this.initialApprovals,\n ...(combinedSchema ? { outputSchema: combinedSchema } : {}),\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 // Native combined mode: synthesize `structured-output.start` BEFORE\n // the first TEXT_MESSAGE_START so the client-side StreamProcessor\n // routes the schema-constrained JSON deltas into a\n // StructuredOutputPart. We delay synthesis until we actually see\n // text starting — intermediate tool-call iterations don't need it,\n // and emitting at run-start would wrap tool-call commentary into a\n // structured-output part too.\n if (\n this.finalStructuredOutput?.nativeCombined === true &&\n this.finalStructuredOutput.yieldChunks &&\n !this.combinedStartEmitted &&\n chunk.type === EventType.TEXT_MESSAGE_START\n ) {\n this.combinedStartEmitted = true\n const messageId =\n typeof chunk.messageId === 'string' && chunk.messageId !== ''\n ? chunk.messageId\n : generateMessageId()\n this.combinedStructuredMessageId = messageId\n const synthStart: StreamChunk = {\n type: EventType.CUSTOM,\n name: 'structured-output.start',\n value: { messageId },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n const synthOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n synthStart,\n )\n for (const outputChunk of synthOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\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 // When a streaming structured-output finalization step will run after\n // the agent loop, suppress the agent-loop's RUN_STARTED/RUN_FINISHED\n // here — the finalization step emits the single outer lifecycle pair\n // that reaches the consumer.\n //\n // Native combined mode does NOT issue a second adapter stream — the\n // agent loop's lifecycle IS the outer pair the consumer sees.\n const suppressAgentLifecycle =\n !!this.finalStructuredOutput &&\n this.finalStructuredOutput.yieldChunks &&\n this.finalStructuredOutput.nativeCombined !== true\n for (const outputChunk of outputChunks) {\n if (\n suppressAgentLifecycle &&\n (outputChunk.type === EventType.RUN_STARTED ||\n outputChunk.type === EventType.RUN_FINISHED)\n ) {\n continue\n }\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 // Drain any sandbox.file events emitted while processing this chunk.\n yield* this.drainSandboxFileQueue()\n\n if (this.earlyTermination) {\n break\n }\n }\n\n // Drain any remaining sandbox.file events emitted after the stream ended.\n yield* this.drainSandboxFileQueue()\n }\n\n private handleStreamChunk(chunk: StreamChunk): void {\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- AG-UI EventType enum members vs string-literal case labels; default branch handles untraced events.\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 /**\n * Tools available for execution this turn. The discovery tool is dropped\n * from the advertised set (`this.tools`) once every lazy tool is discovered,\n * but a model may still re-request discovery; this widens execution lookup\n * to include it so such calls don't fail with \"Unknown tool\". Centralised so\n * both execution sites (`processToolCalls` and `checkForPendingToolCalls`)\n * stay in sync.\n */\n private resolveExecutableTools(\n toolCalls: ReadonlyArray<ToolCall>,\n ): ReadonlyArray<AnyTool> {\n return this.lazyToolManager.getExecutableTools(\n this.tools,\n toolCalls.map((tc) => tc.function.name),\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.resolveExecutableTools(executablePendingCalls),\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 this.middlewareCtx.context,\n this.toolAbortSignal,\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 && this.finishedEvent) {\n for (const chunk of this.buildToolResultChunks(\n undiscoveredLazyResults,\n this.finishedEvent,\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.resolveExecutableTools(executableToolCalls),\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 this.middlewareCtx.context,\n this.toolAbortSignal,\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<\n ReadonlyArray<AnyTool>,\n TContext\n >(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\n // uiMessageToModelMessages). Multimodal results carry an\n // Array<ContentPart> directly — pass it through without parsing.\n let output: unknown\n if (Array.isArray(message.content)) {\n output = message.content\n } else {\n try {\n output = JSON.parse(message.content as string)\n } catch {\n output = message.content\n }\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 // `content` is the canonical value for the tool `ModelMessage` — it may\n // be an `Array<ContentPart>` (multimodal) which the adapters convert to\n // structured provider output on the next iteration. `wireContent` is the\n // string form emitted on the AG-UI stream events (TOOL_CALL_END.result /\n // TOOL_CALL_RESULT.content are string-only per the AG-UI spec); the\n // multimodal array travels via the message itself, not the wire event.\n const content = normalizeToolResult(result.result)\n const wireContent =\n typeof content === 'string' ? content : JSON.stringify(content)\n\n // argsMap is set only on continuation re-executions, where the adapter\n // never streamed these calls. Otherwise it already emitted END, so a\n // second one here would be an orphan that fails verifyEvents (#519).\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 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: wireContent,\n ...(result.state !== undefined && { state: result.state }),\n } as StreamChunk)\n }\n\n // AG-UI spec TOOL_CALL_RESULT event (content is string-only per spec)\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: wireContent,\n role: 'tool',\n ...(result.state !== undefined && { state: result.state }),\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 // Provider-executed tool calls (e.g. Anthropic `web_search`) were\n // already run by the provider; they carry no client result, so they\n // would otherwise look \"pending\" forever and the loop would try (and\n // fail) to execute them client-side. Skip them.\n if (isProviderExecutedToolCall(toolCall)) {\n continue\n }\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 /**\n * Run the final structured-output adapter call through the middleware\n * pipeline. Yields chunks to the caller only when\n * `this.finalStructuredOutput.yieldChunks` is true; otherwise consumes\n * silently while still piping through middleware.\n *\n * On success, populates this.structuredOutputResult.\n * On failure, populates this.finalizationError.\n */\n private async *runStructuredFinalization(): AsyncGenerator<StreamChunk> {\n if (!this.finalStructuredOutput) {\n throw new Error(\n 'runStructuredFinalization called without finalStructuredOutput config',\n )\n }\n\n this.middlewareCtx.phase = 'structuredOutput'\n\n // Build the structured-output config view. `tools` is intentionally\n // excluded from the type because it isn't forwarded to the structured-\n // output adapter call — including it here would be misleading API.\n const baseConfig = this.buildMiddlewareConfig()\n const { tools: _omitTools, ...baseWithoutTools } = baseConfig\n let structuredConfig: StructuredOutputMiddlewareConfig = {\n ...baseWithoutTools,\n outputSchema: this.finalStructuredOutput.jsonSchema,\n }\n\n // 1) onStructuredOutputConfig — middleware can transform messages, options, outputSchema\n structuredConfig = await this.middlewareRunner.runOnStructuredOutputConfig(\n this.middlewareCtx,\n structuredConfig,\n )\n\n // 2) onConfig — phase-aware general-purpose middleware re-runs at the\n // boundary. Re-attach the engine's current tools so onConfig observers\n // see the live tool set (they still won't be forwarded to the structured\n // call — same constraint applies — but the view is consistent with the\n // ChatMiddlewareConfig shape).\n const { outputSchema: pinnedSchema, ...chatConfigSlice } = structuredConfig\n const postOnConfig = await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n { ...chatConfigSlice, tools: baseConfig.tools },\n )\n\n // Apply merged config back to engine state\n this.applyMiddlewareConfig(postOnConfig)\n\n // Build the StructuredOutputOptions the adapter expects.\n // `this.adapter` is already `TAdapter extends AnyTextAdapter` per the\n // class generics — no cast needed.\n const structuredCallOptions = {\n chatOptions: {\n model: this.params.model,\n messages: this.messages,\n metadata: postOnConfig.metadata,\n modelOptions: postOnConfig.modelOptions,\n systemPrompts: postOnConfig.systemPrompts,\n logger: this.logger,\n threadId: this.threadId,\n runId: this.runIdOverride,\n parentRunId: this.parentRunIdOverride,\n ...(this.effectiveRequest ? { request: this.effectiveRequest } : {}),\n },\n outputSchema: pinnedSchema,\n }\n\n // Select the provider call: native streaming if available, else synthesized fallback.\n // The fallback path captures the original adapter error so the engine can\n // attach it as `finalizationError.cause` (the RUN_ERROR wire shape only\n // carries `message` and `code`, losing stack/cause/provider properties).\n let fallbackAdapterError: unknown = undefined\n const providerStream = this.adapter.structuredOutputStream\n ? this.adapter.structuredOutputStream(structuredCallOptions)\n : fallbackStructuredOutputStream(\n this.adapter,\n structuredCallOptions,\n (err) => {\n fallbackAdapterError = err\n },\n )\n\n // ============================================================\n // structured-output.start synthesis\n // ============================================================\n // The client-side StreamProcessor (PR #577) requires a CUSTOM\n // `structured-output.start` event BEFORE the JSON TEXT_MESSAGE_CONTENT\n // deltas — that's how it routes deltas into a `StructuredOutputPart`\n // rather than a plain `TextPart`. No adapter currently emits this,\n // so the engine synthesizes one (and tracks whether the adapter\n // emitted its own to avoid duplicating).\n //\n // Synthesis fires before the FIRST TEXT_MESSAGE_* event from the inner\n // stream, OR before a pre-delta RUN_ERROR (so the client can construct\n // an errored structured-output placeholder).\n let startEmitted = false\n let structuredMessageId: string | null = null\n\n const extractMessageId = (c: StreamChunk): string | null => {\n if (\n c.type === EventType.TEXT_MESSAGE_START ||\n c.type === EventType.TEXT_MESSAGE_CONTENT ||\n c.type === EventType.TEXT_MESSAGE_END\n ) {\n return typeof c.messageId === 'string' && c.messageId !== ''\n ? c.messageId\n : null\n }\n return null\n }\n\n const buildSynthesizedStart = (): StreamChunk => {\n const idForStart = structuredMessageId ?? generateMessageId()\n structuredMessageId = idForStart\n return {\n type: EventType.CUSTOM,\n name: 'structured-output.start',\n value: { messageId: idForStart },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n }\n\n const pipeThroughMiddleware = async (\n synthChunk: StreamChunk,\n ): Promise<Array<StreamChunk>> =>\n this.middlewareRunner.runOnChunk(this.middlewareCtx, synthChunk)\n\n // Track whether a RUN_ERROR has been yielded to streaming consumers so\n // we don't emit a duplicate synthetic one at the end.\n let runErrorYielded = false\n\n // Pipe chunks through middleware; yield to consumer only when yieldChunks=true\n for await (const chunk of providerStream) {\n // Honor cancellation between chunks (mirrors streamModelResponse).\n if (this.isCancelled()) {\n break\n }\n\n // Detect adapter-emitted structured-output.start so we don't duplicate\n if (\n !startEmitted &&\n chunk.type === EventType.CUSTOM &&\n chunk.name === 'structured-output.start'\n ) {\n startEmitted = true\n }\n\n // Capture the assistant messageId off any text-message event so the\n // synthesized start (when needed) uses the SAME id the deltas carry\n if (!structuredMessageId) {\n const extracted = extractMessageId(chunk)\n if (extracted) structuredMessageId = extracted\n }\n\n // Synthesis only matters for the streaming client path — the agentic\n // Promise path consumes chunks internally and returns a Promise, so\n // there's no client-side StreamProcessor to route deltas for.\n if (this.finalStructuredOutput.yieldChunks) {\n // Synthesize start before the FIRST TEXT_MESSAGE_* event\n if (\n !startEmitted &&\n (chunk.type === EventType.TEXT_MESSAGE_START ||\n chunk.type === EventType.TEXT_MESSAGE_CONTENT ||\n chunk.type === EventType.TEXT_MESSAGE_END)\n ) {\n startEmitted = true\n const synthStart = buildSynthesizedStart()\n const synthOutputs = await pipeThroughMiddleware(synthStart)\n for (const outputChunk of synthOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // Synthesize start before a pre-delta RUN_ERROR so the client can\n // construct an errored placeholder structured-output part instead\n // of a silent UI.\n if (!startEmitted && chunk.type === EventType.RUN_ERROR) {\n startEmitted = true\n const synthStart = buildSynthesizedStart()\n const synthOutputs = await pipeThroughMiddleware(synthStart)\n for (const outputChunk of synthOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n }\n\n // 7a. Targeted state updates only.\n // We deliberately do NOT call `handleStreamChunk(chunk)` here — that\n // would mutate agent-loop state with finalization data:\n // - TEXT_MESSAGE_CONTENT deltas would pollute `accumulatedContent`\n // (raw JSON would leak into `info.content` on onFinish)\n // - RUN_FINISHED would overwrite `finishedEvent` + `lastFinishReason`\n // (finalization's 'stop' would overwrite the agent-loop's real\n // finish reason)\n // - STEP_FINISHED would pollute `currentThinkingContent`\n // Finalization is a separate phase from the agent loop; its state must\n // not cross-contaminate. The explicit branches below capture the only\n // bits we actually need from this stream.\n // All narrowing below is via the discriminated-union `chunk.type`\n // — no `as` casts.\n\n // The chunk forwarded to middleware/consumers. Replaced below only for\n // the structured-output.complete event, whose `object` we normalize\n // (un-widen) so streaming consumers see the same cleaned payload the\n // Promise<T> path validates and returns.\n let outboundChunk: StreamChunk = chunk\n\n if (\n chunk.type === EventType.CUSTOM &&\n chunk.name === 'structured-output.complete'\n ) {\n const parsed = readStructuredOutputCompleteValue(chunk.value)\n if (parsed) {\n const object = this.finalStructuredOutput.normalize\n ? this.finalStructuredOutput.normalize(parsed.object)\n : parsed.object\n this.structuredOutputResult = { data: object, rawText: parsed.raw }\n // Rewrite the outbound event so the yielded chunk carries the\n // normalized object (the original `chunk.value` still holds the\n // widened one). Preserve every other field — `raw`, `reasoning` —\n // by spreading the original value.\n const value = chunk.value\n if (object !== parsed.object && value && typeof value === 'object') {\n outboundChunk = { ...chunk, value: { ...value, object } }\n }\n }\n }\n\n if (chunk.type === EventType.RUN_FINISHED && chunk.usage) {\n // RunFinishedEvent already exposes `usage` after type narrowing.\n await this.middlewareRunner.runOnUsage(this.middlewareCtx, chunk.usage)\n }\n\n if (chunk.type === EventType.RUN_ERROR) {\n // RunErrorEvent already exposes `message` and `code` after narrowing.\n this.finalizationError = {\n message: chunk.message,\n ...(chunk.code ? { code: chunk.code } : {}),\n ...(fallbackAdapterError !== undefined\n ? { cause: fallbackAdapterError }\n : {}),\n }\n }\n\n // 7b. Pipe through middleware\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n outboundChunk,\n )\n\n // 7c. Decide consumer visibility — only yieldChunks=true callers get them.\n // We do NOT strip the finalization stream's RUN_STARTED/RUN_FINISHED:\n // they are the single outer lifecycle pair the consumer sees (the\n // agent-loop's pair was suppressed in streamModelResponse when\n // finalStructuredOutput.yieldChunks is true).\n if (this.finalStructuredOutput.yieldChunks) {\n for (const outputChunk of outputChunks) {\n if (outputChunk.type === EventType.RUN_ERROR) {\n runErrorYielded = true\n }\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // 7d. Terminate on error\n if (this.finalizationError) {\n break\n }\n }\n\n // Mid-finalization abort: don't attribute a missing-result error.\n // Let the engine's `finally` block in `run()` route to `onAbort` instead\n // of mis-routing through `onError`.\n if (this.isCancelled()) {\n return\n }\n\n // Empty stream / missing complete event\n if (!this.structuredOutputResult && !this.finalizationError) {\n this.finalizationError = {\n message: 'missing structured result',\n code: 'structured-output-missing-result',\n }\n }\n\n // Run schema validation INSIDE the engine — before the terminal hook\n // chooser runs. Per spec §7.3, validation failures must route through\n // `onError`, not `onFinish`. We do this by writing to `finalizationError`\n // so the chooser in `run()` picks `onError`.\n if (\n this.structuredOutputResult &&\n !this.finalizationError &&\n this.finalStructuredOutput.validate\n ) {\n try {\n const validated = this.finalStructuredOutput.validate(\n this.structuredOutputResult.data,\n )\n this.validatedStructuredOutput = validated\n this.hasValidatedStructuredOutput = true\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n this.finalizationError = {\n message,\n code: 'structured-output-validation-failed',\n cause: err,\n }\n }\n }\n\n // Streaming consumers must see a RUN_ERROR for finalization failures\n // (missing-result, validation-failed, or a finalizationError set after\n // a structured-output.complete already yielded). Without this synthetic\n // emission, the `for await` on the engine ends silently for the client.\n //\n // Skip when a RUN_ERROR was already yielded from the inner stream\n // (otherwise the consumer would see two error events for one failure).\n if (\n this.finalizationError &&\n this.finalStructuredOutput.yieldChunks &&\n !runErrorYielded\n ) {\n // Empty-stream case: no in-loop synthesis fired because no chunks\n // arrived. Synthesize `structured-output.start` here so the client-side\n // StreamProcessor can route the upcoming RUN_ERROR to a\n // `StructuredOutputPart` instead of dropping it as an orphan error.\n if (!startEmitted) {\n const synthStart = buildSynthesizedStart()\n const startOutputs = await pipeThroughMiddleware(synthStart)\n for (const outputChunk of startOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n startEmitted = true\n }\n\n const errChunk: StreamChunk = {\n type: EventType.RUN_ERROR,\n runId: this.runIdOverride ?? this.requestId,\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n error: {\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n },\n }\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n errChunk,\n )\n for (const outputChunk of outputChunks) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n }\n\n /**\n * Native combined mode: harvest the structured output from the agent\n * loop's accumulated final-turn text (no separate provider call).\n *\n * The adapter wired `outputSchema` into the regular `chatStream` request,\n * so the model's final-turn text is the schema-constrained JSON. We parse\n * `this.accumulatedContent`, populate `this.structuredOutputResult`, emit\n * a synthetic `structured-output.complete` (and a `structured-output.start`\n * if one wasn't emitted earlier — only happens on the streaming path when\n * the model returned no text at all), and run the validate callback when\n * present. Failures populate `this.finalizationError` so the engine's\n * terminal-hook chooser routes to `onError` (per spec §7.3).\n *\n * The `'structuredOutput'` middleware phase intentionally does NOT fire on\n * this path — middleware sees the run through `beforeModel` / `modelStream`\n * as usual. See PR #605 / issue #605 for the design rationale.\n */\n private async *harvestCombinedStructuredOutput(): AsyncGenerator<StreamChunk> {\n if (!this.finalStructuredOutput) {\n throw new Error(\n 'harvestCombinedStructuredOutput called without finalStructuredOutput config',\n )\n }\n\n const yieldChunks = this.finalStructuredOutput.yieldChunks\n const rawText = this.accumulatedContent\n\n // Empty final-turn text means the agent loop terminated without the\n // model emitting any assistant content (e.g. early termination after\n // tool calls). Mirror the fallback path's \"missing structured result\"\n // error rather than silently returning undefined.\n if (rawText.length === 0) {\n this.finalizationError = {\n message: 'missing structured result',\n code: 'structured-output-missing-result',\n }\n } else {\n try {\n const parsed: unknown = JSON.parse(rawText)\n // Normalize (un-widen) before storing so the synthesized\n // structured-output.complete chunk and the Promise<T> result both\n // carry the cleaned payload. JSON.parse preserves provider nulls, so\n // this is where native-combined output gets its widening undone.\n const data = this.finalStructuredOutput.normalize\n ? this.finalStructuredOutput.normalize(parsed)\n : parsed\n this.structuredOutputResult = { data, rawText }\n } catch (err: unknown) {\n const detail =\n rawText.slice(0, 200) + (rawText.length > 200 ? '...' : '')\n this.finalizationError = {\n message: `Failed to parse structured output as JSON. Content: ${detail}`,\n code: 'structured-output-parse-failed',\n cause: err,\n }\n }\n }\n\n // Validate against the Standard Schema (when supplied). Validation\n // failures route through onError just like the fallback path.\n if (\n this.structuredOutputResult &&\n !this.finalizationError &&\n this.finalStructuredOutput.validate\n ) {\n try {\n const validated = this.finalStructuredOutput.validate(\n this.structuredOutputResult.data,\n )\n this.validatedStructuredOutput = validated\n this.hasValidatedStructuredOutput = true\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n this.finalizationError = {\n message,\n code: 'structured-output-validation-failed',\n cause: err,\n }\n }\n }\n\n if (!yieldChunks) {\n // Promise<T> path: state is populated, nothing to yield. The\n // activity-layer caller pulls `structuredOutputResult` /\n // `validatedStructuredOutput` directly.\n return\n }\n\n // Streaming path: emit a synthetic `structured-output.start` if the\n // model produced no text at all (so the client snaps an errored\n // StructuredOutputPart rather than nothing). The normal path already\n // emitted start before the first TEXT_MESSAGE_START in\n // `streamModelResponse`.\n if (!this.combinedStartEmitted) {\n this.combinedStartEmitted = true\n const messageId = this.combinedStructuredMessageId ?? generateMessageId()\n this.combinedStructuredMessageId = messageId\n const synthStart: StreamChunk = {\n type: EventType.CUSTOM,\n name: 'structured-output.start',\n value: { messageId },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n const startOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n synthStart,\n )\n for (const outputChunk of startOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // On success, emit the synthetic `structured-output.complete` carrying\n // the parsed object + raw text. Pin the messageId so the client-side\n // handler can target the right UIMessage even when the agent loop's\n // terminal RUN_FINISHED has already cleared `activeMessageIds` (the\n // complete event yields AFTER the loop ends, by which point\n // `getActiveAssistantMessageId()` returns null and would otherwise drop\n // the event silently).\n if (this.structuredOutputResult && !this.finalizationError) {\n const completeChunk: StreamChunk = {\n type: EventType.CUSTOM,\n name: 'structured-output.complete',\n value: {\n object: this.structuredOutputResult.data,\n raw: this.structuredOutputResult.rawText,\n ...(this.combinedStructuredMessageId\n ? { messageId: this.combinedStructuredMessageId }\n : {}),\n },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n const completeOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n completeChunk,\n )\n for (const outputChunk of completeOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // On failure, emit a synthetic RUN_ERROR so the streaming consumer's\n // `for await` doesn't end silently. Mirrors the fallback path.\n if (this.finalizationError) {\n const errChunk: StreamChunk = {\n type: EventType.RUN_ERROR,\n runId: this.runIdOverride ?? this.requestId,\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n error: {\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n },\n }\n const errOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n errChunk,\n )\n for (const outputChunk of errOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n }\n\n private buildMiddlewareConfig(): ChatMiddlewareConfig {\n return {\n messages: this.messages,\n systemPrompts: [...this.systemPrompts],\n tools: [...this.tools],\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 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 queued `sandbox.file` chunks (emitted via the SandboxRuntime sink)\n * through the middleware pipeline and into the public stream.\n */\n private async *drainSandboxFileQueue(): AsyncGenerator<StreamChunk> {\n while (this.sandboxFileQueue.length > 0) {\n const chunk = this.sandboxFileQueue.shift()\n if (chunk) yield* this.pipeThroughMiddleware(chunk)\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 === 'TEXT_MESSAGE_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 const TTools extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['tools'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'],\n const TMiddleware extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'] = TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'],\n>(\n options: TextActivityOptionsWithContext<\n TAdapter,\n TSchema,\n TStream,\n TTools,\n TMiddleware\n >,\n): TextActivityResult<TSchema, TStream> {\n validateCapabilities(options.middleware ?? [], options.adapter)\n\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<TContext = unknown>(\n options: TextActivityOptions<AnyTextAdapter, undefined, true, TContext>,\n): AsyncIterable<StreamChunk> {\n const { adapter, middleware, context, debug, mcp, ...textOptions } = options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n const mcpManager = MCPManager.from(mcp)\n const mcpTools = await mcpManager.discover()\n if (mcpTools.length > 0) {\n textOptions.tools = [...(textOptions.tools ?? []), ...mcpTools]\n }\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 TContext\n >,\n middleware,\n context,\n },\n logger,\n )\n\n try {\n for await (const chunk of engine.run()) {\n yield chunk\n }\n } finally {\n await mcpManager.dispose()\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<TContext = unknown>(\n options: TextActivityOptions<AnyTextAdapter, undefined, false, TContext>,\n): Promise<string> {\n // Run the streaming text and collect all text using streamToText.\n const stream = runStreamingText(\n // eslint-disable-next-line no-restricted-syntax -- generic-stream remap: caller is non-streaming (false), but runStreamingText is invoked internally to collect text; concrete `false`→`true` literals don't structurally overlap.\n options as unknown as TextActivityOptions<\n AnyTextAdapter,\n undefined,\n true,\n TContext\n >,\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<\n TSchema extends SchemaInput,\n TContext = unknown,\n>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, boolean, TContext>,\n): Promise<InferSchemaType<TSchema>> {\n const {\n adapter,\n outputSchema,\n middleware,\n context,\n debug,\n mcp,\n ...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 // Same strict-conversion as the streaming path (`forStructuredOutput: true`)\n // so the same Zod schema produces the same JSON Schema regardless of\n // stream mode — Promise<T> and stream:true must not diverge here. The same\n // pass also records a `nullWideningMap`: optional fields are widened to\n // `required` + nullable for the provider, which then returns `null` for an\n // absent optional — a `null` the original `.optional()` (`T | undefined`)\n // schema would otherwise reject. The map pinpoints exactly those synthesized\n // nulls so `undoNullWidening` can drop them while preserving the ones a\n // `.nullable()` field genuinely allows.\n const { jsonSchema, nullWideningMap } =\n convertSchemaForStructuredOutput(outputSchema)\n if (!jsonSchema) {\n throw new Error('Failed to convert output schema to JSON Schema')\n }\n\n // Un-widening runs in the engine the moment the structured output is\n // captured (`finalStructuredOutput.normalize`), so it applies uniformly to\n // every adapter and to both stream modes — the engine is the only layer\n // holding the schema's `nullWideningMap`. Validation then runs on the\n // already-normalized data, so `validate` is a plain Standard Schema parse.\n const normalize = (data: unknown): unknown =>\n undoNullWidening(data, nullWideningMap)\n\n // Validation runs INSIDE the engine (per spec §7.3) so validation failures\n // route through the engine's terminal-hook chooser as `onError`. We pass a\n // `validate` callback when the schema is a Standard Schema; otherwise we\n // pass through the (normalized) data and the engine returns it unchanged.\n const validate = isStandardSchema(outputSchema)\n ? (data: unknown): unknown =>\n parseWithStandardSchema<InferSchemaType<TSchema>>(outputSchema, data)\n : undefined\n\n // Per issue #605: same capability check as the streaming path. When the\n // adapter handles tools + schema natively, the engine skips the separate\n // structured-output finalization call and harvests the JSON from the\n // agent loop's accumulated final-turn text.\n const nativeCombined =\n adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true\n\n const mcpManager = MCPManager.from(mcp)\n const mcpTools = await mcpManager.discover()\n if (mcpTools.length > 0) {\n textOptions.tools = [...(textOptions.tools ?? []), ...mcpTools]\n }\n\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, unknown>,\n Record<string, unknown>,\n TContext\n >,\n middleware,\n context,\n finalStructuredOutput: {\n jsonSchema,\n yieldChunks: false,\n normalize,\n ...(validate ? { validate } : {}),\n ...(nativeCombined ? { nativeCombined: true } : {}),\n },\n },\n logger,\n )\n\n try {\n // Consume the stream — chunks pipe through middleware but are not yielded externally\n for await (const _chunk of engine.run()) {\n // intentionally empty\n }\n } finally {\n await mcpManager.dispose()\n }\n\n const finalizationError = engine.getFinalizationError()\n if (finalizationError) {\n const err = new Error(\n finalizationError.message,\n finalizationError.cause !== undefined\n ? { cause: finalizationError.cause }\n : undefined,\n )\n if (finalizationError.code !== undefined) {\n Object.defineProperty(err, 'code', {\n value: finalizationError.code,\n enumerable: true,\n })\n }\n throw err\n }\n\n // If a validator ran, return the validated value (typed by InferSchemaType\n // via the callback closure). Otherwise return the raw data.\n const validated = engine.getValidatedStructuredOutput()\n if (validated) {\n return validated.value as InferSchemaType<TSchema>\n }\n\n const result = engine.getStructuredOutputResult()\n if (!result) {\n throw new Error('structured output finalization produced no result')\n }\n return result.data as InferSchemaType<TSchema>\n}\n\n/**\n * Parse the `value` payload of a `structured-output.complete` CUSTOM event\n * into a typed shape, returning `null` if the runtime payload doesn't match.\n *\n * Uses an `unknown`-input runtime check rather than `as` casts so the engine\n * stays cast-free in its hot path.\n */\nfunction readStructuredOutputCompleteValue(\n value: unknown,\n): { object: unknown; raw: string; reasoning?: string } | null {\n if (typeof value !== 'object' || value === null) return null\n if (!('object' in value) || !('raw' in value)) return null\n const raw = (value as { raw: unknown }).raw\n if (typeof raw !== 'string') return null\n const reasoningField = (value as { reasoning?: unknown }).reasoning\n const reasoning =\n typeof reasoningField === 'string' ? reasoningField : undefined\n return {\n object: (value as { object: unknown }).object,\n raw,\n ...(reasoning !== undefined ? { reasoning } : {}),\n }\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 *\n * `onAdapterError`, when provided, is invoked with the raw error from\n * `adapter.structuredOutput` before the synthesized RUN_ERROR is yielded.\n * The engine uses this to preserve the original error (stack, cause, custom\n * properties like provider `status`/`code`) as `finalizationError.cause`,\n * because the RUN_ERROR wire shape only carries `message` and `code`.\n */\nasync function* fallbackStructuredOutputStream(\n adapter: AnyTextAdapter,\n options: StructuredOutputOptions<Record<string, unknown>>,\n onAdapterError?: (err: unknown) => void,\n): AsyncIterable<StreamChunk> {\n const { chatOptions } = options\n // Synthesize run/thread/message IDs only when the caller didn't supply them.\n // Prefix `fallback-` (not `mock-`) because this is production fallback code\n // used by adapters without native `structuredOutputStream`, not test fixtures.\n const fallbackRand = Math.random().toString(36).slice(2)\n const runId = chatOptions.runId ?? `fallback-${Date.now()}-${fallbackRand}`\n const threadId =\n chatOptions.threadId ?? `fallback-${Date.now()}-${fallbackRand}`\n const messageId = `fallback-${Date.now()}-${fallbackRand}`\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: StructuredOutputResult<unknown>\n try {\n result = await adapter.structuredOutput(options)\n } catch (error) {\n onAdapterError?.(error)\n const message = error instanceof Error ? error.message : String(error)\n yield {\n type: EventType.RUN_ERROR,\n runId,\n threadId,\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 // Forward adapter-reported token usage so consumers reading\n // `RUN_FINISHED.usage` (and the engine's `runOnUsage` middleware hook) see\n // it on the fallback path, mirroring the native streaming path. The\n // conditional spread avoids emitting `usage: undefined` for adapters that\n // don't report it. See #758.\n ...(result.usage ? { usage: result.usage } : {}),\n }\n}\n\n/**\n * Run streaming structured output via the TextEngine, with the engine's\n * `finalStructuredOutput.yieldChunks: true` mode. The agent loop's\n * RUN_STARTED/RUN_FINISHED are suppressed; the structured-output finalization\n * step's pair brackets the run for the consumer.\n *\n * Standard Schema *validation* is intentionally NOT run on this path — it is\n * the consumer's responsibility. This is a deliberate asymmetry vs.\n * `runAgenticStructuredOutput` (Promise<T> path), which DOES validate inside\n * the engine and routes validation failures through `onError`. The reason:\n * streaming consumers typically render partial JSON progressively (via\n * `parsePartialJSON` or `useChat`'s `partial` slot) and validate downstream\n * after assembly. Running validation server-side would force a hard error\n * on partial-by-design payloads. See `docs/structured-outputs/overview.md`.\n *\n * Null-widening normalization, however, IS run on both paths: the\n * `structured-output.complete` CUSTOM event is forwarded with its `value.object`\n * already un-widened (synthesized strict-mode nulls dropped, genuine\n * `.nullable()` nulls kept), so a consumer validating the assembled object\n * against the original schema doesn't choke on a `null` for an `.optional()`\n * field. Same `convertSchemaForStructuredOutput` pass and same\n * `undoNullWidening` map as the Promise<T> path — the two must not diverge.\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<\n TSchema extends SchemaInput,\n TContext = unknown,\n>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, true, TContext>,\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, capturing the null-widening map so the engine can un-widen the\n // provider's response before it reaches the consumer. Adapters can re-convert\n // if their wire format diverges, but the default flow hands them a\n // strict-ready schema.\n const { jsonSchema, nullWideningMap } =\n convertSchemaForStructuredOutput(outputSchema)\n if (!jsonSchema) {\n throw new Error('Failed to convert output schema to JSON Schema')\n }\n const normalize = (data: unknown): unknown =>\n undoNullWidening(data, nullWideningMap)\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 normalize,\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<\n TSchema extends SchemaInput,\n TContext = unknown,\n>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, true, TContext>,\n jsonSchema: NonNullable<ReturnType<typeof convertSchemaToJsonSchema>>,\n normalize: (data: unknown) => unknown,\n): StructuredOutputStreamInternal<InferSchemaType<TSchema>> {\n const {\n adapter,\n outputSchema,\n middleware,\n context,\n debug,\n mcp,\n ...textOptions\n } = options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n // Per issue #605: adapters that natively combine tools + schema-constrained\n // output in one streaming call (modern OpenAI, Anthropic 4.5+, Gemini 3+,\n // Grok 4+) opt in via `supportsCombinedToolsAndSchema()`. The engine then\n // forwards the schema into the regular `chatStream` call and harvests the\n // structured result from the agent loop's accumulated text — no separate\n // finalization round-trip, and the `'structuredOutput'` middleware phase\n // does not fire.\n const nativeCombined =\n adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true\n\n const mcpManager = MCPManager.from(mcp)\n const mcpTools = await mcpManager.discover()\n if (mcpTools.length > 0) {\n textOptions.tools = [...(textOptions.tools ?? []), ...mcpTools]\n }\n\n // Inputs may be UIMessages (from useChat) or ModelMessages (from server-side\n // callers). TextEngine handles the conversion uniformly.\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, unknown>,\n Record<string, unknown>,\n TContext\n >,\n middleware,\n context,\n finalStructuredOutput: {\n jsonSchema,\n yieldChunks: true,\n normalize,\n ...(nativeCombined ? { nativeCombined: true } : {}),\n },\n },\n logger,\n )\n\n try {\n for await (const chunk of engine.run()) {\n yield chunk\n }\n } finally {\n await mcpManager.dispose()\n }\n\n // Standard Schema validation for the streaming variant remains the\n // consumer's responsibility — they read the CUSTOM 'structured-output.complete'\n // from the yielded stream. (Null-widening normalization, by contrast, already\n // ran inside the engine via `normalize`, so the object they read is un-widened.)\n void outputSchema\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"],"mappings":";;;;;;;;;;;;;;;;;;AA8FO,MAAM,OAAO;AAsPb,SAAS,kBAsBd,SAYA;AACA,SAAO;AACT;AAwGA,SAAS,oBACP,GACA,GACyB;AACzB,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,CAAC,EAAG,QAAO;AACf,MAAI,EAAE,QAAS,QAAO;AACtB,MAAI,EAAE,QAAS,QAAO;AACtB,QAAM,aAAa,IAAI,gBAAA;AACvB,QAAM,UAAU,CAAC,WAAwB,MAAM;AAC7C,eAAW,MAAM,OAAO,MAAM;AAAA,EAChC;AACA,IAAE,iBAAiB,SAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM;AACtD,IAAE,iBAAiB,SAAS,QAAQ,CAAC,GAAG,EAAE,MAAM,MAAM;AACtD,SAAO,WAAW;AACpB;AAEA,MAAM,WAQJ;AAAA,EACiB;AAAA,EACT;AAAA,EACA;AAAA,EACA;AAAA,EACS;AAAA,EACT;AAAA,EACS;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EAET;AAAA,EACA,iBAAiB;AAAA,EACjB,mBAAkC;AAAA,EAClC,kBAAkB;AAAA,EAClB,kBAAkB;AAAA,EAClB,mBAAkC;AAAA,EAClC,qBAAqB;AAAA,EACrB,sBACN,CAAA;AAAA,EACM,yBAAyB;AAAA,EACzB,2BAA2B;AAAA,EAC3B;AAAA,EACA;AAAA,EACA,gBAAyC;AAAA,EACzC,mBAAmB;AAAA,EACnB,YAA6B;AAAA,EAC7B,aAAyB;AAAA;AAAA,EAEhB;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA;AAAA;AAAA,EAGA;AAAA,EACA;AAAA,EACA,mBAAuC,CAAA;AAAA,EACvC,mBAA4C,CAAA;AAAA,EACrD;AAAA,EACS;AAAA;AAAA;AAAA,EAGA;AAAA,EACT,qBAAqB;AAAA,EAEZ;AAAA;AAAA,EAGT,yBACN;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAMM,uBAAuB;AAAA;AAAA;AAAA;AAAA,EAIvB,8BAA6C;AAAA;AAAA;AAAA;AAAA,EAI7C,4BAAqC;AAAA,EACrC,+BAA+B;AAAA,EAC/B,oBAIG;AAAA,EACM;AAAA,EAQjB,YACE,QACA,QACA;AACA,SAAK,SAAS;AACd,SAAK,UAAU,OAAO;AACtB,SAAK,wBAAwB,OAAO;AACpC,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,+BAA+B,OAAO,OAAO,QAAQ;AAGrE,SAAK,kBAAkB,IAAI;AAAA,MACzB,OAAO,OAAO,SAAS,CAAA;AAAA,MACvB,KAAK;AAAA,MACL,OAAO,OAAO;AAAA,IAAA;AAEhB,SAAK,QAAQ,KAAK,gBAAgB,eAAA;AAClC,SAAK,kBAAkB,IAAI,gBAGzB,KAAK,KAAK;AACZ,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;AAItD,SAAK,WACH,OAAO,OAAO,YACd,OAAO,OAAO,kBACd,KAAK,SAAS,QAAQ;AACxB,SAAK,gBAAgB,OAAO,OAAO;AACnC,SAAK,sBAAsB,OAAO,OAAO;AAMzC,UAAM,gBAAiD;AAAA,MACrD,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,kBAAkB;AAAA,MACrB,KAAK;AAAA,MACL,KAAK,0BAA0B;AAAA,IAAA;AAEjC,SAAK,gBAAgB;AAAA,MACnB,WAAW,KAAK;AAAA,MAChB,UAAU,KAAK;AAAA,MACf,OAAO,KAAK,iBAAiB,KAAK;AAAA,MAClC,UAAU,KAAK;AAAA;AAAA;AAAA,MAGf,gBAAgB,KAAK;AAAA,MACrB,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;AAAA,MACV,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;AAAA,MAElD,cAAc,IAAI,mBAAA;AAAA;AAAA;AAAA;AAAA,MAIlB,KAAK,CAAC,eAAe,WAAW,CAAC,EAAE,KAAK,aAAa;AAAA,MACrD,aAAa,CAAC,eACZ,WAAW,CAAC,EAAE,KAAK,eAAe,EAAE,UAAU,MAAM;AAAA,MACtD,SAAS,CAAC,YAAY,UAAU,WAAW,CAAC,EAAE,KAAK,eAAe,KAAK;AAAA,IAAA;AAOzE,0BAAsB,KAAK,eAAe;AAAA,MACxC,QAAQ,KAAK;AAAA,MACb,MAAM,CAAC,UAAgC;AACrC,aAAK,OAAO,QAAQ,QAAQ,MAAM,IAAI,IAAI,MAAM,IAAI,IAAI;AAAA,UACtD,OAAO;AAAA,YACL,MAAM,MAAM;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,WAAW,MAAM;AAAA,UAAA;AAAA,QACnB,CACD;AACD,aAAK,KAAK,iBACP,eAAe,KAAK,eAAe,KAAK,EACxC,MAAM,CAAC,QAAiB;AACvB,eAAK,OAAO,OAAO,4BAA4B,EAAE,OAAO,KAAK;AAAA,QAC/D,CAAC;AACH,aAAK,iBAAiB;AAAA,UACpB,KAAK,uBAAuB,gBAAgB;AAAA,YAC1C,MAAM,MAAM;AAAA,YACZ,MAAM,MAAM;AAAA,YACZ,WAAW,MAAM;AAAA,UAAA,CAClB;AAAA,QAAA;AAAA,MAEL;AAAA,MACA,cAAc,CAAC,UAA0C;AACvD,aAAK,iBAAiB;AAAA,UACpB,KAAK,uBAAuB,qBAAqB,KAAK;AAAA,QAAA;AAAA,MAE1D;AAAA,IAAA,CACD;AAAA,EACH;AAAA;AAAA,EAGA,wBAAgC;AAC9B,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,cAAmC;AACjC,WAAO,KAAK;AAAA,EACd;AAAA;AAAA,EAGA,4BAAuE;AACrE,WAAO,KAAK;AAAA,EACd;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,+BAA0D;AACxD,WAAO,KAAK,+BACR,EAAE,OAAO,KAAK,8BACd;AAAA,EACN;AAAA;AAAA,EAGA,uBAIS;AACP,WAAO,KAAK;AAAA,EACd;AAAA,EAEA,OAAO,MAAmC;AACxC,SAAK,UAAA;AACL,SAAK,OAAO,UAAU,eAAe;AAAA,MACnC,UAAU,KAAK,cAAc;AAAA,IAAA,CAC9B;AAED,QAAI;AAEF,YAAM,KAAK,iBAAiB,SAAS,KAAK,aAAa;AAGvD,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;AAWA,YAAM,gBACJ,CAAC,CAAC,KAAK,yBACP,KAAK,MAAM,WAAW,KACtB,KAAK,sBAAsB,mBAAmB;AAEhD,UAAI,CAAC,eAAe;AAClB,WAAG;AACD,cAAI,KAAK,oBAAoB,KAAK,YAAA,GAAe;AAC/C;AAAA,UACF;AAEA,eAAK,OAAO,UAAU,aAAa,KAAK,cAAc,SAAS,IAAI;AAAA,YACjE,WAAW,KAAK,cAAc;AAAA,UAAA,CAC/B;AAED,gBAAM,KAAK,WAAA;AAEX,cAAI,KAAK,eAAe,eAAe;AAErC,iBAAK,cAAc,QAAQ;AAC3B,iBAAK,cAAc,YAAY,KAAK;AACpC,kBAAM,aAAa,KAAK,sBAAA;AACxB,kBAAM,wBACJ,MAAM,KAAK,iBAAiB;AAAA,cAC1B,KAAK;AAAA,cACL;AAAA,YAAA;AAEJ,iBAAK,sBAAsB,qBAAqB;AAEhD,mBAAO,KAAK,oBAAA;AAAA,UACd,OAAO;AACL,mBAAO,KAAK,iBAAA;AAAA,UACd;AAEA,eAAK,SAAA;AAAA,QACP,SAAS,KAAK,eAAA;AAAA,MAChB;AAEA,WAAK,OAAO,UAAU,gBAAgB;AAAA,QACpC,cAAc,KAAK;AAAA,MAAA,CACpB;AAUD,UACE,KAAK,yBACL,CAAC,KAAK,iBACN,CAAC,KAAK,mBACN;AACA,YAAI,KAAK,sBAAsB,mBAAmB,MAAM;AACtD,iBAAO,KAAK,gCAAA;AAAA,QACd,OAAO;AACL,iBAAO,KAAK,0BAAA;AAAA,QACd;AAAA,MACF;AAKA,UACE,CAAC,KAAK,sBACN,KAAK,cAAc,UACnB,CAAC,KAAK,eACN;AACA,YAAI,KAAK,mBAAmB;AAC1B,eAAK,qBAAqB;AAC1B,gBAAM,aAAa,IAAI;AAAA,YACrB,KAAK,kBAAkB;AAAA,YACvB,KAAK,kBAAkB,UAAU,SAC7B,EAAE,OAAO,KAAK,kBAAkB,MAAA,IAChC;AAAA,UAAA;AAEN,cAAI,KAAK,kBAAkB,SAAS,QAAW;AAC7C,mBAAO,eAAe,YAAY,QAAQ;AAAA,cACxC,OAAO,KAAK,kBAAkB;AAAA,cAC9B,YAAY;AAAA,YAAA,CACb;AAAA,UACH;AACA,gBAAM,KAAK,iBAAiB,WAAW,KAAK,eAAe;AAAA,YACzD,OAAO;AAAA,YACP,UAAU,KAAK,IAAA,IAAQ,KAAK;AAAA,UAAA,CAC7B;AAAA,QACH,OAAO;AACL,eAAK,qBAAqB;AAC1B,gBAAM,KAAK,iBAAiB,YAAY,KAAK,eAAe;AAAA,YAC1D,cAAc,KAAK;AAAA,YACnB,UAAU,KAAK,IAAA,IAAQ,KAAK;AAAA,YAC5B,SAAS,KAAK;AAAA,YACd,OAAO,KAAK,eAAe;AAAA,UAAA,CAC5B;AAAA,QACH;AAAA,MACF;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,UAAU,KAAK,cAAc;AAAA,UAAA,CAC9B;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,SAAA,IAAa,KAAK;AAGjC,UAAM,UAAmC,CAAA;AACzC,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,UAAU,aAAA,IAAiB,KAAK;AACxC,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;AAUF,UAAM,iBACJ,KAAK,uBAAuB,mBAAmB,OAC3C,KAAK,sBAAsB,aAC3B;AAEN,qBAAiB,SAAS,KAAK,QAAQ,WAAW;AAAA,MAChD,OAAO,KAAK,OAAO;AAAA,MACnB,UAAU,KAAK;AAAA,MACf,OAAO;AAAA,MACP;AAAA,MACA,SAAS,KAAK;AAAA,MACd;AAAA,MACA,eAAe,KAAK;AAAA,MACpB,QAAQ,KAAK;AAAA,MACb,UAAU,KAAK;AAAA,MACf,OAAO,KAAK;AAAA,MACZ,aAAa,KAAK;AAAA;AAAA,MAElB,cAAc,KAAK;AAAA;AAAA,MAEnB,WAAW,KAAK;AAAA,MAChB,GAAI,iBAAiB,EAAE,cAAc,mBAAmB,CAAA;AAAA,IAAC,CAC1D,GAAG;AACF,UAAI,KAAK,eAAe;AACtB;AAAA,MACF;AAEA,WAAK;AAIL,WAAK,kBAAkB,KAAK;AAS5B,UACE,KAAK,uBAAuB,mBAAmB,QAC/C,KAAK,sBAAsB,eAC3B,CAAC,KAAK,wBACN,MAAM,SAAS,UAAU,oBACzB;AACA,aAAK,uBAAuB;AAC5B,cAAM,YACJ,OAAO,MAAM,cAAc,YAAY,MAAM,cAAc,KACvD,MAAM,YACN,kBAAA;AACN,aAAK,8BAA8B;AACnC,cAAM,aAA0B;AAAA,UAC9B,MAAM,UAAU;AAAA,UAChB,MAAM;AAAA,UACN,OAAO,EAAE,UAAA;AAAA,UACT,OAAO,KAAK,OAAO;AAAA,UACnB,WAAW,KAAK,IAAA;AAAA,UAChB,UAAU,KAAK;AAAA,UACf,GAAI,KAAK,gBAAgB,EAAE,OAAO,KAAK,cAAA,IAAkB,CAAA;AAAA,QAAC;AAE5D,cAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,UAC/C,KAAK;AAAA,UACL;AAAA,QAAA;AAEF,mBAAW,eAAe,cAAc;AACtC,gBAAM;AACN,eAAK,cAAc;AAAA,QACrB;AAAA,MACF;AAGA,YAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,QAC/C,KAAK;AAAA,QACL;AAAA,MAAA;AASF,YAAM,yBACJ,CAAC,CAAC,KAAK,yBACP,KAAK,sBAAsB,eAC3B,KAAK,sBAAsB,mBAAmB;AAChD,iBAAW,eAAe,cAAc;AACtC,YACE,2BACC,YAAY,SAAS,UAAU,eAC9B,YAAY,SAAS,UAAU,eACjC;AACA;AAAA,QACF;AACA,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;AAGA,aAAO,KAAK,sBAAA;AAEZ,UAAI,KAAK,kBAAkB;AACzB;AAAA,MACF;AAAA,IACF;AAGA,WAAO,KAAK,sBAAA;AAAA,EACd;AAAA,EAEQ,kBAAkB,OAA0B;AAElD,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUQ,uBACN,WACwB;AACxB,WAAO,KAAK,gBAAgB;AAAA,MAC1B,KAAK;AAAA,MACL,UAAU,IAAI,CAAC,OAAO,GAAG,SAAS,IAAI;AAAA,IAAA;AAAA,EAE1C;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,uBAAuB,sBAAsB;AAAA,MAClD;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,MAEF,KAAK,cAAc;AAAA,MACnB,KAAK;AAAA,IAAA;AAIP,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,KAAK,KAAK,eAAe;AAC5D,iBAAW,SAAS,KAAK;AAAA,QACvB;AAAA,QACA,KAAK;AAAA,MAAA,GACJ;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,uBAAuB,mBAAmB;AAAA,MAC/C;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,MAEF,KAAK,cAAc;AAAA,MACnB,KAAK;AAAA,IAAA;AAIP,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,gBAGzB,KAAK,KAAK;AACZ,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;AAIjD,YAAI;AACJ,YAAI,MAAM,QAAQ,QAAQ,OAAO,GAAG;AAClC,mBAAS,QAAQ;AAAA,QACnB,OAAO;AACL,cAAI;AACF,qBAAS,KAAK,MAAM,QAAQ,OAAiB;AAAA,UAC/C,QAAQ;AACN,qBAAS,QAAQ;AAAA,UACnB;AAAA,QACF;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;AAO5B,YAAM,UAAU,oBAAoB,OAAO,MAAM;AACjD,YAAM,cACJ,OAAO,YAAY,WAAW,UAAU,KAAK,UAAU,OAAO;AAKhE,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;AAEhB,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,UACjB,QAAQ;AAAA,UACR,GAAI,OAAO,UAAU,UAAa,EAAE,OAAO,OAAO,MAAA;AAAA,QAAM,CAC1C;AAAA,MAClB;AAGA,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,SAAS;AAAA,QACT,MAAM;AAAA,QACN,GAAI,OAAO,UAAU,UAAa,EAAE,OAAO,OAAO,MAAA;AAAA,MAAM,CAC1C;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;AAKxC,cAAI,2BAA2B,QAAQ,GAAG;AACxC;AAAA,UACF;AACA,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;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAWA,OAAe,4BAAyD;AACtE,QAAI,CAAC,KAAK,uBAAuB;AAC/B,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAEA,SAAK,cAAc,QAAQ;AAK3B,UAAM,aAAa,KAAK,sBAAA;AACxB,UAAM,EAAE,OAAO,YAAY,GAAG,qBAAqB;AACnD,QAAI,mBAAqD;AAAA,MACvD,GAAG;AAAA,MACH,cAAc,KAAK,sBAAsB;AAAA,IAAA;AAI3C,uBAAmB,MAAM,KAAK,iBAAiB;AAAA,MAC7C,KAAK;AAAA,MACL;AAAA,IAAA;AAQF,UAAM,EAAE,cAAc,cAAc,GAAG,oBAAoB;AAC3D,UAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,MAC/C,KAAK;AAAA,MACL,EAAE,GAAG,iBAAiB,OAAO,WAAW,MAAA;AAAA,IAAM;AAIhD,SAAK,sBAAsB,YAAY;AAKvC,UAAM,wBAAwB;AAAA,MAC5B,aAAa;AAAA,QACX,OAAO,KAAK,OAAO;AAAA,QACnB,UAAU,KAAK;AAAA,QACf,UAAU,aAAa;AAAA,QACvB,cAAc,aAAa;AAAA,QAC3B,eAAe,aAAa;AAAA,QAC5B,QAAQ,KAAK;AAAA,QACb,UAAU,KAAK;AAAA,QACf,OAAO,KAAK;AAAA,QACZ,aAAa,KAAK;AAAA,QAClB,GAAI,KAAK,mBAAmB,EAAE,SAAS,KAAK,iBAAA,IAAqB,CAAA;AAAA,MAAC;AAAA,MAEpE,cAAc;AAAA,IAAA;AAOhB,QAAI,uBAAgC;AACpC,UAAM,iBAAiB,KAAK,QAAQ,yBAChC,KAAK,QAAQ,uBAAuB,qBAAqB,IACzD;AAAA,MACE,KAAK;AAAA,MACL;AAAA,MACA,CAAC,QAAQ;AACP,+BAAuB;AAAA,MACzB;AAAA,IAAA;AAgBN,QAAI,eAAe;AACnB,QAAI,sBAAqC;AAEzC,UAAM,mBAAmB,CAAC,MAAkC;AAC1D,UACE,EAAE,SAAS,UAAU,sBACrB,EAAE,SAAS,UAAU,wBACrB,EAAE,SAAS,UAAU,kBACrB;AACA,eAAO,OAAO,EAAE,cAAc,YAAY,EAAE,cAAc,KACtD,EAAE,YACF;AAAA,MACN;AACA,aAAO;AAAA,IACT;AAEA,UAAM,wBAAwB,MAAmB;AAC/C,YAAM,aAAa,uBAAuB,kBAAA;AAC1C,4BAAsB;AACtB,aAAO;AAAA,QACL,MAAM,UAAU;AAAA,QAChB,MAAM;AAAA,QACN,OAAO,EAAE,WAAW,WAAA;AAAA,QACpB,OAAO,KAAK,OAAO;AAAA,QACnB,WAAW,KAAK,IAAA;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,GAAI,KAAK,gBAAgB,EAAE,OAAO,KAAK,cAAA,IAAkB,CAAA;AAAA,MAAC;AAAA,IAE9D;AAEA,UAAM,wBAAwB,OAC5B,eAEA,KAAK,iBAAiB,WAAW,KAAK,eAAe,UAAU;AAIjE,QAAI,kBAAkB;AAGtB,qBAAiB,SAAS,gBAAgB;AAExC,UAAI,KAAK,eAAe;AACtB;AAAA,MACF;AAGA,UACE,CAAC,gBACD,MAAM,SAAS,UAAU,UACzB,MAAM,SAAS,2BACf;AACA,uBAAe;AAAA,MACjB;AAIA,UAAI,CAAC,qBAAqB;AACxB,cAAM,YAAY,iBAAiB,KAAK;AACxC,YAAI,UAAW,uBAAsB;AAAA,MACvC;AAKA,UAAI,KAAK,sBAAsB,aAAa;AAE1C,YACE,CAAC,iBACA,MAAM,SAAS,UAAU,sBACxB,MAAM,SAAS,UAAU,wBACzB,MAAM,SAAS,UAAU,mBAC3B;AACA,yBAAe;AACf,gBAAM,aAAa,sBAAA;AACnB,gBAAM,eAAe,MAAM,sBAAsB,UAAU;AAC3D,qBAAW,eAAe,cAAc;AACtC,kBAAM;AACN,iBAAK,cAAc;AAAA,UACrB;AAAA,QACF;AAKA,YAAI,CAAC,gBAAgB,MAAM,SAAS,UAAU,WAAW;AACvD,yBAAe;AACf,gBAAM,aAAa,sBAAA;AACnB,gBAAM,eAAe,MAAM,sBAAsB,UAAU;AAC3D,qBAAW,eAAe,cAAc;AACtC,kBAAM;AACN,iBAAK,cAAc;AAAA,UACrB;AAAA,QACF;AAAA,MACF;AAqBA,UAAI,gBAA6B;AAEjC,UACE,MAAM,SAAS,UAAU,UACzB,MAAM,SAAS,8BACf;AACA,cAAM,SAAS,kCAAkC,MAAM,KAAK;AAC5D,YAAI,QAAQ;AACV,gBAAM,SAAS,KAAK,sBAAsB,YACtC,KAAK,sBAAsB,UAAU,OAAO,MAAM,IAClD,OAAO;AACX,eAAK,yBAAyB,EAAE,MAAM,QAAQ,SAAS,OAAO,IAAA;AAK9D,gBAAM,QAAQ,MAAM;AACpB,cAAI,WAAW,OAAO,UAAU,SAAS,OAAO,UAAU,UAAU;AAClE,4BAAgB,EAAE,GAAG,OAAO,OAAO,EAAE,GAAG,OAAO,SAAO;AAAA,UACxD;AAAA,QACF;AAAA,MACF;AAEA,UAAI,MAAM,SAAS,UAAU,gBAAgB,MAAM,OAAO;AAExD,cAAM,KAAK,iBAAiB,WAAW,KAAK,eAAe,MAAM,KAAK;AAAA,MACxE;AAEA,UAAI,MAAM,SAAS,UAAU,WAAW;AAEtC,aAAK,oBAAoB;AAAA,UACvB,SAAS,MAAM;AAAA,UACf,GAAI,MAAM,OAAO,EAAE,MAAM,MAAM,KAAA,IAAS,CAAA;AAAA,UACxC,GAAI,yBAAyB,SACzB,EAAE,OAAO,qBAAA,IACT,CAAA;AAAA,QAAC;AAAA,MAET;AAGA,YAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,QAC/C,KAAK;AAAA,QACL;AAAA,MAAA;AAQF,UAAI,KAAK,sBAAsB,aAAa;AAC1C,mBAAW,eAAe,cAAc;AACtC,cAAI,YAAY,SAAS,UAAU,WAAW;AAC5C,8BAAkB;AAAA,UACpB;AACA,gBAAM;AACN,eAAK,cAAc;AAAA,QACrB;AAAA,MACF;AAGA,UAAI,KAAK,mBAAmB;AAC1B;AAAA,MACF;AAAA,IACF;AAKA,QAAI,KAAK,eAAe;AACtB;AAAA,IACF;AAGA,QAAI,CAAC,KAAK,0BAA0B,CAAC,KAAK,mBAAmB;AAC3D,WAAK,oBAAoB;AAAA,QACvB,SAAS;AAAA,QACT,MAAM;AAAA,MAAA;AAAA,IAEV;AAMA,QACE,KAAK,0BACL,CAAC,KAAK,qBACN,KAAK,sBAAsB,UAC3B;AACA,UAAI;AACF,cAAM,YAAY,KAAK,sBAAsB;AAAA,UAC3C,KAAK,uBAAuB;AAAA,QAAA;AAE9B,aAAK,4BAA4B;AACjC,aAAK,+BAA+B;AAAA,MACtC,SAAS,KAAc;AACrB,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,aAAK,oBAAoB;AAAA,UACvB;AAAA,UACA,MAAM;AAAA,UACN,OAAO;AAAA,QAAA;AAAA,MAEX;AAAA,IACF;AASA,QACE,KAAK,qBACL,KAAK,sBAAsB,eAC3B,CAAC,iBACD;AAKA,UAAI,CAAC,cAAc;AACjB,cAAM,aAAa,sBAAA;AACnB,cAAM,eAAe,MAAM,sBAAsB,UAAU;AAC3D,mBAAW,eAAe,cAAc;AACtC,gBAAM;AACN,eAAK,cAAc;AAAA,QACrB;AACA,uBAAe;AAAA,MACjB;AAEA,YAAM,WAAwB;AAAA,QAC5B,MAAM,UAAU;AAAA,QAChB,OAAO,KAAK,iBAAiB,KAAK;AAAA,QAClC,OAAO,KAAK,OAAO;AAAA,QACnB,WAAW,KAAK,IAAA;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,SAAS,KAAK,kBAAkB;AAAA,QAChC,GAAI,KAAK,kBAAkB,OACvB,EAAE,MAAM,KAAK,kBAAkB,KAAA,IAC/B,CAAA;AAAA,QACJ,OAAO;AAAA,UACL,SAAS,KAAK,kBAAkB;AAAA,UAChC,GAAI,KAAK,kBAAkB,OACvB,EAAE,MAAM,KAAK,kBAAkB,SAC/B,CAAA;AAAA,QAAC;AAAA,MACP;AAEF,YAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,QAC/C,KAAK;AAAA,QACL;AAAA,MAAA;AAEF,iBAAW,eAAe,cAAc;AACtC,cAAM;AACN,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AAAA,EACF;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAmBA,OAAe,kCAA+D;AAC5E,QAAI,CAAC,KAAK,uBAAuB;AAC/B,YAAM,IAAI;AAAA,QACR;AAAA,MAAA;AAAA,IAEJ;AAEA,UAAM,cAAc,KAAK,sBAAsB;AAC/C,UAAM,UAAU,KAAK;AAMrB,QAAI,QAAQ,WAAW,GAAG;AACxB,WAAK,oBAAoB;AAAA,QACvB,SAAS;AAAA,QACT,MAAM;AAAA,MAAA;AAAA,IAEV,OAAO;AACL,UAAI;AACF,cAAM,SAAkB,KAAK,MAAM,OAAO;AAK1C,cAAM,OAAO,KAAK,sBAAsB,YACpC,KAAK,sBAAsB,UAAU,MAAM,IAC3C;AACJ,aAAK,yBAAyB,EAAE,MAAM,QAAA;AAAA,MACxC,SAAS,KAAc;AACrB,cAAM,SACJ,QAAQ,MAAM,GAAG,GAAG,KAAK,QAAQ,SAAS,MAAM,QAAQ;AAC1D,aAAK,oBAAoB;AAAA,UACvB,SAAS,uDAAuD,MAAM;AAAA,UACtE,MAAM;AAAA,UACN,OAAO;AAAA,QAAA;AAAA,MAEX;AAAA,IACF;AAIA,QACE,KAAK,0BACL,CAAC,KAAK,qBACN,KAAK,sBAAsB,UAC3B;AACA,UAAI;AACF,cAAM,YAAY,KAAK,sBAAsB;AAAA,UAC3C,KAAK,uBAAuB;AAAA,QAAA;AAE9B,aAAK,4BAA4B;AACjC,aAAK,+BAA+B;AAAA,MACtC,SAAS,KAAc;AACrB,cAAM,UAAU,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;AAC/D,aAAK,oBAAoB;AAAA,UACvB;AAAA,UACA,MAAM;AAAA,UACN,OAAO;AAAA,QAAA;AAAA,MAEX;AAAA,IACF;AAEA,QAAI,CAAC,aAAa;AAIhB;AAAA,IACF;AAOA,QAAI,CAAC,KAAK,sBAAsB;AAC9B,WAAK,uBAAuB;AAC5B,YAAM,YAAY,KAAK,+BAA+B,kBAAA;AACtD,WAAK,8BAA8B;AACnC,YAAM,aAA0B;AAAA,QAC9B,MAAM,UAAU;AAAA,QAChB,MAAM;AAAA,QACN,OAAO,EAAE,UAAA;AAAA,QACT,OAAO,KAAK,OAAO;AAAA,QACnB,WAAW,KAAK,IAAA;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,GAAI,KAAK,gBAAgB,EAAE,OAAO,KAAK,cAAA,IAAkB,CAAA;AAAA,MAAC;AAE5D,YAAM,eAAe,MAAM,KAAK,iBAAiB;AAAA,QAC/C,KAAK;AAAA,QACL;AAAA,MAAA;AAEF,iBAAW,eAAe,cAAc;AACtC,cAAM;AACN,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AASA,QAAI,KAAK,0BAA0B,CAAC,KAAK,mBAAmB;AAC1D,YAAM,gBAA6B;AAAA,QACjC,MAAM,UAAU;AAAA,QAChB,MAAM;AAAA,QACN,OAAO;AAAA,UACL,QAAQ,KAAK,uBAAuB;AAAA,UACpC,KAAK,KAAK,uBAAuB;AAAA,UACjC,GAAI,KAAK,8BACL,EAAE,WAAW,KAAK,4BAAA,IAClB,CAAA;AAAA,QAAC;AAAA,QAEP,OAAO,KAAK,OAAO;AAAA,QACnB,WAAW,KAAK,IAAA;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,GAAI,KAAK,gBAAgB,EAAE,OAAO,KAAK,cAAA,IAAkB,CAAA;AAAA,MAAC;AAE5D,YAAM,kBAAkB,MAAM,KAAK,iBAAiB;AAAA,QAClD,KAAK;AAAA,QACL;AAAA,MAAA;AAEF,iBAAW,eAAe,iBAAiB;AACzC,cAAM;AACN,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AAIA,QAAI,KAAK,mBAAmB;AAC1B,YAAM,WAAwB;AAAA,QAC5B,MAAM,UAAU;AAAA,QAChB,OAAO,KAAK,iBAAiB,KAAK;AAAA,QAClC,OAAO,KAAK,OAAO;AAAA,QACnB,WAAW,KAAK,IAAA;AAAA,QAChB,UAAU,KAAK;AAAA,QACf,SAAS,KAAK,kBAAkB;AAAA,QAChC,GAAI,KAAK,kBAAkB,OACvB,EAAE,MAAM,KAAK,kBAAkB,KAAA,IAC/B,CAAA;AAAA,QACJ,OAAO;AAAA,UACL,SAAS,KAAK,kBAAkB;AAAA,UAChC,GAAI,KAAK,kBAAkB,OACvB,EAAE,MAAM,KAAK,kBAAkB,SAC/B,CAAA;AAAA,QAAC;AAAA,MACP;AAEF,YAAM,aAAa,MAAM,KAAK,iBAAiB;AAAA,QAC7C,KAAK;AAAA,QACL;AAAA,MAAA;AAEF,iBAAW,eAAe,YAAY;AACpC,cAAM;AACN,aAAK,cAAc;AAAA,MACrB;AAAA,IACF;AAAA,EACF;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,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,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,wBAAqD;AAClE,WAAO,KAAK,iBAAiB,SAAS,GAAG;AACvC,YAAM,QAAQ,KAAK,iBAAiB,MAAA;AACpC,UAAI,MAAO,QAAO,KAAK,sBAAsB,KAAK;AAAA,IACpD;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,KAsBd,SAOsC;AACtC,uBAAqB,QAAQ,cAAc,CAAA,GAAI,QAAQ,OAAO;AAE9D,QAAM,EAAE,cAAc,OAAA,IAAW;AAKjC,MAAI,gBAAgB,WAAW,MAAM;AACnC,WAAO,6BAA6B;AAAA,MAClC,GAAG;AAAA,MACH;AAAA,MACA;AAAA,IAAA,CACD;AAAA,EACH;AAGA,MAAI,cAAc;AAChB,WAAO,2BAA2B;AAAA,MAChC,GAAG;AAAA,MACH;AAAA,IAAA,CACD;AAAA,EACH;AAGA,MAAI,WAAW,OAAO;AACpB,WAAO,oBAAoB;AAAA,MACzB,GAAG;AAAA,MACH,cAAc;AAAA,MACd;AAAA,IAAA,CACD;AAAA,EACH;AAGA,SAAO,iBAAiB;AAAA,IACtB,GAAG;AAAA,IACH,cAAc;AAAA,IACd;AAAA,EAAA,CACD;AACH;AAKA,gBAAgB,iBACd,SAC4B;AAC5B,QAAM,EAAE,SAAS,YAAY,SAAS,OAAO,KAAK,GAAG,gBAAgB;AACrE,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,mBAAmB,KAAK;AAEvC,QAAM,aAAa,WAAW,KAAK,GAAG;AACtC,QAAM,WAAW,MAAM,WAAW,SAAA;AAClC,MAAI,SAAS,SAAS,GAAG;AACvB,gBAAY,QAAQ,CAAC,GAAI,YAAY,SAAS,CAAA,GAAK,GAAG,QAAQ;AAAA,EAChE;AAEA,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE;AAAA,MACA,QAAQ,EAAE,GAAG,aAAa,OAAO,OAAA;AAAA,MAKjC;AAAA,MACA;AAAA,IAAA;AAAA,IAEF;AAAA,EAAA;AAGF,MAAI;AACF,qBAAiB,SAAS,OAAO,OAAO;AACtC,YAAM;AAAA,IACR;AAAA,EACF,UAAA;AACE,UAAM,WAAW,QAAA;AAAA,EACnB;AACF;AAMA,SAAS,oBACP,SACiB;AAEjB,QAAM,SAAS;AAAA;AAAA,IAEb;AAAA,EAAA;AAQF,SAAO,aAAa,MAAM;AAC5B;AAQA,eAAe,2BAIb,SACmC;AACnC,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACD;AACJ,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,mBAAmB,KAAK;AAEvC,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAWA,QAAM,EAAE,YAAY,oBAClB,iCAAiC,YAAY;AAC/C,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AAOA,QAAM,YAAY,CAAC,SACjB,iBAAiB,MAAM,eAAe;AAMxC,QAAM,WAAW,iBAAiB,YAAY,IAC1C,CAAC,SACC,wBAAkD,cAAc,IAAI,IACtE;AAMJ,QAAM,iBACJ,QAAQ,iCAAiC,QAAQ,YAAY,MAAM;AAErE,QAAM,aAAa,WAAW,KAAK,GAAG;AACtC,QAAM,WAAW,MAAM,WAAW,SAAA;AAClC,MAAI,SAAS,SAAS,GAAG;AACvB,gBAAY,QAAQ,CAAC,GAAI,YAAY,SAAS,CAAA,GAAK,GAAG,QAAQ;AAAA,EAChE;AAEA,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE;AAAA,MACA,QAAQ,EAAE,GAAG,aAAa,OAAO,OAAA;AAAA,MAKjC;AAAA,MACA;AAAA,MACA,uBAAuB;AAAA,QACrB;AAAA,QACA,aAAa;AAAA,QACb;AAAA,QACA,GAAI,WAAW,EAAE,SAAA,IAAa,CAAA;AAAA,QAC9B,GAAI,iBAAiB,EAAE,gBAAgB,SAAS,CAAA;AAAA,MAAC;AAAA,IACnD;AAAA,IAEF;AAAA,EAAA;AAGF,MAAI;AAEF,qBAAiB,UAAU,OAAO,OAAO;AAAA,IAEzC;AAAA,EACF,UAAA;AACE,UAAM,WAAW,QAAA;AAAA,EACnB;AAEA,QAAM,oBAAoB,OAAO,qBAAA;AACjC,MAAI,mBAAmB;AACrB,UAAM,MAAM,IAAI;AAAA,MACd,kBAAkB;AAAA,MAClB,kBAAkB,UAAU,SACxB,EAAE,OAAO,kBAAkB,UAC3B;AAAA,IAAA;AAEN,QAAI,kBAAkB,SAAS,QAAW;AACxC,aAAO,eAAe,KAAK,QAAQ;AAAA,QACjC,OAAO,kBAAkB;AAAA,QACzB,YAAY;AAAA,MAAA,CACb;AAAA,IACH;AACA,UAAM;AAAA,EACR;AAIA,QAAM,YAAY,OAAO,6BAAA;AACzB,MAAI,WAAW;AACb,WAAO,UAAU;AAAA,EACnB;AAEA,QAAM,SAAS,OAAO,0BAAA;AACtB,MAAI,CAAC,QAAQ;AACX,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACrE;AACA,SAAO,OAAO;AAChB;AASA,SAAS,kCACP,OAC6D;AAC7D,MAAI,OAAO,UAAU,YAAY,UAAU,KAAM,QAAO;AACxD,MAAI,EAAE,YAAY,UAAU,EAAE,SAAS,OAAQ,QAAO;AACtD,QAAM,MAAO,MAA2B;AACxC,MAAI,OAAO,QAAQ,SAAU,QAAO;AACpC,QAAM,iBAAkB,MAAkC;AAC1D,QAAM,YACJ,OAAO,mBAAmB,WAAW,iBAAiB;AACxD,SAAO;AAAA,IACL,QAAS,MAA8B;AAAA,IACvC;AAAA,IACA,GAAI,cAAc,SAAY,EAAE,cAAc,CAAA;AAAA,EAAC;AAEnD;AAaA,gBAAgB,+BACd,SACA,SACA,gBAC4B;AAC5B,QAAM,EAAE,gBAAgB;AAIxB,QAAM,eAAe,KAAK,OAAA,EAAS,SAAS,EAAE,EAAE,MAAM,CAAC;AACvD,QAAM,QAAQ,YAAY,SAAS,YAAY,KAAK,IAAA,CAAK,IAAI,YAAY;AACzE,QAAM,WACJ,YAAY,YAAY,YAAY,KAAK,IAAA,CAAK,IAAI,YAAY;AAChE,QAAM,YAAY,YAAY,KAAK,KAAK,IAAI,YAAY;AACxD,QAAM,QAAQ,YAAY;AAC1B,QAAM,YAAY,KAAK,IAAA;AAEvB,QAAM;AAAA,IACJ,MAAM,UAAU;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,QAAQ,iBAAiB,OAAO;AAAA,EACjD,SAAS,OAAO;AACd,qBAAiB,KAAK;AACtB,UAAM,UAAU,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;AACrE,UAAM;AAAA,MACJ,MAAM,UAAU;AAAA,MAChB;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA;AAAA,MACA,OAAO,EAAE,QAAA;AAAA,IAAQ;AAEnB;AAAA,EACF;AAEA,QAAM;AAAA,IACJ,MAAM,UAAU;AAAA,IAChB;AAAA,IACA,MAAM;AAAA,IACN;AAAA,IACA;AAAA,EAAA;AAGF,QAAM;AAAA,IACJ,MAAM,UAAU;AAAA,IAChB;AAAA,IACA,OAAO,OAAO;AAAA,IACd;AAAA,IACA;AAAA,EAAA;AAGF,QAAM;AAAA,IACJ,MAAM,UAAU;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAGF,QAAM;AAAA,IACJ,MAAM,UAAU;AAAA,IAChB,MAAM;AAAA,IACN,OAAO,EAAE,QAAQ,OAAO,MAAM,KAAK,OAAO,QAAA;AAAA,IAC1C;AAAA,IACA;AAAA,EAAA;AAGF,QAAM;AAAA,IACJ,MAAM,UAAU;AAAA,IAChB;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,cAAc;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAMd,GAAI,OAAO,QAAQ,EAAE,OAAO,OAAO,MAAA,IAAU,CAAA;AAAA,EAAC;AAElD;AA6BA,SAAS,6BAIP,SACkD;AAClD,QAAM,EAAE,iBAAiB;AAEzB,MAAI,CAAC,cAAc;AACjB,UAAM,IAAI,MAAM,0DAA0D;AAAA,EAC5E;AAOA,QAAM,EAAE,YAAY,oBAClB,iCAAiC,YAAY;AAC/C,MAAI,CAAC,YAAY;AACf,UAAM,IAAI,MAAM,gDAAgD;AAAA,EAClE;AACA,QAAM,YAAY,CAAC,SACjB,iBAAiB,MAAM,eAAe;AAQxC,SAAO;AAAA,IACL;AAAA,IACA;AAAA,IACA;AAAA,EAAA;AAEJ;AAkBA,gBAAgB,iCAId,SACA,YACA,WAC0D;AAC1D,QAAM;AAAA,IACJ;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA;AAAA,IACA,GAAG;AAAA,EAAA,IACD;AACJ,QAAM,QAAQ,QAAQ;AACtB,QAAM,SAAS,mBAAmB,KAAK;AASvC,QAAM,iBACJ,QAAQ,iCAAiC,QAAQ,YAAY,MAAM;AAErE,QAAM,aAAa,WAAW,KAAK,GAAG;AACtC,QAAM,WAAW,MAAM,WAAW,SAAA;AAClC,MAAI,SAAS,SAAS,GAAG;AACvB,gBAAY,QAAQ,CAAC,GAAI,YAAY,SAAS,CAAA,GAAK,GAAG,QAAQ;AAAA,EAChE;AAIA,QAAM,SAAS,IAAI;AAAA,IACjB;AAAA,MACE;AAAA,MACA,QAAQ,EAAE,GAAG,aAAa,OAAO,OAAA;AAAA,MAKjC;AAAA,MACA;AAAA,MACA,uBAAuB;AAAA,QACrB;AAAA,QACA,aAAa;AAAA,QACb;AAAA,QACA,GAAI,iBAAiB,EAAE,gBAAgB,SAAS,CAAA;AAAA,MAAC;AAAA,IACnD;AAAA,IAEF;AAAA,EAAA;AAGF,MAAI;AACF,qBAAiB,SAAS,OAAO,OAAO;AACtC,YAAM;AAAA,IACR;AAAA,EACF,UAAA;AACE,UAAM,WAAW,QAAA;AAAA,EACnB;AAOF;"}
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 { undoNullWidening } from '@tanstack/ai-utils'\nimport { stripToSpecMiddleware } from '../../strip-to-spec-middleware'\nimport { streamToText } from '../../stream-to-response.js'\nimport { resolveDebugOption } from '../../logger/resolve'\nimport { EventType } from '../../types'\nimport { normalizeToolResult } from '../../utilities/tool-result'\nimport { isProviderExecutedToolCall } from '../../utilities/provider-executed'\nimport { LazyToolManager } from './tools/lazy-tool-manager'\nimport {\n MiddlewareAbortError,\n ToolCallManager,\n executeToolCalls,\n} from './tools/tool-calls'\nimport {\n convertSchemaForStructuredOutput,\n convertSchemaToJsonSchema,\n isStandardSchema,\n parseWithStandardSchema,\n} from './tools/schema-converter'\nimport { maxIterations as maxIterationsStrategy } from './agent-loop-strategies'\nimport { convertMessagesToModelMessages, generateMessageId } from './messages'\nimport { MiddlewareRunner } from './middleware/compose'\nimport { provideSandboxRuntime } from './middleware/sandbox-runtime'\nimport { CapabilityRegistry } from './middleware/capabilities'\nimport { validateCapabilities } from './middleware/validate'\nimport { MCPManager } from './mcp/manager'\nimport type {\n ApprovalRequest,\n ClientToolRequest,\n ToolResult,\n} from './tools/tool-calls'\nimport type {\n AnyTextAdapter,\n StructuredOutputOptions,\n StructuredOutputResult,\n} from './adapter'\nimport type {\n AgentLoopStrategy,\n AnyTool,\n ChatStream,\n ConstrainedModelMessage,\n CustomEvent,\n InferSchemaType,\n JSONSchema,\n LazyToolsConfig,\n ModelMessage,\n RunFinishedEvent,\n SchemaInput,\n StreamChunk,\n StructuredOutputCompleteEvent,\n StructuredOutputStream,\n TextMessageContentEvent,\n TextOptions,\n ToolCall,\n ToolCallArgsEvent,\n ToolCallEndEvent,\n ToolCallStartEvent,\n UIMessage,\n} from '../../types'\nimport type {\n AnyChatMiddleware,\n ChatMiddleware,\n ChatMiddlewareConfig,\n ChatMiddlewareContext,\n SandboxFileHookEvent,\n StructuredOutputMiddlewareConfig,\n} from './middleware/types'\nimport type { CheckCoverage } from './middleware/builder'\nimport type { SystemPrompt } from '../../system-prompts'\nimport type { InternalLogger } from '../../logger/internal-logger'\nimport type { DebugOption } from '../../logger/types'\nimport type { ProviderTool } from '../../tools/provider-tool'\nimport type {\n ContextFromMiddleware,\n ContextFromTool,\n DefinedContext,\n MergeContext,\n UnionToIntersection,\n} from './runtime-context-types'\nimport type { ChatMCPOptions } from './mcp/types'\n\n// ===========================\n// Activity Kind\n// ===========================\n\n/** The adapter kind this activity handles */\nexport const kind = 'text' as const\n\ntype AnyRuntimeTool = AnyTool\n\n// The leaf context-inference primitives (KnownContext, MergeContext,\n// UnionToIntersection, DefinedContext, ContextFromTool, ContextFromMiddleware)\n// are shared with the tool execution layer — see ./runtime-context-types.\ntype ContextFromConsumer<T> = ContextFromTool<T> | ContextFromMiddleware<T>\n\ntype RequiredContextFromConsumerUnion<T> = T extends unknown\n ? undefined extends ContextFromConsumer<T>\n ? never\n : ContextFromConsumer<T>\n : never\n\ntype ContextFromConsumerUnion<T> = [\n UnionToIntersection<DefinedContext<ContextFromConsumer<T>>>,\n] extends [never]\n ? never\n : [RequiredContextFromConsumerUnion<T>] extends [never]\n ? UnionToIntersection<DefinedContext<ContextFromConsumer<T>>> | undefined\n : UnionToIntersection<DefinedContext<ContextFromConsumer<T>>>\n\ntype ContextFromArray<T> = T extends readonly [infer THead, ...infer TTail]\n ? MergeContext<ContextFromConsumer<THead>, ContextFromArray<TTail>>\n : T extends ReadonlyArray<infer TItem>\n ? ContextFromConsumerUnion<TItem>\n : never\n\ntype ContextFromInputs<TTools, TMiddleware> = MergeContext<\n ContextFromArray<NonNullable<TTools>>,\n ContextFromArray<NonNullable<TMiddleware>>\n>\n\ntype InferredContext<TTools, TMiddleware> = [\n ContextFromInputs<TTools, TMiddleware>,\n] extends [never]\n ? unknown\n : ContextFromInputs<TTools, TMiddleware>\n\ntype RequiredContextFromInputs<TTools, TMiddleware> = [\n ContextFromInputs<TTools, TMiddleware>,\n] extends [never]\n ? { context?: unknown }\n : undefined extends ContextFromInputs<TTools, TMiddleware>\n ? { context?: ContextFromInputs<TTools, TMiddleware> }\n : { context: ContextFromInputs<TTools, TMiddleware> }\n\ntype TextActivityOptionsWithContext<\n TAdapter extends AnyTextAdapter,\n TSchema extends SchemaInput | undefined,\n TStream extends boolean,\n TTools extends TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'],\n TMiddleware extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'],\n> = Omit<\n TextActivityOptions<TAdapter, TSchema, TStream, any>,\n 'tools' | 'middleware' | 'context'\n> & {\n tools?: TTools\n middleware?: TMiddleware &\n CheckCoverage<Extract<TMiddleware, ReadonlyArray<AnyChatMiddleware>>>\n} & RequiredContextFromInputs<TTools, TMiddleware>\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 TContext = unknown,\n> {\n /** The text adapter to use (created by a provider function like openaiText('gpt-4o')) */\n adapter: TAdapter\n /**\n * Conversation messages. Accepts:\n * - `ConstrainedModelMessage` — content types constrained by the adapter's input modalities.\n * - `ModelMessage` — unconstrained model message (e.g., forwarded from an AG-UI wire payload).\n * - `UIMessage` — parts-based UI representation; converted internally via `convertMessagesToModelMessages`.\n *\n * The three shapes can be mixed in a single array (e.g., when forwarding a wire payload that includes both anchor UIMessages and AG-UI fan-out ModelMessages).\n */\n messages?:\n | Array<\n | UIMessage\n | ModelMessage\n | ConstrainedModelMessage<{\n inputModalities: TAdapter['~types']['inputModalities']\n messageMetadataByModality: TAdapter['~types']['messageMetadataByModality']\n }>\n >\n | undefined\n /**\n * System prompts to prepend to the conversation.\n *\n * Accepts plain strings or `{ content, metadata }` objects. The `metadata`\n * field is typed by the adapter — Anthropic narrows it to\n * `AnthropicSystemPromptMetadata` (with `cache_control` for prompt\n * caching), providers without per-prompt metadata reject the field\n * entirely.\n */\n systemPrompts?:\n | Array<SystemPrompt<TAdapter['~types']['systemPromptMetadata']>>\n | undefined\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?:\n | Array<\n | (AnyRuntimeTool & { readonly '~toolKind'?: never })\n | ProviderTool<string, TAdapter['~types']['toolCapabilities'][number]>\n >\n | undefined\n /**\n * Hand MCP clients/pools to chat(): their tools are discovered at run start\n * and merged into the run; `connection` controls whether chat() closes them\n * when the run ends. See docs/tools/mcp.md \"Managing MCP clients with chat()\".\n */\n mcp?: ChatMCPOptions\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 /**\n * Cap how many tool calls from a single model turn are executed.\n * Excess calls receive error results. See {@link TextOptions.maxToolCallsPerTurn}.\n */\n maxToolCallsPerTurn?: TextOptions['maxToolCallsPerTurn']\n /**\n * Optional configuration for lazy-tool discovery (tools marked `lazy: true`).\n * Tunes how much of each lazy tool's description appears in the discovery\n * catalog. Optional — defaults to `{ includeDescription: 'none' }`.\n */\n lazyToolsConfig?: LazyToolsConfig\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 /** Parent run ID for AG-UI protocol nested run correlation. */\n parentRunId?: TextOptions['parentRunId']\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<TContext>>\n /**\n * Runtime context value passed to middleware hooks and server tools.\n */\n context?: TContext\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 const TTools extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['tools'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'],\n const TMiddleware extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'] = TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'],\n>(\n options: TextActivityOptionsWithContext<\n TAdapter,\n TSchema,\n TStream,\n TTools,\n TMiddleware\n >,\n): TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n InferredContext<TTools, TMiddleware>\n> {\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 : ChatStream\n\n// ===========================\n// ChatEngine Implementation\n// ===========================\n\ninterface TextEngineConfig<\n TAdapter extends AnyTextAdapter,\n TContext = unknown,\n TParams extends TextOptions<any, any, TContext> = TextOptions<\n any,\n any,\n TContext\n >,\n> {\n adapter: TAdapter\n systemPrompts?: Array<SystemPrompt>\n params: TParams\n middleware?: Array<ChatMiddleware<TContext>>\n context?: TContext\n /**\n * If set, after the agent loop finishes the engine runs a\n * structured-output finalization step through the same middleware\n * pipeline. See `runStructuredFinalization` for the flow.\n *\n * - jsonSchema: the JSON Schema to send to the provider\n * - yieldChunks: when true, finalization chunks are yielded to the caller\n * (used by runStreamingStructuredOutput). When false, chunks are\n * consumed internally for middleware visibility but not yielded\n * (used by runAgenticStructuredOutput).\n * - normalize: optional schema-aware transform applied to the captured\n * structured-output object the moment it enters the engine — BEFORE it is\n * stored, validated, or yielded. Used to undo strict-mode null-widening\n * (`undoNullWidening`): strict schemas widen optional fields to\n * `required` + nullable so the provider returns `null` for an absent\n * optional, and this strips exactly those synthesized nulls while keeping\n * the ones a `.nullable()` field genuinely allows. Applied here (not in\n * the adapter) because the engine is the only layer holding the original\n * schema's null-widening map, and applying it at capture fixes BOTH the\n * streaming chunk and the Promise<T> result with one transform.\n * - validate: optional callback invoked AFTER `normalize` and AFTER the\n * structured-output result is captured, but BEFORE the terminal hook\n * fires. If it throws, the engine records a `finalizationError` and fires\n * `onError` instead of `onFinish` (per spec §7.3). On success, the\n * returned value is stored as the validated result and retrievable via\n * `getValidatedStructuredOutput()`. Used by `runAgenticStructuredOutput`\n * to perform Standard Schema validation inside the engine.\n * - nativeCombined: when true, the adapter declared\n * `supportsCombinedToolsAndSchema()` and the engine wires `jsonSchema`\n * into the regular `chatStream` call instead of running a separate\n * finalization round-trip. The agent loop's final-turn text is the\n * schema-constrained JSON; the engine parses it from accumulated\n * content. The `'structuredOutput'` middleware phase does NOT fire on\n * this path — middleware sees the run through `beforeModel` /\n * `modelStream` as usual.\n */\n finalStructuredOutput?: {\n jsonSchema: JSONSchema\n yieldChunks: boolean\n normalize?: (data: unknown) => unknown\n validate?: (data: unknown) => unknown\n nativeCombined?: boolean\n }\n}\n\ntype ToolPhaseResult = 'continue' | 'stop' | 'wait'\ntype CyclePhase = 'processText' | 'executeToolCalls'\n\n/**\n * Validate and normalize `maxToolCallsPerTurn`.\n * Unset → unlimited. `0` → execute none. Negatives / non-finite → throw\n * (Array#slice treats negatives as \"from end\", which is not a useful cap).\n */\nfunction resolveMaxToolCallsPerTurn(\n cap: number | undefined,\n): number | undefined {\n if (cap == null) return undefined\n if (!Number.isFinite(cap) || cap < 0) {\n throw new Error(\n `maxToolCallsPerTurn must be a non-negative finite number, got ${cap}`,\n )\n }\n return Math.floor(cap)\n}\n\n/**\n * Combine two optional AbortSignals into one that aborts when either does.\n * Returns the other signal directly when one is absent or already aborted.\n * (Manual implementation — `AbortSignal.any` requires Node >= 20.3.)\n */\nfunction combineAbortSignals(\n a: AbortSignal | undefined,\n b: AbortSignal | undefined,\n): AbortSignal | undefined {\n if (!a) return b\n if (!b) return a\n if (a.aborted) return a\n if (b.aborted) return b\n const controller = new AbortController()\n const onAbort = (source: AbortSignal) => () => {\n controller.abort(source.reason)\n }\n a.addEventListener('abort', onAbort(a), { once: true })\n b.addEventListener('abort', onAbort(b), { once: true })\n return controller.signal\n}\n\nclass TextEngine<\n TAdapter extends AnyTextAdapter,\n TContext = unknown,\n TParams extends TextOptions<any, any, TContext> = TextOptions<\n any,\n any,\n TContext\n >,\n> {\n private readonly adapter: TAdapter\n private params: TParams\n private systemPrompts: Array<SystemPrompt>\n private tools: Array<AnyRuntimeTool>\n private readonly loopStrategy: AgentLoopStrategy\n private toolCallManager: ToolCallManager<ReadonlyArray<AnyTool>, TContext>\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 /** Cumulative tool calls counted in this run (emitted + pending resume). */\n private toolCallCount = 0\n /** Tool calls in the most recent budgeted batch (0 when none). */\n private lastTurnToolCallCount = 0\n /** Tool call IDs already counted toward `toolCallCount` (avoids double-count on resume). */\n private readonly countedToolCallIds = new Set<string>()\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> | undefined\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 private readonly maxToolCallsPerTurn: number | undefined\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 readonly threadId: string\n private readonly runIdOverride?: string\n private readonly parentRunIdOverride?: string\n\n // Middleware support\n private readonly middlewareRunner: MiddlewareRunner<TContext>\n private readonly middlewareCtx: ChatMiddlewareContext<TContext>\n private readonly sandboxFileQueue: Array<StreamChunk> = []\n private readonly deferredPromises: Array<Promise<unknown>> = []\n private abortReason?: string\n private readonly middlewareAbortController?: AbortController\n // Combines the caller's signal with middleware abort() so running tools\n // observe both cancellation sources via ctx.abortSignal.\n private readonly toolAbortSignal?: AbortSignal\n private terminalHookCalled = false\n\n private readonly logger: InternalLogger\n\n // Structured-output finalization state (populated by runStructuredFinalization)\n private structuredOutputResult: { data: unknown; rawText: string } | null =\n null\n // Native combined mode: tracks whether we've already emitted the synthetic\n // `structured-output.start` event before the schema-constrained final-turn\n // text begins streaming. The event must precede the first\n // TEXT_MESSAGE_START so the client-side StreamProcessor routes the JSON\n // deltas into a StructuredOutputPart instead of a plain TextPart.\n private combinedStartEmitted = false\n // Native combined mode: messageId we want the synthetic\n // `structured-output.start` (and any error emitted before deltas arrive)\n // to carry, so the client matches it to the streaming text deltas.\n private combinedStructuredMessageId: string | null = null\n // Holds the validated value when `finalStructuredOutput.validate` is provided\n // and succeeds. Distinct from `structuredOutputResult.data` (the normalized\n // but unvalidated payload from the structured-output.complete chunk).\n private validatedStructuredOutput: unknown = undefined\n private hasValidatedStructuredOutput = false\n private finalizationError: {\n message: string\n code?: string\n cause?: unknown\n } | null = null\n private readonly finalStructuredOutput?: {\n jsonSchema: JSONSchema\n yieldChunks: boolean\n normalize?: (data: unknown) => unknown\n validate?: (data: unknown) => unknown\n nativeCombined?: boolean\n }\n\n constructor(\n config: TextEngineConfig<TAdapter, TContext, TParams>,\n logger: InternalLogger,\n ) {\n this.logger = logger\n this.adapter = config.adapter\n this.finalStructuredOutput = config.finalStructuredOutput\n this.params = config.params\n this.systemPrompts = config.params.systemPrompts || []\n this.loopStrategy =\n config.params.agentLoopStrategy || maxIterationsStrategy(5)\n this.maxToolCallsPerTurn = resolveMaxToolCallsPerTurn(\n config.params.maxToolCallsPerTurn,\n )\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(config.params.messages)\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 config.params.lazyToolsConfig,\n )\n this.tools = this.lazyToolManager.getActiveTools()\n this.toolCallManager = new ToolCallManager<\n ReadonlyArray<AnyTool>,\n TContext\n >(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 // `conversationId` is the legacy alias of `threadId` — accept it\n // as a fallback so `chat({ conversationId })` keeps working, with\n // explicit `threadId` winning when both are set.\n this.threadId =\n config.params.threadId ||\n config.params.conversationId ||\n this.createId('thread')\n this.runIdOverride = config.params.runId\n this.parentRunIdOverride = config.params.parentRunId\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: Array<ChatMiddleware<TContext>> = [\n devtoolsMiddleware(),\n ...(config.middleware || []),\n stripToSpecMiddleware(),\n ]\n this.middlewareRunner = new MiddlewareRunner(allMiddleware, logger)\n this.middlewareAbortController = new AbortController()\n this.toolAbortSignal = combineAbortSignals(\n this.effectiveSignal,\n this.middlewareAbortController.signal,\n )\n this.middlewareCtx = {\n requestId: this.requestId,\n streamId: this.streamId,\n runId: this.runIdOverride ?? this.requestId,\n threadId: this.threadId,\n // Legacy alias kept on the ctx so middleware that reads\n // `ctx.conversationId` keeps working. Always equals `threadId`.\n conversationId: this.threadId,\n phase: 'init',\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 as TContext,\n defer: (promise: Promise<unknown>) => {\n this.deferredPromises.push(promise)\n },\n // Provider / adapter info\n activity: 'chat',\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 // Capability bookkeeping for this request (populated by middleware setup)\n capabilities: new CapabilityRegistry(),\n // Convenience accessors that delegate to a capability handle's own\n // tuple getter/provider, keyed by this context. `getX(ctx)` and\n // `ctx.get(X)` are interchangeable.\n get: (capability) => capability[0](this.middlewareCtx),\n getOptional: (capability) =>\n capability[0](this.middlewareCtx, { optional: true }),\n provide: (capability, value) => capability[1](this.middlewareCtx, value),\n }\n\n // Provide the internal SandboxRuntime capability so harness adapters and\n // sandbox middleware can emit file events. The sink logs, fans the event\n // out through the middleware `onFile*` hooks (fire-and-forget), and queues\n // a `sandbox.file` custom chunk to be drained into the public stream.\n provideSandboxRuntime(this.middlewareCtx, {\n logger: this.logger,\n emit: (event: SandboxFileHookEvent) => {\n this.logger.sandbox(`file ${event.type} ${event.path}`, {\n event: {\n type: event.type,\n path: event.path,\n timestamp: event.timestamp,\n },\n })\n void this.middlewareRunner\n .runSandboxFile(this.middlewareCtx, event)\n .catch((err: unknown) => {\n this.logger.errors('sandbox file hook failed', { error: err })\n })\n this.sandboxFileQueue.push(\n this.createCustomEventChunk('sandbox.file', {\n type: event.type,\n path: event.path,\n timestamp: event.timestamp,\n }),\n )\n },\n emitFileDiff: (value: { path: string; diff: string }) => {\n this.sandboxFileQueue.push(\n this.createCustomEventChunk('sandbox.file.diff', value),\n )\n },\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 /** Returns the structured-output result if finalization ran successfully. */\n getStructuredOutputResult(): { data: unknown; rawText: string } | null {\n return this.structuredOutputResult\n }\n\n /**\n * Returns the validated structured-output value (the result of running\n * `finalStructuredOutput.validate` against the raw structured-output data)\n * wrapped in a `{ value }` object so callers can distinguish \"no validation\n * happened\" from \"validation produced undefined\". Returns `null` when no\n * validator was configured or validation hasn't been performed yet.\n */\n getValidatedStructuredOutput(): { value: unknown } | null {\n return this.hasValidatedStructuredOutput\n ? { value: this.validatedStructuredOutput }\n : null\n }\n\n /** Returns the recorded finalization error, if any. */\n getFinalizationError(): {\n message: string\n code?: string\n cause?: unknown\n } | null {\n return this.finalizationError\n }\n\n async *run(): AsyncGenerator<StreamChunk> {\n this.beforeRun()\n this.logger.agentLoop('run started', {\n threadId: this.middlewareCtx.threadId,\n })\n\n try {\n // Provision capabilities before any consumer (onConfig onward) can read them\n await this.middlewareRunner.runSetup(this.middlewareCtx)\n\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 // Skip the agent loop entirely when there are no tools AND a separate\n // structured-output finalization will run. Without tools the model has\n // nothing to do in the loop, so executing one iteration would burn an\n // extra provider call before the finalization request.\n //\n // Native combined mode does NOT skip — the agent loop itself produces\n // the schema-constrained final answer in one pass (model emits the\n // schema-constrained text on its natural final turn). Even with zero\n // tools, the single chatStream call IS the structured-output call.\n const skipAgentLoop =\n !!this.finalStructuredOutput &&\n this.tools.length === 0 &&\n this.finalStructuredOutput.nativeCombined !== true\n\n if (!skipAgentLoop) {\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 iterTransformedConfig =\n await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n iterConfig,\n )\n this.applyMiddlewareConfig(iterTransformedConfig)\n\n yield* this.streamModelResponse()\n } else {\n yield* this.processToolCalls()\n }\n\n this.endCycle()\n } while (this.shouldContinue())\n }\n\n this.logger.agentLoop('run finished', {\n finishReason: this.lastFinishReason,\n })\n\n // After the agent loop ends, if a structured-output finalization was\n // requested AND the run hasn't already errored/aborted, run it through\n // the middleware pipeline. The terminal hook fires once at the very\n // end (after finalization), not after the agent loop.\n //\n // Native combined mode takes a different path: the agent loop's final-\n // turn text IS the schema-constrained JSON, so we harvest it from\n // `accumulatedContent` instead of issuing a second provider call.\n if (\n this.finalStructuredOutput &&\n !this.isCancelled() &&\n !this.finalizationError\n ) {\n if (this.finalStructuredOutput.nativeCombined === true) {\n yield* this.harvestCombinedStructuredOutput()\n } else {\n yield* this.runStructuredFinalization()\n }\n }\n\n // Call terminal hook (skip when waiting for client — stream is paused, not finished).\n // Priority: finalizationError → onError; otherwise normal onFinish.\n // Skip on cancellation — the finally block routes aborts to onAbort.\n if (\n !this.terminalHookCalled &&\n this.toolPhase !== 'wait' &&\n !this.isCancelled()\n ) {\n if (this.finalizationError) {\n this.terminalHookCalled = true\n const errForHook = new Error(\n this.finalizationError.message,\n this.finalizationError.cause !== undefined\n ? { cause: this.finalizationError.cause }\n : undefined,\n )\n if (this.finalizationError.code !== undefined) {\n Object.defineProperty(errForHook, 'code', {\n value: this.finalizationError.code,\n enumerable: true,\n })\n }\n await this.middlewareRunner.runOnError(this.middlewareCtx, {\n error: errForHook,\n duration: Date.now() - this.streamStartTime,\n })\n } else {\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 }\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 threadId: this.middlewareCtx.threadId,\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, metadata } = this.params\n\n // Gather flattened options into an object for context\n const options: Record<string, unknown> = {}\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 { 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 // When the adapter declared `supportsCombinedToolsAndSchema()`, the\n // activity layer set `nativeCombined: true` and we forward the\n // pre-converted JSON Schema into the regular chatStream call. The\n // adapter wires it into the upstream request (e.g. `response_format`,\n // `text.format`, `output_format`) so the model's final-turn text is\n // schema-constrained and the engine can harvest it from the agent loop\n // without a separate finalization round-trip.\n const combinedSchema =\n this.finalStructuredOutput?.nativeCombined === true\n ? this.finalStructuredOutput.jsonSchema\n : undefined\n\n for await (const chunk of this.adapter.chatStream({\n model: this.params.model,\n messages: this.messages,\n tools: toolsWithJsonSchemas,\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 parentRunId: this.parentRunIdOverride,\n // Expose provided capabilities (e.g. sandbox) to harness adapters.\n capabilities: this.middlewareCtx,\n // Client approval decisions, for harness interactive-approval resolution.\n approvals: this.initialApprovals,\n ...(combinedSchema ? { outputSchema: combinedSchema } : {}),\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 // Native combined mode: synthesize `structured-output.start` BEFORE\n // the first TEXT_MESSAGE_START so the client-side StreamProcessor\n // routes the schema-constrained JSON deltas into a\n // StructuredOutputPart. We delay synthesis until we actually see\n // text starting — intermediate tool-call iterations don't need it,\n // and emitting at run-start would wrap tool-call commentary into a\n // structured-output part too.\n if (\n this.finalStructuredOutput?.nativeCombined === true &&\n this.finalStructuredOutput.yieldChunks &&\n !this.combinedStartEmitted &&\n chunk.type === EventType.TEXT_MESSAGE_START\n ) {\n this.combinedStartEmitted = true\n const messageId =\n typeof chunk.messageId === 'string' && chunk.messageId !== ''\n ? chunk.messageId\n : generateMessageId()\n this.combinedStructuredMessageId = messageId\n const synthStart: StreamChunk = {\n type: EventType.CUSTOM,\n name: 'structured-output.start',\n value: { messageId },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n const synthOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n synthStart,\n )\n for (const outputChunk of synthOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\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 // When a streaming structured-output finalization step will run after\n // the agent loop, suppress the agent-loop's RUN_STARTED/RUN_FINISHED\n // here — the finalization step emits the single outer lifecycle pair\n // that reaches the consumer.\n //\n // Native combined mode does NOT issue a second adapter stream — the\n // agent loop's lifecycle IS the outer pair the consumer sees.\n const suppressAgentLifecycle =\n !!this.finalStructuredOutput &&\n this.finalStructuredOutput.yieldChunks &&\n this.finalStructuredOutput.nativeCombined !== true\n for (const outputChunk of outputChunks) {\n if (\n suppressAgentLifecycle &&\n (outputChunk.type === EventType.RUN_STARTED ||\n outputChunk.type === EventType.RUN_FINISHED)\n ) {\n continue\n }\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 // Drain any sandbox.file events emitted while processing this chunk.\n yield* this.drainSandboxFileQueue()\n\n if (this.earlyTermination) {\n break\n }\n }\n\n // Drain any remaining sandbox.file events emitted after the stream ended.\n yield* this.drainSandboxFileQueue()\n }\n\n private handleStreamChunk(chunk: StreamChunk): void {\n // eslint-disable-next-line @typescript-eslint/switch-exhaustiveness-check -- AG-UI EventType enum members vs string-literal case labels; default branch handles untraced events.\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 /**\n * Tools available for execution this turn. The discovery tool is dropped\n * from the advertised set (`this.tools`) once every lazy tool is discovered,\n * but a model may still re-request discovery; this widens execution lookup\n * to include it so such calls don't fail with \"Unknown tool\". Centralised so\n * both execution sites (`processToolCalls` and `checkForPendingToolCalls`)\n * stay in sync.\n */\n private resolveExecutableTools(\n toolCalls: ReadonlyArray<ToolCall>,\n ): ReadonlyArray<AnyTool> {\n return this.lazyToolManager.getExecutableTools(\n this.tools,\n toolCalls.map((tc) => tc.function.name),\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 // Same fan-out budget as live model turns (seeded history / resume).\n // Count is deduped so wait→resume after a live turn does not double-count.\n const { toExecute: budgetedToolCalls, skippedResults } =\n this.applyToolCallBudget(pendingToolCalls)\n\n // Handle undiscovered lazy tool calls with self-correcting error messages\n const undiscoveredLazyResults: Array<ToolResult> = []\n const executablePendingCalls = budgetedToolCalls.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 // Non-executed outcomes (undiscovered lazy + per-turn fan-out skips).\n // Emitted after executed results so the stream prefers real results first.\n const deferredErrorResults = [...undiscoveredLazyResults, ...skippedResults]\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 (executablePendingCalls.length === 0) {\n if (deferredErrorResults.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n deferredErrorResults,\n finishEvent,\n argsMap,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\n return 'continue'\n }\n\n const { approvals, clientToolResults } = this.collectClientState()\n\n const generator = executeToolCalls(\n executablePendingCalls,\n this.resolveExecutableTools(executablePendingCalls),\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 this.middlewareCtx.context,\n this.toolAbortSignal,\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 const allResults = [...executionResult.results, ...deferredErrorResults]\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: allResults,\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 (allResults.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n allResults,\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 allResults,\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 // Text-only turn — clear per-turn count so strategies see 0 tools.\n this.lastTurnToolCallCount = 0\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.lastTurnToolCallCount = 0\n this.setToolPhase('stop')\n return\n }\n\n // Count every model-emitted tool call (including ones we may skip).\n const { toExecute: budgetedToolCalls, skippedResults } =\n this.applyToolCallBudget(toolCalls)\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 = budgetedToolCalls.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 // Non-executed outcomes (undiscovered lazy + per-turn fan-out skips).\n // Emitted after executed results so the stream prefers real results first.\n const deferredErrorResults = [...undiscoveredLazyResults, ...skippedResults]\n\n if (executableToolCalls.length === 0) {\n // All tool calls were undiscovered lazy tools and/or skipped by the\n // per-turn fan-out cap — errors emitted, continue loop (strategy may stop).\n if (deferredErrorResults.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n deferredErrorResults,\n finishEvent,\n )) {\n yield* this.pipeThroughMiddleware(chunk)\n }\n }\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.resolveExecutableTools(executableToolCalls),\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 this.middlewareCtx.context,\n this.toolAbortSignal,\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 // Executed results first, then deferred errors (fan-out skips / undiscovered)\n const allResults = [...executionResult.results, ...deferredErrorResults]\n\n // Notify middleware of tool phase completion (devtools emits aggregate events here)\n await this.middlewareRunner.runOnToolPhaseComplete(this.middlewareCtx, {\n toolCalls,\n results: allResults,\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 (allResults.length > 0) {\n for (const chunk of this.buildToolResultChunks(\n allResults,\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(allResults, finishEvent)\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<\n ReadonlyArray<AnyTool>,\n TContext\n >(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\n // uiMessageToModelMessages). Multimodal results carry an\n // Array<ContentPart> directly — pass it through without parsing.\n let output: unknown\n if (Array.isArray(message.content)) {\n output = message.content\n } else {\n try {\n output = JSON.parse(message.content as string)\n } catch {\n output = message.content\n }\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 // `content` is the canonical value for the tool `ModelMessage` — it may\n // be an `Array<ContentPart>` (multimodal) which the adapters convert to\n // structured provider output on the next iteration. `wireContent` is the\n // string form emitted on the AG-UI stream events (TOOL_CALL_END.result /\n // TOOL_CALL_RESULT.content are string-only per the AG-UI spec); the\n // multimodal array travels via the message itself, not the wire event.\n const content = normalizeToolResult(result.result)\n const wireContent =\n typeof content === 'string' ? content : JSON.stringify(content)\n\n // argsMap is set only on continuation re-executions, where the adapter\n // never streamed these calls. Otherwise it already emitted END, so a\n // second one here would be an orphan that fails verifyEvents (#519).\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 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: wireContent,\n ...(result.state !== undefined && { state: result.state }),\n } as StreamChunk)\n }\n\n // AG-UI spec TOOL_CALL_RESULT event (content is string-only per spec)\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: wireContent,\n role: 'tool',\n ...(result.state !== undefined && { state: result.state }),\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 // Provider-executed tool calls (e.g. Anthropic `web_search`) were\n // already run by the provider; they carry no client result, so they\n // would otherwise look \"pending\" forever and the loop would try (and\n // fail) to execute them client-side. Skip them.\n if (isProviderExecutedToolCall(toolCall)) {\n continue\n }\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 toolCallCount: this.toolCallCount,\n lastTurnToolCallCount: this.lastTurnToolCallCount,\n }) && this.toolPhase === 'continue'\n )\n }\n\n /**\n * Record tool calls (deduped by id) and return the subset that should be\n * executed after applying `maxToolCallsPerTurn`. Excess calls get synthetic\n * error results so every tool_call still has a matching result.\n *\n * Used for both live model turns and pending/resume batches. IDs already\n * counted in this run (e.g. wait→resume after a live turn) are not\n * re-added to `toolCallCount`.\n */\n private applyToolCallBudget(toolCalls: Array<ToolCall>): {\n toExecute: Array<ToolCall>\n skippedResults: Array<ToolResult>\n } {\n this.lastTurnToolCallCount = toolCalls.length\n let newlyCounted = 0\n for (const tc of toolCalls) {\n if (!this.countedToolCallIds.has(tc.id)) {\n this.countedToolCallIds.add(tc.id)\n newlyCounted++\n }\n }\n this.toolCallCount += newlyCounted\n\n const cap = this.maxToolCallsPerTurn\n if (cap == null || toolCalls.length <= cap) {\n return { toExecute: toolCalls, skippedResults: [] }\n }\n\n this.logger.agentLoop(\n `maxToolCallsPerTurn=${cap} skipped=${toolCalls.length - cap}`,\n {\n maxToolCallsPerTurn: cap,\n emitted: toolCalls.length,\n skipped: toolCalls.length - cap,\n },\n )\n\n const toExecute = toolCalls.slice(0, cap)\n const skippedResults: Array<ToolResult> = toolCalls\n .slice(cap)\n .map((tc) => ({\n toolCallId: tc.id,\n toolName: tc.function.name,\n result: {\n error: `Skipped: exceeded maxToolCallsPerTurn (${cap})`,\n },\n state: 'output-error' as const,\n }))\n\n return { toExecute, skippedResults }\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 /**\n * Run the final structured-output adapter call through the middleware\n * pipeline. Yields chunks to the caller only when\n * `this.finalStructuredOutput.yieldChunks` is true; otherwise consumes\n * silently while still piping through middleware.\n *\n * On success, populates this.structuredOutputResult.\n * On failure, populates this.finalizationError.\n */\n private async *runStructuredFinalization(): AsyncGenerator<StreamChunk> {\n if (!this.finalStructuredOutput) {\n throw new Error(\n 'runStructuredFinalization called without finalStructuredOutput config',\n )\n }\n\n this.middlewareCtx.phase = 'structuredOutput'\n\n // Build the structured-output config view. `tools` is intentionally\n // excluded from the type because it isn't forwarded to the structured-\n // output adapter call — including it here would be misleading API.\n const baseConfig = this.buildMiddlewareConfig()\n const { tools: _omitTools, ...baseWithoutTools } = baseConfig\n let structuredConfig: StructuredOutputMiddlewareConfig = {\n ...baseWithoutTools,\n outputSchema: this.finalStructuredOutput.jsonSchema,\n }\n\n // 1) onStructuredOutputConfig — middleware can transform messages, options, outputSchema\n structuredConfig = await this.middlewareRunner.runOnStructuredOutputConfig(\n this.middlewareCtx,\n structuredConfig,\n )\n\n // 2) onConfig — phase-aware general-purpose middleware re-runs at the\n // boundary. Re-attach the engine's current tools so onConfig observers\n // see the live tool set (they still won't be forwarded to the structured\n // call — same constraint applies — but the view is consistent with the\n // ChatMiddlewareConfig shape).\n const { outputSchema: pinnedSchema, ...chatConfigSlice } = structuredConfig\n const postOnConfig = await this.middlewareRunner.runOnConfig(\n this.middlewareCtx,\n { ...chatConfigSlice, tools: baseConfig.tools },\n )\n\n // Apply merged config back to engine state\n this.applyMiddlewareConfig(postOnConfig)\n\n // Build the StructuredOutputOptions the adapter expects.\n // `this.adapter` is already `TAdapter extends AnyTextAdapter` per the\n // class generics — no cast needed.\n const structuredCallOptions = {\n chatOptions: {\n model: this.params.model,\n messages: this.messages,\n metadata: postOnConfig.metadata,\n modelOptions: postOnConfig.modelOptions,\n systemPrompts: postOnConfig.systemPrompts,\n logger: this.logger,\n threadId: this.threadId,\n runId: this.runIdOverride,\n parentRunId: this.parentRunIdOverride,\n ...(this.effectiveRequest ? { request: this.effectiveRequest } : {}),\n },\n outputSchema: pinnedSchema,\n }\n\n // Select the provider call: native streaming if available, else synthesized fallback.\n // The fallback path captures the original adapter error so the engine can\n // attach it as `finalizationError.cause` (the RUN_ERROR wire shape only\n // carries `message` and `code`, losing stack/cause/provider properties).\n let fallbackAdapterError: unknown = undefined\n const providerStream = this.adapter.structuredOutputStream\n ? this.adapter.structuredOutputStream(structuredCallOptions)\n : fallbackStructuredOutputStream(\n this.adapter,\n structuredCallOptions,\n (err) => {\n fallbackAdapterError = err\n },\n )\n\n // ============================================================\n // structured-output.start synthesis\n // ============================================================\n // The client-side StreamProcessor (PR #577) requires a CUSTOM\n // `structured-output.start` event BEFORE the JSON TEXT_MESSAGE_CONTENT\n // deltas — that's how it routes deltas into a `StructuredOutputPart`\n // rather than a plain `TextPart`. No adapter currently emits this,\n // so the engine synthesizes one (and tracks whether the adapter\n // emitted its own to avoid duplicating).\n //\n // Synthesis fires before the FIRST TEXT_MESSAGE_* event from the inner\n // stream, OR before a pre-delta RUN_ERROR (so the client can construct\n // an errored structured-output placeholder).\n let startEmitted = false\n let structuredMessageId: string | null = null\n\n const extractMessageId = (c: StreamChunk): string | null => {\n if (\n c.type === EventType.TEXT_MESSAGE_START ||\n c.type === EventType.TEXT_MESSAGE_CONTENT ||\n c.type === EventType.TEXT_MESSAGE_END\n ) {\n return typeof c.messageId === 'string' && c.messageId !== ''\n ? c.messageId\n : null\n }\n return null\n }\n\n const buildSynthesizedStart = (): StreamChunk => {\n const idForStart = structuredMessageId ?? generateMessageId()\n structuredMessageId = idForStart\n return {\n type: EventType.CUSTOM,\n name: 'structured-output.start',\n value: { messageId: idForStart },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n }\n\n const pipeThroughMiddleware = async (\n synthChunk: StreamChunk,\n ): Promise<Array<StreamChunk>> =>\n this.middlewareRunner.runOnChunk(this.middlewareCtx, synthChunk)\n\n // Track whether a RUN_ERROR has been yielded to streaming consumers so\n // we don't emit a duplicate synthetic one at the end.\n let runErrorYielded = false\n\n // Pipe chunks through middleware; yield to consumer only when yieldChunks=true\n for await (const chunk of providerStream) {\n // Honor cancellation between chunks (mirrors streamModelResponse).\n if (this.isCancelled()) {\n break\n }\n\n // Detect adapter-emitted structured-output.start so we don't duplicate\n if (\n !startEmitted &&\n chunk.type === EventType.CUSTOM &&\n chunk.name === 'structured-output.start'\n ) {\n startEmitted = true\n }\n\n // Capture the assistant messageId off any text-message event so the\n // synthesized start (when needed) uses the SAME id the deltas carry\n if (!structuredMessageId) {\n const extracted = extractMessageId(chunk)\n if (extracted) structuredMessageId = extracted\n }\n\n // Synthesis only matters for the streaming client path — the agentic\n // Promise path consumes chunks internally and returns a Promise, so\n // there's no client-side StreamProcessor to route deltas for.\n if (this.finalStructuredOutput.yieldChunks) {\n // Synthesize start before the FIRST TEXT_MESSAGE_* event\n if (\n !startEmitted &&\n (chunk.type === EventType.TEXT_MESSAGE_START ||\n chunk.type === EventType.TEXT_MESSAGE_CONTENT ||\n chunk.type === EventType.TEXT_MESSAGE_END)\n ) {\n startEmitted = true\n const synthStart = buildSynthesizedStart()\n const synthOutputs = await pipeThroughMiddleware(synthStart)\n for (const outputChunk of synthOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // Synthesize start before a pre-delta RUN_ERROR so the client can\n // construct an errored placeholder structured-output part instead\n // of a silent UI.\n if (!startEmitted && chunk.type === EventType.RUN_ERROR) {\n startEmitted = true\n const synthStart = buildSynthesizedStart()\n const synthOutputs = await pipeThroughMiddleware(synthStart)\n for (const outputChunk of synthOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n }\n\n // 7a. Targeted state updates only.\n // We deliberately do NOT call `handleStreamChunk(chunk)` here — that\n // would mutate agent-loop state with finalization data:\n // - TEXT_MESSAGE_CONTENT deltas would pollute `accumulatedContent`\n // (raw JSON would leak into `info.content` on onFinish)\n // - RUN_FINISHED would overwrite `finishedEvent` + `lastFinishReason`\n // (finalization's 'stop' would overwrite the agent-loop's real\n // finish reason)\n // - STEP_FINISHED would pollute `currentThinkingContent`\n // Finalization is a separate phase from the agent loop; its state must\n // not cross-contaminate. The explicit branches below capture the only\n // bits we actually need from this stream.\n // All narrowing below is via the discriminated-union `chunk.type`\n // — no `as` casts.\n\n // The chunk forwarded to middleware/consumers. Replaced below only for\n // the structured-output.complete event, whose `object` we normalize\n // (un-widen) so streaming consumers see the same cleaned payload the\n // Promise<T> path validates and returns.\n let outboundChunk: StreamChunk = chunk\n\n if (\n chunk.type === EventType.CUSTOM &&\n chunk.name === 'structured-output.complete'\n ) {\n const parsed = readStructuredOutputCompleteValue(chunk.value)\n if (parsed) {\n const object = this.finalStructuredOutput.normalize\n ? this.finalStructuredOutput.normalize(parsed.object)\n : parsed.object\n this.structuredOutputResult = { data: object, rawText: parsed.raw }\n // Rewrite the outbound event so the yielded chunk carries the\n // normalized object (the original `chunk.value` still holds the\n // widened one). Preserve every other field — `raw`, `reasoning` —\n // by spreading the original value.\n const value = chunk.value\n if (object !== parsed.object && value && typeof value === 'object') {\n outboundChunk = { ...chunk, value: { ...value, object } }\n }\n }\n }\n\n if (chunk.type === EventType.RUN_FINISHED && chunk.usage) {\n // RunFinishedEvent already exposes `usage` after type narrowing.\n await this.middlewareRunner.runOnUsage(this.middlewareCtx, chunk.usage)\n }\n\n if (chunk.type === EventType.RUN_ERROR) {\n // RunErrorEvent already exposes `message` and `code` after narrowing.\n this.finalizationError = {\n message: chunk.message,\n ...(chunk.code ? { code: chunk.code } : {}),\n ...(fallbackAdapterError !== undefined\n ? { cause: fallbackAdapterError }\n : {}),\n }\n }\n\n // 7b. Pipe through middleware\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n outboundChunk,\n )\n\n // 7c. Decide consumer visibility — only yieldChunks=true callers get them.\n // We do NOT strip the finalization stream's RUN_STARTED/RUN_FINISHED:\n // they are the single outer lifecycle pair the consumer sees (the\n // agent-loop's pair was suppressed in streamModelResponse when\n // finalStructuredOutput.yieldChunks is true).\n if (this.finalStructuredOutput.yieldChunks) {\n for (const outputChunk of outputChunks) {\n if (outputChunk.type === EventType.RUN_ERROR) {\n runErrorYielded = true\n }\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // 7d. Terminate on error\n if (this.finalizationError) {\n break\n }\n }\n\n // Mid-finalization abort: don't attribute a missing-result error.\n // Let the engine's `finally` block in `run()` route to `onAbort` instead\n // of mis-routing through `onError`.\n if (this.isCancelled()) {\n return\n }\n\n // Empty stream / missing complete event\n if (!this.structuredOutputResult && !this.finalizationError) {\n this.finalizationError = {\n message: 'missing structured result',\n code: 'structured-output-missing-result',\n }\n }\n\n // Run schema validation INSIDE the engine — before the terminal hook\n // chooser runs. Per spec §7.3, validation failures must route through\n // `onError`, not `onFinish`. We do this by writing to `finalizationError`\n // so the chooser in `run()` picks `onError`.\n if (\n this.structuredOutputResult &&\n !this.finalizationError &&\n this.finalStructuredOutput.validate\n ) {\n try {\n const validated = this.finalStructuredOutput.validate(\n this.structuredOutputResult.data,\n )\n this.validatedStructuredOutput = validated\n this.hasValidatedStructuredOutput = true\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n this.finalizationError = {\n message,\n code: 'structured-output-validation-failed',\n cause: err,\n }\n }\n }\n\n // Streaming consumers must see a RUN_ERROR for finalization failures\n // (missing-result, validation-failed, or a finalizationError set after\n // a structured-output.complete already yielded). Without this synthetic\n // emission, the `for await` on the engine ends silently for the client.\n //\n // Skip when a RUN_ERROR was already yielded from the inner stream\n // (otherwise the consumer would see two error events for one failure).\n if (\n this.finalizationError &&\n this.finalStructuredOutput.yieldChunks &&\n !runErrorYielded\n ) {\n // Empty-stream case: no in-loop synthesis fired because no chunks\n // arrived. Synthesize `structured-output.start` here so the client-side\n // StreamProcessor can route the upcoming RUN_ERROR to a\n // `StructuredOutputPart` instead of dropping it as an orphan error.\n if (!startEmitted) {\n const synthStart = buildSynthesizedStart()\n const startOutputs = await pipeThroughMiddleware(synthStart)\n for (const outputChunk of startOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n startEmitted = true\n }\n\n const errChunk: StreamChunk = {\n type: EventType.RUN_ERROR,\n runId: this.runIdOverride ?? this.requestId,\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n error: {\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n },\n }\n const outputChunks = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n errChunk,\n )\n for (const outputChunk of outputChunks) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n }\n\n /**\n * Native combined mode: harvest the structured output from the agent\n * loop's accumulated final-turn text (no separate provider call).\n *\n * The adapter wired `outputSchema` into the regular `chatStream` request,\n * so the model's final-turn text is the schema-constrained JSON. We parse\n * `this.accumulatedContent`, populate `this.structuredOutputResult`, emit\n * a synthetic `structured-output.complete` (and a `structured-output.start`\n * if one wasn't emitted earlier — only happens on the streaming path when\n * the model returned no text at all), and run the validate callback when\n * present. Failures populate `this.finalizationError` so the engine's\n * terminal-hook chooser routes to `onError` (per spec §7.3).\n *\n * The `'structuredOutput'` middleware phase intentionally does NOT fire on\n * this path — middleware sees the run through `beforeModel` / `modelStream`\n * as usual. See PR #605 / issue #605 for the design rationale.\n */\n private async *harvestCombinedStructuredOutput(): AsyncGenerator<StreamChunk> {\n if (!this.finalStructuredOutput) {\n throw new Error(\n 'harvestCombinedStructuredOutput called without finalStructuredOutput config',\n )\n }\n\n const yieldChunks = this.finalStructuredOutput.yieldChunks\n const rawText = this.accumulatedContent\n\n // Empty final-turn text means the agent loop terminated without the\n // model emitting any assistant content (e.g. early termination after\n // tool calls). Mirror the fallback path's \"missing structured result\"\n // error rather than silently returning undefined.\n if (rawText.length === 0) {\n this.finalizationError = {\n message: 'missing structured result',\n code: 'structured-output-missing-result',\n }\n } else {\n try {\n const parsed: unknown = JSON.parse(rawText)\n // Normalize (un-widen) before storing so the synthesized\n // structured-output.complete chunk and the Promise<T> result both\n // carry the cleaned payload. JSON.parse preserves provider nulls, so\n // this is where native-combined output gets its widening undone.\n const data = this.finalStructuredOutput.normalize\n ? this.finalStructuredOutput.normalize(parsed)\n : parsed\n this.structuredOutputResult = { data, rawText }\n } catch (err: unknown) {\n const detail =\n rawText.slice(0, 200) + (rawText.length > 200 ? '...' : '')\n this.finalizationError = {\n message: `Failed to parse structured output as JSON. Content: ${detail}`,\n code: 'structured-output-parse-failed',\n cause: err,\n }\n }\n }\n\n // Validate against the Standard Schema (when supplied). Validation\n // failures route through onError just like the fallback path.\n if (\n this.structuredOutputResult &&\n !this.finalizationError &&\n this.finalStructuredOutput.validate\n ) {\n try {\n const validated = this.finalStructuredOutput.validate(\n this.structuredOutputResult.data,\n )\n this.validatedStructuredOutput = validated\n this.hasValidatedStructuredOutput = true\n } catch (err: unknown) {\n const message = err instanceof Error ? err.message : String(err)\n this.finalizationError = {\n message,\n code: 'structured-output-validation-failed',\n cause: err,\n }\n }\n }\n\n if (!yieldChunks) {\n // Promise<T> path: state is populated, nothing to yield. The\n // activity-layer caller pulls `structuredOutputResult` /\n // `validatedStructuredOutput` directly.\n return\n }\n\n // Streaming path: emit a synthetic `structured-output.start` if the\n // model produced no text at all (so the client snaps an errored\n // StructuredOutputPart rather than nothing). The normal path already\n // emitted start before the first TEXT_MESSAGE_START in\n // `streamModelResponse`.\n if (!this.combinedStartEmitted) {\n this.combinedStartEmitted = true\n const messageId = this.combinedStructuredMessageId ?? generateMessageId()\n this.combinedStructuredMessageId = messageId\n const synthStart: StreamChunk = {\n type: EventType.CUSTOM,\n name: 'structured-output.start',\n value: { messageId },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n const startOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n synthStart,\n )\n for (const outputChunk of startOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // On success, emit the synthetic `structured-output.complete` carrying\n // the parsed object + raw text. Pin the messageId so the client-side\n // handler can target the right UIMessage even when the agent loop's\n // terminal RUN_FINISHED has already cleared `activeMessageIds` (the\n // complete event yields AFTER the loop ends, by which point\n // `getActiveAssistantMessageId()` returns null and would otherwise drop\n // the event silently).\n if (this.structuredOutputResult && !this.finalizationError) {\n const completeChunk: StreamChunk = {\n type: EventType.CUSTOM,\n name: 'structured-output.complete',\n value: {\n object: this.structuredOutputResult.data,\n raw: this.structuredOutputResult.rawText,\n ...(this.combinedStructuredMessageId\n ? { messageId: this.combinedStructuredMessageId }\n : {}),\n },\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n ...(this.runIdOverride ? { runId: this.runIdOverride } : {}),\n }\n const completeOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n completeChunk,\n )\n for (const outputChunk of completeOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n\n // On failure, emit a synthetic RUN_ERROR so the streaming consumer's\n // `for await` doesn't end silently. Mirrors the fallback path.\n if (this.finalizationError) {\n const errChunk: StreamChunk = {\n type: EventType.RUN_ERROR,\n runId: this.runIdOverride ?? this.requestId,\n model: this.params.model,\n timestamp: Date.now(),\n threadId: this.threadId,\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n error: {\n message: this.finalizationError.message,\n ...(this.finalizationError.code\n ? { code: this.finalizationError.code }\n : {}),\n },\n }\n const errOutputs = await this.middlewareRunner.runOnChunk(\n this.middlewareCtx,\n errChunk,\n )\n for (const outputChunk of errOutputs) {\n yield outputChunk\n this.middlewareCtx.chunkIndex++\n }\n }\n }\n\n private buildMiddlewareConfig(): ChatMiddlewareConfig {\n return {\n messages: this.messages,\n systemPrompts: [...this.systemPrompts],\n tools: [...this.tools],\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 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 queued `sandbox.file` chunks (emitted via the SandboxRuntime sink)\n * through the middleware pipeline and into the public stream.\n */\n private async *drainSandboxFileQueue(): AsyncGenerator<StreamChunk> {\n while (this.sandboxFileQueue.length > 0) {\n const chunk = this.sandboxFileQueue.shift()\n if (chunk) yield* this.pipeThroughMiddleware(chunk)\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 === 'TEXT_MESSAGE_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 const TTools extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['tools'] = TextActivityOptions<TAdapter, TSchema, TStream, any>['tools'],\n const TMiddleware extends TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'] = TextActivityOptions<\n TAdapter,\n TSchema,\n TStream,\n any\n >['middleware'],\n>(\n options: TextActivityOptionsWithContext<\n TAdapter,\n TSchema,\n TStream,\n TTools,\n TMiddleware\n >,\n): TextActivityResult<TSchema, TStream> {\n validateCapabilities(options.middleware ?? [], options.adapter)\n\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<TContext = unknown>(\n options: TextActivityOptions<AnyTextAdapter, undefined, true, TContext>,\n): AsyncIterable<StreamChunk> {\n const { adapter, middleware, context, debug, mcp, ...textOptions } = options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n const mcpManager = MCPManager.from(mcp)\n const mcpTools = await mcpManager.discover()\n if (mcpTools.length > 0) {\n textOptions.tools = [...(textOptions.tools ?? []), ...mcpTools]\n }\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 TContext\n >,\n middleware,\n context,\n },\n logger,\n )\n\n try {\n for await (const chunk of engine.run()) {\n yield chunk\n }\n } finally {\n await mcpManager.dispose()\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<TContext = unknown>(\n options: TextActivityOptions<AnyTextAdapter, undefined, false, TContext>,\n): Promise<string> {\n // Run the streaming text and collect all text using streamToText.\n const stream = runStreamingText(\n // eslint-disable-next-line no-restricted-syntax -- generic-stream remap: caller is non-streaming (false), but runStreamingText is invoked internally to collect text; concrete `false`→`true` literals don't structurally overlap.\n options as unknown as TextActivityOptions<\n AnyTextAdapter,\n undefined,\n true,\n TContext\n >,\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<\n TSchema extends SchemaInput,\n TContext = unknown,\n>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, boolean, TContext>,\n): Promise<InferSchemaType<TSchema>> {\n const {\n adapter,\n outputSchema,\n middleware,\n context,\n debug,\n mcp,\n ...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 // Same strict-conversion as the streaming path (`forStructuredOutput: true`)\n // so the same Zod schema produces the same JSON Schema regardless of\n // stream mode — Promise<T> and stream:true must not diverge here. The same\n // pass also records a `nullWideningMap`: optional fields are widened to\n // `required` + nullable for the provider, which then returns `null` for an\n // absent optional — a `null` the original `.optional()` (`T | undefined`)\n // schema would otherwise reject. The map pinpoints exactly those synthesized\n // nulls so `undoNullWidening` can drop them while preserving the ones a\n // `.nullable()` field genuinely allows.\n const { jsonSchema, nullWideningMap } =\n convertSchemaForStructuredOutput(outputSchema)\n if (!jsonSchema) {\n throw new Error('Failed to convert output schema to JSON Schema')\n }\n\n // Un-widening runs in the engine the moment the structured output is\n // captured (`finalStructuredOutput.normalize`), so it applies uniformly to\n // every adapter and to both stream modes — the engine is the only layer\n // holding the schema's `nullWideningMap`. Validation then runs on the\n // already-normalized data, so `validate` is a plain Standard Schema parse.\n const normalize = (data: unknown): unknown =>\n undoNullWidening(data, nullWideningMap)\n\n // Validation runs INSIDE the engine (per spec §7.3) so validation failures\n // route through the engine's terminal-hook chooser as `onError`. We pass a\n // `validate` callback when the schema is a Standard Schema; otherwise we\n // pass through the (normalized) data and the engine returns it unchanged.\n const validate = isStandardSchema(outputSchema)\n ? (data: unknown): unknown =>\n parseWithStandardSchema<InferSchemaType<TSchema>>(outputSchema, data)\n : undefined\n\n // Per issue #605: same capability check as the streaming path. When the\n // adapter handles tools + schema natively, the engine skips the separate\n // structured-output finalization call and harvests the JSON from the\n // agent loop's accumulated final-turn text.\n const nativeCombined =\n adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true\n\n const mcpManager = MCPManager.from(mcp)\n const mcpTools = await mcpManager.discover()\n if (mcpTools.length > 0) {\n textOptions.tools = [...(textOptions.tools ?? []), ...mcpTools]\n }\n\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, unknown>,\n Record<string, unknown>,\n TContext\n >,\n middleware,\n context,\n finalStructuredOutput: {\n jsonSchema,\n yieldChunks: false,\n normalize,\n ...(validate ? { validate } : {}),\n ...(nativeCombined ? { nativeCombined: true } : {}),\n },\n },\n logger,\n )\n\n try {\n // Consume the stream — chunks pipe through middleware but are not yielded externally\n for await (const _chunk of engine.run()) {\n // intentionally empty\n }\n } finally {\n await mcpManager.dispose()\n }\n\n const finalizationError = engine.getFinalizationError()\n if (finalizationError) {\n const err = new Error(\n finalizationError.message,\n finalizationError.cause !== undefined\n ? { cause: finalizationError.cause }\n : undefined,\n )\n if (finalizationError.code !== undefined) {\n Object.defineProperty(err, 'code', {\n value: finalizationError.code,\n enumerable: true,\n })\n }\n throw err\n }\n\n // If a validator ran, return the validated value (typed by InferSchemaType\n // via the callback closure). Otherwise return the raw data.\n const validated = engine.getValidatedStructuredOutput()\n if (validated) {\n return validated.value as InferSchemaType<TSchema>\n }\n\n const result = engine.getStructuredOutputResult()\n if (!result) {\n throw new Error('structured output finalization produced no result')\n }\n return result.data as InferSchemaType<TSchema>\n}\n\n/**\n * Parse the `value` payload of a `structured-output.complete` CUSTOM event\n * into a typed shape, returning `null` if the runtime payload doesn't match.\n *\n * Uses an `unknown`-input runtime check rather than `as` casts so the engine\n * stays cast-free in its hot path.\n */\nfunction readStructuredOutputCompleteValue(\n value: unknown,\n): { object: unknown; raw: string; reasoning?: string } | null {\n if (typeof value !== 'object' || value === null) return null\n if (!('object' in value) || !('raw' in value)) return null\n const raw = (value as { raw: unknown }).raw\n if (typeof raw !== 'string') return null\n const reasoningField = (value as { reasoning?: unknown }).reasoning\n const reasoning =\n typeof reasoningField === 'string' ? reasoningField : undefined\n return {\n object: (value as { object: unknown }).object,\n raw,\n ...(reasoning !== undefined ? { reasoning } : {}),\n }\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 *\n * `onAdapterError`, when provided, is invoked with the raw error from\n * `adapter.structuredOutput` before the synthesized RUN_ERROR is yielded.\n * The engine uses this to preserve the original error (stack, cause, custom\n * properties like provider `status`/`code`) as `finalizationError.cause`,\n * because the RUN_ERROR wire shape only carries `message` and `code`.\n */\nasync function* fallbackStructuredOutputStream(\n adapter: AnyTextAdapter,\n options: StructuredOutputOptions<Record<string, unknown>>,\n onAdapterError?: (err: unknown) => void,\n): AsyncIterable<StreamChunk> {\n const { chatOptions } = options\n // Synthesize run/thread/message IDs only when the caller didn't supply them.\n // Prefix `fallback-` (not `mock-`) because this is production fallback code\n // used by adapters without native `structuredOutputStream`, not test fixtures.\n const fallbackRand = Math.random().toString(36).slice(2)\n const runId = chatOptions.runId ?? `fallback-${Date.now()}-${fallbackRand}`\n const threadId =\n chatOptions.threadId ?? `fallback-${Date.now()}-${fallbackRand}`\n const messageId = `fallback-${Date.now()}-${fallbackRand}`\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: StructuredOutputResult<unknown>\n try {\n result = await adapter.structuredOutput(options)\n } catch (error) {\n onAdapterError?.(error)\n const message = error instanceof Error ? error.message : String(error)\n yield {\n type: EventType.RUN_ERROR,\n runId,\n threadId,\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 // Forward adapter-reported token usage so consumers reading\n // `RUN_FINISHED.usage` (and the engine's `runOnUsage` middleware hook) see\n // it on the fallback path, mirroring the native streaming path. The\n // conditional spread avoids emitting `usage: undefined` for adapters that\n // don't report it. See #758.\n ...(result.usage ? { usage: result.usage } : {}),\n }\n}\n\n/**\n * Run streaming structured output via the TextEngine, with the engine's\n * `finalStructuredOutput.yieldChunks: true` mode. The agent loop's\n * RUN_STARTED/RUN_FINISHED are suppressed; the structured-output finalization\n * step's pair brackets the run for the consumer.\n *\n * Standard Schema *validation* is intentionally NOT run on this path — it is\n * the consumer's responsibility. This is a deliberate asymmetry vs.\n * `runAgenticStructuredOutput` (Promise<T> path), which DOES validate inside\n * the engine and routes validation failures through `onError`. The reason:\n * streaming consumers typically render partial JSON progressively (via\n * `parsePartialJSON` or `useChat`'s `partial` slot) and validate downstream\n * after assembly. Running validation server-side would force a hard error\n * on partial-by-design payloads. See `docs/structured-outputs/overview.md`.\n *\n * Null-widening normalization, however, IS run on both paths: the\n * `structured-output.complete` CUSTOM event is forwarded with its `value.object`\n * already un-widened (synthesized strict-mode nulls dropped, genuine\n * `.nullable()` nulls kept), so a consumer validating the assembled object\n * against the original schema doesn't choke on a `null` for an `.optional()`\n * field. Same `convertSchemaForStructuredOutput` pass and same\n * `undoNullWidening` map as the Promise<T> path — the two must not diverge.\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<\n TSchema extends SchemaInput,\n TContext = unknown,\n>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, true, TContext>,\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, capturing the null-widening map so the engine can un-widen the\n // provider's response before it reaches the consumer. Adapters can re-convert\n // if their wire format diverges, but the default flow hands them a\n // strict-ready schema.\n const { jsonSchema, nullWideningMap } =\n convertSchemaForStructuredOutput(outputSchema)\n if (!jsonSchema) {\n throw new Error('Failed to convert output schema to JSON Schema')\n }\n const normalize = (data: unknown): unknown =>\n undoNullWidening(data, nullWideningMap)\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 normalize,\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<\n TSchema extends SchemaInput,\n TContext = unknown,\n>(\n options: TextActivityOptions<AnyTextAdapter, TSchema, true, TContext>,\n jsonSchema: NonNullable<ReturnType<typeof convertSchemaToJsonSchema>>,\n normalize: (data: unknown) => unknown,\n): StructuredOutputStreamInternal<InferSchemaType<TSchema>> {\n const {\n adapter,\n outputSchema,\n middleware,\n context,\n debug,\n mcp,\n ...textOptions\n } = options\n const model = adapter.model\n const logger = resolveDebugOption(debug)\n\n // Per issue #605: adapters that natively combine tools + schema-constrained\n // output in one streaming call (modern OpenAI, Anthropic 4.5+, Gemini 3+,\n // Grok 4+) opt in via `supportsCombinedToolsAndSchema()`. The engine then\n // forwards the schema into the regular `chatStream` call and harvests the\n // structured result from the agent loop's accumulated text — no separate\n // finalization round-trip, and the `'structuredOutput'` middleware phase\n // does not fire.\n const nativeCombined =\n adapter.supportsCombinedToolsAndSchema?.(options.modelOptions) === true\n\n const mcpManager = MCPManager.from(mcp)\n const mcpTools = await mcpManager.discover()\n if (mcpTools.length > 0) {\n textOptions.tools = [...(textOptions.tools ?? []), ...mcpTools]\n }\n\n // Inputs may be UIMessages (from useChat) or ModelMessages (from server-side\n // callers). TextEngine handles the conversion uniformly.\n const engine = new TextEngine(\n {\n adapter,\n params: { ...textOptions, model, logger } as TextOptions<\n Record<string, unknown>,\n Record<string, unknown>,\n TContext\n >,\n middleware,\n context,\n finalStructuredOutput: {\n jsonSchema,\n yieldChunks: true,\n normalize,\n ...(nativeCombined ? { nativeCombined: true } : {}),\n },\n },\n logger,\n )\n\n try {\n for await (const chunk of engine.run()) {\n yield chunk\n }\n } finally {\n await mcpManager.dispose()\n }\n\n // Standard Schema validation for the streaming variant remains the\n // consumer's responsibility — they read the CUSTOM 'structured-output.complete'\n // from the yielded stream. (Null-widening normalization, by contrast, already\n // ran inside the engine via `normalize`, so the object they read is un-widened.)\n void outputSchema\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"],"mappings":"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"}