@copilotkit/runtime 1.61.0 → 1.61.2

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 (112) hide show
  1. package/dist/agent/converters/aisdk.cjs +52 -1
  2. package/dist/agent/converters/aisdk.cjs.map +1 -1
  3. package/dist/agent/converters/aisdk.d.cts +6 -2
  4. package/dist/agent/converters/aisdk.d.cts.map +1 -1
  5. package/dist/agent/converters/aisdk.d.mts +6 -2
  6. package/dist/agent/converters/aisdk.d.mts.map +1 -1
  7. package/dist/agent/converters/aisdk.mjs +52 -1
  8. package/dist/agent/converters/aisdk.mjs.map +1 -1
  9. package/dist/agent/converters/tanstack.cjs +68 -9
  10. package/dist/agent/converters/tanstack.cjs.map +1 -1
  11. package/dist/agent/converters/tanstack.d.cts +30 -2
  12. package/dist/agent/converters/tanstack.d.cts.map +1 -1
  13. package/dist/agent/converters/tanstack.d.mts +30 -2
  14. package/dist/agent/converters/tanstack.d.mts.map +1 -1
  15. package/dist/agent/converters/tanstack.mjs +68 -9
  16. package/dist/agent/converters/tanstack.mjs.map +1 -1
  17. package/dist/agent/index.cjs +165 -39
  18. package/dist/agent/index.cjs.map +1 -1
  19. package/dist/agent/index.d.cts +42 -4
  20. package/dist/agent/index.d.cts.map +1 -1
  21. package/dist/agent/index.d.mts +42 -4
  22. package/dist/agent/index.d.mts.map +1 -1
  23. package/dist/agent/index.mjs +165 -40
  24. package/dist/agent/index.mjs.map +1 -1
  25. package/dist/graphql/message-conversion/agui-to-gql.cjs +5 -3
  26. package/dist/graphql/message-conversion/agui-to-gql.cjs.map +1 -1
  27. package/dist/graphql/message-conversion/agui-to-gql.mjs +5 -3
  28. package/dist/graphql/message-conversion/agui-to-gql.mjs.map +1 -1
  29. package/dist/lib/integrations/node-http/request-handler.cjs.map +1 -1
  30. package/dist/lib/integrations/node-http/request-handler.mjs.map +1 -1
  31. package/dist/lib/runtime/copilot-runtime.cjs +1 -1
  32. package/dist/lib/runtime/copilot-runtime.cjs.map +1 -1
  33. package/dist/lib/runtime/copilot-runtime.d.cts.map +1 -1
  34. package/dist/lib/runtime/copilot-runtime.d.mts.map +1 -1
  35. package/dist/lib/runtime/copilot-runtime.mjs +1 -1
  36. package/dist/lib/runtime/copilot-runtime.mjs.map +1 -1
  37. package/dist/package.cjs +3 -3
  38. package/dist/package.mjs +3 -3
  39. package/dist/service-adapters/openai/openai-assistant-adapter.cjs.map +1 -1
  40. package/dist/service-adapters/openai/openai-assistant-adapter.d.cts.map +1 -1
  41. package/dist/service-adapters/openai/openai-assistant-adapter.d.mts.map +1 -1
  42. package/dist/service-adapters/openai/openai-assistant-adapter.mjs.map +1 -1
  43. package/dist/service-adapters/openai/utils.cjs.map +1 -1
  44. package/dist/service-adapters/openai/utils.mjs.map +1 -1
  45. package/dist/v2/index.cjs +2 -0
  46. package/dist/v2/index.d.cts +3 -3
  47. package/dist/v2/index.d.mts +3 -3
  48. package/dist/v2/index.mjs +3 -3
  49. package/dist/v2/runtime/core/fetch-handler.cjs +5 -4
  50. package/dist/v2/runtime/core/fetch-handler.cjs.map +1 -1
  51. package/dist/v2/runtime/core/fetch-handler.mjs +5 -4
  52. package/dist/v2/runtime/core/fetch-handler.mjs.map +1 -1
  53. package/dist/v2/runtime/core/runtime.cjs +3 -3
  54. package/dist/v2/runtime/core/runtime.cjs.map +1 -1
  55. package/dist/v2/runtime/core/runtime.d.cts +10 -3
  56. package/dist/v2/runtime/core/runtime.d.cts.map +1 -1
  57. package/dist/v2/runtime/core/runtime.d.mts +10 -3
  58. package/dist/v2/runtime/core/runtime.d.mts.map +1 -1
  59. package/dist/v2/runtime/core/runtime.mjs +3 -3
  60. package/dist/v2/runtime/core/runtime.mjs.map +1 -1
  61. package/dist/v2/runtime/endpoints/express-fetch-bridge.cjs.map +1 -1
  62. package/dist/v2/runtime/endpoints/express-fetch-bridge.mjs.map +1 -1
  63. package/dist/v2/runtime/endpoints/single-route-helpers.cjs +1 -1
  64. package/dist/v2/runtime/endpoints/single-route-helpers.cjs.map +1 -1
  65. package/dist/v2/runtime/endpoints/single-route-helpers.mjs +1 -1
  66. package/dist/v2/runtime/endpoints/single-route-helpers.mjs.map +1 -1
  67. package/dist/v2/runtime/handlers/get-runtime-info.cjs +14 -1
  68. package/dist/v2/runtime/handlers/get-runtime-info.cjs.map +1 -1
  69. package/dist/v2/runtime/handlers/get-runtime-info.mjs +14 -1
  70. package/dist/v2/runtime/handlers/get-runtime-info.mjs.map +1 -1
  71. package/dist/v2/runtime/handlers/handle-run.cjs +4 -3
  72. package/dist/v2/runtime/handlers/handle-run.cjs.map +1 -1
  73. package/dist/v2/runtime/handlers/handle-run.mjs +4 -3
  74. package/dist/v2/runtime/handlers/handle-run.mjs.map +1 -1
  75. package/dist/v2/runtime/handlers/intelligence/thread-names.cjs +0 -2
  76. package/dist/v2/runtime/handlers/intelligence/thread-names.cjs.map +1 -1
  77. package/dist/v2/runtime/handlers/intelligence/thread-names.mjs +0 -2
  78. package/dist/v2/runtime/handlers/intelligence/thread-names.mjs.map +1 -1
  79. package/dist/v2/runtime/handlers/intelligence/threads.cjs +6 -6
  80. package/dist/v2/runtime/handlers/intelligence/threads.cjs.map +1 -1
  81. package/dist/v2/runtime/handlers/intelligence/threads.mjs +6 -6
  82. package/dist/v2/runtime/handlers/intelligence/threads.mjs.map +1 -1
  83. package/dist/v2/runtime/handlers/shared/agent-utils.cjs +8 -4
  84. package/dist/v2/runtime/handlers/shared/agent-utils.cjs.map +1 -1
  85. package/dist/v2/runtime/handlers/shared/agent-utils.mjs +8 -4
  86. package/dist/v2/runtime/handlers/shared/agent-utils.mjs.map +1 -1
  87. package/dist/v2/runtime/index.d.cts +1 -1
  88. package/dist/v2/runtime/index.d.mts +1 -1
  89. package/dist/v2/runtime/runner/agent-runner.cjs +4 -0
  90. package/dist/v2/runtime/runner/agent-runner.cjs.map +1 -1
  91. package/dist/v2/runtime/runner/agent-runner.d.cts +21 -1
  92. package/dist/v2/runtime/runner/agent-runner.d.cts.map +1 -1
  93. package/dist/v2/runtime/runner/agent-runner.d.mts +21 -1
  94. package/dist/v2/runtime/runner/agent-runner.d.mts.map +1 -1
  95. package/dist/v2/runtime/runner/agent-runner.mjs +4 -1
  96. package/dist/v2/runtime/runner/agent-runner.mjs.map +1 -1
  97. package/dist/v2/runtime/runner/in-memory.cjs +4 -0
  98. package/dist/v2/runtime/runner/in-memory.cjs.map +1 -1
  99. package/dist/v2/runtime/runner/in-memory.d.cts +1 -0
  100. package/dist/v2/runtime/runner/in-memory.d.cts.map +1 -1
  101. package/dist/v2/runtime/runner/in-memory.d.mts +1 -0
  102. package/dist/v2/runtime/runner/in-memory.d.mts.map +1 -1
  103. package/dist/v2/runtime/runner/in-memory.mjs +4 -0
  104. package/dist/v2/runtime/runner/in-memory.mjs.map +1 -1
  105. package/dist/v2/runtime/runner/index.d.cts +1 -1
  106. package/dist/v2/runtime/runner/index.d.mts +1 -1
  107. package/dist/v2/runtime/runner/index.mjs +1 -1
  108. package/dist/v2/runtime/runner/intelligence.cjs.map +1 -1
  109. package/dist/v2/runtime/runner/intelligence.d.cts.map +1 -1
  110. package/dist/v2/runtime/runner/intelligence.d.mts.map +1 -1
  111. package/dist/v2/runtime/runner/intelligence.mjs.map +1 -1
  112. package/package.json +4 -4
