@copilotkit/runtime 1.3.2 → 1.3.3

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 (34) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/dist/{chunk-VQY3UTNK.mjs → chunk-3RSGBABY.mjs} +2 -2
  3. package/dist/{chunk-CP4IV75Q.mjs → chunk-4QVREBXP.mjs} +2 -2
  4. package/dist/{chunk-IYJBUTRQ.mjs → chunk-AOSWZOH5.mjs} +2 -2
  5. package/dist/{chunk-J3URDBS7.mjs → chunk-LQSJAQSM.mjs} +157 -72
  6. package/dist/chunk-LQSJAQSM.mjs.map +1 -0
  7. package/dist/{chunk-GJHAWL7E.mjs → chunk-TU4DA2BH.mjs} +2 -2
  8. package/dist/index.js +159 -74
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +5 -5
  11. package/dist/lib/index.js +159 -74
  12. package/dist/lib/index.js.map +1 -1
  13. package/dist/lib/index.mjs +5 -5
  14. package/dist/lib/integrations/index.js +4 -2
  15. package/dist/lib/integrations/index.js.map +1 -1
  16. package/dist/lib/integrations/index.mjs +4 -4
  17. package/dist/lib/integrations/nest/index.js +4 -2
  18. package/dist/lib/integrations/nest/index.js.map +1 -1
  19. package/dist/lib/integrations/nest/index.mjs +2 -2
  20. package/dist/lib/integrations/node-express/index.js +4 -2
  21. package/dist/lib/integrations/node-express/index.js.map +1 -1
  22. package/dist/lib/integrations/node-express/index.mjs +2 -2
  23. package/dist/lib/integrations/node-http/index.js +4 -2
  24. package/dist/lib/integrations/node-http/index.js.map +1 -1
  25. package/dist/lib/integrations/node-http/index.mjs +1 -1
  26. package/package.json +7 -5
  27. package/src/agents/langgraph/event-source.ts +97 -24
  28. package/src/agents/langgraph/events.ts +10 -1
  29. package/src/lib/runtime/remote-actions.ts +52 -31
  30. package/dist/chunk-J3URDBS7.mjs.map +0 -1
  31. /package/dist/{chunk-VQY3UTNK.mjs.map → chunk-3RSGBABY.mjs.map} +0 -0
  32. /package/dist/{chunk-CP4IV75Q.mjs.map → chunk-4QVREBXP.mjs.map} +0 -0
  33. /package/dist/{chunk-IYJBUTRQ.mjs.map → chunk-AOSWZOH5.mjs.map} +0 -0
  34. /package/dist/{chunk-GJHAWL7E.mjs.map → chunk-TU4DA2BH.mjs.map} +0 -0
@@ -1,12 +1,14 @@
1
- import { ReplaySubject, scan, mergeMap } from "rxjs";
1
+ import { ReplaySubject, scan, mergeMap, catchError } from "rxjs";
2
2
  import { LangGraphEvent, LangGraphEventTypes } from "./events";
3
3
  import { RuntimeEvent, RuntimeEventTypes } from "../../service-adapters/events";
4
+ import { randomId } from "@copilotkit/shared";
4
5
 
5
6
  interface LangGraphEventWithState {
6
7
  event: LangGraphEvent | null;
7
8
  toolCallName: string | null;
8
9
  toolCallId: string | null;
9
- prevToolCallId: string | null;
10
+ toolCallMessageId: string | null;
11
+ prevToolCallMessageId: string | null;
10
12
  messageId: string | null;
11
13
  prevMessageId: string | null;
12
14
  }
@@ -48,51 +50,77 @@ export class RemoteLangGraphEventSource {
48
50
  });
49
51
  }
50
52
 
