@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
@@ -1,10 +1,10 @@
1
1
  import * as React$1 from "react";
2
2
  import React, { createContext, forwardRef, memo, useCallback, useContext, useEffect, useId, useImperativeHandle, useLayoutEffect, useMemo, useReducer, useRef, useState, useSyncExternalStore } from "react";
3
3
  import { CopilotKitCore, CopilotKitCoreRuntimeConnectionStatus, ProxiedCopilotRuntimeAgent, ToolCallStatus, isRunCompletionAware, ɵcreateThreadStore, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading } from "@copilotkit/core";
4
- import { HttpAgent } from "@ag-ui/client";
4
+ import { HttpAgent, buildResumeArray, isInterruptExpired, randomUUID } from "@ag-ui/client";
5
5
  import { extendTailwindMerge, twMerge } from "tailwind-merge";
6
6
  import { ArrowUp, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronRightIcon, Copy, Edit, Loader2, MessageCircle, Mic, Play, Plus, RefreshCw, Square, ThumbsDown, ThumbsUp, Upload, Volume2, X } from "lucide-react";
7
- import { A2UI_DEFAULT_DESIGN_GUIDELINES, A2UI_DEFAULT_GENERATION_GUIDELINES, COPILOT_CLOUD_API_URL, COPILOT_CLOUD_CHAT_URL, COPILOT_CLOUD_PUBLIC_API_KEY_HEADER, ConfigurationError, CopilotKitAgentDiscoveryError, CopilotKitApiDiscoveryError, CopilotKitError, CopilotKitErrorCode, CopilotKitLowLevelError, CopilotKitRemoteEndpointDiscoveryError, DEFAULT_AGENT_ID, ErrorVisibility, MissingPublicApiKeyError, Severity, TranscriptionErrorCode, TranscriptionErrorCode as TranscriptionErrorCode$1, copyToClipboard, createLicenseContextValue, dataToUUID, exceedsMaxSize, formatFileSize, generateVideoThumbnail, getDocumentIcon, getModalityFromMimeType, getSourceUrl, matchesAcceptFilter, parseJson, partialJSONParse, randomId, randomUUID, readFileAsBase64, schemaToJsonSchema } from "@copilotkit/shared";
7
+ import { A2UI_DEFAULT_DESIGN_GUIDELINES, A2UI_DEFAULT_GENERATION_GUIDELINES, COPILOT_CLOUD_API_URL, COPILOT_CLOUD_CHAT_URL, COPILOT_CLOUD_PUBLIC_API_KEY_HEADER, ConfigurationError, CopilotKitAgentDiscoveryError, CopilotKitApiDiscoveryError, CopilotKitError, CopilotKitErrorCode, CopilotKitLowLevelError, CopilotKitRemoteEndpointDiscoveryError, DEFAULT_AGENT_ID, ErrorVisibility, MissingPublicApiKeyError, Severity, TranscriptionErrorCode, TranscriptionErrorCode as TranscriptionErrorCode$1, copyToClipboard, createLicenseContextValue, dataToUUID, exceedsMaxSize, formatFileSize, generateVideoThumbnail, getDocumentIcon, getModalityFromMimeType, getSourceUrl, matchesAcceptFilter, parseJson, partialJSONParse, randomId, randomUUID as randomUUID$1, readFileAsBase64, schemaToJsonSchema } from "@copilotkit/shared";
8
8
  import { Fragment as Fragment$1, jsx, jsxs } from "react/jsx-runtime";
9
9
  import { Slot } from "@radix-ui/react-slot";
10
10
  import { cva } from "class-variance-authority";
@@ -157,7 +157,7 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
157
157
  const resolvedThreadId = useMemo(() => {
158
158
  if (threadId) return threadId;
159
159
  if (parentConfig?.threadId) return parentConfig.threadId;
160
- return randomUUID();
160
+ return randomUUID$1();
161
161
  }, [threadId, parentConfig?.threadId]);
162
162
  const resolvedHasExplicitThreadId = (hasExplicitThreadId !== void 0 ? hasExplicitThreadId : !!threadId) || !!parentConfig?.hasExplicitThreadId;
163
163
  const [internalModalOpen, setInternalModalOpen] = useState(isModalDefaultOpen ?? true);
@@ -1490,10 +1490,20 @@ function useRenderTool(config, deps) {
1490
1490
  }) : defineToolCallRenderer({
1491
1491
  name: config.name,
1492
1492
  args: config.parameters,
1493
- render: (props) => config.render({
1494
- ...props,
1495
- parameters: props.args
1496
- }),
1493
+ render: (props) => {
1494
+ if (props.status === ToolCallStatus.InProgress) return config.render({
1495
+ ...props,
1496
+ parameters: props.args
1497
+ });
1498
+ if (props.status === ToolCallStatus.Executing) return config.render({
1499
+ ...props,
1500
+ parameters: props.args
1501
+ });
1502
+ return config.render({
1503
+ ...props,
1504
+ parameters: props.args
1505
+ });
1506
+ },
1497
1507
  ...config.agentId ? { agentId: config.agentId } : {}
1498
1508
  });
1499
1509
  copilotkit.addHookRenderToolCall(renderer);
