@copilotkit/runtime 1.3.16-mme-lgc-langgraph-package.11 → 1.3.16-mme-revert-rxjs-changes.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.
Files changed (71) hide show
  1. package/CHANGELOG.md +33 -95
  2. package/dist/{chunk-SMHGZXIT.mjs → chunk-3EIBEZQI.mjs} +4 -3
  3. package/dist/chunk-3EIBEZQI.mjs.map +1 -0
  4. package/dist/{chunk-TTVQTORT.mjs → chunk-4MX7GDLS.mjs} +4 -3
  5. package/dist/chunk-4MX7GDLS.mjs.map +1 -0
  6. package/dist/chunk-DFOKBSIS.mjs +1 -0
  7. package/dist/chunk-DFOKBSIS.mjs.map +1 -0
  8. package/dist/{chunk-HZ2XTQUC.mjs → chunk-UO2QXEDA.mjs} +5 -4
  9. package/dist/chunk-UO2QXEDA.mjs.map +1 -0
  10. package/dist/{chunk-BNQDVBQH.mjs → chunk-WHJ3DAYL.mjs} +251 -34
  11. package/dist/chunk-WHJ3DAYL.mjs.map +1 -0
  12. package/dist/{chunk-JTVWJUZP.mjs → chunk-YSCTOGKC.mjs} +419 -50
  13. package/dist/chunk-YSCTOGKC.mjs.map +1 -0
  14. package/dist/{copilot-runtime-8d3f40c7.d.ts → copilot-runtime-335a610d.d.ts} +10 -10
  15. package/dist/{groq-adapter-dbfba3eb.d.ts → groq-adapter-2f8fd767.d.ts} +1 -1
  16. package/dist/index.d.ts +3 -3
  17. package/dist/index.js +215 -98
  18. package/dist/index.js.map +1 -1
  19. package/dist/index.mjs +22 -22
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/{langserve-f00629d2.d.ts → langserve-cc06e76e.d.ts} +1 -0
  22. package/dist/lib/index.d.ts +3 -3
  23. package/dist/lib/index.js +215 -98
  24. package/dist/lib/index.js.map +1 -1
  25. package/dist/lib/index.mjs +21 -21
  26. package/dist/lib/integrations/index.d.ts +3 -3
  27. package/dist/lib/integrations/index.js +153 -85
  28. package/dist/lib/integrations/index.js.map +1 -1
  29. package/dist/lib/integrations/index.mjs +5 -5
  30. package/dist/lib/integrations/nest/index.d.ts +2 -2
  31. package/dist/lib/integrations/nest/index.js +150 -82
  32. package/dist/lib/integrations/nest/index.js.map +1 -1
  33. package/dist/lib/integrations/nest/index.mjs +3 -3
  34. package/dist/lib/integrations/node-express/index.d.ts +2 -2
  35. package/dist/lib/integrations/node-express/index.js +150 -82
  36. package/dist/lib/integrations/node-express/index.js.map +1 -1
  37. package/dist/lib/integrations/node-express/index.mjs +3 -3
  38. package/dist/lib/integrations/node-http/index.d.ts +2 -2
  39. package/dist/lib/integrations/node-http/index.js +149 -81
  40. package/dist/lib/integrations/node-http/index.js.map +1 -1
  41. package/dist/lib/integrations/node-http/index.mjs +2 -2
  42. package/dist/service-adapters/index.d.ts +3 -3
  43. package/dist/service-adapters/index.js +31 -18
  44. package/dist/service-adapters/index.js.map +1 -1
  45. package/dist/service-adapters/index.mjs +1 -2
  46. package/package.json +4 -4
  47. package/src/agents/langgraph/event-source.ts +2 -2
  48. package/src/agents/langgraph/events.ts +2 -0
  49. package/src/lib/integrations/nest/index.ts +5 -2
  50. package/src/lib/integrations/nextjs/app-router.ts +5 -2
  51. package/src/lib/integrations/nextjs/pages-router.ts +5 -2
  52. package/src/lib/integrations/node-express/index.ts +5 -2
  53. package/src/lib/integrations/node-http/index.ts +5 -2
  54. package/src/lib/runtime/copilot-runtime.ts +53 -47
  55. package/src/lib/runtime/remote-action-constructors.ts +23 -9
  56. package/src/lib/runtime/remote-actions.ts +9 -9
  57. package/src/lib/runtime/{remote-lg-cloud-action.ts → remote-lg-action.ts} +59 -33
  58. package/src/lib/telemetry-client.ts +43 -0
  59. package/src/service-adapters/events.ts +13 -1
  60. package/src/service-adapters/google/google-genai-adapter.ts +2 -2
  61. package/src/service-adapters/langchain/langchain-adapter.ts +22 -16
  62. package/src/service-adapters/openai/openai-adapter.ts +5 -0
  63. package/dist/chunk-BNQDVBQH.mjs.map +0 -1
  64. package/dist/chunk-GWP2VADN.mjs +0 -288
  65. package/dist/chunk-GWP2VADN.mjs.map +0 -1
  66. package/dist/chunk-HZ2XTQUC.mjs.map +0 -1
  67. package/dist/chunk-JTVWJUZP.mjs.map +0 -1
  68. package/dist/chunk-MXXPWWBF.mjs +0 -218
  69. package/dist/chunk-MXXPWWBF.mjs.map +0 -1
  70. package/dist/chunk-SMHGZXIT.mjs.map +0 -1
  71. package/dist/chunk-TTVQTORT.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
 
