@copilotkit/runtime 1.9.2-next.7 → 1.9.2-next.8

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 (32) hide show
  1. package/CHANGELOG.md +7 -0
  2. package/dist/{chunk-GW6ERFKI.mjs → chunk-4TLMVLU4.mjs} +2 -2
  3. package/dist/{chunk-2PQGAIVB.mjs → chunk-5SG4WWXH.mjs} +2 -2
  4. package/dist/{chunk-LSB3QZHS.mjs → chunk-JWPSIGSA.mjs} +2 -2
  5. package/dist/{chunk-2UAJCT5X.mjs → chunk-KYCDL2KX.mjs} +2 -2
  6. package/dist/{chunk-HB4D2KJC.mjs → chunk-WIXS6EG7.mjs} +42 -33
  7. package/dist/chunk-WIXS6EG7.mjs.map +1 -0
  8. package/dist/index.js +41 -32
  9. package/dist/index.js.map +1 -1
  10. package/dist/index.mjs +5 -5
  11. package/dist/lib/index.js +41 -32
  12. package/dist/lib/index.js.map +1 -1
  13. package/dist/lib/index.mjs +5 -5
  14. package/dist/lib/integrations/index.js +1 -1
  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 +1 -1
  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 +1 -1
  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 +1 -1
  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 +2 -2
  27. package/src/lib/runtime/remote-lg-action.ts +45 -37
  28. package/dist/chunk-HB4D2KJC.mjs.map +0 -1
  29. /package/dist/{chunk-GW6ERFKI.mjs.map → chunk-4TLMVLU4.mjs.map} +0 -0
  30. /package/dist/{chunk-2PQGAIVB.mjs.map → chunk-5SG4WWXH.mjs.map} +0 -0
  31. /package/dist/{chunk-LSB3QZHS.mjs.map → chunk-JWPSIGSA.mjs.map} +0 -0
  32. /package/dist/{chunk-2UAJCT5X.mjs.map → chunk-KYCDL2KX.mjs.map} +0 -0
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  copilotRuntimeNodeHttpEndpoint
3
- } from "../../../chunk-HB4D2KJC.mjs";
3
+ } from "../../../chunk-WIXS6EG7.mjs";
4
4
  import "../../../chunk-IIXJVVTV.mjs";
5
5
  import "../../../chunk-5BIEM2UU.mjs";
6
6
  import "../../../chunk-SHBDMA63.mjs";
package/package.json CHANGED
@@ -9,7 +9,7 @@
9
9
  "publishConfig": {
10
10
  "access": "public"
11
11
  },
12
- "version": "1.9.2-next.7",
12
+ "version": "1.9.2-next.8",
13
13
  "sideEffects": false,
14
14
  "main": "./dist/index.js",
15
15
  "module": "./dist/index.mjs",
@@ -66,7 +66,7 @@
66
66
  "rxjs": "7.8.1",
67
67
  "type-graphql": "2.0.0-rc.1",
68
68
  "zod": "^3.23.3",
69
- "@copilotkit/shared": "1.9.2-next.7"
69
+ "@copilotkit/shared": "1.9.2-next.8"
70
70
  },
