@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
@@ -1520,10 +1520,20 @@ function useRenderTool(config, deps) {
1520
1520
  }) : defineToolCallRenderer({
1521
1521
  name: config.name,
1522
1522
  args: config.parameters,
1523
- render: (props) => config.render({
1524
- ...props,
1525
- parameters: props.args
1526
- }),
1523
+ render: (props) => {
1524
+ if (props.status === _copilotkit_core.ToolCallStatus.InProgress) return config.render({
1525
+ ...props,
1526
+ parameters: props.args
1527
+ });
1528
+ if (props.status === _copilotkit_core.ToolCallStatus.Executing) return config.render({
1529
+ ...props,
1530
+ parameters: props.args
1531
+ });
1532
+ return config.render({
1533
+ ...props,
1534
+ parameters: props.args
1535
+ });
1536
+ },
1527
1537
  ...config.agentId ? { agentId: config.agentId } : {}
1528
1538
  });
1529
1539
  copilotkit.addHookRenderToolCall(renderer);
@@ -3561,6 +3571,10 @@ function A2UICatalogContext({ catalog, includeSchema }) {
3561
3571
 
3562
3572
  //#endregion
3563
3573
  //#region src/v2/providers/CopilotKitProvider.tsx
3574
+ const zodToJsonSchemaAdapter = (schema, options) => {
3575
+ const refStrategy = options?.$refStrategy;
3576
+ return (0, zod_to_json_schema.zodToJsonSchema)(schema, refStrategy === "root" || refStrategy === "relative" || refStrategy === "none" || refStrategy === "seen" ? { $refStrategy: refStrategy } : {});
3577
+ };
3564
3578
  const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
3565
3579
  const COPILOT_CLOUD_CHAT_URL$1 = "https://api.cloud.copilotkit.ai/copilotkit/v1";
3566
3580
  const EMPTY_HEADERS = Object.freeze({});
@@ -3591,6 +3605,8 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3591
3605
  const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = (0, react.useState)(false);
3592
3606
  const [runtimeOpenGenUIEnabled, setRuntimeOpenGenUIEnabled] = (0, react.useState)(false);
3593
3607
  const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
3608
+ const a2uiCatalogProvided = !!a2ui?.catalog;
3609
+ const a2uiActive = runtimeA2UIEnabled || a2uiCatalogProvided;
3594
3610
  const [runtimeLicenseStatus, setRuntimeLicenseStatus] = (0, react.useState)(void 0);
3595
3611
  (0, react.useEffect)(() => {
3596
3612
  if (typeof window === "undefined") return;
@@ -3621,7 +3637,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3621
3637
  content: OpenGenerativeUIContentSchema,
3622
3638
  render: OpenGenerativeUIActivityRenderer
3623
3639
  });
3624
- if (runtimeA2UIEnabled) renderers.unshift(createA2UIMessageRenderer({
3640
+ if (a2uiActive) renderers.unshift(createA2UIMessageRenderer({
3625
3641
  theme: a2ui?.theme ?? _copilotkit_a2ui_renderer.viewerTheme,
3626
3642
  catalog: a2ui?.catalog,
3627
3643
  loadingComponent: a2ui?.loadingComponent,
@@ -3629,7 +3645,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3629
3645
  }));
3630
3646
  return renderers;
3631
3647
  }, [
3632
- runtimeA2UIEnabled,
3648
+ a2uiActive,
3633
3649
  openGenUIActive,
3634
3650
  a2ui
3635
3651
  ]);
@@ -3816,7 +3832,10 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3816
3832
  copilotkit.setRuntimeTransport(useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto");
3817
3833
  copilotkit.setHeaders(mergedHeaders);
3818
3834
  copilotkit.setCredentials(credentials);
3819
- copilotkit.setProperties(properties);
3835
+ copilotkit.setProperties(a2uiCatalogProvided ? {
3836
+ ...properties,
3837
+ a2uiCatalogAvailable: true
3838
+ } : properties);
3820
3839
  copilotkit.setAgents__unsafe_dev_only(mergedAgents);
3821
3840
  copilotkit.setDebug(debug);
3822
3841
  }, [
@@ -3825,6 +3844,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3825
3844
  mergedHeaders,
3826
3845
  credentials,
3827
3846
  properties,
3847
+ a2uiCatalogProvided,
3828
3848
  mergedAgents,
3829
3849
  useSingleEndpoint,
3830
3850
  debug
@@ -3872,7 +3892,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3872
3892
  return JSON.stringify(sandboxFunctionsList.map((fn) => ({
3873
3893
  name: fn.name,
3874
3894
  description: fn.description,
3875
- parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema })
3895
+ parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zodToJsonSchemaAdapter })
3876
3896
  })));
