@copilotkit/react-core 1.63.1 → 1.63.2-canary.1784918757

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.
@@ -52,7 +52,7 @@ let _copilotkit_web_components_threads_drawer = require("@copilotkit/web-compone
52
52
  let react_markdown = require("react-markdown");
53
53
  react_markdown = __toESM(react_markdown);
54
54
 
55
- //#region src/v2/lib/slots.tsx
55
+ //#region src/v2/lib/shallow-stable-ref.ts
56
56
  /**
57
57
  * Shallow equality comparison for objects.
58
58
  */
@@ -92,64 +92,6 @@ function useShallowStableRef(value) {
92
92
  ref.current = value;
93
93
  return ref.current;
94
94
  }
95
- /**
96
- * Check if a value is a React component type (function, class, forwardRef, memo, etc.)
97
- */
98
- function isReactComponentType(value) {
99
- if (typeof value === "function") return true;
100
- if (value && typeof value === "object" && "$$typeof" in value && !react.default.isValidElement(value)) return true;
101
- return false;
102
- }
103
- /**
104
- * Internal function to render a slot value as a React element (non-memoized).
105
- */
106
- function renderSlotElement(slot, DefaultComponent, props) {
107
- if (typeof slot === "string") {
108
- const existingClassName = props.className;
109
- return react.default.createElement(DefaultComponent, {
110
- ...props,
111
- className: (0, tailwind_merge.twMerge)(existingClassName, slot)
112
- });
113
- }
114
- if (isReactComponentType(slot)) return react.default.createElement(slot, props);
115
- if (slot && typeof slot === "object" && !react.default.isValidElement(slot)) return react.default.createElement(DefaultComponent, {
116
- ...props,
117
- ...slot
118
- });
119
- return react.default.createElement(DefaultComponent, props);
120
- }
121
- /**
122
- * Internal memoized wrapper component for renderSlot.
123
- * Uses forwardRef to support ref forwarding.
124
- */
125
- const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function MemoizedSlotWrapper(props, ref) {
126
- const { $slot, $component, ...rest } = props;
127
- return renderSlotElement($slot, $component, ref !== null ? {
128
- ...rest,
129
- ref
130
- } : rest);
131
- }), (prev, next) => {
132
- if (prev.$slot !== next.$slot) return false;
133
- if (prev.$component !== next.$component) return false;
134
- const { $slot: _ps, $component: _pc, ...prevRest } = prev;
135
- const { $slot: _ns, $component: _nc, ...nextRest } = next;
136
- return shallowEqual(prevRest, nextRest);
137
- });
138
- /**
139
- * Renders a slot value as a memoized React element.
140
- * Automatically prevents unnecessary re-renders using shallow prop comparison.
141
- * Supports ref forwarding.
142
- *
143
- * @example
144
- * renderSlot(customInput, CopilotChatInput, { onSubmit: handleSubmit })
145
- */
146
- function renderSlot(slot, DefaultComponent, props) {
147
- return react.default.createElement(MemoizedSlotWrapper, {
148
- ...props,
149
- $slot: slot,
150
- $component: DefaultComponent
151
- });
152
- }
153
95
 
154
96
  //#endregion
155
97
  //#region src/v2/providers/CopilotChatConfigurationProvider.tsx
@@ -357,9 +299,9 @@ const useCopilotChatConfiguration = () => {
357
299
 
358
300
  //#endregion
359
301
  //#region src/v2/lib/utils.ts
360
- const twMerge$8 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
302
+ const twMerge$9 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
361
303
  function cn(...inputs) {
362
- return twMerge$8((0, clsx.clsx)(inputs));
304
+ return twMerge$9((0, clsx.clsx)(inputs));
363
305
  }
364
306
 
365
307
  //#endregion
@@ -453,12 +395,13 @@ function Tooltip({ ...props }) {
453
395
  ...props
454
396
  }) });
455
397
  }