71
71
  "peerDependencies": {
72
72
  "@ag-ui/client": ">=0.0.28",
@@ -2,7 +2,9 @@ import {
2
2
  Client as LangGraphClient,
3
3
  EventsStreamEvent,
4
4
  GraphSchema,
5
+ Interrupt,
5
6
  StreamMode,
7
+ ThreadState,
6
8
  } from "@langchain/langgraph-sdk";
7
9
  import { createHash } from "node:crypto";
8
10
  import { isValidUUID, randomUUID } from "@copilotkit/shared";
@@ -84,8 +86,6 @@ type SchemaKeys = {
84
86
  config: string[] | null;
85
87
  } | null;
86
88
 
87
- let activeInterruptEvent = false;
88
-
89
89
  export async function execute(args: ExecutionArgs): Promise<ReadableStream<Uint8Array>> {
90
90
  return new ReadableStream({
91
91
  async start(controller) {
@@ -188,7 +188,7 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
188
188
  await client.threads.create({ threadId });
189
189
  }
190
190
 
191
- let agentState = { values: {} };
191
+ let agentState = { values: {} } as ThreadState;
192
192
  if (wasInitiatedWithExistingThread) {
193
193
  agentState = await client.threads.getState(threadId);
194
194
  }
@@ -218,16 +218,14 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
218
218
  const lgInterruptMetaEvent = metaEvents?.find(
219
219
  (ev) => ev.name === MetaEventName.LangGraphInterruptEvent,
220
220
  );
221
- if (activeInterruptEvent && !lgInterruptMetaEvent) {
222
- // state.messages includes only messages that were not processed by the agent, which are the interrupt messages
223
- payload.command = { resume: state.messages };
224
- }
221
+
225
222
  if (lgInterruptMetaEvent?.response) {
226
223
  let response = lgInterruptMetaEvent.response;
227
224
  payload.command = { resume: parseJson(response, response) };
228
225
  }
229
226
 
230
- if (mode === "continue" && !activeInterruptEvent) {
227
+ const interrupts = (agentState.tasks?.[0]?.interrupts ?? []) as Interrupt[];
228
+ if (mode === "continue" && !interrupts.length) {
231
229
  await client.threads.updateState(threadId, { values: state, asNode: nodeName });
232
230
  }
233
231
 
@@ -311,17 +309,30 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
311
309
  let shouldExit = false;
312
310
  let externalRunId = null;
313
311
 
314
- const streamResponse = client.runs.stream(threadId, assistantId, payload);
315
-
316
312
  const emit = (message: string) => controller.enqueue(new TextEncoder().encode(message));
317
313
 
314
+ // If there are still outstanding unresolved interrupts, we must force resolution of them before moving forward
315
+ if (interrupts?.length && !payload.command?.resume) {
316
+ // If the interrupt is "by message" we assume the upcoming user message is a resoluton for the interrupt
317
+ if (!lgInterruptMetaEvent) {
318
+ // state.messages includes only messages that were not processed by the agent, which are the interrupt messages
319
+ payload.command = { resume: state.messages };
320
+ } else {
321
+ interrupts.forEach((interrupt) => {
322
+ emitInterrupt(interrupt.value, emit);
323
+ });
324
+ return Promise.resolve();
325
+ }
326
+ }
327
+
328
+ const streamResponse = client.runs.stream(threadId, assistantId, payload);
329
+
318
330
  let latestStateValues = {};
319
331
  let updatedState = state;
320
332
  // If a manual emittance happens, it is the ultimate source of truth of state, unless a node has exited.
321
333
  // Therefore, this value should either hold null, or the only edition of state that should be used.
322
334
  let manuallyEmittedState = null;
323
335
 
324
- activeInterruptEvent = false;
325
336
  try {
326
337
  telemetry.capture("oss.runtime.agent_execution_stream_started", {
327
338
  hashedLgcKey: streamInfo.hashedLgcKey,
@@ -345,33 +356,8 @@ async function streamEvents(controller: ReadableStreamDefaultController, args: E
345
356
 
346
357
  const interruptEvents = chunk.data.__interrupt__;
347
358
  if (interruptEvents?.length) {
348
- activeInterruptEvent = true;
349
359
  const interruptValue = interruptEvents?.[0].value;
350
- if (
351
- typeof interruptValue != "string" &&
352
- "__copilotkit_interrupt_value__" in interruptValue
353
- ) {
354
- const evValue = interruptValue.__copilotkit_interrupt_value__;
355
- emit(
356
- JSON.stringify({
357
- event: LangGraphEventTypes.OnCopilotKitInterrupt,
358
- data: {
359
- value: typeof evValue === "string" ? evValue : JSON.stringify(evValue),
360
- messages: langchainMessagesToCopilotKit(interruptValue.__copilotkit_messages__),
361
- },
362
- }) + "\n",
363
- );
364
- } else {
365
- emit(
366
- JSON.stringify({
367
- event: LangGraphEventTypes.OnInterrupt,
368
- value:
369
- typeof interruptValue === "string"
370
- ? interruptValue
371
- : JSON.stringify(interruptValue),
372
- }) + "\n",
373
- );
374
- }
360
+ emitInterrupt(interruptValue, emit);
375
361
  continue;
376
362
  }
377
363
  if (streamResponseChunk.event === "updates") continue;
@@ -909,3 +895,25 @@ function getSchemaKeys(graphSchema: GraphSchema): SchemaKeys {
909
895
  function filterObjectBySchemaKeys(obj: Record<string, any>, schemaKeys: string[]) {
910
896
  return Object.fromEntries(Object.entries(obj).filter(([key]) => schemaKeys.includes(key)));
911
897
  }
898
+
899
+ function emitInterrupt(interruptValue: any, emit: (data: string) => void) {
900
+ if (typeof interruptValue != "string" && "__copilotkit_interrupt_value__" in interruptValue) {
901
+ const evValue = interruptValue.__copilotkit_interrupt_value__;
902
+ emit(
903
+ JSON.stringify({
904
+ event: LangGraphEventTypes.OnCopilotKitInterrupt,
905
+ data: {
906
+ value: typeof evValue === "string" ? evValue : JSON.stringify(evValue),
907
+ messages: langchainMessagesToCopilotKit(interruptValue.__copilotkit_messages__),
908
+ },
909
+ }) + "\n",
910
+ );
911
+ } else {
912
+ emit(
913
+ JSON.stringify({
914
+ event: LangGraphEventTypes.OnInterrupt,
915
+ value: typeof interruptValue === "string" ? interruptValue : JSON.stringify(interruptValue),
916
+ }) + "\n",
917
+ );
918
+ }
919
+ }