3877
3897
  }, [sandboxFunctionsList]);
3878
3898
  (0, react.useLayoutEffect)(() => {
@@ -3893,7 +3913,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3893
3913
  copilotkit,
3894
3914
  executingToolCallIds
3895
3915
  }), [copilotkit, executingToolCallIds]);
3896
- const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
3916
+ const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(runtimeLicenseStatus), [runtimeLicenseStatus]);
3897
3917
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
3898
3918
  value: sandboxFunctionsList,
3899
3919
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
@@ -3901,8 +3921,8 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3901
3921
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
3902
3922
  value: licenseContextValue,
3903
3923
  children: [
3904
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
3905
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
3924
+ a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
3925
+ a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
3906
3926
  catalog: a2ui?.catalog,
3907
3927
  includeSchema: a2ui?.includeSchema
3908
3928
  }),
@@ -3980,16 +4000,20 @@ function useRenderActivityMessage() {
3980
4000
  const renderActivityMessage = (0, react.useCallback)((message) => {
3981
4001
  const renderer = findRenderer(message.activityType);
3982
4002
  if (!renderer) return null;
3983
- const parseResult = renderer.content.safeParse(message.content);
3984
- if (!parseResult.success) {
3985
- console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.error);
4003
+ const parseResult = renderer.content["~standard"].validate(message.content);
4004
+ if (parseResult instanceof Promise) {
4005
+ console.warn(`Async content validation is not supported for activity message '${message.activityType}'`);
4006
+ return null;
4007
+ }
4008
+ if (parseResult.issues) {
4009
+ console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.issues);
3986
4010
  return null;
3987
4011
  }
3988
4012
  const Component = renderer.render;
3989
4013
  const agent = copilotkit.getAgent(agentId);
3990
4014
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3991
4015
  activityType: message.activityType,
3992
- content: parseResult.data,
4016
+ content: parseResult.value,
3993
4017
  message,
3994
4018
  agent
3995
4019
  }, message.id);
