@copilotkit/react-core 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 (42) hide show
  1. package/dist/{copilotkit-BCxdKlMw.mjs → copilotkit-Be-o2UaU.mjs} +262 -128
  2. package/dist/copilotkit-Be-o2UaU.mjs.map +1 -0
  3. package/dist/{copilotkit-M1FiciGd.d.mts → copilotkit-Bpt1c_-q.d.mts} +79 -71
  4. package/dist/copilotkit-Bpt1c_-q.d.mts.map +1 -0
  5. package/dist/{copilotkit-DtPCrXXd.cjs → copilotkit-CTCjVxkH.cjs} +251 -117
  6. package/dist/copilotkit-CTCjVxkH.cjs.map +1 -0
  7. package/dist/{copilotkit-CEdu_aie.d.cts → copilotkit-ClqbUuGX.d.cts} +79 -71
  8. package/dist/copilotkit-ClqbUuGX.d.cts.map +1 -0
  9. package/dist/index.cjs +1 -1
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +1 -1
  12. package/dist/index.d.cts.map +1 -1
  13. package/dist/index.d.mts +1 -1
  14. package/dist/index.d.mts.map +1 -1
  15. package/dist/index.mjs +1 -1
  16. package/dist/index.mjs.map +1 -1
  17. package/dist/index.umd.js +188 -96
  18. package/dist/index.umd.js.map +1 -1
  19. package/dist/v2/context.d.cts +5 -1
  20. package/dist/v2/context.d.cts.map +1 -1
  21. package/dist/v2/context.d.mts +5 -1
  22. package/dist/v2/context.d.mts.map +1 -1
  23. package/dist/v2/headless.cjs +219 -102
  24. package/dist/v2/headless.cjs.map +1 -1
  25. package/dist/v2/headless.d.cts +76 -68
  26. package/dist/v2/headless.d.cts.map +1 -1
  27. package/dist/v2/headless.d.mts +76 -68
  28. package/dist/v2/headless.d.mts.map +1 -1
  29. package/dist/v2/headless.mjs +220 -103
  30. package/dist/v2/headless.mjs.map +1 -1
  31. package/dist/v2/index.cjs +1 -1
  32. package/dist/v2/index.d.cts +2 -2
  33. package/dist/v2/index.d.mts +2 -2
  34. package/dist/v2/index.mjs +1 -1
  35. package/dist/v2/index.umd.js +250 -116
  36. package/dist/v2/index.umd.js.map +1 -1
  37. package/package.json +6 -6
  38. package/skills/react-core/references/provider-setup.md +20 -2
  39. package/dist/copilotkit-BCxdKlMw.mjs.map +0 -1
  40. package/dist/copilotkit-CEdu_aie.d.cts.map +0 -1
  41. package/dist/copilotkit-DtPCrXXd.cjs.map +0 -1
  42. package/dist/copilotkit-M1FiciGd.d.mts.map +0 -1
package/dist/index.umd.js CHANGED
@@ -2280,6 +2280,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2280
2280
 
2281
2281
  //#endregion
2282
2282
  //#region src/v2/providers/CopilotKitProvider.tsx
2283
+ const zodToJsonSchemaAdapter = (schema, options) => {
2284
+ const refStrategy = options?.$refStrategy;
2285
+ return (0, zod_to_json_schema.zodToJsonSchema)(schema, refStrategy === "root" || refStrategy === "relative" || refStrategy === "none" || refStrategy === "seen" ? { $refStrategy: refStrategy } : {});
2286
+ };
2283
2287
  const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
2284
2288
  const COPILOT_CLOUD_CHAT_URL$1 = "https://api.cloud.copilotkit.ai/copilotkit/v1";
2285
2289
  const EMPTY_HEADERS = Object.freeze({});
@@ -2310,6 +2314,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2310
2314
  const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = (0, react.useState)(false);
2311
2315
  const [runtimeOpenGenUIEnabled, setRuntimeOpenGenUIEnabled] = (0, react.useState)(false);
2312
2316
  const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
2317
+ const a2uiCatalogProvided = !!a2ui?.catalog;
2318
+ const a2uiActive = runtimeA2UIEnabled || a2uiCatalogProvided;
2313
2319
  const [runtimeLicenseStatus, setRuntimeLicenseStatus] = (0, react.useState)(void 0);
