@copilotkit/runtime 1.61.1 → 1.61.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/agent/converters/aisdk.cjs +52 -1
- package/dist/agent/converters/aisdk.cjs.map +1 -1
- package/dist/agent/converters/aisdk.d.cts +6 -2
- package/dist/agent/converters/aisdk.d.cts.map +1 -1
- package/dist/agent/converters/aisdk.d.mts +6 -2
- package/dist/agent/converters/aisdk.d.mts.map +1 -1
- package/dist/agent/converters/aisdk.mjs +52 -1
- package/dist/agent/converters/aisdk.mjs.map +1 -1
- package/dist/agent/converters/tanstack.cjs +17 -1
- package/dist/agent/converters/tanstack.cjs.map +1 -1
- package/dist/agent/converters/tanstack.d.cts +6 -2
- package/dist/agent/converters/tanstack.d.cts.map +1 -1
- package/dist/agent/converters/tanstack.d.mts +6 -2
- package/dist/agent/converters/tanstack.d.mts.map +1 -1
- package/dist/agent/converters/tanstack.mjs +17 -1
- package/dist/agent/converters/tanstack.mjs.map +1 -1
- package/dist/agent/index.cjs +165 -39
- package/dist/agent/index.cjs.map +1 -1
- package/dist/agent/index.d.cts +42 -4
- package/dist/agent/index.d.cts.map +1 -1
- package/dist/agent/index.d.mts +42 -4
- package/dist/agent/index.d.mts.map +1 -1
- package/dist/agent/index.mjs +165 -40
- package/dist/agent/index.mjs.map +1 -1
- package/dist/graphql/message-conversion/agui-to-gql.cjs +5 -3
- package/dist/graphql/message-conversion/agui-to-gql.cjs.map +1 -1
- package/dist/graphql/message-conversion/agui-to-gql.mjs +5 -3
- package/dist/graphql/message-conversion/agui-to-gql.mjs.map +1 -1
- package/dist/lib/integrations/node-http/request-handler.cjs.map +1 -1
- package/dist/lib/integrations/node-http/request-handler.mjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.cjs +1 -1
- package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
- package/dist/lib/runtime/copilot-runtime.mjs +1 -1
- package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.mjs +1 -1
- package/dist/service-adapters/openai/openai-assistant-adapter.cjs.map +1 -1
- package/dist/service-adapters/openai/openai-assistant-adapter.d.cts.map +1 -1
- package/dist/service-adapters/openai/openai-assistant-adapter.d.mts.map +1 -1
- package/dist/service-adapters/openai/openai-assistant-adapter.mjs.map +1 -1
- package/dist/service-adapters/openai/utils.cjs.map +1 -1
- package/dist/service-adapters/openai/utils.mjs.map +1 -1
- package/dist/v2/index.cjs +1 -0
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +2 -2
- package/dist/v2/runtime/core/runtime.cjs.map +1 -1
- package/dist/v2/runtime/core/runtime.d.cts +3 -3
- package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
- package/dist/v2/runtime/core/runtime.d.mts +3 -3
- package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
- package/dist/v2/runtime/core/runtime.mjs.map +1 -1
- package/dist/v2/runtime/endpoints/express-fetch-bridge.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/express-fetch-bridge.mjs.map +1 -1
- package/dist/v2/runtime/endpoints/single-route-helpers.cjs +1 -1
- package/dist/v2/runtime/endpoints/single-route-helpers.cjs.map +1 -1
- package/dist/v2/runtime/endpoints/single-route-helpers.mjs +1 -1
- package/dist/v2/runtime/endpoints/single-route-helpers.mjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.cjs +4 -3
- package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -1
- package/dist/v2/runtime/handlers/handle-run.mjs +4 -3
- package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.cjs +0 -2
- package/dist/v2/runtime/handlers/intelligence/thread-names.cjs.map +1 -1
- package/dist/v2/runtime/handlers/intelligence/thread-names.mjs +0 -2
- package/dist/v2/runtime/handlers/intelligence/thread-names.mjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs +8 -4
- package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs +8 -4
- package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
- package/dist/v2/runtime/runner/in-memory.cjs.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.cts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.d.mts.map +1 -1
- package/dist/v2/runtime/runner/in-memory.mjs.map +1 -1
- package/dist/v2/runtime/runner/intelligence.cjs.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -1
- package/dist/v2/runtime/runner/intelligence.mjs.map +1 -1
- package/package.json +2 -2
package/dist/agent/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"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} 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} 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 * Tool definition for BuiltInAgent\n */\nexport interface ToolDefinition<\n TParameters extends StandardSchemaV1 = StandardSchemaV1,\n> {\n name: string;\n description: string;\n parameters: TParameters;\n execute: (args: InferSchemaOutput<TParameters>) => Promise<unknown>;\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}): ToolDefinition<TParameters> {\n return {\n name: config.name,\n description: config.description,\n parameters: config.parameters,\n execute: config.execute,\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\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: 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\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 };\n\n if (!this.config.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 ...this.config.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 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(this.config.model, this.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 = !!this.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(this.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: this.config.forwardSystemMessages,\n forwardDeveloperMessages: this.config.forwardDeveloperMessages,\n });\n if (systemPrompt) {\n messages.unshift({\n role: \"system\",\n content: systemPrompt,\n });\n }\n\n // Merge tools from input and config\n let allTools: ToolSet = convertToolsToVercelAITools(input.tools);\n if (this.config.tools && this.config.tools.length > 0) {\n const configTools = convertToolDefinitionsToVercelAITools(\n this.config.tools,\n );\n allTools = { ...allTools, ...configTools };\n }\n\n const streamTextParams: Parameters<typeof streamText>[0] = {\n model,\n messages,\n tools: allTools,\n toolChoice: this.config.toolChoice,\n stopWhen: this.config.maxSteps\n ? stepCountIs(this.config.maxSteps)\n : undefined,\n maxOutputTokens: this.config.maxOutputTokens,\n temperature: this.config.temperature,\n topP: this.config.topP,\n topK: this.config.topK,\n presencePenalty: this.config.presencePenalty,\n frequencyPenalty: this.config.frequencyPenalty,\n stopSequences: this.config.stopSequences,\n seed: this.config.seed,\n providerOptions: this.config.providerOptions,\n maxRetries: this.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 this.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: z.object({\n snapshot: z.any().describe(\"The complete new state object\"),\n }),\n execute: async ({ snapshot }) => {\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: 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 execute: async ({ delta }) => {\n return { success: true, delta };\n },\n }),\n };\n\n // Merge tools from user-managed MCP clients (user controls lifecycle)\n if (this.config.mcpClients && this.config.mcpClients.length > 0) {\n for (const client of this.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 ...(this.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 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 break;\n }\n\n case \"tool-result\": {\n const toolResult =\n \"output\" in part\n ? part.output\n : \"result\" in part\n ? part.result\n : null;\n const toolName = \"toolName\" in part ? part.toolName : \"\";\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 };\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 const err = part.error ?? part.message ?? part.cause;\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 };\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 };\n\n (async () => {\n try {\n let events: AsyncIterable<BaseEvent>;\n\n switch (config.type) {\n case \"aisdk\": {\n const result = await config.factory(ctx);\n events = convertAISDKStream(result.fullStream, controller.signal);\n break;\n }\n case \"tanstack\": {\n const stream = await config.factory(ctx);\n events = convertTanStackStream(stream, controller.signal);\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 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 (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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"}
|
|
1
|
+
{"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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"}
|
|
@@ -10,8 +10,10 @@ function isAgentStateMessage(message) {
|
|
|
10
10
|
return message.role === "assistant" && "agentName" in message && "state" in message;
|
|
11
11
|
}
|
|
12
12
|
function hasImageProperty(message) {
|
|
13
|
-
if (!(message.role === "assistant" || message.role === "user")
|
|
14
|
-
|
|
13
|
+
if (!(message.role === "assistant" || message.role === "user")) return false;
|
|
14
|
+
const image = "image" in message ? message.image : void 0;
|
|
15
|
+
if (image === void 0) return false;
|
|
16
|
+
if (image.format === void 0 || image.bytes === void 0) return false;
|
|
15
17
|
return true;
|
|
16
18
|
}
|
|
17
19
|
function normalizeMessageContent(content) {
|
|
@@ -99,7 +101,7 @@ function aguiToolCallToGQLActionExecution(toolCall, parentMessageId) {
|
|
|
99
101
|
let argumentsObj;
|
|
100
102
|
if (typeof toolCall.function.arguments === "string") try {
|
|
101
103
|
argumentsObj = JSON.parse(toolCall.function.arguments);
|
|
102
|
-
} catch
|
|
104
|
+
} catch {
|
|
103
105
|
console.warn(`[CopilotKit] Failed to parse tool arguments, falling back to empty object`);
|
|
104
106
|
argumentsObj = {};
|
|
105
107
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"agui-to-gql.cjs","names":[],"sources":["../../../src/graphql/message-conversion/agui-to-gql.ts"],"sourcesContent":["import * as gql from \"../types/converted/index\";\nimport { MessageRole } from \"../types/enums\";\nimport * as agui from \"@copilotkit/shared\"; // named agui for clarity, but this only includes agui message types\n\n// Helper function to extract agent name from message\nfunction extractAgentName(message: agui.Message): string {\n if (message.role !== \"assistant\") {\n throw new Error(\n `Cannot extract agent name from message with role ${message.role}`,\n );\n }\n\n return message.agentName || \"unknown\";\n}\n\n// Type guard for agent state message\nfunction isAgentStateMessage(message: agui.Message): boolean {\n return (\n message.role === \"assistant\" && \"agentName\" in message && \"state\" in message\n );\n}\n\n// Type guard for messages with image property\nfunction hasImageProperty(message: agui.Message): boolean {\n const canContainImage =\n message.role === \"assistant\" || message.role === \"user\";\n if (!canContainImage || message.image === undefined) {\n return false;\n }\n\n const isMalformed =\n message.image.format === undefined || message.image.bytes === undefined;\n if (isMalformed) {\n return false;\n }\n\n return true;\n}\n\nfunction normalizeMessageContent(content: agui.Message[\"content\"]): string {\n if (typeof content === \"string\" || typeof content === \"undefined\") {\n return content || \"\";\n }\n\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (part?.type === \"text\") {\n return part.text;\n }\n if (part?.type === \"binary\") {\n return (\n part.data ||\n part.url ||\n part.filename ||\n `[binary:${part.mimeType}]`\n );\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n }\n\n if (content && typeof content === \"object\") {\n try {\n return JSON.stringify(content);\n } catch (error) {\n console.warn(\"Failed to serialize message content\", error);\n }\n }\n\n return String(content ?? \"\");\n}\n\n/*\n ----------------------------\n AGUI Message -> GQL Message\n ----------------------------\n*/\nexport function aguiToGQL(\n messages: agui.Message[] | agui.Message,\n actions?: Record<string, any>,\n coAgentStateRenders?: Record<string, any>,\n): gql.Message[] {\n const gqlMessages: gql.Message[] = [];\n messages = Array.isArray(messages) ? messages : [messages];\n\n // Track tool call names by their IDs for use in result messages\n const toolCallNames: Record<string, string> = {};\n\n for (const message of messages) {\n // Agent state message support\n if (isAgentStateMessage(message)) {\n const agentName = extractAgentName(message);\n const state = \"state\" in message && message.state ? message.state : {};\n gqlMessages.push(\n new gql.AgentStateMessage({\n id: message.id,\n agentName,\n state,\n role: gql.Role.assistant,\n }),\n );\n // Optionally preserve render function\n if (\n \"generativeUI\" in message &&\n message.generativeUI &&\n coAgentStateRenders\n ) {\n coAgentStateRenders[agentName] = {\n name: agentName,\n render: message.generativeUI,\n };\n }\n continue;\n }\n\n if (hasImageProperty(message)) {\n gqlMessages.push(aguiMessageWithImageToGQLMessage(message));\n continue;\n }\n\n // Action execution message support\n if (message.role === \"assistant\" && message.toolCalls) {\n gqlMessages.push(aguiTextMessageToGQLMessage(message));\n for (const toolCall of message.toolCalls) {\n // Track the tool call name by its ID\n toolCallNames[toolCall.id] = toolCall.function.name;\n\n const actionExecMsg = aguiToolCallToGQLActionExecution(\n toolCall,\n message.id,\n );\n // Preserve render function in actions context\n if (\"generativeUI\" in message && message.generativeUI && actions) {\n const actionName = toolCall.function.name;\n // Check for specific action first, then wild card action\n const specificAction = Object.values(actions).find(\n (action: any) => action.name === actionName,\n );\n const wildcardAction = Object.values(actions).find(\n (action: any) => action.name === \"*\",\n );\n\n // Assign render function to the matching action (specific takes priority)\n if (specificAction) {\n specificAction.render = message.generativeUI;\n } else if (wildcardAction) {\n wildcardAction.render = message.generativeUI;\n }\n }\n gqlMessages.push(actionExecMsg);\n }\n continue;\n }\n // Reasoning messages are ephemeral display-only content with no GQL equivalent — skip them\n if (message.role === \"reasoning\") {\n continue;\n }\n // Regular text messages\n if (\n message.role === \"developer\" ||\n message.role === \"system\" ||\n message.role === \"assistant\" ||\n message.role === \"user\"\n ) {\n gqlMessages.push(aguiTextMessageToGQLMessage(message));\n continue;\n }\n // Tool result message\n if (message.role === \"tool\") {\n gqlMessages.push(\n aguiToolMessageToGQLResultMessage(message, toolCallNames),\n );\n continue;\n }\n throw new Error(\n `Unknown message role: \"${(message as any).role}\" in message with id: ${(message as any).id}`,\n );\n }\n\n return gqlMessages;\n}\n\nexport function aguiTextMessageToGQLMessage(\n message: agui.Message,\n): gql.TextMessage {\n if (\n message.role !== \"developer\" &&\n message.role !== \"system\" &&\n message.role !== \"assistant\" &&\n message.role !== \"user\"\n ) {\n throw new Error(\n `Cannot convert message with role ${message.role} to TextMessage`,\n );\n }\n\n let roleValue: MessageRole;\n\n if (message.role === \"developer\") {\n roleValue = gql.Role.developer;\n } else if (message.role === \"system\") {\n roleValue = gql.Role.system;\n } else if (message.role === \"assistant\") {\n roleValue = gql.Role.assistant;\n } else {\n roleValue = gql.Role.user;\n }\n\n return new gql.TextMessage({\n id: message.id,\n content: normalizeMessageContent(message.content),\n role: roleValue,\n });\n}\n\nexport function aguiToolCallToGQLActionExecution(\n toolCall: agui.ToolCall,\n parentMessageId: string,\n): gql.ActionExecutionMessage {\n if (toolCall.type !== \"function\") {\n throw new Error(`Unsupported tool call type: ${toolCall.type}`);\n }\n\n // Handle arguments - they should be a JSON string in AGUI format,\n // but we need to convert them to an object for GQL format\n let argumentsObj: any;\n\n if (typeof toolCall.function.arguments === \"string\") {\n // Expected case: arguments is a JSON string\n try {\n argumentsObj = JSON.parse(toolCall.function.arguments);\n } catch (error) {\n console.warn(\n `[CopilotKit] Failed to parse tool arguments, falling back to empty object`,\n );\n // Provide fallback empty object to prevent application crash\n argumentsObj = {};\n }\n } else if (\n typeof toolCall.function.arguments === \"object\" &&\n toolCall.function.arguments !== null\n ) {\n // Backward compatibility: arguments is already an object\n argumentsObj = toolCall.function.arguments;\n } else {\n // Fallback for undefined, null, or other types\n console.warn(\n `[CopilotKit] Tool arguments parsed to non-object (${typeof toolCall.function.arguments}), falling back to empty object`,\n );\n argumentsObj = {};\n }\n\n // Guard against successfully parsed non-object values (e.g. JSON.parse('\"\"') → \"\")\n if (\n typeof argumentsObj !== \"object\" ||\n argumentsObj === null ||\n Array.isArray(argumentsObj)\n ) {\n console.warn(\n `[CopilotKit] Tool arguments parsed to non-object (${typeof argumentsObj}), falling back to empty object`,\n );\n argumentsObj = {};\n }\n\n // Always include name and arguments\n return new gql.ActionExecutionMessage({\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: argumentsObj,\n parentMessageId: parentMessageId,\n });\n}\n\nexport function aguiToolMessageToGQLResultMessage(\n message: agui.Message,\n toolCallNames: Record<string, string>,\n): gql.ResultMessage {\n if (message.role !== \"tool\") {\n throw new Error(\n `Cannot convert message with role ${message.role} to ResultMessage`,\n );\n }\n\n if (!message.toolCallId) {\n throw new Error(\"Tool message must have a toolCallId\");\n }\n\n const actionName = toolCallNames[message.toolCallId] || \"unknown\";\n\n // Handle result content - it could be a string or an object that needs serialization\n let resultContent: string;\n const messageContent = message.content || \"\";\n\n if (typeof messageContent === \"string\") {\n // Expected case: content is already a string\n resultContent = messageContent;\n } else if (typeof messageContent === \"object\" && messageContent !== null) {\n // Handle case where content is an object that needs to be serialized\n try {\n resultContent = JSON.stringify(messageContent);\n } catch (error) {\n console.warn(`Failed to stringify tool result for ${actionName}:`, error);\n resultContent = String(messageContent);\n }\n } else {\n // Handle other types (number, boolean, etc.)\n resultContent = String(messageContent);\n }\n\n return new gql.ResultMessage({\n id: message.id,\n result: resultContent,\n actionExecutionId: message.toolCallId,\n actionName: message.toolName || actionName,\n });\n}\n\n// New function to handle AGUI messages with render functions\nexport function aguiMessageWithRenderToGQL(\n message: agui.Message,\n actions?: Record<string, any>,\n coAgentStateRenders?: Record<string, any>,\n): gql.Message[] {\n // Handle the special case: assistant messages with render function but no tool calls\n if (\n message.role === \"assistant\" &&\n \"generativeUI\" in message &&\n message.generativeUI &&\n !message.toolCalls\n ) {\n const gqlMessages: gql.Message[] = [];\n gqlMessages.push(\n new gql.AgentStateMessage({\n id: message.id,\n agentName: \"unknown\",\n state: {},\n role: gql.Role.assistant,\n }),\n );\n if (coAgentStateRenders) {\n coAgentStateRenders.unknown = {\n name: \"unknown\",\n render: message.generativeUI,\n };\n }\n return gqlMessages;\n }\n\n // For all other cases, delegate to aguiToGQL\n return aguiToGQL([message], actions, coAgentStateRenders);\n}\n\nexport function aguiMessageWithImageToGQLMessage(\n message: agui.Message,\n): gql.ImageMessage {\n if (!hasImageProperty(message)) {\n throw new Error(\n `Cannot convert message to ImageMessage: missing format or bytes`,\n );\n }\n\n let roleValue: MessageRole;\n if (message.role === \"assistant\") {\n roleValue = gql.Role.assistant;\n } else {\n roleValue = gql.Role.user;\n }\n\n if (message.role !== \"assistant\" && message.role !== \"user\") {\n throw new Error(\n `Cannot convert message with role ${message.role} to ImageMessage`,\n );\n }\n\n return new gql.ImageMessage({\n id: message.id,\n format: message.image!.format,\n bytes: message.image!.bytes,\n role: roleValue,\n });\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"agui-to-gql.cjs","names":[],"sources":["../../../src/graphql/message-conversion/agui-to-gql.ts"],"sourcesContent":["import * as gql from \"../types/converted/index\";\nimport { MessageRole } from \"../types/enums\";\nimport * as agui from \"@copilotkit/shared\"; // named agui for clarity, but this only includes agui message types\n\n// Helper function to extract agent name from message\nfunction extractAgentName(message: agui.Message): string {\n if (message.role !== \"assistant\") {\n throw new Error(\n `Cannot extract agent name from message with role ${message.role}`,\n );\n }\n\n return message.agentName || \"unknown\";\n}\n\n// Type guard for agent state message\nfunction isAgentStateMessage(message: agui.Message): boolean {\n return (\n message.role === \"assistant\" && \"agentName\" in message && \"state\" in message\n );\n}\n\n// Type guard for messages with image property\nfunction hasImageProperty(\n message: agui.Message,\n): message is agui.Message & { image: agui.ImageData } {\n const canContainImage =\n message.role === \"assistant\" || message.role === \"user\";\n if (!canContainImage) {\n return false;\n }\n\n const image: { format?: string; bytes?: string } | undefined =\n \"image\" in message ? message.image : undefined;\n if (image === undefined) {\n return false;\n }\n\n const isMalformed = image.format === undefined || image.bytes === undefined;\n if (isMalformed) {\n return false;\n }\n\n return true;\n}\n\nfunction normalizeMessageContent(content: agui.Message[\"content\"]): string {\n if (typeof content === \"string\" || typeof content === \"undefined\") {\n return content || \"\";\n }\n\n if (Array.isArray(content)) {\n return content\n .map((part) => {\n if (part?.type === \"text\") {\n return part.text;\n }\n if (part?.type === \"binary\") {\n return (\n part.data ||\n part.url ||\n part.filename ||\n `[binary:${part.mimeType}]`\n );\n }\n return \"\";\n })\n .filter(Boolean)\n .join(\"\\n\");\n }\n\n if (content && typeof content === \"object\") {\n try {\n return JSON.stringify(content);\n } catch (error) {\n console.warn(\"Failed to serialize message content\", error);\n }\n }\n\n return String(content ?? \"\");\n}\n\n/*\n ----------------------------\n AGUI Message -> GQL Message\n ----------------------------\n*/\nexport function aguiToGQL(\n messages: agui.Message[] | agui.Message,\n actions?: Record<string, any>,\n coAgentStateRenders?: Record<string, any>,\n): gql.Message[] {\n const gqlMessages: gql.Message[] = [];\n messages = Array.isArray(messages) ? messages : [messages];\n\n // Track tool call names by their IDs for use in result messages\n const toolCallNames: Record<string, string> = {};\n\n for (const message of messages) {\n // Agent state message support\n if (isAgentStateMessage(message)) {\n const agentName = extractAgentName(message);\n const state = \"state\" in message && message.state ? message.state : {};\n gqlMessages.push(\n new gql.AgentStateMessage({\n id: message.id,\n agentName,\n state,\n role: gql.Role.assistant,\n }),\n );\n // Optionally preserve render function\n if (\n \"generativeUI\" in message &&\n message.generativeUI &&\n coAgentStateRenders\n ) {\n coAgentStateRenders[agentName] = {\n name: agentName,\n render: message.generativeUI,\n };\n }\n continue;\n }\n\n if (hasImageProperty(message)) {\n gqlMessages.push(aguiMessageWithImageToGQLMessage(message));\n continue;\n }\n\n // Action execution message support\n if (message.role === \"assistant\" && message.toolCalls) {\n gqlMessages.push(aguiTextMessageToGQLMessage(message));\n for (const toolCall of message.toolCalls) {\n // Track the tool call name by its ID\n toolCallNames[toolCall.id] = toolCall.function.name;\n\n const actionExecMsg = aguiToolCallToGQLActionExecution(\n toolCall,\n message.id,\n );\n // Preserve render function in actions context\n if (\"generativeUI\" in message && message.generativeUI && actions) {\n const actionName = toolCall.function.name;\n // Check for specific action first, then wild card action\n const specificAction = Object.values(actions).find(\n (action: any) => action.name === actionName,\n );\n const wildcardAction = Object.values(actions).find(\n (action: any) => action.name === \"*\",\n );\n\n // Assign render function to the matching action (specific takes priority)\n if (specificAction) {\n specificAction.render = message.generativeUI;\n } else if (wildcardAction) {\n wildcardAction.render = message.generativeUI;\n }\n }\n gqlMessages.push(actionExecMsg);\n }\n continue;\n }\n // Reasoning messages are ephemeral display-only content with no GQL equivalent — skip them\n if (message.role === \"reasoning\") {\n continue;\n }\n // Regular text messages\n if (\n message.role === \"developer\" ||\n message.role === \"system\" ||\n message.role === \"assistant\" ||\n message.role === \"user\"\n ) {\n gqlMessages.push(aguiTextMessageToGQLMessage(message));\n continue;\n }\n // Tool result message\n if (message.role === \"tool\") {\n gqlMessages.push(\n aguiToolMessageToGQLResultMessage(message, toolCallNames),\n );\n continue;\n }\n throw new Error(\n `Unknown message role: \"${(message as any).role}\" in message with id: ${(message as any).id}`,\n );\n }\n\n return gqlMessages;\n}\n\nexport function aguiTextMessageToGQLMessage(\n message: agui.Message,\n): gql.TextMessage {\n if (\n message.role !== \"developer\" &&\n message.role !== \"system\" &&\n message.role !== \"assistant\" &&\n message.role !== \"user\"\n ) {\n throw new Error(\n `Cannot convert message with role ${message.role} to TextMessage`,\n );\n }\n\n let roleValue: MessageRole;\n\n if (message.role === \"developer\") {\n roleValue = gql.Role.developer;\n } else if (message.role === \"system\") {\n roleValue = gql.Role.system;\n } else if (message.role === \"assistant\") {\n roleValue = gql.Role.assistant;\n } else {\n roleValue = gql.Role.user;\n }\n\n return new gql.TextMessage({\n id: message.id,\n content: normalizeMessageContent(message.content),\n role: roleValue,\n });\n}\n\nexport function aguiToolCallToGQLActionExecution(\n toolCall: agui.ToolCall,\n parentMessageId: string,\n): gql.ActionExecutionMessage {\n if (toolCall.type !== \"function\") {\n throw new Error(`Unsupported tool call type: ${toolCall.type}`);\n }\n\n // Handle arguments - they should be a JSON string in AGUI format,\n // but we need to convert them to an object for GQL format\n let argumentsObj: any;\n\n if (typeof toolCall.function.arguments === \"string\") {\n // Expected case: arguments is a JSON string\n try {\n argumentsObj = JSON.parse(toolCall.function.arguments);\n } catch {\n console.warn(\n `[CopilotKit] Failed to parse tool arguments, falling back to empty object`,\n );\n // Provide fallback empty object to prevent application crash\n argumentsObj = {};\n }\n } else if (\n typeof toolCall.function.arguments === \"object\" &&\n toolCall.function.arguments !== null\n ) {\n // Backward compatibility: arguments is already an object\n argumentsObj = toolCall.function.arguments;\n } else {\n // Fallback for undefined, null, or other types\n console.warn(\n `[CopilotKit] Tool arguments parsed to non-object (${typeof toolCall.function.arguments}), falling back to empty object`,\n );\n argumentsObj = {};\n }\n\n // Guard against successfully parsed non-object values (e.g. JSON.parse('\"\"') → \"\")\n if (\n typeof argumentsObj !== \"object\" ||\n argumentsObj === null ||\n Array.isArray(argumentsObj)\n ) {\n console.warn(\n `[CopilotKit] Tool arguments parsed to non-object (${typeof argumentsObj}), falling back to empty object`,\n );\n argumentsObj = {};\n }\n\n // Always include name and arguments\n return new gql.ActionExecutionMessage({\n id: toolCall.id,\n name: toolCall.function.name,\n arguments: argumentsObj,\n parentMessageId: parentMessageId,\n });\n}\n\nexport function aguiToolMessageToGQLResultMessage(\n message: agui.Message,\n toolCallNames: Record<string, string>,\n): gql.ResultMessage {\n if (message.role !== \"tool\") {\n throw new Error(\n `Cannot convert message with role ${message.role} to ResultMessage`,\n );\n }\n\n if (!message.toolCallId) {\n throw new Error(\"Tool message must have a toolCallId\");\n }\n\n const actionName = toolCallNames[message.toolCallId] || \"unknown\";\n\n // Handle result content - it could be a string or an object that needs serialization\n let resultContent: string;\n const messageContent = message.content || \"\";\n\n if (typeof messageContent === \"string\") {\n // Expected case: content is already a string\n resultContent = messageContent;\n } else if (typeof messageContent === \"object\" && messageContent !== null) {\n // Handle case where content is an object that needs to be serialized\n try {\n resultContent = JSON.stringify(messageContent);\n } catch (error) {\n console.warn(`Failed to stringify tool result for ${actionName}:`, error);\n resultContent = String(messageContent);\n }\n } else {\n // Handle other types (number, boolean, etc.)\n resultContent = String(messageContent);\n }\n\n return new gql.ResultMessage({\n id: message.id,\n result: resultContent,\n actionExecutionId: message.toolCallId,\n actionName: message.toolName || actionName,\n });\n}\n\n// New function to handle AGUI messages with render functions\nexport function aguiMessageWithRenderToGQL(\n message: agui.Message,\n actions?: Record<string, any>,\n coAgentStateRenders?: Record<string, any>,\n): gql.Message[] {\n // Handle the special case: assistant messages with render function but no tool calls\n if (\n message.role === \"assistant\" &&\n \"generativeUI\" in message &&\n message.generativeUI &&\n !message.toolCalls\n ) {\n const gqlMessages: gql.Message[] = [];\n gqlMessages.push(\n new gql.AgentStateMessage({\n id: message.id,\n agentName: \"unknown\",\n state: {},\n role: gql.Role.assistant,\n }),\n );\n if (coAgentStateRenders) {\n coAgentStateRenders.unknown = {\n name: \"unknown\",\n render: message.generativeUI,\n };\n }\n return gqlMessages;\n }\n\n // For all other cases, delegate to aguiToGQL\n return aguiToGQL([message], actions, coAgentStateRenders);\n}\n\nexport function aguiMessageWithImageToGQLMessage(\n message: agui.Message,\n): gql.ImageMessage {\n if (!hasImageProperty(message)) {\n throw new Error(\n `Cannot convert message to ImageMessage: missing format or bytes`,\n );\n }\n\n let roleValue: MessageRole;\n if (message.role === \"assistant\") {\n roleValue = gql.Role.assistant;\n } else {\n roleValue = gql.Role.user;\n }\n\n if (message.role !== \"assistant\" && message.role !== \"user\") {\n throw new Error(\n `Cannot convert message with role ${message.role} to ImageMessage`,\n );\n }\n\n return new gql.ImageMessage({\n id: message.id,\n format: message.image.format,\n bytes: message.image.bytes,\n role: roleValue,\n });\n}\n"],"mappings":"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"}
|
|
@@ -10,8 +10,10 @@ function isAgentStateMessage(message) {
|
|
|
10
10
|
return message.role === "assistant" && "agentName" in message && "state" in message;
|
|
11
11
|
}
|
|
12
12
|
function hasImageProperty(message) {
|
|
13
|
-
if (!(message.role === "assistant" || message.role === "user")
|
|
14
|
-
|
|
13
|
+
if (!(message.role === "assistant" || message.role === "user")) return false;
|
|
14
|
+
const image = "image" in message ? message.image : void 0;
|
|
15
|
+
if (image === void 0) return false;
|
|
16
|
+
if (image.format === void 0 || image.bytes === void 0) return false;
|
|
15
17
|
return true;
|
|
16
18
|
}
|
|
17
19
|
function normalizeMessageContent(content) {
|
|
@@ -99,7 +101,7 @@ function aguiToolCallToGQLActionExecution(toolCall, parentMessageId) {
|
|
|
99
101
|
let argumentsObj;
|
|
100
102
|
if (typeof toolCall.function.arguments === "string") try {
|
|
101
103
|
argumentsObj = JSON.parse(toolCall.function.arguments);
|
|
102
|
-
} catch
|
|
104
|
+
} catch {
|
|
103
105
|
console.warn(`[CopilotKit] Failed to parse tool arguments, falling back to empty object`);
|
|
104
106
|
argumentsObj = {};
|
|
105
107
|
}
|