@@ -3531,6 +3541,10 @@ function A2UICatalogContext({ catalog, includeSchema }) {
3531
3541
 
3532
3542
  //#endregion
3533
3543
  //#region src/v2/providers/CopilotKitProvider.tsx
3544
+ const zodToJsonSchemaAdapter = (schema, options) => {
3545
+ const refStrategy = options?.$refStrategy;
3546
+ return zodToJsonSchema(schema, refStrategy === "root" || refStrategy === "relative" || refStrategy === "none" || refStrategy === "seen" ? { $refStrategy: refStrategy } : {});
3547
+ };
3534
3548
  const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
3535
3549
  const COPILOT_CLOUD_CHAT_URL$1 = "https://api.cloud.copilotkit.ai/copilotkit/v1";
3536
3550
  const EMPTY_HEADERS = Object.freeze({});
@@ -3561,6 +3575,8 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3561
3575
  const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = useState(false);
3562
3576
  const [runtimeOpenGenUIEnabled, setRuntimeOpenGenUIEnabled] = useState(false);
3563
3577
  const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
3578
+ const a2uiCatalogProvided = !!a2ui?.catalog;
3579
+ const a2uiActive = runtimeA2UIEnabled || a2uiCatalogProvided;
3564
3580
  const [runtimeLicenseStatus, setRuntimeLicenseStatus] = useState(void 0);
3565
3581
  useEffect(() => {
3566
3582
  if (typeof window === "undefined") return;
@@ -3591,7 +3607,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3591
3607
  content: OpenGenerativeUIContentSchema,
3592
3608
  render: OpenGenerativeUIActivityRenderer
3593
3609
  });
3594
- if (runtimeA2UIEnabled) renderers.unshift(createA2UIMessageRenderer({
3610
+ if (a2uiActive) renderers.unshift(createA2UIMessageRenderer({
3595
3611
  theme: a2ui?.theme ?? viewerTheme,
3596
3612
  catalog: a2ui?.catalog,
3597
3613
  loadingComponent: a2ui?.loadingComponent,
@@ -3599,7 +3615,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3599
3615
  }));
3600
3616
  return renderers;
3601
3617
  }, [
3602
- runtimeA2UIEnabled,
3618
+ a2uiActive,
3603
3619
  openGenUIActive,
3604
3620
  a2ui
3605
3621
  ]);
@@ -3786,7 +3802,10 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3786
3802
  copilotkit.setRuntimeTransport(useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto");
3787
3803
  copilotkit.setHeaders(mergedHeaders);
3788
3804
  copilotkit.setCredentials(credentials);
3789
- copilotkit.setProperties(properties);
3805
+ copilotkit.setProperties(a2uiCatalogProvided ? {
3806
+ ...properties,
3807
+ a2uiCatalogAvailable: true
3808
+ } : properties);
3790
3809
  copilotkit.setAgents__unsafe_dev_only(mergedAgents);
3791
3810
  copilotkit.setDebug(debug);
3792
3811
  }, [
@@ -3795,6 +3814,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3795
3814
  mergedHeaders,
3796
3815
  credentials,
3797
3816
  properties,
3817
+ a2uiCatalogProvided,
3798
3818
  mergedAgents,
3799
3819
  useSingleEndpoint,
3800
3820
  debug
@@ -3842,7 +3862,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3842
3862
  return JSON.stringify(sandboxFunctionsList.map((fn) => ({
3843
3863
  name: fn.name,
3844
3864
  description: fn.description,
3845
- parameters: schemaToJsonSchema(fn.parameters, { zodToJsonSchema })
3865
+ parameters: schemaToJsonSchema(fn.parameters, { zodToJsonSchema: zodToJsonSchemaAdapter })
3846
3866
  })));
3847
3867
  }, [sandboxFunctionsList]);
3848
3868
  useLayoutEffect(() => {
@@ -3863,7 +3883,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3863
3883
  copilotkit,
3864
3884
  executingToolCallIds
3865
3885
  }), [copilotkit, executingToolCallIds]);