2314
2320
  (0, react.useEffect)(() => {
2315
2321
  if (typeof window === "undefined") return;
@@ -2340,7 +2346,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2340
2346
  content: OpenGenerativeUIContentSchema,
2341
2347
  render: OpenGenerativeUIActivityRenderer
2342
2348
  });
2343
- if (runtimeA2UIEnabled) renderers.unshift(createA2UIMessageRenderer({
2349
+ if (a2uiActive) renderers.unshift(createA2UIMessageRenderer({
2344
2350
  theme: a2ui?.theme ?? _copilotkit_a2ui_renderer.viewerTheme,
2345
2351
  catalog: a2ui?.catalog,
2346
2352
  loadingComponent: a2ui?.loadingComponent,
@@ -2348,7 +2354,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2348
2354
  }));
2349
2355
  return renderers;
2350
2356
  }, [
2351
- runtimeA2UIEnabled,
2357
+ a2uiActive,
2352
2358
  openGenUIActive,
2353
2359
  a2ui
2354
2360
  ]);
@@ -2535,7 +2541,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2535
2541
  copilotkit.setRuntimeTransport(useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto");
2536
2542
  copilotkit.setHeaders(mergedHeaders);
2537
2543
  copilotkit.setCredentials(credentials);
2538
- copilotkit.setProperties(properties);
2544
+ copilotkit.setProperties(a2uiCatalogProvided ? {
2545
+ ...properties,
2546
+ a2uiCatalogAvailable: true
2547
+ } : properties);
2539
2548
  copilotkit.setAgents__unsafe_dev_only(mergedAgents);
2540
2549
  copilotkit.setDebug(debug);
2541
2550
  }, [
@@ -2544,6 +2553,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2544
2553
  mergedHeaders,
2545
2554
  credentials,
2546
2555
  properties,
2556
+ a2uiCatalogProvided,
2547
2557
  mergedAgents,
2548
2558
  useSingleEndpoint,
2549
2559
  debug
@@ -2591,7 +2601,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2591
2601
  return JSON.stringify(sandboxFunctionsList.map((fn) => ({
2592
2602
  name: fn.name,
2593
2603
  description: fn.description,
2594
- parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema })
2604
+ parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zodToJsonSchemaAdapter })
2595
2605
  })));
2596
2606
  }, [sandboxFunctionsList]);
2597
2607
  (0, react.useLayoutEffect)(() => {
@@ -2612,7 +2622,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2612
2622
  copilotkit,
2613
2623
  executingToolCallIds
2614
2624
  }), [copilotkit, executingToolCallIds]);
2615
- const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
2625
+ const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(runtimeLicenseStatus), [runtimeLicenseStatus]);
2616
2626
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
2617
2627
  value: sandboxFunctionsList,
2618
2628
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
@@ -2620,8 +2630,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2620
2630
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
2621
2631
  value: licenseContextValue,
2622
2632
  children: [
2623
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
2624
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
2633
+ a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
2634
+ a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
2625
2635
  catalog: a2ui?.catalog,
2626
2636
  includeSchema: a2ui?.includeSchema
2627
2637
  }),
