UNPKG

@copilotkit/runtime

Version:

<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />

862 lines (860 loc) 30.7 kB
import "reflect-metadata"; import { INTELLIGENCE_USER_ID_HEADER } from "../v2/runtime/intelligence-platform/client.mjs"; import { convertAISDKStream } from "./converters/aisdk.mjs"; import { convertInputToTanStackAI, convertTanStackStream } from "./converters/tanstack.mjs"; import { createOpenAI } from "@ai-sdk/openai"; import { randomUUID, safeParseToolArgs, schemaToJsonSchema } from "@copilotkit/shared"; import { Observable } from "rxjs"; import { AbstractAgent, EventType } from "@ag-ui/client"; import { jsonSchema, stepCountIs, streamText, tool } from "ai"; import { createMCPClient } from "@ai-sdk/mcp"; import { createAnthropic } from "@ai-sdk/anthropic"; import { createGoogleGenerativeAI } from "@ai-sdk/google"; import { createVertex } from "@ai-sdk/google-vertex"; import { z } from "zod"; import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"; import { SSEClientTransport } from "@modelcontextprotocol/sdk/client/sse.js"; //#region src/agent/index.ts /** * Resolves a model specifier to a LanguageModel instance * @param spec - Model string (e.g., "openai/gpt-4o") or LanguageModel instance * @param apiKey - Optional API key to use instead of environment variables * @returns LanguageModel instance */ function resolveModel(spec, apiKey) { if (typeof spec !== "string") return spec; const parts = spec.replace("/", ":").trim().split(":"); const rawProvider = parts[0]; const rest = parts.slice(1); if (!rawProvider) throw new Error(`Invalid model string "${spec}". Use "openai/gpt-5", "anthropic/claude-sonnet-4.5", or "google/gemini-2.5-pro".`); const provider = rawProvider.toLowerCase(); const model = rest.join(":").trim(); if (!model) throw new Error(`Invalid model string "${spec}". Use "openai/gpt-5", "anthropic/claude-sonnet-4.5", or "google/gemini-2.5-pro".`); switch (provider) { case "openai": return createOpenAI({ apiKey: apiKey || process.env.OPENAI_API_KEY })(model); case "anthropic": return createAnthropic({ apiKey: apiKey || process.env.ANTHROPIC_API_KEY })(model); case "google": case "gemini": case "google-gemini": return createGoogleGenerativeAI({ apiKey: apiKey || process.env.GOOGLE_API_KEY })(model); case "vertex": return createVertex()(model); default: throw new Error(`Unknown provider "${provider}" in "${spec}". Supported: openai, anthropic, google (gemini).`); } } /** * Define a tool for use with BuiltInAgent * @param name - The name of the tool * @param description - Description of what the tool does * @param parameters - Schema for the tool's input parameters (any Standard Schema V1 compatible library: Zod, Valibot, ArkType, etc.) * @param execute - Function to execute the tool server-side * @returns Tool definition */ function defineTool(config) { return { name: config.name, description: config.description, parameters: config.parameters, execute: config.execute }; } /** * Converts AG-UI user message content to Vercel AI SDK UserContent format. * Handles plain strings, new modality-specific parts (image/audio/video/document), * and legacy BinaryInputContent for backward compatibility. */ function convertUserMessageContent(content) { if (!content) return ""; if (typeof content === "string") return content; const parts = []; for (const part of content) { if (!part || typeof part !== "object" || !("type" in part)) continue; switch (part.type) { case "text": { const text = part.text; if (text) parts.push({ type: "text", text }); break; } case "image": { const source = part.source; if (!source) break; if (source.type === "data") parts.push({ type: "image", image: source.value, mediaType: source.mimeType }); else if (source.type === "url") try { parts.push({ type: "image", image: new URL(source.value), mediaType: source.mimeType }); } catch { console.error(`[CopilotKit] convertUserMessageContent: invalid URL "${source.value}" in image part — skipping`); } break; } case "audio": case "video": case "document": { const source = part.source; if (!source) break; if (source.type === "data") parts.push({ type: "file", data: source.value, mediaType: source.mimeType }); else if (source.type === "url") try { parts.push({ type: "file", data: new URL(source.value), mediaType: source.mimeType ?? "application/octet-stream" }); } catch { console.error(`[CopilotKit] convertUserMessageContent: invalid URL "${source.value}" in ${part.type} part — skipping`); } break; } case "binary": { const legacy = part; const mimeType = legacy.mimeType ?? "application/octet-stream"; const isImage = mimeType.startsWith("image/"); if (legacy.data) if (isImage) parts.push({ type: "image", image: legacy.data, mediaType: mimeType }); else parts.push({ type: "file", data: legacy.data, mediaType: mimeType }); else if (legacy.url) try { const url = new URL(legacy.url); if (isImage) parts.push({ type: "image", image: url, mediaType: mimeType }); else parts.push({ type: "file", data: url, mediaType: mimeType }); } catch { console.error(`[CopilotKit] convertUserMessageContent: invalid URL "${legacy.url}" in binary part — skipping`); } break; } default: console.error(`[CopilotKit] convertUserMessageContent: unrecognized content part type "${part.type}" — skipping`); break; } } return parts.length > 0 ? parts : ""; } /** * Converts AG-UI messages to Vercel AI SDK ModelMessage format */ function convertMessagesToVercelAISDKMessages(messages, options = {}) { const result = []; for (const message of messages) if (message.role === "system" && options.forwardSystemMessages) { const systemMsg = { role: "system", content: message.content ?? "" }; result.push(systemMsg); } else if (message.role === "developer" && options.forwardDeveloperMessages) { const systemMsg = { role: "system", content: message.content ?? "" }; result.push(systemMsg); } else if (message.role === "assistant") { const parts = message.content ? [{ type: "text", text: message.content }] : []; for (const toolCall of message.toolCalls ?? []) { const toolCallPart = { type: "tool-call", toolCallId: toolCall.id, toolName: toolCall.function.name, input: safeParseToolArgs(toolCall.function.arguments) }; parts.push(toolCallPart); } const assistantMsg = { role: "assistant", content: parts }; result.push(assistantMsg); } else if (message.role === "user") { const userMsg = { role: "user", content: convertUserMessageContent(message.content) }; result.push(userMsg); } else if (message.role === "tool") { let toolName = "unknown"; for (const msg of messages) if (msg.role === "assistant") { for (const toolCall of msg.toolCalls ?? []) if (toolCall.id === message.toolCallId) { toolName = toolCall.function.name; break; } } const toolMsg = { role: "tool", content: [{ type: "tool-result", toolCallId: message.toolCallId, toolName, output: { type: "text", value: message.content } }] }; result.push(toolMsg); } return result; } /** * Converts JSON Schema to Zod schema */ function convertJsonSchemaToZodSchema$1(jsonSchema, required) { if (!jsonSchema.type) return required ? z.object({}) : z.object({}).optional(); if (jsonSchema.type === "object") { const spec = {}; if (!jsonSchema.properties || !Object.keys(jsonSchema.properties).length) return !required ? z.object(spec).optional() : z.object(spec); for (const [key, value] of Object.entries(jsonSchema.properties)) spec[key] = convertJsonSchemaToZodSchema$1(value, jsonSchema.required ? jsonSchema.required.includes(key) : false); const schema = z.object(spec).describe(jsonSchema.description ?? ""); return required ? schema : schema.optional(); } else if (jsonSchema.type === "string") { if (jsonSchema.enum && jsonSchema.enum.length > 0) { const schema = z.enum(jsonSchema.enum).describe(jsonSchema.description ?? ""); return required ? schema : schema.optional(); } const schema = z.string().describe(jsonSchema.description ?? ""); return required ? schema : schema.optional(); } else if (jsonSchema.type === "number" || jsonSchema.type === "integer") { const schema = z.number().describe(jsonSchema.description ?? ""); return required ? schema : schema.optional(); } else if (jsonSchema.type === "boolean") { const schema = z.boolean().describe(jsonSchema.description ?? ""); return required ? schema : schema.optional(); } else if (jsonSchema.type === "array") { if (!jsonSchema.items) throw new Error("Array type must have items property"); const itemSchema = convertJsonSchemaToZodSchema$1(jsonSchema.items, true); const schema = z.array(itemSchema).describe(jsonSchema.description ?? ""); return required ? schema : schema.optional(); } console.error("Invalid JSON schema:", JSON.stringify(jsonSchema, null, 2)); throw new Error("Invalid JSON schema"); } /** * Converts AG-UI tools to Vercel AI SDK ToolSet */ function isJsonSchema(obj) { if (typeof obj !== "object" || obj === null) return false; const schema = obj; if (Object.keys(schema).length === 0) return true; return typeof schema.type === "string" && [ "object", "string", "number", "integer", "boolean", "array" ].includes(schema.type); } function convertToolsToVercelAITools(tools) { const result = {}; for (const tool$1 of tools) { if (!isJsonSchema(tool$1.parameters)) throw new Error(`Invalid JSON schema for tool ${tool$1.name}`); const zodSchema = convertJsonSchemaToZodSchema$1(tool$1.parameters, true); result[tool$1.name] = tool({ description: tool$1.description, inputSchema: zodSchema }); } return result; } /** * Check whether a schema is a Zod schema by inspecting its Standard Schema vendor. */ function isZodSchema(schema) { return schema["~standard"]?.vendor === "zod"; } /** * Converts ToolDefinition array to Vercel AI SDK ToolSet. * * For Zod schemas, passes them directly to the AI SDK (Zod satisfies FlexibleSchema). * For non-Zod schemas, converts to JSON Schema via schemaToJsonSchema() and wraps * with the AI SDK's jsonSchema() helper. */ function convertToolDefinitionsToVercelAITools(tools) { const result = {}; for (const tool$2 of tools) if (isZodSchema(tool$2.parameters)) result[tool$2.name] = tool({ description: tool$2.description, inputSchema: tool$2.parameters, execute: tool$2.execute }); else { const jsonSchemaObj = schemaToJsonSchema(tool$2.parameters); result[tool$2.name] = tool({ description: tool$2.description, inputSchema: jsonSchema(jsonSchemaObj), execute: tool$2.execute }); } return result; } /** * Type guard: returns true if this is a factory-mode config. */ function isFactoryConfig(config) { return "factory" in config; } var BuiltInAgent = class BuiltInAgent extends AbstractAgent { constructor(config) { super(); this.config = config; } /** * Check if a property can be overridden by forwardedProps */ canOverride(property) { if (isFactoryConfig(this.config)) return false; return this.config?.overridableProperties?.includes(property) ?? false; } async getCapabilities() { const inferred = { tools: { supported: true, clientProvided: true }, transport: { streaming: true } }; if (!this.config.capabilities) return inferred; return { ...inferred, ...this.config.capabilities }; } run(input) { if (isFactoryConfig(this.config)) return this.runFactory(input, this.config); if (this.abortController) throw new Error("Agent is already running. Call abortRun() first or create a new instance."); this.abortController = new AbortController(); const abortController = this.abortController; return new Observable((subscriber) => { const startEvent = { type: EventType.RUN_STARTED, threadId: input.threadId, runId: input.runId }; subscriber.next(startEvent); const model = resolveModel(this.config.model, this.config.apiKey); let systemPrompt = void 0; const hasPrompt = !!this.config.prompt; const hasContext = input.context && input.context.length > 0; const hasState = input.state !== void 0 && input.state !== null && !(typeof input.state === "object" && Object.keys(input.state).length === 0); if (hasPrompt || hasContext || hasState) { const parts = []; if (hasPrompt) parts.push(this.config.prompt); if (hasContext) { parts.push("\n## Context from the application\n"); for (const ctx of input.context) parts.push(`${ctx.description}:\n${ctx.value}\n`); } if (hasState) parts.push(` ## Application State This is state from the application that you can edit by calling AGUISendStateSnapshot or AGUISendStateDelta. \`\`\`json\n${JSON.stringify(input.state, null, 2)}\n\`\`\`\n`); systemPrompt = parts.join(""); } const messages = convertMessagesToVercelAISDKMessages(input.messages, { forwardSystemMessages: this.config.forwardSystemMessages, forwardDeveloperMessages: this.config.forwardDeveloperMessages }); if (systemPrompt) messages.unshift({ role: "system", content: systemPrompt }); let allTools = convertToolsToVercelAITools(input.tools); if (this.config.tools && this.config.tools.length > 0) { const configTools = convertToolDefinitionsToVercelAITools(this.config.tools); allTools = { ...allTools, ...configTools }; } const streamTextParams = { model, messages, tools: allTools, toolChoice: this.config.toolChoice, stopWhen: this.config.maxSteps ? stepCountIs(this.config.maxSteps) : void 0, maxOutputTokens: this.config.maxOutputTokens, temperature: this.config.temperature, topP: this.config.topP, topK: this.config.topK, presencePenalty: this.config.presencePenalty, frequencyPenalty: this.config.frequencyPenalty, stopSequences: this.config.stopSequences, seed: this.config.seed, providerOptions: this.config.providerOptions, maxRetries: this.config.maxRetries }; if (input.forwardedProps && typeof input.forwardedProps === "object") { const props = input.forwardedProps; if (props.model !== void 0 && this.canOverride("model")) { if (typeof props.model === "string" || typeof props.model === "object") streamTextParams.model = resolveModel(props.model, this.config.apiKey); } if (props.toolChoice !== void 0 && this.canOverride("toolChoice")) { const toolChoice = props.toolChoice; if (toolChoice === "auto" || toolChoice === "required" || toolChoice === "none" || typeof toolChoice === "object" && toolChoice !== null && "type" in toolChoice && toolChoice.type === "tool") streamTextParams.toolChoice = toolChoice; } if (typeof props.maxOutputTokens === "number" && this.canOverride("maxOutputTokens")) streamTextParams.maxOutputTokens = props.maxOutputTokens; if (typeof props.temperature === "number" && this.canOverride("temperature")) streamTextParams.temperature = props.temperature; if (typeof props.topP === "number" && this.canOverride("topP")) streamTextParams.topP = props.topP; if (typeof props.topK === "number" && this.canOverride("topK")) streamTextParams.topK = props.topK; if (typeof props.presencePenalty === "number" && this.canOverride("presencePenalty")) streamTextParams.presencePenalty = props.presencePenalty; if (typeof props.frequencyPenalty === "number" && this.canOverride("frequencyPenalty")) streamTextParams.frequencyPenalty = props.frequencyPenalty; if (Array.isArray(props.stopSequences) && this.canOverride("stopSequences")) { if (props.stopSequences.every((item) => typeof item === "string")) streamTextParams.stopSequences = props.stopSequences; } if (typeof props.seed === "number" && this.canOverride("seed")) streamTextParams.seed = props.seed; if (typeof props.maxRetries === "number" && this.canOverride("maxRetries")) streamTextParams.maxRetries = props.maxRetries; if (props.providerOptions !== void 0 && this.canOverride("providerOptions")) { if (typeof props.providerOptions === "object" && props.providerOptions !== null) streamTextParams.providerOptions = props.providerOptions; } } const mcpClients = []; (async () => { let terminalEventEmitted = false; let messageId = randomUUID(); let reasoningMessageId = randomUUID(); let isInReasoning = false; const closeReasoningIfOpen = () => { if (!isInReasoning) return; isInReasoning = false; const reasoningMsgEnd = { type: EventType.REASONING_MESSAGE_END, messageId: reasoningMessageId }; subscriber.next(reasoningMsgEnd); const reasoningEnd = { type: EventType.REASONING_END, messageId: reasoningMessageId }; subscriber.next(reasoningEnd); }; try { streamTextParams.tools = { ...streamTextParams.tools, AGUISendStateSnapshot: tool({ description: "Replace the entire application state with a new snapshot", inputSchema: z.object({ snapshot: z.any().describe("The complete new state object") }), execute: async ({ snapshot }) => { return { success: true, snapshot }; } }), AGUISendStateDelta: tool({ description: "Apply incremental updates to application state using JSON Patch operations", inputSchema: z.object({ delta: z.array(z.object({ op: z.enum([ "add", "replace", "remove" ]).describe("The operation to perform"), path: z.string().describe("JSON Pointer path (e.g., '/foo/bar')"), value: z.any().optional().describe("The value to set. Required for 'add' and 'replace' operations, ignored for 'remove'.") })).describe("Array of JSON Patch operations") }), execute: async ({ delta }) => { return { success: true, delta }; } }) }; if (this.config.mcpClients && this.config.mcpClients.length > 0) for (const client of this.config.mcpClients) { const mcpTools = await client.tools(); streamTextParams.tools = { ...streamTextParams.tools, ...mcpTools }; } const allMcpServers = [...this.config.mcpServers ?? []]; const cpki = (input.forwardedProps?.auth)?.copilotkitIntelligence; const cpkiUserId = typeof cpki?.userId === "string" ? cpki.userId : void 0; const cpkiApiKey = typeof cpki?.apiKey === "string" ? cpki.apiKey : void 0; const cpkiMcpUrl = typeof cpki?.mcpUrl === "string" ? cpki.mcpUrl : void 0; if (cpkiUserId && cpkiApiKey && cpkiMcpUrl && !allMcpServers.some((s) => s.type === "http" && s.url === cpkiMcpUrl)) allMcpServers.push({ type: "http", url: cpkiMcpUrl, options: { fetch: async (req, init) => { const headers = new Headers(init?.headers); headers.set("Authorization", `Bearer ${cpkiApiKey}`); headers.set(INTELLIGENCE_USER_ID_HEADER, cpkiUserId); return globalThis.fetch(req, { ...init, headers }); } } }); if (allMcpServers.length > 0) for (const serverConfig of allMcpServers) { let transport; if (serverConfig.type === "http") transport = new StreamableHTTPClientTransport(new URL(serverConfig.url), serverConfig.options); else if (serverConfig.type === "sse") transport = new SSEClientTransport(new URL(serverConfig.url), serverConfig.headers); if (transport) { const mcpClient = await createMCPClient({ transport }); mcpClients.push(mcpClient); const mcpTools = await mcpClient.tools(); streamTextParams.tools = { ...streamTextParams.tools, ...mcpTools }; } } const response = streamText({ ...streamTextParams, abortSignal: abortController.signal }); const toolCallStates = /* @__PURE__ */ new Map(); const ensureToolCallState = (toolCallId) => { let state = toolCallStates.get(toolCallId); if (!state) { state = { started: false, hasArgsDelta: false, ended: false }; toolCallStates.set(toolCallId, state); } return state; }; for await (const part of response.fullStream) { if (part.type !== "reasoning-delta") closeReasoningIfOpen(); switch (part.type) { case "abort": { const abortEndEvent = { type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId }; subscriber.next(abortEndEvent); terminalEventEmitted = true; subscriber.complete(); break; } case "reasoning-start": { const providedId = "id" in part ? part.id : void 0; reasoningMessageId = !providedId || providedId === "0" || /^(txt|reasoning|msg)-0$/.test(providedId) ? randomUUID() : providedId; const reasoningStartEvent = { type: EventType.REASONING_START, messageId: reasoningMessageId }; subscriber.next(reasoningStartEvent); const reasoningMessageStart = { type: EventType.REASONING_MESSAGE_START, messageId: reasoningMessageId, role: "reasoning" }; subscriber.next(reasoningMessageStart); isInReasoning = true; break; } case "reasoning-delta": { const delta = part.text ?? ""; if (!delta) break; const reasoningDeltaEvent = { type: EventType.REASONING_MESSAGE_CONTENT, messageId: reasoningMessageId, delta }; subscriber.next(reasoningDeltaEvent); break; } case "reasoning-end": break; case "tool-input-start": { const toolCallId = part.id; const state = ensureToolCallState(toolCallId); state.toolName = part.toolName; if (!state.started) { state.started = true; const startEvent = { type: EventType.TOOL_CALL_START, parentMessageId: messageId, toolCallId, toolCallName: part.toolName }; subscriber.next(startEvent); } break; } case "tool-input-delta": { const toolCallId = part.id; const state = ensureToolCallState(toolCallId); state.hasArgsDelta = true; const argsEvent = { type: EventType.TOOL_CALL_ARGS, toolCallId, delta: part.delta }; subscriber.next(argsEvent); break; } case "tool-input-end": break; case "text-start": { const providedId = "id" in part ? part.id : void 0; messageId = !providedId || providedId === "0" || /^(txt|reasoning|msg)-0$/.test(providedId) ? randomUUID() : providedId; break; } case "text-delta": { const textDelta = "text" in part ? part.text : ""; const textEvent = { type: EventType.TEXT_MESSAGE_CHUNK, role: "assistant", messageId, delta: textDelta }; subscriber.next(textEvent); break; } case "tool-call": { const toolCallId = part.toolCallId; const state = ensureToolCallState(toolCallId); state.toolName = part.toolName ?? state.toolName; if (!state.started) { state.started = true; const startEvent = { type: EventType.TOOL_CALL_START, parentMessageId: messageId, toolCallId, toolCallName: part.toolName }; subscriber.next(startEvent); } if (!state.hasArgsDelta && "input" in part && part.input !== void 0) { let serializedInput = ""; if (typeof part.input === "string") serializedInput = part.input; else try { serializedInput = JSON.stringify(part.input); } catch { serializedInput = String(part.input); } if (serializedInput.length > 0) { const argsEvent = { type: EventType.TOOL_CALL_ARGS, toolCallId, delta: serializedInput }; subscriber.next(argsEvent); state.hasArgsDelta = true; } } if (!state.ended) { state.ended = true; const endEvent = { type: EventType.TOOL_CALL_END, toolCallId }; subscriber.next(endEvent); } break; } case "tool-result": { const toolResult = "output" in part ? part.output : "result" in part ? part.result : null; const toolName = "toolName" in part ? part.toolName : ""; toolCallStates.delete(part.toolCallId); if (toolName === "AGUISendStateSnapshot" && toolResult && typeof toolResult === "object") { const snapshot = toolResult.snapshot; if (snapshot !== void 0) { const stateSnapshotEvent = { type: EventType.STATE_SNAPSHOT, snapshot }; subscriber.next(stateSnapshotEvent); } } else if (toolName === "AGUISendStateDelta" && toolResult && typeof toolResult === "object") { const delta = toolResult.delta; if (delta !== void 0) { const stateDeltaEvent = { type: EventType.STATE_DELTA, delta }; subscriber.next(stateDeltaEvent); } } let serializedResult; try { serializedResult = JSON.stringify(toolResult); } catch { serializedResult = `[Unserializable tool result from ${toolName || part.toolCallId}]`; } const resultEvent = { type: EventType.TOOL_CALL_RESULT, role: "tool", messageId: randomUUID(), toolCallId: part.toolCallId, content: serializedResult }; subscriber.next(resultEvent); break; } case "finish": { const finishedEvent = { type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId }; subscriber.next(finishedEvent); terminalEventEmitted = true; subscriber.complete(); break; } case "error": { if (abortController.signal.aborted) break; const err = part.error ?? part.message ?? part.cause; const runErrorEvent = { type: EventType.RUN_ERROR, message: err instanceof Error ? err.message : typeof err === "string" ? err : `AI SDK stream error: ${JSON.stringify(part)}`, threadId: input.threadId, runId: input.runId }; subscriber.next(runErrorEvent); terminalEventEmitted = true; if (err instanceof Error) subscriber.error(err); else subscriber.error(new Error(typeof err === "string" ? err : `AI SDK stream error`)); break; } } } if (!terminalEventEmitted) { closeReasoningIfOpen(); if (abortController.signal.aborted) {} else { const finishedEvent = { type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId }; subscriber.next(finishedEvent); } terminalEventEmitted = true; subscriber.complete(); } } catch (error) { closeReasoningIfOpen(); if (abortController.signal.aborted) subscriber.complete(); else { const runErrorEvent = { type: EventType.RUN_ERROR, message: error instanceof Error ? error.message : String(error), threadId: input.threadId, runId: input.runId }; subscriber.next(runErrorEvent); terminalEventEmitted = true; subscriber.error(error); } } finally { this.abortController = void 0; await Promise.all(mcpClients.map((client) => client.close())); } })(); return () => { Promise.all(mcpClients.map((client) => client.close())).catch(() => {}); }; }); } runFactory(input, config) { if (this.abortController) throw new Error("Agent is already running. Call abortRun() first or create a new instance."); this.abortController = new AbortController(); const controller = this.abortController; return new Observable((subscriber) => { const startEvent = { type: EventType.RUN_STARTED, threadId: input.threadId, runId: input.runId }; subscriber.next(startEvent); const ctx = { input, abortController: controller, abortSignal: controller.signal }; (async () => { try { let events; switch (config.type) { case "aisdk": events = convertAISDKStream((await config.factory(ctx)).fullStream, controller.signal); break; case "tanstack": events = convertTanStackStream(await config.factory(ctx), controller.signal); break; case "custom": events = await config.factory(ctx); break; default: { const _exhaustive = config; throw new Error(`Unknown agent config type: ${_exhaustive.type}`); } } for await (const event of events) subscriber.next(event); if (!controller.signal.aborted) { const finishedEvent = { type: EventType.RUN_FINISHED, threadId: input.threadId, runId: input.runId }; subscriber.next(finishedEvent); } subscriber.complete(); } catch (error) { if (controller.signal.aborted) subscriber.complete(); else { const runErrorEvent = { type: EventType.RUN_ERROR, message: error instanceof Error ? error.message : String(error), threadId: input.threadId, runId: input.runId }; subscriber.next(runErrorEvent); subscriber.error(error); } } finally { this.abortController = void 0; } })(); return () => { controller.abort(); }; }); } clone() { const cloned = new BuiltInAgent(this.config); cloned.middlewares = [...this.middlewares]; return cloned; } abortRun() { this.abortController?.abort(); } }; /** * @deprecated Use BuiltInAgent instead */ var BasicAgent = class extends BuiltInAgent { constructor(config) { super(config); console.warn("BasicAgent is deprecated, use BuiltInAgent instead"); } }; //#endregion export { BasicAgent, BuiltInAgent, convertJsonSchemaToZodSchema$1 as convertJsonSchemaToZodSchema, convertMessagesToVercelAISDKMessages, convertToolDefinitionsToVercelAITools, convertToolsToVercelAITools, defineTool, resolveModel }; //# sourceMappingURL=index.mjs.map