@@ -4110,15 +4134,34 @@ function useComponent(config, deps) {
4110
4134
  function useHumanInTheLoop(tool, deps) {
4111
4135
  const { copilotkit } = useCopilotKit();
4112
4136
  const resolvePromiseRef = (0, react.useRef)(null);
4137
+ const cleanupAbortRef = (0, react.useRef)(null);
4113
4138
  const respond = (0, react.useCallback)(async (result) => {
4114
4139
  if (resolvePromiseRef.current) {
4140
+ cleanupAbortRef.current?.();
4141
+ cleanupAbortRef.current = null;
4115
4142
  resolvePromiseRef.current(result);
4116
4143
  resolvePromiseRef.current = null;
4117
4144
  }
4118
4145
  }, []);
4119
- const handler = (0, react.useCallback)(async () => {
4120
- return new Promise((resolve) => {
4146
+ const handler = (0, react.useCallback)(async (_args, context) => {
4147
+ const signal = context?.signal;
4148
+ return new Promise((resolve, reject) => {
4149
+ if (signal?.aborted) {
4150
+ reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
4151
+ return;
4152
+ }
4121
4153
  resolvePromiseRef.current = resolve;
4154
+ if (signal) {
4155
+ const onAbort = () => {
4156
+ cleanupAbortRef.current = null;
4157
+ resolvePromiseRef.current = null;
4158
+ reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
4159
+ };
4160
+ signal.addEventListener("abort", onAbort, { once: true });
4161
+ cleanupAbortRef.current = () => {
4162
+ signal.removeEventListener("abort", onAbort);
4163
+ };
4164
+ }
4122
4165
  });
4123
4166
  }, []);
4124
4167
  const RenderComponent = (0, react.useCallback)((props) => {
@@ -4206,7 +4249,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4206
4249
  if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4207
4250
  const cached = provisionalAgentCache.current.get(agentId);
4208
4251
  if (cached) {
4209
- cached.headers = { ...copilotkit.headers };
4252
+ copilotkit.applyHeadersToAgent(cached);
4210
4253
  return cached;
4211
4254
  }
4212
4255
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
@@ -4215,14 +4258,14 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4215
4258
  transport: copilotkit.runtimeTransport,
4216
4259
  runtimeMode: "pending"
4217
4260
  });
4218
- provisional.headers = { ...copilotkit.headers };
4261
+ copilotkit.applyHeadersToAgent(provisional);
4219
4262
  provisionalAgentCache.current.set(agentId, provisional);
4220
4263
  return provisional;
4221
4264
  }
4222
4265
  if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
4223
4266
  const cached = provisionalAgentCache.current.get(agentId);
4224
4267
  if (cached) {
4225
- cached.headers = { ...copilotkit.headers };
4268
+ copilotkit.applyHeadersToAgent(cached);
4226
4269
  return cached;
4227
4270
  }
4228
4271
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
@@ -4231,7 +4274,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4231
4274
  transport: copilotkit.runtimeTransport,
4232
4275
  runtimeMode: "pending"
4233
4276
  });
4234
- provisional.headers = { ...copilotkit.headers };
4277
+ copilotkit.applyHeadersToAgent(provisional);
4235
4278
  provisionalAgentCache.current.set(agentId, provisional);
4236
4279
  return provisional;
4237
4280
  }
@@ -4282,7 +4325,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4282
4325
  updateFlags
4283
4326
  ]);
4284
4327
  (0, react.useEffect)(() => {
4285
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
4328
+ if (agent instanceof _ag_ui_client.HttpAgent) copilotkit.applyHeadersToAgent(agent);
4286
4329
  }, [agent, JSON.stringify(copilotkit.headers)]);
4287
4330
  const chatConfig = useCopilotChatConfiguration();
4288
4331
  const configThreadId = chatConfig?.threadId;
@@ -4559,114 +4602,165 @@ const INTERRUPT_EVENT_NAME = "on_interrupt";
4559
4602
  function isPromiseLike(value) {
4560
4603
  return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
4561
4604
  }
