@copilotkit/react-core 1.70.1 → 1.70.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.
@@ -298,6 +298,62 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
298
298
  const useCopilotChatConfiguration = () => {
299
299
  return (0, react.useContext)(CopilotChatConfiguration);
300
300
  };
301
+ /**
302
+ * Reports modal open/close requests to the host, and — when `open` is
303
+ * supplied — makes the modal state of an already-established chat
304
+ * configuration **controlled** for the subtree it wraps.
305
+ *
306
+ * This is deliberately a scope component rather than another mode inside
307
+ * {@link CopilotChatConfigurationProvider}. The provider resolves modal state
308
+ * across a nested chain (own state, parent sync, drawer mutual-exclusion, the
309
+ * modal-closer registry); a controlled branch inside that resolution would add
310
+ * a fourth interacting mode. Overriding the context for the subtree instead
311
+ * leaves every one of those paths untouched:
312
+ *
313
+ * - `isModalOpen` is replaced with the host's `open`, so the rendered surface
314
+ * follows the prop from the very first frame (no open-then-close flash).
315
+ * - `setModalOpen` still calls the underlying setter, so the existing
316
+ * parent-sync and drawer mutual-exclusion side effects continue to run, and
317
+ * *then* reports the request through `onOpenChange`.
318
+ * - The wrapped setter is registered as the modal closer, so the drawer's
319
+ * mobile mutual-exclusion reaches the host instead of silently flipping
320
+ * state that nothing displays.
321
+ *
322
+ * A host that supplies `open` and ignores `onOpenChange` gets a modal pinned
323
+ * to `open`, which is the standard controlled-component contract. A host that
324
+ * supplies only `onOpenChange` is notified while the modal keeps managing
325
+ * itself.
326
+ *
327
+ * Renders `children` unchanged when no chat configuration is in scope.
328
+ */
329
+ const ControlledModalOpenScope = ({ children, open, onOpenChange }) => {
330
+ const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
331
+ const parentSetModalOpen = parentConfig?.setModalOpen;
332
+ const registerModalCloser = parentConfig?.ɵregisterModalCloser;
333
+ const setModalOpen = (0, react.useCallback)((next) => {
334
+ parentSetModalOpen?.(next);
335
+ onOpenChange?.(next);
336
+ }, [parentSetModalOpen, onOpenChange]);
337
+ (0, react.useEffect)(() => {
338
+ if (!registerModalCloser) return;
339
+ return registerModalCloser(setModalOpen);
340
+ }, [registerModalCloser, setModalOpen]);
341
+ const configurationValue = (0, react.useMemo)(() => parentConfig ? {
342
+ ...parentConfig,
343
+ isModalOpen: open ?? parentConfig.isModalOpen,
344
+ setModalOpen
345
+ } : null, [
346
+ parentConfig,
347
+ open,
348
+ setModalOpen
349
+ ]);
350
+ if (!configurationValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
351
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
352
+ value: configurationValue,
353
+ children
354
+ });
355
+ };
356
+ ControlledModalOpenScope.displayName = "ControlledModalOpenScope";
301
357
 
302
358
  //#endregion
303
359
  //#region src/v2/lib/utils.ts
