@copilotkit/runtime 1.4.0-pre-1-4-0.11 → 1.4.0-pre-1-4-0-alpha.10
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 +33 -100
- package/dist/{chunk-BNQDVBQH.mjs → chunk-56IQ6PGC.mjs} +449 -75
- package/dist/chunk-56IQ6PGC.mjs.map +1 -0
- package/dist/chunk-DFOKBSIS.mjs +1 -0
- package/dist/chunk-DFOKBSIS.mjs.map +1 -0
- package/dist/{chunk-VBGS6IWV.mjs → chunk-RDHJQVWH.mjs} +483 -71
- package/dist/chunk-RDHJQVWH.mjs.map +1 -0
- package/dist/{chunk-V2YEM4Z5.mjs → chunk-SBWLAAB3.mjs} +4 -3
- package/dist/chunk-SBWLAAB3.mjs.map +1 -0
- package/dist/{chunk-677K33J7.mjs → chunk-SVL5LEKB.mjs} +4 -3
- package/dist/chunk-SVL5LEKB.mjs.map +1 -0
- package/dist/{chunk-3DNY5YTL.mjs → chunk-YUJSVJWS.mjs} +5 -4
- package/dist/chunk-YUJSVJWS.mjs.map +1 -0
- package/dist/{copilot-runtime-8d3f40c7.d.ts → copilot-runtime-dbe5fa02.d.ts} +4 -4
- package/dist/{groq-adapter-dbfba3eb.d.ts → groq-adapter-192d2413.d.ts} +1 -1
- package/dist/index.d.ts +3 -3
- package/dist/index.js +486 -169
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +22 -22
- package/dist/index.mjs.map +1 -1
- package/dist/{langserve-f00629d2.d.ts → langserve-878c62b9.d.ts} +46 -9
- package/dist/lib/index.d.ts +3 -3
- package/dist/lib/index.js +465 -163
- package/dist/lib/index.js.map +1 -1
- package/dist/lib/index.mjs +21 -21
- package/dist/lib/integrations/index.d.ts +3 -3
- package/dist/lib/integrations/index.js +161 -85
- package/dist/lib/integrations/index.js.map +1 -1
- package/dist/lib/integrations/index.mjs +5 -5
- package/dist/lib/integrations/nest/index.d.ts +2 -2
- package/dist/lib/integrations/nest/index.js +158 -82
- package/dist/lib/integrations/nest/index.js.map +1 -1
- package/dist/lib/integrations/nest/index.mjs +3 -3
- package/dist/lib/integrations/node-express/index.d.ts +2 -2
- package/dist/lib/integrations/node-express/index.js +158 -82
- package/dist/lib/integrations/node-express/index.js.map +1 -1
- package/dist/lib/integrations/node-express/index.mjs +3 -3
- package/dist/lib/integrations/node-http/index.d.ts +2 -2
- package/dist/lib/integrations/node-http/index.js +157 -81
- package/dist/lib/integrations/node-http/index.js.map +1 -1
- package/dist/lib/integrations/node-http/index.mjs +2 -2
- package/dist/service-adapters/index.d.ts +3 -3
- package/dist/service-adapters/index.js +243 -73
- package/dist/service-adapters/index.js.map +1 -1
- package/dist/service-adapters/index.mjs +1 -2
- package/package.json +4 -4
- package/src/agents/langgraph/event-source.ts +12 -0
- package/src/agents/langgraph/events.ts +2 -0
- package/src/graphql/resolvers/copilot.resolver.ts +28 -2
- package/src/lib/integrations/nest/index.ts +5 -2
- package/src/lib/integrations/nextjs/app-router.ts +5 -2
- package/src/lib/integrations/nextjs/pages-router.ts +5 -2
- package/src/lib/integrations/node-express/index.ts +5 -2
- package/src/lib/integrations/node-http/index.ts +5 -2
- package/src/lib/runtime/copilot-runtime.ts +48 -42
- package/src/lib/runtime/remote-action-constructors.ts +17 -3
- package/src/lib/runtime/remote-lg-cloud-action.ts +41 -15
- package/src/lib/telemetry-client.ts +43 -0
- package/src/service-adapters/anthropic/anthropic-adapter.ts +15 -6
- package/src/service-adapters/events.ts +86 -36
- package/src/service-adapters/experimental/ollama/ollama-adapter.ts +7 -3
- package/src/service-adapters/google/google-genai-adapter.ts +2 -2
- package/src/service-adapters/groq/groq-adapter.ts +22 -8
- package/src/service-adapters/langchain/langchain-adapter.ts +22 -16
- package/src/service-adapters/langchain/utils.ts +47 -31
- package/src/service-adapters/openai/openai-adapter.ts +25 -8
- package/src/service-adapters/openai/openai-assistant-adapter.ts +21 -8
- package/src/service-adapters/unify/unify-adapter.ts +28 -11
- package/dist/chunk-3DNY5YTL.mjs.map +0 -1
- package/dist/chunk-677K33J7.mjs.map +0 -1
- package/dist/chunk-BNQDVBQH.mjs.map +0 -1
- package/dist/chunk-FL67XJAX.mjs +0 -288
- package/dist/chunk-FL67XJAX.mjs.map +0 -1
- package/dist/chunk-MXXPWWBF.mjs +0 -218
- package/dist/chunk-MXXPWWBF.mjs.map +0 -1
- package/dist/chunk-V2YEM4Z5.mjs.map +0 -1
- package/dist/chunk-VBGS6IWV.mjs.map +0 -1
|
@@ -8,6 +8,8 @@ export enum LangGraphEventTypes {
|
|
|
8
8
|
OnToolStart = "on_tool_start",
|
|
9
9
|
OnToolEnd = "on_tool_end",
|
|
10
10
|
OnCopilotKitStateSync = "on_copilotkit_state_sync",
|
|
11
|
+
OnCopilotKitEmitMessage = "on_copilotkit_emit_message",
|
|
12
|
+
OnCopilotKitEmitToolCall = "on_copilotkit_emit_tool_call",
|
|
11
13
|
OnCustomEvent = "on_custom_event",
|
|
12
14
|
}
|
|
13
15
|
|
|
@@ -3,6 +3,7 @@ import {
|
|
|
3
3
|
ReplaySubject,
|
|
4
4
|
Subject,
|
|
5
5
|
Subscription,
|
|
6
|
+
filter,
|
|
6
7
|
finalize,
|
|
7
8
|
firstValueFrom,
|
|
8
9
|
shareReplay,
|
|
@@ -286,7 +287,19 @@ export class CopilotResolver {
|
|
|
286
287
|
// skip until this message start event
|
|
287
288
|
skipWhile((e) => e !== event),
|
|
288
289
|
// take until the message end event
|
|
289
|
-
takeWhile(
|
|
290
|
+
takeWhile(
|
|
291
|
+
(e) =>
|
|
292
|
+
!(
|
|
293
|
+
e.type === RuntimeEventTypes.TextMessageEnd &&
|
|
294
|
+
e.messageId == event.messageId
|
|
295
|
+
),
|
|
296
|
+
),
|
|
297
|
+
// filter out any other message events or message ids
|
|
298
|
+
filter(
|
|
299
|
+
(e) =>
|
|
300
|
+
e.type == RuntimeEventTypes.TextMessageContent &&
|
|
301
|
+
e.messageId == event.messageId,
|
|
302
|
+
),
|
|
290
303
|
);
|
|
291
304
|
|
|
292
305
|
// signal when we are done streaming
|
|
@@ -367,7 +380,20 @@ export class CopilotResolver {
|
|
|
367
380
|
logger.debug("Action execution start event received");
|
|
368
381
|
const actionExecutionArgumentStream = eventStream.pipe(
|
|
369
382
|
skipWhile((e) => e !== event),
|
|
370
|
-
|
|
383
|
+
// take until the action execution end event
|
|
384
|
+
takeWhile(
|
|
385
|
+
(e) =>
|
|
386
|
+
!(
|
|
387
|
+
e.type === RuntimeEventTypes.ActionExecutionEnd &&
|
|
388
|
+
e.actionExecutionId == event.actionExecutionId
|
|
389
|
+
),
|
|
390
|
+
),
|
|
391
|
+
// filter out any other action execution events or action execution ids
|
|
392
|
+
filter(
|
|
393
|
+
(e) =>
|
|
394
|
+
e.type == RuntimeEventTypes.ActionExecutionArgs &&
|
|
395
|
+
e.actionExecutionId == event.actionExecutionId,
|
|
396
|
+
),
|
|
371
397
|
);
|
|
372
398
|
const streamingArgumentsStatus = new Subject<typeof MessageStatusUnion>();
|
|
373
399
|
pushMessage({
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CreateCopilotRuntimeServerOptions } from "../shared";
|
|
2
2
|
import { copilotRuntimeNodeHttpEndpoint } from "../node-http";
|
|
3
|
-
import telemetry from "../../telemetry-client";
|
|
3
|
+
import telemetry, { getRuntimeInstanceTelemetryInfo } from "../../telemetry-client";
|
|
4
4
|
|
|
5
5
|
export function copilotRuntimeNestEndpoint(options: CreateCopilotRuntimeServerOptions) {
|
|
6
6
|
telemetry.setGlobalProperties({
|
|
@@ -9,6 +9,9 @@ export function copilotRuntimeNestEndpoint(options: CreateCopilotRuntimeServerOp
|
|
|
9
9
|
},
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
telemetry.capture(
|
|
12
|
+
telemetry.capture(
|
|
13
|
+
"oss.runtime.instance_created",
|
|
14
|
+
getRuntimeInstanceTelemetryInfo(options.runtime),
|
|
15
|
+
);
|
|
13
16
|
return copilotRuntimeNodeHttpEndpoint(options);
|
|
14
17
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createYoga } from "graphql-yoga";
|
|
2
2
|
import { CreateCopilotRuntimeServerOptions, getCommonConfig } from "../shared";
|
|
3
|
-
import telemetry from "../../telemetry-client";
|
|
3
|
+
import telemetry, { getRuntimeInstanceTelemetryInfo } from "../../telemetry-client";
|
|
4
4
|
|
|
5
5
|
export function copilotRuntimeNextJSAppRouterEndpoint(options: CreateCopilotRuntimeServerOptions) {
|
|
6
6
|
const commonConfig = getCommonConfig(options);
|
|
@@ -17,7 +17,10 @@ export function copilotRuntimeNextJSAppRouterEndpoint(options: CreateCopilotRunt
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
telemetry.capture(
|
|
20
|
+
telemetry.capture(
|
|
21
|
+
"oss.runtime.instance_created",
|
|
22
|
+
getRuntimeInstanceTelemetryInfo(options.runtime),
|
|
23
|
+
);
|
|
21
24
|
|
|
22
25
|
const logger = commonConfig.logging;
|
|
23
26
|
logger.debug("Creating NextJS App Router endpoint");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { YogaServerInstance, createYoga } from "graphql-yoga";
|
|
2
2
|
import { CreateCopilotRuntimeServerOptions, GraphQLContext, getCommonConfig } from "../shared";
|
|
3
|
-
import telemetry from "../../telemetry-client";
|
|
3
|
+
import telemetry, { getRuntimeInstanceTelemetryInfo } from "../../telemetry-client";
|
|
4
4
|
|
|
5
5
|
export const config = {
|
|
6
6
|
api: {
|
|
@@ -32,7 +32,10 @@ export function copilotRuntimeNextJSPagesRouterEndpoint(
|
|
|
32
32
|
});
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
telemetry.capture(
|
|
35
|
+
telemetry.capture(
|
|
36
|
+
"oss.runtime.instance_created",
|
|
37
|
+
getRuntimeInstanceTelemetryInfo(options.runtime),
|
|
38
|
+
);
|
|
36
39
|
|
|
37
40
|
const logger = commonConfig.logging;
|
|
38
41
|
logger.debug("Creating NextJS Pages Router endpoint");
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { CreateCopilotRuntimeServerOptions } from "../shared";
|
|
2
2
|
import { copilotRuntimeNodeHttpEndpoint } from "../node-http";
|
|
3
|
-
import telemetry from "../../telemetry-client";
|
|
3
|
+
import telemetry, { getRuntimeInstanceTelemetryInfo } from "../../telemetry-client";
|
|
4
4
|
|
|
5
5
|
export function copilotRuntimeNodeExpressEndpoint(options: CreateCopilotRuntimeServerOptions) {
|
|
6
6
|
telemetry.setGlobalProperties({
|
|
@@ -9,6 +9,9 @@ export function copilotRuntimeNodeExpressEndpoint(options: CreateCopilotRuntimeS
|
|
|
9
9
|
},
|
|
10
10
|
});
|
|
11
11
|
|
|
12
|
-
telemetry.capture(
|
|
12
|
+
telemetry.capture(
|
|
13
|
+
"oss.runtime.instance_created",
|
|
14
|
+
getRuntimeInstanceTelemetryInfo(options.runtime),
|
|
15
|
+
);
|
|
13
16
|
return copilotRuntimeNodeHttpEndpoint(options);
|
|
14
17
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { createYoga } from "graphql-yoga";
|
|
2
2
|
import { CreateCopilotRuntimeServerOptions, getCommonConfig } from "../shared";
|
|
3
|
-
import telemetry from "../../telemetry-client";
|
|
3
|
+
import telemetry, { getRuntimeInstanceTelemetryInfo } from "../../telemetry-client";
|
|
4
4
|
|
|
5
5
|
export function copilotRuntimeNodeHttpEndpoint(options: CreateCopilotRuntimeServerOptions) {
|
|
6
6
|
const commonConfig = getCommonConfig(options);
|
|
@@ -17,7 +17,10 @@ export function copilotRuntimeNodeHttpEndpoint(options: CreateCopilotRuntimeServ
|
|
|
17
17
|
});
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
telemetry.capture(
|
|
20
|
+
telemetry.capture(
|
|
21
|
+
"oss.runtime.instance_created",
|
|
22
|
+
getRuntimeInstanceTelemetryInfo(options.runtime),
|
|
23
|
+
);
|
|
21
24
|
|
|
22
25
|
const logger = commonConfig.logging;
|
|
23
26
|
logger.debug("Creating Node HTTP endpoint");
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
* ```
|
|
13
13
|
*/
|
|
14
14
|
|
|
15
|
-
import { Action, actionParametersToJsonSchema, Parameter } from "@copilotkit/shared";
|
|
15
|
+
import { Action, actionParametersToJsonSchema, Parameter, randomId } from "@copilotkit/shared";
|
|
16
16
|
import { CopilotServiceAdapter, RemoteChain, RemoteChainParameters } from "../../service-adapters";
|
|
17
17
|
import { MessageInput } from "../../graphql/inputs/message.input";
|
|
18
18
|
import { ActionInput } from "../../graphql/inputs/action.input";
|
|
@@ -142,7 +142,7 @@ export interface CopilotRuntimeConstructorParams<T extends Parameter[] | [] = []
|
|
|
142
142
|
|
|
143
143
|
export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
144
144
|
public actions: ActionsConfiguration<T>;
|
|
145
|
-
|
|
145
|
+
public remoteEndpointDefinitions: EndpointDefinition[];
|
|
146
146
|
private langserve: Promise<Action<any>>[] = [];
|
|
147
147
|
private onBeforeRequest?: OnBeforeRequestHandler;
|
|
148
148
|
private onAfterRequest?: OnAfterRequestHandler;
|
|
@@ -155,7 +155,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
155
155
|
this.langserve.push(remoteChain.toAction());
|
|
156
156
|
}
|
|
157
157
|
|
|
158
|
-
this.remoteEndpointDefinitions = params?.remoteEndpoints
|
|
158
|
+
this.remoteEndpointDefinitions = params?.remoteEndpoints ?? params?.remoteActions ?? [];
|
|
159
159
|
|
|
160
160
|
this.onBeforeRequest = params?.middleware?.onBeforeRequest;
|
|
161
161
|
this.onAfterRequest = params?.middleware?.onAfterRequest;
|
|
@@ -175,36 +175,36 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
175
175
|
url,
|
|
176
176
|
} = request;
|
|
177
177
|
|
|
178
|
-
|
|
179
|
-
return this.processAgentRequest(request);
|
|
180
|
-
}
|
|
178
|
+
const eventSource = new RuntimeEventSource();
|
|
181
179
|
|
|
182
|
-
|
|
180
|
+
try {
|
|
181
|
+
if (agentSession) {
|
|
182
|
+
return await this.processAgentRequest(request);
|
|
183
|
+
}
|
|
183
184
|
|
|
184
|
-
|
|
185
|
-
const serverSideActions = await this.getServerSideActions(request);
|
|
185
|
+
const messages = rawMessages.filter((message) => !message.agentStateMessage);
|
|
186
186
|
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
description: action.description,
|
|
190
|
-
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters)),
|
|
191
|
-
}));
|
|
187
|
+
const inputMessages = convertGqlInputToMessages(messages);
|
|
188
|
+
const serverSideActions = await this.getServerSideActions(request);
|
|
192
189
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
190
|
+
const serverSideActionsInput: ActionInput[] = serverSideActions.map((action) => ({
|
|
191
|
+
name: action.name,
|
|
192
|
+
description: action.description,
|
|
193
|
+
jsonSchema: JSON.stringify(actionParametersToJsonSchema(action.parameters)),
|
|
194
|
+
}));
|
|
197
195
|
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
properties: graphqlContext.properties,
|
|
203
|
-
url,
|
|
204
|
-
});
|
|
196
|
+
const actionInputs = flattenToolCallsNoDuplicates([
|
|
197
|
+
...serverSideActionsInput,
|
|
198
|
+
...clientSideActionsInput,
|
|
199
|
+
]);
|
|
205
200
|
|
|
206
|
-
|
|
207
|
-
|
|
201
|
+
await this.onBeforeRequest?.({
|
|
202
|
+
threadId,
|
|
203
|
+
runId,
|
|
204
|
+
inputMessages,
|
|
205
|
+
properties: graphqlContext.properties,
|
|
206
|
+
url,
|
|
207
|
+
});
|
|
208
208
|
|
|
209
209
|
const result = await serviceAdapter.process({
|
|
210
210
|
messages: inputMessages,
|
|
@@ -244,7 +244,14 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
244
244
|
};
|
|
245
245
|
} catch (error) {
|
|
246
246
|
console.error("Error getting response:", error);
|
|
247
|
-
|
|
247
|
+
eventSource.sendErrorMessageToChat();
|
|
248
|
+
return {
|
|
249
|
+
threadId: threadId || randomId(),
|
|
250
|
+
runId: runId || randomId(),
|
|
251
|
+
eventSource,
|
|
252
|
+
serverSideActions: [],
|
|
253
|
+
actionInputsWithoutAgents: [],
|
|
254
|
+
};
|
|
248
255
|
}
|
|
249
256
|
}
|
|
250
257
|
|
|
@@ -344,7 +351,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
344
351
|
(endpoint) =>
|
|
345
352
|
({
|
|
346
353
|
...endpoint,
|
|
347
|
-
type:
|
|
354
|
+
type: resolveEndpointType(endpoint),
|
|
348
355
|
}) as EndpointDefinition,
|
|
349
356
|
);
|
|
350
357
|
|
|
@@ -363,19 +370,6 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
|
|
|
363
370
|
|
|
364
371
|
return [...configuredActions, ...langserveFunctions, ...remoteActions];
|
|
365
372
|
}
|
|
366
|
-
|
|
367
|
-
private resolveEndpointType(endpoint: EndpointDefinition) {
|
|
368
|
-
if (
|
|
369
|
-
!endpoint.type &&
|
|
370
|
-
"langsmithApiKey" in endpoint &&
|
|
371
|
-
"deploymentUrl" in endpoint &&
|
|
372
|
-
"agents" in endpoint
|
|
373
|
-
) {
|
|
374
|
-
return EndpointType.LangGraphCloud;
|
|
375
|
-
}
|
|
376
|
-
|
|
377
|
-
return endpoint.type;
|
|
378
|
-
}
|
|
379
373
|
}
|
|
380
374
|
|
|
381
375
|
export function flattenToolCallsNoDuplicates(toolsByPriority: ActionInput[]): ActionInput[] {
|
|
@@ -406,3 +400,15 @@ export function langGraphCloudEndpoint(
|
|
|
406
400
|
type: EndpointType.LangGraphCloud,
|
|
407
401
|
};
|
|
408
402
|
}
|
|
403
|
+
|
|
404
|
+
export function resolveEndpointType(endpoint: EndpointDefinition) {
|
|
405
|
+
if (!endpoint.type) {
|
|
406
|
+
if ("langsmithApiKey" in endpoint && "deploymentUrl" in endpoint && "agents" in endpoint) {
|
|
407
|
+
return EndpointType.LangGraphCloud;
|
|
408
|
+
} else {
|
|
409
|
+
return EndpointType.CopilotKit;
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
return endpoint.type;
|
|
414
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
1
2
|
import {
|
|
2
3
|
CopilotKitEndpoint,
|
|
3
4
|
LangGraphAgentHandlerParams,
|
|
@@ -42,7 +43,12 @@ export function constructLGCRemoteAction({
|
|
|
42
43
|
}: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
|
|
43
44
|
logger.debug({ actionName: agent.name }, "Executing LangGraph Cloud agent");
|
|
44
45
|
|
|
45
|
-
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
46
|
+
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
47
|
+
agentExecution: true,
|
|
48
|
+
type: "langgraph-cloud",
|
|
49
|
+
agentsAmount: endpoint.agents.length,
|
|
50
|
+
hashedLgcKey: createHash("sha256").update(endpoint.langsmithApiKey).digest("hex"),
|
|
51
|
+
});
|
|
46
52
|
|
|
47
53
|
let state = {};
|
|
48
54
|
if (agentStates) {
|
|
@@ -111,7 +117,11 @@ export function constructRemoteActions({
|
|
|
111
117
|
logger.debug({ actionName: action.name, args }, "Executing remote action");
|
|
112
118
|
|
|
113
119
|
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
114
|
-
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
120
|
+
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
121
|
+
agentExecution: false,
|
|
122
|
+
type: "self-hosted",
|
|
123
|
+
agentsAmount: json["agents"].length,
|
|
124
|
+
});
|
|
115
125
|
|
|
116
126
|
try {
|
|
117
127
|
const response = await fetch(`${url}/actions/execute`, {
|
|
@@ -162,7 +172,11 @@ export function constructRemoteActions({
|
|
|
162
172
|
logger.debug({ actionName: agent.name }, "Executing remote agent");
|
|
163
173
|
|
|
164
174
|
const headers = createHeaders(onBeforeRequest, graphqlContext);
|
|
165
|
-
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
175
|
+
telemetry.capture("oss.runtime.remote_action_executed", {
|
|
176
|
+
agentExecution: true,
|
|
177
|
+
type: "self-hosted",
|
|
178
|
+
agentsAmount: json["agents"].length,
|
|
179
|
+
});
|
|
166
180
|
|
|
167
181
|
let state = {};
|
|
168
182
|
if (agentStates) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Client } from "@langchain/langgraph-sdk";
|
|
2
|
-
import { randomUUID } from "node:crypto";
|
|
2
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
3
3
|
import { parse as parsePartialJson } from "partial-json";
|
|
4
4
|
import { Logger } from "pino";
|
|
5
5
|
import { ActionInput } from "../../graphql/inputs/action.input";
|
|
@@ -8,6 +8,7 @@ import { CopilotRequestContextProperties } from "../integrations";
|
|
|
8
8
|
import { Message, MessageType } from "../../graphql/types/converted";
|
|
9
9
|
import { MessageRole } from "../../graphql/types/enums";
|
|
10
10
|
import { CustomEventNames, LangGraphEventTypes } from "../../agents/langgraph/events";
|
|
11
|
+
import telemetry from "../telemetry-client";
|
|
11
12
|
|
|
12
13
|
type State = Record<string, any>;
|
|
13
14
|
|
|
@@ -88,7 +89,6 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
88
89
|
let state = initialState;
|
|
89
90
|
const { name, assistantId: initialAssistantId } = agent;
|
|
90
91
|
|
|
91
|
-
// TODO: deploymentUrl is not required in local development
|
|
92
92
|
const client = new Client({ apiUrl: deploymentUrl, apiKey: langsmithApiKey });
|
|
93
93
|
let initialThreadId = agrsInitialThreadId;
|
|
94
94
|
const wasInitiatedWithExistingThread = !!initialThreadId;
|
|
@@ -152,8 +152,22 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
152
152
|
|
|
153
153
|
let latestStateValues = {};
|
|
154
154
|
let updatedState = state;
|
|
155
|
+
// If a manual emittance happens, it is the ultimate source of truth of state, unless a node has exited.
|
|
156
|
+
// Therefore, this value should either hold null, or the only edition of state that should be used.
|
|
157
|
+
let manuallyEmittedState = null;
|
|
158
|
+
let streamInfo: {
|
|
159
|
+
provider?: string;
|
|
160
|
+
langGraphHost?: string;
|
|
161
|
+
langGraphVersion?: string;
|
|
162
|
+
hashedLgcKey: string;
|
|
163
|
+
} = {
|
|
164
|
+
hashedLgcKey: createHash("sha256").update(langsmithApiKey).digest("hex"),
|
|
165
|
+
};
|
|
155
166
|
|
|
156
167
|
try {
|
|
168
|
+
telemetry.capture("oss.runtime.agent_execution_stream_started", {
|
|
169
|
+
hashedLgcKey: streamInfo.hashedLgcKey,
|
|
170
|
+
});
|
|
157
171
|
for await (const chunk of streamResponse) {
|
|
158
172
|
if (!["events", "values", "error"].includes(chunk.event)) continue;
|
|
159
173
|
|
|
@@ -174,6 +188,16 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
174
188
|
externalRunId = runId;
|
|
175
189
|
const metadata = event.metadata;
|
|
176
190
|
|
|
191
|
+
if (event.data?.output?.model != null && event.data?.output?.model != "") {
|
|
192
|
+
streamInfo.provider = event.data?.output?.model;
|
|
193
|
+
}
|
|
194
|
+
if (metadata.langgraph_host != null && metadata.langgraph_host != "") {
|
|
195
|
+
streamInfo.langGraphHost = metadata.langgraph_host;
|
|
196
|
+
}
|
|
197
|
+
if (metadata.langgraph_version != null && metadata.langgraph_version != "") {
|
|
198
|
+
streamInfo.langGraphVersion = metadata.langgraph_version;
|
|
199
|
+
}
|
|
200
|
+
|
|
177
201
|
shouldExit =
|
|
178
202
|
shouldExit ||
|
|
179
203
|
(eventType === LangGraphEventTypes.OnCustomEvent &&
|
|
@@ -184,33 +208,36 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
184
208
|
eventType === LangGraphEventTypes.OnCustomEvent &&
|
|
185
209
|
event.name === CustomEventNames.CopilotKitManuallyEmitIntermediateState;
|
|
186
210
|
|
|
211
|
+
const exitingNode =
|
|
212
|
+
nodeName === currentNodeName && eventType === LangGraphEventTypes.OnChainEnd;
|
|
213
|
+
|
|
214
|
+
// See manuallyEmittedState for explanation
|
|
215
|
+
if (exitingNode) {
|
|
216
|
+
manuallyEmittedState = null;
|
|
217
|
+
}
|
|
218
|
+
|
|
187
219
|
// we only want to update the node name under certain conditions
|
|
188
220
|
// since we don't need any internal node names to be sent to the frontend
|
|
189
221
|
if (graphInfo["nodes"].some((node) => node.id === currentNodeName)) {
|
|
190
222
|
nodeName = currentNodeName;
|
|
191
|
-
|
|
192
|
-
// only update state from values when entering or exiting a known node
|
|
193
|
-
if (
|
|
194
|
-
eventType === LangGraphEventTypes.OnChainStart ||
|
|
195
|
-
eventType === LangGraphEventTypes.OnChainEnd
|
|
196
|
-
) {
|
|
197
|
-
updatedState = latestStateValues;
|
|
198
|
-
}
|
|
199
223
|
}
|
|
200
224
|
|
|
225
|
+
updatedState = manuallyEmittedState ?? latestStateValues;
|
|
226
|
+
|
|
201
227
|
if (!nodeName) {
|
|
202
228
|
continue;
|
|
203
229
|
}
|
|
204
230
|
|
|
205
231
|
if (manuallyEmitIntermediateState) {
|
|
206
|
-
|
|
232
|
+
// See manuallyEmittedState for explanation
|
|
233
|
+
manuallyEmittedState = event.data;
|
|
207
234
|
emit(
|
|
208
235
|
getStateSyncEvent({
|
|
209
236
|
threadId,
|
|
210
237
|
runId,
|
|
211
238
|
agentName: agent.name,
|
|
212
239
|
nodeName,
|
|
213
|
-
state:
|
|
240
|
+
state: manuallyEmittedState,
|
|
214
241
|
running: true,
|
|
215
242
|
active: true,
|
|
216
243
|
}),
|
|
@@ -247,9 +274,6 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
247
274
|
emitIntermediateStateUntilEnd = null;
|
|
248
275
|
}
|
|
249
276
|
|
|
250
|
-
const exitingNode =
|
|
251
|
-
nodeName === currentNodeName && eventType === LangGraphEventTypes.OnChainEnd;
|
|
252
|
-
|
|
253
277
|
if (
|
|
254
278
|
JSON.stringify(updatedState) !== JSON.stringify(state) ||
|
|
255
279
|
prevNodeName != nodeName ||
|
|
@@ -277,6 +301,8 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
|
|
|
277
301
|
const isEndNode = state.next.length === 0;
|
|
278
302
|
nodeName = Object.keys(state.metadata.writes)[0];
|
|
279
303
|
|
|
304
|
+
telemetry.capture("oss.runtime.agent_execution_stream_ended", streamInfo);
|
|
305
|
+
|
|
280
306
|
emit(
|
|
281
307
|
getStateSyncEvent({
|
|
282
308
|
threadId,
|
|
@@ -1,4 +1,8 @@
|
|
|
1
1
|
import { TelemetryClient } from "@copilotkit/shared";
|
|
2
|
+
import { EndpointType, LangGraphCloudEndpoint } from "./runtime/remote-actions";
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { CopilotRuntime, resolveEndpointType } from "./runtime/copilot-runtime";
|
|
5
|
+
import { RuntimeInstanceCreatedInfo } from "@copilotkit/shared/src/telemetry/events";
|
|
2
6
|
const packageJson = require("../../package.json");
|
|
3
7
|
|
|
4
8
|
const telemetryClient = new TelemetryClient({
|
|
@@ -6,4 +10,43 @@ const telemetryClient = new TelemetryClient({
|
|
|
6
10
|
packageVersion: packageJson.version,
|
|
7
11
|
});
|
|
8
12
|
|
|
13
|
+
export function getRuntimeInstanceTelemetryInfo(
|
|
14
|
+
runtime: CopilotRuntime,
|
|
15
|
+
): RuntimeInstanceCreatedInfo {
|
|
16
|
+
const endpointsInfo = runtime.remoteEndpointDefinitions.reduce(
|
|
17
|
+
(acc, endpoint) => {
|
|
18
|
+
let info = { ...acc };
|
|
19
|
+
|
|
20
|
+
const endpointType = resolveEndpointType(endpoint);
|
|
21
|
+
if (!info.endpointTypes.includes(endpointType)) {
|
|
22
|
+
info = {
|
|
23
|
+
...info,
|
|
24
|
+
endpointTypes: [...info.endpointTypes, endpointType],
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (endpointType === EndpointType.LangGraphCloud) {
|
|
29
|
+
// When type is resolved, recreating a const with casting of type
|
|
30
|
+
const ep = endpoint as LangGraphCloudEndpoint;
|
|
31
|
+
info = {
|
|
32
|
+
...info,
|
|
33
|
+
agentsAmount: ep.agents.length,
|
|
34
|
+
hashedKey: createHash("sha256").update(ep.langsmithApiKey).digest("hex"),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
return info;
|
|
39
|
+
},
|
|
40
|
+
{ endpointTypes: [], agentsAmount: null, hashedKey: null },
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
return {
|
|
44
|
+
actionsAmount: runtime.actions.length,
|
|
45
|
+
endpointsAmount: runtime.remoteEndpointDefinitions.length,
|
|
46
|
+
endpointTypes: endpointsInfo.endpointTypes,
|
|
47
|
+
agentsAmount: endpointsInfo.agentsAmount,
|
|
48
|
+
hashedLgcKey: endpointsInfo.hashedKey,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
|
|
9
52
|
export default telemetryClient;
|
|
@@ -122,7 +122,10 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
122
122
|
mode = "message";
|
|
123
123
|
} else if (chunk.content_block.type === "tool_use") {
|
|
124
124
|
currentToolCallId = chunk.content_block.id;
|
|
125
|
-
eventStream$.sendActionExecutionStart(
|
|
125
|
+
eventStream$.sendActionExecutionStart({
|
|
126
|
+
actionExecutionId: currentToolCallId,
|
|
127
|
+
actionName: chunk.content_block.name,
|
|
128
|
+
});
|
|
126
129
|
mode = "function";
|
|
127
130
|
}
|
|
128
131
|
} else if (chunk.type === "content_block_delta") {
|
|
@@ -130,21 +133,27 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
|
|
|
130
133
|
const text = filterThinkingTextBuffer.onTextChunk(chunk.delta.text);
|
|
131
134
|
if (text.length > 0) {
|
|
132
135
|
if (!didOutputText) {
|
|
133
|
-
eventStream$.sendTextMessageStart(currentMessageId);
|
|
136
|
+
eventStream$.sendTextMessageStart({ messageId: currentMessageId });
|
|
134
137
|
didOutputText = true;
|
|
135
138
|
}
|
|
136
|
-
eventStream$.sendTextMessageContent(
|
|
139
|
+
eventStream$.sendTextMessageContent({
|
|
140
|
+
messageId: currentMessageId,
|
|
141
|
+
content: text,
|
|
142
|
+
});
|
|
137
143
|
}
|
|
138
144
|
} else if (chunk.delta.type === "input_json_delta") {
|
|
139
|
-
eventStream$.sendActionExecutionArgs(
|
|
145
|
+
eventStream$.sendActionExecutionArgs({
|
|
146
|
+
actionExecutionId: currentToolCallId,
|
|
147
|
+
args: chunk.delta.partial_json,
|
|
148
|
+
});
|
|
140
149
|
}
|
|
141
150
|
} else if (chunk.type === "content_block_stop") {
|
|
142
151
|
if (mode === "message") {
|
|
143
152
|
if (didOutputText) {
|
|
144
|
-
eventStream$.sendTextMessageEnd();
|
|
153
|
+
eventStream$.sendTextMessageEnd({ messageId: currentMessageId });
|
|
145
154
|
}
|
|
146
155
|
} else if (mode === "function") {
|
|
147
|
-
eventStream$.sendActionExecutionEnd();
|
|
156
|
+
eventStream$.sendActionExecutionEnd({ actionExecutionId: currentToolCallId });
|
|
148
157
|
}
|
|
149
158
|
}
|
|
150
159
|
}
|