@@ -2723,15 +2733,34 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2723
2733
  function useHumanInTheLoop$1(tool, deps) {
2724
2734
  const { copilotkit } = useCopilotKit();
2725
2735
  const resolvePromiseRef = (0, react.useRef)(null);
2736
+ const cleanupAbortRef = (0, react.useRef)(null);
2726
2737
  const respond = (0, react.useCallback)(async (result) => {
2727
2738
  if (resolvePromiseRef.current) {
2739
+ cleanupAbortRef.current?.();
2740
+ cleanupAbortRef.current = null;
2728
2741
  resolvePromiseRef.current(result);
2729
2742
  resolvePromiseRef.current = null;
2730
2743
  }
2731
2744
  }, []);
2732
- const handler = (0, react.useCallback)(async () => {
2733
- return new Promise((resolve) => {
2745
+ const handler = (0, react.useCallback)(async (_args, context) => {
2746
+ const signal = context?.signal;
2747
+ return new Promise((resolve, reject) => {
2748
+ if (signal?.aborted) {
2749
+ reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
2750
+ return;
2751
+ }
2734
2752
  resolvePromiseRef.current = resolve;
2753
+ if (signal) {
2754
+ const onAbort = () => {
2755
+ cleanupAbortRef.current = null;
2756
+ resolvePromiseRef.current = null;
2757
+ reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
2758
+ };
2759
+ signal.addEventListener("abort", onAbort, { once: true });
2760
+ cleanupAbortRef.current = () => {
2761
+ signal.removeEventListener("abort", onAbort);
2762
+ };
2763
+ }
2735
2764
  });
2736
2765
  }, []);
2737
2766
  const RenderComponent = (0, react.useCallback)((props) => {
@@ -2819,7 +2848,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2819
2848
  if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
2820
2849
  const cached = provisionalAgentCache.current.get(agentId);
2821
2850
  if (cached) {
2822
- cached.headers = { ...copilotkit.headers };
2851
+ copilotkit.applyHeadersToAgent(cached);
2823
2852
  return cached;
2824
2853
  }
2825
2854
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
@@ -2828,14 +2857,14 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2828
2857
  transport: copilotkit.runtimeTransport,
2829
2858
  runtimeMode: "pending"
2830
2859
  });
2831
- provisional.headers = { ...copilotkit.headers };
2860
+ copilotkit.applyHeadersToAgent(provisional);
2832
2861
  provisionalAgentCache.current.set(agentId, provisional);
2833
2862
  return provisional;
2834
2863
  }
2835
2864
  if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
2836
2865
  const cached = provisionalAgentCache.current.get(agentId);
2837
2866
  if (cached) {
2838
- cached.headers = { ...copilotkit.headers };
2867
+ copilotkit.applyHeadersToAgent(cached);
2839
2868
  return cached;
2840
2869
  }
2841
2870
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
@@ -2844,7 +2873,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2844
2873
  transport: copilotkit.runtimeTransport,
2845
2874
  runtimeMode: "pending"
2846
2875
  });
2847
- provisional.headers = { ...copilotkit.headers };
2876
+ copilotkit.applyHeadersToAgent(provisional);
2848
2877
  provisionalAgentCache.current.set(agentId, provisional);
2849
2878
  return provisional;
2850
2879
  }
@@ -2895,7 +2924,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2895
2924
  updateFlags
2896
2925
  ]);
2897
2926
  (0, react.useEffect)(() => {
2898
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
2927
+ if (agent instanceof _ag_ui_client.HttpAgent) copilotkit.applyHeadersToAgent(agent);
2899
2928
  }, [agent, JSON.stringify(copilotkit.headers)]);
2900
2929
  const chatConfig = useCopilotChatConfiguration();
2901
2930
  const configThreadId = chatConfig?.threadId;
@@ -3129,114 +3158,165 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3129
3158
  function isPromiseLike(value) {
3130
3159
  return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
3131
3160
  }
