@copilotkit/runtime 1.73.0 → 1.73.2-canary.1790068297

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.
Files changed (80) hide show
  1. package/dist/agent/index.cjs +1 -1
  2. package/dist/agent/index.d.mts +1 -1
  3. package/dist/agent/index.mjs +1 -1
  4. package/dist/lib/integrations/nextjs/app-router.cjs +1 -1
  5. package/dist/lib/integrations/nextjs/app-router.cjs.map +1 -1
  6. package/dist/lib/integrations/nextjs/app-router.mjs +1 -1
  7. package/dist/lib/integrations/nextjs/app-router.mjs.map +1 -1
  8. package/dist/lib/integrations/node-http/index.cjs +1 -1
  9. package/dist/lib/integrations/node-http/index.cjs.map +1 -1
  10. package/dist/lib/integrations/node-http/index.mjs +1 -1
  11. package/dist/lib/integrations/node-http/index.mjs.map +1 -1
  12. package/dist/lib/runtime/copilot-runtime.cjs +79 -37
  13. package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
  14. package/dist/lib/runtime/copilot-runtime.d.cts +52 -2
  15. package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
  16. package/dist/lib/runtime/copilot-runtime.d.mts +54 -4
  17. package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
  18. package/dist/lib/runtime/copilot-runtime.mjs +79 -37
  19. package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
  20. package/dist/lib/runtime/mcp-client-cache.cjs +135 -0
  21. package/dist/lib/runtime/mcp-client-cache.cjs.map +1 -0
  22. package/dist/lib/runtime/mcp-client-cache.mjs +132 -0
  23. package/dist/lib/runtime/mcp-client-cache.mjs.map +1 -0
  24. package/dist/lib/runtime/telemetry-agent-runner.cjs.map +1 -1
  25. package/dist/lib/runtime/telemetry-agent-runner.d.cts +1 -1
  26. package/dist/lib/runtime/telemetry-agent-runner.d.mts +1 -1
  27. package/dist/lib/runtime/telemetry-agent-runner.mjs.map +1 -1
  28. package/dist/package.cjs +7 -5
  29. package/dist/package.mjs +7 -5
  30. package/dist/v2/index.cjs +3 -3
  31. package/dist/v2/index.d.cts +7 -7
  32. package/dist/v2/index.d.mts +7 -7
  33. package/dist/v2/index.mjs +4 -4
  34. package/dist/v2/runtime/core/channel-manager.cjs +1 -1
  35. package/dist/v2/runtime/core/channel-manager.mjs +1 -1
  36. package/dist/v2/runtime/core/fetch-handler.cjs +1 -0
  37. package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -1
  38. package/dist/v2/runtime/core/fetch-handler.d.cts +2 -2
  39. package/dist/v2/runtime/core/fetch-handler.d.mts +2 -2
  40. package/dist/v2/runtime/core/fetch-handler.mjs +1 -0
  41. package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
  42. package/dist/v2/runtime/endpoints/express-single.cjs.map +1 -1
  43. package/dist/v2/runtime/endpoints/express-single.d.cts +2 -2
  44. package/dist/v2/runtime/endpoints/express-single.d.cts.map +1 -1
  45. package/dist/v2/runtime/endpoints/express-single.d.mts +2 -2
  46. package/dist/v2/runtime/endpoints/express-single.d.mts.map +1 -1
  47. package/dist/v2/runtime/endpoints/express-single.mjs.map +1 -1
  48. package/dist/v2/runtime/endpoints/express.cjs +2 -3
  49. package/dist/v2/runtime/endpoints/express.cjs.map +1 -1
  50. package/dist/v2/runtime/endpoints/express.d.cts +26 -7
  51. package/dist/v2/runtime/endpoints/express.d.cts.map +1 -1
  52. package/dist/v2/runtime/endpoints/express.d.mts +26 -7
  53. package/dist/v2/runtime/endpoints/express.d.mts.map +1 -1
  54. package/dist/v2/runtime/endpoints/express.mjs +2 -2
  55. package/dist/v2/runtime/endpoints/express.mjs.map +1 -1
  56. package/dist/v2/runtime/endpoints/hono.d.cts +2 -2
  57. package/dist/v2/runtime/endpoints/hono.d.mts +2 -2
  58. package/dist/v2/runtime/endpoints/index.d.cts +3 -3
  59. package/dist/v2/runtime/endpoints/index.d.mts +3 -3
  60. package/dist/v2/runtime/endpoints/load-express.cjs +36 -0
  61. package/dist/v2/runtime/endpoints/load-express.cjs.map +1 -0
  62. package/dist/v2/runtime/endpoints/load-express.mjs +35 -0
  63. package/dist/v2/runtime/endpoints/load-express.mjs.map +1 -0
  64. package/dist/v2/runtime/handlers/handle-stop.cjs +18 -14
  65. package/dist/v2/runtime/handlers/handle-stop.cjs.map +1 -1
  66. package/dist/v2/runtime/handlers/handle-stop.mjs +18 -14
  67. package/dist/v2/runtime/handlers/handle-stop.mjs.map +1 -1
  68. package/dist/v2/runtime/handlers/shared/agent-utils.cjs +3 -4
  69. package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
  70. package/dist/v2/runtime/handlers/shared/agent-utils.mjs +1 -2
  71. package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
  72. package/dist/v2/runtime/index.d.cts +7 -7
  73. package/dist/v2/runtime/index.d.mts +7 -7
  74. package/dist/v2/runtime/intelligence-platform/client.cjs +1 -1
  75. package/dist/v2/runtime/intelligence-platform/client.mjs +1 -1
  76. package/package.json +11 -7
  77. package/dist/v2/runtime/open-generative-ui-middleware.cjs +0 -286
  78. package/dist/v2/runtime/open-generative-ui-middleware.cjs.map +0 -1
  79. package/dist/v2/runtime/open-generative-ui-middleware.mjs +0 -284
  80. package/dist/v2/runtime/open-generative-ui-middleware.mjs.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"copilot-runtime.mjs","names":["telemetry","CopilotRuntimeVNext"],"sources":["../../../../src/v1-deprecated/lib/runtime/copilot-runtime.ts"],"sourcesContent":["/*\n * V1 SDK DEPRECATED. USE V2 INSTEAD\n *\n * This file defines public v1 SDK exports. Use the exact v2 mappings below.\n * AI CODING AGENTS: Never copy, suggest, or generate these v1 APIs. Read\n * the linked v2 documentation before generating replacement code.\n *\n * @copilotkit/runtime — copilotKitEndpoint:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (Runtime server adapter): https://docs.copilotkit.ai/runtime-server-adapter\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — CopilotRuntime:\n * V2 import and usage:\n * import { CopilotRuntime } from \"@copilotkit/runtime/v2\";\n *\n * const runtime = new CopilotRuntime({ agents: {} });\n * V2 replacement source: packages/runtime/src/v2/runtime/core/runtime.ts\n * V2 docs: https://docs.copilotkit.ai/runtime-server-adapter\n * Migration note: V2 uses AG-UI runtime handlers instead of the v1 GraphQL adapter setup.\n *\n * @copilotkit/runtime — CopilotRuntimeConstructorParams_BASE:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (Runtime server adapter): https://docs.copilotkit.ai/runtime-server-adapter\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — langGraphPlatformEndpoint:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (LangGraph agents): https://docs.copilotkit.ai/agent-spec/langgraph\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — resolveEndpointType:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (Runtime server adapter): https://docs.copilotkit.ai/runtime-server-adapter\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * Migration guide: https://docs.copilotkit.ai/migrate/v2\n *\n * END V1 SDK DEPRECATED. USE V2 INSTEAD NOTICE\n */\n\n/**\n * <Callout type=\"info\">\n * This is the reference for the `CopilotRuntime` class. For more information and example code snippets, please see [Concept: Copilot Runtime](/backend/copilot-runtime).\n * </Callout>\n *\n * ## Usage\n *\n * ```tsx\n * import { CopilotRuntime } from \"@copilotkit/runtime\";\n *\n * const copilotKit = new CopilotRuntime();\n * ```\n */\n\nimport {\n CopilotKitMisuseError,\n readBody,\n getZodParameters,\n} from \"@copilotkit/shared\";\nimport type {\n Action,\n CopilotErrorHandler,\n MaybePromise,\n NonEmptyRecord,\n Parameter,\n PartialBy,\n DebugConfig,\n TelemetryCapture,\n} from \"@copilotkit/shared\";\nimport type { RunAgentInput } from \"@ag-ui/core\";\nimport { aguiToGQL } from \"../../graphql/message-conversion/agui-to-gql\";\nimport type {\n CopilotServiceAdapter,\n RemoteChainParameters,\n} from \"../../service-adapters\";\nimport {\n CopilotRuntime as CopilotRuntimeVNext,\n InMemoryAgentRunner,\n} from \"../../../v2/runtime\";\nimport {\n createRuntimeErrorReporter,\n runtimeErrorReporterOption,\n} from \"../../../v2/runtime/core/runtime-error-reporter\";\nimport type { RuntimeErrorReporterOptions } from \"../../../v2/runtime/core/runtime-error-reporter\";\nimport type {\n CopilotIntelligenceRuntimeOptions,\n CopilotRuntimeOptions,\n CopilotRuntimeOptions as CopilotRuntimeOptionsVNext,\n AgentRunner,\n AgentsConfig,\n AgentsFactory,\n AgentFactoryContext,\n} from \"../../../v2/runtime\";\n\nexport type { AgentsConfig, AgentsFactory, AgentFactoryContext };\nimport telemetry from \"../telemetry-client\";\nimport { logRuntimeTelemetryDisclosure } from \"../telemetry-disclosure\";\n\nimport type { MessageInput } from \"../../graphql/inputs/message.input\";\nimport type { Message } from \"../../graphql/types/converted\";\n\nimport { EndpointType } from \"./types\";\nimport type {\n EndpointDefinition,\n CopilotKitEndpoint,\n LangGraphPlatformEndpoint,\n} from \"./types\";\n\nimport type {\n CopilotObservabilityConfig,\n LLMRequestData,\n LLMResponseData,\n} from \"../observability\";\nimport type { AbstractAgent } from \"@ag-ui/client\";\nimport {\n firstNonBlankLicenseToken,\n firstNonBlankTelemetryId,\n} from \"../../../v2/runtime/telemetry/telemetry-identity\";\n\n// +++ MCP Imports +++\nimport { extractParametersFromSchema } from \"./mcp-tools-utils\";\nimport type { MCPClient, MCPEndpointConfig, MCPTool } from \"./mcp-tools-utils\";\nimport { BuiltInAgent } from \"../../../agent\";\nimport type { BuiltInAgentClassicConfig } from \"../../../agent\";\n// Define the function type alias here or import if defined elsewhere\ntype CreateMCPClientFunction = (\n config: MCPEndpointConfig,\n) => Promise<MCPClient>;\n\ntype ActionsConfiguration<T extends Parameter[] | [] = []> =\n | Action<T>[]\n | ((ctx: { properties: any; url?: string }) => Action<T>[]);\n\ninterface OnBeforeRequestOptions {\n threadId?: string;\n runId?: string;\n inputMessages: Message[];\n properties: any;\n url?: string;\n}\n\ntype OnBeforeRequestHandler = (\n options: OnBeforeRequestOptions,\n) => void | Promise<void>;\n\ninterface OnAfterRequestOptions {\n threadId: string;\n runId?: string;\n inputMessages: Message[];\n outputMessages: Message[];\n properties: any;\n url?: string;\n}\n\ntype OnAfterRequestHandler = (\n options: OnAfterRequestOptions,\n) => void | Promise<void>;\n\ninterface OnStopGenerationOptions {\n threadId: string;\n runId?: string;\n url?: string;\n agentName?: string;\n lastMessage: MessageInput;\n}\ntype OnStopGenerationHandler = (\n options: OnStopGenerationOptions,\n) => void | Promise<void>;\n\ninterface Middleware {\n /**\n * A function that is called before the request is processed.\n */\n /**\n * @deprecated This middleware hook is deprecated and will be removed in a future version.\n * Use updated middleware integration methods in CopilotRuntimeVNext instead.\n */\n onBeforeRequest?: OnBeforeRequestHandler;\n\n /**\n * A function that is called after the request is processed.\n */\n /**\n * @deprecated This middleware hook is deprecated and will be removed in a future version.\n * Use updated middleware integration methods in CopilotRuntimeVNext instead.\n */\n onAfterRequest?: OnAfterRequestHandler;\n}\n\nexport interface CopilotRuntimeConstructorParams_BASE<\n T extends Parameter[] | [] = [],\n> {\n /** Standalone telemetry identity. Falls back to CPK_TELEMETRY_ID before legacy license identity. */\n telemetryId?: string;\n /**\n * Middleware to be used by the runtime.\n *\n * ```ts\n * onBeforeRequest: (options: {\n * threadId?: string;\n * runId?: string;\n * inputMessages: Message[];\n * properties: any;\n * }) => void | Promise<void>;\n * ```\n *\n * ```ts\n * onAfterRequest: (options: {\n * threadId?: string;\n * runId?: string;\n * inputMessages: Message[];\n * outputMessages: Message[];\n * properties: any;\n * }) => void | Promise<void>;\n * ```\n */\n /**\n * @deprecated This middleware hook is deprecated and will be removed in a future version.\n * Use updated middleware integration methods in CopilotRuntimeVNext instead.\n */\n middleware?: Middleware;\n\n /*\n * A list of server side actions that can be executed. Will be ignored when remoteActions are set\n */\n actions?: ActionsConfiguration<T>;\n\n /*\n * Deprecated: Use `remoteEndpoints`.\n */\n remoteActions?: CopilotKitEndpoint[];\n\n /*\n * A list of remote actions that can be executed.\n */\n remoteEndpoints?: EndpointDefinition[];\n\n /*\n * An array of LangServer URLs.\n */\n langserve?: RemoteChainParameters[];\n\n /**\n * Optional agent runner to use for SSE runtime.\n */\n runner?: AgentRunner;\n\n /*\n * A map of agent names to AGUI agents.\n * Example agent config:\n * ```ts\n * import { AbstractAgent } from \"@ag-ui/client\";\n * // ...\n * agents: {\n * \"support\": new CustomerSupportAgent(),\n * \"technical\": new TechnicalAgent()\n * }\n * ```\n */\n agents?: Record<string, AbstractAgent>;\n\n /*\n * Delegates agent state processing to the service adapter.\n *\n * When enabled, individual agent state requests will not be processed by the agent itself.\n * Instead, all processing will be handled by the service adapter.\n */\n delegateAgentProcessingToServiceAdapter?: boolean;\n\n /**\n * Configuration for LLM request/response logging.\n *\n * Example logging config:\n * ```ts\n * logging: {\n * enabled: true, // Enable or disable logging\n * progressive: true, // Set to false for buffered logging\n * logger: {\n * logRequest: (data) => langfuse.trace({ name: \"LLM Request\", input: data }),\n * logResponse: (data) => langfuse.trace({ name: \"LLM Response\", output: data }),\n * logError: (errorData) => langfuse.trace({ name: \"LLM Error\", metadata: errorData }),\n * },\n * }\n * ```\n */\n observability_c?: CopilotObservabilityConfig;\n\n /**\n * Configuration for connecting to Model Context Protocol (MCP) servers.\n * Allows fetching and using tools defined on external MCP-compliant servers.\n * Requires providing the `createMCPClient` function during instantiation.\n * @experimental\n */\n mcpServers?: MCPEndpointConfig[];\n\n /**\n * A function that creates an MCP client instance for a given endpoint configuration.\n * This function is responsible for using the appropriate MCP client library\n * (e.g., `@copilotkit/runtime`, `ai`) to establish a connection.\n * Required if `mcpServers` is provided.\n *\n * ```typescript\n * import { experimental_createMCPClient } from \"ai\"; // Import from vercel ai library\n * // ...\n * const runtime = new CopilotRuntime({\n * mcpServers: [{ endpoint: \"...\" }],\n * async createMCPClient(config) {\n * return await experimental_createMCPClient({\n * transport: {\n * type: \"sse\",\n * url: config.endpoint,\n * headers: config.apiKey\n * ? { Authorization: `Bearer ${config.apiKey}` }\n * : undefined,\n * },\n * });\n * }\n * });\n * ```\n */\n createMCPClient?: CreateMCPClientFunction;\n\n /**\n * Optional error handler for comprehensive debugging and observability.\n *\n * @param errorEvent - Structured error event with rich debugging context\n *\n * @example\n * ```typescript\n * const runtime = new CopilotRuntime({\n * onError: (errorEvent) => {\n * debugDashboard.capture(errorEvent);\n * }\n * });\n * ```\n */\n onError?: CopilotErrorHandler;\n\n onStopGeneration?: OnStopGenerationHandler;\n\n /**\n * Enable debug logging for the runtime event pipeline.\n * Pass `true` for full output, or an object for granular control:\n *\n * ```ts\n * const runtime = new CopilotRuntime({\n * debug: true,\n * // or: debug: { events: true, lifecycle: true, verbose: false }\n * });\n * ```\n */\n debug?: DebugConfig;\n\n // /** Optional transcription service for audio processing. */\n // transcriptionService?: CopilotRuntimeOptionsVNext[\"transcriptionService\"];\n // /** Optional *before* middleware – callback function or webhook URL. */\n // beforeRequestMiddleware?: CopilotRuntimeOptionsVNext[\"beforeRequestMiddleware\"];\n // /** Optional *after* middleware – callback function or webhook URL. */\n // afterRequestMiddleware?: CopilotRuntimeOptionsVNext[\"afterRequestMiddleware\"];\n}\n\ntype BeforeRequestMiddleware =\n CopilotRuntimeOptionsVNext[\"beforeRequestMiddleware\"];\ntype AfterRequestMiddleware =\n CopilotRuntimeOptionsVNext[\"afterRequestMiddleware\"];\ntype BeforeRequestMiddlewareFn = Exclude<BeforeRequestMiddleware, string>;\ntype BeforeRequestMiddlewareFnParameters =\n Parameters<BeforeRequestMiddlewareFn>;\ntype BeforeRequestMiddlewareFnResult = ReturnType<BeforeRequestMiddlewareFn>;\ntype AfterRequestMiddlewareFn = Exclude<AfterRequestMiddleware, string>;\ntype AfterRequestMiddlewareFnParameters = Parameters<AfterRequestMiddlewareFn>;\n\ninterface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []>\n extends\n Omit<CopilotRuntimeConstructorParams_BASE<T>, \"agents\">,\n Omit<CopilotRuntimeOptionsVNext, \"agents\" | \"transcriptionService\"> {\n /**\n * TODO: un-omit `transcriptionService` above once it's supported\n *\n * This satisfies...\n * – the optional constraint in `CopilotRuntimeConstructorParams_BASE`\n * – the `MaybePromise<NonEmptyRecord<T>>` constraint in `CopilotRuntimeOptionsVNext`\n * – the `Record<string, AbstractAgent>` constraint in `both\n */\n agents?: AgentsConfig;\n\n intelligence?: CopilotIntelligenceRuntimeOptions[\"intelligence\"];\n identifyUser?: CopilotIntelligenceRuntimeOptions[\"identifyUser\"];\n memory?: CopilotIntelligenceRuntimeOptions[\"memory\"];\n channels?: CopilotIntelligenceRuntimeOptions[\"channels\"];\n ɵlearning?: CopilotIntelligenceRuntimeOptions[\"ɵlearning\"];\n generateThreadNames?: CopilotIntelligenceRuntimeOptions[\"generateThreadNames\"];\n maxReconnectMs?: CopilotIntelligenceRuntimeOptions[\"maxReconnectMs\"];\n maxRejoinMs?: CopilotIntelligenceRuntimeOptions[\"maxRejoinMs\"];\n lockTtlSeconds?: CopilotIntelligenceRuntimeOptions[\"lockTtlSeconds\"];\n lockKeyPrefix?: CopilotIntelligenceRuntimeOptions[\"lockKeyPrefix\"];\n lockHeartbeatIntervalSeconds?: CopilotIntelligenceRuntimeOptions[\"lockHeartbeatIntervalSeconds\"];\n}\n\n/**\n * Central runtime object passed to all request handlers.\n * @deprecated The v1 SDK is deprecated. Use v2 instead. Use `CopilotRuntime` from `@copilotkit/runtime/v2` instead.\n *\n * ```tsx\n * import { CopilotRuntime } from \"@copilotkit/runtime/v2\";\n *\n * const runtime = new CopilotRuntime({ agents: {} });\n * ```\n * See https://docs.copilotkit.ai/runtime-server-adapter\n */\nexport class CopilotRuntime<const T extends Parameter[] | [] = []> {\n params?: CopilotRuntimeConstructorParams<T>;\n private observability?: CopilotObservabilityConfig;\n // Cache MCP tools per endpoint to avoid re-fetching repeatedly\n private mcpToolsCache: Map<string, BuiltInAgentClassicConfig[\"tools\"]> =\n new Map();\n private runtimeArgs: CopilotRuntimeOptions & RuntimeErrorReporterOptions;\n private _instance: CopilotRuntimeVNext;\n /** Runtime-bound telemetry identity and sampling authority. */\n public readonly telemetry: TelemetryCapture;\n\n constructor(params?: CopilotRuntimeConstructorParams<T>) {\n logRuntimeTelemetryDisclosure();\n\n const agents = params?.agents ?? {};\n const endpointAgents = this.assignEndpointsToAgents(\n params?.remoteEndpoints ?? [],\n );\n\n // Merge endpoint agents with user-provided agents.\n // When agents is a factory function, wrap it so endpoint agents are merged\n // at resolution time (spreading a function produces {} — silent data loss).\n let mergedAgents: AgentsConfig;\n if (typeof agents === \"function\") {\n mergedAgents = async (ctx) => {\n const resolved = await agents(ctx);\n return { ...endpointAgents, ...resolved };\n };\n } else {\n mergedAgents = Promise.resolve(agents).then((resolved) => ({\n ...endpointAgents,\n ...resolved,\n }));\n }\n\n // Resolve identity once and bind it to this compatibility Runtime. The\n // capture scope shares process-level sinks and settings without exposing\n // mutable identity to other live runtimes.\n const resolvedLicenseToken = firstNonBlankLicenseToken(\n params?.licenseToken,\n process.env.COPILOTKIT_LICENSE_TOKEN,\n );\n const resolvedTelemetryId = firstNonBlankTelemetryId(\n params?.telemetryId,\n process.env.CPK_TELEMETRY_ID,\n );\n const resolvedTelemetryIdentity =\n resolvedTelemetryId !== undefined\n ? { telemetryId: resolvedTelemetryId }\n : resolvedLicenseToken !== undefined\n ? { licenseToken: resolvedLicenseToken }\n : {};\n this.telemetry = telemetry.createScope(resolvedTelemetryIdentity);\n\n // No TelemetryAgentRunner wrap. The V2 SSE path already emits\n // `agent_execution_stream_*` for this runtime, and since it now emits\n // through this entrypoint's scope, wrapping would put two copies of\n // every stream event on the wire. The class stays exported for callers\n // who construct it themselves. The rawEvent enrichment it used to add\n // moved to `v2/runtime/handlers/shared/sse-response.ts`, so nothing is\n // lost and v2 callers gain it too.\n const runner = params?.runner ?? new InMemoryAgentRunner();\n\n const sharedRuntimeArgs = {\n agents: mergedAgents,\n telemetryId: resolvedTelemetryId,\n licenseToken: resolvedLicenseToken,\n // Emit through this entrypoint's own scope rather than letting the\n // delegated V2 runtime build its own. That scope writes to Segment\n // and stamps the v1 surface, so handing it down is what lets the v1\n // middleware below stop emitting the same events a second time.\n ɵtelemetry: this.telemetry,\n telemetryProperties: params?.telemetryProperties,\n debug: params?.debug,\n // TODO: add support for transcriptionService from CopilotRuntimeOptionsVNext once it is ready\n // transcriptionService: params?.transcriptionService,\n\n beforeRequestMiddleware:\n this.createOnBeforeRequestHandler(params).bind(this),\n ...(params?.afterRequestMiddleware || params?.middleware?.onAfterRequest\n ? {\n afterRequestMiddleware:\n this.createOnAfterRequestHandler(params).bind(this),\n }\n : {}),\n a2ui: params?.a2ui,\n mcpApps: params?.mcpApps,\n openGenerativeUI: params?.openGenerativeUI,\n [runtimeErrorReporterOption]: createRuntimeErrorReporter(params?.onError),\n forwardHeaders: params?.forwardHeaders,\n exposeMemoryRoutes: params?.exposeMemoryRoutes,\n };\n if (params?.intelligence !== undefined) {\n // The compatibility constructor keeps Intelligence identity optional at\n // compile time, while the v2 runtime checks that callers supply web\n // identity, Channels, or both. Preserve that runtime validation here.\n this.runtimeArgs = {\n ...sharedRuntimeArgs,\n intelligence: params.intelligence,\n identifyUser: params.identifyUser,\n memory: params.memory,\n channels: params.channels,\n ɵlearning: params.ɵlearning,\n generateThreadNames: params.generateThreadNames,\n maxReconnectMs: params.maxReconnectMs,\n maxRejoinMs: params.maxRejoinMs,\n lockTtlSeconds: params.lockTtlSeconds,\n lockKeyPrefix: params.lockKeyPrefix,\n lockHeartbeatIntervalSeconds: params.lockHeartbeatIntervalSeconds,\n } as CopilotRuntimeOptions;\n } else {\n this.runtimeArgs = {\n ...sharedRuntimeArgs,\n runner,\n };\n }\n this.params = params;\n this.observability = params?.observability_c;\n }\n\n get instance() {\n if (!this._instance) {\n this._instance = new CopilotRuntimeVNext(this.runtimeArgs);\n }\n\n return this._instance;\n }\n\n private assignEndpointsToAgents(\n endpoints: CopilotRuntimeConstructorParams<T>[\"remoteEndpoints\"],\n ): Record<string, AbstractAgent> {\n let result: Record<string, AbstractAgent> = {};\n\n if (\n endpoints.some(\n (endpoint) =>\n resolveEndpointType(endpoint) == EndpointType.LangGraphPlatform,\n )\n ) {\n throw new CopilotKitMisuseError({\n message:\n \"LangGraphPlatformEndpoint in remoteEndpoints is deprecated. \" +\n 'Please use the \"agents\" option instead with LangGraphAgent from \"@copilotkit/runtime/langgraph\". ' +\n 'Example: agents: { myAgent: new LangGraphAgent({ deploymentUrl: \"...\", graphId: \"...\" }) }',\n });\n }\n\n return result;\n }\n\n handleServiceAdapter(serviceAdapter: CopilotServiceAdapter) {\n this.runtimeArgs.agents = Promise.resolve(\n this.runtimeArgs.agents ?? {},\n ).then(async (agents) => {\n // An AgentsFactory function has no enumerable keys, so it flows through\n // this path the same way an empty record does.\n let agentsList = agents as Record<string, AbstractAgent>;\n const isAgentsListEmpty = !Object.keys(agents).length;\n const hasServiceAdapter = Boolean(serviceAdapter);\n const illegalServiceAdapterNames = [\"EmptyAdapter\"];\n const serviceAdapterCanBeUsedForAgent =\n !illegalServiceAdapterNames.includes(serviceAdapter.name);\n\n if (\n isAgentsListEmpty &&\n (!hasServiceAdapter || !serviceAdapterCanBeUsedForAgent)\n ) {\n throw new CopilotKitMisuseError({\n message:\n \"No default agent provided. Please provide a default agent in the runtime config.\",\n });\n }\n\n if (isAgentsListEmpty) {\n const languageModel = serviceAdapter.getLanguageModel?.();\n if (languageModel) {\n // Adapter exposes a pre-configured LanguageModel (e.g. OpenAI/Anthropic adapters)\n agentsList.default = new BuiltInAgent({ model: languageModel });\n } else if (serviceAdapter.provider && serviceAdapter.model) {\n // Adapter exposes provider/model strings\n agentsList.default = new BuiltInAgent({\n model: `${serviceAdapter.provider}/${serviceAdapter.model}`,\n });\n } else {\n throw new CopilotKitMisuseError({\n message:\n `Service adapter \"${serviceAdapter.name ?? \"unknown\"}\" does not provide model information. ` +\n `When using adapters like LangChainAdapter without an explicit agents list, ` +\n `please provide a default agent in the runtime config. Example:\\n` +\n ` new CopilotRuntime({\\n` +\n ` agents: { default: new BuiltInAgent({ model: \"openai/gpt-4o\" }) }\\n` +\n ` })`,\n });\n }\n }\n\n const actions = this.params?.actions;\n\n // `actions` and `mcpServers` are attached independently: a runtime may\n // configure MCP servers without any local actions.\n const mcpTools = await this.getToolsFromMCP();\n const actionTools = actions ? this.getToolsFromActions(actions) : [];\n agentsList = this.assignToolsToAgents(agentsList, [\n ...actionTools,\n ...mcpTools,\n ]);\n\n return agentsList;\n });\n }\n\n // Receive this.params.action and turn it into the AbstractAgent tools\n private getToolsFromActions(\n actions: ActionsConfiguration<any>,\n ): BuiltInAgentClassicConfig[\"tools\"] {\n // Resolve actions to an array (handle function case)\n const actionsArray =\n typeof actions === \"function\"\n ? actions({ properties: {}, url: undefined })\n : actions;\n\n // Convert each Action to a ToolDefinition\n return actionsArray.map((action) => {\n // Convert JSON schema to Zod schema\n const zodSchema = getZodParameters(action.parameters || []);\n\n return {\n name: action.name,\n description: action.description || \"\",\n parameters: zodSchema,\n // `handler` is an in-process function and was never part of the remote\n // executor deleted in v1.50.0 — only the wiring to it was lost. Call it.\n //\n // The result must never be `undefined`: `JSON.stringify(undefined)` is\n // not a string, which strips the required `content` off\n // TOOL_CALL_RESULT and surfaces as a Zod error in the browser\n // (#2915, #3198). Both branches below return a string instead.\n execute: async (args: unknown) => {\n if (typeof action.handler !== \"function\") {\n return (\n `The tool \"${action.name}\" was advertised without a handler, so it ` +\n `has no implementation to run. Tell the user this tool is unavailable.`\n );\n }\n const result = await action.handler(args as any);\n return result === undefined\n ? `The tool \"${action.name}\" ran and returned no value.`\n : result;\n },\n };\n });\n }\n\n private assignToolsToAgents(\n agents: Record<string, AbstractAgent>,\n tools: BuiltInAgentClassicConfig[\"tools\"],\n ): Record<string, AbstractAgent> {\n if (!tools?.length) {\n return agents;\n }\n\n const enrichedAgents: Record<string, AbstractAgent> = { ...agents };\n\n for (const [agentId, agent] of Object.entries(enrichedAgents)) {\n const existingConfig = (Reflect.get(agent, \"config\") ?? {}) as Record<\n string,\n unknown\n >;\n\n // Skip factory-mode agents — they don't have a tools property\n if (\"factory\" in existingConfig) {\n continue;\n }\n\n const classicConfig =\n existingConfig as unknown as BuiltInAgentClassicConfig;\n const existingTools = classicConfig.tools ?? [];\n\n // The endpoint factory runs `handleServiceAdapter` every time it is\n // called, and the documented v1 route builds the endpoint inside the\n // request handler — so a module-scope runtime lands here once per\n // request. Appending unconditionally advertised N copies of every tool\n // to the model. Skip names the agent already carries, which also leaves\n // a tool the agent defines itself in place.\n const existingNames = new Set(existingTools.map((tool) => tool.name));\n const newTools = tools.filter((tool) => !existingNames.has(tool.name));\n if (newTools.length === 0) {\n continue;\n }\n\n const updatedConfig: BuiltInAgentClassicConfig = {\n ...classicConfig,\n tools: [...existingTools, ...newTools],\n };\n\n Reflect.set(agent, \"config\", updatedConfig);\n enrichedAgents[agentId] = agent;\n }\n\n return enrichedAgents;\n }\n\n private createOnBeforeRequestHandler(\n params?: CopilotRuntimeConstructorParams<T> &\n PartialBy<CopilotRuntimeOptions, \"agents\">,\n ) {\n return async (hookParams: BeforeRequestMiddlewareFnParameters[0]) => {\n const { request } = hookParams;\n\n // No `copilot_request_created` capture here. The V2 handlers this\n // runtime delegates to already emit it, through this runtime's own\n // scope, and they know the route — so `requestType` is \"run\" or\n // \"connect\" rather than the \"unknown\" this site reported for every\n // request that did not set `forwardedProps.metadata.requestType`.\n const body = (await readBody(request)) as RunAgentInput;\n\n // We do not process middleware for the internal GET requests\n if (request.method === \"GET\" || !body) return;\n\n // TODO: get public api key and run with expected data\n // if (this.observability?.enabled && this.params.publicApiKey) {\n // this.logObservabilityBeforeRequest()\n // }\n\n // TODO: replace hooksParams top argument type with BeforeRequestMiddlewareParameters when exported\n const middlewareResult =\n await params?.beforeRequestMiddleware?.(hookParams);\n\n if (params?.middleware?.onBeforeRequest) {\n const { request, runtime, path } = hookParams;\n const gqlMessages = (aguiToGQL(body.messages) as Message[]).reduce(\n (acc, msg) => {\n if (\"role\" in msg && msg.role === \"user\") {\n acc.inputMessages.push(msg);\n } else {\n acc.outputMessages.push(msg);\n }\n return acc;\n },\n { inputMessages: [] as Message[], outputMessages: [] as Message[] },\n );\n const { inputMessages, outputMessages } = gqlMessages;\n params.middleware.onBeforeRequest({\n threadId: body.threadId,\n runId: body.runId,\n inputMessages,\n properties: body.forwardedProps,\n url: request.url,\n } satisfies OnBeforeRequestOptions);\n }\n\n return middlewareResult;\n };\n }\n\n private createOnAfterRequestHandler(\n params?: CopilotRuntimeConstructorParams<T> &\n PartialBy<CopilotRuntimeOptions, \"agents\">,\n ) {\n return async (hookParams: AfterRequestMiddlewareFnParameters[0]) => {\n // TODO: get public api key and run with expected data\n // if (this.observability?.enabled && publicApiKey) {\n // this.logObservabilityAfterRequest()\n // }\n\n // TODO: replace hooksParams top argument type with AfterRequestMiddlewareParameters when exported\n params?.afterRequestMiddleware?.(hookParams);\n\n if (params?.middleware?.onAfterRequest) {\n const messages = hookParams.messages ?? [];\n params.middleware.onAfterRequest({\n threadId: hookParams.threadId ?? \"\",\n runId: hookParams.runId,\n inputMessages: messages.filter(\n (m): m is typeof m & { role: string } =>\n \"role\" in m && m.role === \"user\",\n ) as unknown as Message[],\n outputMessages: messages.filter(\n (m): m is typeof m & { role: string } =>\n \"role\" in m && m.role !== \"user\",\n ) as unknown as Message[],\n // TODO: forward actual properties once the after-request hook has access to the request body\n properties: {},\n url: hookParams.path,\n } satisfies OnAfterRequestOptions);\n }\n };\n }\n\n // Observability Methods\n\n /**\n * Log LLM request if observability is enabled\n */\n private async logObservabilityBeforeRequest(\n requestData: LLMRequestData,\n ): Promise<void> {\n try {\n await this.observability.hooks.handleRequest(requestData);\n } catch (error) {\n console.error(\"Error logging LLM request:\", error);\n }\n }\n\n /**\n * Log final LLM response after request completes\n */\n private logObservabilityAfterRequest(\n outputMessagesPromise: Promise<Message[]>,\n baseData: {\n threadId: string;\n runId?: string;\n model?: string;\n provider?: string;\n agentName?: string;\n nodeName?: string;\n },\n streamedChunks: any[],\n requestStartTime: number,\n publicApiKey?: string,\n ): void {\n try {\n outputMessagesPromise\n .then((outputMessages) => {\n const responseData: LLMResponseData = {\n threadId: baseData.threadId,\n runId: baseData.runId,\n model: baseData.model,\n // Use collected chunks for progressive mode or outputMessages for regular mode\n output: this.observability.progressive\n ? streamedChunks\n : outputMessages,\n latency: Date.now() - requestStartTime,\n timestamp: Date.now(),\n provider: baseData.provider,\n isFinalResponse: true,\n agentName: baseData.agentName,\n nodeName: baseData.nodeName,\n };\n\n try {\n this.observability.hooks.handleResponse(responseData);\n } catch (logError) {\n console.error(\"Error logging LLM response:\", logError);\n }\n })\n .catch((error) => {\n console.error(\"Failed to get output messages for logging:\", error);\n });\n } catch (error) {\n console.error(\"Error setting up logging for LLM response:\", error);\n }\n }\n\n // Resolve MCP tools to BuiltInAgent tool definitions\n // Optionally accepts request-scoped properties to merge request-provided mcpServers\n private async getToolsFromMCP(options?: {\n properties?: Record<string, unknown>;\n }): Promise<BuiltInAgentClassicConfig[\"tools\"]> {\n const runtimeMcpServers = (this.params?.mcpServers ??\n []) as MCPEndpointConfig[];\n const createMCPClient = this.params?.createMCPClient as\n | CreateMCPClientFunction\n | undefined;\n\n // If no runtime config and no request overrides, nothing to do\n const requestMcpServers = ((\n options?.properties as { mcpServers?: MCPEndpointConfig[] } | undefined\n )?.mcpServers ??\n (\n options?.properties as\n | { mcpEndpoints?: MCPEndpointConfig[] }\n | undefined\n )?.mcpEndpoints ??\n []) as MCPEndpointConfig[];\n\n const hasAnyServers =\n (runtimeMcpServers?.length ?? 0) > 0 ||\n (requestMcpServers?.length ?? 0) > 0;\n if (!hasAnyServers) {\n return [];\n }\n\n if (!createMCPClient) {\n // Mirror legacy behavior: when servers are provided without a factory, treat as misconfiguration\n throw new CopilotKitMisuseError({\n message:\n \"MCP Integration Error: `mcpServers` were provided, but the `createMCPClient` function was not passed to the CopilotRuntime constructor. Please provide an implementation for `createMCPClient`.\",\n });\n }\n\n // Merge and dedupe endpoints by URL; request-level overrides take precedence\n const effectiveEndpoints = (() => {\n const byUrl = new Map<string, MCPEndpointConfig>();\n for (const ep of runtimeMcpServers) {\n if (ep?.endpoint) byUrl.set(ep.endpoint, ep);\n }\n for (const ep of requestMcpServers) {\n if (ep?.endpoint) byUrl.set(ep.endpoint, ep);\n }\n return Array.from(byUrl.values());\n })();\n\n const allTools: BuiltInAgentClassicConfig[\"tools\"] = [];\n\n for (const config of effectiveEndpoints) {\n const endpointUrl = config.endpoint;\n // Return cached tool definitions when available\n const cached = this.mcpToolsCache.get(endpointUrl);\n if (cached) {\n allTools.push(...cached);\n continue;\n }\n\n try {\n const client = await createMCPClient(config);\n const toolsMap = await client.tools();\n\n const toolDefs: BuiltInAgentClassicConfig[\"tools\"] = Object.entries(\n toolsMap,\n ).map(([toolName, tool]: [string, MCPTool]) => {\n const params: Parameter[] = extractParametersFromSchema(tool);\n const zodSchema = getZodParameters(params);\n return {\n name: toolName,\n description:\n tool.description || `MCP tool: ${toolName} (from ${endpointUrl})`,\n parameters: zodSchema,\n // The MCP client stays live for the lifetime of the cached tool\n // definitions; `tool.execute` calls the server.\n execute: async (args: unknown) => tool.execute(args),\n };\n });\n\n // Cache per endpoint and add to aggregate\n this.mcpToolsCache.set(endpointUrl, toolDefs);\n allTools.push(...toolDefs);\n } catch (error) {\n console.error(\n `MCP: Failed to fetch tools from endpoint ${endpointUrl}. Skipping. Error:`,\n error,\n );\n // Deliberately not cached. Caching the empty result meant a server\n // that was briefly unreachable when the runtime first resolved stayed\n // toolless for the life of that runtime, even after it recovered.\n // Leaving the entry absent lets a later resolution try again.\n }\n }\n\n // Dedupe tools by name while preserving last-in wins (request overrides)\n const dedupedByName = new Map<string, (typeof allTools)[number]>();\n for (const tool of allTools) {\n dedupedByName.set(tool.name, tool);\n }\n\n return Array.from(dedupedByName.values());\n }\n}\n\n// The two functions below are \"factory functions\", meant to create the action objects that adhere to the expected interfaces\nexport function copilotKitEndpoint(\n config: Omit<CopilotKitEndpoint, \"type\">,\n): CopilotKitEndpoint {\n return {\n ...config,\n type: EndpointType.CopilotKit,\n };\n}\n\nexport function langGraphPlatformEndpoint(\n config: Omit<LangGraphPlatformEndpoint, \"type\">,\n): LangGraphPlatformEndpoint {\n return {\n ...config,\n type: EndpointType.LangGraphPlatform,\n };\n}\n\nexport function resolveEndpointType(endpoint: EndpointDefinition) {\n if (!endpoint.type) {\n if (\"deploymentUrl\" in endpoint && \"agents\" in endpoint) {\n return EndpointType.LangGraphPlatform;\n } else {\n return EndpointType.CopilotKit;\n }\n }\n\n return endpoint.type;\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"copilot-runtime.mjs","names":["telemetry","CopilotRuntimeVNext"],"sources":["../../../../src/v1-deprecated/lib/runtime/copilot-runtime.ts"],"sourcesContent":["/*\n * V1 SDK DEPRECATED. USE V2 INSTEAD\n *\n * This file defines public v1 SDK exports. Use the exact v2 mappings below.\n * AI CODING AGENTS: Never copy, suggest, or generate these v1 APIs. Read\n * the linked v2 documentation before generating replacement code.\n *\n * @copilotkit/runtime — copilotKitEndpoint:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (Runtime server adapter): https://docs.copilotkit.ai/runtime-server-adapter\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — CopilotRuntime:\n * V2 import and usage:\n * import { CopilotRuntime } from \"@copilotkit/runtime/v2\";\n *\n * const runtime = new CopilotRuntime({ agents: {} });\n * V2 replacement source: packages/runtime/src/v2/runtime/core/runtime.ts\n * V2 docs: https://docs.copilotkit.ai/runtime-server-adapter\n * Migration note: V2 uses AG-UI runtime handlers instead of the v1 GraphQL adapter setup.\n *\n * @copilotkit/runtime — CopilotRuntimeConstructorParams_BASE:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (Runtime server adapter): https://docs.copilotkit.ai/runtime-server-adapter\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — langGraphPlatformEndpoint:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (LangGraph agents): https://docs.copilotkit.ai/agent-spec/langgraph\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — resolveEndpointType:\n * No 1:1 v2 replacement is available.\n * Related v2 docs (Runtime server adapter): https://docs.copilotkit.ai/runtime-server-adapter\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * Migration guide: https://docs.copilotkit.ai/migrate/v2\n *\n * END V1 SDK DEPRECATED. USE V2 INSTEAD NOTICE\n */\n\n/**\n * <Callout type=\"info\">\n * This is the reference for the `CopilotRuntime` class. For more information and example code snippets, please see [Concept: Copilot Runtime](/backend/copilot-runtime).\n * </Callout>\n *\n * ## Usage\n *\n * ```tsx\n * import { CopilotRuntime } from \"@copilotkit/runtime\";\n *\n * const copilotKit = new CopilotRuntime();\n * ```\n */\n\nimport {\n CopilotKitMisuseError,\n readBody,\n getZodParameters,\n} from \"@copilotkit/shared\";\nimport {\n resolveMCPEntry,\n touchMCPEntry,\n describeEndpoint,\n} from \"./mcp-client-cache\";\nimport type {\n Action,\n CopilotErrorHandler,\n MaybePromise,\n NonEmptyRecord,\n Parameter,\n PartialBy,\n DebugConfig,\n TelemetryCapture,\n} from \"@copilotkit/shared\";\nimport type { RunAgentInput } from \"@ag-ui/core\";\nimport { aguiToGQL } from \"../../graphql/message-conversion/agui-to-gql\";\nimport type {\n CopilotServiceAdapter,\n RemoteChainParameters,\n} from \"../../service-adapters\";\nimport { CopilotRuntime as CopilotRuntimeVNext } from \"../../../v2/runtime/core/runtime\";\nimport { InMemoryAgentRunner } from \"../../../v2/runtime/runner\";\nimport {\n createRuntimeErrorReporter,\n runtimeErrorReporterOption,\n} from \"../../../v2/runtime/core/runtime-error-reporter\";\nimport type { RuntimeErrorReporterOptions } from \"../../../v2/runtime/core/runtime-error-reporter\";\nimport type {\n CopilotIntelligenceRuntimeOptions,\n CopilotRuntimeOptions,\n CopilotRuntimeOptions as CopilotRuntimeOptionsVNext,\n AgentsConfig,\n AgentsFactory,\n AgentFactoryContext,\n} from \"../../../v2/runtime/core/runtime\";\nimport type { AgentRunner } from \"../../../v2/runtime/runner\";\n\nexport type { AgentsConfig, AgentsFactory, AgentFactoryContext };\nimport telemetry from \"../telemetry-client\";\nimport { logRuntimeTelemetryDisclosure } from \"../telemetry-disclosure\";\n\nimport type { MessageInput } from \"../../graphql/inputs/message.input\";\nimport type { Message } from \"../../graphql/types/converted\";\n\nimport { EndpointType } from \"./types\";\nimport type {\n EndpointDefinition,\n CopilotKitEndpoint,\n LangGraphPlatformEndpoint,\n} from \"./types\";\n\nimport type {\n CopilotObservabilityConfig,\n LLMRequestData,\n LLMResponseData,\n} from \"../observability\";\nimport type { AbstractAgent } from \"@ag-ui/client\";\nimport {\n firstNonBlankLicenseToken,\n firstNonBlankTelemetryId,\n} from \"../../../v2/runtime/telemetry/telemetry-identity\";\n\n// +++ MCP Imports +++\nimport { extractParametersFromSchema } from \"./mcp-tools-utils\";\nimport type { MCPClient, MCPEndpointConfig, MCPTool } from \"./mcp-tools-utils\";\nimport { BuiltInAgent } from \"../../../agent\";\nimport type { BuiltInAgentClassicConfig } from \"../../../agent\";\n// Define the function type alias here or import if defined elsewhere\ntype CreateMCPClientFunction = (\n config: MCPEndpointConfig,\n) => Promise<MCPClient>;\n\ntype ActionsConfiguration<T extends Parameter[] | [] = []> =\n | Action<T>[]\n | ((ctx: { properties: any; url?: string }) => Action<T>[]);\n\ninterface OnBeforeRequestOptions {\n threadId?: string;\n runId?: string;\n inputMessages: Message[];\n properties: any;\n url?: string;\n}\n\ntype OnBeforeRequestHandler = (\n options: OnBeforeRequestOptions,\n) => void | Promise<void>;\n\ninterface OnAfterRequestOptions {\n threadId: string;\n runId?: string;\n inputMessages: Message[];\n outputMessages: Message[];\n properties: any;\n url?: string;\n}\n\ntype OnAfterRequestHandler = (\n options: OnAfterRequestOptions,\n) => void | Promise<void>;\n\ninterface OnStopGenerationOptions {\n threadId: string;\n runId?: string;\n url?: string;\n agentName?: string;\n lastMessage: MessageInput;\n}\ntype OnStopGenerationHandler = (\n options: OnStopGenerationOptions,\n) => void | Promise<void>;\n\ninterface Middleware {\n /**\n * A function that is called before the request is processed.\n */\n /**\n * @deprecated This middleware hook is deprecated and will be removed in a future version.\n * Use updated middleware integration methods in CopilotRuntimeVNext instead.\n */\n onBeforeRequest?: OnBeforeRequestHandler;\n\n /**\n * A function that is called after the request is processed.\n */\n /**\n * @deprecated This middleware hook is deprecated and will be removed in a future version.\n * Use updated middleware integration methods in CopilotRuntimeVNext instead.\n */\n onAfterRequest?: OnAfterRequestHandler;\n}\n\nexport interface CopilotRuntimeConstructorParams_BASE<\n T extends Parameter[] | [] = [],\n> {\n /** Standalone telemetry identity. Falls back to CPK_TELEMETRY_ID before legacy license identity. */\n telemetryId?: string;\n /**\n * Middleware to be used by the runtime.\n *\n * ```ts\n * onBeforeRequest: (options: {\n * threadId?: string;\n * runId?: string;\n * inputMessages: Message[];\n * properties: any;\n * }) => void | Promise<void>;\n * ```\n *\n * ```ts\n * onAfterRequest: (options: {\n * threadId?: string;\n * runId?: string;\n * inputMessages: Message[];\n * outputMessages: Message[];\n * properties: any;\n * }) => void | Promise<void>;\n * ```\n */\n /**\n * @deprecated This middleware hook is deprecated and will be removed in a future version.\n * Use updated middleware integration methods in CopilotRuntimeVNext instead.\n */\n middleware?: Middleware;\n\n /*\n * A list of server side actions that can be executed. Will be ignored when remoteActions are set\n */\n actions?: ActionsConfiguration<T>;\n\n /*\n * Deprecated: Use `remoteEndpoints`.\n */\n remoteActions?: CopilotKitEndpoint[];\n\n /*\n * A list of remote actions that can be executed.\n */\n remoteEndpoints?: EndpointDefinition[];\n\n /*\n * An array of LangServer URLs.\n */\n langserve?: RemoteChainParameters[];\n\n /**\n * Optional agent runner to use for SSE runtime.\n */\n runner?: AgentRunner;\n\n /*\n * A map of agent names to AGUI agents.\n * Example agent config:\n * ```ts\n * import { AbstractAgent } from \"@ag-ui/client\";\n * // ...\n * agents: {\n * \"support\": new CustomerSupportAgent(),\n * \"technical\": new TechnicalAgent()\n * }\n * ```\n */\n agents?: Record<string, AbstractAgent>;\n\n /*\n * Delegates agent state processing to the service adapter.\n *\n * When enabled, individual agent state requests will not be processed by the agent itself.\n * Instead, all processing will be handled by the service adapter.\n */\n delegateAgentProcessingToServiceAdapter?: boolean;\n\n /**\n * Configuration for LLM request/response logging.\n *\n * Example logging config:\n * ```ts\n * logging: {\n * enabled: true, // Enable or disable logging\n * progressive: true, // Set to false for buffered logging\n * logger: {\n * logRequest: (data) => langfuse.trace({ name: \"LLM Request\", input: data }),\n * logResponse: (data) => langfuse.trace({ name: \"LLM Response\", output: data }),\n * logError: (errorData) => langfuse.trace({ name: \"LLM Error\", metadata: errorData }),\n * },\n * }\n * ```\n */\n observability_c?: CopilotObservabilityConfig;\n\n /**\n * Configuration for connecting to Model Context Protocol (MCP) servers.\n * Allows fetching and using tools defined on external MCP-compliant servers.\n * Requires providing the `createMCPClient` function during instantiation.\n *\n * A request can also name its own servers, as `mcpServers` (or the older\n * `mcpEndpoints`) inside `forwardedProps` — that is what the frontend's\n * `setMcpServers` sends. Those are merged with this list and connected from\n * the server.\n *\n * That merge previously never ran: whatever the browser sent was accepted\n * and discarded. It now takes effect, so a deployment that has been sending\n * `setMcpServers` will start connecting to those endpoints without changing\n * anything on its side.\n *\n * The destination is therefore caller-controlled, not only config-controlled.\n * If your deployment does not mean to let the browser choose an MCP server,\n * check `config.endpoint` inside `createMCPClient` and reject anything\n * outside your allowlist. Without that check a request can aim the server at\n * a loopback, link-local, or otherwise internal address (SSRF).\n * @experimental\n */\n mcpServers?: MCPEndpointConfig[];\n\n /**\n * A function that creates an MCP client instance for a given endpoint configuration.\n * This function is responsible for using the appropriate MCP client library\n * (e.g., `@copilotkit/runtime`, `ai`) to establish a connection.\n * Required if `mcpServers` is provided.\n *\n * ```typescript\n * import { experimental_createMCPClient } from \"ai\"; // Import from vercel ai library\n * // ...\n * const runtime = new CopilotRuntime({\n * mcpServers: [{ endpoint: \"...\" }],\n * async createMCPClient(config) {\n * return await experimental_createMCPClient({\n * transport: {\n * type: \"sse\",\n * url: config.endpoint,\n * headers: config.apiKey\n * ? { Authorization: `Bearer ${config.apiKey}` }\n * : undefined,\n * },\n * });\n * }\n * });\n * ```\n *\n * Define this once, at module scope, if you build a new `CopilotRuntime`\n * per request. Connections are cached against the identity of this function\n * plus the endpoint config, and an inline function is a new object on every\n * request — so a per-request runtime with an inline factory opens a new\n * connection each time and never reuses one. A module-scope factory, which\n * is what the documented setup uses, shares connections across requests and\n * keeps the cache bounded by how many distinct credentials are in play\n * rather than by traffic.\n */\n createMCPClient?: CreateMCPClientFunction;\n\n /**\n * Optional error handler for comprehensive debugging and observability.\n *\n * @param errorEvent - Structured error event with rich debugging context\n *\n * @example\n * ```typescript\n * const runtime = new CopilotRuntime({\n * onError: (errorEvent) => {\n * debugDashboard.capture(errorEvent);\n * }\n * });\n * ```\n */\n onError?: CopilotErrorHandler;\n\n onStopGeneration?: OnStopGenerationHandler;\n\n /**\n * Enable debug logging for the runtime event pipeline.\n * Pass `true` for full output, or an object for granular control:\n *\n * ```ts\n * const runtime = new CopilotRuntime({\n * debug: true,\n * // or: debug: { events: true, lifecycle: true, verbose: false }\n * });\n * ```\n */\n debug?: DebugConfig;\n\n // /** Optional transcription service for audio processing. */\n // transcriptionService?: CopilotRuntimeOptionsVNext[\"transcriptionService\"];\n // /** Optional *before* middleware – callback function or webhook URL. */\n // beforeRequestMiddleware?: CopilotRuntimeOptionsVNext[\"beforeRequestMiddleware\"];\n // /** Optional *after* middleware – callback function or webhook URL. */\n // afterRequestMiddleware?: CopilotRuntimeOptionsVNext[\"afterRequestMiddleware\"];\n}\n\ntype BeforeRequestMiddleware =\n CopilotRuntimeOptionsVNext[\"beforeRequestMiddleware\"];\ntype AfterRequestMiddleware =\n CopilotRuntimeOptionsVNext[\"afterRequestMiddleware\"];\ntype BeforeRequestMiddlewareFn = Exclude<BeforeRequestMiddleware, string>;\ntype BeforeRequestMiddlewareFnParameters =\n Parameters<BeforeRequestMiddlewareFn>;\ntype BeforeRequestMiddlewareFnResult = ReturnType<BeforeRequestMiddlewareFn>;\ntype AfterRequestMiddlewareFn = Exclude<AfterRequestMiddleware, string>;\ntype AfterRequestMiddlewareFnParameters = Parameters<AfterRequestMiddlewareFn>;\n\ninterface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []>\n extends\n Omit<CopilotRuntimeConstructorParams_BASE<T>, \"agents\">,\n Omit<CopilotRuntimeOptionsVNext, \"agents\" | \"transcriptionService\"> {\n /**\n * TODO: un-omit `transcriptionService` above once it's supported\n *\n * This satisfies...\n * – the optional constraint in `CopilotRuntimeConstructorParams_BASE`\n * – the `MaybePromise<NonEmptyRecord<T>>` constraint in `CopilotRuntimeOptionsVNext`\n * – the `Record<string, AbstractAgent>` constraint in `both\n */\n agents?: AgentsConfig;\n\n intelligence?: CopilotIntelligenceRuntimeOptions[\"intelligence\"];\n identifyUser?: CopilotIntelligenceRuntimeOptions[\"identifyUser\"];\n memory?: CopilotIntelligenceRuntimeOptions[\"memory\"];\n channels?: CopilotIntelligenceRuntimeOptions[\"channels\"];\n ɵlearning?: CopilotIntelligenceRuntimeOptions[\"ɵlearning\"];\n generateThreadNames?: CopilotIntelligenceRuntimeOptions[\"generateThreadNames\"];\n maxReconnectMs?: CopilotIntelligenceRuntimeOptions[\"maxReconnectMs\"];\n maxRejoinMs?: CopilotIntelligenceRuntimeOptions[\"maxRejoinMs\"];\n lockTtlSeconds?: CopilotIntelligenceRuntimeOptions[\"lockTtlSeconds\"];\n lockKeyPrefix?: CopilotIntelligenceRuntimeOptions[\"lockKeyPrefix\"];\n lockHeartbeatIntervalSeconds?: CopilotIntelligenceRuntimeOptions[\"lockHeartbeatIntervalSeconds\"];\n}\n\n/**\n * Central runtime object passed to all request handlers.\n * @deprecated The v1 SDK is deprecated. Use v2 instead. Use `CopilotRuntime` from `@copilotkit/runtime/v2` instead.\n *\n * ```tsx\n * import { CopilotRuntime } from \"@copilotkit/runtime/v2\";\n *\n * const runtime = new CopilotRuntime({ agents: {} });\n * ```\n * See https://docs.copilotkit.ai/runtime-server-adapter\n */\nexport class CopilotRuntime<const T extends Parameter[] | [] = []> {\n params?: CopilotRuntimeConstructorParams<T>;\n private observability?: CopilotObservabilityConfig;\n /**\n * The request-independent half of agent resolution: validation, and the\n * default agent built from the service adapter. Resolved once, because\n * re-running the misuse checks on every request would turn a configuration\n * error into a per-request throw.\n */\n private baseAgents?: Promise<Record<string, AbstractAgent>>;\n /**\n * The `agents` value as configured, captured before the per-request factory\n * replaces it, so that repeated `handleServiceAdapter` calls do not wrap the\n * factory in itself.\n */\n private configuredAgents?: CopilotRuntimeOptions[\"agents\"];\n private runtimeArgs: CopilotRuntimeOptions & RuntimeErrorReporterOptions;\n private _instance: CopilotRuntimeVNext;\n /** Runtime-bound telemetry identity and sampling authority. */\n public readonly telemetry: TelemetryCapture;\n\n constructor(params?: CopilotRuntimeConstructorParams<T>) {\n logRuntimeTelemetryDisclosure();\n\n const agents = params?.agents ?? {};\n const endpointAgents = this.assignEndpointsToAgents(\n params?.remoteEndpoints ?? [],\n );\n\n // Merge endpoint agents with user-provided agents.\n // When agents is a factory function, wrap it so endpoint agents are merged\n // at resolution time (spreading a function produces {} — silent data loss).\n let mergedAgents: AgentsConfig;\n if (typeof agents === \"function\") {\n mergedAgents = async (ctx) => {\n const resolved = await agents(ctx);\n return { ...endpointAgents, ...resolved };\n };\n } else {\n mergedAgents = Promise.resolve(agents).then((resolved) => ({\n ...endpointAgents,\n ...resolved,\n }));\n }\n\n // Resolve identity once and bind it to this compatibility Runtime. The\n // capture scope shares process-level sinks and settings without exposing\n // mutable identity to other live runtimes.\n const resolvedLicenseToken = firstNonBlankLicenseToken(\n params?.licenseToken,\n process.env.COPILOTKIT_LICENSE_TOKEN,\n );\n const resolvedTelemetryId = firstNonBlankTelemetryId(\n params?.telemetryId,\n process.env.CPK_TELEMETRY_ID,\n );\n const resolvedTelemetryIdentity =\n resolvedTelemetryId !== undefined\n ? { telemetryId: resolvedTelemetryId }\n : resolvedLicenseToken !== undefined\n ? { licenseToken: resolvedLicenseToken }\n : {};\n this.telemetry = telemetry.createScope(resolvedTelemetryIdentity);\n\n // No TelemetryAgentRunner wrap. The V2 SSE path already emits\n // `agent_execution_stream_*` for this runtime, and since it now emits\n // through this entrypoint's scope, wrapping would put two copies of\n // every stream event on the wire. The class stays exported for callers\n // who construct it themselves. The rawEvent enrichment it used to add\n // moved to `v2/runtime/handlers/shared/sse-response.ts`, so nothing is\n // lost and v2 callers gain it too.\n const runner = params?.runner ?? new InMemoryAgentRunner();\n\n const sharedRuntimeArgs = {\n agents: mergedAgents,\n telemetryId: resolvedTelemetryId,\n licenseToken: resolvedLicenseToken,\n // Emit through this entrypoint's own scope rather than letting the\n // delegated V2 runtime build its own. That scope writes to Segment\n // and stamps the v1 surface, so handing it down is what lets the v1\n // middleware below stop emitting the same events a second time.\n ɵtelemetry: this.telemetry,\n telemetryProperties: params?.telemetryProperties,\n debug: params?.debug,\n // TODO: add support for transcriptionService from CopilotRuntimeOptionsVNext once it is ready\n // transcriptionService: params?.transcriptionService,\n\n beforeRequestMiddleware:\n this.createOnBeforeRequestHandler(params).bind(this),\n ...(params?.afterRequestMiddleware || params?.middleware?.onAfterRequest\n ? {\n afterRequestMiddleware:\n this.createOnAfterRequestHandler(params).bind(this),\n }\n : {}),\n a2ui: params?.a2ui,\n mcpApps: params?.mcpApps,\n openGenerativeUI: params?.openGenerativeUI,\n [runtimeErrorReporterOption]: createRuntimeErrorReporter(params?.onError),\n forwardHeaders: params?.forwardHeaders,\n exposeMemoryRoutes: params?.exposeMemoryRoutes,\n };\n if (params?.intelligence !== undefined) {\n // The compatibility constructor keeps Intelligence identity optional at\n // compile time, while the v2 runtime checks that callers supply web\n // identity, Channels, or both. Preserve that runtime validation here.\n this.runtimeArgs = {\n ...sharedRuntimeArgs,\n intelligence: params.intelligence,\n identifyUser: params.identifyUser,\n memory: params.memory,\n channels: params.channels,\n ɵlearning: params.ɵlearning,\n generateThreadNames: params.generateThreadNames,\n maxReconnectMs: params.maxReconnectMs,\n maxRejoinMs: params.maxRejoinMs,\n lockTtlSeconds: params.lockTtlSeconds,\n lockKeyPrefix: params.lockKeyPrefix,\n lockHeartbeatIntervalSeconds: params.lockHeartbeatIntervalSeconds,\n } as CopilotRuntimeOptions;\n } else {\n this.runtimeArgs = {\n ...sharedRuntimeArgs,\n runner,\n };\n }\n this.params = params;\n this.observability = params?.observability_c;\n }\n\n get instance() {\n if (!this._instance) {\n this._instance = new CopilotRuntimeVNext(this.runtimeArgs);\n }\n\n return this._instance;\n }\n\n private assignEndpointsToAgents(\n endpoints: CopilotRuntimeConstructorParams<T>[\"remoteEndpoints\"],\n ): Record<string, AbstractAgent> {\n let result: Record<string, AbstractAgent> = {};\n\n if (\n endpoints.some(\n (endpoint) =>\n resolveEndpointType(endpoint) == EndpointType.LangGraphPlatform,\n )\n ) {\n throw new CopilotKitMisuseError({\n message:\n \"LangGraphPlatformEndpoint in remoteEndpoints is deprecated. \" +\n 'Please use the \"agents\" option instead with LangGraphAgent from \"@copilotkit/runtime/langgraph\". ' +\n 'Example: agents: { myAgent: new LangGraphAgent({ deploymentUrl: \"...\", graphId: \"...\" }) }',\n });\n }\n\n return result;\n }\n\n handleServiceAdapter(serviceAdapter: CopilotServiceAdapter) {\n // Capture the configured value before the factory below replaces it, so a\n // second call does not wrap the factory in itself.\n this.configuredAgents ??= this.runtimeArgs.agents ?? {};\n const configuredAgents = this.configuredAgents;\n\n // Resolve the request-independent half once. Calling this twice (the\n // endpoint factory runs on every request under the documented v1 route)\n // must not re-validate or rebuild the default agent.\n //\n // A caller who supplied their own agents factory has no request-independent\n // half: their record is whatever they return for this request, so the same\n // checks run per request further down.\n if (typeof configuredAgents !== \"function\") {\n this.baseAgents ??= Promise.resolve(configuredAgents).then((agents) =>\n this.ensureDefaultAgent(\n agents as Record<string, AbstractAgent>,\n serviceAdapter,\n ),\n );\n // A misconfigured adapter rejects that promise, and nothing awaits it\n // until the first request arrives. Attach an inert handler so a runtime\n // that is never called does not surface an unhandled rejection; the\n // factory below still sees the rejection when it awaits.\n this.baseAgents.catch(() => {});\n }\n\n // Install the per-request factory the v2 runtime has supported since\n // #2941. Resolving once was what kept a dynamic `actions` function from\n // ever seeing request properties, and kept every request sharing one MCP\n // client regardless of whose credentials built it (#7116, #2407).\n const resolvePerRequest = async ({ request }: { request: Request }) => {\n // A caller-supplied agents factory is called here, with this request.\n // Treating it as a record instead (a function has no enumerable keys)\n // meant the service adapter's default replaced it and the caller's\n // function was never invoked at all.\n const baseAgents =\n typeof configuredAgents === \"function\"\n ? this.ensureDefaultAgent(\n { ...(await configuredAgents({ request })) },\n serviceAdapter,\n )\n : await this.baseAgents!;\n const properties = await this.readRequestProperties(request);\n const actions = this.params?.actions;\n\n // `actions` and `mcpServers` are attached independently: a runtime may\n // configure MCP servers without any local actions.\n const mcpTools = await this.getToolsFromMCP({ properties });\n const actionTools = actions\n ? this.getToolsFromActions(actions, { properties, url: request.url })\n : [];\n const tools = [...actionTools, ...mcpTools];\n\n // Nothing to attach means nothing to isolate: hand the record back\n // untouched, exactly as a runtime with no actions and no MCP behaved\n // before this became a factory.\n if (!tools.length) {\n return baseAgents;\n }\n\n // Clone before attaching. `assignToolsToAgents` writes `config` onto the\n // agent, so mutating the shared instances would let one request's tools\n // reach another request that is already in flight.\n const perRequestAgents: Record<string, AbstractAgent> = {};\n for (const [agentId, agent] of Object.entries(baseAgents)) {\n const clone = agent.clone() as AbstractAgent;\n // `BuiltInAgent.clone()` rebuilds from `this.config`, so its own tools\n // survive. An agent whose `clone()` does not know about `config` --\n // `HttpAgent`, and anything else a v1 user registered -- would arrive\n // here empty, and the tools it declares itself would be shadowed by a\n // v1 action of the same name. Carry the config across when the clone\n // did not.\n if (\n Reflect.get(clone, \"config\") === undefined &&\n Reflect.get(agent, \"config\") !== undefined\n ) {\n Reflect.set(clone, \"config\", Reflect.get(agent, \"config\"));\n }\n perRequestAgents[agentId] = clone;\n }\n\n return this.assignToolsToAgents(perRequestAgents, tools);\n };\n\n this.runtimeArgs.agents =\n resolvePerRequest as unknown as CopilotRuntimeOptions[\"agents\"];\n }\n\n /**\n * Fill in the default agent the service adapter implies, and reject a\n * configuration that names no model at all.\n */\n private ensureDefaultAgent(\n agentsList: Record<string, AbstractAgent>,\n serviceAdapter: CopilotServiceAdapter,\n ): Record<string, AbstractAgent> {\n const isAgentsListEmpty = !Object.keys(agentsList).length;\n const hasServiceAdapter = Boolean(serviceAdapter);\n const illegalServiceAdapterNames = [\"EmptyAdapter\"];\n const serviceAdapterCanBeUsedForAgent =\n !illegalServiceAdapterNames.includes(serviceAdapter.name);\n\n if (\n isAgentsListEmpty &&\n (!hasServiceAdapter || !serviceAdapterCanBeUsedForAgent)\n ) {\n throw new CopilotKitMisuseError({\n message:\n \"No default agent provided. Please provide a default agent in the runtime config.\",\n });\n }\n\n if (isAgentsListEmpty) {\n const languageModel = serviceAdapter.getLanguageModel?.();\n if (languageModel) {\n // Adapter exposes a pre-configured LanguageModel (e.g. OpenAI/Anthropic adapters)\n agentsList.default = new BuiltInAgent({ model: languageModel });\n } else if (serviceAdapter.provider && serviceAdapter.model) {\n // Adapter exposes provider/model strings\n agentsList.default = new BuiltInAgent({\n model: `${serviceAdapter.provider}/${serviceAdapter.model}`,\n });\n } else {\n throw new CopilotKitMisuseError({\n message:\n `Service adapter \"${serviceAdapter.name ?? \"unknown\"}\" does not provide model information. ` +\n `When using adapters like LangChainAdapter without an explicit agents list, ` +\n `please provide a default agent in the runtime config. Example:\\n` +\n ` new CopilotRuntime({\\n` +\n ` agents: { default: new BuiltInAgent({ model: \"openai/gpt-4o\" }) }\\n` +\n ` })`,\n });\n }\n }\n\n return agentsList;\n }\n\n /**\n * The `forwardedProps` the browser sent with this request, which is what a\n * v1 `actions` function and `mcpServers` overrides are documented to read.\n *\n * `readBody` clones, so the handler still gets an unconsumed body, and it\n * returns `undefined` for GET, which is how the `/info` route reaches here.\n */\n private async readRequestProperties(\n request: Request,\n ): Promise<Record<string, unknown>> {\n try {\n const body = (await readBody(request)) as RunAgentInput | undefined;\n const properties = body?.forwardedProps;\n return properties && typeof properties === \"object\"\n ? (properties as Record<string, unknown>)\n : {};\n } catch {\n // A malformed body is the request handler's problem to report, not a\n // reason to fail agent resolution.\n return {};\n }\n }\n\n // Receive this.params.action and turn it into the AbstractAgent tools\n private getToolsFromActions(\n actions: ActionsConfiguration<any>,\n ctx: { properties: Record<string, unknown>; url?: string },\n ): BuiltInAgentClassicConfig[\"tools\"] {\n // Resolve actions to an array (handle function case).\n //\n // The function form is documented to receive the request's properties and\n // url. It was called once at resolution time with `{ properties: {}, url:\n // undefined }`, so a runtime that keyed its action list on the tenant, the\n // user, or anything else request-shaped got the same empty context every\n // time (#7116).\n const actionsArray =\n typeof actions === \"function\"\n ? actions({ properties: ctx.properties, url: ctx.url })\n : actions;\n\n // Convert each Action to a ToolDefinition\n return actionsArray.map((action) => {\n // Convert JSON schema to Zod schema\n const zodSchema = getZodParameters(action.parameters || []);\n\n return {\n name: action.name,\n description: action.description || \"\",\n parameters: zodSchema,\n // `handler` is an in-process function and was never part of the remote\n // executor deleted in v1.50.0 — only the wiring to it was lost. Call it.\n //\n // The result must never be `undefined`: `JSON.stringify(undefined)` is\n // not a string, which strips the required `content` off\n // TOOL_CALL_RESULT and surfaces as a Zod error in the browser\n // (#2915, #3198). Both branches below return a string instead.\n execute: async (args: unknown) => {\n if (typeof action.handler !== \"function\") {\n return (\n `The tool \"${action.name}\" was advertised without a handler, so it ` +\n `has no implementation to run. Tell the user this tool is unavailable.`\n );\n }\n const result = await action.handler(args as any);\n return result === undefined\n ? `The tool \"${action.name}\" ran and returned no value.`\n : result;\n },\n };\n });\n }\n\n private assignToolsToAgents(\n agents: Record<string, AbstractAgent>,\n tools: BuiltInAgentClassicConfig[\"tools\"],\n ): Record<string, AbstractAgent> {\n if (!tools?.length) {\n return agents;\n }\n\n const enrichedAgents: Record<string, AbstractAgent> = { ...agents };\n\n for (const [agentId, agent] of Object.entries(enrichedAgents)) {\n const existingConfig = (Reflect.get(agent, \"config\") ?? {}) as Record<\n string,\n unknown\n >;\n\n // Skip factory-mode agents — they don't have a tools property\n if (\"factory\" in existingConfig) {\n continue;\n }\n\n const classicConfig =\n existingConfig as unknown as BuiltInAgentClassicConfig;\n const existingTools = classicConfig.tools ?? [];\n\n // The endpoint factory runs `handleServiceAdapter` every time it is\n // called, and the documented v1 route builds the endpoint inside the\n // request handler — so a module-scope runtime lands here once per\n // request. Appending unconditionally advertised N copies of every tool\n // to the model. Skip names the agent already carries, which also leaves\n // a tool the agent defines itself in place.\n const existingNames = new Set(existingTools.map((tool) => tool.name));\n const newTools = tools.filter((tool) => !existingNames.has(tool.name));\n if (newTools.length === 0) {\n continue;\n }\n\n const updatedConfig: BuiltInAgentClassicConfig = {\n ...classicConfig,\n tools: [...existingTools, ...newTools],\n };\n\n Reflect.set(agent, \"config\", updatedConfig);\n enrichedAgents[agentId] = agent;\n }\n\n return enrichedAgents;\n }\n\n private createOnBeforeRequestHandler(\n params?: CopilotRuntimeConstructorParams<T> &\n PartialBy<CopilotRuntimeOptions, \"agents\">,\n ) {\n return async (hookParams: BeforeRequestMiddlewareFnParameters[0]) => {\n const { request } = hookParams;\n\n // No `copilot_request_created` capture here. The V2 handlers this\n // runtime delegates to already emit it, through this runtime's own\n // scope, and they know the route — so `requestType` is \"run\" or\n // \"connect\" rather than the \"unknown\" this site reported for every\n // request that did not set `forwardedProps.metadata.requestType`.\n const body = (await readBody(request)) as RunAgentInput;\n\n // We do not process middleware for the internal GET requests\n if (request.method === \"GET\" || !body) return;\n\n // TODO: get public api key and run with expected data\n // if (this.observability?.enabled && this.params.publicApiKey) {\n // this.logObservabilityBeforeRequest()\n // }\n\n // TODO: replace hooksParams top argument type with BeforeRequestMiddlewareParameters when exported\n const middlewareResult =\n await params?.beforeRequestMiddleware?.(hookParams);\n\n if (params?.middleware?.onBeforeRequest) {\n const { request, runtime, path } = hookParams;\n const gqlMessages = (aguiToGQL(body.messages) as Message[]).reduce(\n (acc, msg) => {\n if (\"role\" in msg && msg.role === \"user\") {\n acc.inputMessages.push(msg);\n } else {\n acc.outputMessages.push(msg);\n }\n return acc;\n },\n { inputMessages: [] as Message[], outputMessages: [] as Message[] },\n );\n const { inputMessages, outputMessages } = gqlMessages;\n params.middleware.onBeforeRequest({\n threadId: body.threadId,\n runId: body.runId,\n inputMessages,\n properties: body.forwardedProps,\n url: request.url,\n } satisfies OnBeforeRequestOptions);\n }\n\n return middlewareResult;\n };\n }\n\n private createOnAfterRequestHandler(\n params?: CopilotRuntimeConstructorParams<T> &\n PartialBy<CopilotRuntimeOptions, \"agents\">,\n ) {\n return async (hookParams: AfterRequestMiddlewareFnParameters[0]) => {\n // TODO: get public api key and run with expected data\n // if (this.observability?.enabled && publicApiKey) {\n // this.logObservabilityAfterRequest()\n // }\n\n // TODO: replace hooksParams top argument type with AfterRequestMiddlewareParameters when exported\n params?.afterRequestMiddleware?.(hookParams);\n\n if (params?.middleware?.onAfterRequest) {\n const messages = hookParams.messages ?? [];\n params.middleware.onAfterRequest({\n threadId: hookParams.threadId ?? \"\",\n runId: hookParams.runId,\n inputMessages: messages.filter(\n (m): m is typeof m & { role: string } =>\n \"role\" in m && m.role === \"user\",\n ) as unknown as Message[],\n outputMessages: messages.filter(\n (m): m is typeof m & { role: string } =>\n \"role\" in m && m.role !== \"user\",\n ) as unknown as Message[],\n // TODO: forward actual properties once the after-request hook has access to the request body\n properties: {},\n url: hookParams.path,\n } satisfies OnAfterRequestOptions);\n }\n };\n }\n\n // Observability Methods\n\n /**\n * Log LLM request if observability is enabled\n */\n private async logObservabilityBeforeRequest(\n requestData: LLMRequestData,\n ): Promise<void> {\n try {\n await this.observability.hooks.handleRequest(requestData);\n } catch (error) {\n console.error(\"Error logging LLM request:\", error);\n }\n }\n\n /**\n * Log final LLM response after request completes\n */\n private logObservabilityAfterRequest(\n outputMessagesPromise: Promise<Message[]>,\n baseData: {\n threadId: string;\n runId?: string;\n model?: string;\n provider?: string;\n agentName?: string;\n nodeName?: string;\n },\n streamedChunks: any[],\n requestStartTime: number,\n publicApiKey?: string,\n ): void {\n try {\n outputMessagesPromise\n .then((outputMessages) => {\n const responseData: LLMResponseData = {\n threadId: baseData.threadId,\n runId: baseData.runId,\n model: baseData.model,\n // Use collected chunks for progressive mode or outputMessages for regular mode\n output: this.observability.progressive\n ? streamedChunks\n : outputMessages,\n latency: Date.now() - requestStartTime,\n timestamp: Date.now(),\n provider: baseData.provider,\n isFinalResponse: true,\n agentName: baseData.agentName,\n nodeName: baseData.nodeName,\n };\n\n try {\n this.observability.hooks.handleResponse(responseData);\n } catch (logError) {\n console.error(\"Error logging LLM response:\", logError);\n }\n })\n .catch((error) => {\n console.error(\"Failed to get output messages for logging:\", error);\n });\n } catch (error) {\n console.error(\"Error setting up logging for LLM response:\", error);\n }\n }\n\n // Resolve MCP tools to BuiltInAgent tool definitions\n // Optionally accepts request-scoped properties to merge request-provided mcpServers\n private async getToolsFromMCP(options?: {\n properties?: Record<string, unknown>;\n }): Promise<BuiltInAgentClassicConfig[\"tools\"]> {\n const runtimeMcpServers = (this.params?.mcpServers ??\n []) as MCPEndpointConfig[];\n const createMCPClient = this.params?.createMCPClient as\n | CreateMCPClientFunction\n | undefined;\n\n // If no runtime config and no request overrides, nothing to do\n const requestMcpServers = ((\n options?.properties as { mcpServers?: MCPEndpointConfig[] } | undefined\n )?.mcpServers ??\n (\n options?.properties as\n | { mcpEndpoints?: MCPEndpointConfig[] }\n | undefined\n )?.mcpEndpoints ??\n []) as MCPEndpointConfig[];\n\n const hasAnyServers =\n (runtimeMcpServers?.length ?? 0) > 0 ||\n (requestMcpServers?.length ?? 0) > 0;\n if (!hasAnyServers) {\n return [];\n }\n\n if (!createMCPClient) {\n // Mirror legacy behavior: when servers are provided without a factory, treat as misconfiguration\n throw new CopilotKitMisuseError({\n message:\n \"MCP Integration Error: `mcpServers` were provided, but the `createMCPClient` function was not passed to the CopilotRuntime constructor. Please provide an implementation for `createMCPClient`.\",\n });\n }\n\n // Merge and dedupe endpoints by URL; request-level overrides take precedence.\n //\n // `requestMcpServers` is caller-supplied: it arrives in `forwardedProps`\n // from the browser. Validating it here is not this shim's call — the\n // endpoint shape, the transport, and the auth all belong to the\n // application's `createMCPClient`, and a hardcoded allowlist would break\n // the multi-tenant case this per-request path exists to serve. The\n // constraint is documented on `mcpServers` instead: a deployment that does\n // not intend browser-chosen servers has to reject them in its factory.\n const effectiveEndpoints = (() => {\n const byUrl = new Map<string, MCPEndpointConfig>();\n for (const ep of runtimeMcpServers) {\n if (ep?.endpoint) byUrl.set(ep.endpoint, ep);\n }\n for (const ep of requestMcpServers) {\n if (ep?.endpoint) byUrl.set(ep.endpoint, ep);\n }\n return Array.from(byUrl.values());\n })();\n\n const allTools: BuiltInAgentClassicConfig[\"tools\"] = [];\n\n for (const config of effectiveEndpoints) {\n // Everything that leaves this process with the endpoint in it uses the\n // redacted form: the raw URL's query can carry the credential, which is\n // exactly what the #2407 workaround puts there.\n const endpointLabel = describeEndpoint(config.endpoint);\n\n try {\n // Keyed by the client factory plus the whole config, so two callers\n // with different credentials for one endpoint get one client each.\n // Keying on the URL alone is #2407: the first caller's client served\n // everyone, and the reporter's `?uid=<hash>` workaround existed only\n // to force distinct keys.\n const entry = await resolveMCPEntry<BuiltInAgentClassicConfig[\"tools\"]>(\n createMCPClient,\n config,\n async () => {\n const client = await createMCPClient(config);\n const toolsMap = await client.tools();\n\n const toolDefs: BuiltInAgentClassicConfig[\"tools\"] = Object.entries(\n toolsMap,\n ).map(([toolName, tool]: [string, MCPTool]) => {\n const params: Parameter[] = extractParametersFromSchema(tool);\n const zodSchema = getZodParameters(params);\n return {\n name: toolName,\n description:\n tool.description ||\n `MCP tool: ${toolName} (from ${endpointLabel})`,\n parameters: zodSchema,\n // `tool.execute` calls the server over the cached client. That\n // client outlives this request but not necessarily this tool\n // definition: eviction can close it while these defs are still\n // held by an already-resolved agent.\n execute: async (args: unknown) => {\n // Executing is the only evidence this runtime gets that a\n // connection is still in use. Without it the entry ages from\n // the moment the agent resolved, and a busy process evicts\n // and closes a client that a live run is still calling.\n touchMCPEntry(createMCPClient, config);\n return tool.execute(args);\n },\n };\n });\n\n return { client, tools: toolDefs };\n },\n );\n\n allTools.push(...(entry.tools ?? []));\n } catch (error) {\n console.error(\n `MCP: Failed to fetch tools from endpoint ${endpointLabel}. Skipping. Error:`,\n error,\n );\n // Deliberately not cached. Caching the empty result meant a server\n // that was briefly unreachable when the runtime first resolved stayed\n // toolless for the life of that runtime, even after it recovered.\n // `resolveMCPEntry` drops a rejected entry so a later request retries.\n }\n }\n\n // Dedupe tools by name while preserving last-in wins (request overrides)\n const dedupedByName = new Map<string, (typeof allTools)[number]>();\n for (const tool of allTools) {\n dedupedByName.set(tool.name, tool);\n }\n\n return Array.from(dedupedByName.values());\n }\n}\n\n// The two functions below are \"factory functions\", meant to create the action objects that adhere to the expected interfaces\nexport function copilotKitEndpoint(\n config: Omit<CopilotKitEndpoint, \"type\">,\n): CopilotKitEndpoint {\n return {\n ...config,\n type: EndpointType.CopilotKit,\n };\n}\n\nexport function langGraphPlatformEndpoint(\n config: Omit<LangGraphPlatformEndpoint, \"type\">,\n): LangGraphPlatformEndpoint {\n return {\n ...config,\n type: EndpointType.LangGraphPlatform,\n };\n}\n\nexport function resolveEndpointType(endpoint: EndpointDefinition) {\n if (!endpoint.type) {\n if (\"deploymentUrl\" in endpoint && \"agents\" in endpoint) {\n return EndpointType.LangGraphPlatform;\n } else {\n return EndpointType.CopilotKit;\n }\n }\n\n return endpoint.type;\n}\n"],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ require("reflect-metadata");