@@ -42,6 +42,18 @@ function resolveModel(spec, apiKey) {
42
42
  }
43
43
  }
44
44
  /**
45
+ * Thrown by `AgentFactoryContext.interrupt()` on a fresh (non-resume) run to
46
+ * pause the factory. Caught in `runFactory` and translated into a RUN_FINISHED
47
+ * event carrying `outcome:{type:"interrupt",interrupts}`. Not a real error.
48
+ */
49
+ var InterruptSignal = class extends Error {
50
+ constructor(interrupts) {
51
+ super("CopilotKit interrupt: run paused awaiting human input");
52
+ this.interrupts = interrupts;
53
+ this.name = "InterruptSignal";
54
+ }
55
+ };
56
+ /**
45
57
  * Define a tool for use with BuiltInAgent
46
58
  * @param name - The name of the tool
47
59
  * @param description - Description of what the tool does
@@ -54,7 +66,10 @@ function defineTool(config) {
54
66
  name: config.name,
55
67
  description: config.description,
56
68
  parameters: config.parameters,
57
- execute: config.execute
69
+ execute: config.execute,
70
+ interrupt: config.interrupt,
71
+ interruptReason: config.interruptReason,
72
+ interruptMessage: config.interruptMessage
58
73
  };
59
74
  }
60
75
  /**
@@ -270,6 +285,19 @@ function isJsonSchema(obj) {
270
285
  "array"
271
286
  ].includes(schema.type);
272
287
  }
288
+ /**
289
+ * Type-only pass-through for handing a Zod schema to the AI SDK's `tool()`.
290
+ * The raw Zod schema is returned unchanged at runtime — the SDK's `asSchema()`
291
+ * converts and validates it internally exactly as before.
292
+ *
293
+ * The Zod type is erased through `unknown` deliberately: letting tsc relate
294
+ * Zod schema types to the AI SDK's `FlexibleSchema` union (conditional types
295
+ * spanning zod v3/v4) makes type instantiation explode (TS2589 / compiler
296
+ * OOM) under this package's `moduleResolution: node`.
297
+ */
298
+ function toLanguageModelSchema(schema) {
299
+ return schema;
300
+ }
273
301
  function convertToolsToVercelAITools(tools) {
274
302
  const result = {};
275
303
  for (const tool of tools) {
@@ -277,7 +305,7 @@ function convertToolsToVercelAITools(tools) {
277
305
  const zodSchema = convertJsonSchemaToZodSchema(tool.parameters, true);
278
306
  result[tool.name] = (0, ai.tool)({
279
307
  description: tool.description,
280
- inputSchema: zodSchema
308
+ inputSchema: toLanguageModelSchema(zodSchema)
281
309
  });
282
310
  }
283
311
  return result;
@@ -336,16 +364,19 @@ var BuiltInAgent = class BuiltInAgent extends _ag_ui_client.AbstractAgent {
336
364
  supported: true,
337
365
  clientProvided: true
338
366
  },
339
- transport: { streaming: true }
367
+ transport: { streaming: true },
368
+ humanInTheLoop: { interrupts: true }
340
369
  };
341
- if (!this.config.capabilities) return inferred;
370
+ const capabilities = isFactoryConfig(this.config) ? void 0 : this.config.capabilities;
371
+ if (!capabilities) return inferred;
342
372
  return {
343
373
  ...inferred,
344
- ...this.config.capabilities
374
+ ...capabilities
345
375
  };
346
376
  }