3161
+ /** Derive the legacy-compatible `event` for any pending interrupt. */
3162
+ function toLegacyEvent(pending) {
3163
+ if (pending.kind === "legacy") return pending.event;
3164
+ return {
3165
+ name: INTERRUPT_EVENT_NAME,
3166
+ value: pending.interrupts[0]
3167
+ };
3168
+ }
3132
3169
  /**
3133
- * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.
3134
- *
3135
- * The hook listens to custom events on the active agent, stores interrupt payloads per run,
3136
- * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
3137
- * execution with user-provided data.
3138
- *
3139
- * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
3140
- * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
3170
+ * Handles agent interrupts with optional filtering, preprocessing, and resume behavior.
3141
3171
  *
3142
- * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
3143
- * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
3172
+ * Supports both the AG-UI standard interrupt flow (`RUN_FINISHED` with
3173
+ * `outcome.type === "interrupt"`) and the legacy custom-event flow
3174
+ * (`on_interrupt`). For standard interrupts, `render` receives `interrupt`
3175
+ * (the primary one) and `interrupts` (the full open set); call `resolve(payload)`
3176
+ * to resume or `cancel()` to cancel. Resuming addresses the targeted interrupt
3177
+ * and, once every open interrupt is addressed, submits a single spec `resume`
3178
+ * array via `copilotkit.runAgent`.
3144
3179
  *
3145
- * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
3146
- * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
3147
- * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
3148
- * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
3149
- * either the handler's resolved return value or `null` (including when no handler is provided,
3150
- * when filtering skips the interrupt, or when handler execution fails).
3180
+ * - `renderInChat: true` (default): the element is published into `<CopilotChat>`; returns `void`.
3181
+ * - `renderInChat: false`: the hook returns the interrupt element for manual placement.
3151
3182
  *
3152
3183
  * @example
3153
3184
  * ```tsx
3154
- * import { useInterrupt } from "@copilotkit/react-core/v2";
3155
- *
3156
- * function InterruptUI() {
3157
- * useInterrupt({
3158
- * render: ({ event, resolve }) => (
3159
- * <div>
3160
- * <p>{event.value.question}</p>
3161
- * <button onClick={() => resolve({ approved: true })}>Approve</button>
3162
- * <button onClick={() => resolve({ approved: false })}>Reject</button>
3163
- * </div>
3164
- * ),
3165
- * });
3166
- *
3167
- * return null;
3168
- * }
3169
- * ```
3170
- *
3171
- * @example
3172
- * ```tsx
3173
- * import { useInterrupt } from "@copilotkit/react-core/v2";
3174
- *
3175
- * function CustomPanel() {
3176
- * const interruptElement = useInterrupt({
3177
- * renderInChat: false,
3178
- * enabled: (event) => event.value.startsWith("approval:"),
3179
- * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
3180
- * render: ({ event, result, resolve }) => (
3181
- * <aside>
3182
- * <strong>{result?.label ?? ""}</strong>
3183
- * <button onClick={() => resolve({ value: event.value })}>Continue</button>
3184
- * </aside>
3185
- * ),
3186
- * });
3187
- *
3188
- * return <>{interruptElement}</>;
3189
- * }
3185
+ * useInterrupt({
3186
+ * render: ({ interrupt, resolve, cancel }) => (
3187
+ * <div>
3188
+ * <p>{interrupt?.message}</p>
3189
+ * <button onClick={() => resolve({ approved: true })}>Approve</button>
3190
+ * <button onClick={() => cancel()}>Cancel</button>
3191
+ * </div>
3192
+ * ),
3193
+ * });
3190
3194
  * ```
3191
3195
  */