4605
+ /** Derive the legacy-compatible `event` for any pending interrupt. */
4606
+ function toLegacyEvent(pending) {
4607
+ if (pending.kind === "legacy") return pending.event;
4608
+ return {
4609
+ name: INTERRUPT_EVENT_NAME,
4610
+ value: pending.interrupts[0]
4611
+ };
4612
+ }
4562
4613
  /**
4563
- * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.
4614
+ * Handles agent interrupts with optional filtering, preprocessing, and resume behavior.
4564
4615
  *
4565
- * The hook listens to custom events on the active agent, stores interrupt payloads per run,
4566
- * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
4567
- * execution with user-provided data.
4616
+ * Supports both the AG-UI standard interrupt flow (`RUN_FINISHED` with
4617
+ * `outcome.type === "interrupt"`) and the legacy custom-event flow
4618
+ * (`on_interrupt`). For standard interrupts, `render` receives `interrupt`
4619
+ * (the primary one) and `interrupts` (the full open set); call `resolve(payload)`
4620
+ * to resume or `cancel()` to cancel. Resuming addresses the targeted interrupt
4621
+ * and, once every open interrupt is addressed, submits a single spec `resume`
4622
+ * array via `copilotkit.runAgent`.
4568
4623
  *
4569
- * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
4570
- * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
4571
- *
4572
- * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
4573
- * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
4574
- *
4575
- * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
4576
- * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
4577
- * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
4578
- * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
4579
- * either the handler's resolved return value or `null` (including when no handler is provided,
4580
- * when filtering skips the interrupt, or when handler execution fails).
4624
+ * - `renderInChat: true` (default): the element is published into `<CopilotChat>`; returns `void`.
4625
+ * - `renderInChat: false`: the hook returns the interrupt element for manual placement.
4581
4626
  *
4582
4627
  * @example
4583
4628
  * ```tsx
4584
- * import { useInterrupt } from "@copilotkit/react-core/v2";
4585
- *
4586
- * function InterruptUI() {
4587
- * useInterrupt({
4588
- * render: ({ event, resolve }) => (
4589
- * <div>
4590
- * <p>{event.value.question}</p>
4591
- * <button onClick={() => resolve({ approved: true })}>Approve</button>
4592
- * <button onClick={() => resolve({ approved: false })}>Reject</button>
4593
- * </div>
4594
- * ),
4595
- * });
4596
- *
4597
- * return null;
4598
- * }
4599
- * ```
4600
- *
4601
- * @example
4602
- * ```tsx
4603
- * import { useInterrupt } from "@copilotkit/react-core/v2";
4604
- *
4605
- * function CustomPanel() {
4606
- * const interruptElement = useInterrupt({
4607
- * renderInChat: false,
4608
- * enabled: (event) => event.value.startsWith("approval:"),
4609
- * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
4610
- * render: ({ event, result, resolve }) => (
4611
- * <aside>
4612
- * <strong>{result?.label ?? ""}</strong>
4613
- * <button onClick={() => resolve({ value: event.value })}>Continue</button>
4614
- * </aside>
4615
- * ),
4616
- * });
4617
- *
4618
- * return <>{interruptElement}</>;
4619
- * }
4629
+ * useInterrupt({
4630
+ * render: ({ interrupt, resolve, cancel }) => (
4631
+ * <div>
4632
+ * <p>{interrupt?.message}</p>
4633
+ * <button onClick={() => resolve({ approved: true })}>Approve</button>
4634
+ * <button onClick={() => cancel()}>Cancel</button>
4635
+ * </div>
4636
+ * ),
4637
+ * });
4620
4638
  * ```
4621
4639
  */
