@copilotkit/runtime 1.4.8-no-pino-redact.1 → 1.5.0-coagents-v0-3.0

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 (78) hide show
  1. package/CHANGELOG.md +20 -5
  2. package/__snapshots__/schema/schema.graphql +7 -9
  3. package/dist/{chunk-OKQVDDJ2.mjs → chunk-4AYRDPWK.mjs} +285 -63
  4. package/dist/chunk-4AYRDPWK.mjs.map +1 -0
  5. package/dist/{chunk-APVJZO3R.mjs → chunk-7BOO3OFP.mjs} +2 -2
  6. package/dist/{chunk-OSWF5QDO.mjs → chunk-GSTWFOZF.mjs} +2 -2
  7. package/dist/{chunk-M74ZTUCC.mjs → chunk-OMAAKIJQ.mjs} +2 -2
  8. package/dist/{chunk-36AYTJIE.mjs → chunk-PXS4SBRF.mjs} +447 -321
  9. package/dist/chunk-PXS4SBRF.mjs.map +1 -0
  10. package/dist/{chunk-B74M7FXG.mjs → chunk-RFF5IIZJ.mjs} +3 -2
  11. package/dist/chunk-RFF5IIZJ.mjs.map +1 -0
  12. package/dist/{copilot-runtime-12e7ac40.d.ts → copilot-runtime-2e46a7b6.d.ts} +2 -2
  13. package/dist/graphql/types/converted/index.d.ts +1 -1
  14. package/dist/graphql/types/converted/index.js +2 -1
  15. package/dist/graphql/types/converted/index.js.map +1 -1
  16. package/dist/graphql/types/converted/index.mjs +1 -1
  17. package/dist/{groq-adapter-24abe931.d.ts → groq-adapter-7bf6824b.d.ts} +1 -1
  18. package/dist/{index-10b1c870.d.ts → index-ff3fbc33.d.ts} +7 -8
  19. package/dist/index.d.ts +5 -5
  20. package/dist/index.js +824 -473
  21. package/dist/index.js.map +1 -1
  22. package/dist/index.mjs +10 -6
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/{langserve-f021ab9c.d.ts → langserve-f318db89.d.ts} +53 -14
  25. package/dist/lib/index.d.ts +4 -4
  26. package/dist/lib/index.js +729 -452
  27. package/dist/lib/index.js.map +1 -1
  28. package/dist/lib/index.mjs +6 -6
  29. package/dist/lib/integrations/index.d.ts +4 -4
  30. package/dist/lib/integrations/index.js +79 -31
  31. package/dist/lib/integrations/index.js.map +1 -1
  32. package/dist/lib/integrations/index.mjs +6 -6
  33. package/dist/lib/integrations/nest/index.d.ts +3 -3
  34. package/dist/lib/integrations/nest/index.js +79 -31
  35. package/dist/lib/integrations/nest/index.js.map +1 -1
  36. package/dist/lib/integrations/nest/index.mjs +4 -4
  37. package/dist/lib/integrations/node-express/index.d.ts +3 -3
  38. package/dist/lib/integrations/node-express/index.js +79 -31
  39. package/dist/lib/integrations/node-express/index.js.map +1 -1
  40. package/dist/lib/integrations/node-express/index.mjs +4 -4
  41. package/dist/lib/integrations/node-http/index.d.ts +3 -3
  42. package/dist/lib/integrations/node-http/index.js +79 -31
  43. package/dist/lib/integrations/node-http/index.js.map +1 -1
  44. package/dist/lib/integrations/node-http/index.mjs +3 -3
  45. package/dist/service-adapters/index.d.ts +36 -5
  46. package/dist/service-adapters/index.js +285 -61
  47. package/dist/service-adapters/index.js.map +1 -1
  48. package/dist/service-adapters/index.mjs +5 -1
  49. package/package.json +2 -2
  50. package/src/agents/langgraph/event-source.ts +140 -148
  51. package/src/agents/langgraph/events.ts +1 -1
  52. package/src/graphql/inputs/message.input.ts +15 -3
  53. package/src/graphql/resolvers/copilot.resolver.ts +32 -6
  54. package/src/graphql/types/converted/index.ts +4 -3
  55. package/src/graphql/types/copilot-response.type.ts +12 -3
  56. package/src/graphql/types/enums.ts +0 -11
  57. package/src/lib/logger.ts +4 -0
  58. package/src/lib/runtime/copilot-runtime.ts +1 -7
  59. package/src/lib/runtime/remote-action-constructors.ts +64 -58
  60. package/src/lib/runtime/remote-actions.ts +1 -0
  61. package/src/lib/runtime/remote-lg-action.ts +159 -140
  62. package/src/service-adapters/anthropic/anthropic-adapter.ts +16 -6
  63. package/src/service-adapters/conversion.ts +2 -1
  64. package/src/service-adapters/events.ts +118 -54
  65. package/src/service-adapters/experimental/empty/empty-adapter.ts +33 -0
  66. package/src/service-adapters/experimental/ollama/ollama-adapter.ts +7 -3
  67. package/src/service-adapters/groq/groq-adapter.ts +23 -8
  68. package/src/service-adapters/index.ts +7 -1
  69. package/src/service-adapters/langchain/utils.ts +55 -32
  70. package/src/service-adapters/openai/openai-adapter.ts +22 -9
  71. package/src/service-adapters/openai/openai-assistant-adapter.ts +22 -8
  72. package/src/service-adapters/unify/unify-adapter.ts +28 -11
  73. package/dist/chunk-36AYTJIE.mjs.map +0 -1
  74. package/dist/chunk-B74M7FXG.mjs.map +0 -1
  75. package/dist/chunk-OKQVDDJ2.mjs.map +0 -1
  76. /package/dist/{chunk-APVJZO3R.mjs.map → chunk-7BOO3OFP.mjs.map} +0 -0
  77. /package/dist/{chunk-OSWF5QDO.mjs.map → chunk-GSTWFOZF.mjs.map} +0 -0
  78. /package/dist/{chunk-M74ZTUCC.mjs.map → chunk-OMAAKIJQ.mjs.map} +0 -0