3192
3196
  function useInterrupt(config) {
3193
3197
  const { copilotkit } = useCopilotKit();
3194
3198
  const { agent } = useAgent({ agentId: config.agentId });
3195
- const [pendingEvent, setPendingEvent] = (0, react.useState)(null);
3196
- const pendingEventRef = (0, react.useRef)(pendingEvent);
3197
- pendingEventRef.current = pendingEvent;
3199
+ const [pending, setPending] = (0, react.useState)(null);
3200
+ const pendingRef = (0, react.useRef)(pending);
3201
+ pendingRef.current = pending;
3198
3202
  const [handlerResult, setHandlerResult] = (0, react.useState)(null);
3203
+ const responsesRef = (0, react.useRef)({});
3199
3204
  (0, react.useEffect)(() => {
3200
- let localInterrupt = null;
3205
+ let localLegacy = null;
3206
+ let localStandard = null;
3201
3207
  const subscription = agent.subscribe({
3202
3208
  onCustomEvent: ({ event }) => {
3203
- if (event.name === INTERRUPT_EVENT_NAME) localInterrupt = {
3209
+ if (event.name === INTERRUPT_EVENT_NAME) localLegacy = {
3204
3210
  name: event.name,
3205
3211
  value: event.value
3206
3212
  };
3207
3213
  },
3214
+ onRunFinishedEvent: (params) => {
3215
+ if (params.outcome === "interrupt") localStandard = params.interrupts;
3216
+ },
3208
3217
  onRunStartedEvent: () => {
3209
- localInterrupt = null;
3210
- setPendingEvent(null);
3218
+ localLegacy = null;
3219
+ localStandard = null;
3220
+ responsesRef.current = {};
3221
+ setPending(null);
3211
3222
  },
3212
3223
  onRunFinalized: () => {
3213
- if (localInterrupt) {
3214
- setPendingEvent(localInterrupt);
3215
- localInterrupt = null;
3216
- }
3224
+ if (localStandard && localStandard.length > 0) setPending({
3225
+ kind: "standard",
3226
+ interrupts: localStandard
3227
+ });
3228
+ else if (localLegacy) setPending({
3229
+ kind: "legacy",
3230
+ event: localLegacy
3231
+ });
3232
+ localLegacy = null;
3233
+ localStandard = null;
3217
3234
  },
3218
3235
  onRunFailed: () => {
3219
- localInterrupt = null;
3220
- setPendingEvent(null);
3236
+ localLegacy = null;
3237
+ localStandard = null;
3238
+ responsesRef.current = {};
3239
+ setPending(null);
3221
3240
  }
3222
3241
  });
3223
3242
  return () => subscription.unsubscribe();
3224
3243
  }, [agent]);
3225
- const resolve = (0, react.useCallback)(async (response) => {
3244
+ const submitStandardIfComplete = (0, react.useCallback)(async (interrupts) => {
3245
+ if (!interrupts.every((i) => responsesRef.current[i.id])) return;
3246
+ const expired = interrupts.find((i) => (0, _ag_ui_client.isInterruptExpired)(i));
3247
+ if (expired) {
3248
+ console.error(`[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`);
3249
+ responsesRef.current = {};
3250
+ setPending(null);
3251
+ return;
3252
+ }
3253
+ const resume = (0, _ag_ui_client.buildResumeArray)(interrupts, responsesRef.current);
3254
+ for (const i of interrupts) {
3255
+ if (!i.toolCallId) continue;
3256
+ const response = responsesRef.current[i.id];
3257
+ const content = response.status === "cancelled" ? { status: "cancelled" } : response.payload ?? { status: "resolved" };
3258
+ agent.addMessage({
3259
+ id: (0, _ag_ui_client.randomUUID)(),
3260
+ role: "tool",
3261
+ toolCallId: i.toolCallId,
3262
+ content: JSON.stringify(content)
3263
+ });
3264
+ }
3265
+ responsesRef.current = {};
3226
3266
  try {
3267
+ return await copilotkit.runAgent({
3268
+ agent,
3269
+ resume
3270
+ });
3271
+ } catch (err) {
3272
+ console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
3273
+ setPending(null);
3274
+ throw err;
3275
+ }
3276
+ }, [agent, copilotkit]);
3277
+ const resolve = (0, react.useCallback)(async (payload, interruptId) => {
3278
+ const current = pendingRef.current;
3279
+ if (!current) return;
3280
+ if (current.kind === "legacy") try {
3227
3281
  return await copilotkit.runAgent({
3228
3282
  agent,
3229
3283
  forwardedProps: { command: {
3230
- resume: response,
3231
- interruptEvent: pendingEventRef.current?.value
3284
+ resume: payload,
3285
+ interruptEvent: current.event.value
3232
3286
  } }
3233
3287
  });
3234
3288
  } catch (err) {
3235
3289
  console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
3236
- setPendingEvent(null);
3290
+ setPending(null);
3237
3291
  throw err;
3238
3292
  }
3239
- }, [agent, copilotkit]);
3293
+ if (current.interrupts.length > 1 && interruptId === void 0) console.warn(`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`);
3294
+ const id = interruptId ?? current.interrupts[0]?.id;
3295
+ if (!id) return;
3296
+ responsesRef.current[id] = {
3297
+ status: "resolved",
3298
+ payload
3299
+ };
3300
+ return submitStandardIfComplete(current.interrupts);
3301
+ }, [
3302
+ agent,
3303
+ copilotkit,
3304
+ submitStandardIfComplete
3305
+ ]);
3306
+ const cancel = (0, react.useCallback)(async (interruptId) => {
3307
+ const current = pendingRef.current;
3308
+ if (!current) return;
3309
+ if (current.kind === "legacy") {
3310
+ console.warn("[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.");
3311
+ setPending(null);
3312
+ return;
3313
+ }
3314
+ if (current.interrupts.length > 1 && interruptId === void 0) console.warn(`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`);
3315
+ const id = interruptId ?? current.interrupts[0]?.id;
3316
+ if (!id) return;
3317
+ responsesRef.current[id] = { status: "cancelled" };
3318
+ return submitStandardIfComplete(current.interrupts);
3319
+ }, [submitStandardIfComplete]);
3240
3320
  const renderRef = (0, react.useRef)(config.render);
3241
3321
  renderRef.current = config.render;
3242
3322
  const enabledRef = (0, react.useRef)(config.enabled);
@@ -3245,6 +3325,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3245
3325
  handlerRef.current = config.handler;
3246
3326
  const resolveRef = (0, react.useRef)(resolve);
3247
3327
  resolveRef.current = resolve;
3328
+ const cancelRef = (0, react.useRef)(cancel);
3329
+ cancelRef.current = cancel;
3248
3330
  const isEnabled = (event) => {
3249
3331
  const predicate = enabledRef.current;
3250
3332
  if (!predicate) return true;
@@ -3256,11 +3338,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3256
3338
  }
3257
3339
  };
3258
3340
  (0, react.useEffect)(() => {
3259
- if (!pendingEvent) {
3341
+ if (!pending) {
3260
3342
  setHandlerResult(null);
3261
3343
  return;
3262
3344
  }
3263
- if (!isEnabled(pendingEvent)) {
3345
+ const legacyEvent = toLegacyEvent(pending);
3346
+ if (!isEnabled(legacyEvent)) {
3264
3347
  setHandlerResult(null);
3265
3348
  return;
3266
3349
  }
@@ -3273,8 +3356,11 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3273
3356
  let maybePromise;
3274
3357
  try {
3275
3358
  maybePromise = handler({
3276
- event: pendingEvent,
3277
- resolve: resolveRef.current
3359
+ event: legacyEvent,
3360
+ interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
3361
+ interrupts: pending.kind === "standard" ? pending.interrupts : [],
3362
+ resolve: resolveRef.current,
3363
+ cancel: cancelRef.current
3278
3364
  });
3279
3365
  } catch (err) {
3280
3366
  console.error("[CopilotKit] useInterrupt handler threw; result will be null:", err);
@@ -3293,19 +3379,24 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3293
3379
  return () => {
3294
3380
  cancelled = true;
3295
3381
  };
3296
- }, [pendingEvent]);
3382
+ }, [pending]);
3297
3383
  const element = (0, react.useMemo)(() => {
3298
- if (!pendingEvent) return null;
3299
- if (!isEnabled(pendingEvent)) return null;
3384
+ if (!pending) return null;
3385
+ const legacyEvent = toLegacyEvent(pending);
3386
+ if (!isEnabled(legacyEvent)) return null;
3300
3387
  return renderRef.current({
3301
- event: pendingEvent,
3388
+ event: legacyEvent,
3389
+ interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
3390
+ interrupts: pending.kind === "standard" ? pending.interrupts : [],
3302
3391
  result: handlerResult,
3303
- resolve
3392
+ resolve,
3393
+ cancel
3304
3394
  });
3305
3395
  }, [
3306
- pendingEvent,
3396
+ pending,
3307
3397
  handlerResult,
3308
- resolve
3398
+ resolve,
3399
+ cancel
3309
3400
  ]);
3310
3401
  (0, react.useEffect)(() => {
3311
3402
  if (config.renderInChat === false) return;
@@ -4963,6 +5054,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4963
5054
  const showInspector = shouldShowDevConsole(props.enableInspector);
4964
5055
  const publicApiKey = props.publicApiKey || props.publicLicenseKey;
4965
5056
  const renderArr = (0, react.useMemo)(() => [{ render: CoAgentStateRenderBridge }], []);
5057
+ const { onError: _onError, ...v2Props } = props;
4966
5058
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToastProvider, {
4967
5059
  enabled,
4968
5060
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotErrorBoundary, {
@@ -4971,7 +5063,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4971
5063
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadsProvider, {
4972
5064
  threadId: props.threadId,
4973
5065
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitProvider, {
4974
- ...props,
5066
+ ...v2Props,
4975
5067
  showDevConsole: showInspector,
4976
5068
  renderCustomMessages: renderArr,
4977
5069
  useSingleEndpoint: props.useSingleEndpoint ?? true,