@copilotkit/runtime 1.50.0-beta.1 → 1.50.0-beta.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +85 -0
- package/dist/chunk-2OZAGFV3.mjs +43 -0
- package/dist/chunk-2OZAGFV3.mjs.map +1 -0
- package/dist/chunk-62NE5S6M.mjs +226 -0
- package/dist/chunk-62NE5S6M.mjs.map +1 -0
- package/dist/chunk-6XRUR5UK.mjs +1 -0
- package/dist/chunk-6XRUR5UK.mjs.map +1 -0
- package/dist/chunk-AMUJQ6IR.mjs +50 -0
- package/dist/chunk-AMUJQ6IR.mjs.map +1 -0
- package/dist/chunk-BJEYMRDD.mjs +25 -0
- package/dist/chunk-BJEYMRDD.mjs.map +1 -0
- package/dist/chunk-DZV4ZIAR.mjs +3063 -0
- package/dist/chunk-DZV4ZIAR.mjs.map +1 -0
- package/dist/chunk-FHD4JECV.mjs +33 -0
- package/dist/chunk-FHD4JECV.mjs.map +1 -0
- package/dist/chunk-FMU55SEU.mjs +25 -0
- package/dist/chunk-FMU55SEU.mjs.map +1 -0
- package/dist/chunk-OWIGJONH.mjs +275 -0
- package/dist/chunk-OWIGJONH.mjs.map +1 -0
- package/dist/chunk-SBCOROE4.mjs +1112 -0
- package/dist/chunk-SBCOROE4.mjs.map +1 -0
- package/dist/chunk-TTUAEJLD.mjs +617 -0
- package/dist/chunk-TTUAEJLD.mjs.map +1 -0
- package/dist/chunk-XWBDEXDA.mjs +153 -0
- package/dist/chunk-XWBDEXDA.mjs.map +1 -0
- package/dist/chunk-Z752VE75.mjs +74 -0
- package/dist/chunk-Z752VE75.mjs.map +1 -0
- package/dist/graphql/message-conversion/index.d.ts +18 -0
- package/dist/graphql/message-conversion/index.js +725 -0
- package/dist/graphql/message-conversion/index.js.map +1 -0
- package/dist/graphql/message-conversion/index.mjs +245 -0
- package/dist/graphql/message-conversion/index.mjs.map +1 -0
- package/dist/graphql/types/base/index.d.ts +6 -0
- package/dist/graphql/types/base/index.js +63 -0
- package/dist/graphql/types/base/index.js.map +1 -0
- package/dist/graphql/types/base/index.mjs +8 -0
- package/dist/graphql/types/base/index.mjs.map +1 -0
- package/dist/graphql/types/converted/index.d.ts +2 -0
- package/dist/graphql/types/converted/index.js +294 -0
- package/dist/graphql/types/converted/index.js.map +1 -0
- package/dist/graphql/types/converted/index.mjs +20 -0
- package/dist/graphql/types/converted/index.mjs.map +1 -0
- package/dist/groq-adapter-50bc6e4a.d.ts +326 -0
- package/dist/index-adbd78f1.d.ts +154 -0
- package/dist/index.d.ts +136 -287
- package/dist/index.js +414 -293
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +407 -283
- package/dist/index.mjs.map +1 -1
- package/dist/langgraph.d.ts +284 -0
- package/dist/langgraph.js +211 -0
- package/dist/langgraph.js.map +1 -0
- package/dist/langgraph.mjs +206 -0
- package/dist/langgraph.mjs.map +1 -0
- package/dist/langserve-74a52292.d.ts +242 -0
- package/dist/lib/cloud/index.d.ts +6 -0
- package/dist/lib/cloud/index.js +18 -0
- package/dist/lib/cloud/index.js.map +1 -0
- package/dist/lib/cloud/index.mjs +1 -0
- package/dist/lib/cloud/index.mjs.map +1 -0
- package/dist/lib/index.d.ts +266 -0
- package/dist/lib/index.js +4944 -0
- package/dist/lib/index.js.map +1 -0
- package/dist/lib/index.mjs +74 -0
- package/dist/lib/index.mjs.map +1 -0
- package/dist/lib/integrations/index.d.ts +28 -0
- package/dist/lib/integrations/index.js +3024 -0
- package/dist/lib/integrations/index.js.map +1 -0
- package/dist/lib/integrations/index.mjs +36 -0
- package/dist/lib/integrations/index.mjs.map +1 -0
- package/dist/lib/integrations/nest/index.d.ts +16 -0
- package/dist/lib/integrations/nest/index.js +2937 -0
- package/dist/lib/integrations/nest/index.js.map +1 -0
- package/dist/lib/integrations/nest/index.mjs +13 -0
- package/dist/lib/integrations/nest/index.mjs.map +1 -0
- package/dist/lib/integrations/node-express/index.d.ts +16 -0
- package/dist/lib/integrations/node-express/index.js +2937 -0
- package/dist/lib/integrations/node-express/index.js.map +1 -0
- package/dist/lib/integrations/node-express/index.mjs +13 -0
- package/dist/lib/integrations/node-express/index.mjs.map +1 -0
- package/dist/lib/integrations/node-http/index.d.ts +16 -0
- package/dist/lib/integrations/node-http/index.js +2923 -0
- package/dist/lib/integrations/node-http/index.js.map +1 -0
- package/dist/lib/integrations/node-http/index.mjs +12 -0
- package/dist/lib/integrations/node-http/index.mjs.map +1 -0
- package/dist/service-adapters/index.d.ts +166 -0
- package/dist/service-adapters/index.js +1800 -0
- package/dist/service-adapters/index.js.map +1 -0
- package/dist/service-adapters/index.mjs +36 -0
- package/dist/service-adapters/index.mjs.map +1 -0
- package/dist/service-adapters/shared/index.d.ts +9 -0
- package/dist/service-adapters/shared/index.js +72 -0
- package/dist/service-adapters/shared/index.js.map +1 -0
- package/dist/service-adapters/shared/index.mjs +8 -0
- package/dist/service-adapters/shared/index.mjs.map +1 -0
- package/dist/shared-f6d43ef8.d.ts +446 -0
- package/dist/utils/index.d.ts +65 -0
- package/dist/utils/index.js +175 -0
- package/dist/utils/index.js.map +1 -0
- package/dist/utils/index.mjs +12 -0
- package/dist/utils/index.mjs.map +1 -0
- package/dist/v2/index.d.ts +1 -0
- package/dist/v2/index.js +7 -0
- package/dist/v2/index.js.map +1 -1
- package/dist/v2/index.mjs +1 -0
- package/dist/v2/index.mjs.map +1 -1
- package/package.json +56 -18
- package/src/graphql/message-conversion/agui-to-gql.test.ts +2 -2
- package/src/graphql/message-conversion/gql-to-agui.test.ts +30 -28
- package/src/graphql/message-conversion/roundtrip-conversion.test.ts +8 -8
- package/src/langgraph.ts +1 -0
- package/src/lib/index.ts +42 -1
- package/src/lib/integrations/nextjs/app-router.ts +3 -1
- package/src/lib/integrations/node-http/index.ts +132 -11
- package/src/lib/integrations/shared.ts +2 -2
- package/src/lib/runtime/agent-integrations/{langgraph.agent.ts → langgraph/agent.ts} +5 -30
- package/src/lib/runtime/agent-integrations/langgraph/consts.ts +34 -0
- package/src/lib/runtime/agent-integrations/langgraph/index.ts +2 -0
- package/src/lib/runtime/copilot-runtime.ts +86 -69
- package/src/lib/runtime/telemetry-agent-runner.ts +134 -0
- package/src/service-adapters/anthropic/anthropic-adapter.ts +16 -3
- package/src/service-adapters/bedrock/bedrock-adapter.ts +4 -1
- package/src/service-adapters/experimental/ollama/ollama-adapter.ts +2 -1
- package/src/service-adapters/google/google-genai-adapter.ts +9 -4
- package/src/service-adapters/groq/groq-adapter.ts +16 -3
- package/src/service-adapters/langchain/langchain-adapter.ts +5 -3
- package/src/service-adapters/langchain/langserve.ts +2 -1
- package/src/service-adapters/openai/openai-adapter.ts +17 -3
- package/src/service-adapters/openai/openai-assistant-adapter.ts +26 -11
- package/src/service-adapters/unify/unify-adapter.ts +3 -1
- package/src/v2/index.ts +1 -0
- package/tsup.config.ts +5 -2
|
@@ -4,6 +4,8 @@ import { createCopilotEndpointSingleRoute } from "@copilotkitnext/runtime";
|
|
|
4
4
|
import { IncomingMessage, ServerResponse } from "http";
|
|
5
5
|
import { Readable } from "node:stream";
|
|
6
6
|
|
|
7
|
+
type IncomingWithBody = IncomingMessage & { body?: unknown; complete?: boolean };
|
|
8
|
+
|
|
7
9
|
export function readableStreamToNodeStream(webStream: ReadableStream): Readable {
|
|
8
10
|
const reader = webStream.getReader();
|
|
9
11
|
|
|
@@ -24,7 +26,10 @@ export function readableStreamToNodeStream(webStream: ReadableStream): Readable
|
|
|
24
26
|
}
|
|
25
27
|
|
|
26
28
|
function getFullUrl(req: IncomingMessage): string {
|
|
27
|
-
const
|
|
29
|
+
const expressPath =
|
|
30
|
+
(req as any).originalUrl ??
|
|
31
|
+
((req as any).baseUrl ? `${(req as any).baseUrl}${req.url ?? ""}` : undefined);
|
|
32
|
+
const path = expressPath || req.url || "/";
|
|
28
33
|
const host =
|
|
29
34
|
(req.headers["x-forwarded-host"] as string) || (req.headers.host as string) || "localhost";
|
|
30
35
|
const proto =
|
|
@@ -34,6 +39,61 @@ function getFullUrl(req: IncomingMessage): string {
|
|
|
34
39
|
return `${proto}://${host}${path}`;
|
|
35
40
|
}
|
|
36
41
|
|
|
42
|
+
function toHeaders(rawHeaders: IncomingMessage["headers"]): Headers {
|
|
43
|
+
const headers = new Headers();
|
|
44
|
+
|
|
45
|
+
for (const [key, value] of Object.entries(rawHeaders)) {
|
|
46
|
+
if (value === undefined) continue;
|
|
47
|
+
|
|
48
|
+
if (Array.isArray(value)) {
|
|
49
|
+
value.forEach((entry) => headers.append(key, entry));
|
|
50
|
+
continue;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
headers.append(key, value);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
return headers;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function isStreamConsumed(req: IncomingWithBody): boolean {
|
|
60
|
+
const readableState = (req as any)._readableState;
|
|
61
|
+
|
|
62
|
+
return Boolean(
|
|
63
|
+
req.readableEnded || req.complete || readableState?.ended || readableState?.endEmitted,
|
|
64
|
+
);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function synthesizeBodyFromParsedBody(
|
|
68
|
+
parsedBody: unknown,
|
|
69
|
+
headers: Headers,
|
|
70
|
+
): { body: BodyInit | null; contentType?: string } {
|
|
71
|
+
if (parsedBody === null || parsedBody === undefined) {
|
|
72
|
+
return { body: null };
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
if (parsedBody instanceof Buffer || parsedBody instanceof Uint8Array) {
|
|
76
|
+
return { body: parsedBody };
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
if (typeof parsedBody === "string") {
|
|
80
|
+
return { body: parsedBody, contentType: headers.get("content-type") ?? "text/plain" };
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
return {
|
|
84
|
+
body: JSON.stringify(parsedBody),
|
|
85
|
+
contentType: "application/json",
|
|
86
|
+
};
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function isDisturbedOrLockedError(error: unknown): boolean {
|
|
90
|
+
return (
|
|
91
|
+
error instanceof TypeError &&
|
|
92
|
+
typeof error.message === "string" &&
|
|
93
|
+
(error.message.includes("disturbed") || error.message.includes("locked"))
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
37
97
|
export function copilotRuntimeNodeHttpEndpoint(options: CreateCopilotRuntimeServerOptions) {
|
|
38
98
|
const commonConfig = getCommonConfig(options);
|
|
39
99
|
|
|
@@ -55,26 +115,87 @@ export function copilotRuntimeNodeHttpEndpoint(options: CreateCopilotRuntimeServ
|
|
|
55
115
|
logger.debug("Creating Node HTTP endpoint");
|
|
56
116
|
|
|
57
117
|
const serviceAdapter = options.serviceAdapter;
|
|
58
|
-
|
|
118
|
+
if (serviceAdapter) {
|
|
119
|
+
options.runtime.handleServiceAdapter(serviceAdapter);
|
|
120
|
+
}
|
|
59
121
|
|
|
60
122
|
const honoApp = createCopilotEndpointSingleRoute({
|
|
61
123
|
runtime: options.runtime.instance,
|
|
62
124
|
basePath: options.baseUrl ?? options.endpoint,
|
|
63
125
|
});
|
|
64
126
|
|
|
65
|
-
return async function handler(req:
|
|
127
|
+
return async function handler(req: IncomingWithBody, res: ServerResponse) {
|
|
66
128
|
const url = getFullUrl(req);
|
|
67
129
|
const hasBody = req.method !== "GET" && req.method !== "HEAD";
|
|
68
130
|
|
|
69
|
-
const
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
duplex: hasBody ? "half" : undefined,
|
|
75
|
-
} as any);
|
|
131
|
+
const baseHeaders = toHeaders(req.headers);
|
|
132
|
+
const parsedBody = req.body;
|
|
133
|
+
|
|
134
|
+
const streamConsumed = isStreamConsumed(req) || parsedBody !== undefined;
|
|
135
|
+
const canStream = hasBody && !streamConsumed;
|
|
76
136
|
|
|
77
|
-
|
|
137
|
+
let requestBody: BodyInit | null | undefined = undefined;
|
|
138
|
+
let useDuplex = false;
|
|
139
|
+
|
|
140
|
+
if (hasBody && canStream) {
|
|
141
|
+
requestBody = req as unknown as BodyInit;
|
|
142
|
+
useDuplex = true;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
if (hasBody && streamConsumed) {
|
|
146
|
+
if (parsedBody !== undefined) {
|
|
147
|
+
const synthesized = synthesizeBodyFromParsedBody(parsedBody, baseHeaders);
|
|
148
|
+
requestBody = synthesized.body ?? undefined;
|
|
149
|
+
baseHeaders.delete("content-length");
|
|
150
|
+
|
|
151
|
+
if (synthesized.contentType) {
|
|
152
|
+
baseHeaders.set("content-type", synthesized.contentType);
|
|
153
|
+
}
|
|
154
|
+
|
|
155
|
+
logger.debug("Request stream already consumed; using parsed req.body to rebuild request.");
|
|
156
|
+
} else {
|
|
157
|
+
logger.warn("Request stream consumed with no available body; sending empty payload.");
|
|
158
|
+
requestBody = undefined;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
const buildRequest = (body: BodyInit | null | undefined, headers: Headers, duplex: boolean) =>
|
|
163
|
+
new Request(url, {
|
|
164
|
+
method: req.method,
|
|
165
|
+
headers,
|
|
166
|
+
body,
|
|
167
|
+
duplex: duplex ? "half" : undefined,
|
|
168
|
+
} as RequestInit);
|
|
169
|
+
|
|
170
|
+
let response: Response;
|
|
171
|
+
try {
|
|
172
|
+
response = await honoApp.fetch(buildRequest(requestBody, baseHeaders, useDuplex));
|
|
173
|
+
} catch (error) {
|
|
174
|
+
if (isDisturbedOrLockedError(error) && hasBody) {
|
|
175
|
+
logger.warn(
|
|
176
|
+
"Encountered disturbed/locked request body; rebuilding request using parsed body or empty payload.",
|
|
177
|
+
);
|
|
178
|
+
|
|
179
|
+
const fallbackHeaders = new Headers(baseHeaders);
|
|
180
|
+
let fallbackBody: BodyInit | null | undefined;
|
|
181
|
+
|
|
182
|
+
if (parsedBody !== undefined) {
|
|
183
|
+
const synthesized = synthesizeBodyFromParsedBody(parsedBody, fallbackHeaders);
|
|
184
|
+
fallbackBody = synthesized.body ?? undefined;
|
|
185
|
+
fallbackHeaders.delete("content-length");
|
|
186
|
+
|
|
187
|
+
if (synthesized.contentType) {
|
|
188
|
+
fallbackHeaders.set("content-type", synthesized.contentType);
|
|
189
|
+
}
|
|
190
|
+
} else {
|
|
191
|
+
fallbackBody = undefined;
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
response = await honoApp.fetch(buildRequest(fallbackBody, fallbackHeaders, false));
|
|
195
|
+
} else {
|
|
196
|
+
throw error;
|
|
197
|
+
}
|
|
198
|
+
}
|
|
78
199
|
|
|
79
200
|
res.statusCode = response.status;
|
|
80
201
|
response.headers.forEach((value, key) => {
|
|
@@ -34,8 +34,8 @@ export type GraphQLContext = YogaInitialContext & {
|
|
|
34
34
|
};
|
|
35
35
|
|
|
36
36
|
export interface CreateCopilotRuntimeServerOptions {
|
|
37
|
-
runtime: CopilotRuntime
|
|
38
|
-
serviceAdapter
|
|
37
|
+
runtime: CopilotRuntime<any>;
|
|
38
|
+
serviceAdapter?: CopilotServiceAdapter;
|
|
39
39
|
endpoint: string;
|
|
40
40
|
baseUrl?: string;
|
|
41
41
|
cloud?: CopilotCloudOptions;
|
|
@@ -1,16 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
RunAgentInput,
|
|
3
|
-
EventType,
|
|
4
|
-
CustomEvent,
|
|
5
|
-
TextMessageStartEvent,
|
|
6
|
-
TextMessageContentEvent,
|
|
7
|
-
TextMessageEndEvent,
|
|
8
|
-
ToolCallStartEvent,
|
|
9
|
-
ToolCallArgsEvent,
|
|
10
|
-
ToolCallEndEvent,
|
|
11
|
-
} from "@ag-ui/client";
|
|
12
1
|
import { map } from "rxjs";
|
|
13
|
-
import { LangGraphEventTypes } from "
|
|
2
|
+
import { LangGraphEventTypes } from "../../../../agents/langgraph/events";
|
|
14
3
|
import { RawEvent } from "@ag-ui/core";
|
|
15
4
|
import {
|
|
16
5
|
LangGraphAgent as AGUILangGraphAgent,
|
|
@@ -31,25 +20,11 @@ interface CopilotKitStateEnrichment {
|
|
|
31
20
|
};
|
|
32
21
|
}
|
|
33
22
|
|
|
34
|
-
|
|
35
|
-
tool: string;
|
|
36
|
-
state_key: string;
|
|
37
|
-
tool_argument: string;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
export type TextMessageEvents =
|
|
41
|
-
| TextMessageStartEvent
|
|
42
|
-
| TextMessageContentEvent
|
|
43
|
-
| TextMessageEndEvent;
|
|
23
|
+
import { RunAgentInput, EventType, CustomEvent } from "@ag-ui/client";
|
|
44
24
|
|
|
45
|
-
export
|
|
46
|
-
|
|
47
|
-
export
|
|
48
|
-
CopilotKitManuallyEmitMessage = "copilotkit_manually_emit_message",
|
|
49
|
-
CopilotKitManuallyEmitToolCall = "copilotkit_manually_emit_tool_call",
|
|
50
|
-
CopilotKitManuallyEmitIntermediateState = "copilotkit_manually_emit_intermediate_state",
|
|
51
|
-
CopilotKitExit = "copilotkit_exit",
|
|
52
|
-
}
|
|
25
|
+
// Import and re-export from separate file to maintain API compatibility
|
|
26
|
+
import { CustomEventNames, TextMessageEvents, ToolCallEvents, PredictStateTool } from "./consts";
|
|
27
|
+
export { CustomEventNames };
|
|
53
28
|
|
|
54
29
|
export class LangGraphAgent extends AGUILangGraphAgent {
|
|
55
30
|
constructor(config: LangGraphAgentConfig) {
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Constants for LangGraph integration.
|
|
3
|
+
* This file is separate from langgraph.agent.ts to avoid pulling in @ag-ui/langgraph
|
|
4
|
+
* when only these constants are needed.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import {
|
|
8
|
+
TextMessageStartEvent,
|
|
9
|
+
TextMessageContentEvent,
|
|
10
|
+
TextMessageEndEvent,
|
|
11
|
+
ToolCallStartEvent,
|
|
12
|
+
ToolCallArgsEvent,
|
|
13
|
+
ToolCallEndEvent,
|
|
14
|
+
} from "@ag-ui/client";
|
|
15
|
+
|
|
16
|
+
export type TextMessageEvents =
|
|
17
|
+
| TextMessageStartEvent
|
|
18
|
+
| TextMessageContentEvent
|
|
19
|
+
| TextMessageEndEvent;
|
|
20
|
+
|
|
21
|
+
export type ToolCallEvents = ToolCallStartEvent | ToolCallArgsEvent | ToolCallEndEvent;
|
|
22
|
+
|
|
23
|
+
export enum CustomEventNames {
|
|
24
|
+
CopilotKitManuallyEmitMessage = "copilotkit_manually_emit_message",
|
|
25
|
+
CopilotKitManuallyEmitToolCall = "copilotkit_manually_emit_tool_call",
|
|
26
|
+
CopilotKitManuallyEmitIntermediateState = "copilotkit_manually_emit_intermediate_state",
|
|
27
|
+
CopilotKitExit = "copilotkit_exit",
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface PredictStateTool {
|
|
31
|
+
tool: string;
|
|
32
|
+
state_key: string;
|
|
33
|
+
tool_argument: string;
|
|
34
|
+
}
|
|
@@ -13,65 +13,50 @@
|
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
15
|
import {
|
|
16
|
-
Action,
|
|
17
|
-
CopilotErrorHandler,
|
|
16
|
+
type Action,
|
|
17
|
+
type CopilotErrorHandler,
|
|
18
18
|
CopilotKitMisuseError,
|
|
19
|
-
MaybePromise,
|
|
20
|
-
NonEmptyRecord,
|
|
21
|
-
Parameter,
|
|
19
|
+
type MaybePromise,
|
|
20
|
+
type NonEmptyRecord,
|
|
21
|
+
type Parameter,
|
|
22
22
|
readBody,
|
|
23
23
|
getZodParameters,
|
|
24
|
-
PartialBy,
|
|
24
|
+
type PartialBy,
|
|
25
|
+
isTelemetryDisabled,
|
|
25
26
|
} from "@copilotkit/shared";
|
|
26
|
-
import {
|
|
27
|
+
import type { RunAgentInput } from "@ag-ui/core";
|
|
27
28
|
import { aguiToGQL } from "../../graphql/message-conversion/agui-to-gql";
|
|
28
|
-
import { CopilotServiceAdapter, RemoteChainParameters } from "../../service-adapters";
|
|
29
|
+
import type { CopilotServiceAdapter, RemoteChainParameters } from "../../service-adapters";
|
|
29
30
|
import {
|
|
30
31
|
CopilotRuntime as CopilotRuntimeVNext,
|
|
31
|
-
CopilotRuntimeOptions,
|
|
32
|
-
CopilotRuntimeOptions as CopilotRuntimeOptionsVNext,
|
|
33
|
-
InMemoryAgentRunner
|
|
32
|
+
type CopilotRuntimeOptions,
|
|
33
|
+
type CopilotRuntimeOptions as CopilotRuntimeOptionsVNext,
|
|
34
|
+
InMemoryAgentRunner,
|
|
34
35
|
} from "@copilotkitnext/runtime";
|
|
36
|
+
import { TelemetryAgentRunner } from "./telemetry-agent-runner";
|
|
37
|
+
import telemetry from "../telemetry-client";
|
|
35
38
|
|
|
36
|
-
import { MessageInput } from "../../graphql/inputs/message.input";
|
|
37
|
-
import {
|
|
38
|
-
import { RuntimeEventSource } from "../../service-adapters/events";
|
|
39
|
-
import { Message } from "../../graphql/types/converted";
|
|
40
|
-
import { ForwardedParametersInput } from "../../graphql/inputs/forwarded-parameters.input";
|
|
39
|
+
import type { MessageInput } from "../../graphql/inputs/message.input";
|
|
40
|
+
import type { Message } from "../../graphql/types/converted";
|
|
41
41
|
|
|
42
42
|
import {
|
|
43
43
|
EndpointType,
|
|
44
|
-
EndpointDefinition,
|
|
45
|
-
CopilotKitEndpoint,
|
|
46
|
-
LangGraphPlatformEndpoint,
|
|
44
|
+
type EndpointDefinition,
|
|
45
|
+
type CopilotKitEndpoint,
|
|
46
|
+
type LangGraphPlatformEndpoint,
|
|
47
47
|
} from "./types";
|
|
48
48
|
|
|
49
|
-
import {
|
|
50
|
-
import {
|
|
51
|
-
import { AgentStateInput } from "../../graphql/inputs/agent-state.input";
|
|
52
|
-
import { Agent } from "../../graphql/types/agents-response.type";
|
|
53
|
-
import { ExtensionsInput } from "../../graphql/inputs/extensions.input";
|
|
54
|
-
import { ExtensionsResponse } from "../../graphql/types/extensions-response.type";
|
|
55
|
-
import { MetaEventInput } from "../../graphql/inputs/meta-event.input";
|
|
56
|
-
import {
|
|
57
|
-
CopilotObservabilityConfig,
|
|
58
|
-
LLMRequestData,
|
|
59
|
-
LLMResponseData,
|
|
60
|
-
LLMErrorData,
|
|
61
|
-
} from "../observability";
|
|
62
|
-
import { AbstractAgent } from "@ag-ui/client";
|
|
49
|
+
import type { CopilotObservabilityConfig, LLMRequestData, LLMResponseData } from "../observability";
|
|
50
|
+
import type { AbstractAgent } from "@ag-ui/client";
|
|
63
51
|
|
|
64
52
|
// +++ MCP Imports +++
|
|
65
53
|
import {
|
|
66
|
-
MCPClient,
|
|
67
|
-
MCPEndpointConfig,
|
|
68
|
-
MCPTool,
|
|
54
|
+
type MCPClient,
|
|
55
|
+
type MCPEndpointConfig,
|
|
56
|
+
type MCPTool,
|
|
69
57
|
extractParametersFromSchema,
|
|
70
|
-
convertMCPToolsToActions,
|
|
71
|
-
generateMcpToolInstructions,
|
|
72
58
|
} from "./mcp-tools-utils";
|
|
73
|
-
import {
|
|
74
|
-
import { BasicAgent, BasicAgentConfiguration } from "@copilotkitnext/agent";
|
|
59
|
+
import { BasicAgent, type BasicAgentConfiguration } from "@copilotkitnext/agent";
|
|
75
60
|
// Define the function type alias here or import if defined elsewhere
|
|
76
61
|
type CreateMCPClientFunction = (config: MCPEndpointConfig) => Promise<MCPClient>;
|
|
77
62
|
|
|
@@ -312,8 +297,8 @@ interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []>
|
|
|
312
297
|
/**
|
|
313
298
|
* Central runtime object passed to all request handlers.
|
|
314
299
|
*/
|
|
315
|
-
export class CopilotRuntime {
|
|
316
|
-
params?: CopilotRuntimeConstructorParams
|
|
300
|
+
export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
301
|
+
params?: CopilotRuntimeConstructorParams<T>;
|
|
317
302
|
private observability?: CopilotObservabilityConfig;
|
|
318
303
|
// Cache MCP tools per endpoint to avoid re-fetching repeatedly
|
|
319
304
|
private mcpToolsCache: Map<string, BasicAgentConfiguration["tools"]> = new Map();
|
|
@@ -321,12 +306,24 @@ export class CopilotRuntime {
|
|
|
321
306
|
private _instance: CopilotRuntimeVNext;
|
|
322
307
|
|
|
323
308
|
constructor(
|
|
324
|
-
params?: CopilotRuntimeConstructorParams & PartialBy<CopilotRuntimeOptions, "agents">,
|
|
309
|
+
params?: CopilotRuntimeConstructorParams<T> & PartialBy<CopilotRuntimeOptions, "agents">,
|
|
325
310
|
) {
|
|
326
311
|
const agents = params?.agents ?? {};
|
|
312
|
+
const endpointAgents = this.assignEndpointsToAgents(params?.remoteEndpoints ?? []);
|
|
313
|
+
|
|
314
|
+
// Determine the base runner (user-provided or default)
|
|
315
|
+
const baseRunner = params?.runner ?? new InMemoryAgentRunner();
|
|
316
|
+
|
|
317
|
+
// Wrap with TelemetryAgentRunner unless telemetry is disabled
|
|
318
|
+
// This ensures we always capture agent execution telemetry when enabled,
|
|
319
|
+
// even if the user provides their own custom runner
|
|
320
|
+
const runner = isTelemetryDisabled()
|
|
321
|
+
? baseRunner
|
|
322
|
+
: new TelemetryAgentRunner({ runner: baseRunner });
|
|
323
|
+
|
|
327
324
|
this.runtimeArgs = {
|
|
328
|
-
agents: { ...
|
|
329
|
-
runner
|
|
325
|
+
agents: { ...endpointAgents, ...agents },
|
|
326
|
+
runner,
|
|
330
327
|
// TODO: add support for transcriptionService from CopilotRuntimeOptionsVNext once it is ready
|
|
331
328
|
// transcriptionService: params?.transcriptionService,
|
|
332
329
|
|
|
@@ -345,28 +342,23 @@ export class CopilotRuntime {
|
|
|
345
342
|
return this._instance;
|
|
346
343
|
}
|
|
347
344
|
|
|
348
|
-
private assignEndpointsToAgents(
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
const lgEndpoint = endpoint as LangGraphPlatformEndpoint;
|
|
353
|
-
lgEndpoint.agents.forEach((agent) => {
|
|
354
|
-
const graphId = agent.assistantId ?? agent.name;
|
|
355
|
-
lgAgents[graphId] = new LangGraphAgent({
|
|
356
|
-
deploymentUrl: lgEndpoint.deploymentUrl,
|
|
357
|
-
langsmithApiKey: lgEndpoint.langsmithApiKey,
|
|
358
|
-
graphId,
|
|
359
|
-
});
|
|
360
|
-
});
|
|
345
|
+
private assignEndpointsToAgents(
|
|
346
|
+
endpoints: CopilotRuntimeConstructorParams<T>["remoteEndpoints"],
|
|
347
|
+
): Record<string, AbstractAgent> {
|
|
348
|
+
let result: Record<string, AbstractAgent> = {};
|
|
361
349
|
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
350
|
+
if (
|
|
351
|
+
endpoints.some((endpoint) => resolveEndpointType(endpoint) == EndpointType.LangGraphPlatform)
|
|
352
|
+
) {
|
|
353
|
+
throw new CopilotKitMisuseError({
|
|
354
|
+
message:
|
|
355
|
+
"LangGraphPlatformEndpoint in remoteEndpoints is deprecated. " +
|
|
356
|
+
'Please use the "agents" option instead with LangGraphAgent from "@copilotkit/runtime/langgraph". ' +
|
|
357
|
+
'Example: agents: { myAgent: new LangGraphAgent({ deploymentUrl: "...", graphId: "..." }) }',
|
|
358
|
+
});
|
|
359
|
+
}
|
|
367
360
|
|
|
368
|
-
|
|
369
|
-
}, {});
|
|
361
|
+
return result;
|
|
370
362
|
}
|
|
371
363
|
|
|
372
364
|
handleServiceAdapter(serviceAdapter: CopilotServiceAdapter) {
|
|
@@ -393,7 +385,7 @@ export class CopilotRuntime {
|
|
|
393
385
|
});
|
|
394
386
|
}
|
|
395
387
|
|
|
396
|
-
if (this.params.actions
|
|
388
|
+
if (this.params.actions) {
|
|
397
389
|
const mcpTools = await this.getToolsFromMCP();
|
|
398
390
|
agentsList = this.assignToolsToAgents(agents, [
|
|
399
391
|
...this.getToolsFromActions(this.params.actions),
|
|
@@ -423,6 +415,7 @@ export class CopilotRuntime {
|
|
|
423
415
|
name: action.name,
|
|
424
416
|
description: action.description || "",
|
|
425
417
|
parameters: zodSchema,
|
|
418
|
+
execute: () => Promise.resolve(),
|
|
426
419
|
};
|
|
427
420
|
});
|
|
428
421
|
}
|
|
@@ -454,9 +447,33 @@ export class CopilotRuntime {
|
|
|
454
447
|
}
|
|
455
448
|
|
|
456
449
|
private createOnBeforeRequestHandler(
|
|
457
|
-
params?: CopilotRuntimeConstructorParams & PartialBy<CopilotRuntimeOptions, "agents">,
|
|
450
|
+
params?: CopilotRuntimeConstructorParams<T> & PartialBy<CopilotRuntimeOptions, "agents">,
|
|
458
451
|
) {
|
|
459
452
|
return async (hookParams: BeforeRequestMiddlewareFnParameters[0]) => {
|
|
453
|
+
const { request } = hookParams;
|
|
454
|
+
|
|
455
|
+
// Capture telemetry for copilot request creation
|
|
456
|
+
const publicApiKey = request.headers.get("x-copilotcloud-public-api-key");
|
|
457
|
+
const body = (await readBody(request)) as RunAgentInput;
|
|
458
|
+
const forwardedProps = body.forwardedProps as
|
|
459
|
+
| {
|
|
460
|
+
cloud?: { guardrails?: unknown };
|
|
461
|
+
metadata?: { requestType?: string };
|
|
462
|
+
}
|
|
463
|
+
| undefined;
|
|
464
|
+
|
|
465
|
+
// Get cloud base URL from environment or default
|
|
466
|
+
const cloudBaseUrl =
|
|
467
|
+
process.env.COPILOT_CLOUD_BASE_URL || "https://api.cloud.copilotkit.ai";
|
|
468
|
+
|
|
469
|
+
telemetry.capture("oss.runtime.copilot_request_created", {
|
|
470
|
+
"cloud.guardrails.enabled": forwardedProps?.cloud?.guardrails !== undefined,
|
|
471
|
+
requestType: forwardedProps?.metadata?.requestType ?? "unknown",
|
|
472
|
+
"cloud.api_key_provided": !!publicApiKey,
|
|
473
|
+
...(publicApiKey ? { "cloud.public_api_key": publicApiKey } : {}),
|
|
474
|
+
"cloud.base_url": cloudBaseUrl,
|
|
475
|
+
});
|
|
476
|
+
|
|
460
477
|
// TODO: get public api key and run with expected data
|
|
461
478
|
// if (this.observability?.enabled && this.params.publicApiKey) {
|
|
462
479
|
// this.logObservabilityBeforeRequest()
|
|
@@ -467,7 +484,6 @@ export class CopilotRuntime {
|
|
|
467
484
|
|
|
468
485
|
if (params?.middleware?.onBeforeRequest) {
|
|
469
486
|
const { request, runtime, path } = hookParams;
|
|
470
|
-
const body = (await readBody(request)) as RunAgentInput;
|
|
471
487
|
const gqlMessages = (aguiToGQL(body.messages) as Message[]).reduce(
|
|
472
488
|
(acc, msg) => {
|
|
473
489
|
if ("role" in msg && msg.role === "user") {
|
|
@@ -492,7 +508,7 @@ export class CopilotRuntime {
|
|
|
492
508
|
}
|
|
493
509
|
|
|
494
510
|
private createOnAfterRequestHandler(
|
|
495
|
-
params?: CopilotRuntimeConstructorParams & PartialBy<CopilotRuntimeOptions, "agents">,
|
|
511
|
+
params?: CopilotRuntimeConstructorParams<T> & PartialBy<CopilotRuntimeOptions, "agents">,
|
|
496
512
|
) {
|
|
497
513
|
return async (hookParams: AfterRequestMiddlewareFnParameters[0]) => {
|
|
498
514
|
// TODO: get public api key and run with expected data
|
|
@@ -636,6 +652,7 @@ export class CopilotRuntime {
|
|
|
636
652
|
name: toolName,
|
|
637
653
|
description: tool.description || `MCP tool: ${toolName} (from ${endpointUrl})`,
|
|
638
654
|
parameters: zodSchema,
|
|
655
|
+
execute: () => Promise.resolve(),
|
|
639
656
|
};
|
|
640
657
|
},
|
|
641
658
|
);
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TelemetryAgentRunner - A wrapper around AgentRunner that adds telemetry
|
|
3
|
+
* for agent execution streams.
|
|
4
|
+
*
|
|
5
|
+
* This captures the following telemetry events:
|
|
6
|
+
* - oss.runtime.agent_execution_stream_started - when an agent execution starts
|
|
7
|
+
* - oss.runtime.agent_execution_stream_ended - when an agent execution completes
|
|
8
|
+
* - oss.runtime.agent_execution_stream_errored - when an agent execution fails
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import { type AgentRunner, InMemoryAgentRunner } from "@copilotkitnext/runtime";
|
|
12
|
+
import { createHash } from "node:crypto";
|
|
13
|
+
import { tap, catchError, finalize } from "rxjs";
|
|
14
|
+
import telemetry from "../telemetry-client";
|
|
15
|
+
import type { AgentExecutionResponseInfo } from "@copilotkit/shared/src/telemetry/events";
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Configuration options for TelemetryAgentRunner
|
|
19
|
+
*/
|
|
20
|
+
export interface TelemetryAgentRunnerConfig {
|
|
21
|
+
/**
|
|
22
|
+
* The underlying runner to delegate to
|
|
23
|
+
* If not provided, defaults to InMemoryAgentRunner
|
|
24
|
+
*/
|
|
25
|
+
runner?: AgentRunner;
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Optional LangSmith API key (will be hashed for telemetry)
|
|
29
|
+
*/
|
|
30
|
+
langsmithApiKey?: string;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* An AgentRunner wrapper that adds telemetry tracking for agent executions.
|
|
35
|
+
*
|
|
36
|
+
* Usage:
|
|
37
|
+
* ```ts
|
|
38
|
+
* const runtime = new CopilotRuntime({
|
|
39
|
+
* runner: new TelemetryAgentRunner(),
|
|
40
|
+
* // or with custom runner:
|
|
41
|
+
* runner: new TelemetryAgentRunner({ runner: customRunner }),
|
|
42
|
+
* });
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export class TelemetryAgentRunner implements AgentRunner {
|
|
46
|
+
private readonly _runner: AgentRunner;
|
|
47
|
+
private readonly hashedLgcKey: string | undefined;
|
|
48
|
+
|
|
49
|
+
constructor(config?: TelemetryAgentRunnerConfig) {
|
|
50
|
+
this._runner = config?.runner ?? new InMemoryAgentRunner();
|
|
51
|
+
this.hashedLgcKey = config?.langsmithApiKey
|
|
52
|
+
? createHash("sha256").update(config.langsmithApiKey).digest("hex")
|
|
53
|
+
: undefined;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
/**
|
|
57
|
+
* Runs an agent with telemetry tracking.
|
|
58
|
+
* Wraps the underlying runner's Observable stream with telemetry events.
|
|
59
|
+
*/
|
|
60
|
+
run(
|
|
61
|
+
...args: Parameters<AgentRunner["run"]>
|
|
62
|
+
): ReturnType<AgentRunner["run"]> {
|
|
63
|
+
const streamInfo: AgentExecutionResponseInfo = {
|
|
64
|
+
hashedLgcKey: this.hashedLgcKey,
|
|
65
|
+
};
|
|
66
|
+
let streamErrored = false;
|
|
67
|
+
|
|
68
|
+
// Capture stream started event
|
|
69
|
+
telemetry.capture("oss.runtime.agent_execution_stream_started", {
|
|
70
|
+
hashedLgcKey: this.hashedLgcKey,
|
|
71
|
+
});
|
|
72
|
+
|
|
73
|
+
// Delegate to the underlying runner and wrap with telemetry
|
|
74
|
+
return this._runner.run(...args).pipe(
|
|
75
|
+
// Extract metadata from events if available
|
|
76
|
+
tap((event) => {
|
|
77
|
+
// Try to extract provider/model info from raw events
|
|
78
|
+
const rawEvent = (event as { rawEvent?: { metadata?: Record<string, unknown>; data?: Record<string, unknown> } }).rawEvent;
|
|
79
|
+
if (rawEvent?.data) {
|
|
80
|
+
const data = rawEvent.data as { output?: { model?: string } };
|
|
81
|
+
if (data?.output?.model) {
|
|
82
|
+
streamInfo.model = data.output.model;
|
|
83
|
+
streamInfo.provider = data.output.model;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (rawEvent?.metadata) {
|
|
87
|
+
const metadata = rawEvent.metadata as { langgraph_host?: string; langgraph_version?: string };
|
|
88
|
+
if (metadata?.langgraph_host) {
|
|
89
|
+
streamInfo.langGraphHost = metadata.langgraph_host;
|
|
90
|
+
}
|
|
91
|
+
if (metadata?.langgraph_version) {
|
|
92
|
+
streamInfo.langGraphVersion = metadata.langgraph_version;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}),
|
|
96
|
+
catchError((error) => {
|
|
97
|
+
// Capture stream error event
|
|
98
|
+
streamErrored = true;
|
|
99
|
+
telemetry.capture("oss.runtime.agent_execution_stream_errored", {
|
|
100
|
+
...streamInfo,
|
|
101
|
+
error: error instanceof Error ? error.message : String(error),
|
|
102
|
+
});
|
|
103
|
+
throw error;
|
|
104
|
+
}),
|
|
105
|
+
finalize(() => {
|
|
106
|
+
// Capture stream ended event (only if not errored)
|
|
107
|
+
if (!streamErrored) {
|
|
108
|
+
telemetry.capture("oss.runtime.agent_execution_stream_ended", streamInfo);
|
|
109
|
+
}
|
|
110
|
+
}),
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* Delegates to the underlying runner's connect method
|
|
116
|
+
*/
|
|
117
|
+
connect(...args: Parameters<AgentRunner["connect"]>): ReturnType<AgentRunner["connect"]> {
|
|
118
|
+
return this._runner.connect(...args);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
/**
|
|
122
|
+
* Delegates to the underlying runner's isRunning method
|
|
123
|
+
*/
|
|
124
|
+
isRunning(...args: Parameters<AgentRunner["isRunning"]>): ReturnType<AgentRunner["isRunning"]> {
|
|
125
|
+
return this._runner.isRunning(...args);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* Delegates to the underlying runner's stop method
|
|
130
|
+
*/
|
|
131
|
+
stop(...args: Parameters<AgentRunner["stop"]>): ReturnType<AgentRunner["stop"]> {
|
|
132
|
+
return this._runner.stop(...args);
|
|
133
|
+
}
|
|
134
|
+
}
|