4622
4640
  function useInterrupt(config) {
4623
4641
  const { copilotkit } = useCopilotKit();
4624
4642
  const { agent } = useAgent({ agentId: config.agentId });
4625
- const [pendingEvent, setPendingEvent] = (0, react.useState)(null);
4626
- const pendingEventRef = (0, react.useRef)(pendingEvent);
4627
- pendingEventRef.current = pendingEvent;
4643
+ const [pending, setPending] = (0, react.useState)(null);
4644
+ const pendingRef = (0, react.useRef)(pending);
4645
+ pendingRef.current = pending;
4628
4646
  const [handlerResult, setHandlerResult] = (0, react.useState)(null);
4647
+ const responsesRef = (0, react.useRef)({});
4629
4648
  (0, react.useEffect)(() => {
4630
- let localInterrupt = null;
4649
+ let localLegacy = null;
4650
+ let localStandard = null;
4631
4651
  const subscription = agent.subscribe({
4632
4652
  onCustomEvent: ({ event }) => {
4633
- if (event.name === INTERRUPT_EVENT_NAME) localInterrupt = {
4653
+ if (event.name === INTERRUPT_EVENT_NAME) localLegacy = {
4634
4654
  name: event.name,
4635
4655
  value: event.value
4636
4656
  };
4637
4657
  },
4658
+ onRunFinishedEvent: (params) => {
4659
+ if (params.outcome === "interrupt") localStandard = params.interrupts;
4660
+ },
4638
4661
  onRunStartedEvent: () => {
4639
- localInterrupt = null;
4640
- setPendingEvent(null);
4662
+ localLegacy = null;
4663
+ localStandard = null;
4664
+ responsesRef.current = {};
4665
+ setPending(null);
4641
4666
  },
4642
4667
  onRunFinalized: () => {
4643
- if (localInterrupt) {
4644
- setPendingEvent(localInterrupt);
4645
- localInterrupt = null;
4646
- }
4668
+ if (localStandard && localStandard.length > 0) setPending({
4669
+ kind: "standard",
4670
+ interrupts: localStandard
4671
+ });
4672
+ else if (localLegacy) setPending({
4673
+ kind: "legacy",
4674
+ event: localLegacy
4675
+ });
4676
+ localLegacy = null;
4677
+ localStandard = null;
4647
4678
  },
4648
4679
  onRunFailed: () => {
4649
- localInterrupt = null;
4650
- setPendingEvent(null);
4680
+ localLegacy = null;
4681
+ localStandard = null;
4682
+ responsesRef.current = {};
4683
+ setPending(null);
4651
4684
  }
4652
4685
  });
4653
4686
  return () => subscription.unsubscribe();
4654
4687
  }, [agent]);
4655
- const resolve = (0, react.useCallback)(async (response) => {
4688
+ const submitStandardIfComplete = (0, react.useCallback)(async (interrupts) => {
4689
+ if (!interrupts.every((i) => responsesRef.current[i.id])) return;
4690
+ const expired = interrupts.find((i) => (0, _ag_ui_client.isInterruptExpired)(i));
4691
+ if (expired) {
4692
+ console.error(`[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`);
4693
+ responsesRef.current = {};
4694
+ setPending(null);
4695
+ return;
4696
+ }
4697
+ const resume = (0, _ag_ui_client.buildResumeArray)(interrupts, responsesRef.current);
4698
+ for (const i of interrupts) {
4699
+ if (!i.toolCallId) continue;
4700
+ const response = responsesRef.current[i.id];
4701
+ const content = response.status === "cancelled" ? { status: "cancelled" } : response.payload ?? { status: "resolved" };
4702
+ agent.addMessage({
4703
+ id: (0, _ag_ui_client.randomUUID)(),
4704
+ role: "tool",
4705
+ toolCallId: i.toolCallId,
4706
+ content: JSON.stringify(content)
4707
+ });
4708
+ }
4709
+ responsesRef.current = {};
4656
4710
  try {
4711
+ return await copilotkit.runAgent({
4712
+ agent,
4713
+ resume
4714
+ });
4715
+ } catch (err) {
4716
+ console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
4717
+ setPending(null);
4718
+ throw err;
4719
+ }
4720
+ }, [agent, copilotkit]);
4721
+ const resolve = (0, react.useCallback)(async (payload, interruptId) => {
4722
+ const current = pendingRef.current;
4723
+ if (!current) return;
4724
+ if (current.kind === "legacy") try {
4657
4725
  return await copilotkit.runAgent({
4658
4726
  agent,
4659
4727
  forwardedProps: { command: {
4660
- resume: response,
4661
- interruptEvent: pendingEventRef.current?.value
4728
+ resume: payload,
4729
+ interruptEvent: current.event.value
4662
4730
  } }
4663
4731
  });
4664
4732
  } catch (err) {
4665
4733
  console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
4666
- setPendingEvent(null);
4734
+ setPending(null);
4667
4735
  throw err;
4668
4736
  }
4669
- }, [agent, copilotkit]);
4737
+ 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.`);
4738
+ const id = interruptId ?? current.interrupts[0]?.id;
4739
+ if (!id) return;
4740
+ responsesRef.current[id] = {
4741
+ status: "resolved",
4742
+ payload
4743
+ };
4744
+ return submitStandardIfComplete(current.interrupts);
4745
+ }, [
4746
+ agent,
4747
+ copilotkit,
4748
+ submitStandardIfComplete
4749
+ ]);
4750
+ const cancel = (0, react.useCallback)(async (interruptId) => {
4751
+ const current = pendingRef.current;
4752
+ if (!current) return;
4753
+ if (current.kind === "legacy") {
4754
+ console.warn("[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.");
4755
+ setPending(null);
4756
+ return;
4757
+ }
4758
+ 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.`);
4759
+ const id = interruptId ?? current.interrupts[0]?.id;
4760
+ if (!id) return;
4761
+ responsesRef.current[id] = { status: "cancelled" };
4762
+ return submitStandardIfComplete(current.interrupts);
4763
+ }, [submitStandardIfComplete]);
4670
4764
  const renderRef = (0, react.useRef)(config.render);
4671
4765
  renderRef.current = config.render;
4672
4766
  const enabledRef = (0, react.useRef)(config.enabled);
@@ -4675,6 +4769,8 @@ function useInterrupt(config) {
4675
4769
  handlerRef.current = config.handler;
4676
4770
  const resolveRef = (0, react.useRef)(resolve);
4677
4771
  resolveRef.current = resolve;
4772
+ const cancelRef = (0, react.useRef)(cancel);
4773
+ cancelRef.current = cancel;
4678
4774
  const isEnabled = (event) => {
4679
4775
  const predicate = enabledRef.current;
4680
4776
  if (!predicate) return true;
@@ -4686,11 +4782,12 @@ function useInterrupt(config) {
4686
4782
  }
4687
4783
  };
4688
4784
  (0, react.useEffect)(() => {
4689
- if (!pendingEvent) {
4785
+ if (!pending) {
4690
4786
  setHandlerResult(null);
4691
4787
  return;
4692
4788
  }
4693
- if (!isEnabled(pendingEvent)) {
4789
+ const legacyEvent = toLegacyEvent(pending);
4790
+ if (!isEnabled(legacyEvent)) {
4694
4791
  setHandlerResult(null);
4695
4792
  return;
4696
4793
  }
@@ -4703,8 +4800,11 @@ function useInterrupt(config) {
4703
4800
  let maybePromise;
4704
4801
  try {
4705
4802
  maybePromise = handler({
4706
- event: pendingEvent,
4707
- resolve: resolveRef.current
4803
+ event: legacyEvent,
4804
+ interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
4805
+ interrupts: pending.kind === "standard" ? pending.interrupts : [],
4806
+ resolve: resolveRef.current,
4807
+ cancel: cancelRef.current
4708
4808
  });
4709
4809
  } catch (err) {
4710
4810
  console.error("[CopilotKit] useInterrupt handler threw; result will be null:", err);
@@ -4723,19 +4823,24 @@ function useInterrupt(config) {
4723
4823
  return () => {
4724
4824
  cancelled = true;
4725
4825
  };
4726
- }, [pendingEvent]);
4826
+ }, [pending]);
4727
4827
  const element = (0, react.useMemo)(() => {
4728
- if (!pendingEvent) return null;
4729
- if (!isEnabled(pendingEvent)) return null;
4828
+ if (!pending) return null;
4829
+ const legacyEvent = toLegacyEvent(pending);
4830
+ if (!isEnabled(legacyEvent)) return null;
4730
4831
  return renderRef.current({
4731
- event: pendingEvent,
4832
+ event: legacyEvent,
4833
+ interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
4834
+ interrupts: pending.kind === "standard" ? pending.interrupts : [],
4732
4835
  result: handlerResult,
4733
- resolve
4836
+ resolve,
4837
+ cancel
4734
4838
  });
4735
4839
  }, [
4736
- pendingEvent,
4840
+ pending,
4737
4841
  handlerResult,
4738
- resolve
4842
+ resolve,
4843
+ cancel
4739
4844
  ]);
4740
4845
  (0, react.useEffect)(() => {
4741
4846
  if (config.renderInChat === false) return;
@@ -4771,9 +4876,9 @@ function useThreadStoreSelector(store, selector) {
4771
4876
  * current without polling — thread creates, renames, archives, and deletes
4772
4877
  * from any client are reflected immediately.
4773
4878
  *
4774
- * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return
4775
- * promises that resolve once the platform confirms the operation and reject
4776
- * with an `Error` on failure.
4879
+ * Mutation methods (`renameThread`, `archiveThread`, `unarchiveThread`,
4880
+ * `deleteThread`) return promises that resolve once the platform confirms the
4881
+ * operation and reject with an `Error` on failure.
4777
4882
  *
4778
4883
  * @param input - Agent identifier and optional list controls.
4779
4884
  * @returns Thread list state and stable mutation callbacks.
@@ -4823,21 +4928,32 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4823
4928
  const headersKey = (0, react.useMemo)(() => {
4824
4929
  return JSON.stringify(Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) => left.localeCompare(right)));
4825
4930
  }, [copilotkit.headers]);
4931
+ const runtimeStatus = copilotkit.runtimeConnectionStatus;
4932
+ const threadListEndpointSupported = copilotkit.threadEndpoints?.list !== false;
4933
+ const threadMutationsSupported = copilotkit.threadEndpoints?.mutations !== false;
4934
+ const threadEndpointsUnavailable = !!copilotkit.runtimeUrl && runtimeStatus === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected && !threadListEndpointSupported;
4826
4935
  const runtimeError = (0, react.useMemo)(() => {
4827
4936
  if (copilotkit.runtimeUrl) return null;
4828
4937
  return /* @__PURE__ */ new Error("Runtime URL is not configured");
4829
4938
  }, [copilotkit.runtimeUrl]);
4939
+ const threadEndpointsError = (0, react.useMemo)(() => {
4940
+ if (!threadEndpointsUnavailable) return null;
4941
+ return /* @__PURE__ */ new Error("Thread endpoints are not available on this CopilotKit runtime");
4942
+ }, [threadEndpointsUnavailable]);
4943
+ const threadMutationsError = (0, react.useMemo)(() => {
4944
+ if (threadMutationsSupported) return null;
4945
+ return /* @__PURE__ */ new Error("Thread mutations are not available on this CopilotKit runtime");
4946
+ }, [threadMutationsSupported]);
4830
4947
  const [hasDispatchedContext, setHasDispatchedContext] = (0, react.useState)(false);
4831
- const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
4832
- const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
4833
- const error = runtimeError ?? storeError;
4948
+ const preConnectLoading = !!copilotkit.runtimeUrl && !threadEndpointsUnavailable && !hasDispatchedContext;
4949
+ const isLoading = runtimeError || threadEndpointsError ? false : preConnectLoading || storeIsLoading;
4950
+ const error = runtimeError ?? threadEndpointsError ?? storeError;
4834
4951
  (0, react.useEffect)(() => {
4835
4952
  store.start();
4836
4953
  return () => {
4837
4954
  store.stop();
4838
4955
  };
4839
4956
  }, [store]);
4840
- const runtimeStatus = copilotkit.runtimeConnectionStatus;
4841
4957
  (0, react.useEffect)(() => {
4842
4958
  copilotkit.registerThreadStore(agentId, store);
4843
4959
  return () => {
@@ -4851,9 +4967,15 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4851
4967
  (0, react.useEffect)(() => {
4852
4968
  if (!copilotkit.runtimeUrl) {
4853
4969
  store.setContext(null);
4970
+ setHasDispatchedContext(false);
4854
4971
  return;
4855
4972
  }
4856
4973
  if (runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return;
4974
+ if (!threadListEndpointSupported) {
4975
+ store.setContext(null);
4976
+ setHasDispatchedContext(false);
4977
+ return;
4978
+ }
4857
4979
  const context = {
4858
4980
  runtimeUrl: copilotkit.runtimeUrl,
4859
4981
  headers: { ...copilotkit.headers },
@@ -4870,13 +4992,21 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4870
4992
  runtimeStatus,
4871
4993
  headersKey,
4872
4994
  copilotkit.intelligence?.wsUrl,
4995
+ threadListEndpointSupported,
4873
4996
  agentId,
4874
4997
  includeArchived,
4875
4998
  limit
4876
4999
  ]);
4877
- const renameThread = (0, react.useCallback)((threadId, name) => store.renameThread(threadId, name), [store]);
4878
- const archiveThread = (0, react.useCallback)((threadId) => store.archiveThread(threadId), [store]);
4879
- const deleteThread = (0, react.useCallback)((threadId) => store.deleteThread(threadId), [store]);
5000
+ const guardMutation = (0, react.useCallback)((mutation) => {
5001
+ return (...args) => {
5002
+ if (threadMutationsError) return Promise.reject(threadMutationsError);
5003
+ return mutation(...args);
5004
+ };
5005
+ }, [threadMutationsError]);
5006
+ const renameThread = (0, react.useMemo)(() => guardMutation((threadId, name) => store.renameThread(threadId, name)), [store, guardMutation]);
5007
+ const archiveThread = (0, react.useMemo)(() => guardMutation((threadId) => store.archiveThread(threadId)), [store, guardMutation]);
5008
+ const unarchiveThread = (0, react.useMemo)(() => guardMutation((threadId) => store.unarchiveThread(threadId)), [store, guardMutation]);
5009
+ const deleteThread = (0, react.useMemo)(() => guardMutation((threadId) => store.deleteThread(threadId)), [store, guardMutation]);
4880
5010
  return {
4881
5011
  threads,
4882
5012
  isLoading,
@@ -4886,6 +5016,7 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4886
5016
  fetchMoreThreads: (0, react.useCallback)(() => store.fetchNextPage(), [store]),
4887
5017
  renameThread,
4888
5018
  archiveThread,
5019
+ unarchiveThread,
4889
5020
  deleteThread
4890
5021
  };
4891
5022
  }
@@ -7683,8 +7814,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7683
7814
  hasExplicitThreadId
7684
7815
  ]);
7685
7816
  const waitForActiveRunToSettle = (0, react.useCallback)(async () => {
7686
- if (agent.isRunning && (0, _copilotkit_core.isRunCompletionAware)(agent) && agent.activeRunCompletionPromise) try {
7687
- await agent.activeRunCompletionPromise;
7817
+ const maybeAware = agent;
7818
+ const activeRunCompletionPromise = (0, _copilotkit_core.isRunCompletionAware)(maybeAware) ? maybeAware.activeRunCompletionPromise : void 0;
7819
+ if (agent.isRunning && activeRunCompletionPromise) try {
7820
+ await activeRunCompletionPromise;
7688
7821
  } catch (error) {
7689
7822
  console.error("CopilotChat: in-flight run rejected while queuing send", error);
7690
7823
  }
@@ -10123,6 +10256,7 @@ function CopilotKit({ children, ...props }) {
10123
10256
  const showInspector = shouldShowDevConsole(props.enableInspector);
10124
10257
  const publicApiKey = props.publicApiKey || props.publicLicenseKey;
10125
10258
  const renderArr = (0, react.useMemo)(() => [{ render: CoAgentStateRenderBridge }], []);
10259
+ const { onError: _onError, ...v2Props } = props;
10126
10260
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToastProvider, {
10127
10261
  enabled,
10128
10262
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotErrorBoundary, {
@@ -10131,7 +10265,7 @@ function CopilotKit({ children, ...props }) {
10131
10265
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadsProvider, {
10132
10266
  threadId: props.threadId,
10133
10267
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitProvider, {
10134
- ...props,
10268
+ ...v2Props,
10135
10269
  showDevConsole: showInspector,
10136
10270
  renderCustomMessages: renderArr,
10137
10271
  useSingleEndpoint: props.useSingleEndpoint ?? true,
@@ -11083,4 +11217,4 @@ Object.defineProperty(exports, 'useToast', {
11083
11217
  return useToast;
11084
11218
  }
11085
11219
  });
11086
- //# sourceMappingURL=copilotkit-DtPCrXXd.cjs.map
11220
+ //# sourceMappingURL=copilotkit-CTCjVxkH.cjs.map