51
- while (true) {
52
- const { done, value } = await reader.read();
53
+ try {
54
+ while (true) {
55
+ const { done, value } = await reader.read();
53
56
 
54
- if (!done) {
55
- buffer.push(decoder.decode(value, { stream: true }));
56
- }
57
+ if (!done) {
58
+ buffer.push(decoder.decode(value, { stream: true }));
59
+ }
57
60
 
58
- flushBuffer();
61
+ flushBuffer();
59
62
 
60
- if (done) {
61
- break;
63
+ if (done) {
64
+ break;
65
+ }
62
66
  }
67
+ } catch (error) {
68
+ console.error("Error in stream", error);
69
+ eventStream$.error(error);
70
+ return;
63
71
  }
64
72
  eventStream$.complete();
65
73
  }
66
74
 
75
+ private shouldEmitToolCall(
76
+ shouldEmitToolCalls: string | string[] | boolean,
77
+ toolCallName: string,
78
+ ) {
79
+ if (typeof shouldEmitToolCalls === "boolean") {
80
+ return shouldEmitToolCalls;
81
+ }
82
+ if (Array.isArray(shouldEmitToolCalls)) {
83
+ return shouldEmitToolCalls.includes(toolCallName);
84
+ }
85
+ return shouldEmitToolCalls === toolCallName;
86
+ }
87
+
67
88
  processLangGraphEvents() {
89
+ let lastEventWithState: LangGraphEventWithState | null = null;
90
+
68
91
  return this.eventStream$.pipe(
69
92
  scan(
70
93
  (acc, event) => {
71
94
  if (event.event === LangGraphEventTypes.OnChatModelStream) {
72
95
  if (event.data?.chunk?.kwargs?.tool_call_chunks) {
73
- acc.prevToolCallId = acc.toolCallId;
74
- acc.toolCallId = event.data.chunk.kwargs?.id;
96
+ acc.prevToolCallMessageId = acc.toolCallMessageId;
97
+ acc.toolCallMessageId = event.data.chunk.kwargs?.id;
75
98
  if (event.data.chunk.kwargs.tool_call_chunks[0]?.name) {
76
99
  acc.toolCallName = event.data.chunk.kwargs.tool_call_chunks[0].name;
77
100
  }
101
+ if (event.data.chunk.kwargs.tool_call_chunks[0]?.id) {
102
+ acc.toolCallId = event.data.chunk.kwargs.tool_call_chunks[0].id;
103
+ }
78
104
  }
79
105
  acc.prevMessageId = acc.messageId;
80
106
  acc.messageId = event.data?.chunk?.kwargs?.id;
81
107
  } else {
82
- acc.prevToolCallId = acc.toolCallId;
83
- acc.toolCallId = null;
108
+ acc.prevToolCallMessageId = acc.toolCallMessageId;
109
+ acc.toolCallMessageId = null;
84
110
  acc.prevMessageId = acc.messageId;
85
111
  acc.messageId = null;
86
112
  acc.toolCallName = null;
87
113
  }
88
114
 
89
115
  acc.event = event;
116
+ lastEventWithState = acc; // Capture the state
90
117
  return acc;
91
118
  },
92
119
  {
93
120
  event: null,
94
121
  toolCallId: null,
95
- prevToolCallId: null,
122
+ toolCallMessageId: null,
123
+ prevToolCallMessageId: null,
96
124
  messageId: null,
97
125
  toolCallName: null,
98
126
  prevMessageId: null,
@@ -102,7 +130,7 @@ export class RemoteLangGraphEventSource {
102
130
  const events: RuntimeEvent[] = [];
103
131
 
104
132
  let shouldEmitMessages = true;
105
- let shouldEmitToolCalls = false;
133
+ let shouldEmitToolCalls: string | string[] | boolean = false;
106
134
 
107
135
  if (eventWithState.event.event == LangGraphEventTypes.OnChatModelStream) {
108
136
  if ("copilotkit:emit-tool-calls" in (eventWithState.event.metadata || {})) {
@@ -115,9 +143,9 @@ export class RemoteLangGraphEventSource {
115
143
 
116
144
  // Tool call ended: emit ActionExecutionEnd
117
145
  if (
118
- eventWithState.prevToolCallId !== null &&
119
- eventWithState.prevToolCallId !== eventWithState.toolCallId &&
120
- shouldEmitToolCalls
146
+ eventWithState.prevToolCallMessageId !== null &&
147
+ eventWithState.prevToolCallMessageId !== eventWithState.toolCallMessageId &&
148
+ this.shouldEmitToolCall(shouldEmitToolCalls, eventWithState.toolCallName)
121
149
  ) {
122
150
  events.push({
123
151
  type: RuntimeEventTypes.ActionExecutionEnd,
@@ -149,6 +177,20 @@ export class RemoteLangGraphEventSource {
149
177
  type: RuntimeEventTypes.TextMessageEnd,
150
178
  });
151
179
  break;
180
+ case LangGraphEventTypes.OnCopilotKitEmitToolCall:
181
+ events.push({
182
+ type: RuntimeEventTypes.ActionExecutionStart,
183
+ actionExecutionId: eventWithState.event.id,
184
+ actionName: eventWithState.event.name,
185
+ });
186
+ events.push({
187
+ type: RuntimeEventTypes.ActionExecutionArgs,
188
+ args: JSON.stringify(eventWithState.event.args),
189
+ });
190
+ events.push({
191
+ type: RuntimeEventTypes.ActionExecutionEnd,
192
+ });
193
+ break;
152
194
  case LangGraphEventTypes.OnCopilotKitStateSync:
153
195
  events.push({
154
196
  type: RuntimeEventTypes.AgentStateMessage,
@@ -180,13 +222,13 @@ export class RemoteLangGraphEventSource {
180
222
  break;
181
223
  case LangGraphEventTypes.OnChatModelStream:
182
224
  if (
183
- eventWithState.toolCallId !== null &&
184
- eventWithState.prevToolCallId !== eventWithState.toolCallId
225
+ eventWithState.toolCallMessageId !== null &&
226
+ eventWithState.prevToolCallMessageId !== eventWithState.toolCallMessageId
185
227
  ) {
186
- if (shouldEmitToolCalls) {
228
+ if (this.shouldEmitToolCall(shouldEmitToolCalls, eventWithState.toolCallName)) {
187
229
  events.push({
188
230
  type: RuntimeEventTypes.ActionExecutionStart,
189
- actionExecutionId: eventWithState.toolCallId,
231
+ actionExecutionId: eventWithState.toolCallMessageId,
190
232
  actionName: eventWithState.toolCallName,
191
233
  scope: "client",
192
234
  });
@@ -210,7 +252,7 @@ export class RemoteLangGraphEventSource {
210
252
 
211
253
  // Tool call args: emit ActionExecutionArgs
212
254
  if (args) {
213
- if (shouldEmitToolCalls) {
255
+ if (this.shouldEmitToolCall(shouldEmitToolCalls, eventWithState.toolCallName)) {
214
256
  events.push({
215
257
  type: RuntimeEventTypes.ActionExecutionArgs,
216
258
  args,
@@ -230,6 +272,37 @@ export class RemoteLangGraphEventSource {
230
272
  }
231
273
  return events;
232
274
  }),
275
+ catchError((error) => {
276
+ console.error(error);
277
+ const events: RuntimeEvent[] = [];
278
+
279
+ if (lastEventWithState?.messageId) {
280
+ events.push({
281
+ type: RuntimeEventTypes.TextMessageEnd,
282
+ });
283
+ }
284
+ if (lastEventWithState?.toolCallMessageId) {
285
+ events.push({
286
+ type: RuntimeEventTypes.ActionExecutionEnd,
287
+ });
288
+ }
289
+
290
+ const messageId = randomId();
291
+
292
+ events.push({
293
+ type: RuntimeEventTypes.TextMessageStart,
294
+ messageId: messageId,
295
+ });
296
+ events.push({
297
+ type: RuntimeEventTypes.TextMessageContent,
298
+ content: "❌ An error occurred. Please try again.",
299
+ });
300
+ events.push({
301
+ type: RuntimeEventTypes.TextMessageEnd,
302
+ });
303
+
304
+ return events;
305
+ }),
233
306
  );
234
307
  }
235
308
  }
@@ -9,6 +9,7 @@ export enum LangGraphEventTypes {
9
9
  OnToolEnd = "on_tool_end",
10
10
  OnCopilotKitStateSync = "on_copilotkit_state_sync",
11
11
  OnCopilotKitEmitMessage = "on_copilotkit_emit_message",
12
+ OnCopilotKitEmitToolCall = "on_copilotkit_emit_tool_call",
12
13
  }
13
14
 
14
15
  type LangGraphOnCopilotKitStateSyncEvent = {
@@ -29,6 +30,13 @@ type LangGraphOnCopilotKitManualMessageEvent = {
29
30
  message_id: string;
30
31
  };
31
32
 
33
+ type LangGraphOnCopilotKitEmitToolCallEvent = {
34
+ event: LangGraphEventTypes.OnCopilotKitEmitToolCall;
35
+ name: string;
36
+ args: any;
37
+ id: string;
38
+ };
39
+
32
40
  type LangGraphOnChainStartEvent = {
33
41
  event: LangGraphEventTypes.OnChainStart;
34
42
  run_id: string;
@@ -314,4 +322,5 @@ export type LangGraphEvent =
314
322
  | LangGraphOnToolStartEvent
315
323
  | LangGraphOnToolEndEvent
316
324
  | LangGraphOnCopilotKitStateSyncEvent
317
- | LangGraphOnCopilotKitManualMessageEvent;
325
+ | LangGraphOnCopilotKitManualMessageEvent
326
+ | LangGraphOnCopilotKitEmitToolCallEvent;
@@ -16,6 +16,11 @@ export type RemoteActionDefinition = {
16
16
  };
17
17
  };
18
18
 
19
+ export type RemoteActionInfoResponse = {
20
+ actions: any[];
21
+ agents: any[];
22
+ };
23
+
19
24
  export type LangGraphAgentHandlerParams = {
20
25
  name: string;
21
26
  actionInputsWithoutAgents: ActionInput[];
@@ -64,27 +69,35 @@ async function fetchRemoteInfo({
64
69
  graphqlContext: GraphQLContext;
65
70
  logger: Logger;
66
71
  frontendUrl?: string;
67
- }): Promise<any[]> {
72
+ }): Promise<RemoteActionInfoResponse> {
68
73
  logger.debug({ url }, "Fetching actions from url");
69
74
  const headers = createHeaders(onBeforeRequest, graphqlContext);
70
75
 
71
- const response = await fetch(`${url}/info`, {
72
- method: "POST",
73
- headers,
74
- body: JSON.stringify({ properties: graphqlContext.properties, frontendUrl }),
75
- });
76
+ try {
77
+ const response = await fetch(`${url}/info`, {
78
+ method: "POST",
79
+ headers,
80
+ body: JSON.stringify({ properties: graphqlContext.properties, frontendUrl }),
81
+ });
76
82
 
77
- if (!response.ok) {
83
+ if (!response.ok) {
84
+ logger.error(
85
+ { url, status: response.status, body: await response.text() },
86
+ "Failed to fetch actions from url",
87
+ );
88
+ return { actions: [], agents: [] };
89
+ }
90
+
91
+ const json = await response.json();
92
+ logger.debug({ json }, "Fetched actions from url");
93
+ return json;
94
+ } catch (error) {
78
95
  logger.error(
79
- { url, status: response.status, body: await response.text() },
96
+ { error: error.message ? error.message : error + "" },
80
97
  "Failed to fetch actions from url",
81
98
  );
82
- return [];
99
+ return { actions: [], agents: [] };
83
100
  }
84
-
85
- const json = await response.json();
86
- logger.debug({ json }, "Fetched actions from url");
87
- return json;
88
101
  }
89
102
 
90
103
  function constructRemoteActions({
@@ -96,7 +109,7 @@ function constructRemoteActions({
96
109
  messages,
97
110
  agentStates,
98
111
  }: {
99
- json: any[];
112
+ json: RemoteActionInfoResponse;
100
113
  url: string;
101
114
  onBeforeRequest?: RemoteActionDefinition["onBeforeRequest"];
102
115
  graphqlContext: GraphQLContext;
@@ -114,29 +127,37 @@ function constructRemoteActions({
114
127
  const headers = createHeaders(onBeforeRequest, graphqlContext);
115
128
  telemetry.capture("oss.runtime.remote_action_executed", {});
116
129
 
117
- const response = await fetch(`${url}/actions/execute`, {
118
- method: "POST",
119
- headers,
120
- body: JSON.stringify({
121
- name: action.name,
122
- arguments: args,
123
- properties: graphqlContext.properties,
124
- }),
125
- });
130
+ try {
131
+ const response = await fetch(`${url}/actions/execute`, {
132
+ method: "POST",
133
+ headers,
134
+ body: JSON.stringify({
135
+ name: action.name,
136
+ arguments: args,
137
+ properties: graphqlContext.properties,
138
+ }),
139
+ });
126
140
 
127
- if (!response.ok) {
141
+ if (!response.ok) {
142
+ logger.error(
143
+ { url, status: response.status, body: await response.text() },
144
+ "Failed to execute remote action",
145
+ );
146
+ return "Failed to execute remote action";
147
+ }
148
+
149
+ const requestResult = await response.json();
150
+
151
+ const result = requestResult["result"];
152
+ logger.debug({ actionName: action.name, result }, "Executed remote action");
153
+ return result;
154
+ } catch (error) {
128
155
  logger.error(
129
- { url, status: response.status, body: await response.text() },
156
+ { error: error.message ? error.message : error + "" },
130
157
  "Failed to execute remote action",
131
158
  );
132
159
  return "Failed to execute remote action";
133
160
  }
134
-
135
- const requestResult = await response.json();
136
-
137
- const result = requestResult["result"];
138
- logger.debug({ actionName: action.name, result }, "Executed remote action");
139
- return result;
140
161
  },
141
162
  }));
142
163