456
- function TooltipTrigger({ ...props }) {
398
+ const TooltipTrigger = react.forwardRef(function TooltipTrigger({ ...props }, ref) {
457
399
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Trigger, {
400
+ ref,
458
401
  "data-slot": "tooltip-trigger",
459
402
  ...props
460
403
  });
461
- }
404
+ });
462
405
  function TooltipContent({ className, sideOffset = 0, children, ...props }) {
463
406
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_tooltip.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_radix_ui_react_tooltip.Content, {
464
407
  "data-copilotkit": true,
@@ -478,12 +421,13 @@ function DropdownMenu({ ...props }) {
478
421
  ...props
479
422
  });
480
423
  }
481
- function DropdownMenuTrigger({ ...props }) {
424
+ const DropdownMenuTrigger = react.forwardRef(function DropdownMenuTrigger({ ...props }, ref) {
482
425
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Trigger, {
426
+ ref,
483
427
  "data-slot": "dropdown-menu-trigger",
484
428
  ...props
485
429
  });
486
- }
430
+ });
487
431
  function DropdownMenuContent({ className, sideOffset = 4, ...props }) {
488
432
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Portal, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_radix_ui_react_dropdown_menu.Content, {
489
433
  "data-copilotkit": true,
@@ -732,6 +676,67 @@ const CopilotChatAudioRecorder = (0, react.forwardRef)((props, ref) => {
732
676
  });
733
677
  CopilotChatAudioRecorder.displayName = "CopilotChatAudioRecorder";
734
678
 
679
+ //#endregion
680
+ //#region src/v2/lib/slots.tsx
681
+ /**
682
+ * Check if a value is a React component type (function, class, forwardRef, memo, etc.)
683
+ */
684
+ function isReactComponentType(value) {
685
+ if (typeof value === "function") return true;
686
+ if (value && typeof value === "object" && "$$typeof" in value && !react.default.isValidElement(value)) return true;
687
+ return false;
688
+ }
689
+ /**
690
+ * Internal function to render a slot value as a React element (non-memoized).
691
+ */
692
+ function renderSlotElement(slot, DefaultComponent, props) {
693
+ if (typeof slot === "string") {
694
+ const existingClassName = props.className;
695
+ return react.default.createElement(DefaultComponent, {
696
+ ...props,
697
+ className: (0, tailwind_merge.twMerge)(existingClassName, slot)
698
+ });
699
+ }
700
+ if (isReactComponentType(slot)) return react.default.createElement(slot, props);
701
+ if (slot && typeof slot === "object" && !react.default.isValidElement(slot)) return react.default.createElement(DefaultComponent, {
702
+ ...props,
703
+ ...slot
704
+ });
705
+ return react.default.createElement(DefaultComponent, props);
706
+ }
707
+ /**
708
+ * Internal memoized wrapper component for renderSlot.
709
+ * Uses forwardRef to support ref forwarding.
710
+ */
711
+ const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function MemoizedSlotWrapper(props, ref) {
712
+ const { $slot, $component, ...rest } = props;
713
+ return renderSlotElement($slot, $component, ref !== null ? {
714
+ ...rest,
715
+ ref
716
+ } : rest);
717
+ }), (prev, next) => {
718
+ if (prev.$slot !== next.$slot) return false;
719
+ if (prev.$component !== next.$component) return false;
720
+ const { $slot: _ps, $component: _pc, ...prevRest } = prev;
721
+ const { $slot: _ns, $component: _nc, ...nextRest } = next;
722
+ return shallowEqual(prevRest, nextRest);
723
+ });
724
+ /**
725
+ * Renders a slot value as a memoized React element.
726
+ * Automatically prevents unnecessary re-renders using shallow prop comparison.
727
+ * Supports ref forwarding.
728
+ *
729
+ * @example
730
+ * renderSlot(customInput, CopilotChatInput, { onSubmit: handleSubmit })
731
+ */
732
+ function renderSlot(slot, DefaultComponent, props) {
733
+ return react.default.createElement(MemoizedSlotWrapper, {
734
+ ...props,
735
+ $slot: slot,
736
+ $component: DefaultComponent
737
+ });
738
+ }
739
+
735
740
  //#endregion
736
741
  //#region src/v2/components/chat/CopilotChatInput.tsx
737
742
  const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
@@ -1085,7 +1090,6 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
1085
1090
  }
