{"version":3,"file":"index.mjs","names":["convertJsonSchemaToZodSchema","tool","createVercelAISDKTool","aiJsonSchema"],"sources":["../../src/agent/index.ts"],"sourcesContent":["import type {\n  BaseEvent,\n  RunAgentInput,\n  Message,\n  ReasoningEndEvent,\n  ReasoningMessageContentEvent,\n  ReasoningMessageEndEvent,\n  ReasoningMessageStartEvent,\n  ReasoningStartEvent,\n  RunFinishedEvent,\n  RunStartedEvent,\n  TextMessageChunkEvent,\n  ToolCallArgsEvent,\n  ToolCallEndEvent,\n  ToolCallStartEvent,\n  ToolCallResultEvent,\n  RunErrorEvent,\n  StateSnapshotEvent,\n  StateDeltaEvent,\n  Interrupt,\n  ResumeEntry,\n} from \"@ag-ui/client\";\nimport { AbstractAgent, EventType } from \"@ag-ui/client\";\nimport type { AgentCapabilities } from \"@ag-ui/core\";\nimport type {\n  LanguageModel,\n  ModelMessage,\n  AssistantModelMessage,\n  UserModelMessage,\n  ToolModelMessage,\n  SystemModelMessage,\n  ToolCallPart,\n  ToolResultPart,\n  TextPart,\n  ImagePart,\n  FilePart,\n  ToolChoice,\n  ToolSet,\n  Schema,\n} from \"ai\";\nimport { streamText, tool as createVercelAISDKTool, stepCountIs } from \"ai\";\nimport { createMCPClient } from \"@ai-sdk/mcp\";\nimport type { MCPClient } from \"@ai-sdk/mcp\";\nimport { Observable } from \"rxjs\";\nimport { createOpenAI } from \"@ai-sdk/openai\";\nimport { createAnthropic } from \"@ai-sdk/anthropic\";\nimport { createGoogleGenerativeAI } from \"@ai-sdk/google\";\nimport { createVertex } from \"@ai-sdk/google-vertex\";\nimport { safeParseToolArgs } from \"@copilotkit/shared\";\nimport { z } from \"zod\";\nimport type { StandardSchemaV1, InferSchemaOutput } from \"@copilotkit/shared\";\nimport { schemaToJsonSchema } from \"@copilotkit/shared\";\nimport { jsonSchema as aiJsonSchema } from \"ai\";\nimport { convertAISDKStream } from \"./converters/aisdk\";\nimport { convertTanStackStream } from \"./converters/tanstack\";\nimport type { StreamableHTTPClientTransportOptions } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { SSEClientTransport } from \"@modelcontextprotocol/sdk/client/sse.js\";\nimport { randomUUID } from \"@copilotkit/shared\";\n\n/**\n * Properties that can be overridden by forwardedProps\n * These match the exact parameter names in streamText\n */\nexport type OverridableProperty =\n  | \"model\"\n  | \"toolChoice\"\n  | \"maxOutputTokens\"\n  | \"temperature\"\n  | \"topP\"\n  | \"topK\"\n  | \"presencePenalty\"\n  | \"frequencyPenalty\"\n  | \"stopSequences\"\n  | \"seed\"\n  | \"maxRetries\"\n  | \"prompt\"\n  | \"providerOptions\";\n\n/**\n * Supported model identifiers for BuiltInAgent\n */\nexport type BuiltInAgentModel =\n  // OpenAI models\n  | \"openai/gpt-5\"\n  | \"openai/gpt-5-mini\"\n  | \"openai/gpt-4.1\"\n  | \"openai/gpt-4.1-mini\"\n  | \"openai/gpt-4.1-nano\"\n  | \"openai/gpt-4o\"\n  | \"openai/gpt-4o-mini\"\n  // OpenAI reasoning series\n  | \"openai/o3\"\n  | \"openai/o3-mini\"\n  | \"openai/o4-mini\"\n  // Anthropic (Claude) models\n  | \"anthropic/claude-sonnet-4.5\"\n  | \"anthropic/claude-sonnet-4\"\n  | \"anthropic/claude-3.7-sonnet\"\n  | \"anthropic/claude-opus-4.1\"\n  | \"anthropic/claude-opus-4\"\n  | \"anthropic/claude-3.5-haiku\"\n  // Google (Gemini) models\n  | \"google/gemini-2.5-pro\"\n  | \"google/gemini-2.5-flash\"\n  | \"google/gemini-2.5-flash-lite\"\n  // Allow any LanguageModel instance\n  | (string & {});\n\n/**\n * Model specifier - can be a string like \"openai/gpt-4o\" or a LanguageModel instance\n */\nexport type ModelSpecifier = string | LanguageModel;\n\n/**\n * MCP Client configuration for HTTP transport\n */\nexport interface MCPClientConfigHTTP {\n  /** Type of MCP client */\n  type: \"http\";\n  /** URL of the MCP server */\n  url: string;\n  /**\n   * Optional transport options for the underlying\n   * `StreamableHTTPClientTransport`. The SDK's documented extension point\n   * for per-request customization is `options.fetch` — pass a wrapped fetch\n   * here if you need static + dynamic headers on outbound MCP requests.\n   */\n  options?: StreamableHTTPClientTransportOptions;\n}\n\n/**\n * MCP Client configuration for SSE transport\n */\nexport interface MCPClientConfigSSE {\n  /** Type of MCP client */\n  type: \"sse\";\n  /** URL of the MCP server */\n  url: string;\n  /** Optional HTTP headers (e.g., for authentication) */\n  headers?: Record<string, string>;\n}\n\n/**\n * MCP Client configuration\n */\nexport type MCPClientConfig = MCPClientConfigHTTP | MCPClientConfigSSE;\n\n/**\n * A user-managed MCP client that provides tools to the agent.\n * The user is responsible for creating, configuring, and closing the client.\n * Compatible with the return type of @ai-sdk/mcp's createMCPClient().\n *\n * Unlike mcpServers, the agent does NOT create or close these clients.\n * This allows persistent connections, custom auth, and tool caching.\n */\nexport interface MCPClientProvider {\n  /** Return tools to be merged into the agent's tool set. */\n  tools(): Promise<ToolSet>;\n}\n\n/**\n * Resolves a model specifier to a LanguageModel instance\n * @param spec - Model string (e.g., \"openai/gpt-4o\") or LanguageModel instance\n * @param apiKey - Optional API key to use instead of environment variables\n * @returns LanguageModel instance\n */\nexport function resolveModel(\n  spec: ModelSpecifier,\n  apiKey?: string,\n): LanguageModel {\n  // If already a LanguageModel instance, pass through\n  if (typeof spec !== \"string\") {\n    return spec;\n  }\n\n  // Normalize \"provider/model\" or \"provider:model\" format\n  const normalized = spec.replace(\"/\", \":\").trim();\n  const parts = normalized.split(\":\");\n  const rawProvider = parts[0];\n  const rest = parts.slice(1);\n\n  if (!rawProvider) {\n    throw new Error(\n      `Invalid model string \"${spec}\". Use \"openai/gpt-5\", \"anthropic/claude-sonnet-4.5\", or \"google/gemini-2.5-pro\".`,\n    );\n  }\n\n  const provider = rawProvider.toLowerCase();\n  const model = rest.join(\":\").trim();\n\n  if (!model) {\n    throw new Error(\n      `Invalid model string \"${spec}\". Use \"openai/gpt-5\", \"anthropic/claude-sonnet-4.5\", or \"google/gemini-2.5-pro\".`,\n    );\n  }\n\n  switch (provider) {\n    case \"openai\": {\n      // Lazily create OpenAI provider\n      // Use provided apiKey, or fall back to environment variable\n      const openai = createOpenAI({\n        apiKey: apiKey || process.env.OPENAI_API_KEY!,\n      });\n      // Accepts any OpenAI model id, e.g. \"gpt-4o\", \"gpt-4.1-mini\", \"o3-mini\"\n      return openai(model);\n    }\n\n    case \"anthropic\": {\n      // Lazily create Anthropic provider\n      // Use provided apiKey, or fall back to environment variable\n      const anthropic = createAnthropic({\n        apiKey: apiKey || process.env.ANTHROPIC_API_KEY!,\n      });\n      // Accepts any Claude id, e.g. \"claude-3.7-sonnet\", \"claude-3.5-haiku\"\n      return anthropic(model);\n    }\n\n    case \"google\":\n    case \"gemini\":\n    case \"google-gemini\": {\n      // Lazily create Google provider\n      // Use provided apiKey, or fall back to environment variable\n      const google = createGoogleGenerativeAI({\n        apiKey: apiKey || process.env.GOOGLE_API_KEY!,\n      });\n      // Accepts any Gemini id, e.g. \"gemini-2.5-pro\", \"gemini-2.5-flash\"\n      return google(model);\n    }\n\n    case \"vertex\": {\n      const vertex = createVertex();\n      return vertex(model);\n    }\n\n    default:\n      throw new Error(\n        `Unknown provider \"${provider}\" in \"${spec}\". Supported: openai, anthropic, google (gemini).`,\n      );\n  }\n}\n\n/**\n * Thrown by `AgentFactoryContext.interrupt()` on a fresh (non-resume) run to\n * pause the factory. Caught in `runFactory` and translated into a RUN_FINISHED\n * event carrying `outcome:{type:\"interrupt\",interrupts}`. Not a real error.\n */\nexport class InterruptSignal extends Error {\n  constructor(public readonly interrupts: Interrupt[]) {\n    super(\"CopilotKit interrupt: run paused awaiting human input\");\n    this.name = \"InterruptSignal\";\n  }\n}\n\n/**\n * Tool definition for BuiltInAgent\n */\nexport interface ToolDefinition<\n  TParameters extends StandardSchemaV1 = StandardSchemaV1,\n> {\n  name: string;\n  description: string;\n  parameters: TParameters;\n  /**\n   * Server-side executor. Optional ONLY for interrupt tools (`interrupt:true`),\n   * which pause the run instead of executing.\n   */\n  execute?: (args: InferSchemaOutput<TParameters>) => Promise<unknown>;\n  /**\n   * When true, calling this tool pauses the run and emits a standard AG-UI\n   * interrupt (RUN_FINISHED outcome:interrupt) keyed by the tool call's id.\n   * The human response (resume payload) is injected as this tool call's result\n   * on the resume run. Interrupt tools must NOT define `execute`, and require\n   * the default `maxSteps: 1` — with `maxSteps > 1` the AI SDK's agentic loop\n   * would try to continue past the unexecuted tool call instead of pausing.\n   */\n  interrupt?: boolean;\n  /** Optional categorical reason surfaced on the Interrupt (default: \"tool_call\"). */\n  interruptReason?: string;\n  /** Optional human-readable prompt surfaced on the Interrupt. */\n  interruptMessage?: string;\n}\n\n/**\n * Define a tool for use with BuiltInAgent\n * @param name - The name of the tool\n * @param description - Description of what the tool does\n * @param parameters - Schema for the tool's input parameters (any Standard Schema V1 compatible library: Zod, Valibot, ArkType, etc.)\n * @param execute - Function to execute the tool server-side\n * @returns Tool definition\n */\nexport function defineTool<TParameters extends StandardSchemaV1>(config: {\n  name: string;\n  description: string;\n  parameters: TParameters;\n  execute?: (args: InferSchemaOutput<TParameters>) => Promise<unknown>;\n  interrupt?: boolean;\n  interruptReason?: string;\n  interruptMessage?: string;\n}): ToolDefinition<TParameters> {\n  return {\n    name: config.name,\n    description: config.description,\n    parameters: config.parameters,\n    execute: config.execute,\n    interrupt: config.interrupt,\n    interruptReason: config.interruptReason,\n    interruptMessage: config.interruptMessage,\n  };\n}\n\ntype AGUIUserMessage = Extract<Message, { role: \"user\" }>;\n\n/**\n * Converts AG-UI user message content to Vercel AI SDK UserContent format.\n * Handles plain strings, new modality-specific parts (image/audio/video/document),\n * and legacy BinaryInputContent for backward compatibility.\n */\nfunction convertUserMessageContent(\n  content: AGUIUserMessage[\"content\"],\n): string | Array<TextPart | ImagePart | FilePart> {\n  if (!content) {\n    return \"\";\n  }\n\n  if (typeof content === \"string\") {\n    return content;\n  }\n\n  const parts: Array<TextPart | ImagePart | FilePart> = [];\n\n  for (const part of content) {\n    if (!part || typeof part !== \"object\" || !(\"type\" in part)) {\n      continue;\n    }\n\n    switch (part.type) {\n      case \"text\": {\n        const text = (part as { text?: string }).text;\n        if (text) {\n          parts.push({ type: \"text\", text });\n        }\n        break;\n      }\n\n      case \"image\": {\n        const source = (part as { source?: any }).source;\n        if (!source) break;\n        if (source.type === \"data\") {\n          parts.push({\n            type: \"image\",\n            image: source.value,\n            mediaType: source.mimeType,\n          });\n        } else if (source.type === \"url\") {\n          try {\n            parts.push({\n              type: \"image\",\n              image: new URL(source.value),\n              mediaType: source.mimeType,\n            });\n          } catch {\n            console.error(\n              `[CopilotKit] convertUserMessageContent: invalid URL \"${source.value}\" in image part — skipping`,\n            );\n          }\n        }\n        break;\n      }\n\n      case \"audio\":\n      case \"video\":\n      case \"document\": {\n        const source = (part as { source?: any }).source;\n        if (!source) break;\n        if (source.type === \"data\") {\n          parts.push({\n            type: \"file\",\n            data: source.value,\n            mediaType: source.mimeType,\n          });\n        } else if (source.type === \"url\") {\n          try {\n            parts.push({\n              type: \"file\",\n              data: new URL(source.value),\n              mediaType: source.mimeType ?? \"application/octet-stream\",\n            });\n          } catch {\n            console.error(\n              `[CopilotKit] convertUserMessageContent: invalid URL \"${source.value}\" in ${part.type} part — skipping`,\n            );\n          }\n        }\n        break;\n      }\n\n      // Legacy BinaryInputContent backward compatibility\n      case \"binary\": {\n        const legacy = part as {\n          mimeType?: string;\n          data?: string;\n          url?: string;\n        };\n        const mimeType = legacy.mimeType ?? \"application/octet-stream\";\n        const isImage = mimeType.startsWith(\"image/\");\n\n        if (legacy.data) {\n          if (isImage) {\n            parts.push({\n              type: \"image\",\n              image: legacy.data,\n              mediaType: mimeType,\n            });\n          } else {\n            parts.push({\n              type: \"file\",\n              data: legacy.data,\n              mediaType: mimeType,\n            });\n          }\n        } else if (legacy.url) {\n          try {\n            const url = new URL(legacy.url);\n            if (isImage) {\n              parts.push({ type: \"image\", image: url, mediaType: mimeType });\n            } else {\n              parts.push({ type: \"file\", data: url, mediaType: mimeType });\n            }\n          } catch {\n            console.error(\n              `[CopilotKit] convertUserMessageContent: invalid URL \"${legacy.url}\" in binary part — skipping`,\n            );\n          }\n        }\n        break;\n      }\n\n      default: {\n        console.error(\n          `[CopilotKit] convertUserMessageContent: unrecognized content part type \"${(part as { type: string }).type}\" — skipping`,\n        );\n        break;\n      }\n    }\n  }\n\n  return parts.length > 0 ? parts : \"\";\n}\n\n/**\n * Options for converting AG-UI messages to Vercel AI SDK format\n */\nexport interface MessageConversionOptions {\n  forwardSystemMessages?: boolean;\n  forwardDeveloperMessages?: boolean;\n}\n\n/**\n * Converts AG-UI messages to Vercel AI SDK ModelMessage format\n */\nexport function convertMessagesToVercelAISDKMessages(\n  messages: Message[],\n  options: MessageConversionOptions = {},\n): ModelMessage[] {\n  const result: ModelMessage[] = [];\n\n  for (const message of messages) {\n    if (message.role === \"system\" && options.forwardSystemMessages) {\n      const systemMsg: SystemModelMessage = {\n        role: \"system\",\n        content: message.content ?? \"\",\n      };\n      result.push(systemMsg);\n    } else if (\n      message.role === \"developer\" &&\n      options.forwardDeveloperMessages\n    ) {\n      const systemMsg: SystemModelMessage = {\n        role: \"system\",\n        content: message.content ?? \"\",\n      };\n      result.push(systemMsg);\n    } else if (message.role === \"assistant\") {\n      const parts: Array<TextPart | ToolCallPart> = message.content\n        ? [{ type: \"text\", text: message.content }]\n        : [];\n\n      for (const toolCall of message.toolCalls ?? []) {\n        const toolCallPart: ToolCallPart = {\n          type: \"tool-call\",\n          toolCallId: toolCall.id,\n          toolName: toolCall.function.name,\n          input: safeParseToolArgs(toolCall.function.arguments),\n        };\n        parts.push(toolCallPart);\n      }\n\n      const assistantMsg: AssistantModelMessage = {\n        role: \"assistant\",\n        content: parts,\n      };\n      result.push(assistantMsg);\n    } else if (message.role === \"user\") {\n      const userMsg: UserModelMessage = {\n        role: \"user\",\n        content: convertUserMessageContent(message.content),\n      };\n      result.push(userMsg);\n    } else if (message.role === \"tool\") {\n      let toolName = \"unknown\";\n      // Find the tool name from the corresponding tool call\n      for (const msg of messages) {\n        if (msg.role === \"assistant\") {\n          for (const toolCall of msg.toolCalls ?? []) {\n            if (toolCall.id === message.toolCallId) {\n              toolName = toolCall.function.name;\n              break;\n            }\n          }\n        }\n      }\n\n      const toolResultPart: ToolResultPart = {\n        type: \"tool-result\",\n        toolCallId: message.toolCallId,\n        toolName: toolName,\n        output: {\n          type: \"text\",\n          value: message.content,\n        },\n      };\n\n      const toolMsg: ToolModelMessage = {\n        role: \"tool\",\n        content: [toolResultPart],\n      };\n      result.push(toolMsg);\n    }\n  }\n\n  return result;\n}\n\n/**\n * JSON Schema type definition\n */\ninterface JsonSchema {\n  type: \"object\" | \"string\" | \"number\" | \"integer\" | \"boolean\" | \"array\";\n  description?: string;\n  properties?: Record<string, JsonSchema>;\n  required?: string[];\n  items?: JsonSchema;\n  enum?: string[];\n}\n\n/**\n * Converts JSON Schema to Zod schema\n */\nexport function convertJsonSchemaToZodSchema(\n  jsonSchema: JsonSchema,\n  required: boolean,\n): z.ZodSchema {\n  // Handle empty schemas {} (no input required) - treat as empty object\n  if (!jsonSchema.type) {\n    return required ? z.object({}) : z.object({}).optional();\n  }\n  if (jsonSchema.type === \"object\") {\n    const spec: { [key: string]: z.ZodSchema } = {};\n\n    if (!jsonSchema.properties || !Object.keys(jsonSchema.properties).length) {\n      return !required ? z.object(spec).optional() : z.object(spec);\n    }\n\n    for (const [key, value] of Object.entries(jsonSchema.properties)) {\n      spec[key] = convertJsonSchemaToZodSchema(\n        value,\n        jsonSchema.required ? jsonSchema.required.includes(key) : false,\n      );\n    }\n    const schema = z.object(spec).describe(jsonSchema.description ?? \"\");\n    return required ? schema : schema.optional();\n  } else if (jsonSchema.type === \"string\") {\n    if (jsonSchema.enum && jsonSchema.enum.length > 0) {\n      const schema = z\n        .enum(jsonSchema.enum as [string, ...string[]])\n        .describe(jsonSchema.description ?? \"\");\n      return required ? schema : schema.optional();\n    }\n    const schema = z.string().describe(jsonSchema.description ?? \"\");\n    return required ? schema : schema.optional();\n  } else if (jsonSchema.type === \"number\" || jsonSchema.type === \"integer\") {\n    const schema = z.number().describe(jsonSchema.description ?? \"\");\n    return required ? schema : schema.optional();\n  } else if (jsonSchema.type === \"boolean\") {\n    const schema = z.boolean().describe(jsonSchema.description ?? \"\");\n    return required ? schema : schema.optional();\n  } else if (jsonSchema.type === \"array\") {\n    if (!jsonSchema.items) {\n      throw new Error(\"Array type must have items property\");\n    }\n    const itemSchema = convertJsonSchemaToZodSchema(jsonSchema.items, true);\n    const schema = z.array(itemSchema).describe(jsonSchema.description ?? \"\");\n    return required ? schema : schema.optional();\n  }\n  console.error(\"Invalid JSON schema:\", JSON.stringify(jsonSchema, null, 2));\n  throw new Error(\"Invalid JSON schema\");\n}\n\n/**\n * Converts AG-UI tools to Vercel AI SDK ToolSet\n */\nfunction isJsonSchema(obj: unknown): obj is JsonSchema {\n  if (typeof obj !== \"object\" || obj === null) return false;\n  const schema = obj as Record<string, unknown>;\n  // Empty objects {} are valid JSON schemas (no input required)\n  if (Object.keys(schema).length === 0) return true;\n  return (\n    typeof schema.type === \"string\" &&\n    [\"object\", \"string\", \"number\", \"integer\", \"boolean\", \"array\"].includes(\n      schema.type,\n    )\n  );\n}\n\n/**\n * Type-only pass-through for handing a Zod schema to the AI SDK's `tool()`.\n * The raw Zod schema is returned unchanged at runtime — the SDK's `asSchema()`\n * converts and validates it internally exactly as before.\n *\n * The Zod type is erased through `unknown` deliberately: letting tsc relate\n * Zod schema types to the AI SDK's `FlexibleSchema` union (conditional types\n * spanning zod v3/v4) makes type instantiation explode (TS2589 / compiler\n * OOM) under this package's `moduleResolution: node`.\n */\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction toLanguageModelSchema(schema: z.ZodSchema): Schema<any> {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  return schema as unknown as Schema<any>;\n}\n\nexport function convertToolsToVercelAITools(\n  tools: RunAgentInput[\"tools\"],\n): ToolSet {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  const result: Record<string, any> = {};\n\n  for (const tool of tools) {\n    if (!isJsonSchema(tool.parameters)) {\n      throw new Error(`Invalid JSON schema for tool ${tool.name}`);\n    }\n    const zodSchema = convertJsonSchemaToZodSchema(tool.parameters, true);\n    result[tool.name] = createVercelAISDKTool({\n      description: tool.description,\n      inputSchema: toLanguageModelSchema(zodSchema),\n    });\n  }\n\n  return result;\n}\n\n/**\n * Check whether a schema is a Zod schema by inspecting its Standard Schema vendor.\n */\nfunction isZodSchema(schema: StandardSchemaV1): boolean {\n  return schema[\"~standard\"]?.vendor === \"zod\";\n}\n\n/**\n * Converts ToolDefinition array to Vercel AI SDK ToolSet.\n *\n * For Zod schemas, passes them directly to the AI SDK (Zod satisfies FlexibleSchema).\n * For non-Zod schemas, converts to JSON Schema via schemaToJsonSchema() and wraps\n * with the AI SDK's jsonSchema() helper.\n */\nexport function convertToolDefinitionsToVercelAITools(\n  tools: ToolDefinition[],\n): ToolSet {\n  // eslint-disable-next-line @typescript-eslint/no-explicit-any\n  const result: Record<string, any> = {};\n\n  for (const tool of tools) {\n    if (isZodSchema(tool.parameters)) {\n      // Zod schemas can be passed directly to AI SDK (satisfies FlexibleSchema)\n      result[tool.name] = createVercelAISDKTool({\n        description: tool.description,\n        inputSchema: tool.parameters as any,\n        execute: tool.execute,\n      });\n    } else {\n      // Non-Zod: convert to JSON Schema and wrap with AI SDK's jsonSchema()\n      const jsonSchemaObj = schemaToJsonSchema(tool.parameters);\n      result[tool.name] = createVercelAISDKTool({\n        description: tool.description,\n        inputSchema: aiJsonSchema(jsonSchemaObj),\n        execute: tool.execute,\n      });\n    }\n  }\n\n  return result;\n}\n\n/**\n * Context passed to the user-supplied factory function in factory mode.\n */\nexport interface AgentFactoryContext {\n  input: RunAgentInput;\n  /**\n   * Prefer `abortSignal` for most use cases (AI SDK, fetch, custom backends).\n   * Provided for backends like TanStack AI that require the full AbortController.\n   * Do NOT call `.abort()` on this controller — use `abortRun()` on the agent instead.\n   */\n  abortController: AbortController;\n  abortSignal: AbortSignal;\n  /**\n   * Pause the run for human input (AG-UI standard interrupt). On a fresh run\n   * this throws an InterruptSignal (caught by the runtime) and the run finishes\n   * with `outcome:{type:\"interrupt\",interrupts}`. On the resume run (when\n   * `input.resume` covers these interrupts) it returns the matching ResumeEntry\n   * responses so the factory can continue. Each `interrupts[i].id` is matched to\n   * `input.resume[].interruptId`.\n   */\n  interrupt: (interrupts: Interrupt[]) => Promise<ResumeEntry[]>;\n}\n\n/**\n * Factory config for AI SDK backend.\n * The factory must return an object with a `fullStream` async iterable\n * (compatible with the result of `streamText()` — only `fullStream` is consumed).\n */\nexport interface BuiltInAgentAISDKFactoryConfig {\n  type: \"aisdk\";\n  factory: (\n    ctx: AgentFactoryContext,\n  ) =>\n    | { fullStream: AsyncIterable<unknown> }\n    | Promise<{ fullStream: AsyncIterable<unknown> }>;\n}\n\n/**\n * Factory config for TanStack AI backend.\n * The factory must return an async iterable of TanStack AI stream chunks.\n */\nexport interface BuiltInAgentTanStackFactoryConfig {\n  type: \"tanstack\";\n  factory: (\n    ctx: AgentFactoryContext,\n  ) => AsyncIterable<unknown> | Promise<AsyncIterable<unknown>>;\n}\n\n/**\n * Factory config for a custom backend that directly yields AG-UI events.\n */\nexport interface BuiltInAgentCustomFactoryConfig {\n  type: \"custom\";\n  factory: (\n    ctx: AgentFactoryContext,\n  ) => AsyncIterable<BaseEvent> | Promise<AsyncIterable<BaseEvent>>;\n}\n\n/**\n * Union of all factory-mode configurations.\n */\nexport type BuiltInAgentFactoryConfig =\n  | BuiltInAgentAISDKFactoryConfig\n  | BuiltInAgentTanStackFactoryConfig\n  | BuiltInAgentCustomFactoryConfig;\n\n/**\n * Classic config — BuiltInAgent handles streamText, tools, MCP, state tools, prompt building.\n */\nexport interface BuiltInAgentClassicConfig {\n  /**\n   * The model to use\n   */\n  model: BuiltInAgentModel | LanguageModel;\n  /**\n   * API key for the model provider (OpenAI, Anthropic, Google)\n   * If not provided, falls back to environment variables:\n   * - OPENAI_API_KEY for OpenAI models\n   * - ANTHROPIC_API_KEY for Anthropic models\n   * - GOOGLE_API_KEY for Google models\n   */\n  apiKey?: string;\n  /**\n   * Maximum number of steps/iterations for tool calling (default: 1)\n   */\n  maxSteps?: number;\n  /**\n   * Tool choice setting - how tools are selected for execution (default: \"auto\")\n   */\n  toolChoice?: ToolChoice<Record<string, unknown>>;\n  /**\n   * Maximum number of tokens to generate\n   */\n  maxOutputTokens?: number;\n  /**\n   * Temperature setting (range depends on provider)\n   */\n  temperature?: number;\n  /**\n   * Nucleus sampling (topP)\n   */\n  topP?: number;\n  /**\n   * Top K sampling\n   */\n  topK?: number;\n  /**\n   * Presence penalty\n   */\n  presencePenalty?: number;\n  /**\n   * Frequency penalty\n   */\n  frequencyPenalty?: number;\n  /**\n   * Sequences that will stop the generation\n   */\n  stopSequences?: string[];\n  /**\n   * Seed for deterministic results\n   */\n  seed?: number;\n  /**\n   * Maximum number of retries\n   */\n  maxRetries?: number;\n  /**\n   * Prompt for the agent\n   */\n  prompt?: string;\n  /**\n   * List of properties that can be overridden by forwardedProps.\n   */\n  overridableProperties?: OverridableProperty[];\n  /**\n   * Optional list of MCP server configurations\n   */\n  mcpServers?: MCPClientConfig[];\n  /**\n   * Optional list of user-managed MCP clients.\n   * Unlike mcpServers, the agent does NOT create or close these clients.\n   * The user controls the lifecycle, persistence, auth, and caching.\n   *\n   * Compatible with @ai-sdk/mcp's createMCPClient() return type:\n   * ```typescript\n   * const client = await createMCPClient({ transport });\n   * const agent = new BuiltInAgent({ model: \"...\", mcpClients: [client] });\n   * ```\n   */\n  mcpClients?: MCPClientProvider[];\n  /**\n   * Optional tools available to the agent\n   */\n  tools?: ToolDefinition[];\n  /**\n   * Forward system-role messages from input to the LLM.\n   * Default: false\n   */\n  forwardSystemMessages?: boolean;\n  /**\n   * Forward developer-role messages from input to the LLM (as system messages).\n   * Default: false\n   */\n  forwardDeveloperMessages?: boolean;\n  /**\n   * Provider-specific options passed to the model (e.g., OpenAI reasoningEffort).\n   * Example: `{ openai: { reasoningEffort: \"high\" } }`\n   */\n  providerOptions?: Record<string, any>;\n  /**\n   * Explicit agent capabilities. **Shallow-merged** at the category level on\n   * top of auto-inferred defaults — providing a category (e.g. `tools`)\n   * replaces that entire category, not individual fields within it.\n   *\n   * For example, `{ tools: { supported: true } }` will drop the inferred\n   * `clientProvided` value. Include all fields for any category you override.\n   */\n  capabilities?: Partial<AgentCapabilities>;\n}\n\n/**\n * Configuration for BuiltInAgent.\n *\n * Two modes:\n * - **Classic** (model + params): BuiltInAgent handles everything — streamText, tools, MCP, state tools.\n * - **Factory** (type + factory): You own the LLM call. BuiltInAgent handles lifecycle only.\n */\nexport type BuiltInAgentConfiguration =\n  | BuiltInAgentClassicConfig\n  | BuiltInAgentFactoryConfig;\n\n/**\n * Type guard: returns true if this is a factory-mode config.\n */\nfunction isFactoryConfig(\n  config: BuiltInAgentConfiguration,\n): config is BuiltInAgentFactoryConfig {\n  return \"factory\" in config;\n}\n\nexport class BuiltInAgent extends AbstractAgent {\n  private abortController?: AbortController;\n\n  constructor(private config: BuiltInAgentConfiguration) {\n    super();\n  }\n\n  /**\n   * Check if a property can be overridden by forwardedProps\n   */\n  canOverride(property: OverridableProperty): boolean {\n    if (isFactoryConfig(this.config)) return false;\n    return this.config?.overridableProperties?.includes(property) ?? false;\n  }\n\n  async getCapabilities(): Promise<AgentCapabilities> {\n    const inferred: AgentCapabilities = {\n      tools: {\n        supported: true,\n        clientProvided: true,\n      },\n      transport: {\n        streaming: true,\n      },\n      humanInTheLoop: {\n        interrupts: true,\n      },\n    };\n\n    // Factory-mode configs have no `capabilities` property.\n    const capabilities = isFactoryConfig(this.config)\n      ? undefined\n      : this.config.capabilities;\n\n    if (!capabilities) {\n      return inferred;\n    }\n\n    // Shallow merge at the category level — explicit overrides replace\n    // entire categories when provided, inferred defaults fill the rest.\n    return {\n      ...inferred,\n      ...capabilities,\n    };\n  }\n\n  run(input: RunAgentInput): Observable<BaseEvent> {\n    if (isFactoryConfig(this.config)) {\n      return this.runFactory(input, this.config);\n    }\n\n    // Capture the narrowed classic config — the narrowing of `this.config`\n    // above does not survive into the Observable/async closures below.\n    const config = this.config;\n\n    if (this.abortController) {\n      throw new Error(\n        \"Agent is already running. Call abortRun() first or create a new instance.\",\n      );\n    }\n\n    // Set synchronously before Observable creation to close TOCTOU window\n    this.abortController = new AbortController();\n    const abortController = this.abortController;\n\n    return new Observable<BaseEvent>((subscriber) => {\n      // Emit RUN_STARTED event\n      const startEvent: RunStartedEvent = {\n        type: EventType.RUN_STARTED,\n        threadId: input.threadId,\n        runId: input.runId,\n      };\n      subscriber.next(startEvent);\n\n      // Resolve the model, passing API key if provided\n      const model = resolveModel(config.model, config.apiKey);\n\n      // Build prompt based on conditions\n      let systemPrompt: string | undefined = undefined;\n\n      // Check if we should build a prompt:\n      // - config.prompt is set, OR\n      // - input.context is non-empty, OR\n      // - input.state is non-empty and not an empty object\n      const hasPrompt = !!config.prompt;\n      const hasContext = input.context && input.context.length > 0;\n      const hasState =\n        input.state !== undefined &&\n        input.state !== null &&\n        !(\n          typeof input.state === \"object\" &&\n          Object.keys(input.state).length === 0\n        );\n\n      if (hasPrompt || hasContext || hasState) {\n        const parts: string[] = [];\n\n        // First: the prompt if any\n        if (hasPrompt) {\n          parts.push(config.prompt!);\n        }\n\n        // Second: context from the application\n        if (hasContext) {\n          parts.push(\"\\n## Context from the application\\n\");\n          for (const ctx of input.context) {\n            parts.push(`${ctx.description}:\\n${ctx.value}\\n`);\n          }\n        }\n\n        // Third: state from the application that can be edited\n        if (hasState) {\n          parts.push(\n            \"\\n## Application State\\n\" +\n              \"This is state from the application that you can edit by calling AGUISendStateSnapshot or AGUISendStateDelta.\\n\" +\n              `\\`\\`\\`json\\n${JSON.stringify(input.state, null, 2)}\\n\\`\\`\\`\\n`,\n          );\n        }\n\n        systemPrompt = parts.join(\"\");\n      }\n\n      // Convert messages and prepend system message if we have a prompt\n      const messages = convertMessagesToVercelAISDKMessages(input.messages, {\n        forwardSystemMessages: config.forwardSystemMessages,\n        forwardDeveloperMessages: config.forwardDeveloperMessages,\n      });\n      if (systemPrompt) {\n        messages.unshift({\n          role: \"system\",\n          content: systemPrompt,\n        });\n      }\n\n      // Resume injection: each ResumeEntry maps to the interrupt tool call it\n      // addresses (interruptId === toolCallId) and is appended as that call's\n      // tool-role result so the model can continue the agentic loop.\n      const resumeEntries: ResumeEntry[] = input.resume ?? [];\n      if (resumeEntries.length > 0) {\n        // Recover the originating tool name for each interrupt tool call so the\n        // injected tool-result carries the real name. Providers like Anthropic\n        // and Google reject a tool-result whose name doesn't match the prior\n        // tool-call; an empty name fails there (OpenAI tolerates it).\n        const toolNameById = new Map<string, string>();\n        for (const m of input.messages) {\n          if (m.role !== \"assistant\") continue;\n          for (const tc of m.toolCalls ?? []) {\n            if (tc.id && tc.function?.name) {\n              toolNameById.set(tc.id, tc.function.name);\n            }\n          }\n        }\n        // Idempotent: a client (useInterrupt) may already have appended the\n        // resolution as a tool message — converted into a tool-result above.\n        // Skip those so we don't answer the same tool call twice.\n        const alreadyAnswered = new Set<string>();\n        for (const m of messages) {\n          if (m.role !== \"tool\" || !Array.isArray(m.content)) continue;\n          for (const part of m.content) {\n            if (part && typeof part === \"object\" && \"toolCallId\" in part) {\n              alreadyAnswered.add((part as { toolCallId: string }).toolCallId);\n            }\n          }\n        }\n        for (const entry of resumeEntries) {\n          if (alreadyAnswered.has(entry.interruptId)) continue;\n          const value =\n            entry.status === \"cancelled\"\n              ? { status: \"cancelled\" }\n              : (entry.payload ?? { status: \"resolved\" });\n          const toolResultMessage: ToolModelMessage = {\n            role: \"tool\",\n            content: [\n              {\n                type: \"tool-result\",\n                toolCallId: entry.interruptId,\n                toolName: toolNameById.get(entry.interruptId) ?? \"\",\n                output: { type: \"json\", value },\n              },\n            ],\n          };\n          messages.push(toolResultMessage);\n        }\n      }\n\n      // Merge tools from input and config\n      let allTools: ToolSet = convertToolsToVercelAITools(input.tools);\n      if (config.tools && config.tools.length > 0) {\n        const configTools = convertToolDefinitionsToVercelAITools(config.tools);\n        allTools = { ...allTools, ...configTools };\n      }\n\n      const streamTextParams: Parameters<typeof streamText>[0] = {\n        model,\n        messages,\n        tools: allTools,\n        toolChoice: config.toolChoice,\n        stopWhen: config.maxSteps ? stepCountIs(config.maxSteps) : undefined,\n        maxOutputTokens: config.maxOutputTokens,\n        temperature: config.temperature,\n        topP: config.topP,\n        topK: config.topK,\n        presencePenalty: config.presencePenalty,\n        frequencyPenalty: config.frequencyPenalty,\n        stopSequences: config.stopSequences,\n        seed: config.seed,\n        providerOptions: config.providerOptions,\n        maxRetries: config.maxRetries,\n      };\n\n      // Apply forwardedProps overrides (if allowed)\n      if (input.forwardedProps && typeof input.forwardedProps === \"object\") {\n        const props = input.forwardedProps as Record<string, unknown>;\n\n        // Check and apply each overridable property\n        if (props.model !== undefined && this.canOverride(\"model\")) {\n          if (\n            typeof props.model === \"string\" ||\n            typeof props.model === \"object\"\n          ) {\n            // Accept any string or LanguageModel instance for model override\n            // Use the configured API key when resolving overridden models\n            streamTextParams.model = resolveModel(\n              props.model as string | LanguageModel,\n              config.apiKey,\n            );\n          }\n        }\n        if (props.toolChoice !== undefined && this.canOverride(\"toolChoice\")) {\n          // ToolChoice can be 'auto', 'required', 'none', or { type: 'tool', toolName: string }\n          const toolChoice = props.toolChoice;\n          if (\n            toolChoice === \"auto\" ||\n            toolChoice === \"required\" ||\n            toolChoice === \"none\" ||\n            (typeof toolChoice === \"object\" &&\n              toolChoice !== null &&\n              \"type\" in toolChoice &&\n              toolChoice.type === \"tool\")\n          ) {\n            streamTextParams.toolChoice = toolChoice as ToolChoice<\n              Record<string, unknown>\n            >;\n          }\n        }\n        if (\n          typeof props.maxOutputTokens === \"number\" &&\n          this.canOverride(\"maxOutputTokens\")\n        ) {\n          streamTextParams.maxOutputTokens = props.maxOutputTokens;\n        }\n        if (\n          typeof props.temperature === \"number\" &&\n          this.canOverride(\"temperature\")\n        ) {\n          streamTextParams.temperature = props.temperature;\n        }\n        if (typeof props.topP === \"number\" && this.canOverride(\"topP\")) {\n          streamTextParams.topP = props.topP;\n        }\n        if (typeof props.topK === \"number\" && this.canOverride(\"topK\")) {\n          streamTextParams.topK = props.topK;\n        }\n        if (\n          typeof props.presencePenalty === \"number\" &&\n          this.canOverride(\"presencePenalty\")\n        ) {\n          streamTextParams.presencePenalty = props.presencePenalty;\n        }\n        if (\n          typeof props.frequencyPenalty === \"number\" &&\n          this.canOverride(\"frequencyPenalty\")\n        ) {\n          streamTextParams.frequencyPenalty = props.frequencyPenalty;\n        }\n        if (\n          Array.isArray(props.stopSequences) &&\n          this.canOverride(\"stopSequences\")\n        ) {\n          // Validate all elements are strings\n          if (\n            props.stopSequences.every(\n              (item): item is string => typeof item === \"string\",\n            )\n          ) {\n            streamTextParams.stopSequences = props.stopSequences;\n          }\n        }\n        if (typeof props.seed === \"number\" && this.canOverride(\"seed\")) {\n          streamTextParams.seed = props.seed;\n        }\n        if (\n          typeof props.maxRetries === \"number\" &&\n          this.canOverride(\"maxRetries\")\n        ) {\n          streamTextParams.maxRetries = props.maxRetries;\n        }\n        if (\n          props.providerOptions !== undefined &&\n          this.canOverride(\"providerOptions\")\n        ) {\n          if (\n            typeof props.providerOptions === \"object\" &&\n            props.providerOptions !== null\n          ) {\n            streamTextParams.providerOptions = props.providerOptions as Record<\n              string,\n              any\n            >;\n          }\n        }\n      }\n\n      // Set up MCP clients if configured and process the stream\n      const mcpClients: MCPClient[] = [];\n\n      (async () => {\n        let terminalEventEmitted = false;\n        let messageId = randomUUID();\n        let reasoningMessageId = randomUUID();\n        let isInReasoning = false;\n\n        // Auto-close an open reasoning lifecycle.\n        // Some AI SDK providers (notably @ai-sdk/anthropic) never emit \"reasoning-end\",\n        // which leaves downstream state machines stuck. This helper emits the\n        // missing REASONING_MESSAGE_END + REASONING_END events so the stream\n        // can transition to text, tool-call, or finish phases.\n        // Declared before try/catch so it is accessible in the catch block.\n        const closeReasoningIfOpen = () => {\n          if (!isInReasoning) return;\n          isInReasoning = false;\n          const reasoningMsgEnd: ReasoningMessageEndEvent = {\n            type: EventType.REASONING_MESSAGE_END,\n            messageId: reasoningMessageId,\n          };\n          subscriber.next(reasoningMsgEnd);\n          const reasoningEnd: ReasoningEndEvent = {\n            type: EventType.REASONING_END,\n            messageId: reasoningMessageId,\n          };\n          subscriber.next(reasoningEnd);\n        };\n\n        try {\n          // Add AG-UI state update tools\n          streamTextParams.tools = {\n            ...streamTextParams.tools,\n            AGUISendStateSnapshot: createVercelAISDKTool({\n              description:\n                \"Replace the entire application state with a new snapshot\",\n              inputSchema: toLanguageModelSchema(\n                z.object({\n                  snapshot: z.any().describe(\"The complete new state object\"),\n                }),\n              ),\n              execute: async ({ snapshot }: { snapshot?: unknown }) => {\n                return { success: true, snapshot };\n              },\n            }),\n            AGUISendStateDelta: createVercelAISDKTool({\n              description:\n                \"Apply incremental updates to application state using JSON Patch operations\",\n              inputSchema: toLanguageModelSchema(\n                z.object({\n                  delta: z\n                    .array(\n                      z.object({\n                        op: z\n                          .enum([\"add\", \"replace\", \"remove\"])\n                          .describe(\"The operation to perform\"),\n                        path: z\n                          .string()\n                          .describe(\"JSON Pointer path (e.g., '/foo/bar')\"),\n                        value: z\n                          .any()\n                          .optional()\n                          .describe(\n                            \"The value to set. Required for 'add' and 'replace' operations, ignored for 'remove'.\",\n                          ),\n                      }),\n                    )\n                    .describe(\"Array of JSON Patch operations\"),\n                }),\n              ),\n              execute: async ({\n                delta,\n              }: {\n                delta: {\n                  op: \"add\" | \"replace\" | \"remove\";\n                  path: string;\n                  value?: unknown;\n                }[];\n              }) => {\n                return { success: true, delta };\n              },\n            }),\n          };\n\n          // Merge tools from user-managed MCP clients (user controls lifecycle)\n          if (config.mcpClients && config.mcpClients.length > 0) {\n            for (const client of config.mcpClients) {\n              const mcpTools = await client.tools();\n              streamTextParams.tools = {\n                ...streamTextParams.tools,\n                ...mcpTools,\n              } as ToolSet;\n            }\n          }\n\n          // Initialize MCP clients and get their tools from\n          // `config.mcpServers` — the user-supplied static array.\n          const allMcpServers: MCPClientConfig[] = [\n            ...(config.mcpServers ?? []),\n          ];\n          if (allMcpServers.length > 0) {\n            for (const serverConfig of allMcpServers) {\n              let transport;\n\n              if (serverConfig.type === \"http\") {\n                const url = new URL(serverConfig.url);\n                transport = new StreamableHTTPClientTransport(\n                  url,\n                  serverConfig.options,\n                );\n              } else if (serverConfig.type === \"sse\") {\n                transport = new SSEClientTransport(\n                  new URL(serverConfig.url),\n                  serverConfig.headers,\n                );\n              }\n\n              if (transport) {\n                // A single MCP server being unavailable (down, 5xx, timeout,\n                // bad auth) must NOT fail the whole run — skip it and continue\n                // with the healthy servers and the agent's own tools. The run\n                // degrades gracefully instead of erroring out.\n                let mcpClient;\n                try {\n                  mcpClient = await createMCPClient({ transport });\n                } catch (err) {\n                  console.error(\n                    `[CopilotKit] MCP server ${serverConfig.url} failed to connect — skipping it for this run:`,\n                    err,\n                  );\n                  continue;\n                }\n                // Track it so it's closed on cleanup even if tools() fails.\n                mcpClients.push(mcpClient);\n                try {\n                  // Get tools from this MCP server and merge with existing tools\n                  const mcpTools = await mcpClient.tools();\n                  streamTextParams.tools = {\n                    ...streamTextParams.tools,\n                    ...mcpTools,\n                  } as ToolSet;\n                } catch (err) {\n                  console.error(\n                    `[CopilotKit] MCP server ${serverConfig.url} tools() failed — skipping its tools for this run:`,\n                    err,\n                  );\n                }\n              }\n            }\n          }\n\n          // Call streamText and process the stream\n          const response = streamText({\n            ...streamTextParams,\n            abortSignal: abortController.signal,\n          });\n\n          // Names of tools flagged as interrupt tools (classic config only).\n          const interruptToolNames = new Set(\n            (isFactoryConfig(this.config) ? [] : (this.config.tools ?? []))\n              .filter((t) => t.interrupt)\n              .map((t) => t.name),\n          );\n          const interruptToolMeta = new Map(\n            (isFactoryConfig(this.config) ? [] : (this.config.tools ?? []))\n              .filter((t) => t.interrupt)\n              .map((t) => [\n                t.name,\n                {\n                  reason: t.interruptReason ?? \"tool_call\",\n                  message: t.interruptMessage,\n                },\n              ]),\n          );\n          const pendingInterrupts: Interrupt[] = [];\n\n          const toolCallStates = new Map<\n            string,\n            {\n              started: boolean;\n              hasArgsDelta: boolean;\n              ended: boolean;\n              toolName?: string;\n            }\n          >();\n\n          const ensureToolCallState = (toolCallId: string) => {\n            let state = toolCallStates.get(toolCallId);\n            if (!state) {\n              state = { started: false, hasArgsDelta: false, ended: false };\n              toolCallStates.set(toolCallId, state);\n            }\n            return state;\n          };\n\n          // Process fullStream events\n          for await (const part of response.fullStream) {\n            // Close any open reasoning lifecycle on every event except\n            // reasoning-delta, which arrives mid-block and must not interrupt it.\n            if (part.type !== \"reasoning-delta\") {\n              closeReasoningIfOpen();\n            }\n\n            switch (part.type) {\n              case \"abort\": {\n                const abortEndEvent: RunFinishedEvent = {\n                  type: EventType.RUN_FINISHED,\n                  threadId: input.threadId,\n                  runId: input.runId,\n                };\n                subscriber.next(abortEndEvent);\n                terminalEventEmitted = true;\n\n                // Complete the observable\n                subscriber.complete();\n                break;\n              }\n              case \"reasoning-start\": {\n                // Use SDK-provided id, or generate a fresh UUID if the id is falsy,\n                // \"0\", or matches the non-unique pattern emitted by @ai-sdk/openai-compatible\n                // (e.g. \"txt-0\", \"reasoning-0\", \"msg-0\").\n                const providedId = \"id\" in part ? part.id : undefined;\n                const isNonUniqueId =\n                  !providedId ||\n                  providedId === \"0\" ||\n                  /^(txt|reasoning|msg)-0$/.test(providedId);\n                reasoningMessageId = isNonUniqueId\n                  ? randomUUID()\n                  : (providedId as typeof reasoningMessageId);\n                const reasoningStartEvent: ReasoningStartEvent = {\n                  type: EventType.REASONING_START,\n                  messageId: reasoningMessageId,\n                };\n                subscriber.next(reasoningStartEvent);\n                const reasoningMessageStart: ReasoningMessageStartEvent = {\n                  type: EventType.REASONING_MESSAGE_START,\n                  messageId: reasoningMessageId,\n                  role: \"reasoning\",\n                };\n                subscriber.next(reasoningMessageStart);\n                isInReasoning = true;\n                break;\n              }\n              case \"reasoning-delta\": {\n                const delta = part.text ?? \"\";\n                if (!delta) break; // skip — @ag-ui/core schema requires delta to be non-empty\n                const reasoningDeltaEvent: ReasoningMessageContentEvent = {\n                  type: EventType.REASONING_MESSAGE_CONTENT,\n                  messageId: reasoningMessageId,\n                  delta,\n                };\n                subscriber.next(reasoningDeltaEvent);\n                break;\n              }\n              case \"reasoning-end\": {\n                // closeReasoningIfOpen() already called before the switch — no-op here\n                // if the SDK never emits this event (e.g. @ai-sdk/anthropic).\n                break;\n              }\n              case \"tool-input-start\": {\n                const toolCallId = part.id;\n                const state = ensureToolCallState(toolCallId);\n                state.toolName = part.toolName;\n                if (!state.started) {\n                  state.started = true;\n                  const startEvent: ToolCallStartEvent = {\n                    type: EventType.TOOL_CALL_START,\n                    parentMessageId: messageId,\n                    toolCallId,\n                    toolCallName: part.toolName,\n                  };\n                  subscriber.next(startEvent);\n                }\n                break;\n              }\n\n              case \"tool-input-delta\": {\n                const toolCallId = part.id;\n                const state = ensureToolCallState(toolCallId);\n                state.hasArgsDelta = true;\n                const argsEvent: ToolCallArgsEvent = {\n                  type: EventType.TOOL_CALL_ARGS,\n                  toolCallId,\n                  delta: part.delta,\n                };\n                subscriber.next(argsEvent);\n                break;\n              }\n\n              case \"tool-input-end\": {\n                // No direct event – the subsequent \"tool-call\" part marks completion.\n                break;\n              }\n\n              case \"text-start\": {\n                // New text message starting - use the SDK-provided id\n                // Use randomUUID() if part.id is falsy, \"0\", or matches the non-unique\n                // pattern emitted by @ai-sdk/openai-compatible (e.g. \"txt-0\", \"msg-0\").\n                const providedId = \"id\" in part ? part.id : undefined;\n                const isNonUniqueTextId =\n                  !providedId ||\n                  providedId === \"0\" ||\n                  /^(txt|reasoning|msg)-0$/.test(providedId);\n                messageId = isNonUniqueTextId\n                  ? randomUUID()\n                  : (providedId as typeof messageId);\n                break;\n              }\n\n              case \"text-delta\": {\n                // Accumulate text content - in AI SDK 5.0, the property is 'text'\n                const textDelta = \"text\" in part ? part.text : \"\";\n                // Emit text chunk event\n                const textEvent: TextMessageChunkEvent = {\n                  type: EventType.TEXT_MESSAGE_CHUNK,\n                  role: \"assistant\",\n                  messageId,\n                  delta: textDelta,\n                };\n                subscriber.next(textEvent);\n                break;\n              }\n\n              case \"tool-call\": {\n                const toolCallId = part.toolCallId;\n                const state = ensureToolCallState(toolCallId);\n                state.toolName = part.toolName ?? state.toolName;\n\n                if (!state.started) {\n                  state.started = true;\n                  const startEvent: ToolCallStartEvent = {\n                    type: EventType.TOOL_CALL_START,\n                    parentMessageId: messageId,\n                    toolCallId,\n                    toolCallName: part.toolName,\n                  };\n                  subscriber.next(startEvent);\n                }\n\n                if (\n                  !state.hasArgsDelta &&\n                  \"input\" in part &&\n                  part.input !== undefined\n                ) {\n                  let serializedInput = \"\";\n                  if (typeof part.input === \"string\") {\n                    serializedInput = part.input;\n                  } else {\n                    try {\n                      serializedInput = JSON.stringify(part.input);\n                    } catch {\n                      serializedInput = String(part.input);\n                    }\n                  }\n\n                  if (serializedInput.length > 0) {\n                    const argsEvent: ToolCallArgsEvent = {\n                      type: EventType.TOOL_CALL_ARGS,\n                      toolCallId,\n                      delta: serializedInput,\n                    };\n                    subscriber.next(argsEvent);\n                    state.hasArgsDelta = true;\n                  }\n                }\n\n                if (!state.ended) {\n                  state.ended = true;\n                  const endEvent: ToolCallEndEvent = {\n                    type: EventType.TOOL_CALL_END,\n                    toolCallId,\n                  };\n                  subscriber.next(endEvent);\n                }\n\n                if (state.toolName && interruptToolNames.has(state.toolName)) {\n                  const meta = interruptToolMeta.get(state.toolName);\n                  pendingInterrupts.push({\n                    id: toolCallId,\n                    toolCallId,\n                    reason: meta?.reason ?? \"tool_call\",\n                    ...(meta?.message ? { message: meta.message } : {}),\n                  });\n                }\n                break;\n              }\n\n              case \"tool-result\": {\n                // Prefer the accumulated tool name (some providers omit toolName\n                // on the result part); fall back to the tool-call state so\n                // interrupt-tool suppression below can't desync from detection.\n                const toolName =\n                  (\"toolName\" in part && part.toolName) ||\n                  toolCallStates.get(part.toolCallId)?.toolName ||\n                  \"\";\n                // Suppress result events for interrupt tools — they have no execute\n                // and the result is provided by the human on the resume run.\n                if (toolName && interruptToolNames.has(toolName)) {\n                  toolCallStates.delete(part.toolCallId);\n                  break;\n                }\n                // AI SDK tool-result uses \"output\"; older versions used\n                // \"result\" (which current typings no longer declare) — check both\n                const legacyPart = part as {\n                  output?: unknown;\n                  result?: unknown;\n                };\n                const toolResult =\n                  \"output\" in part\n                    ? part.output\n                    : \"result\" in legacyPart\n                      ? legacyPart.result\n                      : null;\n                toolCallStates.delete(part.toolCallId);\n\n                // Check if this is a state update tool\n                if (\n                  toolName === \"AGUISendStateSnapshot\" &&\n                  toolResult &&\n                  typeof toolResult === \"object\"\n                ) {\n                  const snapshot = toolResult.snapshot;\n                  if (snapshot !== undefined) {\n                    const stateSnapshotEvent: StateSnapshotEvent = {\n                      type: EventType.STATE_SNAPSHOT,\n                      snapshot,\n                    };\n                    subscriber.next(stateSnapshotEvent);\n                  }\n                } else if (\n                  toolName === \"AGUISendStateDelta\" &&\n                  toolResult &&\n                  typeof toolResult === \"object\"\n                ) {\n                  const delta = toolResult.delta;\n                  if (delta !== undefined) {\n                    const stateDeltaEvent: StateDeltaEvent = {\n                      type: EventType.STATE_DELTA,\n                      delta,\n                    };\n                    subscriber.next(stateDeltaEvent);\n                  }\n                }\n\n                // Always emit the tool result event for the LLM\n                let serializedResult: string;\n                try {\n                  serializedResult = JSON.stringify(toolResult);\n                } catch {\n                  serializedResult = `[Unserializable tool result from ${toolName || part.toolCallId}]`;\n                }\n                const resultEvent: ToolCallResultEvent = {\n                  type: EventType.TOOL_CALL_RESULT,\n                  role: \"tool\",\n                  messageId: randomUUID(),\n                  toolCallId: part.toolCallId,\n                  content: serializedResult,\n                };\n                subscriber.next(resultEvent);\n                break;\n              }\n\n              case \"finish\": {\n                // Emit run finished event\n                const finishedEvent: RunFinishedEvent = {\n                  type: EventType.RUN_FINISHED,\n                  threadId: input.threadId,\n                  runId: input.runId,\n                  ...(pendingInterrupts.length > 0\n                    ? {\n                        outcome: {\n                          type: \"interrupt\",\n                          interrupts: pendingInterrupts,\n                        },\n                      }\n                    : {}),\n                };\n                subscriber.next(finishedEvent);\n                terminalEventEmitted = true;\n\n                // Complete the observable\n                subscriber.complete();\n                break;\n              }\n\n              case \"error\": {\n                if (abortController.signal.aborted) {\n                  break;\n                }\n                // Current typings only declare `error`; older stream shapes\n                // also carried `message`/`cause`.\n                const err =\n                  part.error ??\n                  (\"message\" in part ? part.message : undefined) ??\n                  (\"cause\" in part ? part.cause : undefined);\n                const runErrorEvent: RunErrorEvent = {\n                  type: EventType.RUN_ERROR,\n                  message:\n                    err instanceof Error\n                      ? err.message\n                      : typeof err === \"string\"\n                        ? err\n                        : `AI SDK stream error: ${JSON.stringify(part)}`,\n                  threadId: input.threadId,\n                  runId: input.runId,\n                } as RunErrorEvent;\n                subscriber.next(runErrorEvent);\n                terminalEventEmitted = true;\n\n                // Handle error\n                if (err instanceof Error) subscriber.error(err);\n                else\n                  subscriber.error(\n                    new Error(\n                      typeof err === \"string\" ? err : `AI SDK stream error`,\n                    ),\n                  );\n                break;\n              }\n            }\n          }\n\n          if (!terminalEventEmitted) {\n            closeReasoningIfOpen();\n            if (abortController.signal.aborted) {\n              // Let the runner finalize the stream on stop requests so it can\n              // inject consistent closing events and a RUN_FINISHED marker.\n            } else {\n              const finishedEvent: RunFinishedEvent = {\n                type: EventType.RUN_FINISHED,\n                threadId: input.threadId,\n                runId: input.runId,\n                ...(pendingInterrupts.length > 0\n                  ? {\n                      outcome: {\n                        type: \"interrupt\",\n                        interrupts: pendingInterrupts,\n                      },\n                    }\n                  : {}),\n              };\n              subscriber.next(finishedEvent);\n            }\n\n            terminalEventEmitted = true;\n            subscriber.complete();\n          }\n        } catch (error) {\n          closeReasoningIfOpen();\n          if (abortController.signal.aborted) {\n            subscriber.complete();\n          } else {\n            const runErrorEvent: RunErrorEvent = {\n              type: EventType.RUN_ERROR,\n              message: error instanceof Error ? error.message : String(error),\n              threadId: input.threadId,\n              runId: input.runId,\n            } as RunErrorEvent;\n            subscriber.next(runErrorEvent);\n            terminalEventEmitted = true;\n            subscriber.error(error);\n          }\n        } finally {\n          this.abortController = undefined;\n          await Promise.all(mcpClients.map((client) => client.close()));\n        }\n      })();\n\n      // Cleanup function\n      return () => {\n        // Cleanup MCP clients if stream is unsubscribed\n        Promise.all(mcpClients.map((client) => client.close())).catch(() => {\n          // Ignore cleanup errors\n        });\n      };\n    });\n  }\n\n  private runFactory(\n    input: RunAgentInput,\n    config: BuiltInAgentFactoryConfig,\n  ): Observable<BaseEvent> {\n    if (this.abortController) {\n      throw new Error(\n        \"Agent is already running. Call abortRun() first or create a new instance.\",\n      );\n    }\n\n    // Set synchronously before Observable creation to close TOCTOU window\n    this.abortController = new AbortController();\n    const controller = this.abortController;\n\n    return new Observable<BaseEvent>((subscriber) => {\n      const startEvent: RunStartedEvent = {\n        type: EventType.RUN_STARTED,\n        threadId: input.threadId,\n        runId: input.runId,\n      };\n      subscriber.next(startEvent);\n\n      const ctx: AgentFactoryContext = {\n        input,\n        abortController: controller,\n        abortSignal: controller.signal,\n        interrupt: async (interrupts: Interrupt[]) => {\n          const resume = input.resume ?? [];\n          const ids = new Set(interrupts.map((i) => i.id));\n          const matching = resume.filter((r) => ids.has(r.interruptId));\n          // All requested interrupts addressed → resume: return responses.\n          if (interrupts.length > 0 && matching.length === interrupts.length) {\n            return matching;\n          }\n          // Fresh run (or not yet addressed) → pause.\n          throw new InterruptSignal(interrupts);\n        },\n      };\n\n      // Resume injection (aisdk/tanstack): map each ResumeEntry to a tool-role\n      // message keyed by interruptId (=== the paused tool call's id) and append\n      // it to the messages the factory sees. Both SDK converters\n      // (convertMessagesToVercelAISDKMessages / convertInputToTanStackAI) turn a\n      // tool-role message into that SDK's native tool-result, so the model\n      // continues — no SDK-specific approval-response wiring needed. The `custom`\n      // factory reads input.resume itself via ctx.interrupt(), so leave it alone.\n      // Idempotent: skip entries the client already recorded as a tool-result\n      // message in the thread (useInterrupt persists resolutions so the\n      // conversation stays well-formed across turns). Only synthesize results\n      // for entries that aren't already answered, so we never double-answer a\n      // tool call.\n      const answeredToolCallIds = new Set(\n        input.messages\n          .filter((m) => m.role === \"tool\")\n          .map((m) => (m as { toolCallId?: string }).toolCallId)\n          .filter((id): id is string => typeof id === \"string\"),\n      );\n      const resumeToolMessages: Message[] = (input.resume ?? [])\n        .filter(\n          (entry: ResumeEntry) => !answeredToolCallIds.has(entry.interruptId),\n        )\n        .map(\n          (entry: ResumeEntry): Message => ({\n            id: randomUUID(),\n            role: \"tool\",\n            toolCallId: entry.interruptId,\n            content: JSON.stringify(\n              entry.status === \"cancelled\"\n                ? { status: \"cancelled\" }\n                : (entry.payload ?? { status: \"resolved\" }),\n            ),\n          }),\n        );\n      const factoryInput: RunAgentInput =\n        resumeToolMessages.length > 0 && config.type !== \"custom\"\n          ? { ...input, messages: [...input.messages, ...resumeToolMessages] }\n          : input;\n      const factoryCtx: AgentFactoryContext = { ...ctx, input: factoryInput };\n\n      (async () => {\n        try {\n          let events: AsyncIterable<BaseEvent>;\n          // Filled by the converters with one Interrupt per native approval\n          // request; a non-empty array after the stream drains pauses the run.\n          const pendingInterrupts: Interrupt[] = [];\n\n          switch (config.type) {\n            case \"aisdk\": {\n              const result = await config.factory(factoryCtx);\n              events = convertAISDKStream(\n                result.fullStream,\n                controller.signal,\n                pendingInterrupts,\n              );\n              break;\n            }\n            case \"tanstack\": {\n              const stream = await config.factory(factoryCtx);\n              events = convertTanStackStream(\n                stream,\n                controller.signal,\n                pendingInterrupts,\n              );\n              break;\n            }\n            case \"custom\": {\n              events = await config.factory(ctx);\n              break;\n            }\n            default: {\n              const _exhaustive: never = config;\n              throw new Error(\n                `Unknown agent config type: ${(_exhaustive as BuiltInAgentFactoryConfig).type}`,\n              );\n            }\n          }\n\n          for await (const event of events) {\n            subscriber.next(event);\n          }\n\n          // A native approval request pauses the run: reuse the same\n          // InterruptSignal path the `custom` factory's ctx.interrupt() uses,\n          // which the catch below turns into RUN_FINISHED outcome:interrupt.\n          if (pendingInterrupts.length > 0 && !controller.signal.aborted) {\n            throw new InterruptSignal(pendingInterrupts);\n          }\n\n          if (!controller.signal.aborted) {\n            const finishedEvent: RunFinishedEvent = {\n              type: EventType.RUN_FINISHED,\n              threadId: input.threadId,\n              runId: input.runId,\n            };\n            subscriber.next(finishedEvent);\n          }\n          subscriber.complete();\n        } catch (error) {\n          if (error instanceof InterruptSignal) {\n            const finishedEvent: RunFinishedEvent = {\n              type: EventType.RUN_FINISHED,\n              threadId: input.threadId,\n              runId: input.runId,\n              outcome: { type: \"interrupt\", interrupts: error.interrupts },\n            };\n            subscriber.next(finishedEvent);\n            subscriber.complete();\n          } else if (controller.signal.aborted) {\n            subscriber.complete();\n          } else {\n            const runErrorEvent: RunErrorEvent = {\n              type: EventType.RUN_ERROR,\n              message: error instanceof Error ? error.message : String(error),\n              threadId: input.threadId,\n              runId: input.runId,\n            } as RunErrorEvent;\n            subscriber.next(runErrorEvent);\n            subscriber.error(error);\n          }\n        } finally {\n          this.abortController = undefined;\n        }\n      })();\n\n      return () => {\n        controller.abort();\n      };\n    });\n  }\n\n  clone() {\n    const cloned = new BuiltInAgent(this.config);\n    // AbstractAgent.middlewares is private in @ag-ui/client — no public accessor exists.\n    // This coupling is intentional: clone() must preserve middleware chains.\n    // @ts-expect-error accessing private AbstractAgent.middlewares\n    cloned.middlewares = [...this.middlewares];\n    return cloned;\n  }\n\n  abortRun(): void {\n    this.abortController?.abort();\n  }\n}\n\n/**\n * @deprecated Use BuiltInAgent instead\n */\nexport class BasicAgent extends BuiltInAgent {\n  constructor(config: BuiltInAgentConfiguration) {\n    super(config);\n    console.warn(\"BasicAgent is deprecated, use BuiltInAgent instead\");\n  }\n}\n\n/** @deprecated Use BuiltInAgentClassicConfig instead */\nexport type BasicAgentConfiguration = BuiltInAgentClassicConfig;\n\nexport * from \"./converters\";\n"],"mappings":"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"}