347
377
  run(input) {
348
378
  if (isFactoryConfig(this.config)) return this.runFactory(input, this.config);
379
+ const config = this.config;
349
380
  if (this.abortController) throw new Error("Agent is already running. Call abortRun() first or create a new instance.");
350
381
  this.abortController = new AbortController();
351
382
  const abortController = this.abortController;
@@ -356,14 +387,14 @@ var BuiltInAgent = class BuiltInAgent extends _ag_ui_client.AbstractAgent {
356
387
  runId: input.runId
357
388
  };
358
389
  subscriber.next(startEvent);
359
- const model = resolveModel(this.config.model, this.config.apiKey);
390
+ const model = resolveModel(config.model, config.apiKey);
360
391
  let systemPrompt = void 0;
361
- const hasPrompt = !!this.config.prompt;
392
+ const hasPrompt = !!config.prompt;
362
393
  const hasContext = input.context && input.context.length > 0;
363
394
  const hasState = input.state !== void 0 && input.state !== null && !(typeof input.state === "object" && Object.keys(input.state).length === 0);
364
395
  if (hasPrompt || hasContext || hasState) {
365
396
  const parts = [];
366
- if (hasPrompt) parts.push(this.config.prompt);
397
+ if (hasPrompt) parts.push(config.prompt);
367
398
  if (hasContext) {
368
399
  parts.push("\n## Context from the application\n");
369
400
  for (const ctx of input.context) parts.push(`${ctx.description}:\n${ctx.value}\n`);
@@ -375,16 +406,46 @@ This is state from the application that you can edit by calling AGUISendStateSna
375
406
  systemPrompt = parts.join("");
376
407
  }
377
408
  const messages = convertMessagesToVercelAISDKMessages(input.messages, {
378
- forwardSystemMessages: this.config.forwardSystemMessages,
379
- forwardDeveloperMessages: this.config.forwardDeveloperMessages
409
+ forwardSystemMessages: config.forwardSystemMessages,
410
+ forwardDeveloperMessages: config.forwardDeveloperMessages
380
411
  });
381
412
  if (systemPrompt) messages.unshift({
382
413
  role: "system",
383
414
  content: systemPrompt
384
415
  });
416
+ const resumeEntries = input.resume ?? [];
417
+ if (resumeEntries.length > 0) {
418
+ const toolNameById = /* @__PURE__ */ new Map();
419
+ for (const m of input.messages) {
420
+ if (m.role !== "assistant") continue;
421
+ for (const tc of m.toolCalls ?? []) if (tc.id && tc.function?.name) toolNameById.set(tc.id, tc.function.name);
422
+ }
423
+ const alreadyAnswered = /* @__PURE__ */ new Set();
424
+ for (const m of messages) {
425
+ if (m.role !== "tool" || !Array.isArray(m.content)) continue;
426
+ for (const part of m.content) if (part && typeof part === "object" && "toolCallId" in part) alreadyAnswered.add(part.toolCallId);
427
+ }
428
+ for (const entry of resumeEntries) {
429
+ if (alreadyAnswered.has(entry.interruptId)) continue;
430
+ const value = entry.status === "cancelled" ? { status: "cancelled" } : entry.payload ?? { status: "resolved" };
431
+ const toolResultMessage = {
432
+ role: "tool",
433
+ content: [{
434
+ type: "tool-result",
435
+ toolCallId: entry.interruptId,
436
+ toolName: toolNameById.get(entry.interruptId) ?? "",
437
+ output: {
438
+ type: "json",
439
+ value
440
+ }
441
+ }]
442
+ };
443
+ messages.push(toolResultMessage);
444
+ }
445
+ }
385
446
  let allTools = convertToolsToVercelAITools(input.tools);
386
- if (this.config.tools && this.config.tools.length > 0) {
387
- const configTools = convertToolDefinitionsToVercelAITools(this.config.tools);
447
+ if (config.tools && config.tools.length > 0) {
448
+ const configTools = convertToolDefinitionsToVercelAITools(config.tools);
388
449
  allTools = {
389
450
  ...allTools,
390
451
  ...configTools
@@ -394,23 +455,23 @@ This is state from the application that you can edit by calling AGUISendStateSna
394
455
  model,
395
456
  messages,
396
457
  tools: allTools,
397
- toolChoice: this.config.toolChoice,
398
- stopWhen: this.config.maxSteps ? (0, ai.stepCountIs)(this.config.maxSteps) : void 0,
399
- maxOutputTokens: this.config.maxOutputTokens,
400
- temperature: this.config.temperature,
401
- topP: this.config.topP,
402
- topK: this.config.topK,
403
- presencePenalty: this.config.presencePenalty,
404
- frequencyPenalty: this.config.frequencyPenalty,
405
- stopSequences: this.config.stopSequences,
406
- seed: this.config.seed,
407
- providerOptions: this.config.providerOptions,
408
- maxRetries: this.config.maxRetries
458
+ toolChoice: config.toolChoice,
459
+ stopWhen: config.maxSteps ? (0, ai.stepCountIs)(config.maxSteps) : void 0,
460
+ maxOutputTokens: config.maxOutputTokens,
461
+ temperature: config.temperature,
462
+ topP: config.topP,
463
+ topK: config.topK,
464
+ presencePenalty: config.presencePenalty,
465
+ frequencyPenalty: config.frequencyPenalty,
466
+ stopSequences: config.stopSequences,
467
+ seed: config.seed,
468
+ providerOptions: config.providerOptions,
469
+ maxRetries: config.maxRetries
409
470
  };
410
471
  if (input.forwardedProps && typeof input.forwardedProps === "object") {
411
472
  const props = input.forwardedProps;
412
473
  if (props.model !== void 0 && this.canOverride("model")) {
413
- if (typeof props.model === "string" || typeof props.model === "object") streamTextParams.model = resolveModel(props.model, this.config.apiKey);
474
+ if (typeof props.model === "string" || typeof props.model === "object") streamTextParams.model = resolveModel(props.model, config.apiKey);
414
475
  }
415
476
  if (props.toolChoice !== void 0 && this.canOverride("toolChoice")) {
416
477
  const toolChoice = props.toolChoice;
@@ -456,7 +517,7 @@ This is state from the application that you can edit by calling AGUISendStateSna
456
517
  ...streamTextParams.tools,
457
518
  AGUISendStateSnapshot: (0, ai.tool)({
458
519
  description: "Replace the entire application state with a new snapshot",
459
- inputSchema: zod.z.object({ snapshot: zod.z.any().describe("The complete new state object") }),
520
+ inputSchema: toLanguageModelSchema(zod.z.object({ snapshot: zod.z.any().describe("The complete new state object") })),
460
521
  execute: async ({ snapshot }) => {
461
522
  return {
462
523
  success: true,
@@ -466,7 +527,7 @@ This is state from the application that you can edit by calling AGUISendStateSna
466
527
  }),
467
528
  AGUISendStateDelta: (0, ai.tool)({
468
529
  description: "Apply incremental updates to application state using JSON Patch operations",
469
- inputSchema: zod.z.object({ delta: zod.z.array(zod.z.object({
530
+ inputSchema: toLanguageModelSchema(zod.z.object({ delta: zod.z.array(zod.z.object({
470
531
  op: zod.z.enum([
471
532
  "add",
472
533
  "replace",
@@ -474,7 +535,7 @@ This is state from the application that you can edit by calling AGUISendStateSna
474
535
  ]).describe("The operation to perform"),
475
536
  path: zod.z.string().describe("JSON Pointer path (e.g., '/foo/bar')"),
476
537
  value: zod.z.any().optional().describe("The value to set. Required for 'add' and 'replace' operations, ignored for 'remove'.")
477
- })).describe("Array of JSON Patch operations") }),
538
+ })).describe("Array of JSON Patch operations") })),
478
539
  execute: async ({ delta }) => {
479
540
  return {
480
541
  success: true,
@@ -483,14 +544,14 @@ This is state from the application that you can edit by calling AGUISendStateSna
483
544
  }
484
545
  })
485
546
  };
486
- if (this.config.mcpClients && this.config.mcpClients.length > 0) for (const client of this.config.mcpClients) {
547
+ if (config.mcpClients && config.mcpClients.length > 0) for (const client of config.mcpClients) {
487
548
  const mcpTools = await client.tools();
488
549
  streamTextParams.tools = {
489
550
  ...streamTextParams.tools,
490
551
  ...mcpTools
491
552
  };
492
553
  }
493
- const allMcpServers = [...this.config.mcpServers ?? []];
554
+ const allMcpServers = [...config.mcpServers ?? []];
494
555
  if (allMcpServers.length > 0) for (const serverConfig of allMcpServers) {
495
556
  let transport;
496
557
  if (serverConfig.type === "http") transport = new _modelcontextprotocol_sdk_client_streamableHttp_js.StreamableHTTPClientTransport(new URL(serverConfig.url), serverConfig.options);
@@ -519,6 +580,12 @@ This is state from the application that you can edit by calling AGUISendStateSna
519
580
  ...streamTextParams,
520
581
  abortSignal: abortController.signal
521
582
  });
583
+ const interruptToolNames = new Set((isFactoryConfig(this.config) ? [] : this.config.tools ?? []).filter((t) => t.interrupt).map((t) => t.name));
584
+ const interruptToolMeta = new Map((isFactoryConfig(this.config) ? [] : this.config.tools ?? []).filter((t) => t.interrupt).map((t) => [t.name, {
585
+ reason: t.interruptReason ?? "tool_call",
586
+ message: t.interruptMessage
587
+ }]));
588
+ const pendingInterrupts = [];
522
589
  const toolCallStates = /* @__PURE__ */ new Map();
523
590
  const ensureToolCallState = (toolCallId) => {
524
591
  let state = toolCallStates.get(toolCallId);
@@ -660,11 +727,25 @@ This is state from the application that you can edit by calling AGUISendStateSna
660
727
  };
661
728
  subscriber.next(endEvent);
662
729
  }
730
+ if (state.toolName && interruptToolNames.has(state.toolName)) {
731
+ const meta = interruptToolMeta.get(state.toolName);
732
+ pendingInterrupts.push({
733
+ id: toolCallId,
734
+ toolCallId,
735
+ reason: meta?.reason ?? "tool_call",
736
+ ...meta?.message ? { message: meta.message } : {}
737
+ });
738
+ }
663
739
  break;
664
740
  }
665
741
  case "tool-result": {
666
- const toolResult = "output" in part ? part.output : "result" in part ? part.result : null;
667
- const toolName = "toolName" in part ? part.toolName : "";
742
+ const toolName = "toolName" in part && part.toolName || toolCallStates.get(part.toolCallId)?.toolName || "";
743
+ if (toolName && interruptToolNames.has(toolName)) {
744
+ toolCallStates.delete(part.toolCallId);
745
+ break;
746
+ }
747
+ const legacyPart = part;
748
+ const toolResult = "output" in part ? part.output : "result" in legacyPart ? legacyPart.result : null;
668
749
  toolCallStates.delete(part.toolCallId);
669
750
  if (toolName === "AGUISendStateSnapshot" && toolResult && typeof toolResult === "object") {
670
751
  const snapshot = toolResult.snapshot;
@@ -705,7 +786,11 @@ This is state from the application that you can edit by calling AGUISendStateSna
705
786
  const finishedEvent = {
706
787
  type: _ag_ui_client.EventType.RUN_FINISHED,
707
788
  threadId: input.threadId,
708
- runId: input.runId
789
+ runId: input.runId,
790
+ ...pendingInterrupts.length > 0 ? { outcome: {
791
+ type: "interrupt",
792
+ interrupts: pendingInterrupts
793
+ } } : {}
709
794
  };
710
795
  subscriber.next(finishedEvent);
711
796
  terminalEventEmitted = true;
@@ -714,7 +799,7 @@ This is state from the application that you can edit by calling AGUISendStateSna
714
799
  }
715
800
  case "error": {
716
801
  if (abortController.signal.aborted) break;
717
- const err = part.error ?? part.message ?? part.cause;
802
+ const err = part.error ?? ("message" in part ? part.message : void 0) ?? ("cause" in part ? part.cause : void 0);
718
803
  const runErrorEvent = {
719
804
  type: _ag_ui_client.EventType.RUN_ERROR,
720
805
  message: err instanceof Error ? err.message : typeof err === "string" ? err : `AI SDK stream error: ${JSON.stringify(part)}`,
@@ -735,7 +820,11 @@ This is state from the application that you can edit by calling AGUISendStateSna
735
820
  const finishedEvent = {
736
821
  type: _ag_ui_client.EventType.RUN_FINISHED,
737
822
  threadId: input.threadId,
738
- runId: input.runId
823
+ runId: input.runId,
824
+ ...pendingInterrupts.length > 0 ? { outcome: {
825
+ type: "interrupt",
826
+ interrupts: pendingInterrupts
827
+ } } : {}
739
828
  };
740
829
  subscriber.next(finishedEvent);
741
830
  }
@@ -780,17 +869,40 @@ This is state from the application that you can edit by calling AGUISendStateSna
780
869
  const ctx = {
781
870
  input,
782
871
  abortController: controller,
783
- abortSignal: controller.signal
872
+ abortSignal: controller.signal,
873
+ interrupt: async (interrupts) => {
874
+ const resume = input.resume ?? [];
875
+ const ids = new Set(interrupts.map((i) => i.id));
876
+ const matching = resume.filter((r) => ids.has(r.interruptId));
877
+ if (interrupts.length > 0 && matching.length === interrupts.length) return matching;
878
+ throw new InterruptSignal(interrupts);
879
+ }
880
+ };
881
+ const answeredToolCallIds = new Set(input.messages.filter((m) => m.role === "tool").map((m) => m.toolCallId).filter((id) => typeof id === "string"));
882
+ const resumeToolMessages = (input.resume ?? []).filter((entry) => !answeredToolCallIds.has(entry.interruptId)).map((entry) => ({
883
+ id: (0, _copilotkit_shared.randomUUID)(),
884
+ role: "tool",
885
+ toolCallId: entry.interruptId,
886
+ content: JSON.stringify(entry.status === "cancelled" ? { status: "cancelled" } : entry.payload ?? { status: "resolved" })
887
+ }));
888
+ const factoryInput = resumeToolMessages.length > 0 && config.type !== "custom" ? {
889
+ ...input,
890
+ messages: [...input.messages, ...resumeToolMessages]
891
+ } : input;
892
+ const factoryCtx = {
893
+ ...ctx,
894
+ input: factoryInput
784
895
  };
785
896
  (async () => {
786
897
  try {
787
898
  let events;
899
+ const pendingInterrupts = [];
788
900
  switch (config.type) {
789
901
  case "aisdk":
790
- events = require_aisdk.convertAISDKStream((await config.factory(ctx)).fullStream, controller.signal);
902
+ events = require_aisdk.convertAISDKStream((await config.factory(factoryCtx)).fullStream, controller.signal, pendingInterrupts);
791
903
  break;
792
904
  case "tanstack":
793
- events = require_tanstack.convertTanStackStream(await config.factory(ctx), controller.signal);
905
+ events = require_tanstack.convertTanStackStream(await config.factory(factoryCtx), controller.signal, pendingInterrupts);
794
906
  break;
795
907
  case "custom":
796
908
  events = await config.factory(ctx);
@@ -801,6 +913,7 @@ This is state from the application that you can edit by calling AGUISendStateSna
801
913
  }
802
914
  }
803
915
  for await (const event of events) subscriber.next(event);
916
+ if (pendingInterrupts.length > 0 && !controller.signal.aborted) throw new InterruptSignal(pendingInterrupts);
804
917
  if (!controller.signal.aborted) {
805
918
  const finishedEvent = {
806
919
  type: _ag_ui_client.EventType.RUN_FINISHED,
@@ -811,7 +924,19 @@ This is state from the application that you can edit by calling AGUISendStateSna
811
924
  }
812
925
  subscriber.complete();
813
926
  } catch (error) {
814
- if (controller.signal.aborted) subscriber.complete();
927
+ if (error instanceof InterruptSignal) {
928
+ const finishedEvent = {
929
+ type: _ag_ui_client.EventType.RUN_FINISHED,
930
+ threadId: input.threadId,
931
+ runId: input.runId,
932
+ outcome: {
933
+ type: "interrupt",
934
+ interrupts: error.interrupts
935
+ }
936
+ };
937
+ subscriber.next(finishedEvent);
938
+ subscriber.complete();
939
+ } else if (controller.signal.aborted) subscriber.complete();
815
940
  else {
816
941
  const runErrorEvent = {
817
942
  type: _ag_ui_client.EventType.RUN_ERROR,
@@ -853,6 +978,7 @@ var BasicAgent = class extends BuiltInAgent {
853
978
  //#endregion
854
979
  exports.BasicAgent = BasicAgent;
855
980
  exports.BuiltInAgent = BuiltInAgent;
981
+ exports.InterruptSignal = InterruptSignal;
856
982
  exports.convertJsonSchemaToZodSchema = convertJsonSchemaToZodSchema;
857
983
  exports.convertMessagesToVercelAISDKMessages = convertMessagesToVercelAISDKMessages;
858
984
  exports.convertToolDefinitionsToVercelAITools = convertToolDefinitionsToVercelAITools;