@@ -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("oss.runtime.instance_created", {});
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("oss.runtime.instance_created", {});
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("oss.runtime.instance_created", {});
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("oss.runtime.instance_created", {});
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("oss.runtime.instance_created", {});
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";
@@ -27,7 +27,7 @@ import {
27
27
  setupRemoteActions,
28
28
  EndpointDefinition,
29
29
  CopilotKitEndpoint,
30
- LangGraphCloudEndpoint,
30
+ LangGraphPlatformEndpoint,
31
31
  } from "./remote-actions";
32
32
  import { GraphQLContext } from "../integrations/shared";
33
33
  import { AgentSessionInput } from "../../graphql/inputs/agent-session.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
- private remoteEndpointDefinitions: EndpointDefinition[];
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
- if (agentSession) {
179
- return this.processAgentRequest(request);
180
- }
178
+ const eventSource = new RuntimeEventSource();
181
179
 
182
- const messages = rawMessages.filter((message) => !message.agentStateMessage);
180
+ try {
181
+ if (agentSession) {
182
+ return await this.processAgentRequest(request);
183
+ }
183
184
 
184
- const inputMessages = convertGqlInputToMessages(messages);
185
- const serverSideActions = await this.getServerSideActions(request);
185
+ const messages = rawMessages.filter((message) => !message.agentStateMessage);
186
186
 
187
- const serverSideActionsInput: ActionInput[] = serverSideActions.map((action) => ({
188
- name: action.name,
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
- const actionInputs = flattenToolCallsNoDuplicates([
194
- ...serverSideActionsInput,
195
- ...clientSideActionsInput,
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
- await this.onBeforeRequest?.({
199
- threadId,
200
- runId,
201
- inputMessages,
202
- properties: graphqlContext.properties,
203
- url,
204
- });
196
+ const actionInputs = flattenToolCallsNoDuplicates([
197
+ ...serverSideActionsInput,
198
+ ...clientSideActionsInput,
199
+ ]);
205
200
 
206
- try {
207
- const eventSource = new RuntimeEventSource();
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
- throw error;
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: this.resolveEndpointType(endpoint),
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[] {
@@ -398,11 +392,23 @@ export function copilotKitEndpoint(config: Omit<CopilotKitEndpoint, "type">): Co
398
392
  };
399
393
  }
400
394
 
401
- export function langGraphCloudEndpoint(
402
- config: Omit<LangGraphCloudEndpoint, "type">,
403
- ): LangGraphCloudEndpoint {
395
+ export function langGraphPlatformEndpoint(
396
+ config: Omit<LangGraphPlatformEndpoint, "type">,
397
+ ): LangGraphPlatformEndpoint {
404
398
  return {
405
399
  ...config,
406
- type: EndpointType.LangGraphCloud,
400
+ type: EndpointType.LangGraphPlatform,
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.LangGraphPlatform;
408
+ } else {
409
+ return EndpointType.CopilotKit;
410
+ }
411
+ }
412
+
413
+ return endpoint.type;
414
+ }
@@ -1,8 +1,9 @@
1
+ import { createHash } from "node:crypto";
1
2
  import {
2
3
  CopilotKitEndpoint,
3
4
  LangGraphAgentHandlerParams,
4
5
  RemoteActionInfoResponse,
5
- LangGraphCloudEndpoint,
6
+ LangGraphPlatformEndpoint,
6
7
  } from "./remote-actions";
7
8
  import { GraphQLContext } from "../integrations";
8
9
  import { Logger } from "pino";
@@ -14,7 +15,7 @@ import telemetry from "../telemetry-client";
14
15
  import { RemoteLangGraphEventSource } from "../../agents/langgraph/event-source";
15
16
  import { Action } from "@copilotkit/shared";
16
17
  import { LangGraphEvent } from "../../agents/langgraph/events";
17
- import { execute } from "./remote-lg-cloud-action";
18
+ import { execute } from "./remote-lg-action";
18
19
 
19
20
  export function constructLGCRemoteAction({
20
21
  endpoint,
@@ -23,7 +24,7 @@ export function constructLGCRemoteAction({
23
24
  messages,
24
25
  agentStates,
25
26
  }: {
26
- endpoint: LangGraphCloudEndpoint;
27
+ endpoint: LangGraphPlatformEndpoint;
27
28
  graphqlContext: GraphQLContext;
28
29
  logger: Logger;
29
30
  messages: Message[];
@@ -40,9 +41,14 @@ export function constructLGCRemoteAction({
40
41
  threadId,
41
42
  nodeName,
42
43
  }: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
43
- logger.debug({ actionName: agent.name }, "Executing LangGraph Cloud agent");
44
+ logger.debug({ actionName: agent.name }, "Executing LangGraph Platform 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-platform",
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) {
@@ -76,9 +82,9 @@ export function constructLGCRemoteAction({
76
82
  } catch (error) {
77
83
  logger.error(
78
84
  { url: endpoint.deploymentUrl, status: 500, body: error.message },
79
- "Failed to execute LangGraph Cloud agent",
85
+ "Failed to execute LangGraph Platform agent",
80
86
  );
81
- throw new Error("Failed to execute LangGraph Cloud agent");
87
+ throw new Error("Failed to execute LangGraph Platform agent");
82
88
  }
83
89
  },
84
90
  }));
@@ -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) {
@@ -12,11 +12,11 @@ import {
12
12
  createHeaders,
13
13
  } from "./remote-action-constructors";
14
14
 
15
- export type EndpointDefinition = CopilotKitEndpoint | LangGraphCloudEndpoint;
15
+ export type EndpointDefinition = CopilotKitEndpoint | LangGraphPlatformEndpoint;
16
16
 
17
17
  export enum EndpointType {
18
18
  CopilotKit = "copilotKit",
19
- LangGraphCloud = "langgraph-cloud",
19
+ LangGraphPlatform = "langgraph-platform",
20
20
  }
21
21
 
22
22
  export interface BaseEndpointDefinition<TActionType extends EndpointType> {
@@ -30,17 +30,17 @@ export interface CopilotKitEndpoint extends BaseEndpointDefinition<EndpointType.
30
30
  };
31
31
  }
32
32
 
33
- export interface LangGraphCloudAgent {
33
+ export interface LangGraphPlatformAgent {
34
34
  name: string;
35
35
  description: string;
36
36
  assistantId?: string;
37
37
  }
38
38
 
39
- export interface LangGraphCloudEndpoint
40
- extends BaseEndpointDefinition<EndpointType.LangGraphCloud> {
39
+ export interface LangGraphPlatformEndpoint
40
+ extends BaseEndpointDefinition<EndpointType.LangGraphPlatform> {
41
41
  deploymentUrl: string;
42
42
  langsmithApiKey: string;
43
- agents: LangGraphCloudAgent[];
43
+ agents: LangGraphPlatformAgent[];
44
44
  }
45
45
 
46
46
  export type RemoteActionInfoResponse = {
@@ -127,7 +127,7 @@ export async function setupRemoteActions({
127
127
 
128
128
  // Remove duplicates of remoteEndpointDefinitions.url
129
129
  const filtered = remoteEndpointDefinitions.filter((value, index, self) => {
130
- if (value.type === EndpointType.LangGraphCloud) {
130
+ if (value.type === EndpointType.LangGraphPlatform) {
131
131
  return value;
132
132
  }
133
133
  return index === self.findIndex((t: CopilotKitEndpoint) => t.url === value.url);
@@ -135,8 +135,8 @@ export async function setupRemoteActions({
135
135
 
136
136
  const result = await Promise.all(
137
137
  filtered.map(async (endpoint) => {
138
- // Check for properties that can distinguish LG cloud from other actions
139
- if (endpoint.type === EndpointType.LangGraphCloud) {
138
+ // Check for properties that can distinguish LG platform from other actions
139
+ if (endpoint.type === EndpointType.LangGraphPlatform) {
140
140
  return constructLGCRemoteAction({
141
141
  endpoint,
142
142
  messages,
@@ -1,20 +1,21 @@
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";
6
- import { LangGraphCloudAgent, LangGraphCloudEndpoint } from "./remote-actions";
6
+ import { LangGraphPlatformAgent, LangGraphPlatformEndpoint } from "./remote-actions";
7
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
 
14
15
  type ExecutionAction = Pick<ActionInput, "name" | "description"> & { parameters: string };
15
16
 
16
- interface ExecutionArgs extends Omit<LangGraphCloudEndpoint, "agents"> {
17
- agent: LangGraphCloudAgent;
17
+ interface ExecutionArgs extends Omit<LangGraphPlatformEndpoint, "agents"> {
18
+ agent: LangGraphPlatformAgent;
18
19
  threadId: string;
19
20
  nodeName: string;
20
21
  messages: Message[];
@@ -24,14 +25,14 @@ interface ExecutionArgs extends Omit<LangGraphCloudEndpoint, "agents"> {
24
25
  logger: Logger;
25
26
  }
26
27
 
27
- // The following types are our own definition to the messages accepted by LangGraph cloud, enhanced with some of our extra data.
28
+ // The following types are our own definition to the messages accepted by LangGraph Platform, enhanced with some of our extra data.
28
29
  interface ToolCall {
29
30
  id: string;
30
31
  name: string;
31
32
  args: Record<string, unknown>;
32
33
  }
33
34
 
34
- type BaseLangGraphCloudMessage = Omit<
35
+ type BaseLangGraphPlatformMessage = Omit<
35
36
  Message,
36
37
  | "isResultMessage"
37
38
  | "isTextMessage"
@@ -46,19 +47,19 @@ type BaseLangGraphCloudMessage = Omit<
46
47
  type: MessageType;
47
48
  };
48
49
 
49
- interface LangGraphCloudResultMessage extends BaseLangGraphCloudMessage {
50
+ interface LangGraphPlatformResultMessage extends BaseLangGraphPlatformMessage {
50
51
  tool_call_id: string;
51
52
  name: string;
52
53
  }
53
54
 
54
- interface LangGraphCloudActionExecutionMessage extends BaseLangGraphCloudMessage {
55
+ interface LangGraphPlatformActionExecutionMessage extends BaseLangGraphPlatformMessage {
55
56
  tool_calls: ToolCall[];
56
57
  }
57
58
 
58
- type LangGraphCloudMessage =
59
- | LangGraphCloudActionExecutionMessage
60
- | LangGraphCloudResultMessage
61
- | BaseLangGraphCloudMessage;
59
+ type LangGraphPlatformMessage =
60
+ | LangGraphPlatformActionExecutionMessage
61
+ | LangGraphPlatformResultMessage
62
+ | BaseLangGraphPlatformMessage;
62
63
 
63
64
  export async function execute(args: ExecutionArgs): Promise<ReadableStream<Uint8Array>> {
64
65
  return new ReadableStream({
@@ -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;
@@ -128,7 +128,7 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
128
128
  if (!assistantId) {
129
129
  console.error(`
130
130
  No agent found for the agent name specified in CopilotKit provider
131
- Please check your available agents or provide an agent ID in the LangGraph Cloud endpoint definition.\n
131
+ Please check your available agents or provide an agent ID in the LangGraph Platform endpoint definition.\n
132
132
 
133
133
  These are the available agents: [${assistants.map((a) => `${a.name} (ID: ${a.assistant_id})`).join(", ")}]
134
134
  `);
@@ -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
- updatedState = event.data;
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: updatedState,
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,
@@ -413,7 +439,7 @@ class StreamingStateExtractor {
413
439
  // Start of Selection
414
440
  function langGraphDefaultMergeState(
415
441
  state: State,
416
- messages: LangGraphCloudMessage[],
442
+ messages: LangGraphPlatformMessage[],
417
443
  actions: ExecutionAction[],
418
444
  agentName: string,
419
445
  ): State {
@@ -423,7 +449,7 @@ function langGraphDefaultMergeState(
423
449
  }
424
450
 
425
451
  // merge with existing messages
426
- const mergedMessages: LangGraphCloudMessage[] = state.messages || [];
452
+ const mergedMessages: LangGraphPlatformMessage[] = state.messages || [];
427
453
  const existingMessageIds = new Set(mergedMessages.map((message) => message.id));
428
454
  const existingToolCallResults = new Set<string>();
429
455
 
@@ -489,7 +515,7 @@ function langGraphDefaultMergeState(
489
515
  }
490
516
 
491
517
  // try to auto-correct and log alignment issues
492
- const correctedMessages: LangGraphCloudMessage[] = [];
518
+ const correctedMessages: LangGraphPlatformMessage[] = [];
493
519
 
494
520
  for (let i = 0; i < mergedMessages.length; i++) {
495
521
  const currentMessage = mergedMessages[i];
@@ -560,7 +586,7 @@ function langGraphDefaultMergeState(
560
586
  };
561
587
  }
562
588
 
563
- function formatMessages(messages: Message[]): LangGraphCloudMessage[] {
589
+ function formatMessages(messages: Message[]): LangGraphPlatformMessage[] {
564
590
  return messages.map((message) => {
565
591
  if (message.isTextMessage() && message.role === "assistant") {
566
592
  return message;
@@ -583,7 +609,7 @@ function formatMessages(messages: Message[]): LangGraphCloudMessage[] {
583
609
  tool_calls: [toolCall],
584
610
  role: MessageRole.assistant,
585
611
  id: message.id,
586
- } satisfies LangGraphCloudActionExecutionMessage;
612
+ } satisfies LangGraphPlatformActionExecutionMessage;
587
613
  }
588
614
  if (message.isResultMessage()) {
589
615
  return {
@@ -593,7 +619,7 @@ function formatMessages(messages: Message[]): LangGraphCloudMessage[] {
593
619
  tool_call_id: message.actionExecutionId,
594
620
  name: message.actionName,
595
621
  role: MessageRole.tool,
596
- } satisfies LangGraphCloudResultMessage;
622
+ } satisfies LangGraphPlatformResultMessage;
597
623
  }
598
624
 
599
625
  throw new Error(`Unknown message type ${message.type}`);