2
+
3
+ //#region src/v1-deprecated/lib/runtime/mcp-client-cache.ts
4
+ /**
5
+ * Cap on live MCP connections. Reached only by runtimes whose endpoint config
6
+ * varies per request — a static `mcpServers` list occupies one slot per
7
+ * server for the life of the process.
8
+ */
9
+ const MAX_ENTRIES = 100;
10
+ const cache = /* @__PURE__ */ new Map();
11
+ /**
12
+ * A form of the endpoint that is safe to write to application logs.
13
+ *
14
+ * Both halves of an endpoint URL can carry a secret: userinfo, and the query
15
+ * string — the #2407 reporter's own workaround appended `?uid=<hash of the
16
+ * API key>`. Only the origin and path survive.
17
+ *
18
+ * Used for anything that leaves this process with an endpoint in it: log
19
+ * lines, and the tool descriptions that go to the model provider.
20
+ */
21
+ function describeEndpoint(endpoint) {
22
+ if (!endpoint) return "an MCP endpoint";
23
+ try {
24
+ const url = new URL(endpoint);
25
+ return `${url.protocol}//${url.host}${url.pathname}`;
26
+ } catch {
27
+ return "an MCP endpoint";
28
+ }
29
+ }
30
+ /**
31
+ * Identity for a `createMCPClient` implementation.
32
+ *
33
+ * Two runtimes that pass the same factory may share a connection. Two that
34
+ * pass different factories must not: the second runtime's factory could wrap
35
+ * the transport, add auth, or point somewhere else entirely, and handing it a
36
+ * client built by the first would silently bypass all of that.
37
+ */
38
+ const factoryIds = /* @__PURE__ */ new WeakMap();
39
+ let nextFactoryId = 0;
40
+ function factoryId(factory) {
41
+ let id = factoryIds.get(factory);
42
+ if (!id) {
43
+ id = `f${++nextFactoryId}`;
44
+ factoryIds.set(factory, id);
45
+ }
46
+ return id;
47
+ }
48
+ /**
49
+ * Deterministic serialization of an endpoint config, so that two configs that
50
+ * differ only in key order produce one cache entry, and two that differ in
51
+ * `apiKey` produce two.
52
+ */
53
+ function stableStringify(value) {
54
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
55
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
56
+ return `{${Object.entries(value).filter(([, v]) => typeof v !== "function" && v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
57
+ }
58
+ function mcpCacheKey(createMCPClient, config) {
59
+ return `${factoryId(createMCPClient)}::${stableStringify(config)}`;
60
+ }
61
+ async function closeQuietly(client, label) {
62
+ try {
63
+ await client.close?.();
64
+ } catch (error) {
65
+ console.error(`MCP: Failed to close the client for ${label}:`, error);
66
+ }
67
+ }
68
+ /** Drop the least recently used entries until the cache is within its cap. */
69
+ async function evictDownToCap() {
70
+ while (cache.size > MAX_ENTRIES) {
71
+ const oldestKey = cache.keys().next().value;
72
+ if (oldestKey === void 0) return;
73
+ const evicted = cache.get(oldestKey);
74
+ cache.delete(oldestKey);
75
+ if (!evicted) continue;
76
+ try {
77
+ const entry = await evicted.entry;
78
+ if (entry) await closeQuietly(entry.client, evicted.label);
79
+ } catch {}
80
+ }
81
+ }
82
+ /**
83
+ * Return the cached connection for this factory and config, creating it on
84
+ * first use.
85
+ *
86
+ * A rejected creation is removed rather than cached, so a server that was
87
+ * briefly unreachable is retried on the next request instead of staying
88
+ * toolless for the life of the process.
89
+ */
90
+ function resolveMCPEntry(createMCPClient, config, build) {
91
+ const key = mcpCacheKey(createMCPClient, config);
92
+ const hit = cache.get(key);
93
+ if (hit) {
94
+ cache.delete(key);
95
+ cache.set(key, hit);
96
+ return hit.entry;
97
+ }
98
+ const slot = {
99
+ label: describeEndpoint(config?.endpoint),
100
+ entry: void 0
101
+ };
102
+ const created = build().catch((error) => {
103
+ if (cache.get(key) === slot) cache.delete(key);
104
+ throw error;
105
+ });
106
+ slot.entry = created;
107
+ cache.set(key, slot);
108
+ evictDownToCap();
109
+ return created;
110
+ }
111
+ /**
112
+ * Mark an entry as recently used.
113
+ *
114
+ * Without this, an entry's position is set once, when the agent resolves, and
115
+ * a run that is actively calling tools still ages toward eviction — so a busy
116
+ * process can close a connection out from under a live run. Tool execution is
117
+ * the only signal available that a connection is still wanted: the v1 runtime
118
+ * has no reliable end-of-run hook to lease against (an abandoned SSE run never
119
+ * fires one), so a lease taken at resolution could never be released.
120
+ *
121
+ * A no-op when the key is gone, which is the already-evicted case.
122
+ */
123
+ function touchMCPEntry(createMCPClient, config) {
124
+ const key = mcpCacheKey(createMCPClient, config);
125
+ const slot = cache.get(key);
126
+ if (!slot) return;
127
+ cache.delete(key);
128
+ cache.set(key, slot);
129
+ }
130
+
131
+ //#endregion
132
+ exports.describeEndpoint = describeEndpoint;
133
+ exports.resolveMCPEntry = resolveMCPEntry;
134
+ exports.touchMCPEntry = touchMCPEntry;
135
+ //# sourceMappingURL=mcp-client-cache.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client-cache.cjs","names":[],"sources":["../../../../src/v1-deprecated/lib/runtime/mcp-client-cache.ts"],"sourcesContent":["/*\n * V1 SDK DEPRECATED. USE V2 INSTEAD\n *\n * Internal helper for the v1 CopilotRuntime shim. Not exported from the\n * package. The v2 path builds its MCP clients per run in `agent/index.ts`.\n *\n * END V1 SDK DEPRECATED. USE V2 INSTEAD NOTICE\n */\n\nimport type { MCPClient, MCPEndpointConfig } from \"./mcp-tools-utils\";\n\n/**\n * One cached MCP connection and the tool definitions built from it.\n *\n * The tool definitions close over `tool.execute` on this exact client, so the\n * two share a lifetime: dropping the entry has to close the client, and\n * closing the client has to drop the tools.\n */\nexport interface MCPCacheEntry<TTools> {\n client: MCPClient;\n tools: TTools;\n}\n\n/**\n * Cap on live MCP connections. Reached only by runtimes whose endpoint config\n * varies per request — a static `mcpServers` list occupies one slot per\n * server for the life of the process.\n */\nconst MAX_ENTRIES = 100;\n\n/**\n * Process-wide, not per runtime instance.\n *\n * The documented per-request pattern builds `new CopilotRuntime(...)` inside\n * the request handler, so a cache owned by the instance is a fresh cache on\n * every request: one connection per HTTP request, never closed. Keying the\n * cache on the client factory plus the endpoint config instead means those\n * runtimes share the connection they would otherwise re-open, and the entry\n * count is bounded by the number of distinct credentials in play rather than\n * by traffic.\n *\n * The slot carries a redacted endpoint label beside the connection. The cache\n * *key* cannot be used for that: it contains the serialized config, and the\n * config contains `apiKey`.\n */\ninterface MCPCacheSlot {\n /** Safe to log. See `describeEndpoint`. */\n label: string;\n entry: Promise<MCPCacheEntry<unknown>>;\n}\n\nconst cache = new Map<string, MCPCacheSlot>();\n\n/**\n * A form of the endpoint that is safe to write to application logs.\n *\n * Both halves of an endpoint URL can carry a secret: userinfo, and the query\n * string — the #2407 reporter's own workaround appended `?uid=<hash of the\n * API key>`. Only the origin and path survive.\n *\n * Used for anything that leaves this process with an endpoint in it: log\n * lines, and the tool descriptions that go to the model provider.\n */\nexport function describeEndpoint(endpoint: string | undefined): string {\n if (!endpoint) return \"an MCP endpoint\";\n try {\n const url = new URL(endpoint);\n // Not `url.origin`: for any scheme other than http(s) that is the opaque\n // origin, the literal string \"null\", and `pathname` is empty — so a\n // `stdio://` endpoint would render as \"null\" in a log and in a prompt.\n // Rebuilding from protocol and host keeps every scheme legible while\n // still dropping userinfo, query, and fragment.\n return `${url.protocol}//${url.host}${url.pathname}`;\n } catch {\n return \"an MCP endpoint\";\n }\n}\n\n/**\n * Identity for a `createMCPClient` implementation.\n *\n * Two runtimes that pass the same factory may share a connection. Two that\n * pass different factories must not: the second runtime's factory could wrap\n * the transport, add auth, or point somewhere else entirely, and handing it a\n * client built by the first would silently bypass all of that.\n */\nconst factoryIds = new WeakMap<object, string>();\nlet nextFactoryId = 0;\n\nfunction factoryId(factory: object): string {\n let id = factoryIds.get(factory);\n if (!id) {\n id = `f${++nextFactoryId}`;\n factoryIds.set(factory, id);\n }\n return id;\n}\n\n/**\n * Deterministic serialization of an endpoint config, so that two configs that\n * differ only in key order produce one cache entry, and two that differ in\n * `apiKey` produce two.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value) ?? \"null\";\n }\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => typeof v !== \"function\" && v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`);\n return `{${entries.join(\",\")}}`;\n}\n\nexport function mcpCacheKey(\n createMCPClient: object,\n config: MCPEndpointConfig,\n): string {\n return `${factoryId(createMCPClient)}::${stableStringify(config)}`;\n}\n\nasync function closeQuietly(client: MCPClient, label: string) {\n try {\n await client.close?.();\n } catch (error) {\n console.error(`MCP: Failed to close the client for ${label}:`, error);\n }\n}\n\n/** Drop the least recently used entries until the cache is within its cap. */\nasync function evictDownToCap() {\n while (cache.size > MAX_ENTRIES) {\n const oldestKey = cache.keys().next().value as string | undefined;\n if (oldestKey === undefined) return;\n const evicted = cache.get(oldestKey);\n cache.delete(oldestKey);\n if (!evicted) continue;\n try {\n const entry = await evicted.entry;\n if (entry) await closeQuietly(entry.client, evicted.label);\n } catch {\n // A rejected entry has nothing to close.\n }\n }\n}\n\n/**\n * Return the cached connection for this factory and config, creating it on\n * first use.\n *\n * A rejected creation is removed rather than cached, so a server that was\n * briefly unreachable is retried on the next request instead of staying\n * toolless for the life of the process.\n */\nexport function resolveMCPEntry<TTools>(\n createMCPClient: object,\n config: MCPEndpointConfig,\n build: () => Promise<MCPCacheEntry<TTools>>,\n): Promise<MCPCacheEntry<TTools>> {\n const key = mcpCacheKey(createMCPClient, config);\n const hit = cache.get(key);\n if (hit) {\n // Re-insert so that Map iteration order stays least-recently-used first.\n cache.delete(key);\n cache.set(key, hit);\n return hit.entry as Promise<MCPCacheEntry<TTools>>;\n }\n\n const slot: MCPCacheSlot = {\n label: describeEndpoint(config?.endpoint),\n // Assigned below; `build()` cannot run before the slot exists, because the\n // rejection handler compares against it.\n entry: undefined as unknown as Promise<MCPCacheEntry<unknown>>,\n };\n\n const created = build().catch((error: unknown) => {\n // Only drop our own slot. Eviction can remove this key while `build()` is\n // still in flight, and a later request can insert a replacement under it;\n // an unconditional delete would evict that replacement and leave its\n // client live but outside cache cleanup, which is the leak this file\n // exists to prevent.\n if (cache.get(key) === slot) {\n cache.delete(key);\n }\n throw error;\n });\n\n slot.entry = created as Promise<MCPCacheEntry<unknown>>;\n cache.set(key, slot);\n void evictDownToCap();\n return created;\n}\n\n/**\n * Mark an entry as recently used.\n *\n * Without this, an entry's position is set once, when the agent resolves, and\n * a run that is actively calling tools still ages toward eviction — so a busy\n * process can close a connection out from under a live run. Tool execution is\n * the only signal available that a connection is still wanted: the v1 runtime\n * has no reliable end-of-run hook to lease against (an abandoned SSE run never\n * fires one), so a lease taken at resolution could never be released.\n *\n * A no-op when the key is gone, which is the already-evicted case.\n */\nexport function touchMCPEntry(\n createMCPClient: object,\n config: MCPEndpointConfig,\n): void {\n const key = mcpCacheKey(createMCPClient, config);\n const slot = cache.get(key);\n if (!slot) return;\n cache.delete(key);\n cache.set(key, slot);\n}\n\n/** Test seam: close and forget every cached connection. */\nexport async function __resetMCPClientCache() {\n const slots = Array.from(cache.values());\n cache.clear();\n await Promise.all(\n slots.map(async (slot) => {\n try {\n const entry = await slot.entry;\n await closeQuietly(entry.client, slot.label);\n } catch {\n // Nothing to close.\n }\n }),\n );\n}\n\n/** Test seam: how many connections are live. */\nexport function __mcpClientCacheSize() {\n return cache.size;\n}\n"],"mappings":";;;;;;;;AA4BA,MAAM,cAAc;AAuBpB,MAAM,wBAAQ,IAAI,KAA2B;;;;;;;;;;;AAY7C,SAAgB,iBAAiB,UAAsC;AACrE,KAAI,CAAC,SAAU,QAAO;AACtB,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,SAAS;AAM7B,SAAO,GAAG,IAAI,SAAS,IAAI,IAAI,OAAO,IAAI;SACpC;AACN,SAAO;;;;;;;;;;;AAYX,MAAM,6BAAa,IAAI,SAAyB;AAChD,IAAI,gBAAgB;AAEpB,SAAS,UAAU,SAAyB;CAC1C,IAAI,KAAK,WAAW,IAAI,QAAQ;AAChC,KAAI,CAAC,IAAI;AACP,OAAK,IAAI,EAAE;AACX,aAAW,IAAI,SAAS,GAAG;;AAE7B,QAAO;;;;;;;AAQT,SAAS,gBAAgB,OAAwB;AAC/C,KAAI,UAAU,QAAQ,OAAO,UAAU,SACrC,QAAO,KAAK,UAAU,MAAM,IAAI;AAElC,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,IAAI,MAAM,IAAI,gBAAgB,CAAC,KAAK,IAAI,CAAC;AAMlD,QAAO,IAJS,OAAO,QAAQ,MAAiC,CAC7D,QAAQ,GAAG,OAAO,OAAO,MAAM,cAAc,MAAM,OAAU,CAC7D,MAAM,CAAC,IAAI,CAAC,OAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,EAAG,CAChD,KAAK,CAAC,GAAG,OAAO,GAAG,KAAK,UAAU,EAAE,CAAC,GAAG,gBAAgB,EAAE,GAAG,CAC7C,KAAK,IAAI,CAAC;;AAG/B,SAAgB,YACd,iBACA,QACQ;AACR,QAAO,GAAG,UAAU,gBAAgB,CAAC,IAAI,gBAAgB,OAAO;;AAGlE,eAAe,aAAa,QAAmB,OAAe;AAC5D,KAAI;AACF,QAAM,OAAO,SAAS;UACf,OAAO;AACd,UAAQ,MAAM,uCAAuC,MAAM,IAAI,MAAM;;;;AAKzE,eAAe,iBAAiB;AAC9B,QAAO,MAAM,OAAO,aAAa;EAC/B,MAAM,YAAY,MAAM,MAAM,CAAC,MAAM,CAAC;AACtC,MAAI,cAAc,OAAW;EAC7B,MAAM,UAAU,MAAM,IAAI,UAAU;AACpC,QAAM,OAAO,UAAU;AACvB,MAAI,CAAC,QAAS;AACd,MAAI;GACF,MAAM,QAAQ,MAAM,QAAQ;AAC5B,OAAI,MAAO,OAAM,aAAa,MAAM,QAAQ,QAAQ,MAAM;UACpD;;;;;;;;;;;AAcZ,SAAgB,gBACd,iBACA,QACA,OACgC;CAChC,MAAM,MAAM,YAAY,iBAAiB,OAAO;CAChD,MAAM,MAAM,MAAM,IAAI,IAAI;AAC1B,KAAI,KAAK;AAEP,QAAM,OAAO,IAAI;AACjB,QAAM,IAAI,KAAK,IAAI;AACnB,SAAO,IAAI;;CAGb,MAAM,OAAqB;EACzB,OAAO,iBAAiB,QAAQ,SAAS;EAGzC,OAAO;EACR;CAED,MAAM,UAAU,OAAO,CAAC,OAAO,UAAmB;AAMhD,MAAI,MAAM,IAAI,IAAI,KAAK,KACrB,OAAM,OAAO,IAAI;AAEnB,QAAM;GACN;AAEF,MAAK,QAAQ;AACb,OAAM,IAAI,KAAK,KAAK;AACpB,CAAK,gBAAgB;AACrB,QAAO;;;;;;;;;;;;;;AAeT,SAAgB,cACd,iBACA,QACM;CACN,MAAM,MAAM,YAAY,iBAAiB,OAAO;CAChD,MAAM,OAAO,MAAM,IAAI,IAAI;AAC3B,KAAI,CAAC,KAAM;AACX,OAAM,OAAO,IAAI;AACjB,OAAM,IAAI,KAAK,KAAK"}
@@ -0,0 +1,132 @@
1
+ import "reflect-metadata";
2
+ //#region src/v1-deprecated/lib/runtime/mcp-client-cache.ts
3
+ /**
4
+ * Cap on live MCP connections. Reached only by runtimes whose endpoint config
5
+ * varies per request — a static `mcpServers` list occupies one slot per
6
+ * server for the life of the process.
7
+ */
8
+ const MAX_ENTRIES = 100;
9
+ const cache = /* @__PURE__ */ new Map();
10
+ /**
11
+ * A form of the endpoint that is safe to write to application logs.
12
+ *
13
+ * Both halves of an endpoint URL can carry a secret: userinfo, and the query
14
+ * string — the #2407 reporter's own workaround appended `?uid=<hash of the
15
+ * API key>`. Only the origin and path survive.
16
+ *
17
+ * Used for anything that leaves this process with an endpoint in it: log
18
+ * lines, and the tool descriptions that go to the model provider.
19
+ */
20
+ function describeEndpoint(endpoint) {
21
+ if (!endpoint) return "an MCP endpoint";
22
+ try {
23
+ const url = new URL(endpoint);
24
+ return `${url.protocol}//${url.host}${url.pathname}`;
25
+ } catch {
26
+ return "an MCP endpoint";
27
+ }
28
+ }
29
+ /**
30
+ * Identity for a `createMCPClient` implementation.
31
+ *
32
+ * Two runtimes that pass the same factory may share a connection. Two that
33
+ * pass different factories must not: the second runtime's factory could wrap
34
+ * the transport, add auth, or point somewhere else entirely, and handing it a
35
+ * client built by the first would silently bypass all of that.
36
+ */
37
+ const factoryIds = /* @__PURE__ */ new WeakMap();
38
+ let nextFactoryId = 0;
39
+ function factoryId(factory) {
40
+ let id = factoryIds.get(factory);
41
+ if (!id) {
42
+ id = `f${++nextFactoryId}`;
43
+ factoryIds.set(factory, id);
44
+ }
45
+ return id;
46
+ }
47
+ /**
48
+ * Deterministic serialization of an endpoint config, so that two configs that
49
+ * differ only in key order produce one cache entry, and two that differ in
50
+ * `apiKey` produce two.
51
+ */
52
+ function stableStringify(value) {
53
+ if (value === null || typeof value !== "object") return JSON.stringify(value) ?? "null";
54
+ if (Array.isArray(value)) return `[${value.map(stableStringify).join(",")}]`;
55
+ return `{${Object.entries(value).filter(([, v]) => typeof v !== "function" && v !== void 0).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`).join(",")}}`;
56
+ }
57
+ function mcpCacheKey(createMCPClient, config) {
58
+ return `${factoryId(createMCPClient)}::${stableStringify(config)}`;
59
+ }
60
+ async function closeQuietly(client, label) {
61
+ try {
62
+ await client.close?.();
63
+ } catch (error) {
64
+ console.error(`MCP: Failed to close the client for ${label}:`, error);
65
+ }
66
+ }
67
+ /** Drop the least recently used entries until the cache is within its cap. */
68
+ async function evictDownToCap() {
69
+ while (cache.size > MAX_ENTRIES) {
70
+ const oldestKey = cache.keys().next().value;
71
+ if (oldestKey === void 0) return;
72
+ const evicted = cache.get(oldestKey);
73
+ cache.delete(oldestKey);
74
+ if (!evicted) continue;
75
+ try {
76
+ const entry = await evicted.entry;
77
+ if (entry) await closeQuietly(entry.client, evicted.label);
78
+ } catch {}
79
+ }
80
+ }
81
+ /**
82
+ * Return the cached connection for this factory and config, creating it on
83
+ * first use.
84
+ *
85
+ * A rejected creation is removed rather than cached, so a server that was
86
+ * briefly unreachable is retried on the next request instead of staying
87
+ * toolless for the life of the process.
88
+ */
89
+ function resolveMCPEntry(createMCPClient, config, build) {
90
+ const key = mcpCacheKey(createMCPClient, config);
91
+ const hit = cache.get(key);
92
+ if (hit) {
93
+ cache.delete(key);
94
+ cache.set(key, hit);
95
+ return hit.entry;
96
+ }
97
+ const slot = {
98
+ label: describeEndpoint(config?.endpoint),
99
+ entry: void 0
100
+ };
101
+ const created = build().catch((error) => {
102
+ if (cache.get(key) === slot) cache.delete(key);
103
+ throw error;
104
+ });
105
+ slot.entry = created;
106
+ cache.set(key, slot);
107
+ evictDownToCap();
108
+ return created;
109
+ }
110
+ /**
111
+ * Mark an entry as recently used.
112
+ *
113
+ * Without this, an entry's position is set once, when the agent resolves, and
114
+ * a run that is actively calling tools still ages toward eviction — so a busy
115
+ * process can close a connection out from under a live run. Tool execution is
116
+ * the only signal available that a connection is still wanted: the v1 runtime
117
+ * has no reliable end-of-run hook to lease against (an abandoned SSE run never
118
+ * fires one), so a lease taken at resolution could never be released.
119
+ *
120
+ * A no-op when the key is gone, which is the already-evicted case.
121
+ */
122
+ function touchMCPEntry(createMCPClient, config) {
123
+ const key = mcpCacheKey(createMCPClient, config);
124
+ const slot = cache.get(key);
125
+ if (!slot) return;
126
+ cache.delete(key);
127
+ cache.set(key, slot);
128
+ }
129
+
130
+ //#endregion
131
+ export { describeEndpoint, resolveMCPEntry, touchMCPEntry };
132
+ //# sourceMappingURL=mcp-client-cache.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mcp-client-cache.mjs","names":[],"sources":["../../../../src/v1-deprecated/lib/runtime/mcp-client-cache.ts"],"sourcesContent":["/*\n * V1 SDK DEPRECATED. USE V2 INSTEAD\n *\n * Internal helper for the v1 CopilotRuntime shim. Not exported from the\n * package. The v2 path builds its MCP clients per run in `agent/index.ts`.\n *\n * END V1 SDK DEPRECATED. USE V2 INSTEAD NOTICE\n */\n\nimport type { MCPClient, MCPEndpointConfig } from \"./mcp-tools-utils\";\n\n/**\n * One cached MCP connection and the tool definitions built from it.\n *\n * The tool definitions close over `tool.execute` on this exact client, so the\n * two share a lifetime: dropping the entry has to close the client, and\n * closing the client has to drop the tools.\n */\nexport interface MCPCacheEntry<TTools> {\n client: MCPClient;\n tools: TTools;\n}\n\n/**\n * Cap on live MCP connections. Reached only by runtimes whose endpoint config\n * varies per request — a static `mcpServers` list occupies one slot per\n * server for the life of the process.\n */\nconst MAX_ENTRIES = 100;\n\n/**\n * Process-wide, not per runtime instance.\n *\n * The documented per-request pattern builds `new CopilotRuntime(...)` inside\n * the request handler, so a cache owned by the instance is a fresh cache on\n * every request: one connection per HTTP request, never closed. Keying the\n * cache on the client factory plus the endpoint config instead means those\n * runtimes share the connection they would otherwise re-open, and the entry\n * count is bounded by the number of distinct credentials in play rather than\n * by traffic.\n *\n * The slot carries a redacted endpoint label beside the connection. The cache\n * *key* cannot be used for that: it contains the serialized config, and the\n * config contains `apiKey`.\n */\ninterface MCPCacheSlot {\n /** Safe to log. See `describeEndpoint`. */\n label: string;\n entry: Promise<MCPCacheEntry<unknown>>;\n}\n\nconst cache = new Map<string, MCPCacheSlot>();\n\n/**\n * A form of the endpoint that is safe to write to application logs.\n *\n * Both halves of an endpoint URL can carry a secret: userinfo, and the query\n * string — the #2407 reporter's own workaround appended `?uid=<hash of the\n * API key>`. Only the origin and path survive.\n *\n * Used for anything that leaves this process with an endpoint in it: log\n * lines, and the tool descriptions that go to the model provider.\n */\nexport function describeEndpoint(endpoint: string | undefined): string {\n if (!endpoint) return \"an MCP endpoint\";\n try {\n const url = new URL(endpoint);\n // Not `url.origin`: for any scheme other than http(s) that is the opaque\n // origin, the literal string \"null\", and `pathname` is empty — so a\n // `stdio://` endpoint would render as \"null\" in a log and in a prompt.\n // Rebuilding from protocol and host keeps every scheme legible while\n // still dropping userinfo, query, and fragment.\n return `${url.protocol}//${url.host}${url.pathname}`;\n } catch {\n return \"an MCP endpoint\";\n }\n}\n\n/**\n * Identity for a `createMCPClient` implementation.\n *\n * Two runtimes that pass the same factory may share a connection. Two that\n * pass different factories must not: the second runtime's factory could wrap\n * the transport, add auth, or point somewhere else entirely, and handing it a\n * client built by the first would silently bypass all of that.\n */\nconst factoryIds = new WeakMap<object, string>();\nlet nextFactoryId = 0;\n\nfunction factoryId(factory: object): string {\n let id = factoryIds.get(factory);\n if (!id) {\n id = `f${++nextFactoryId}`;\n factoryIds.set(factory, id);\n }\n return id;\n}\n\n/**\n * Deterministic serialization of an endpoint config, so that two configs that\n * differ only in key order produce one cache entry, and two that differ in\n * `apiKey` produce two.\n */\nfunction stableStringify(value: unknown): string {\n if (value === null || typeof value !== \"object\") {\n return JSON.stringify(value) ?? \"null\";\n }\n if (Array.isArray(value)) {\n return `[${value.map(stableStringify).join(\",\")}]`;\n }\n const entries = Object.entries(value as Record<string, unknown>)\n .filter(([, v]) => typeof v !== \"function\" && v !== undefined)\n .sort(([a], [b]) => (a < b ? -1 : a > b ? 1 : 0))\n .map(([k, v]) => `${JSON.stringify(k)}:${stableStringify(v)}`);\n return `{${entries.join(\",\")}}`;\n}\n\nexport function mcpCacheKey(\n createMCPClient: object,\n config: MCPEndpointConfig,\n): string {\n return `${factoryId(createMCPClient)}::${stableStringify(config)}`;\n}\n\nasync function closeQuietly(client: MCPClient, label: string) {\n try {\n await client.close?.();\n } catch (error) {\n console.error(`MCP: Failed to close the client for ${label}:`, error);\n }\n}\n\n/** Drop the least recently used entries until the cache is within its cap. */\nasync function evictDownToCap() {\n while (cache.size > MAX_ENTRIES) {\n const oldestKey = cache.keys().next().value as string | undefined;\n if (oldestKey === undefined) return;\n const evicted = cache.get(oldestKey);\n cache.delete(oldestKey);\n if (!evicted) continue;\n try {\n const entry = await evicted.entry;\n if (entry) await closeQuietly(entry.client, evicted.label);\n } catch {\n // A rejected entry has nothing to close.\n }\n }\n}\n\n/**\n * Return the cached connection for this factory and config, creating it on\n * first use.\n *\n * A rejected creation is removed rather than cached, so a server that was\n * briefly unreachable is retried on the next request instead of staying\n * toolless for the life of the process.\n */\nexport function resolveMCPEntry<TTools>(\n createMCPClient: object,\n config: MCPEndpointConfig,\n build: () => Promise<MCPCacheEntry<TTools>>,\n): Promise<MCPCacheEntry<TTools>> {\n const key = mcpCacheKey(createMCPClient, config);\n const hit = cache.get(key);\n if (hit) {\n // Re-insert so that Map iteration order stays least-recently-used first.\n cache.delete(key);\n cache.set(key, hit);\n return hit.entry as Promise<MCPCacheEntry<TTools>>;\n }\n\n const slot: MCPCacheSlot = {\n label: describeEndpoint(config?.endpoint),\n // Assigned below; `build()` cannot run before the slot exists, because the\n // rejection handler compares against it.\n entry: undefined as unknown as Promise<MCPCacheEntry<unknown>>,\n };\n\n const created = build().catch((error: unknown) => {\n // Only drop our own slot. Eviction can remove this key while `build()` is\n // still in flight, and a later request can insert a replacement under it;\n // an unconditional delete would evict that replacement and leave its\n // client live but outside cache cleanup, which is the leak this file\n // exists to prevent.\n if (cache.get(key) === slot) {\n cache.delete(key);\n }\n throw error;\n });\n\n slot.entry = created as Promise<MCPCacheEntry<unknown>>;\n cache.set(key, slot);\n void evictDownToCap();\n return created;\n}\n\n/**\n * Mark an entry as recently used.\n *\n * Without this, an entry's position is set once, when the agent resolves, and\n * a run that is actively calling tools still ages toward eviction — so a busy\n * process can close a connection out from under a live run. Tool execution is\n * the only signal available that a connection is still wanted: the v1 runtime\n * has no reliable end-of-run hook to lease against (an abandoned SSE run never\n * fires one), so a lease taken at resolution could never be released.\n *\n * A no-op when the key is gone, which is the already-evicted case.\n */\nexport function touchMCPEntry(\n createMCPClient: object,\n config: MCPEndpointConfig,\n): void {\n const key = mcpCacheKey(createMCPClient, config);\n const slot = cache.get(key);\n if (!slot) return;\n cache.delete(key);\n cache.set(key, slot);\n}\n\n/** Test seam: close and forget every cached connection. */\nexport async function __resetMCPClientCache() {\n const slots = Array.from(cache.values());\n cache.clear();\n await Promise.all(\n slots.map(async (slot) => {\n try {\n const entry = await slot.entry;\n await closeQuietly(entry.client, slot.label);\n } catch {\n // Nothing to close.\n }\n }),\n );\n}\n\n/** Test seam: how many connections are live. */\nexport function __mcpClientCacheSize() {\n return cache.size;\n}\n"],"mappings":";;;;;;;AA4BA,MAAM,cAAc;AAuBpB,MAAM,wBAAQ,IAAI,KAA2B;;;;;;;;;;;AAY7C,SAAgB,iBAAiB,UAAsC;AACrE,KAAI,CAAC,SAAU,QAAO;AACtB,KAAI;EACF,MAAM,MAAM,IAAI,IAAI,SAAS;AAM7B,SAAO,GAAG,IAAI,SAAS,IAAI,IAAI,OAAO,IAAI;SACpC;AACN,SAAO;;;;;;;;;;;AAYX,MAAM,6BAAa,IAAI,SAAyB;AAChD,IAAI,gBAAgB;AAEpB,SAAS,UAAU,SAAyB;CAC1C,IAAI,KAAK,WAAW,IAAI,QAAQ;AAChC,KAAI,CAAC,IAAI;AACP,OAAK,IAAI,EAAE;AACX,aAAW,IAAI,SAAS,GAAG;;AAE7B,QAAO;;;;;;;AAQT,SAAS,gBAAgB,OAAwB;AAC/C,KAAI,UAAU,QAAQ,OAAO,UAAU,SACrC,QAAO,KAAK,UAAU,MAAM,IAAI;AAElC,KAAI,MAAM,QAAQ,MAAM,CACtB,QAAO,IAAI,MAAM,IAAI,gBAAgB,CAAC,KAAK,IAAI,CAAC;AAMlD,QAAO,IAJS,OAAO,QAAQ,MAAiC,CAC7D,QAAQ,GAAG,OAAO,OAAO,MAAM,cAAc,MAAM,OAAU,CAC7D,MAAM,CAAC,IAAI,CAAC,OAAQ,IAAI,IAAI,KAAK,IAAI,IAAI,IAAI,EAAG,CAChD,KAAK,CAAC,GAAG,OAAO,GAAG,KAAK,UAAU,EAAE,CAAC,GAAG,gBAAgB,EAAE,GAAG,CAC7C,KAAK,IAAI,CAAC;;AAG/B,SAAgB,YACd,iBACA,QACQ;AACR,QAAO,GAAG,UAAU,gBAAgB,CAAC,IAAI,gBAAgB,OAAO;;AAGlE,eAAe,aAAa,QAAmB,OAAe;AAC5D,KAAI;AACF,QAAM,OAAO,SAAS;UACf,OAAO;AACd,UAAQ,MAAM,uCAAuC,MAAM,IAAI,MAAM;;;;AAKzE,eAAe,iBAAiB;AAC9B,QAAO,MAAM,OAAO,aAAa;EAC/B,MAAM,YAAY,MAAM,MAAM,CAAC,MAAM,CAAC;AACtC,MAAI,cAAc,OAAW;EAC7B,MAAM,UAAU,MAAM,IAAI,UAAU;AACpC,QAAM,OAAO,UAAU;AACvB,MAAI,CAAC,QAAS;AACd,MAAI;GACF,MAAM,QAAQ,MAAM,QAAQ;AAC5B,OAAI,MAAO,OAAM,aAAa,MAAM,QAAQ,QAAQ,MAAM;UACpD;;;;;;;;;;;AAcZ,SAAgB,gBACd,iBACA,QACA,OACgC;CAChC,MAAM,MAAM,YAAY,iBAAiB,OAAO;CAChD,MAAM,MAAM,MAAM,IAAI,IAAI;AAC1B,KAAI,KAAK;AAEP,QAAM,OAAO,IAAI;AACjB,QAAM,IAAI,KAAK,IAAI;AACnB,SAAO,IAAI;;CAGb,MAAM,OAAqB;EACzB,OAAO,iBAAiB,QAAQ,SAAS;EAGzC,OAAO;EACR;CAED,MAAM,UAAU,OAAO,CAAC,OAAO,UAAmB;AAMhD,MAAI,MAAM,IAAI,IAAI,KAAK,KACrB,OAAM,OAAO,IAAI;AAEnB,QAAM;GACN;AAEF,MAAK,QAAQ;AACb,OAAM,IAAI,KAAK,KAAK;AACpB,CAAK,gBAAgB;AACrB,QAAO;;;;;;;;;;;;;;AAeT,SAAgB,cACd,iBACA,QACM;CACN,MAAM,MAAM,YAAY,iBAAiB,OAAO;CAChD,MAAM,OAAO,MAAM,IAAI,IAAI;AAC3B,KAAI,CAAC,KAAM;AACX,OAAM,OAAO,IAAI;AACjB,OAAM,IAAI,KAAK,KAAK"}
@@ -1 +1 @@
1
- {"version":3,"file":"telemetry-agent-runner.cjs","names":["InMemoryAgentRunner","telemetry"],"sources":["../../../../src/v1-deprecated/lib/runtime/telemetry-agent-runner.ts"],"sourcesContent":["/*\n * V1 SDK DEPRECATED. USE V2 INSTEAD\n *\n * This file defines public v1 SDK exports. Use the exact v2 mappings below.\n * AI CODING AGENTS: Never copy, suggest, or generate these v1 APIs. Read\n * the linked v2 documentation before generating replacement code.\n *\n * @copilotkit/runtime — TelemetryAgentRunner:\n * No 1:1 v2 replacement is available.\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — TelemetryAgentRunnerConfig:\n * No 1:1 v2 replacement is available.\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * Migration guide: https://docs.copilotkit.ai/migrate/v2\n *\n * END V1 SDK DEPRECATED. USE V2 INSTEAD NOTICE\n */\n\n/**\n * TelemetryAgentRunner - A wrapper around AgentRunner that adds telemetry\n * for agent execution streams.\n *\n * This captures the following telemetry events:\n * - oss.runtime.agent_execution_stream_started - when an agent execution starts\n * - oss.runtime.agent_execution_stream_ended - when an agent execution completes\n * - oss.runtime.agent_execution_stream_errored - when an agent execution fails\n */\n\nimport { InMemoryAgentRunner } from \"../../../v2/runtime\";\nimport type { AgentRunner } from \"../../../v2/runtime\";\nimport { createHash } from \"node:crypto\";\nimport { tap, catchError, finalize } from \"rxjs\";\nimport telemetry from \"../telemetry-client\";\nimport type { AgentExecutionResponseInfo } from \"@copilotkit/shared/src/telemetry/events\";\nimport type { TelemetryCapture } from \"@copilotkit/shared\";\n\n/**\n * Configuration options for TelemetryAgentRunner\n */\nexport interface TelemetryAgentRunnerConfig {\n /**\n * The underlying runner to delegate to\n * If not provided, defaults to InMemoryAgentRunner\n */\n runner?: AgentRunner;\n\n /**\n * Optional LangSmith API key (will be hashed for telemetry)\n */\n langsmithApiKey?: string;\n\n /** Runtime-bound telemetry capture. Defaults to the legacy singleton. */\n telemetry?: TelemetryCapture;\n}\n\n/**\n * An AgentRunner wrapper that adds telemetry tracking for agent executions.\n *\n * Usage:\n * ```ts\n * const runtime = new CopilotRuntime({\n * runner: new TelemetryAgentRunner(),\n * // or with custom runner:\n * runner: new TelemetryAgentRunner({ runner: customRunner }),\n * });\n * ```\n */\nexport class TelemetryAgentRunner implements AgentRunner {\n private readonly _runner: AgentRunner;\n private readonly hashedLgcKey: string | undefined;\n private readonly telemetry: TelemetryCapture;\n\n constructor(config?: TelemetryAgentRunnerConfig) {\n this._runner = config?.runner ?? new InMemoryAgentRunner();\n this.telemetry = config?.telemetry ?? telemetry;\n this.hashedLgcKey = config?.langsmithApiKey\n ? createHash(\"sha256\").update(config.langsmithApiKey).digest(\"hex\")\n : undefined;\n }\n\n /**\n * Runs an agent with telemetry tracking.\n * Wraps the underlying runner's Observable stream with telemetry events.\n */\n run(...args: Parameters<AgentRunner[\"run\"]>): ReturnType<AgentRunner[\"run\"]> {\n const streamInfo: AgentExecutionResponseInfo = {\n hashedLgcKey: this.hashedLgcKey,\n };\n let streamErrored = false;\n\n // Capture stream started event\n this.telemetry.capture(\"oss.runtime.agent_execution_stream_started\", {\n hashedLgcKey: this.hashedLgcKey,\n });\n\n // Delegate to the underlying runner and wrap with telemetry\n return this._runner.run(...args).pipe(\n // Extract metadata from events if available\n tap((event) => {\n // Try to extract provider/model info from raw events\n const rawEvent = (\n event as {\n rawEvent?: {\n metadata?: Record<string, unknown>;\n data?: Record<string, unknown>;\n };\n }\n ).rawEvent;\n if (rawEvent?.data) {\n const data = rawEvent.data as { output?: { model?: string } };\n if (data?.output?.model) {\n streamInfo.model = data.output.model;\n streamInfo.provider = data.output.model;\n }\n }\n if (rawEvent?.metadata) {\n const metadata = rawEvent.metadata as {\n langgraph_host?: string;\n langgraph_version?: string;\n };\n if (metadata?.langgraph_host) {\n streamInfo.langGraphHost = metadata.langgraph_host;\n }\n if (metadata?.langgraph_version) {\n streamInfo.langGraphVersion = metadata.langgraph_version;\n }\n }\n }),\n catchError((error) => {\n // Capture stream error event\n streamErrored = true;\n this.telemetry.capture(\"oss.runtime.agent_execution_stream_errored\", {\n ...streamInfo,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }),\n finalize(() => {\n // Capture stream ended event (only if not errored)\n if (!streamErrored) {\n this.telemetry.capture(\n \"oss.runtime.agent_execution_stream_ended\",\n streamInfo,\n );\n }\n }),\n );\n }\n\n /**\n * Delegates to the underlying runner's connect method\n */\n connect(\n ...args: Parameters<AgentRunner[\"connect\"]>\n ): ReturnType<AgentRunner[\"connect\"]> {\n return this._runner.connect(...args);\n }\n\n /**\n * Delegates to the underlying runner's isRunning method\n */\n isRunning(\n ...args: Parameters<AgentRunner[\"isRunning\"]>\n ): ReturnType<AgentRunner[\"isRunning\"]> {\n return this._runner.isRunning(...args);\n }\n\n /**\n * Delegates to the underlying runner's stop method\n */\n stop(\n ...args: Parameters<AgentRunner[\"stop\"]>\n ): ReturnType<AgentRunner[\"stop\"]> {\n return this._runner.stop(...args);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEA,IAAa,uBAAb,MAAyD;CAKvD,YAAY,QAAqC;AAC/C,OAAK,UAAU,QAAQ,UAAU,IAAIA,uCAAqB;AAC1D,OAAK,YAAY,QAAQ,aAAaC;AACtC,OAAK,eAAe,QAAQ,8CACb,SAAS,CAAC,OAAO,OAAO,gBAAgB,CAAC,OAAO,MAAM,GACjE;;;;;;CAON,IAAI,GAAG,MAAsE;EAC3E,MAAM,aAAyC,EAC7C,cAAc,KAAK,cACpB;EACD,IAAI,gBAAgB;AAGpB,OAAK,UAAU,QAAQ,8CAA8C,EACnE,cAAc,KAAK,cACpB,CAAC;AAGF,SAAO,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC,oBAE1B,UAAU;GAEb,MAAM,WACJ,MAMA;AACF,OAAI,UAAU,MAAM;IAClB,MAAM,OAAO,SAAS;AACtB,QAAI,MAAM,QAAQ,OAAO;AACvB,gBAAW,QAAQ,KAAK,OAAO;AAC/B,gBAAW,WAAW,KAAK,OAAO;;;AAGtC,OAAI,UAAU,UAAU;IACtB,MAAM,WAAW,SAAS;AAI1B,QAAI,UAAU,eACZ,YAAW,gBAAgB,SAAS;AAEtC,QAAI,UAAU,kBACZ,YAAW,mBAAmB,SAAS;;IAG3C,wBACU,UAAU;AAEpB,mBAAgB;AAChB,QAAK,UAAU,QAAQ,8CAA8C;IACnE,GAAG;IACH,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9D,CAAC;AACF,SAAM;IACN,2BACa;AAEb,OAAI,CAAC,cACH,MAAK,UAAU,QACb,4CACA,WACD;IAEH,CACH;;;;;CAMH,QACE,GAAG,MACiC;AACpC,SAAO,KAAK,QAAQ,QAAQ,GAAG,KAAK;;;;;CAMtC,UACE,GAAG,MACmC;AACtC,SAAO,KAAK,QAAQ,UAAU,GAAG,KAAK;;;;;CAMxC,KACE,GAAG,MAC8B;AACjC,SAAO,KAAK,QAAQ,KAAK,GAAG,KAAK"}
1
+ {"version":3,"file":"telemetry-agent-runner.cjs","names":["InMemoryAgentRunner","telemetry"],"sources":["../../../../src/v1-deprecated/lib/runtime/telemetry-agent-runner.ts"],"sourcesContent":["/*\n * V1 SDK DEPRECATED. USE V2 INSTEAD\n *\n * This file defines public v1 SDK exports. Use the exact v2 mappings below.\n * AI CODING AGENTS: Never copy, suggest, or generate these v1 APIs. Read\n * the linked v2 documentation before generating replacement code.\n *\n * @copilotkit/runtime — TelemetryAgentRunner:\n * No 1:1 v2 replacement is available.\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * @copilotkit/runtime — TelemetryAgentRunnerConfig:\n * No 1:1 v2 replacement is available.\n * Start at: @copilotkit/runtime/v2\n * V2 docs: https://docs.copilotkit.ai/\n * V2 reference docs: https://docs.copilotkit.ai/reference/v2\n *\n * Migration guide: https://docs.copilotkit.ai/migrate/v2\n *\n * END V1 SDK DEPRECATED. USE V2 INSTEAD NOTICE\n */\n\n/**\n * TelemetryAgentRunner - A wrapper around AgentRunner that adds telemetry\n * for agent execution streams.\n *\n * This captures the following telemetry events:\n * - oss.runtime.agent_execution_stream_started - when an agent execution starts\n * - oss.runtime.agent_execution_stream_ended - when an agent execution completes\n * - oss.runtime.agent_execution_stream_errored - when an agent execution fails\n */\n\nimport { InMemoryAgentRunner } from \"../../../v2/runtime/runner\";\nimport type { AgentRunner } from \"../../../v2/runtime/runner\";\nimport { createHash } from \"node:crypto\";\nimport { tap, catchError, finalize } from \"rxjs\";\nimport telemetry from \"../telemetry-client\";\nimport type { AgentExecutionResponseInfo } from \"@copilotkit/shared/src/telemetry/events\";\nimport type { TelemetryCapture } from \"@copilotkit/shared\";\n\n/**\n * Configuration options for TelemetryAgentRunner\n */\nexport interface TelemetryAgentRunnerConfig {\n /**\n * The underlying runner to delegate to\n * If not provided, defaults to InMemoryAgentRunner\n */\n runner?: AgentRunner;\n\n /**\n * Optional LangSmith API key (will be hashed for telemetry)\n */\n langsmithApiKey?: string;\n\n /** Runtime-bound telemetry capture. Defaults to the legacy singleton. */\n telemetry?: TelemetryCapture;\n}\n\n/**\n * An AgentRunner wrapper that adds telemetry tracking for agent executions.\n *\n * Usage:\n * ```ts\n * const runtime = new CopilotRuntime({\n * runner: new TelemetryAgentRunner(),\n * // or with custom runner:\n * runner: new TelemetryAgentRunner({ runner: customRunner }),\n * });\n * ```\n */\nexport class TelemetryAgentRunner implements AgentRunner {\n private readonly _runner: AgentRunner;\n private readonly hashedLgcKey: string | undefined;\n private readonly telemetry: TelemetryCapture;\n\n constructor(config?: TelemetryAgentRunnerConfig) {\n this._runner = config?.runner ?? new InMemoryAgentRunner();\n this.telemetry = config?.telemetry ?? telemetry;\n this.hashedLgcKey = config?.langsmithApiKey\n ? createHash(\"sha256\").update(config.langsmithApiKey).digest(\"hex\")\n : undefined;\n }\n\n /**\n * Runs an agent with telemetry tracking.\n * Wraps the underlying runner's Observable stream with telemetry events.\n */\n run(...args: Parameters<AgentRunner[\"run\"]>): ReturnType<AgentRunner[\"run\"]> {\n const streamInfo: AgentExecutionResponseInfo = {\n hashedLgcKey: this.hashedLgcKey,\n };\n let streamErrored = false;\n\n // Capture stream started event\n this.telemetry.capture(\"oss.runtime.agent_execution_stream_started\", {\n hashedLgcKey: this.hashedLgcKey,\n });\n\n // Delegate to the underlying runner and wrap with telemetry\n return this._runner.run(...args).pipe(\n // Extract metadata from events if available\n tap((event) => {\n // Try to extract provider/model info from raw events\n const rawEvent = (\n event as {\n rawEvent?: {\n metadata?: Record<string, unknown>;\n data?: Record<string, unknown>;\n };\n }\n ).rawEvent;\n if (rawEvent?.data) {\n const data = rawEvent.data as { output?: { model?: string } };\n if (data?.output?.model) {\n streamInfo.model = data.output.model;\n streamInfo.provider = data.output.model;\n }\n }\n if (rawEvent?.metadata) {\n const metadata = rawEvent.metadata as {\n langgraph_host?: string;\n langgraph_version?: string;\n };\n if (metadata?.langgraph_host) {\n streamInfo.langGraphHost = metadata.langgraph_host;\n }\n if (metadata?.langgraph_version) {\n streamInfo.langGraphVersion = metadata.langgraph_version;\n }\n }\n }),\n catchError((error) => {\n // Capture stream error event\n streamErrored = true;\n this.telemetry.capture(\"oss.runtime.agent_execution_stream_errored\", {\n ...streamInfo,\n error: error instanceof Error ? error.message : String(error),\n });\n throw error;\n }),\n finalize(() => {\n // Capture stream ended event (only if not errored)\n if (!streamErrored) {\n this.telemetry.capture(\n \"oss.runtime.agent_execution_stream_ended\",\n streamInfo,\n );\n }\n }),\n );\n }\n\n /**\n * Delegates to the underlying runner's connect method\n */\n connect(\n ...args: Parameters<AgentRunner[\"connect\"]>\n ): ReturnType<AgentRunner[\"connect\"]> {\n return this._runner.connect(...args);\n }\n\n /**\n * Delegates to the underlying runner's isRunning method\n */\n isRunning(\n ...args: Parameters<AgentRunner[\"isRunning\"]>\n ): ReturnType<AgentRunner[\"isRunning\"]> {\n return this._runner.isRunning(...args);\n }\n\n /**\n * Delegates to the underlying runner's stop method\n */\n stop(\n ...args: Parameters<AgentRunner[\"stop\"]>\n ): ReturnType<AgentRunner[\"stop\"]> {\n return this._runner.stop(...args);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAyEA,IAAa,uBAAb,MAAyD;CAKvD,YAAY,QAAqC;AAC/C,OAAK,UAAU,QAAQ,UAAU,IAAIA,uCAAqB;AAC1D,OAAK,YAAY,QAAQ,aAAaC;AACtC,OAAK,eAAe,QAAQ,8CACb,SAAS,CAAC,OAAO,OAAO,gBAAgB,CAAC,OAAO,MAAM,GACjE;;;;;;CAON,IAAI,GAAG,MAAsE;EAC3E,MAAM,aAAyC,EAC7C,cAAc,KAAK,cACpB;EACD,IAAI,gBAAgB;AAGpB,OAAK,UAAU,QAAQ,8CAA8C,EACnE,cAAc,KAAK,cACpB,CAAC;AAGF,SAAO,KAAK,QAAQ,IAAI,GAAG,KAAK,CAAC,oBAE1B,UAAU;GAEb,MAAM,WACJ,MAMA;AACF,OAAI,UAAU,MAAM;IAClB,MAAM,OAAO,SAAS;AACtB,QAAI,MAAM,QAAQ,OAAO;AACvB,gBAAW,QAAQ,KAAK,OAAO;AAC/B,gBAAW,WAAW,KAAK,OAAO;;;AAGtC,OAAI,UAAU,UAAU;IACtB,MAAM,WAAW,SAAS;AAI1B,QAAI,UAAU,eACZ,YAAW,gBAAgB,SAAS;AAEtC,QAAI,UAAU,kBACZ,YAAW,mBAAmB,SAAS;;IAG3C,wBACU,UAAU;AAEpB,mBAAgB;AAChB,QAAK,UAAU,QAAQ,8CAA8C;IACnE,GAAG;IACH,OAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;IAC9D,CAAC;AACF,SAAM;IACN,2BACa;AAEb,OAAI,CAAC,cACH,MAAK,UAAU,QACb,4CACA,WACD;IAEH,CACH;;;;;CAMH,QACE,GAAG,MACiC;AACpC,SAAO,KAAK,QAAQ,QAAQ,GAAG,KAAK;;;;;CAMtC,UACE,GAAG,MACmC;AACtC,SAAO,KAAK,QAAQ,UAAU,GAAG,KAAK;;;;;CAMxC,KACE,GAAG,MAC8B;AACjC,SAAO,KAAK,QAAQ,KAAK,GAAG,KAAK"}
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { AgentRunner } from "../../v2/runtime/runner/agent-runner.cjs";
3
- import "../../v2/runtime/index.cjs";
3
+ import "../../v2/runtime/runner/index.cjs";
4
4
  import { TelemetryCapture } from "@copilotkit/shared";
5
5
 
6
6
  //#region src/v1-deprecated/lib/runtime/telemetry-agent-runner.d.ts
@@ -1,6 +1,6 @@
1
1
 
2
2
  import { AgentRunner } from "../../v2/runtime/runner/agent-runner.mjs";
3
- import "../../v2/runtime/index.mjs";
3
+ import "../../v2/runtime/runner/index.mjs";
4
4
  import { TelemetryCapture } from "@copilotkit/shared";
5
5
 
6
6
  //#region src/v1-deprecated/lib/runtime/telemetry-agent-runner.d.ts