@@ -5424,7 +5480,7 @@ function useMemories() {
5424
5480
  * at the call site.
5425
5481
  */
5426
5482
  async function recordAnnotation(args) {
5427
- const { runtimeUrl, headers, type, payload, threadId, occurredAt } = args;
5483
+ const { runtimeUrl, headers, type, payload, threadId, occurredAt, fetch: fetchImplementation = globalThis.fetch } = args;
5428
5484
  const body = {
5429
5485
  type,
5430
5486
  threadId,
@@ -5432,7 +5488,7 @@ async function recordAnnotation(args) {
5432
5488
  ...payload !== void 0 ? { payload } : {},
5433
5489
  ...occurredAt !== void 0 ? { occurredAt } : {}
5434
5490
  };
5435
- const response = await fetch(`${runtimeUrl}/annotate`, {
5491
+ const response = await fetchImplementation(`${runtimeUrl}/annotate`, {
5436
5492
  method: "POST",
5437
5493
  headers: {
5438
5494
  "Content-Type": "application/json",
@@ -5501,6 +5557,7 @@ function useLearnFromUserAction() {
5501
5557
  ...input.data !== void 0 ? { data: input.data } : {}
5502
5558
  };
5503
5559
  return recordAnnotation({
5560
+ fetch: copilotkit.ɵruntimeFetch,
5504
5561
  runtimeUrl,
5505
5562
  headers: copilotkit.headers ?? {},
5506
5563
  type: "user_action",
@@ -5570,6 +5627,21 @@ function useLearnFromUserActionInCurrentThread() {
5570
5627
 
5571
5628
  //#endregion
5572
5629
  //#region src/v2/hooks/use-attachments.tsx
5630
+ const DEFAULT_MAX_SIZE = 20 * 1024 * 1024;
5631
+ /**
5632
+ * How many uploads run at once when `maxConcurrentUploads` is unset. One, because
5633
+ * `onUpload` is a public callback an app may have written expecting the previous
5634
+ * file to have finished — concurrency is something the app asks for.
5635
+ */
5636
+ const DEFAULT_MAX_CONCURRENT_UPLOADS = 1;
5637
+ /**
5638
+ * At least one upload at a time, whole files only; `NaN` or a non-number falls back to the
5639
+ * default, and `Infinity` means "no limit" — bounded in practice by how many files are queued.
5640
+ */
5641
+ function resolveMaxConcurrentUploads(configured) {
5642
+ if (typeof configured !== "number" || Number.isNaN(configured)) return DEFAULT_MAX_CONCURRENT_UPLOADS;
5643
+ return Math.max(1, Math.floor(configured));
5644
+ }
5573
5645
  /**
5574
5646
  * Hook that manages file attachment state — uploads, drag-and-drop, paste,
5575
5647
  * and lifecycle. All returned callbacks are referentially stable across
@@ -5585,10 +5657,62 @@ function useAttachments({ config }) {
5585
5657
  configRef.current = config;
5586
5658
  const attachmentsRef = (0, react.useRef)([]);
5587
5659
  attachmentsRef.current = attachments;
5660
+ const uploadQueueRef = (0, react.useRef)([]);
5661
+ const activeWorkersRef = (0, react.useRef)(0);
5662
+ const uploadFile = (0, react.useCallback)(async (file, placeholder, cfg) => {
5663
+ try {
5664
+ let source;
5665
+ let uploadMetadata;
5666
+ if (cfg?.onUpload) {
5667
+ const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
5668
+ source = uploadSource;
5669
+ uploadMetadata = meta;
5670
+ } else source = {
5671
+ type: "data",
5672
+ value: await (0, _copilotkit_shared.readFileAsBase64)(file),
5673
+ mimeType: file.type
5674
+ };
5675
+ let thumbnail;
5676
+ if (placeholder.type === "video") thumbnail = await (0, _copilotkit_shared.generateVideoThumbnail)(file);
5677
+ setAttachments((prev) => prev.map((att) => att.id === placeholder.id ? {
5678
+ ...att,
5679
+ source,
5680
+ status: "ready",
5681
+ thumbnail,
5682
+ metadata: uploadMetadata
5683
+ } : att));
5684
+ } catch (error) {
5685
+ setAttachments((prev) => prev.filter((att) => att.id !== placeholder.id));
5686
+ console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
5687
+ cfg?.onUploadFailed?.({
5688
+ reason: "upload-failed",
5689
+ file,
5690
+ message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
5691
+ });
5692
+ }
5693
+ }, []);
5694
+ const drainUploadQueue = (0, react.useCallback)(async () => {
5695
+ activeWorkersRef.current++;
5696
+ try {
5697
+ for (;;) {
5698
+ const item = uploadQueueRef.current.shift();
5699
+ if (!item) return;
5700
+ try {
5701
+ await uploadFile(item.file, item.placeholder, item.cfg);
5702
+ } catch (error) {
5703
+ console.error("[CopilotKit] Upload worker error:", error);
5704
+ } finally {
5705
+ item.settle();
5706
+ }
5707
+ }
5708
+ } finally {
5709
+ activeWorkersRef.current--;
5710
+ }
5711
+ }, [uploadFile]);
5588
5712
  const processFiles = (0, react.useCallback)(async (files) => {
5589
5713
  const cfg = configRef.current;
5590
5714
  const accept = cfg?.accept ?? "*/*";
5591
- const maxSize = cfg?.maxSize ?? 20 * 1024 * 1024;
5715
+ const maxSize = cfg?.maxSize ?? DEFAULT_MAX_SIZE;
5592
5716
  const rejectedFiles = files.filter((file) => !(0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
5593
5717
  for (const file of rejectedFiles) cfg?.onUploadFailed?.({
5594
5718
  reason: "invalid-type",
@@ -5596,6 +5720,7 @@ function useAttachments({ config }) {
5596
5720
  message: `File "${file.name}" is not accepted. Supported types: ${accept}`
5597
5721
  });
5598
5722
  const validFiles = files.filter((file) => (0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
5723
+ const queued = [];
5599
5724
  for (const file of validFiles) {
5600
5725
  if ((0, _copilotkit_shared.exceedsMaxSize)(file, maxSize)) {
5601
5726
  cfg?.onUploadFailed?.({
@@ -5605,53 +5730,37 @@ function useAttachments({ config }) {
5605
5730
  });
5606
5731
  continue;
5607
5732
  }
5608
- const modality = (0, _copilotkit_shared.getModalityFromMimeType)(file.type);
5609
- const placeholderId = (0, _copilotkit_shared.randomUUID)();
5610
- const placeholder = {
5611
- id: placeholderId,
5612
- type: modality,
5613
- source: {
5614
- type: "data",
5615
- value: "",
5616
- mimeType: file.type
5617
- },
5618
- filename: file.name,
5619
- size: file.size,
5620
- status: "uploading"
5621
- };
5622
- setAttachments((prev) => [...prev, placeholder]);
5623
- try {
5624
- let source;
5625
- let uploadMetadata;
5626
- if (cfg?.onUpload) {
5627
- const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
5628
- source = uploadSource;
5629
- uploadMetadata = meta;
5630
- } else source = {
5631
- type: "data",
5632
- value: await (0, _copilotkit_shared.readFileAsBase64)(file),
5633
- mimeType: file.type
5634
- };
5635
- let thumbnail;
5636
- if (modality === "video") thumbnail = await (0, _copilotkit_shared.generateVideoThumbnail)(file);
5637
- setAttachments((prev) => prev.map((att) => att.id === placeholderId ? {
5638
- ...att,
5639
- source,
5640
- status: "ready",
5641
- thumbnail,
5642
- metadata: uploadMetadata
5643
- } : att));
5644
- } catch (error) {
5645
- setAttachments((prev) => prev.filter((att) => att.id !== placeholderId));
5646
- console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
5647
- cfg?.onUploadFailed?.({
5648
- reason: "upload-failed",
5649
- file,
5650
- message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
5651
- });
5652
- }
5733
+ queued.push({
5734
+ file,
5735
+ placeholder: {
5736
+ id: (0, _copilotkit_shared.randomUUID)(),
5737
+ type: (0, _copilotkit_shared.getModalityFromMimeType)(file.type),
5738
+ source: {
5739
+ type: "data",
5740
+ value: "",
5741
+ mimeType: file.type
5742
+ },
5743
+ filename: file.name,
5744
+ size: file.size,
5745
+ status: "uploading"
5746
+ }
5747
+ });
5653
5748
  }
5654
- }, []);
5749
+ if (queued.length === 0) return;
5750
+ setAttachments((prev) => [...prev, ...queued.map((q) => q.placeholder)]);
5751
+ const settled = queued.map(({ file, placeholder }) => new Promise((resolve) => {
5752
+ uploadQueueRef.current.push({
5753
+ file,
5754
+ placeholder,
5755
+ cfg,
5756
+ settle: resolve
5757
+ });
5758
+ }));
5759
+ const limit = resolveMaxConcurrentUploads(cfg?.maxConcurrentUploads);
5760
+ const toSpawn = Math.min(uploadQueueRef.current.length, Math.max(0, limit - activeWorkersRef.current));
5761
+ for (let i = 0; i < toSpawn; i++) drainUploadQueue();
5762
+ await Promise.all(settled);
5763
+ }, [drainUploadQueue]);
5655
5764
  const handleFileUpload = (0, react.useCallback)(async (e) => {
5656
5765
  if (!e.target.files?.length) return;
5657
5766
  try {
@@ -5779,8 +5888,10 @@ function useLearningContainers({ threadId, learningContainers }) {
5779
5888
  const warnedMissingUrlRef = (0, react.useRef)(false);
5780
5889
  const runtimeUrlRef = (0, react.useRef)(copilotkit.runtimeUrl);
5781
5890
  const headersRef = (0, react.useRef)(copilotkit.headers ?? {});
5891
+ const runtimeFetchRef = (0, react.useRef)(copilotkit.ɵruntimeFetch);
5782
5892
  runtimeUrlRef.current = copilotkit.runtimeUrl;
5783
5893
  headersRef.current = copilotkit.headers ?? {};
5894
+ runtimeFetchRef.current = copilotkit.ɵruntimeFetch;
5784
5895
  const key = JSON.stringify(learningContainers);
5785
5896
  const defaultKey = JSON.stringify(DEFAULT_CONTAINERS);
5786
5897
  (0, react.useEffect)(() => {
@@ -5800,6 +5911,7 @@ function useLearningContainers({ threadId, learningContainers }) {
5800
5911
  return;
5801
5912
  }
5802
5913
  recordAnnotation({
5914
+ fetch: copilotkit.ɵruntimeFetch,
5803
5915
  runtimeUrl,
5804
5916
  headers,
5805
5917
  type: "set_learning_containers",
@@ -5827,6 +5939,7 @@ function useLearningContainers({ threadId, learningContainers }) {
5827
5939
  const capturedRuntimeUrl = runtimeUrlRef.current;
5828
5940
  const capturedHeaders = headersRef.current;
5829
5941
  if (capturedRuntimeUrl) recordAnnotation({
5942
+ fetch: runtimeFetchRef.current,
5830
5943
  runtimeUrl: capturedRuntimeUrl,
5831
5944
  headers: capturedHeaders,
5832
5945
  type: "set_learning_containers",
@@ -9089,6 +9202,41 @@ const CopilotChatToggleButton = react.default.forwardRef(function CopilotChatTog
9089
9202
  });
9090
9203
  CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
9091
9204
 
9205
+ //#endregion
9206
+ //#region src/v2/components/chat/modal-open-control.tsx
9207
+ const ModalOpenControlContext = (0, react.createContext)({});
9208
+ /**
9209
+ * Carries `open` / `onOpenChange` from a prebuilt surface down to the view that
9210
+ * owns the modal state.
9211
+ *
9212
+ * A context is required rather than plain props because `<CopilotSidebar>`
9213
+ * hands its view to `<CopilotChat>` as a `chatView` **component**. Threading a
9214
+ * value that changes (like `open`) through that component's identity would mint
9215
+ * a new element type on every toggle, and React unmounts and remounts the whole
9216
+ * chat subtree when the element type changes. That is the remount class of bug
9217
+ * already fixed for `<CopilotPopup>` on resize. Context keeps the override
9218
+ * identity stable while still re-rendering the view when `open` changes.
9219
+ */
9220
+ function ModalOpenControlProvider({ open, onOpenChange, children }) {
9221
+ const value = (0, react.useMemo)(() => ({
9222
+ open,
9223
+ onOpenChange
9224
+ }), [open, onOpenChange]);
9225
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlContext.Provider, {
9226
+ value,
9227
+ children
9228
+ });
9229
+ }
9230
+ /**
9231
+ * Reads the controlled open state supplied by the surrounding prebuilt
9232
+ * surface. Returns an empty control (uncontrolled) when there is none.
9233
+ *
9234
+ * @returns The host's `open` / `onOpenChange` pair.
9235
+ */
9236
+ function useModalOpenControl() {
9237
+ return (0, react.useContext)(ModalOpenControlContext);
9238
+ }
9239
+
9092
9240
  //#endregion
9093
9241
  //#region src/v2/components/chat/CopilotModalHeader.tsx
9094
9242
  /**
@@ -9198,15 +9346,22 @@ CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLaunch
9198
9346
  const DEFAULT_SIDEBAR_WIDTH = 480;
9199
9347
  const SIDEBAR_TRANSITION_MS = 260;
9200
9348
  function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
9349
+ const { open, onOpenChange } = useModalOpenControl();
9350
+ const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
9351
+ const internal = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarViewInternal, {
9352
+ header,
9353
+ toggleButton,
9354
+ width,
9355
+ position,
9356
+ ...props
9357
+ });
9201
9358
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
9202
- isModalDefaultOpen: defaultOpen,
9203
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarViewInternal, {
9204
- header,
9205
- toggleButton,
9206
- width,
9207
- position,
9208
- ...props
9209
- })
9359
+ isModalDefaultOpen: open ?? defaultOpen,
9360
+ children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
9361
+ open,
9362
+ onOpenChange,
9363
+ children: internal
9364
+ }) : internal
9210
9365
  });
9211
9366
  }
9212
9367
  function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
@@ -9270,7 +9425,7 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "r
9270
9425
  "data-position": position,
9271
9426
  className: cn("copilotKitSidebar copilotKitWindow", "cpk:fixed cpk:top-0 cpk:z-[1200] cpk:flex", position === "left" ? "cpk:left-0" : "cpk:right-0", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", position === "left" ? "cpk:border-r" : "cpk:border-l", "cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl", "cpk:transition-transform cpk:duration-300 cpk:ease-out", isSidebarOpen ? "cpk:translate-x-0" : position === "left" ? "cpk:-translate-x-full cpk:pointer-events-none" : "cpk:translate-x-full cpk:pointer-events-none"),
9272
9427
  style: {
9273
- ["--sidebar-width"]: widthToCss(sidebarWidth),
9428
+ "--sidebar-width": widthToCss(sidebarWidth),
9274
9429
  paddingTop: "env(safe-area-inset-top)",
9275
9430
  paddingBottom: "env(safe-area-inset-bottom)"
9276
9431
  },
@@ -9332,17 +9487,24 @@ const dimensionToCss = (value, fallback) => {
9332
9487
  return `${fallback}px`;
9333
9488
  };
9334
9489
  function CopilotPopupView({ header, toggleButton, width, height, clickOutsideToClose, defaultOpen = true, className, ...restProps }) {
9490
+ const { open, onOpenChange } = useModalOpenControl();
9491
+ const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
9492
+ const internal = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotPopupViewInternal, {
9493
+ header,
9494
+ toggleButton,
9495
+ width,
9496
+ height,
9497
+ clickOutsideToClose,
9498
+ className,
9499
+ ...restProps
9500
+ });
9335
9501
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
9336
- isModalDefaultOpen: defaultOpen,
9337
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotPopupViewInternal, {
9338
- header,
9339
- toggleButton,
9340
- width,
9341
- height,
9342
- clickOutsideToClose,
9343
- className,
9344
- ...restProps
9345
- })
9502
+ isModalDefaultOpen: open ?? defaultOpen,
9503
+ children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
9504
+ open,
9505
+ onOpenChange,
9506
+ children: internal
9507
+ }) : internal
9346
9508
  });
9347
9509
  }
9348
9510
  function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOutsideToClose, className, ...restProps }) {
@@ -9475,7 +9637,7 @@ var CopilotPopupView_default = CopilotPopupView;
9475
9637
 
9476
9638
  //#endregion
9477
9639
  //#region src/v2/components/chat/CopilotSidebar.tsx
9478
- function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ...chatProps }) {
9640
+ function CopilotSidebar({ header, toggleButton, defaultOpen, open, onOpenChange, width, position, ...chatProps }) {
9479
9641
  const { checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
9480
9642
  const isSidebarLicensed = checkFeature("sidebar");
9481
9643
  (0, react.useEffect)(() => {
@@ -9501,11 +9663,15 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ..
9501
9663
  defaultOpen,
9502
9664
  position
9503
9665
  ]);
9504
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isSidebarLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9505
- welcomeScreen: CopilotSidebarView.WelcomeScreen,
9506
- ...chatProps,
9507
- isModalDefaultOpen: defaultOpen,
9508
- chatView: SidebarViewOverride
9666
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isSidebarLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlProvider, {
9667
+ open,
9668
+ onOpenChange,
9669
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9670
+ welcomeScreen: CopilotSidebarView.WelcomeScreen,
9671
+ ...chatProps,
9672
+ isModalDefaultOpen: defaultOpen,
9673
+ chatView: SidebarViewOverride
9674
+ })
9509
9675
  })] });
9510
9676
  }
9511
9677
  CopilotSidebar.displayName = "CopilotSidebar";
@@ -9527,7 +9693,7 @@ const PopupViewOverride = (viewProps) => {
9527
9693
  });
9528
9694
  };
9529
9695
  const PopupViewOverrideWithStatics = Object.assign(PopupViewOverride, CopilotChatView_default);
9530
- function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickOutsideToClose, ...chatProps }) {
9696
+ function CopilotPopup({ header, toggleButton, defaultOpen, open, onOpenChange, width, height, clickOutsideToClose, ...chatProps }) {
9531
9697
  const { checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
9532
9698
  const isPopupLicensed = checkFeature("popup");
9533
9699
  (0, react.useEffect)(() => {
@@ -9550,11 +9716,15 @@ function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickO
9550
9716
  ]);
9551
9717
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isPopupLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Popup" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PopupShellPropsContext.Provider, {
9552
9718
  value: shellProps,
9553
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9554
- welcomeScreen: CopilotPopupView_default.WelcomeScreen,
9555
- ...chatProps,
9556
- isModalDefaultOpen: defaultOpen,
9557
- chatView: PopupViewOverrideWithStatics
9719
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlProvider, {
9720
+ open,
9721
+ onOpenChange,
9722
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
9723
+ welcomeScreen: CopilotPopupView_default.WelcomeScreen,
9724
+ ...chatProps,
9725
+ isModalDefaultOpen: defaultOpen,
9726
+ chatView: PopupViewOverrideWithStatics
9727
+ })
9558
9728
  })
9559
9729
  })] });
9560
9730
  }
@@ -12623,4 +12793,4 @@ Object.defineProperty(exports, 'ɵrunMcpFollowUp', {
12623
12793
  return ɵrunMcpFollowUp;
12624
12794
  }
12625
12795
  });
12626
- //# sourceMappingURL=copilotkit-CxLT6zFx.cjs.map
12796
+ //# sourceMappingURL=copilotkit-DcFo270Y.cjs.map