1086
1091
  if (typeof window !== "undefined" && typeof window.matchMedia === "function") {
1087
1092
  if (window.matchMedia("(max-width: 767px)").matches) {
1088
- ensureMeasurements();
1089
1093
  adjustTextareaHeight();
1090
1094
  updateLayout("expanded");
1091
1095
  return;
@@ -4426,11 +4430,14 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4426
4430
  const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
4427
4431
  const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
4428
4432
  const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
4429
- const agent = (0, react.useMemo)(() => {
4433
+ const { agent, isReady } = (0, react.useMemo)(() => {
4430
4434
  const existing = copilotkit.getAgent(resolvedAgentId);
4431
4435
  if (existing) {
4432
4436
  provisionalAgentCache.current.delete(resolvedAgentId);
4433
- return existing;
4437
+ return {
4438
+ agent: existing,
4439
+ isReady: true
4440
+ };
4434
4441
  }
4435
4442
  const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
4436
4443
  const status = copilotkit.runtimeConnectionStatus;
@@ -4438,7 +4445,10 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4438
4445
  const cached = provisionalAgentCache.current.get(resolvedAgentId);
4439
4446
  if (cached) {
4440
4447
  copilotkit.applyHeadersToAgent(cached);
4441
- return cached;
4448
+ return {
4449
+ agent: cached,
4450
+ isReady: false
4451
+ };
4442
4452
  }
4443
4453
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4444
4454
  runtimeUrl: copilotkit.runtimeUrl,
@@ -4448,13 +4458,19 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4448
4458
  });
4449
4459
  copilotkit.applyHeadersToAgent(provisional);
4450
4460
  provisionalAgentCache.current.set(resolvedAgentId, provisional);
4451
- return provisional;
4461
+ return {
4462
+ agent: provisional,
4463
+ isReady: false
4464
+ };
4452
4465
  }
4453
4466
  if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
4454
4467
  const cached = provisionalAgentCache.current.get(resolvedAgentId);
4455
4468
  if (cached) {
4456
4469
  copilotkit.applyHeadersToAgent(cached);
4457
- return cached;
4470
+ return {
4471
+ agent: cached,
4472
+ isReady: false
4473
+ };
4458
4474
  }
4459
4475
  const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4460
4476
  runtimeUrl: copilotkit.runtimeUrl,
@@ -4464,7 +4480,10 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4464
4480
  });
4465
4481
  copilotkit.applyHeadersToAgent(provisional);
4466
4482
  provisionalAgentCache.current.set(resolvedAgentId, provisional);
4467
- return provisional;
4483
+ return {
4484
+ agent: provisional,
4485
+ isReady: false
4486
+ };
4468
4487
  }
4469
4488
  const knownAgents = Object.keys(copilotkit.agents ?? {});
4470
4489
  const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
@@ -4525,7 +4544,10 @@ function useAgent({ agentId, updates, throttleMs } = {}) {
4525
4544
  configThreadId,
4526
4545
  configHasExplicitThreadId
4527
4546
  ]);
4528
- return { agent };
4547
+ return {
4548
+ agent,
4549
+ isReady
4550
+ };
4529
4551
  }
4530
4552
 
4531
4553
  //#endregion