3866
- const licenseContextValue = useMemo(() => createLicenseContextValue(null), []);
3886
+ const licenseContextValue = useMemo(() => createLicenseContextValue(runtimeLicenseStatus), [runtimeLicenseStatus]);
3867
3887
  return /* @__PURE__ */ jsx(SandboxFunctionsContext.Provider, {
3868
3888
  value: sandboxFunctionsList,
3869
3889
  children: /* @__PURE__ */ jsx(CopilotKitContext.Provider, {
@@ -3871,8 +3891,8 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
3871
3891
  children: /* @__PURE__ */ jsxs(LicenseContext.Provider, {
3872
3892
  value: licenseContextValue,
3873
3893
  children: [
3874
- runtimeA2UIEnabled && /* @__PURE__ */ jsx(A2UIBuiltInToolCallRenderer, {}),
3875
- runtimeA2UIEnabled && /* @__PURE__ */ jsx(A2UICatalogContext, {
3894
+ a2uiActive && /* @__PURE__ */ jsx(A2UIBuiltInToolCallRenderer, {}),
3895
+ a2uiActive && /* @__PURE__ */ jsx(A2UICatalogContext, {
3876
3896
  catalog: a2ui?.catalog,
3877
3897
  includeSchema: a2ui?.includeSchema
3878
3898
  }),
@@ -3950,16 +3970,20 @@ function useRenderActivityMessage() {
3950
3970
  const renderActivityMessage = useCallback((message) => {
3951
3971
  const renderer = findRenderer(message.activityType);
3952
3972
  if (!renderer) return null;
3953
- const parseResult = renderer.content.safeParse(message.content);
3954
- if (!parseResult.success) {
3955
- console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.error);
3973
+ const parseResult = renderer.content["~standard"].validate(message.content);
3974
+ if (parseResult instanceof Promise) {
3975
+ console.warn(`Async content validation is not supported for activity message '${message.activityType}'`);
3976
+ return null;
3977
+ }
3978
+ if (parseResult.issues) {
3979
+ console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.issues);
3956
3980
  return null;
3957
3981
  }
3958
3982
  const Component = renderer.render;
3959
3983
  const agent = copilotkit.getAgent(agentId);
3960
3984
  return /* @__PURE__ */ jsx(Component, {
3961
3985
  activityType: message.activityType,
3962
- content: parseResult.data,
3986
+ content: parseResult.value,
3963
3987
  message,
3964
3988
  agent
3965
3989
  }, message.id);
@@ -4080,15 +4104,34 @@ function useComponent(config, deps) {
4080
4104
  function useHumanInTheLoop(tool, deps) {
4081
4105
  const { copilotkit } = useCopilotKit();
4082
4106
  const resolvePromiseRef = useRef(null);
4107
+ const cleanupAbortRef = useRef(null);
4083
4108
  const respond = useCallback(async (result) => {
4084
4109
  if (resolvePromiseRef.current) {
4110
+ cleanupAbortRef.current?.();
4111
+ cleanupAbortRef.current = null;
4085
4112
  resolvePromiseRef.current(result);
4086
4113
  resolvePromiseRef.current = null;
4087
4114
  }
4088
4115
  }, []);
4089
- const handler = useCallback(async () => {
4090
- return new Promise((resolve) => {
4116
+ const handler = useCallback(async (_args, context) => {
4117
+ const signal = context?.signal;
4118
+ return new Promise((resolve, reject) => {
4119
+ if (signal?.aborted) {
4120
+ reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
4121
+ return;
4122
+ }
4091
4123
  resolvePromiseRef.current = resolve;
4124
+ if (signal) {
4125
+ const onAbort = () => {
4126
+ cleanupAbortRef.current = null;
4127
+ resolvePromiseRef.current = null;
4128
+ reject(/* @__PURE__ */ new Error("Human-in-the-loop interaction aborted"));
4129
+ };
4130
+ signal.addEventListener("abort", onAbort, { once: true });
4131
+ cleanupAbortRef.current = () => {
4132
+ signal.removeEventListener("abort", onAbort);
4133
+ };
4134
+ }
4092
4135
  });
4093
4136
  }, []);
4094
4137
  const RenderComponent = useCallback((props) => {
@@ -4176,7 +4219,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4176
4219
  if (isRuntimeConfigured && (status === CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4177
4220
  const cached = provisionalAgentCache.current.get(agentId);
4178
4221
  if (cached) {
4179
- cached.headers = { ...copilotkit.headers };
4222
+ copilotkit.applyHeadersToAgent(cached);
4180
4223
  return cached;
4181
4224
  }
4182
4225
  const provisional = new ProxiedCopilotRuntimeAgent({
@@ -4185,14 +4228,14 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4185
4228
  transport: copilotkit.runtimeTransport,
4186
4229
  runtimeMode: "pending"
4187
4230
  });
4188
- provisional.headers = { ...copilotkit.headers };
4231
+ copilotkit.applyHeadersToAgent(provisional);
4189
4232
  provisionalAgentCache.current.set(agentId, provisional);
4190
4233
  return provisional;
4191
4234
  }
4192
4235
  if (isRuntimeConfigured && status === CopilotKitCoreRuntimeConnectionStatus.Error) {
4193
4236
  const cached = provisionalAgentCache.current.get(agentId);
4194
4237
  if (cached) {
4195
- cached.headers = { ...copilotkit.headers };
4238
+ copilotkit.applyHeadersToAgent(cached);
4196
4239
  return cached;
4197
4240
  }
4198
4241
  const provisional = new ProxiedCopilotRuntimeAgent({
@@ -4201,7 +4244,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4201
4244
  transport: copilotkit.runtimeTransport,
4202
4245
  runtimeMode: "pending"
4203
4246
  });
4204
- provisional.headers = { ...copilotkit.headers };
4247
+ copilotkit.applyHeadersToAgent(provisional);
4205
4248
  provisionalAgentCache.current.set(agentId, provisional);
4206
4249
  return provisional;
4207
4250
  }
@@ -4252,7 +4295,7 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4252
4295
  updateFlags
4253
4296
  ]);
4254
4297
  useEffect(() => {
4255
- if (agent instanceof HttpAgent) agent.headers = { ...copilotkit.headers };
4298
+ if (agent instanceof HttpAgent) copilotkit.applyHeadersToAgent(agent);
4256
4299
  }, [agent, JSON.stringify(copilotkit.headers)]);
4257
4300
  const chatConfig = useCopilotChatConfiguration();
4258
4301
  const configThreadId = chatConfig?.threadId;
@@ -4529,114 +4572,165 @@ const INTERRUPT_EVENT_NAME = "on_interrupt";
4529
4572
  function isPromiseLike(value) {
4530
4573
  return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
4531
4574
  }
4575
+ /** Derive the legacy-compatible `event` for any pending interrupt. */
4576
+ function toLegacyEvent(pending) {
4577
+ if (pending.kind === "legacy") return pending.event;
4578
+ return {
4579
+ name: INTERRUPT_EVENT_NAME,
4580
+ value: pending.interrupts[0]
4581
+ };
4582
+ }
4532
4583
  /**
4533
- * Handles agent interrupts (`on_interrupt`) with optional filtering, preprocessing, and resume behavior.
4534
- *
4535
- * The hook listens to custom events on the active agent, stores interrupt payloads per run,
4536
- * and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
4537
- * execution with user-provided data.
4584
+ * Handles agent interrupts with optional filtering, preprocessing, and resume behavior.
4538
4585
  *
4539
- * - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
4540
- * - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
4586
+ * Supports both the AG-UI standard interrupt flow (`RUN_FINISHED` with
4587
+ * `outcome.type === "interrupt"`) and the legacy custom-event flow
4588
+ * (`on_interrupt`). For standard interrupts, `render` receives `interrupt`
4589
+ * (the primary one) and `interrupts` (the full open set); call `resolve(payload)`
4590
+ * to resume or `cancel()` to cancel. Resuming addresses the targeted interrupt
4591
+ * and, once every open interrupt is addressed, submits a single spec `resume`
4592
+ * array via `copilotkit.runAgent`.
4541
4593
  *
4542
- * `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
4543
- * Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
4544
- *
4545
- * @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
4546
- * @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
4547
- * @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
4548
- * Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
4549
- * either the handler's resolved return value or `null` (including when no handler is provided,
4550
- * when filtering skips the interrupt, or when handler execution fails).
4594
+ * - `renderInChat: true` (default): the element is published into `<CopilotChat>`; returns `void`.
4595
+ * - `renderInChat: false`: the hook returns the interrupt element for manual placement.
4551
4596
  *
4552
4597
  * @example
4553
4598
  * ```tsx
4554
- * import { useInterrupt } from "@copilotkit/react-core/v2";
4555
- *
4556
- * function InterruptUI() {
4557
- * useInterrupt({
4558
- * render: ({ event, resolve }) => (
4559
- * <div>
4560
- * <p>{event.value.question}</p>
4561
- * <button onClick={() => resolve({ approved: true })}>Approve</button>
4562
- * <button onClick={() => resolve({ approved: false })}>Reject</button>
4563
- * </div>
4564
- * ),
4565
- * });
4566
- *
4567
- * return null;
4568
- * }
4569
- * ```
4570
- *
4571
- * @example
4572
- * ```tsx
4573
- * import { useInterrupt } from "@copilotkit/react-core/v2";
4574
- *
4575
- * function CustomPanel() {
4576
- * const interruptElement = useInterrupt({
4577
- * renderInChat: false,
4578
- * enabled: (event) => event.value.startsWith("approval:"),
4579
- * handler: async ({ event }) => ({ label: event.value.toUpperCase() }),
4580
- * render: ({ event, result, resolve }) => (
4581
- * <aside>
4582
- * <strong>{result?.label ?? ""}</strong>
4583
- * <button onClick={() => resolve({ value: event.value })}>Continue</button>
4584
- * </aside>
4585
- * ),
4586
- * });
4587
- *
4588
- * return <>{interruptElement}</>;
4589
- * }
4599
+ * useInterrupt({
4600
+ * render: ({ interrupt, resolve, cancel }) => (
4601
+ * <div>
4602
+ * <p>{interrupt?.message}</p>
4603
+ * <button onClick={() => resolve({ approved: true })}>Approve</button>
4604
+ * <button onClick={() => cancel()}>Cancel</button>
4605
+ * </div>
4606
+ * ),
4607
+ * });
4590
4608
  * ```
4591
4609
  */
4592
4610
  function useInterrupt(config) {
4593
4611
  const { copilotkit } = useCopilotKit();
4594
4612
  const { agent } = useAgent({ agentId: config.agentId });
4595
- const [pendingEvent, setPendingEvent] = useState(null);
4596
- const pendingEventRef = useRef(pendingEvent);
4597
- pendingEventRef.current = pendingEvent;
4613
+ const [pending, setPending] = useState(null);
4614
+ const pendingRef = useRef(pending);
4615
+ pendingRef.current = pending;
4598
4616
  const [handlerResult, setHandlerResult] = useState(null);
4617
+ const responsesRef = useRef({});
4599
4618
  useEffect(() => {
4600
- let localInterrupt = null;
4619
+ let localLegacy = null;
4620
+ let localStandard = null;
4601
4621
  const subscription = agent.subscribe({
4602
4622
  onCustomEvent: ({ event }) => {
4603
- if (event.name === INTERRUPT_EVENT_NAME) localInterrupt = {
4623
+ if (event.name === INTERRUPT_EVENT_NAME) localLegacy = {
4604
4624
  name: event.name,
4605
4625
  value: event.value
4606
4626
  };
4607
4627
  },
4628
+ onRunFinishedEvent: (params) => {
4629
+ if (params.outcome === "interrupt") localStandard = params.interrupts;
4630
+ },
4608
4631
  onRunStartedEvent: () => {
4609
- localInterrupt = null;
4610
- setPendingEvent(null);
4632
+ localLegacy = null;
4633
+ localStandard = null;
4634
+ responsesRef.current = {};
4635
+ setPending(null);
4611
4636
  },
4612
4637
  onRunFinalized: () => {
4613
- if (localInterrupt) {
4614
- setPendingEvent(localInterrupt);
4615
- localInterrupt = null;
4616
- }
4638
+ if (localStandard && localStandard.length > 0) setPending({
4639
+ kind: "standard",
4640
+ interrupts: localStandard
4641
+ });
4642
+ else if (localLegacy) setPending({
4643
+ kind: "legacy",
4644
+ event: localLegacy
4645
+ });
4646
+ localLegacy = null;
4647
+ localStandard = null;
4617
4648
  },
4618
4649
  onRunFailed: () => {
4619
- localInterrupt = null;
4620
- setPendingEvent(null);
4650
+ localLegacy = null;
4651
+ localStandard = null;
4652
+ responsesRef.current = {};
4653
+ setPending(null);
4621
4654
  }
4622
4655
  });
4623
4656
  return () => subscription.unsubscribe();
4624
4657
  }, [agent]);
4625
- const resolve = useCallback(async (response) => {
4658
+ const submitStandardIfComplete = useCallback(async (interrupts) => {
4659
+ if (!interrupts.every((i) => responsesRef.current[i.id])) return;
4660
+ const expired = interrupts.find((i) => isInterruptExpired(i));
4661
+ if (expired) {
4662
+ console.error(`[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`);
4663
+ responsesRef.current = {};
4664
+ setPending(null);
4665
+ return;
4666
+ }
4667
+ const resume = buildResumeArray(interrupts, responsesRef.current);
4668
+ for (const i of interrupts) {
4669
+ if (!i.toolCallId) continue;
4670
+ const response = responsesRef.current[i.id];
4671
+ const content = response.status === "cancelled" ? { status: "cancelled" } : response.payload ?? { status: "resolved" };
4672
+ agent.addMessage({
4673
+ id: randomUUID(),
4674
+ role: "tool",
4675
+ toolCallId: i.toolCallId,
4676
+ content: JSON.stringify(content)
4677
+ });
4678
+ }
4679
+ responsesRef.current = {};
4626
4680
  try {
4681
+ return await copilotkit.runAgent({
4682
+ agent,
4683
+ resume
4684
+ });
4685
+ } catch (err) {
4686
+ console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
4687
+ setPending(null);
4688
+ throw err;
4689
+ }
4690
+ }, [agent, copilotkit]);
4691
+ const resolve = useCallback(async (payload, interruptId) => {
4692
+ const current = pendingRef.current;
4693
+ if (!current) return;
4694
+ if (current.kind === "legacy") try {
4627
4695
  return await copilotkit.runAgent({
4628
4696
  agent,
4629
4697
  forwardedProps: { command: {
4630
- resume: response,
4631
- interruptEvent: pendingEventRef.current?.value
4698
+ resume: payload,
4699
+ interruptEvent: current.event.value
4632
4700
  } }
4633
4701
  });
4634
4702
  } catch (err) {
4635
4703
  console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
4636
- setPendingEvent(null);
4704
+ setPending(null);
4637
4705
  throw err;
4638
4706
  }
4639
- }, [agent, copilotkit]);
4707
+ 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.`);
4708
+ const id = interruptId ?? current.interrupts[0]?.id;
4709
+ if (!id) return;
4710
+ responsesRef.current[id] = {
4711
+ status: "resolved",
4712
+ payload
4713
+ };
4714
+ return submitStandardIfComplete(current.interrupts);
4715
+ }, [
4716
+ agent,
4717
+ copilotkit,
4718
+ submitStandardIfComplete
4719
+ ]);
4720
+ const cancel = useCallback(async (interruptId) => {
4721
+ const current = pendingRef.current;
4722
+ if (!current) return;
4723
+ if (current.kind === "legacy") {
4724
+ console.warn("[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.");
4725
+ setPending(null);
4726
+ return;
4727
+ }
4728
+ 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.`);
4729
+ const id = interruptId ?? current.interrupts[0]?.id;
4730
+ if (!id) return;
4731
+ responsesRef.current[id] = { status: "cancelled" };
4732
+ return submitStandardIfComplete(current.interrupts);
4733
+ }, [submitStandardIfComplete]);
4640
4734
  const renderRef = useRef(config.render);
4641
4735
  renderRef.current = config.render;
4642
4736
  const enabledRef = useRef(config.enabled);
@@ -4645,6 +4739,8 @@ function useInterrupt(config) {
4645
4739
  handlerRef.current = config.handler;
4646
4740
  const resolveRef = useRef(resolve);
4647
4741
  resolveRef.current = resolve;
4742
+ const cancelRef = useRef(cancel);
4743
+ cancelRef.current = cancel;
4648
4744
  const isEnabled = (event) => {
4649
4745
  const predicate = enabledRef.current;
4650
4746
  if (!predicate) return true;
@@ -4656,11 +4752,12 @@ function useInterrupt(config) {
4656
4752
  }
4657
4753
  };
4658
4754
  useEffect(() => {
4659
- if (!pendingEvent) {
4755
+ if (!pending) {
4660
4756
  setHandlerResult(null);
4661
4757
  return;
4662
4758
  }
4663
- if (!isEnabled(pendingEvent)) {
4759
+ const legacyEvent = toLegacyEvent(pending);
4760
+ if (!isEnabled(legacyEvent)) {
4664
4761
  setHandlerResult(null);
4665
4762
  return;
4666
4763
  }
@@ -4673,8 +4770,11 @@ function useInterrupt(config) {
4673
4770
  let maybePromise;
4674
4771
  try {
4675
4772
  maybePromise = handler({
4676
- event: pendingEvent,
4677
- resolve: resolveRef.current
4773
+ event: legacyEvent,
4774
+ interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
4775
+ interrupts: pending.kind === "standard" ? pending.interrupts : [],
4776
+ resolve: resolveRef.current,
4777
+ cancel: cancelRef.current
4678
4778
  });
4679
4779
  } catch (err) {
4680
4780
  console.error("[CopilotKit] useInterrupt handler threw; result will be null:", err);
@@ -4693,19 +4793,24 @@ function useInterrupt(config) {
4693
4793
  return () => {
4694
4794
  cancelled = true;
4695
4795
  };
4696
- }, [pendingEvent]);
4796
+ }, [pending]);
4697
4797
  const element = useMemo(() => {
4698
- if (!pendingEvent) return null;
4699
- if (!isEnabled(pendingEvent)) return null;
4798
+ if (!pending) return null;
4799
+ const legacyEvent = toLegacyEvent(pending);
4800
+ if (!isEnabled(legacyEvent)) return null;
4700
4801
  return renderRef.current({
4701
- event: pendingEvent,
4802
+ event: legacyEvent,
4803
+ interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
4804
+ interrupts: pending.kind === "standard" ? pending.interrupts : [],
4702
4805
  result: handlerResult,
4703
- resolve
4806
+ resolve,
4807
+ cancel
4704
4808
  });
4705
4809
  }, [
4706
- pendingEvent,
4810
+ pending,
4707
4811
  handlerResult,
4708
- resolve
4812
+ resolve,
4813
+ cancel
4709
4814
  ]);
4710
4815
  useEffect(() => {
4711
4816
  if (config.renderInChat === false) return;
@@ -4741,9 +4846,9 @@ function useThreadStoreSelector(store, selector) {
4741
4846
  * current without polling — thread creates, renames, archives, and deletes
4742
4847
  * from any client are reflected immediately.
4743
4848
  *
4744
- * Mutation methods (`renameThread`, `archiveThread`, `deleteThread`) return
4745
- * promises that resolve once the platform confirms the operation and reject
4746
- * with an `Error` on failure.
4849
+ * Mutation methods (`renameThread`, `archiveThread`, `unarchiveThread`,
4850
+ * `deleteThread`) return promises that resolve once the platform confirms the
4851
+ * operation and reject with an `Error` on failure.
4747
4852
  *
4748
4853
  * @param input - Agent identifier and optional list controls.
4749
4854
  * @returns Thread list state and stable mutation callbacks.
@@ -4793,21 +4898,32 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4793
4898
  const headersKey = useMemo(() => {
4794
4899
  return JSON.stringify(Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) => left.localeCompare(right)));
4795
4900
  }, [copilotkit.headers]);
4901
+ const runtimeStatus = copilotkit.runtimeConnectionStatus;
4902
+ const threadListEndpointSupported = copilotkit.threadEndpoints?.list !== false;
4903
+ const threadMutationsSupported = copilotkit.threadEndpoints?.mutations !== false;
4904
+ const threadEndpointsUnavailable = !!copilotkit.runtimeUrl && runtimeStatus === CopilotKitCoreRuntimeConnectionStatus.Connected && !threadListEndpointSupported;
4796
4905
  const runtimeError = useMemo(() => {
4797
4906
  if (copilotkit.runtimeUrl) return null;
4798
4907
  return /* @__PURE__ */ new Error("Runtime URL is not configured");
4799
4908
  }, [copilotkit.runtimeUrl]);
4909
+ const threadEndpointsError = useMemo(() => {
4910
+ if (!threadEndpointsUnavailable) return null;
4911
+ return /* @__PURE__ */ new Error("Thread endpoints are not available on this CopilotKit runtime");
4912
+ }, [threadEndpointsUnavailable]);
4913
+ const threadMutationsError = useMemo(() => {
4914
+ if (threadMutationsSupported) return null;
4915
+ return /* @__PURE__ */ new Error("Thread mutations are not available on this CopilotKit runtime");
4916
+ }, [threadMutationsSupported]);
4800
4917
  const [hasDispatchedContext, setHasDispatchedContext] = useState(false);
4801
- const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
4802
- const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
4803
- const error = runtimeError ?? storeError;
4918
+ const preConnectLoading = !!copilotkit.runtimeUrl && !threadEndpointsUnavailable && !hasDispatchedContext;
4919
+ const isLoading = runtimeError || threadEndpointsError ? false : preConnectLoading || storeIsLoading;
4920
+ const error = runtimeError ?? threadEndpointsError ?? storeError;
4804
4921
  useEffect(() => {
4805
4922
  store.start();
4806
4923
  return () => {
4807
4924
  store.stop();
4808
4925
  };
4809
4926
  }, [store]);
4810
- const runtimeStatus = copilotkit.runtimeConnectionStatus;
4811
4927
  useEffect(() => {
4812
4928
  copilotkit.registerThreadStore(agentId, store);
4813
4929
  return () => {
@@ -4821,9 +4937,15 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4821
4937
  useEffect(() => {
4822
4938
  if (!copilotkit.runtimeUrl) {
4823
4939
  store.setContext(null);
4940
+ setHasDispatchedContext(false);
4824
4941
  return;
4825
4942
  }
4826
4943
  if (runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) return;
4944
+ if (!threadListEndpointSupported) {
4945
+ store.setContext(null);
4946
+ setHasDispatchedContext(false);
4947
+ return;
4948
+ }
4827
4949
  const context = {
4828
4950
  runtimeUrl: copilotkit.runtimeUrl,
4829
4951
  headers: { ...copilotkit.headers },
@@ -4840,13 +4962,21 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4840
4962
  runtimeStatus,
4841
4963
  headersKey,
4842
4964
  copilotkit.intelligence?.wsUrl,
4965
+ threadListEndpointSupported,
4843
4966
  agentId,
4844
4967
  includeArchived,
4845
4968
  limit
4846
4969
  ]);
4847
- const renameThread = useCallback((threadId, name) => store.renameThread(threadId, name), [store]);
4848
- const archiveThread = useCallback((threadId) => store.archiveThread(threadId), [store]);
4849
- const deleteThread = useCallback((threadId) => store.deleteThread(threadId), [store]);
4970
+ const guardMutation = useCallback((mutation) => {
4971
+ return (...args) => {
4972
+ if (threadMutationsError) return Promise.reject(threadMutationsError);
4973
+ return mutation(...args);
4974
+ };
4975
+ }, [threadMutationsError]);
4976
+ const renameThread = useMemo(() => guardMutation((threadId, name) => store.renameThread(threadId, name)), [store, guardMutation]);
4977
+ const archiveThread = useMemo(() => guardMutation((threadId) => store.archiveThread(threadId)), [store, guardMutation]);
4978
+ const unarchiveThread = useMemo(() => guardMutation((threadId) => store.unarchiveThread(threadId)), [store, guardMutation]);
4979
+ const deleteThread = useMemo(() => guardMutation((threadId) => store.deleteThread(threadId)), [store, guardMutation]);
4850
4980
  return {
4851
4981
  threads,
4852
4982
  isLoading,
@@ -4856,6 +4986,7 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4856
4986
  fetchMoreThreads: useCallback(() => store.fetchNextPage(), [store]),
4857
4987
  renameThread,
4858
4988
  archiveThread,
4989
+ unarchiveThread,
4859
4990
  deleteThread
4860
4991
  };
4861
4992
  }
@@ -4889,7 +5020,7 @@ async function recordAnnotation(args) {
4889
5020
  const body = {
4890
5021
  type,
4891
5022
  threadId,
4892
- clientEventId: args.clientEventId ?? randomUUID(),
5023
+ clientEventId: args.clientEventId ?? randomUUID$1(),
4893
5024
  ...payload !== void 0 ? { payload } : {},
4894
5025
  ...occurredAt !== void 0 ? { occurredAt } : {}
4895
5026
  };
@@ -5067,7 +5198,7 @@ function useAttachments({ config }) {
5067
5198
  continue;
5068
5199
  }
5069
5200
  const modality = getModalityFromMimeType(file.type);
5070
- const placeholderId = randomUUID();
5201
+ const placeholderId = randomUUID$1();
5071
5202
  const placeholder = {
5072
5203
  id: placeholderId,
5073
5204
  type: modality,
@@ -7578,7 +7709,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7578
7709
  const existingConfig = useCopilotChatConfiguration();
7579
7710
  const resolvedAgentId = agentId ?? existingConfig?.agentId ?? DEFAULT_AGENT_ID;
7580
7711
  const providedThreadId = threadId ?? existingConfig?.threadId;
7581
- const resolvedThreadId = useMemo(() => providedThreadId ?? randomUUID(), [providedThreadId]);
7712
+ const resolvedThreadId = useMemo(() => providedThreadId ?? randomUUID$1(), [providedThreadId]);
7582
7713
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
7583
7714
  const { agent } = useAgent({
7584
7715
  agentId: resolvedAgentId,
@@ -7653,8 +7784,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7653
7784
  hasExplicitThreadId
7654
7785
  ]);
7655
7786
  const waitForActiveRunToSettle = useCallback(async () => {
7656
- if (agent.isRunning && isRunCompletionAware(agent) && agent.activeRunCompletionPromise) try {
7657
- await agent.activeRunCompletionPromise;
7787
+ const maybeAware = agent;
7788
+ const activeRunCompletionPromise = isRunCompletionAware(maybeAware) ? maybeAware.activeRunCompletionPromise : void 0;
7789
+ if (agent.isRunning && activeRunCompletionPromise) try {
7790
+ await activeRunCompletionPromise;
7658
7791
  } catch (error) {
7659
7792
  console.error("CopilotChat: in-flight run rejected while queuing send", error);
7660
7793
  }
@@ -7689,12 +7822,12 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7689
7822
  }
7690
7823
  });
7691
7824
  agent.addMessage({
7692
- id: randomUUID(),
7825
+ id: randomUUID$1(),
7693
7826
  role: "user",
7694
7827
  content: contentParts
7695
7828
  });
7696
7829
  } else agent.addMessage({
7697
- id: randomUUID(),
7830
+ id: randomUUID$1(),
7698
7831
  role: "user",
7699
7832
  content: value
7700
7833
  });
@@ -7711,7 +7844,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7711
7844
  const handleSelectSuggestion = useCallback(async (suggestion) => {
7712
7845
  await waitForActiveRunToSettle();
7713
7846
  agent.addMessage({
7714
- id: randomUUID(),
7847
+ id: randomUUID$1(),
7715
7848
  role: "user",
7716
7849
  content: suggestion.message
7717
7850
  });
@@ -9632,7 +9765,7 @@ function useCoAgentStateRenders() {
9632
9765
  //#region src/context/threads-context.tsx
9633
9766
  const ThreadsContext = createContext(void 0);
9634
9767
  function ThreadsProvider({ children, threadId: explicitThreadId }) {
9635
- const [internalThreadId, setInternalThreadId] = useState(() => randomUUID());
9768
+ const [internalThreadId, setInternalThreadId] = useState(() => randomUUID$1());
9636
9769
  const [internalIsExplicit, setInternalIsExplicit] = useState(false);
9637
9770
  const threadId = explicitThreadId ?? internalThreadId;
9638
9771
  const isThreadIdExplicit = explicitThreadId != null || internalIsExplicit;
@@ -10093,6 +10226,7 @@ function CopilotKit({ children, ...props }) {
10093
10226
  const showInspector = shouldShowDevConsole(props.enableInspector);
10094
10227
  const publicApiKey = props.publicApiKey || props.publicLicenseKey;
10095
10228
  const renderArr = useMemo(() => [{ render: CoAgentStateRenderBridge }], []);
10229
+ const { onError: _onError, ...v2Props } = props;
10096
10230
  return /* @__PURE__ */ jsx(ToastProvider, {
10097
10231
  enabled,
10098
10232
  children: /* @__PURE__ */ jsx(CopilotErrorBoundary, {
@@ -10101,7 +10235,7 @@ function CopilotKit({ children, ...props }) {
10101
10235
  children: /* @__PURE__ */ jsx(ThreadsProvider, {
10102
10236
  threadId: props.threadId,
10103
10237
  children: /* @__PURE__ */ jsx(CopilotKitProvider, {
10104
- ...props,
10238
+ ...v2Props,
10105
10239
  showDevConsole: showInspector,
10106
10240
  renderCustomMessages: renderArr,
10107
10241
  useSingleEndpoint: props.useSingleEndpoint ?? true,
@@ -10400,7 +10534,7 @@ function CopilotKitInternal(cpkProps) {
10400
10534
  });
10401
10535
  }, [setAuthStates]);
10402
10536
  const handleSetRegisteredActions = useCallback((actionConfig) => {
10403
- const key = actionConfig.action.name || randomUUID();
10537
+ const key = actionConfig.action.name || randomUUID$1();
10404
10538
  setRegisteredActionConfigs((prev) => {
10405
10539
  const newMap = new Map(prev);
10406
10540
  newMap.set(key, actionConfig);
@@ -10586,4 +10720,4 @@ function validateProps(props) {
10586
10720
 
10587
10721
  //#endregion
10588
10722
  export { useAgent as $, INTELLIGENCE_TURN_HEAD as A, CopilotChatToolCallsView as B, CopilotChatToggleButton as C, useCopilotChatConfiguration as Ct, CopilotChatView_default as D, CopilotChat as E, CopilotChatSuggestionPill as F, useLearnFromUserAction as G, useLearningContainers as H, CopilotChatReasoningMessage_default as I, useConfigureSuggestions as J, useThreads$1 as K, CopilotChatUserMessage_default as L, getIntelligenceTurnAnchors as M, IntelligenceIndicatorView as N, CopilotChatAttachmentQueue as O, CopilotChatSuggestionView as P, UseAgentUpdate as Q, CopilotChatAttachmentRenderer as R, CopilotModalHeader as S, CopilotChatConfigurationProvider as St, DefaultOpenIcon as T, useAttachments as U, useLearningContainersInCurrentThread as V, useLearnFromUserActionInCurrentThread as W, useAgentContext as X, useSuggestions as Y, useCapabilities as Z, WildcardToolCallRender as _, useCopilotKit as _t, ThreadsProvider as a, CopilotKitProvider as at, CopilotPopupView as b, AudioRecorderError as bt, CoAgentStateRendersProvider as c, useSandboxFunctions as ct, shouldShowDevConsole as d, MCPAppsActivityType as dt, useHumanInTheLoop as et, useToast as f, CopilotKitInspector as ft, useCopilotContext as g, defineToolCallRenderer as gt, CopilotContext as h, useRenderTool as ht, ThreadsContext as i, useRenderCustomMessages as it, IntelligenceIndicator as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, MCPAppsActivityContentSchema as lt, useCopilotMessagesContext as m, useDefaultRenderTool as mt, defaultCopilotContextCategories as n, useFrontendTool as nt, useThreads as o, createA2UIMessageRenderer as ot, CopilotMessagesContext as p, useRenderToolCall as pt, useInterrupt as q, CoAgentStateRenderBridge as r, useRenderActivityMessage as rt, CoAgentStateRendersContext as s, SandboxFunctionsContext as st, CopilotKit as t, useComponent as tt, useAsyncCallback as u, MCPAppsActivityRenderer as ut, CopilotPopup as v, CopilotKitCoreReact as vt, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotChatAudioRecorder as xt, CopilotSidebar as y, CopilotChatInput_default as yt, CopilotChatAssistantMessage_default as z };
10589
- //# sourceMappingURL=copilotkit-BCxdKlMw.mjs.map
10723
+ //# sourceMappingURL=copilotkit-Be-o2UaU.mjs.map