@@ -249,13 +249,7 @@ export class CopilotRuntime<const T extends Parameter[] | [] = []> {
249
249
  } catch (error) {
250
250
  console.error("Error getting response:", error);
251
251
  eventSource.sendErrorMessageToChat();
252
- return {
253
- threadId: threadId || randomId(),
254
- runId: runId || randomId(),
255
- eventSource,
256
- serverSideActions: [],
257
- actionInputsWithoutAgents: [],
258
- };
252
+ throw error;
259
253
  }
260
254
  }
261
255
 
@@ -40,6 +40,7 @@ export function constructLGCRemoteAction({
40
40
  actionInputsWithoutAgents,
41
41
  threadId,
42
42
  nodeName,
43
+ additionalMessages = [],
43
44
  }: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
44
45
  logger.debug({ actionName: agent.name }, "Executing LangGraph Platform agent");
45
46
 
@@ -66,7 +67,7 @@ export function constructLGCRemoteAction({
66
67
  agent,
67
68
  threadId,
68
69
  nodeName,
69
- messages,
70
+ messages: [...messages, ...additionalMessages],
70
71
  state,
71
72
  properties: graphqlContext.properties,
72
73
  actions: actionInputsWithoutAgents.map((action) => ({
@@ -109,6 +110,8 @@ export function constructRemoteActions({
109
110
  messages: Message[];
110
111
  agentStates?: AgentStateInput[];
111
112
  }): Action<any>[] {
113
+ const totalAgents = Array.isArray(json["agents"]) ? json["agents"].length : 0;
114
+
112
115
  const actions = json["actions"].map((action) => ({
113
116
  name: action.name,
114
117
  description: action.description,
@@ -120,7 +123,7 @@ export function constructRemoteActions({
120
123
  telemetry.capture("oss.runtime.remote_action_executed", {
121
124
  agentExecution: false,
122
125
  type: "self-hosted",
123
- agentsAmount: json["agents"].length,
126
+ agentsAmount: totalAgents,
124
127
  });
125
128
 
126
129
  try {
@@ -157,66 +160,69 @@ export function constructRemoteActions({
157
160
  },
158
161
  }));
159
162
 
160
- const agents = json["agents"].map((agent) => ({
161
- name: agent.name,
162
- description: agent.description,
163
- parameters: [],
164
- handler: async (_args: any) => {},
165
-
166
- langGraphAgentHandler: async ({
167
- name,
168
- actionInputsWithoutAgents,
169
- threadId,
170
- nodeName,
171
- }: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
172
- logger.debug({ actionName: agent.name }, "Executing remote agent");
173
-
174
- const headers = createHeaders(onBeforeRequest, graphqlContext);
175
- telemetry.capture("oss.runtime.remote_action_executed", {
176
- agentExecution: true,
177
- type: "self-hosted",
178
- agentsAmount: json["agents"].length,
179
- });
180
-
181
- let state = {};
182
- if (agentStates) {
183
- const jsonState = agentStates.find((state) => state.agentName === name)?.state;
184
- if (jsonState) {
185
- state = JSON.parse(jsonState);
186
- }
187
- }
163
+ const agents = totalAgents
164
+ ? json["agents"].map((agent) => ({
165
+ name: agent.name,
166
+ description: agent.description,
167
+ parameters: [],
168
+ handler: async (_args: any) => {},
188
169
 
189
- const response = await fetch(`${url}/agents/execute`, {
190
- method: "POST",
191
- headers,
192
- body: JSON.stringify({
170
+ langGraphAgentHandler: async ({
193
171
  name,
172
+ actionInputsWithoutAgents,
194
173
  threadId,
195
174
  nodeName,
196
- messages,
197
- state,
198
- properties: graphqlContext.properties,
199
- actions: actionInputsWithoutAgents.map((action) => ({
200
- name: action.name,
201
- description: action.description,
202
- parameters: JSON.parse(action.jsonSchema),
203
- })),
204
- }),
205
- });
206
-
207
- if (!response.ok) {
208
- logger.error(
209
- { url, status: response.status, body: await response.text() },
210
- "Failed to execute remote agent",
211
- );
212
- throw new Error("Failed to execute remote agent");
213
- }
214
-
215
- const eventSource = new RemoteLangGraphEventSource();
216
- streamResponse(response.body!, eventSource.eventStream$);
217
- return eventSource.processLangGraphEvents();
218
- },
219
- }));
175
+ additionalMessages = [],
176
+ }: LangGraphAgentHandlerParams): Promise<Observable<RuntimeEvent>> => {
177
+ logger.debug({ actionName: agent.name }, "Executing remote agent");
178
+
179
+ const headers = createHeaders(onBeforeRequest, graphqlContext);
180
+ telemetry.capture("oss.runtime.remote_action_executed", {
181
+ agentExecution: true,
182
+ type: "self-hosted",
183
+ agentsAmount: json["agents"].length,
184
+ });
185
+
186
+ let state = {};
187
+ if (agentStates) {
188
+ const jsonState = agentStates.find((state) => state.agentName === name)?.state;
189
+ if (jsonState) {
190
+ state = JSON.parse(jsonState);
191
+ }
192
+ }
193
+
194
+ const response = await fetch(`${url}/agents/execute`, {
195
+ method: "POST",
196
+ headers,
197
+ body: JSON.stringify({
198
+ name,
199
+ threadId,
200
+ nodeName,
201
+ messages: [...messages, ...additionalMessages],
202
+ state,
203
+ properties: graphqlContext.properties,
204
+ actions: actionInputsWithoutAgents.map((action) => ({
205
+ name: action.name,
206
+ description: action.description,
207
+ parameters: JSON.parse(action.jsonSchema),
208
+ })),
209
+ }),
210
+ });
211
+
212
+ if (!response.ok) {
213
+ logger.error(
214
+ { url, status: response.status, body: await response.text() },
215
+ "Failed to execute remote agent",
216
+ );
217
+ throw new Error("Failed to execute remote agent");
218
+ }
219
+
220
+ const eventSource = new RemoteLangGraphEventSource();
221
+ streamResponse(response.body!, eventSource.eventStream$);
222
+ return eventSource.processLangGraphEvents();
223
+ },
224
+ }))
225
+ : [];
220
226
 
221
227
  return [...actions, ...agents];
222
228
  }
@@ -53,6 +53,7 @@ export type LangGraphAgentHandlerParams = {
53
53
  actionInputsWithoutAgents: ActionInput[];
54
54
  threadId?: string;
55
55
  nodeName?: string;
56
+ additionalMessages?: Message[];
56
57
  };
57
58
 
58
59
  export type LangGraphAgentAction = Action<any> & {
@@ -5,7 +5,7 @@ import { Logger } from "pino";
5
5
  import { ActionInput } from "../../graphql/inputs/action.input";
6
6
  import { LangGraphPlatformAgent, LangGraphPlatformEndpoint } from "./remote-actions";
7
7
  import { CopilotRequestContextProperties } from "../integrations";
8
- import { Message, MessageType } from "../../graphql/types/converted";
8
+ import { ActionExecutionMessage, Message, MessageType } from "../../graphql/types/converted";
9
9
  import { MessageRole } from "../../graphql/types/enums";
10
10
  import { CustomEventNames, LangGraphEventTypes } from "../../agents/langgraph/events";
11
11
  import telemetry from "../telemetry-client";
@@ -112,7 +112,7 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
112
112
  const mode = wasInitiatedWithExistingThread && nodeName != "__end__" ? "continue" : "start";
113
113
  let formattedMessages = [];
114
114
  try {
115
- formattedMessages = formatMessages(messages);
115
+ formattedMessages = copilotkitMessagesToLangChain(messages);
116
116
  } catch (e) {
117
117
  logger.error(e, `Error event thrown: ${e.message}`);
118
118
  }
@@ -319,6 +319,7 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
319
319
  state: state.values,
320
320
  running: !shouldExit,
321
321
  active: false,
322
+ includeMessages: true,
322
323
  }),
323
324
  );
324
325
 
@@ -341,6 +342,7 @@ function getStateSyncEvent({
341
342
  state,
342
343
  running,
343
344
  active,
345
+ includeMessages = false,
344
346
  }: {
345
347
  threadId: string;
346
348
  runId: string;
@@ -349,13 +351,21 @@ function getStateSyncEvent({
349
351
  state: State;
350
352
  running: boolean;
351
353
  active: boolean;
354
+ includeMessages?: boolean;
352
355
  }): string {
353
- const stateWithoutMessages = Object.keys(state).reduce((acc, key) => {
354
- if (key !== "messages") {
355
- acc[key] = state[key];
356
- }
357
- return acc;
358
- }, {} as State);
356
+ if (!includeMessages) {
357
+ state = Object.keys(state).reduce((acc, key) => {
358
+ if (key !== "messages") {
359
+ acc[key] = state[key];
360
+ }
361
+ return acc;
362
+ }, {} as State);
363
+ } else {
364
+ state = {
365
+ ...state,
366
+ messages: langchainMessagesToCopilotKit(state.messages || []),
367
+ };
368
+ }
359
369
 
360
370
  return (
361
371
  JSON.stringify({
@@ -365,7 +375,7 @@ function getStateSyncEvent({
365
375
  agent_name: agentName,
366
376
  node_name: nodeName,
367
377
  active: active,
368
- state: stateWithoutMessages,
378
+ state: state,
369
379
  running: running,
370
380
  role: "assistant",
371
381
  }) + "\n"
@@ -460,179 +470,188 @@ function langGraphDefaultMergeState(
460
470
  }
461
471
 
462
472
  // merge with existing messages
463
- const mergedMessages: LangGraphPlatformMessage[] = state.messages || [];
464
- const existingMessageIds = new Set(mergedMessages.map((message) => message.id));
465
- const existingToolCallResults = new Set<string>();
473
+ const existingMessages: LangGraphPlatformMessage[] = state.messages || [];
474
+ const existingMessageIds = new Set(existingMessages.map((message) => message.id));
475
+ const newMessages = messages.filter((message) => !existingMessageIds.has(message.id));
476
+
477
+ return {
478
+ ...state,
479
+ messages: newMessages,
480
+ copilotkit: {
481
+ actions,
482
+ },
483
+ };
484
+ }
466
485
 
467
- for (const message of mergedMessages) {
468
- if ("tool_call_id" in message) {
469
- existingToolCallResults.add(message.tool_call_id);
486
+ function langchainMessagesToCopilotKit(messages: any[]): any[] {
487
+ const result: any[] = [];
488
+ const tool_call_names: Record<string, string> = {};
489
+
490
+ // First pass: gather all tool call names from AI messages
491
+ for (const message of messages) {
492
+ if (message.type === "ai") {
493
+ for (const tool_call of message.tool_calls) {
494
+ tool_call_names[tool_call.id] = tool_call.name;
495
+ }
470
496
  }
471
497
  }
472
498
 
473
499
  for (const message of messages) {
474
- // filter tool calls to activate the agent itself
475
- if (
476
- "tool_calls" in message &&
477
- message.tool_calls.length > 0 &&
478
- message.tool_calls[0].name === agentName
479
- ) {
480
- continue;
500
+ let content: any = message.content;
501
+ if (content instanceof Array) {
502
+ content = content[0];
481
503
  }
482
-
483
- // filter results from activating the agent
484
- if ("name" in message && message.name === agentName) {
485
- continue;
504
+ if (content instanceof Object) {
505
+ content = content.text;
486
506
  }
487
507
 
488
- if (!existingMessageIds.has(message.id)) {
489
- // skip duplicate tool call results
490
- if ("tool_call_id" in message && existingToolCallResults.has(message.tool_call_id)) {
491
- console.warn("Warning: Duplicate tool call result, skipping:", message.tool_call_id);
492
- continue;
493
- }
494
-
495
- mergedMessages.push(message);
496
- } else {
497
- // Replace the message with the existing one
498
- for (let i = 0; i < mergedMessages.length; i++) {
499
- if (mergedMessages[i].id === message.id && message.role === "assistant") {
500
- if (
501
- ("tool_calls" in mergedMessages[i] || "additional_kwargs" in mergedMessages[i]) &&
502
- mergedMessages[i].content
503
- ) {
504
- // @ts-expect-error -- message did not have a tool call, now it will
505
- message.tool_calls = mergedMessages[i]["tool_calls"];
506
- message.additional_kwargs = mergedMessages[i].additional_kwargs;
507
- }
508
- mergedMessages[i] = message;
508
+ if (message.type === "human") {
509
+ result.push({
510
+ role: "user",
511
+ content: content,
512
+ id: message.id,
513
+ });
514
+ } else if (message.type === "system") {
515
+ result.push({
516
+ role: "system",
517
+ content: content,
518
+ id: message.id,
519
+ });
520
+ } else if (message.type === "ai") {
521
+ if (message.tool_calls && message.tool_calls.length > 0) {
522
+ for (const tool_call of message.tool_calls) {
523
+ result.push({
524
+ id: tool_call.id,
525
+ name: tool_call.name,
526
+ arguments: tool_call.args,
527
+ parentMessageId: message.id,
528
+ });
509
529
  }
530
+ } else {
531
+ result.push({
532
+ role: "assistant",
533
+ content: content,
534
+ id: message.id,
535
+ parentMessageId: message.id,
536
+ });
510
537
  }
538
+ } else if (message.type === "tool") {
539
+ const actionName = tool_call_names[message.tool_call_id] || message.name || "";
540
+ result.push({
541
+ actionExecutionId: message.tool_call_id,
542
+ actionName: actionName,
543
+ result: content,
544
+ id: message.id,
545
+ });
511
546
  }
512
547
  }
513
-
514
- // fix wrong tool call ids
515
- for (let i = 0; i < mergedMessages.length - 1; i++) {
516
- const currentMessage = mergedMessages[i];
517
- const nextMessage = mergedMessages[i + 1];
518
-
519
- if (
520
- "tool_calls" in currentMessage &&
521
- currentMessage.tool_calls.length > 0 &&
522
- "tool_call_id" in nextMessage
523
- ) {
524
- nextMessage.tool_call_id = currentMessage.tool_calls[0].id;
548
+ const resultsDict: Record<string, any> = {};
549
+ for (const msg of result) {
550
+ if (msg.actionExecutionId) {
551
+ resultsDict[msg.actionExecutionId] = msg;
525
552
  }
526
553
  }
527
554
 
528
- // try to auto-correct and log alignment issues
529
- const correctedMessages: LangGraphPlatformMessage[] = [];
555
+ const reorderedResult: Message[] = [];
530
556
 
531
- for (let i = 0; i < mergedMessages.length; i++) {
532
- const currentMessage = mergedMessages[i];
533
- const nextMessage = mergedMessages[i + 1] || null;
534
- const prevMessage = mergedMessages[i - 1] || null;
557
+ for (const msg of result) {
558
+ // If it's not a tool result, just append it
559
+ if (!("actionExecutionId" in msg)) {
560
+ reorderedResult.push(msg);
561
+ }
535
562
 
536
- if ("tool_calls" in currentMessage && currentMessage.tool_calls.length > 0) {
537
- if (!nextMessage) {
538
- console.warn(
539
- "No next message to auto-correct tool call, skipping:",
540
- currentMessage.tool_calls[0].id,
541
- );
542
- continue;
563
+ // If the message has arguments (i.e., is a tool call invocation),
564
+ // append the corresponding result right after it
565
+ if ("arguments" in msg) {
566
+ const msgId = msg.id;
567
+ if (msgId in resultsDict) {
568
+ reorderedResult.push(resultsDict[msgId]);
543
569
  }
570
+ }
571
+ }
544
572
 
545
- if (
546
- !("tool_call_id" in nextMessage) ||
547
- nextMessage.tool_call_id !== currentMessage.tool_calls[0].id
548
- ) {
549
- const toolMessage = mergedMessages.find(
550
- (m) => "tool_call_id" in m && m.tool_call_id === currentMessage.tool_calls[0].id,
551
- );
573
+ return reorderedResult;
574
+ }
552
575
 
553
- if (toolMessage) {
554
- console.warn(
555
- "Auto-corrected tool call alignment issue:",
556
- currentMessage.tool_calls[0].id,
557
- );
558
- correctedMessages.push(currentMessage, toolMessage);
559
- continue;
560
- } else {
561
- console.warn(
562
- "No corresponding tool call result found for tool call, skipping:",
563
- currentMessage.tool_calls[0].id,
564
- );
565
- continue;
566
- }
567
- }
576
+ function copilotkitMessagesToLangChain(messages: Message[]): LangGraphPlatformMessage[] {
577
+ const result: LangGraphPlatformMessage[] = [];
578
+ const processedActionExecutions = new Set<string>();
568
579
 
569
- correctedMessages.push(currentMessage);
580
+ for (const message of messages) {
581
+ // Handle TextMessage
582
+ if (message.isTextMessage()) {
583
+ if (message.role === "user") {
584
+ // Human message
585
+ result.push({
586
+ ...message,
587
+ role: MessageRole.user,
588
+ });
589
+ } else if (message.role === "system") {
590
+ // System message
591
+ result.push({
592
+ ...message,
593
+ role: MessageRole.system,
594
+ });
595
+ } else if (message.role === "assistant") {
596
+ // Assistant message
597
+ result.push({
598
+ ...message,
599
+ role: MessageRole.assistant,
600
+ });
601
+ }
570
602
  continue;
571
603
  }
572
604
 
573
- if ("tool_call_id" in currentMessage) {
574
- if (!prevMessage || !("tool_calls" in prevMessage)) {
575
- console.warn("No previous tool call, skipping tool call result:", currentMessage.id);
576
- continue;
577
- }
605
+ // Handle ActionExecutionMessage (multiple tool calls per parentMessageId)
606
+ if (message.isActionExecutionMessage()) {
607
+ const messageId = message.parentMessageId ?? message.id;
578
608
 
579
- if (prevMessage.tool_calls && prevMessage.tool_calls[0].id !== currentMessage.tool_call_id) {
580
- console.warn("Tool call id is incorrect, skipping tool call result:", currentMessage.id);
609
+ // If we've already processed this action execution group, skip
610
+ if (processedActionExecutions.has(messageId)) {
581
611
  continue;
582
612
  }
583
613
 
584
- correctedMessages.push(currentMessage);
585
- continue;
586
- }
614
+ processedActionExecutions.add(messageId);
587
615
 
588
- correctedMessages.push(currentMessage);
589
- }
616
+ // Gather all tool calls related to this messageId
617
+ const relatedActionExecutions = messages.filter(
618
+ (m) =>
619
+ m.isActionExecutionMessage() &&
620
+ ((m.parentMessageId && m.parentMessageId === messageId) || m.id === messageId),
621
+ ) as ActionExecutionMessage[];
590
622
 
591
- return {
592
- ...state,
593
- messages: correctedMessages,
594
- copilotkit: {
595
- actions,
596
- },
597
- };
598
- }
623
+ const tool_calls: ToolCall[] = relatedActionExecutions.map((m) => ({
624
+ name: m.name,
625
+ args: m.arguments,
626
+ id: m.id,
627
+ }));
599
628
 
600
- function formatMessages(messages: Message[]): LangGraphPlatformMessage[] {
601
- return messages.map((message) => {
602
- if (message.isTextMessage() && message.role === "assistant") {
603
- return message;
604
- }
605
- if (message.isTextMessage() && message.role === "system") {
606
- return message;
607
- }
608
- if (message.isTextMessage() && message.role === "user") {
609
- return message;
610
- }
611
- if (message.isActionExecutionMessage()) {
612
- const toolCall: ToolCall = {
613
- name: message.name,
614
- args: message.arguments,
615
- id: message.id,
616
- };
617
- return {
618
- type: message.type,
629
+ result.push({
630
+ id: messageId,
631
+ type: "ActionExecutionMessage",
619
632
  content: "",
620
- tool_calls: [toolCall],
633
+ tool_calls: tool_calls,
621
634
  role: MessageRole.assistant,
622
- id: message.id,
623
- } satisfies LangGraphPlatformActionExecutionMessage;
635
+ } satisfies LangGraphPlatformActionExecutionMessage);
636
+
637
+ continue;
624
638
  }
639
+
640
+ // Handle ResultMessage
625
641
  if (message.isResultMessage()) {
626
- return {
642
+ result.push({
627
643
  type: message.type,
628
644
  content: message.result,
629
645
  id: message.id,
630
646
  tool_call_id: message.actionExecutionId,
631
647
  name: message.actionName,
632
648
  role: MessageRole.tool,
633
- } satisfies LangGraphPlatformResultMessage;
649
+ } satisfies LangGraphPlatformResultMessage);
650
+ continue;
634
651
  }
635
652
 
636
653
  throw new Error(`Unknown message type ${message.type}`);
637
- });
654
+ }
655
+
656
+ return result;
638
657
  }
@@ -120,7 +120,11 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
120
120
  mode = "message";
121
121
  } else if (chunk.content_block.type === "tool_use") {
122
122
  currentToolCallId = chunk.content_block.id;
123
- eventStream$.sendActionExecutionStart(currentToolCallId, chunk.content_block.name);
123
+ eventStream$.sendActionExecutionStart({
124
+ actionExecutionId: currentToolCallId,
125
+ actionName: chunk.content_block.name,
126
+ parentMessageId: currentMessageId,
127
+ });
124
128
  mode = "function";
125
129
  }
126
130
  } else if (chunk.type === "content_block_delta") {
@@ -128,21 +132,27 @@ export class AnthropicAdapter implements CopilotServiceAdapter {
128
132
  const text = filterThinkingTextBuffer.onTextChunk(chunk.delta.text);
129
133
  if (text.length > 0) {
130
134
  if (!didOutputText) {
131
- eventStream$.sendTextMessageStart(currentMessageId);
135
+ eventStream$.sendTextMessageStart({ messageId: currentMessageId });
132
136
  didOutputText = true;
133
137
  }
134
- eventStream$.sendTextMessageContent(text);
138
+ eventStream$.sendTextMessageContent({
139
+ messageId: currentMessageId,
140
+ content: text,
141
+ });
135
142
  }
136
143
  } else if (chunk.delta.type === "input_json_delta") {
137
- eventStream$.sendActionExecutionArgs(chunk.delta.partial_json);
144
+ eventStream$.sendActionExecutionArgs({
145
+ actionExecutionId: currentToolCallId,
146
+ args: chunk.delta.partial_json,
147
+ });
138
148
  }
139
149
  } else if (chunk.type === "content_block_stop") {
140
150
  if (mode === "message") {
141
151
  if (didOutputText) {
142
- eventStream$.sendTextMessageEnd();
152
+ eventStream$.sendTextMessageEnd({ messageId: currentMessageId });
143
153
  }
144
154
  } else if (mode === "function") {
145
- eventStream$.sendActionExecutionEnd();
155
+ eventStream$.sendActionExecutionEnd({ actionExecutionId: currentToolCallId });
146
156
  }
147
157
  }
148
158
  }
@@ -19,6 +19,7 @@ export function convertGqlInputToMessages(inputMessages: MessageInput[]): Messag
19
19
  createdAt: message.createdAt,
20
20
  role: message.textMessage.role,
21
21
  content: message.textMessage.content,
22
+ parentMessageId: message.textMessage.parentMessageId,
22
23
  }),
23
24
  );
24
25
  } else if (message.actionExecutionMessage) {
@@ -28,7 +29,7 @@ export function convertGqlInputToMessages(inputMessages: MessageInput[]): Messag
28
29
  createdAt: message.createdAt,
29
30
  name: message.actionExecutionMessage.name,
30
31
  arguments: JSON.parse(message.actionExecutionMessage.arguments),
31
- scope: message.actionExecutionMessage.scope,
32
+ parentMessageId: message.actionExecutionMessage.parentMessageId,
32
33
  }),
33
34
  );
34
35
  } else if (message.resultMessage) {