@@ -4833,8 +4855,9 @@ function useInterrupt(config) {
4833
4855
  const pendingRef = (0, react.useRef)(pending);
4834
4856
  pendingRef.current = pending;
4835
4857
  const [handlerResult, setHandlerResult] = (0, react.useState)(null);
4836
- const responsesRef = (0, react.useRef)({});
4858
+ const interruptStateRef = (0, react.useRef)(new _copilotkit_core.ɵInterruptState());
4837
4859
  (0, react.useEffect)(() => {
4860
+ const interruptState = interruptStateRef.current;
4838
4861
  let localLegacy = null;
4839
4862
  let localStandard = null;
4840
4863
  const subscription = agent.subscribe({
@@ -4850,106 +4873,111 @@ function useInterrupt(config) {
4850
4873
  onRunStartedEvent: () => {
4851
4874
  localLegacy = null;
4852
4875
  localStandard = null;
4853
- responsesRef.current = {};
4876
+ interruptState.clear();
4854
4877
  setPending(null);
4855
4878
  },
4856
4879
  onRunFinalized: () => {
4857
- if (localStandard && localStandard.length > 0) setPending({
4858
- kind: "standard",
4859
- interrupts: localStandard
4860
- });
4861
- else if (localLegacy) setPending({
4862
- kind: "legacy",
4863
- event: localLegacy
4864
- });
4880
+ if (localStandard && localStandard.length > 0) {
4881
+ interruptState.setStandard(localStandard);
4882
+ setPending(interruptState.pending);
4883
+ } else if (localLegacy) {
4884
+ interruptState.setLegacy(localLegacy);
4885
+ setPending(interruptState.pending);
4886
+ }
4865
4887
  localLegacy = null;
4866
4888
  localStandard = null;
4867
4889
  },
4868
4890
  onRunFailed: () => {
4869
4891
  localLegacy = null;
4870
4892
  localStandard = null;
4871
- responsesRef.current = {};
4893
+ interruptState.clear();
4872
4894
  setPending(null);
4873
4895
  }
4874
4896
  });
4875
- return () => subscription.unsubscribe();
4897
+ return () => {
4898
+ subscription.unsubscribe();
4899
+ interruptState.clear();
4900
+ };
4876
4901
  }, [agent]);
4877
- const submitStandardIfComplete = (0, react.useCallback)(async (interrupts) => {
4878
- if (!interrupts.every((i) => responsesRef.current[i.id])) return;
4879
- const expired = interrupts.find((i) => (0, _ag_ui_client.isInterruptExpired)(i));
4880
- if (expired) {
4881
- console.error(`[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`);
4882
- responsesRef.current = {};
4883
- setPending(null);
4884
- return;
4885
- }
4886
- const resume = (0, _ag_ui_client.buildResumeArray)(interrupts, responsesRef.current);
4887
- for (const i of interrupts) {
4888
- if (!i.toolCallId) continue;
4889
- const response = responsesRef.current[i.id];
4890
- const content = response.status === "cancelled" ? { status: "cancelled" } : response.payload ?? { status: "resolved" };
4891
- agent.addMessage({
4892
- id: (0, _ag_ui_client.randomUUID)(),
4893
- role: "tool",
4894
- toolCallId: i.toolCallId,
4895
- content: JSON.stringify(content)
4896
- });
4897
- }
4898
- responsesRef.current = {};
4899
- try {
4902
+ const resolve = (0, react.useCallback)(async (payload, interruptId) => {
4903
+ const current = pendingRef.current;
4904
+ if (!current) return;
4905
+ if (current.kind === "standard" && 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.`);
4906
+ const decision = interruptStateRef.current.resolve(payload, interruptId);
4907
+ if (decision.kind === "legacy-resume") try {
4900
4908
  return await copilotkit.runAgent({
4901
4909
  agent,
4902
- resume
4910
+ forwardedProps: { command: {
4911
+ resume: decision.payload,
4912
+ interruptEvent: decision.interruptValue
4913
+ } }
4903
4914
  });
4904
4915
  } catch (err) {
4905
4916
  console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
4906
4917
  setPending(null);
4907
4918
  throw err;
4908
4919
  }
4909
- }, [agent, copilotkit]);
4910
- const resolve = (0, react.useCallback)(async (payload, interruptId) => {
4911
- const current = pendingRef.current;
4912
- if (!current) return;
4913
- if (current.kind === "legacy") try {
4920
+ if (decision.kind === "expired") {
4921
+ console.error(`[CopilotKit] useInterrupt: interrupt ${decision.interrupt.id} expired at ${decision.interrupt.expiresAt}; not resuming.`);
4922
+ interruptStateRef.current.clear();
4923
+ setPending(null);
4924
+ return;
4925
+ }
4926
+ if (decision.kind !== "resume") return;
4927
+ for (const toolResult of decision.toolResults) agent.addMessage({
4928
+ id: (0, _ag_ui_client.randomUUID)(),
4929
+ role: "tool",
4930
+ toolCallId: toolResult.toolCallId,
4931
+ content: toolResult.content
4932
+ });
4933
+ try {
4914
4934
  return await copilotkit.runAgent({
4915
4935
  agent,
4916
- forwardedProps: { command: {
4917
- resume: payload,
4918
- interruptEvent: current.event.value
4919
- } }
4936
+ resume: decision.resume
4920
4937
  });
4921
4938
  } catch (err) {
4922
4939
  console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
4940
+ interruptStateRef.current.clear();
4923
4941
  setPending(null);
4924
4942
  throw err;
4925
4943
  }
4926
- 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.`);
4927
- const id = interruptId ?? current.interrupts[0]?.id;
4928
- if (!id) return;
4929
- responsesRef.current[id] = {
4930
- status: "resolved",
4931
- payload
4932
- };
4933
- return submitStandardIfComplete(current.interrupts);
4934
- }, [
4935
- agent,
4936
- copilotkit,
4937
- submitStandardIfComplete
4938
- ]);
4944
+ }, [agent, copilotkit]);
4939
4945
  const cancel = (0, react.useCallback)(async (interruptId) => {
4940
4946
  const current = pendingRef.current;
4941
4947
  if (!current) return;
4942
- if (current.kind === "legacy") {
4948
+ if (current.kind === "standard" && 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.`);
4949
+ const decision = interruptStateRef.current.cancel(interruptId);
4950
+ if (decision.kind === "dismiss") {
4943
4951
  console.warn("[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.");
4952
+ interruptStateRef.current.clear();
4944
4953
  setPending(null);
4945
4954
  return;
4946
4955
  }
4947
- 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.`);
4948
- const id = interruptId ?? current.interrupts[0]?.id;
4949
- if (!id) return;
4950
- responsesRef.current[id] = { status: "cancelled" };
4951
- return submitStandardIfComplete(current.interrupts);
4952
- }, [submitStandardIfComplete]);
4956
+ if (decision.kind === "expired") {
4957
+ console.error(`[CopilotKit] useInterrupt: interrupt ${decision.interrupt.id} expired at ${decision.interrupt.expiresAt}; not resuming.`);
4958
+ interruptStateRef.current.clear();
4959
+ setPending(null);
4960
+ return;
4961
+ }
4962
+ if (decision.kind !== "resume") return;
4963
+ for (const toolResult of decision.toolResults) agent.addMessage({
4964
+ id: (0, _ag_ui_client.randomUUID)(),
4965
+ role: "tool",
4966
+ toolCallId: toolResult.toolCallId,
4967
+ content: toolResult.content
4968
+ });
4969
+ try {
4970
+ return await copilotkit.runAgent({
4971
+ agent,
4972
+ resume: decision.resume
4973
+ });
4974
+ } catch (err) {
4975
+ console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
4976
+ interruptStateRef.current.clear();
4977
+ setPending(null);
4978
+ throw err;
4979
+ }
4980
+ }, [agent, copilotkit]);
4953
4981
  const renderRef = (0, react.useRef)(config.render);
4954
4982
  renderRef.current = config.render;
4955
4983
  const enabledRef = (0, react.useRef)(config.enabled);
@@ -4991,7 +5019,7 @@ function useInterrupt(config) {
4991
5019
  maybePromise = handler({
4992
5020
  event: legacyEvent,
4993
5021
  interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
4994
- interrupts: pending.kind === "standard" ? pending.interrupts : [],
5022
+ interrupts: pending.kind === "standard" ? [...pending.interrupts] : [],
4995
5023
  resolve: resolveRef.current,
4996
5024
  cancel: cancelRef.current
4997
5025
  });
@@ -5020,7 +5048,7 @@ function useInterrupt(config) {
5020
5048
  return renderRef.current({
5021
5049
  event: legacyEvent,
5022
5050
  interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
5023
- interrupts: pending.kind === "standard" ? pending.interrupts : [],
5051
+ interrupts: pending.kind === "standard" ? [...pending.interrupts] : [],
5024
5052
  result: handlerResult,
5025
5053
  resolve,
5026
5054
  cancel
@@ -12148,4 +12176,4 @@ Object.defineProperty(exports, 'ɵrunMcpFollowUp', {
12148
12176
  return ɵrunMcpFollowUp;
12149
12177
  }
12150
12178
  });
12151
- //# sourceMappingURL=copilotkit-nu7NwzH6.cjs.map
12179
+ //# sourceMappingURL=copilotkit-rYTwMndy.cjs.map