@copilotkit/runtime
Version:
<img src="https://github.com/user-attachments/assets/0a6b64d9-e193-4940-a3f6-60334ac34084" alt="banner" style="border-radius: 12px; border: 2px solid #d6d4fa;" />
287 lines (285 loc) • 12.3 kB
JavaScript
require("reflect-metadata");
const require_runtime = require('../../_virtual/_rolldown/runtime.cjs');
const require_agui_to_gql = require('../../graphql/message-conversion/agui-to-gql.cjs');
const require_telemetry_disclosure = require('../telemetry-disclosure.cjs');
const require_in_memory = require('../../v2/runtime/runner/in-memory.cjs');
const require_runtime$1 = require('../../v2/runtime/core/runtime.cjs');
const require_telemetry_agent_runner = require('./telemetry-agent-runner.cjs');
const require_types = require('./types.cjs');
const require_mcp_tools_utils = require('./mcp-tools-utils.cjs');
const require_index = require('../../agent/index.cjs');
const require_telemetry_client = require('../telemetry-client.cjs');
let _copilotkit_shared = require("@copilotkit/shared");
//#region src/lib/runtime/copilot-runtime.ts
/**
* <Callout type="info">
* This is the reference for the `CopilotRuntime` class. For more information and example code snippets, please see [Concept: Copilot Runtime](/concepts/copilot-runtime).
* </Callout>
*
* ## Usage
*
* ```tsx
* import { CopilotRuntime } from "@copilotkit/runtime";
*
* const copilotKit = new CopilotRuntime();
* ```
*/
/**
* Central runtime object passed to all request handlers.
*/
var CopilotRuntime = class {
constructor(params) {
this.mcpToolsCache = /* @__PURE__ */ new Map();
require_telemetry_disclosure.logRuntimeTelemetryDisclosure();
const agents = params?.agents ?? {};
const endpointAgents = this.assignEndpointsToAgents(params?.remoteEndpoints ?? []);
let mergedAgents;
if (typeof agents === "function") mergedAgents = async (ctx) => {
const resolved = await agents(ctx);
return {
...endpointAgents,
...resolved
};
};
else mergedAgents = Promise.resolve(agents).then((resolved) => ({
...endpointAgents,
...resolved
}));
const baseRunner = params?.runner ?? new require_in_memory.InMemoryAgentRunner();
const runner = (0, _copilotkit_shared.isTelemetryDisabled)() ? baseRunner : new require_telemetry_agent_runner.TelemetryAgentRunner({ runner: baseRunner });
const resolvedLicenseToken = params?.licenseToken ?? process.env.COPILOTKIT_LICENSE_TOKEN;
if (resolvedLicenseToken) require_telemetry_client.default.setLicenseToken(resolvedLicenseToken);
this.runtimeArgs = {
agents: mergedAgents,
runner,
licenseToken: params?.licenseToken,
debug: params?.debug,
beforeRequestMiddleware: this.createOnBeforeRequestHandler(params).bind(this),
...params?.afterRequestMiddleware || params?.middleware?.onAfterRequest ? { afterRequestMiddleware: this.createOnAfterRequestHandler(params).bind(this) } : {},
a2ui: params?.a2ui,
mcpApps: params?.mcpApps,
openGenerativeUI: params?.openGenerativeUI
};
this.params = params;
this.observability = params?.observability_c;
}
get instance() {
if (!this._instance) this._instance = new require_runtime$1.CopilotRuntime(this.runtimeArgs);
return this._instance;
}
assignEndpointsToAgents(endpoints) {
let result = {};
if (endpoints.some((endpoint) => resolveEndpointType(endpoint) == require_types.EndpointType.LangGraphPlatform)) throw new _copilotkit_shared.CopilotKitMisuseError({ message: "LangGraphPlatformEndpoint in remoteEndpoints is deprecated. Please use the \"agents\" option instead with LangGraphAgent from \"@copilotkit/runtime/langgraph\". Example: agents: { myAgent: new LangGraphAgent({ deploymentUrl: \"...\", graphId: \"...\" }) }" });
return result;
}
handleServiceAdapter(serviceAdapter) {
this.runtimeArgs.agents = Promise.resolve(this.runtimeArgs.agents ?? {}).then(async (agents) => {
let agentsList = agents;
const isAgentsListEmpty = !Object.keys(agents).length;
const hasServiceAdapter = Boolean(serviceAdapter);
const serviceAdapterCanBeUsedForAgent = !["EmptyAdapter"].includes(serviceAdapter.name);
if (isAgentsListEmpty && (!hasServiceAdapter || !serviceAdapterCanBeUsedForAgent)) throw new _copilotkit_shared.CopilotKitMisuseError({ message: "No default agent provided. Please provide a default agent in the runtime config." });
if (isAgentsListEmpty) {
const languageModel = serviceAdapter.getLanguageModel?.();
if (languageModel) agentsList.default = new require_index.BuiltInAgent({ model: languageModel });
else if (serviceAdapter.provider && serviceAdapter.model) agentsList.default = new require_index.BuiltInAgent({ model: `${serviceAdapter.provider}/${serviceAdapter.model}` });
else throw new _copilotkit_shared.CopilotKitMisuseError({ message: `Service adapter "${serviceAdapter.name ?? "unknown"}" does not provide model information. When using adapters like LangChainAdapter without an explicit agents list, please provide a default agent in the runtime config. Example:\n new CopilotRuntime({\n agents: { default: new BuiltInAgent({ model: "openai/gpt-4o" }) }\n })` });
}
const actions = this.params?.actions;
if (actions) {
const mcpTools = await this.getToolsFromMCP();
agentsList = this.assignToolsToAgents(agents, [...this.getToolsFromActions(actions), ...mcpTools]);
}
return agentsList;
});
}
getToolsFromActions(actions) {
return (typeof actions === "function" ? actions({
properties: {},
url: void 0
}) : actions).map((action) => {
const zodSchema = (0, _copilotkit_shared.getZodParameters)(action.parameters || []);
return {
name: action.name,
description: action.description || "",
parameters: zodSchema,
execute: () => Promise.resolve()
};
});
}
assignToolsToAgents(agents, tools) {
if (!tools?.length) return agents;
const enrichedAgents = { ...agents };
for (const [agentId, agent] of Object.entries(enrichedAgents)) {
const existingConfig = Reflect.get(agent, "config") ?? {};
if ("factory" in existingConfig) continue;
const classicConfig = existingConfig;
const existingTools = classicConfig.tools ?? [];
const updatedConfig = {
...classicConfig,
tools: [...existingTools, ...tools]
};
Reflect.set(agent, "config", updatedConfig);
enrichedAgents[agentId] = agent;
}
return enrichedAgents;
}
createOnBeforeRequestHandler(params) {
return async (hookParams) => {
const { request } = hookParams;
const publicApiKey = request.headers.get("x-copilotcloud-public-api-key");
const body = await (0, _copilotkit_shared.readBody)(request);
const forwardedProps = body?.forwardedProps;
const cloudBaseUrl = process.env.COPILOT_CLOUD_BASE_URL || "https://api.cloud.copilotkit.ai";
require_telemetry_client.default.capture("oss.runtime.copilot_request_created", {
"cloud.guardrails.enabled": forwardedProps?.cloud?.guardrails !== void 0,
requestType: forwardedProps?.metadata?.requestType ?? "unknown",
"cloud.api_key_provided": !!publicApiKey,
...publicApiKey ? { "cloud.public_api_key": publicApiKey } : {},
"cloud.base_url": cloudBaseUrl
});
if (request.method === "GET" || !body) return;
const middlewareResult = await params?.beforeRequestMiddleware?.(hookParams);
if (params?.middleware?.onBeforeRequest) {
const { request, runtime, path } = hookParams;
const { inputMessages, outputMessages } = require_agui_to_gql.aguiToGQL(body.messages).reduce((acc, msg) => {
if ("role" in msg && msg.role === "user") acc.inputMessages.push(msg);
else acc.outputMessages.push(msg);
return acc;
}, {
inputMessages: [],
outputMessages: []
});
params.middleware.onBeforeRequest({
threadId: body.threadId,
runId: body.runId,
inputMessages,
properties: body.forwardedProps,
url: request.url
});
}
return middlewareResult;
};
}
createOnAfterRequestHandler(params) {
return async (hookParams) => {
params?.afterRequestMiddleware?.(hookParams);
if (params?.middleware?.onAfterRequest) {
const messages = hookParams.messages ?? [];
params.middleware.onAfterRequest({
threadId: hookParams.threadId ?? "",
runId: hookParams.runId,
inputMessages: messages.filter((m) => "role" in m && m.role === "user"),
outputMessages: messages.filter((m) => "role" in m && m.role !== "user"),
properties: {},
url: hookParams.path
});
}
};
}
/**
* Log LLM request if observability is enabled
*/
async logObservabilityBeforeRequest(requestData) {
try {
await this.observability.hooks.handleRequest(requestData);
} catch (error) {
console.error("Error logging LLM request:", error);
}
}
/**
* Log final LLM response after request completes
*/
logObservabilityAfterRequest(outputMessagesPromise, baseData, streamedChunks, requestStartTime, publicApiKey) {
try {
outputMessagesPromise.then((outputMessages) => {
const responseData = {
threadId: baseData.threadId,
runId: baseData.runId,
model: baseData.model,
output: this.observability.progressive ? streamedChunks : outputMessages,
latency: Date.now() - requestStartTime,
timestamp: Date.now(),
provider: baseData.provider,
isFinalResponse: true,
agentName: baseData.agentName,
nodeName: baseData.nodeName
};
try {
this.observability.hooks.handleResponse(responseData);
} catch (logError) {
console.error("Error logging LLM response:", logError);
}
}).catch((error) => {
console.error("Failed to get output messages for logging:", error);
});
} catch (error) {
console.error("Error setting up logging for LLM response:", error);
}
}
async getToolsFromMCP(options) {
const runtimeMcpServers = this.params?.mcpServers ?? [];
const createMCPClient = this.params?.createMCPClient;
const requestMcpServers = (options?.properties)?.mcpServers ?? (options?.properties)?.mcpEndpoints ?? [];
if (!((runtimeMcpServers?.length ?? 0) > 0 || (requestMcpServers?.length ?? 0) > 0)) return [];
if (!createMCPClient) throw new _copilotkit_shared.CopilotKitMisuseError({ message: "MCP Integration Error: `mcpServers` were provided, but the `createMCPClient` function was not passed to the CopilotRuntime constructor. Please provide an implementation for `createMCPClient`." });
const effectiveEndpoints = (() => {
const byUrl = /* @__PURE__ */ new Map();
for (const ep of runtimeMcpServers) if (ep?.endpoint) byUrl.set(ep.endpoint, ep);
for (const ep of requestMcpServers) if (ep?.endpoint) byUrl.set(ep.endpoint, ep);
return Array.from(byUrl.values());
})();
const allTools = [];
for (const config of effectiveEndpoints) {
const endpointUrl = config.endpoint;
const cached = this.mcpToolsCache.get(endpointUrl);
if (cached) {
allTools.push(...cached);
continue;
}
try {
const toolsMap = await (await createMCPClient(config)).tools();
const toolDefs = Object.entries(toolsMap).map(([toolName, tool]) => {
const zodSchema = (0, _copilotkit_shared.getZodParameters)(require_mcp_tools_utils.extractParametersFromSchema(tool));
return {
name: toolName,
description: tool.description || `MCP tool: ${toolName} (from ${endpointUrl})`,
parameters: zodSchema,
execute: () => Promise.resolve()
};
});
this.mcpToolsCache.set(endpointUrl, toolDefs);
allTools.push(...toolDefs);
} catch (error) {
console.error(`MCP: Failed to fetch tools from endpoint ${endpointUrl}. Skipping. Error:`, error);
this.mcpToolsCache.set(endpointUrl, []);
}
}
const dedupedByName = /* @__PURE__ */ new Map();
for (const tool of allTools) dedupedByName.set(tool.name, tool);
return Array.from(dedupedByName.values());
}
};
function copilotKitEndpoint(config) {
return {
...config,
type: require_types.EndpointType.CopilotKit
};
}
function langGraphPlatformEndpoint(config) {
return {
...config,
type: require_types.EndpointType.LangGraphPlatform
};
}
function resolveEndpointType(endpoint) {
if (!endpoint.type) if ("deploymentUrl" in endpoint && "agents" in endpoint) return require_types.EndpointType.LangGraphPlatform;
else return require_types.EndpointType.CopilotKit;
return endpoint.type;
}
//#endregion
exports.CopilotRuntime = CopilotRuntime;
exports.copilotKitEndpoint = copilotKitEndpoint;
exports.langGraphPlatformEndpoint = langGraphPlatformEndpoint;
exports.resolveEndpointType = resolveEndpointType;
//# sourceMappingURL=copilot-runtime.cjs.map