@copilotkit/runtime
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
1 lines • 93.8 kB
Source Map (JSON)
{"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 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, MCPTransport } 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 { createStateEventNormalizer } from \"./state-delta\";\nimport type { StreamableHTTPClientTransportOptions } from \"@modelcontextprotocol/sdk/client/streamableHttp.js\";\nimport { StreamableHTTPClientTransport } from \"@modelcontextprotocol/sdk/client/streamableHttp.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 // MiniMax models\n | \"minimax/MiniMax-M3\"\n | \"minimax/MiniMax-M2.7\"\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 // Honor an OpenAI-COMPATIBLE endpoint (Azure OpenAI, OpenRouter, a gateway,\n // vLLM/LM Studio/Ollama, etc.) via the standard OPENAI_BASE_URL env var.\n // Undefined when unset, so the provider falls back to its default\n // (api.openai.com) — fully backward compatible.\n baseURL: process.env.OPENAI_BASE_URL,\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 // Honor a custom Anthropic-compatible endpoint via ANTHROPIC_BASE_URL (see OpenAI note).\n baseURL: process.env.ANTHROPIC_BASE_URL,\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 // Honor a custom Google-compatible endpoint via GOOGLE_GENERATIVE_AI_BASE_URL (see OpenAI note).\n baseURL: process.env.GOOGLE_GENERATIVE_AI_BASE_URL,\n });\n // Accepts any Gemini id, e.g. \"gemini-2.5-pro\", \"gemini-2.5-flash\"\n return google(model);\n }\n\n case \"minimax\": {\n const minimax = createOpenAI({\n name: \"minimax\",\n apiKey: apiKey || process.env.MINIMAX_API_KEY!,\n baseURL: process.env.MINIMAX_BASE_URL || \"https://api.minimax.io/v1\",\n });\n return minimax(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 // Union combinators. A frontend tool authored with `z.discriminatedUnion`\n // (or any `z.union`) serializes to a node carrying `anyOf` / `oneOf` and\n // usually NO top-level `type`.\n anyOf?: JsonSchema[];\n oneOf?: JsonSchema[];\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 `anyOf` / `oneOf` unions (e.g. `z.discriminatedUnion` or `z.union`\n // on a frontend tool) as `z.union`. These nodes usually carry no top-level\n // `type`, so they MUST be handled before the empty-schema guard below —\n // otherwise the union collapses to an empty object (`z.object({})`), the\n // reconstructed tool schema loses the union-typed field entirely, and the\n // model can never emit it. This is especially load-bearing for a union\n // nested inside array `items`, which OpenAI otherwise silently drops.\n const unionVariants = jsonSchema.anyOf ?? jsonSchema.oneOf;\n if (Array.isArray(unionVariants) && unionVariants.length > 0) {\n // A single-variant union is just that variant.\n if (unionVariants.length === 1) {\n return convertJsonSchemaToZodSchema(unionVariants[0], required);\n }\n const variantSchemas = unionVariants.map((variant) =>\n convertJsonSchemaToZodSchema(variant, true),\n );\n const schema = z\n .union(variantSchemas as [z.ZodSchema, z.ZodSchema, ...z.ZodSchema[]])\n .describe(jsonSchema.description ?? \"\");\n return required ? schema : schema.optional();\n }\n\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 * - MINIMAX_API_KEY for MiniMax 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: MCPTransport | undefined;\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 // Imported lazily: the SDK's SSE transport pulls in\n // `eventsource`, whose `bun` export condition resolves to ESM\n // and breaks the SDK's own CJS `require()` under Bun. Keeping\n // it out of this module's static graph means only configs that\n // actually ask for SSE ever load it.\n const { SSEClientTransport } =\n await import(\"@modelcontextprotocol/sdk/client/sse.js\");\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: 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 const normalizeStateEvent = createStateEventNormalizer(input.state);\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: BaseEvent = {\n type: EventType.STATE_SNAPSHOT,\n snapshot,\n };\n for (const event of normalizeStateEvent(\n stateSnapshotEvent,\n )) {\n subscriber.next(event);\n }\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: BaseEvent = {\n type: EventType.STATE_DELTA,\n delta,\n };\n for (const event of normalizeStateEvent(stateDeltaEvent)) {\n subscriber.next(event);\n }\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 input.state,\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 input.state,\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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"}