@copilotkit/react-core 1.61.2 → 1.62.1

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 (34) hide show
  1. package/dist/{copilotkit-Be-o2UaU.mjs → copilotkit-BtRkFsNR.mjs} +941 -404
  2. package/dist/copilotkit-BtRkFsNR.mjs.map +1 -0
  3. package/dist/{copilotkit-CTCjVxkH.cjs → copilotkit-CdpDZi3i.cjs} +943 -400
  4. package/dist/copilotkit-CdpDZi3i.cjs.map +1 -0
  5. package/dist/{copilotkit-ClqbUuGX.d.cts → copilotkit-Cga6AHO0.d.cts} +429 -149
  6. package/dist/copilotkit-Cga6AHO0.d.cts.map +1 -0
  7. package/dist/{copilotkit-Bpt1c_-q.d.mts → copilotkit-DnLpJ2Cl.d.mts} +429 -149
  8. package/dist/copilotkit-DnLpJ2Cl.d.mts.map +1 -0
  9. package/dist/index.cjs +1 -1
  10. package/dist/index.d.cts +1 -1
  11. package/dist/index.d.mts +1 -1
  12. package/dist/index.mjs +1 -1
  13. package/dist/index.umd.js +193 -176
  14. package/dist/index.umd.js.map +1 -1
  15. package/dist/v2/headless.cjs +156 -11
  16. package/dist/v2/headless.cjs.map +1 -1
  17. package/dist/v2/headless.d.cts +111 -1
  18. package/dist/v2/headless.d.cts.map +1 -1
  19. package/dist/v2/headless.d.mts +111 -1
  20. package/dist/v2/headless.d.mts.map +1 -1
  21. package/dist/v2/headless.mjs +157 -12
  22. package/dist/v2/headless.mjs.map +1 -1
  23. package/dist/v2/index.cjs +2 -1
  24. package/dist/v2/index.css +1 -1
  25. package/dist/v2/index.d.cts +2 -2
  26. package/dist/v2/index.d.mts +2 -2
  27. package/dist/v2/index.mjs +2 -2
  28. package/dist/v2/index.umd.js +949 -412
  29. package/dist/v2/index.umd.js.map +1 -1
  30. package/package.json +8 -6
  31. package/dist/copilotkit-Be-o2UaU.mjs.map +0 -1
  32. package/dist/copilotkit-Bpt1c_-q.d.mts.map +0 -1
  33. package/dist/copilotkit-CTCjVxkH.cjs.map +0 -1
  34. package/dist/copilotkit-ClqbUuGX.d.cts.map +0 -1
@@ -1,9 +1,9 @@
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
- import { CopilotKitCore, CopilotKitCoreRuntimeConnectionStatus, ProxiedCopilotRuntimeAgent, ToolCallStatus, isRunCompletionAware, ɵcreateThreadStore, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading } from "@copilotkit/core";
3
+ import { CopilotKitCore, CopilotKitCoreRuntimeConnectionStatus, ProxiedCopilotRuntimeAgent, ToolCallStatus, isRunCompletionAware, ɵcreateThreadStore, ɵselectHasNextPage, ɵselectIsFetchingNextPage, ɵselectIsMutating, ɵselectThreads, ɵselectThreadsError, ɵselectThreadsIsLoading } from "@copilotkit/core";
4
4
  import { HttpAgent, buildResumeArray, isInterruptExpired, randomUUID } from "@ag-ui/client";
5
5
  import { extendTailwindMerge, twMerge } from "tailwind-merge";
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";
6
+ import { ArrowUp, Check, ChevronDown, ChevronLeft, ChevronRight, ChevronRightIcon, Copy, Edit, Loader2, MessageCircle, Mic, PanelLeftOpen, Play, Plus, RefreshCw, Square, ThumbsDown, ThumbsUp, Upload, Volume2, X } from "lucide-react";
7
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";
@@ -19,6 +19,7 @@ import { zodToJsonSchema } from "zod-to-json-schema";
19
19
  import { createPortal, flushSync } from "react-dom";
20
20
  import { useVirtualizer } from "@tanstack/react-virtual";
21
21
  import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
22
+ import { COPILOTKIT_THREADS_DRAWER_TAG, defineCopilotKitThreadsDrawer } from "@copilotkit/web-components/threads-drawer";
22
23
  import ReactMarkdown from "react-markdown";
23
24
 
24
25
  //#region src/v2/lib/slots.tsx
@@ -144,6 +145,25 @@ const CopilotChatDefaultLabels = {
144
145
  modalHeaderTitle: "CopilotKit Chat",
145
146
  welcomeMessageText: "How can I help you today?"
146
147
  };
148
+ /**
149
+ * Mobile breakpoint below which the chat modal and the thread-list drawer are
150
+ * mutually exclusive. At or above this width both surfaces may coexist. This
151
+ * mirrors the `(max-width: 767px)` / `(min-width: 768px)` split already used by
152
+ * CopilotChatInput and CopilotSidebarView.
153
+ */
154
+ const MOBILE_MAX_WIDTH_PX = 767;
155
+ /**
156
+ * Reports whether the current viewport is in the mobile range (`<768px`), where
157
+ * the chat modal and drawer must not be open simultaneously. SSR-safe and
158
+ * defensive against environments without `matchMedia` (treated as desktop, so
159
+ * no mutual-exclusion constraint is applied).
160
+ *
161
+ * @returns `true` when the viewport is mobile-width, `false` otherwise.
162
+ */
163
+ function isMobileViewport() {
164
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
165
+ return window.matchMedia(`(max-width: ${MOBILE_MAX_WIDTH_PX}px)`).matches;
166
+ }
147
167
  const CopilotChatConfiguration = createContext(null);
148
168
  const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, hasExplicitThreadId, isModalDefaultOpen }) => {
149
169
  const parentConfig = useContext(CopilotChatConfiguration);
@@ -154,12 +174,22 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
154
174
  ...stableLabels
155
175
  }), [stableLabels, parentConfig?.labels]);
156
176
  const resolvedAgentId = agentId ?? parentConfig?.agentId ?? DEFAULT_AGENT_ID;
177
+ const threadIdPropIsAuthoritative = threadId !== void 0 && hasExplicitThreadId !== false;
178
+ const isThreadIdControlled = threadIdPropIsAuthoritative;
179
+ const [activeThreadOverride, setActiveThreadOverride] = useState(null);
157
180
  const resolvedThreadId = useMemo(() => {
158
- if (threadId) return threadId;
181
+ if (threadIdPropIsAuthoritative) return threadId;
182
+ if (activeThreadOverride) return activeThreadOverride.threadId;
159
183
  if (parentConfig?.threadId) return parentConfig.threadId;
184
+ if (threadId) return threadId;
160
185
  return randomUUID$1();
161
- }, [threadId, parentConfig?.threadId]);
162
- const resolvedHasExplicitThreadId = (hasExplicitThreadId !== void 0 ? hasExplicitThreadId : !!threadId) || !!parentConfig?.hasExplicitThreadId;
186
+ }, [
187
+ threadIdPropIsAuthoritative,
188
+ threadId,
189
+ parentConfig?.threadId,
190
+ activeThreadOverride
191
+ ]);
192
+ const resolvedHasExplicitThreadId = (threadIdPropIsAuthoritative ? true : activeThreadOverride?.explicit ?? hasExplicitThreadId ?? false) || !!parentConfig?.hasExplicitThreadId;
163
193
  const [internalModalOpen, setInternalModalOpen] = useState(isModalDefaultOpen ?? true);
164
194
  const hasExplicitDefault = isModalDefaultOpen !== void 0;
165
195
  const setAndSync = useCallback((open) => {
@@ -178,20 +208,113 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
178
208
  }, [parentConfig?.isModalOpen, hasExplicitDefault]);
179
209
  const resolvedIsModalOpen = hasExplicitDefault ? internalModalOpen : parentConfig?.isModalOpen ?? internalModalOpen;
180
210
  const resolvedSetModalOpen = hasExplicitDefault ? setAndSync : parentConfig?.setModalOpen ?? setInternalModalOpen;
211
+ const [ownDrawerOpen, setOwnDrawerOpen] = useState(false);
212
+ const [ownDrawerCount, setOwnDrawerCount] = useState(0);
213
+ const modalCloseRef = useRef(() => {});
214
+ modalCloseRef.current = resolvedSetModalOpen;
215
+ const registeredModalClosersRef = useRef([]);
216
+ const ownRegisterModalCloser = useCallback((closeModal) => {
217
+ registeredModalClosersRef.current.push(closeModal);
218
+ return () => {
219
+ registeredModalClosersRef.current = registeredModalClosersRef.current.filter((entry) => entry !== closeModal);
220
+ };
221
+ }, []);
222
+ const ownSetDrawerOpen = useCallback((open) => {
223
+ setOwnDrawerOpen(open);
224
+ if (open && isMobileViewport()) {
225
+ const registered = registeredModalClosersRef.current;
226
+ (registered.length > 0 ? registered[registered.length - 1] : modalCloseRef.current)(false);
227
+ }
228
+ }, []);
229
+ const ownRegisterDrawer = useCallback(() => {
230
+ setOwnDrawerCount((count) => count + 1);
231
+ return () => {
232
+ setOwnDrawerCount((count) => Math.max(0, count - 1));
233
+ };
234
+ }, []);
235
+ const resolvedDrawerOpen = parentConfig ? parentConfig.drawerOpen : ownDrawerOpen;
236
+ const resolvedSetDrawerOpen = parentConfig ? parentConfig.setDrawerOpen : ownSetDrawerOpen;
237
+ const resolvedDrawerRegistered = parentConfig ? parentConfig.drawerRegistered : ownDrawerCount > 0;
238
+ const resolvedRegisterDrawer = parentConfig ? parentConfig.registerDrawer : ownRegisterDrawer;
239
+ const resolvedRegisterModalCloser = parentConfig ? parentConfig.ɵregisterModalCloser : ownRegisterModalCloser;
240
+ useEffect(() => {
241
+ if (!hasExplicitDefault) return;
242
+ return resolvedRegisterModalCloser(resolvedSetModalOpen);
243
+ }, [
244
+ hasExplicitDefault,
245
+ resolvedRegisterModalCloser,
246
+ resolvedSetModalOpen
247
+ ]);
248
+ const isThreadIdControlledRef = useRef(isThreadIdControlled);
249
+ isThreadIdControlledRef.current = isThreadIdControlled;
250
+ const ownSetActiveThreadId = useCallback((id, options) => {
251
+ setActiveThreadOverride({
252
+ threadId: id,
253
+ explicit: options?.explicit ?? true
254
+ });
255
+ }, []);
256
+ const ownStartNewThread = useCallback(() => {
257
+ setActiveThreadOverride({
258
+ threadId: randomUUID$1(),
259
+ explicit: false
260
+ });
261
+ }, []);
262
+ const parentSetActiveThreadId = parentConfig?.setActiveThreadId;
263
+ const parentStartNewThread = parentConfig?.startNewThread;
264
+ const resolvedSetActiveThreadId = useCallback((id, options) => {
265
+ if (isThreadIdControlledRef.current) {
266
+ console.warn("[CopilotKit] Ignoring setActiveThreadId(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
267
+ return;
268
+ }
269
+ if (parentSetActiveThreadId) {
270
+ parentSetActiveThreadId(id, options);
271
+ return;
272
+ }
273
+ ownSetActiveThreadId(id, options);
274
+ }, [parentSetActiveThreadId, ownSetActiveThreadId]);
275
+ const resolvedStartNewThread = useCallback(() => {
276
+ if (isThreadIdControlledRef.current) {
277
+ console.warn("[CopilotKit] Ignoring startNewThread(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
278
+ return;
279
+ }
280
+ if (parentStartNewThread) {
281
+ parentStartNewThread();
282
+ return;
283
+ }
284
+ ownStartNewThread();
285
+ }, [parentStartNewThread, ownStartNewThread]);
286
+ const setModalOpenWithDrawerExclusion = useCallback((open) => {
287
+ if (open && isMobileViewport()) resolvedSetDrawerOpen(false);
288
+ resolvedSetModalOpen(open);
289
+ }, [resolvedSetModalOpen, resolvedSetDrawerOpen]);
181
290
  const configurationValue = useMemo(() => ({
182
291
  labels: mergedLabels,
183
292
  agentId: resolvedAgentId,
184
293
  threadId: resolvedThreadId,
185
294
  hasExplicitThreadId: resolvedHasExplicitThreadId,
186
295
  isModalOpen: resolvedIsModalOpen,
187
- setModalOpen: resolvedSetModalOpen
296
+ setModalOpen: setModalOpenWithDrawerExclusion,
297
+ drawerOpen: resolvedDrawerOpen,
298
+ setDrawerOpen: resolvedSetDrawerOpen,
299
+ drawerRegistered: resolvedDrawerRegistered,
300
+ registerDrawer: resolvedRegisterDrawer,
301
+ ɵregisterModalCloser: resolvedRegisterModalCloser,
302
+ setActiveThreadId: resolvedSetActiveThreadId,
303
+ startNewThread: resolvedStartNewThread
188
304
  }), [
189
305
  mergedLabels,
190
306
  resolvedAgentId,
191
307
  resolvedThreadId,
192
308
  resolvedHasExplicitThreadId,
193
309
  resolvedIsModalOpen,
194
- resolvedSetModalOpen
310
+ setModalOpenWithDrawerExclusion,
311
+ resolvedDrawerOpen,
312
+ resolvedSetDrawerOpen,
313
+ resolvedDrawerRegistered,
314
+ resolvedRegisterDrawer,
315
+ resolvedRegisterModalCloser,
316
+ resolvedSetActiveThreadId,
317
+ resolvedStartNewThread
195
318
  ]);
196
319
  return /* @__PURE__ */ jsx(CopilotChatConfiguration.Provider, {
197
320
  value: configurationValue,
@@ -1112,7 +1235,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
1112
1235
  },
1113
1236
  ...props,
1114
1237
  children: [/* @__PURE__ */ jsx("div", {
1115
- className: "cpk:max-w-3xl cpk:mx-auto cpk:py-0 cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-4 cpk:pointer-events-auto",
1238
+ className: "cpk:max-w-3xl cpk:mx-auto cpk:py-0 cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-4 cpk:pointer-events-auto",
1116
1239
  children: inputPill
1117
1240
  }), shouldShowDisclaimer && BoundDisclaimer]
1118
1241
  });
@@ -1400,307 +1523,25 @@ const useCopilotKit = () => {
1400
1523
  useEffect(() => {
1401
1524
  const subscription = context.copilotkit.subscribe({
1402
1525
  onRuntimeConnectionStatusChanged: () => {
1403
- forceUpdate();
1404
- },
1405
- onHeadersChanged: () => {
1406
- forceUpdate();
1407
- }
1408
- });
1409
- return () => {
1410
- subscription.unsubscribe();
1411
- };
1412
- }, []);
1413
- return context;
1414
- };
1415
- const LicenseContext = createContext({
1416
- status: null,
1417
- license: null,
1418
- checkFeature: () => true,
1419
- getLimit: () => null
1420
- });
1421
- const useLicenseContext = () => useContext(LicenseContext);
1422
-
1423
- //#endregion
1424
- //#region src/v2/types/defineToolCallRenderer.ts
1425
- function defineToolCallRenderer(def) {
1426
- const argsSchema = def.name === "*" && !def.args ? z.any() : def.args;
1427
- return {
1428
- name: def.name,
1429
- args: argsSchema,
1430
- render: def.render,
1431
- ...def.agentId ? { agentId: def.agentId } : {}
1432
- };
1433
- }
1434
-
1435
- //#endregion
1436
- //#region src/v2/hooks/use-render-tool.tsx
1437
- const EMPTY_DEPS$1 = [];
1438
- /**
1439
- * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
1440
- *
1441
- * Key behavior:
1442
- * - deduplicates by `agentId:name` (latest registration wins),
1443
- * - keeps renderer entries on cleanup so historical chat tool calls can still render,
1444
- * - refreshes registration when `deps` change.
1445
- *
1446
- * @typeParam S - Schema type describing tool call parameters.
1447
- * @param config - Renderer config for wildcard or named tools.
1448
- * @param deps - Optional dependencies to refresh registration.
1449
- *
1450
- * @example
1451
- * ```tsx
1452
- * useRenderTool(
1453
- * {
1454
- * name: "searchDocs",
1455
- * parameters: z.object({ query: z.string() }),
1456
- * render: ({ status, parameters, result }) => {
1457
- * if (status === "executing") return <div>Searching {parameters.query}</div>;
1458
- * if (status === "complete") return <div>{result}</div>;
1459
- * return <div>Preparing...</div>;
1460
- * },
1461
- * },
1462
- * [],
1463
- * );
1464
- * ```
1465
- *
1466
- * @example
1467
- * ```tsx
1468
- * useRenderTool(
1469
- * {
1470
- * name: "summarize",
1471
- * parameters: z.object({ text: z.string() }),
1472
- * agentId: "research-agent",
1473
- * render: ({ name, status }) => <div>{name}: {status}</div>,
1474
- * },
1475
- * [selectedAgentId],
1476
- * );
1477
- * ```
1478
- */
1479
- function useRenderTool(config, deps) {
1480
- const { copilotkit } = useCopilotKit();
1481
- const extraDeps = deps ?? EMPTY_DEPS$1;
1482
- useEffect(() => {
1483
- const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
1484
- name: "*",
1485
- render: (props) => config.render({
1486
- ...props,
1487
- parameters: props.args
1488
- }),
1489
- ...config.agentId ? { agentId: config.agentId } : {}
1490
- }) : defineToolCallRenderer({
1491
- name: config.name,
1492
- args: config.parameters,
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
- },
1507
- ...config.agentId ? { agentId: config.agentId } : {}
1508
- });
1509
- copilotkit.addHookRenderToolCall(renderer);
1510
- }, [
1511
- config.name,
1512
- copilotkit,
1513
- JSON.stringify(extraDeps)
1514
- ]);
1515
- }
1516
-
1517
- //#endregion
1518
- //#region src/v2/hooks/use-default-render-tool.tsx
1519
- /**
1520
- * Module-level dedup set so an unknown status value only emits a console
1521
- * warning the FIRST time we encounter it. Otherwise a stuck/unmapped status
1522
- * would log on every re-render (potentially many per second).
1523
- */
1524
- const warnedUnknownStatuses = /* @__PURE__ */ new Set();
1525
- /**
1526
- * Map a {@link ToolCallStatus} enum value to the documented string-union
1527
- * status the {@link DefaultRenderProps} contract exposes. Unknown / future
1528
- * enum members log a warning (once per distinct value) and fall back to
1529
- * `"inProgress"`.
1530
- */
1531
- function mapToolCallStatus(status) {
1532
- switch (status) {
1533
- case ToolCallStatus.Complete: return "complete";
1534
- case ToolCallStatus.Executing: return "executing";
1535
- case ToolCallStatus.InProgress: return "inProgress";
1536
- default: {
1537
- const key = String(status);
1538
- if (!warnedUnknownStatuses.has(key)) {
1539
- warnedUnknownStatuses.add(key);
1540
- console.warn(`[CopilotKit] Unknown ToolCallStatus "${key}" in default tool-call renderer; falling back to "inProgress".`);
1541
- }
1542
- return "inProgress";
1543
- }
1544
- }
1545
- }
1546
- /**
1547
- * Convert the framework-internal renderer props (`args`, enum status) into
1548
- * the documented {@link DefaultRenderProps} shape (`parameters`, string-union
1549
- * status) so a user `config.render` always sees the documented contract.
1550
- */
1551
- function adaptRendererProps(props) {
1552
- return {
1553
- name: props.name,
1554
- toolCallId: props.toolCallId,
1555
- parameters: props.args,
1556
- status: mapToolCallStatus(props.status),
1557
- result: props.result
1558
- };
1559
- }
1560
- /**
1561
- * Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
1562
- *
1563
- * - Call with no config to use CopilotKit's built-in default tool-call card.
1564
- * - Pass `config.render` to replace the default UI with your own fallback renderer.
1565
- *
1566
- * This is useful when you want a generic renderer for tools that do not have a
1567
- * dedicated `useRenderTool({ name: "..." })` registration.
1568
- *
1569
- * @param config - Optional custom wildcard render function.
1570
- * @param deps - Optional dependencies to refresh registration.
1571
- *
1572
- * @example
1573
- * ```tsx
1574
- * useDefaultRenderTool();
1575
- * ```
1576
- *
1577
- * @example
1578
- * ```tsx
1579
- * useDefaultRenderTool({
1580
- * render: ({ name, status }) => <div>{name}: {status}</div>,
1581
- * });
1582
- * ```
1583
- *
1584
- * @example
1585
- * ```tsx
1586
- * useDefaultRenderTool(
1587
- * {
1588
- * render: ({ name, result }) => (
1589
- * <ToolEventRow title={name} payload={result} compact={compactMode} />
1590
- * ),
1591
- * },
1592
- * [compactMode],
1593
- * );
1594
- * ```
1595
- */
1596
- function useDefaultRenderTool(config, deps) {
1597
- const userRender = config?.render;
1598
- useRenderTool({
1599
- name: "*",
1600
- render: userRender ? (raw) => userRender(adaptRendererProps(raw)) : (raw) => /* @__PURE__ */ jsx(DefaultToolCallRenderer, { ...adaptRendererProps(raw) })
1601
- }, deps);
1602
- }
1603
- /**
1604
- * Guarded JSON.stringify used inside the expanded `<pre>` blocks. A circular
1605
- * reference would otherwise crash the entire React tree on render.
1606
- */
1607
- function safeStringifyForPre(value) {
1608
- try {
1609
- return JSON.stringify(value, null, 2);
1610
- } catch (err) {
1611
- console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for default renderer; falling back to String():", err);
1612
- try {
1613
- return String(value);
1614
- } catch (innerErr) {
1615
- console.warn("[CopilotKit] safeStringifyForPre: value could not be stringified:", innerErr);
1616
- return "[unserializable]";
1617
- }
1618
- }
1619
- }
1620
- function DefaultToolCallRenderer({ name, toolCallId, parameters, status, result }) {
1621
- const [isExpanded, setIsExpanded] = useState(false);
1622
- const isActive = status === "inProgress" || status === "executing";
1623
- const isComplete = status === "complete";
1624
- const statusLabel = isActive ? "Running" : isComplete ? "Done" : status;
1625
- const dotClassName = isActive ? "cpk:bg-amber-500" : isComplete ? "cpk:bg-emerald-500" : "cpk:bg-zinc-400";
1626
- const badgeClassName = isActive ? "cpk:bg-amber-100 cpk:text-amber-800 cpk:dark:bg-amber-500/15 cpk:dark:text-amber-400" : isComplete ? "cpk:bg-emerald-100 cpk:text-emerald-800 cpk:dark:bg-emerald-500/15 cpk:dark:text-emerald-400" : "cpk:bg-zinc-100 cpk:text-zinc-800 cpk:dark:bg-zinc-700/40 cpk:dark:text-zinc-300";
1627
- return /* @__PURE__ */ jsx("div", {
1628
- "data-testid": "copilot-tool-render",
1629
- "data-tool-name": name,
1630
- "data-tool-call-id": toolCallId,
1631
- "data-status": status,
1632
- "data-args": safeStringifyForAttr(parameters),
1633
- "data-result": safeStringifyForAttr(result),
1634
- className: "cpk:mt-2 cpk:pb-2",
1635
- children: /* @__PURE__ */ jsxs("div", {
1636
- className: "cpk:rounded-xl cpk:border cpk:border-zinc-200/60 cpk:bg-white/70 cpk:p-4 cpk:shadow-sm cpk:backdrop-blur cpk:dark:border-zinc-800/60 cpk:dark:bg-zinc-900/50",
1637
- children: [/* @__PURE__ */ jsxs("button", {
1638
- type: "button",
1639
- "aria-expanded": isExpanded,
1640
- onClick: () => setIsExpanded(!isExpanded),
1641
- className: "cpk:flex cpk:w-full cpk:cursor-pointer cpk:select-none cpk:items-center cpk:justify-between cpk:gap-2.5 cpk:border-none cpk:bg-transparent cpk:p-0 cpk:m-0 cpk:text-left cpk:text-inherit",
1642
- style: { font: "inherit" },
1643
- children: [/* @__PURE__ */ jsxs("div", {
1644
- className: "cpk:flex cpk:min-w-0 cpk:items-center cpk:gap-2",
1645
- children: [
1646
- /* @__PURE__ */ jsx("svg", {
1647
- className: `cpk:h-3.5 cpk:w-3.5 cpk:flex-shrink-0 cpk:text-zinc-500 cpk:transition-transform cpk:dark:text-zinc-400 ${isExpanded ? "cpk:rotate-90" : ""}`,
1648
- fill: "none",
1649
- viewBox: "0 0 24 24",
1650
- strokeWidth: 2,
1651
- stroke: "currentColor",
1652
- children: /* @__PURE__ */ jsx("path", {
1653
- strokeLinecap: "round",
1654
- strokeLinejoin: "round",
1655
- d: "M8.25 4.5l7.5 7.5-7.5 7.5"
1656
- })
1657
- }),
1658
- /* @__PURE__ */ jsx("span", { className: `cpk:inline-block cpk:h-2 cpk:w-2 cpk:flex-shrink-0 cpk:rounded-full ${dotClassName}` }),
1659
- /* @__PURE__ */ jsx("span", {
1660
- "data-testid": "copilot-tool-render-name",
1661
- className: "cpk:truncate cpk:text-[13px] cpk:font-semibold cpk:text-zinc-900 cpk:dark:text-zinc-100",
1662
- children: name
1663
- })
1664
- ]
1665
- }), /* @__PURE__ */ jsx("span", {
1666
- "data-testid": "copilot-tool-render-status",
1667
- className: `cpk:inline-flex cpk:flex-shrink-0 cpk:items-center cpk:rounded-full cpk:px-2 cpk:py-0.5 cpk:text-[11px] cpk:font-medium ${badgeClassName}`,
1668
- children: statusLabel
1669
- })]
1670
- }), isExpanded && /* @__PURE__ */ jsxs("div", {
1671
- className: "cpk:mt-3 cpk:grid cpk:gap-3",
1672
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
1673
- className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
1674
- children: "Arguments"
1675
- }), /* @__PURE__ */ jsx("pre", {
1676
- className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
1677
- children: safeStringifyForPre(parameters ?? {})
1678
- })] }), result !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
1679
- className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
1680
- children: "Result"
1681
- }), /* @__PURE__ */ jsx("pre", {
1682
- className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
1683
- children: typeof result === "string" ? result : safeStringifyForPre(result)
1684
- })] })]
1685
- })]
1686
- })
1687
- });
1688
- }
1689
- function safeStringifyForAttr(value) {
1690
- if (value === void 0 || value === null) return "";
1691
- if (typeof value === "string") return value;
1692
- try {
1693
- return JSON.stringify(value);
1694
- } catch (err) {
1695
- console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for data-* attribute; falling back to String():", err);
1696
- try {
1697
- return String(value);
1698
- } catch (innerErr) {
1699
- console.warn("[CopilotKit] safeStringifyForAttr: value could not be stringified:", innerErr);
1700
- return "";
1701
- }
1702
- }
1703
- }
1526
+ forceUpdate();
1527
+ },
1528
+ onHeadersChanged: () => {
1529
+ forceUpdate();
1530
+ }
1531
+ });
1532
+ return () => {
1533
+ subscription.unsubscribe();
1534
+ };
1535
+ }, []);
1536
+ return context;
1537
+ };
1538
+ const LicenseContext = createContext({
1539
+ status: null,
1540
+ license: null,
1541
+ checkFeature: () => true,
1542
+ getLimit: () => null
1543
+ });
1544
+ const useLicenseContext = () => useContext(LicenseContext);
1704
1545
 
1705
1546
  //#endregion
1706
1547
  //#region src/v2/hooks/use-render-tool-call.tsx
@@ -1756,10 +1597,13 @@ function useRenderToolCall() {
1756
1597
  }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
1757
1598
  return useCallback(({ toolCall, toolMessage }) => {
1758
1599
  const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
1600
+ const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
1601
+ if (!renderConfig) return null;
1602
+ const RenderComponent = renderConfig.render;
1759
1603
  return /* @__PURE__ */ jsx(ToolCallRenderer, {
1760
1604
  toolCall,
1761
1605
  toolMessage,
1762
- RenderComponent: (exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*"))?.render ?? defaultToolCallRenderAdapter,
1606
+ RenderComponent,
1763
1607
  isExecuting: executingToolCallIds.has(toolCall.id)
1764
1608
  }, toolCall.id);
1765
1609
  }, [
@@ -1768,15 +1612,6 @@ function useRenderToolCall() {
1768
1612
  agentId
1769
1613
  ]);
1770
1614
  }
1771
- function defaultToolCallRenderAdapter(props) {
1772
- return /* @__PURE__ */ jsx(DefaultToolCallRenderer, {
1773
- name: props.name,
1774
- toolCallId: props.toolCallId,
1775
- parameters: props.args,
1776
- status: mapToolCallStatus(props.status),
1777
- result: props.result
1778
- });
1779
- }
1780
1615
 
1781
1616
  //#endregion
1782
1617
  //#region src/v2/components/CopilotKitInspector.tsx
@@ -3258,7 +3093,7 @@ const A2UISurfaceContentSchema = z.object({
3258
3093
  ...A2UILifecycleFields
3259
3094
  }).passthrough();
3260
3095
  function createA2UIMessageRenderer(options) {
3261
- const { theme, catalog, loadingComponent, recovery } = options;
3096
+ const { theme, catalog, loadingComponent, recovery, onAction } = options;
3262
3097
  const showAfterMs = recovery?.showAfterMs ?? 2e3;
3263
3098
  const showAfterAttempts = recovery?.showAfterAttempts ?? 2;
3264
3099
  const optionDebugExposure = recovery?.debugExposure ?? "collapsed";
@@ -3334,6 +3169,7 @@ function createA2UIMessageRenderer(options) {
3334
3169
  agent,
3335
3170
  copilotkit,
3336
3171
  catalog,
3172
+ onAction,
3337
3173
  onReady: markSurfaceReady
3338
3174
  }, surfaceId))
3339
3175
  });
@@ -3354,29 +3190,60 @@ function createA2UIMessageRenderer(options) {
3354
3190
  };
3355
3191
  }
3356
3192
  /**
3193
+ * Orchestrates a single A2UI user action: runs the optional `onAction`
3194
+ * interceptor first, then forwards to the agent unless the interceptor
3195
+ * suppressed it (returned `null`). Exported for unit testing; the wiring lives
3196
+ * in {@link ReactSurfaceHost}.
3197
+ */
3198
+ async function runA2UIAction({ message, agent, copilotkit, onAction }) {
3199
+ if (!agent) return;
3200
+ const action = message.userAction;
3201
+ const forward = async (forwardAction) => {
3202
+ const a2uiAction = forwardAction !== void 0 ? {
3203
+ ...message,
3204
+ userAction: forwardAction
3205
+ } : message;
3206
+ try {
3207
+ copilotkit.setProperties({
3208
+ ...copilotkit.properties,
3209
+ a2uiAction
3210
+ });
3211
+ await copilotkit.runAgent({ agent });
3212
+ } finally {
3213
+ if (copilotkit.properties) {
3214
+ const { a2uiAction: _omit, ...rest } = copilotkit.properties;
3215
+ copilotkit.setProperties(rest);
3216
+ }
3217
+ }
3218
+ };
3219
+ if (onAction && action) {
3220
+ const result = await onAction(action, forward);
3221
+ if (result === null) return;
3222
+ if (result) {
3223
+ await forward(result);
3224
+ return;
3225
+ }
3226
+ }
3227
+ await forward();
3228
+ }
3229
+ /**
3357
3230
  * Renders a single A2UI surface using the React renderer.
3358
3231
  * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
3359
3232
  */
3360
- function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog, onReady }) {
3233
+ function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog, onAction, onReady }) {
3361
3234
  return /* @__PURE__ */ jsx("div", {
3362
3235
  className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
3363
3236
  children: /* @__PURE__ */ jsxs(A2UIProvider, {
3364
- onAction: useCallback(async (message) => {
3365
- if (!agent) return;
3366
- message.userAction;
3367
- try {
3368
- copilotkit.setProperties({
3369
- ...copilotkit.properties,
3370
- a2uiAction: message
3371
- });
3372
- await copilotkit.runAgent({ agent });
3373
- } finally {
3374
- if (copilotkit.properties) {
3375
- const { a2uiAction, ...rest } = copilotkit.properties;
3376
- copilotkit.setProperties(rest);
3377
- }
3378
- }
3379
- }, [agent, copilotkit]),
3237
+ onAction: useCallback((message) => runA2UIAction({
3238
+ message,
3239
+ agent,
3240
+ copilotkit,
3241
+ onAction
3242
+ }), [
3243
+ agent,
3244
+ copilotkit,
3245
+ onAction
3246
+ ]),
3380
3247
  theme,
3381
3248
  catalog,
3382
3249
  children: [/* @__PURE__ */ jsx(SurfaceMessageProcessor, {
@@ -3447,6 +3314,18 @@ function getOperationSurfaceId(operation) {
3447
3314
  return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
3448
3315
  }
3449
3316
 
3317
+ //#endregion
3318
+ //#region src/v2/types/defineToolCallRenderer.ts
3319
+ function defineToolCallRenderer(def) {
3320
+ const argsSchema = def.name === "*" && !def.args ? z.any() : def.args;
3321
+ return {
3322
+ name: def.name,
3323
+ args: argsSchema,
3324
+ render: def.render,
3325
+ ...def.agentId ? { agentId: def.agentId } : {}
3326
+ };
3327
+ }
3328
+
3450
3329
  //#endregion
3451
3330
  //#region src/v2/a2ui/A2UIToolCallRenderer.tsx
3452
3331
  /**
@@ -4000,10 +3879,10 @@ function useRenderActivityMessage() {
4000
3879
 
4001
3880
  //#endregion
4002
3881
  //#region src/v2/hooks/use-frontend-tool.tsx
4003
- const EMPTY_DEPS = [];
3882
+ const EMPTY_DEPS$1 = [];
4004
3883
  function useFrontendTool(tool, deps) {
4005
3884
  const { copilotkit } = useCopilotKit();
4006
- const extraDeps = deps ?? EMPTY_DEPS;
3885
+ const extraDeps = deps ?? EMPTY_DEPS$1;
4007
3886
  useEffect(() => {
4008
3887
  const name = tool.name;
4009
3888
  if (copilotkit.getTool({
@@ -4030,74 +3909,344 @@ function useFrontendTool(tool, deps) {
4030
3909
  JSON.stringify(extraDeps)
4031
3910
  ]);
4032
3911
  }
4033
-
4034
- //#endregion
4035
- //#region src/v2/hooks/use-component.tsx
3912
+
3913
+ //#endregion
3914
+ //#region src/v2/hooks/use-component.tsx
3915
+ /**
3916
+ * Registers a React component as a frontend tool renderer in chat.
3917
+ *
3918
+ * This hook is a convenience wrapper around `useFrontendTool` that:
3919
+ * - builds a model-facing tool description,
3920
+ * - forwards optional schema parameters (any Standard Schema V1 compatible library),
3921
+ * - renders your component with tool call parameters.
3922
+ *
3923
+ * Use this when you want to display a typed visual component for a tool call
3924
+ * without manually wiring a full frontend tool object.
3925
+ *
3926
+ * When `parameters` is provided, render props are inferred from the schema.
3927
+ * When omitted, the render component may accept any props.
3928
+ *
3929
+ * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
3930
+ * @param config - Tool registration config.
3931
+ * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
3932
+ *
3933
+ * @example
3934
+ * ```tsx
3935
+ * // Without parameters — render accepts any props
3936
+ * useComponent({
3937
+ * name: "showGreeting",
3938
+ * render: ({ message }: { message: string }) => <div>{message}</div>,
3939
+ * });
3940
+ * ```
3941
+ *
3942
+ * @example
3943
+ * ```tsx
3944
+ * // With parameters — render props inferred from schema
3945
+ * useComponent({
3946
+ * name: "showWeatherCard",
3947
+ * parameters: z.object({ city: z.string() }),
3948
+ * render: ({ city }) => <div>{city}</div>,
3949
+ * });
3950
+ * ```
3951
+ *
3952
+ * @example
3953
+ * ```tsx
3954
+ * useComponent(
3955
+ * {
3956
+ * name: "renderProfile",
3957
+ * parameters: z.object({ userId: z.string() }),
3958
+ * render: ProfileCard,
3959
+ * agentId: "support-agent",
3960
+ * },
3961
+ * [selectedAgentId],
3962
+ * );
3963
+ * ```
3964
+ */
3965
+ function useComponent(config, deps) {
3966
+ const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
3967
+ const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
3968
+ useFrontendTool({
3969
+ name: config.name,
3970
+ description: fullDescription,
3971
+ parameters: config.parameters,
3972
+ render: ({ args }) => {
3973
+ const Component = config.render;
3974
+ return /* @__PURE__ */ jsx(Component, { ...args });
3975
+ },
3976
+ agentId: config.agentId,
3977
+ followUp: config.followUp
3978
+ }, deps);
3979
+ }
3980
+
3981
+ //#endregion
3982
+ //#region src/v2/hooks/use-render-tool.tsx
3983
+ const EMPTY_DEPS = [];
3984
+ /**
3985
+ * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
3986
+ *
3987
+ * Key behavior:
3988
+ * - deduplicates by `agentId:name` (latest registration wins),
3989
+ * - keeps renderer entries on cleanup so historical chat tool calls can still render,
3990
+ * - refreshes registration when `deps` change.
3991
+ *
3992
+ * @typeParam S - Schema type describing tool call parameters.
3993
+ * @param config - Renderer config for wildcard or named tools.
3994
+ * @param deps - Optional dependencies to refresh registration.
3995
+ *
3996
+ * @example
3997
+ * ```tsx
3998
+ * useRenderTool(
3999
+ * {
4000
+ * name: "searchDocs",
4001
+ * parameters: z.object({ query: z.string() }),
4002
+ * render: ({ status, parameters, result }) => {
4003
+ * if (status === "executing") return <div>Searching {parameters.query}</div>;
4004
+ * if (status === "complete") return <div>{result}</div>;
4005
+ * return <div>Preparing...</div>;
4006
+ * },
4007
+ * },
4008
+ * [],
4009
+ * );
4010
+ * ```
4011
+ *
4012
+ * @example
4013
+ * ```tsx
4014
+ * useRenderTool(
4015
+ * {
4016
+ * name: "summarize",
4017
+ * parameters: z.object({ text: z.string() }),
4018
+ * agentId: "research-agent",
4019
+ * render: ({ name, status }) => <div>{name}: {status}</div>,
4020
+ * },
4021
+ * [selectedAgentId],
4022
+ * );
4023
+ * ```
4024
+ */
4025
+ function useRenderTool(config, deps) {
4026
+ const { copilotkit } = useCopilotKit();
4027
+ const extraDeps = deps ?? EMPTY_DEPS;
4028
+ useEffect(() => {
4029
+ const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
4030
+ name: "*",
4031
+ render: (props) => config.render({
4032
+ ...props,
4033
+ parameters: props.args
4034
+ }),
4035
+ ...config.agentId ? { agentId: config.agentId } : {}
4036
+ }) : defineToolCallRenderer({
4037
+ name: config.name,
4038
+ args: config.parameters,
4039
+ render: (props) => {
4040
+ if (props.status === ToolCallStatus.InProgress) return config.render({
4041
+ ...props,
4042
+ parameters: props.args
4043
+ });
4044
+ if (props.status === ToolCallStatus.Executing) return config.render({
4045
+ ...props,
4046
+ parameters: props.args
4047
+ });
4048
+ return config.render({
4049
+ ...props,
4050
+ parameters: props.args
4051
+ });
4052
+ },
4053
+ ...config.agentId ? { agentId: config.agentId } : {}
4054
+ });
4055
+ copilotkit.addHookRenderToolCall(renderer);
4056
+ }, [
4057
+ config.name,
4058
+ copilotkit,
4059
+ JSON.stringify(extraDeps)
4060
+ ]);
4061
+ }
4062
+
4063
+ //#endregion
4064
+ //#region src/v2/hooks/use-default-render-tool.tsx
4065
+ /**
4066
+ * Module-level dedup set so an unknown status value only emits a console
4067
+ * warning the FIRST time we encounter it. Otherwise a stuck/unmapped status
4068
+ * would log on every re-render (potentially many per second).
4069
+ */
4070
+ const warnedUnknownStatuses = /* @__PURE__ */ new Set();
4071
+ /**
4072
+ * Map a {@link ToolCallStatus} enum value to the documented string-union
4073
+ * status the {@link DefaultRenderProps} contract exposes. Unknown / future
4074
+ * enum members log a warning (once per distinct value) and fall back to
4075
+ * `"inProgress"`.
4076
+ */
4077
+ function mapToolCallStatus(status) {
4078
+ switch (status) {
4079
+ case ToolCallStatus.Complete: return "complete";
4080
+ case ToolCallStatus.Executing: return "executing";
4081
+ case ToolCallStatus.InProgress: return "inProgress";
4082
+ default: {
4083
+ const key = String(status);
4084
+ if (!warnedUnknownStatuses.has(key)) {
4085
+ warnedUnknownStatuses.add(key);
4086
+ console.warn(`[CopilotKit] Unknown ToolCallStatus "${key}" in default tool-call renderer; falling back to "inProgress".`);
4087
+ }
4088
+ return "inProgress";
4089
+ }
4090
+ }
4091
+ }
4092
+ /**
4093
+ * Convert the framework-internal renderer props (`args`, enum status) into
4094
+ * the documented {@link DefaultRenderProps} shape (`parameters`, string-union
4095
+ * status) so a user `config.render` always sees the documented contract.
4096
+ */
4097
+ function adaptRendererProps(props) {
4098
+ return {
4099
+ name: props.name,
4100
+ toolCallId: props.toolCallId,
4101
+ parameters: props.args,
4102
+ status: mapToolCallStatus(props.status),
4103
+ result: props.result
4104
+ };
4105
+ }
4036
4106
  /**
4037
- * Registers a React component as a frontend tool renderer in chat.
4038
- *
4039
- * This hook is a convenience wrapper around `useFrontendTool` that:
4040
- * - builds a model-facing tool description,
4041
- * - forwards optional schema parameters (any Standard Schema V1 compatible library),
4042
- * - renders your component with tool call parameters.
4107
+ * Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
4043
4108
  *
4044
- * Use this when you want to display a typed visual component for a tool call
4045
- * without manually wiring a full frontend tool object.
4109
+ * - Call with no config to use CopilotKit's built-in default tool-call card.
4110
+ * - Pass `config.render` to replace the default UI with your own fallback renderer.
4046
4111
  *
4047
- * When `parameters` is provided, render props are inferred from the schema.
4048
- * When omitted, the render component may accept any props.
4112
+ * This is useful when you want a generic renderer for tools that do not have a
4113
+ * dedicated `useRenderTool({ name: "..." })` registration.
4049
4114
  *
4050
- * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
4051
- * @param config - Tool registration config.
4052
- * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
4115
+ * @param config - Optional custom wildcard render function.
4116
+ * @param deps - Optional dependencies to refresh registration.
4053
4117
  *
4054
4118
  * @example
4055
4119
  * ```tsx
4056
- * // Without parameters — render accepts any props
4057
- * useComponent({
4058
- * name: "showGreeting",
4059
- * render: ({ message }: { message: string }) => <div>{message}</div>,
4060
- * });
4120
+ * useDefaultRenderTool();
4061
4121
  * ```
4062
4122
  *
4063
4123
  * @example
4064
4124
  * ```tsx
4065
- * // With parameters — render props inferred from schema
4066
- * useComponent({
4067
- * name: "showWeatherCard",
4068
- * parameters: z.object({ city: z.string() }),
4069
- * render: ({ city }) => <div>{city}</div>,
4125
+ * useDefaultRenderTool({
4126
+ * render: ({ name, status }) => <div>{name}: {status}</div>,
4070
4127
  * });
4071
4128
  * ```
4072
4129
  *
4073
4130
  * @example
4074
4131
  * ```tsx
4075
- * useComponent(
4132
+ * useDefaultRenderTool(
4076
4133
  * {
4077
- * name: "renderProfile",
4078
- * parameters: z.object({ userId: z.string() }),
4079
- * render: ProfileCard,
4080
- * agentId: "support-agent",
4134
+ * render: ({ name, result }) => (
4135
+ * <ToolEventRow title={name} payload={result} compact={compactMode} />
4136
+ * ),
4081
4137
  * },
4082
- * [selectedAgentId],
4138
+ * [compactMode],
4083
4139
  * );
4084
4140
  * ```
4085
4141
  */
4086
- function useComponent(config, deps) {
4087
- const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
4088
- const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
4089
- useFrontendTool({
4090
- name: config.name,
4091
- description: fullDescription,
4092
- parameters: config.parameters,
4093
- render: ({ args }) => {
4094
- const Component = config.render;
4095
- return /* @__PURE__ */ jsx(Component, { ...args });
4096
- },
4097
- agentId: config.agentId,
4098
- followUp: config.followUp
4142
+ function useDefaultRenderTool(config, deps) {
4143
+ const userRender = config?.render;
4144
+ useRenderTool({
4145
+ name: "*",
4146
+ render: userRender ? (raw) => userRender(adaptRendererProps(raw)) : (raw) => /* @__PURE__ */ jsx(DefaultToolCallRenderer, { ...adaptRendererProps(raw) })
4099
4147
  }, deps);
4100
4148
  }
4149
+ /**
4150
+ * Guarded JSON.stringify used inside the expanded `<pre>` blocks. A circular
4151
+ * reference would otherwise crash the entire React tree on render.
4152
+ */
4153
+ function safeStringifyForPre(value) {
4154
+ try {
4155
+ return JSON.stringify(value, null, 2);
4156
+ } catch (err) {
4157
+ console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for default renderer; falling back to String():", err);
4158
+ try {
4159
+ return String(value);
4160
+ } catch (innerErr) {
4161
+ console.warn("[CopilotKit] safeStringifyForPre: value could not be stringified:", innerErr);
4162
+ return "[unserializable]";
4163
+ }
4164
+ }
4165
+ }
4166
+ function DefaultToolCallRenderer({ name, toolCallId, parameters, status, result }) {
4167
+ const [isExpanded, setIsExpanded] = useState(false);
4168
+ const isActive = status === "inProgress" || status === "executing";
4169
+ const isComplete = status === "complete";
4170
+ const statusLabel = isActive ? "Running" : isComplete ? "Done" : status;
4171
+ const dotClassName = isActive ? "cpk:bg-amber-500" : isComplete ? "cpk:bg-emerald-500" : "cpk:bg-zinc-400";
4172
+ const badgeClassName = isActive ? "cpk:bg-amber-100 cpk:text-amber-800 cpk:dark:bg-amber-500/15 cpk:dark:text-amber-400" : isComplete ? "cpk:bg-emerald-100 cpk:text-emerald-800 cpk:dark:bg-emerald-500/15 cpk:dark:text-emerald-400" : "cpk:bg-zinc-100 cpk:text-zinc-800 cpk:dark:bg-zinc-700/40 cpk:dark:text-zinc-300";
4173
+ return /* @__PURE__ */ jsx("div", {
4174
+ "data-testid": "copilot-tool-render",
4175
+ "data-tool-name": name,
4176
+ "data-tool-call-id": toolCallId,
4177
+ "data-status": status,
4178
+ "data-args": safeStringifyForAttr(parameters),
4179
+ "data-result": safeStringifyForAttr(result),
4180
+ className: "cpk:mt-2 cpk:pb-2",
4181
+ children: /* @__PURE__ */ jsxs("div", {
4182
+ className: "cpk:rounded-xl cpk:border cpk:border-zinc-200/60 cpk:bg-white/70 cpk:p-4 cpk:shadow-sm cpk:backdrop-blur cpk:dark:border-zinc-800/60 cpk:dark:bg-zinc-900/50",
4183
+ children: [/* @__PURE__ */ jsxs("button", {
4184
+ type: "button",
4185
+ "aria-expanded": isExpanded,
4186
+ onClick: () => setIsExpanded(!isExpanded),
4187
+ className: "cpk:flex cpk:w-full cpk:cursor-pointer cpk:select-none cpk:items-center cpk:justify-between cpk:gap-2.5 cpk:border-none cpk:bg-transparent cpk:p-0 cpk:m-0 cpk:text-left cpk:text-inherit",
4188
+ style: { font: "inherit" },
4189
+ children: [/* @__PURE__ */ jsxs("div", {
4190
+ className: "cpk:flex cpk:min-w-0 cpk:items-center cpk:gap-2",
4191
+ children: [
4192
+ /* @__PURE__ */ jsx("svg", {
4193
+ className: `cpk:h-3.5 cpk:w-3.5 cpk:flex-shrink-0 cpk:text-zinc-500 cpk:transition-transform cpk:dark:text-zinc-400 ${isExpanded ? "cpk:rotate-90" : ""}`,
4194
+ fill: "none",
4195
+ viewBox: "0 0 24 24",
4196
+ strokeWidth: 2,
4197
+ stroke: "currentColor",
4198
+ children: /* @__PURE__ */ jsx("path", {
4199
+ strokeLinecap: "round",
4200
+ strokeLinejoin: "round",
4201
+ d: "M8.25 4.5l7.5 7.5-7.5 7.5"
4202
+ })
4203
+ }),
4204
+ /* @__PURE__ */ jsx("span", { className: `cpk:inline-block cpk:h-2 cpk:w-2 cpk:flex-shrink-0 cpk:rounded-full ${dotClassName}` }),
4205
+ /* @__PURE__ */ jsx("span", {
4206
+ "data-testid": "copilot-tool-render-name",
4207
+ className: "cpk:truncate cpk:text-[13px] cpk:font-semibold cpk:text-zinc-900 cpk:dark:text-zinc-100",
4208
+ children: name
4209
+ })
4210
+ ]
4211
+ }), /* @__PURE__ */ jsx("span", {
4212
+ "data-testid": "copilot-tool-render-status",
4213
+ className: `cpk:inline-flex cpk:flex-shrink-0 cpk:items-center cpk:rounded-full cpk:px-2 cpk:py-0.5 cpk:text-[11px] cpk:font-medium ${badgeClassName}`,
4214
+ children: statusLabel
4215
+ })]
4216
+ }), isExpanded && /* @__PURE__ */ jsxs("div", {
4217
+ className: "cpk:mt-3 cpk:grid cpk:gap-3",
4218
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
4219
+ className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
4220
+ children: "Arguments"
4221
+ }), /* @__PURE__ */ jsx("pre", {
4222
+ className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
4223
+ children: safeStringifyForPre(parameters ?? {})
4224
+ })] }), result !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
4225
+ className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
4226
+ children: "Result"
4227
+ }), /* @__PURE__ */ jsx("pre", {
4228
+ className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
4229
+ children: typeof result === "string" ? result : safeStringifyForPre(result)
4230
+ })] })]
4231
+ })]
4232
+ })
4233
+ });
4234
+ }
4235
+ function safeStringifyForAttr(value) {
4236
+ if (value === void 0 || value === null) return "";
4237
+ if (typeof value === "string") return value;
4238
+ try {
4239
+ return JSON.stringify(value);
4240
+ } catch (err) {
4241
+ console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for data-* attribute; falling back to String():", err);
4242
+ try {
4243
+ return String(value);
4244
+ } catch (innerErr) {
4245
+ console.warn("[CopilotKit] safeStringifyForAttr: value could not be stringified:", innerErr);
4246
+ return "";
4247
+ }
4248
+ }
4249
+ }
4101
4250
 
4102
4251
  //#endregion
4103
4252
  //#region src/v2/hooks/use-human-in-the-loop.tsx
@@ -4835,7 +4984,7 @@ function useThreadStoreSelector(store, selector) {
4835
4984
  return useSyncExternalStore(useCallback((onStoreChange) => {
4836
4985
  const subscription = store.select(selector).subscribe(onStoreChange);
4837
4986
  return () => subscription.unsubscribe();
4838
- }, [store, selector]), () => selector(store.getState()));
4987
+ }, [store, selector]), () => selector(store.getState()), () => selector(store.getServerState()));
4839
4988
  }
4840
4989
  /**
4841
4990
  * React hook for listing and managing Intelligence platform threads.
@@ -4878,7 +5027,7 @@ function useThreadStoreSelector(store, selector) {
4878
5027
  * }
4879
5028
  * ```
4880
5029
  */
4881
- function useThreads$1({ agentId, includeArchived, limit }) {
5030
+ function useThreads$1({ agentId, includeArchived, limit, enabled = true }) {
4882
5031
  const { copilotkit } = useCopilotKit();
4883
5032
  const [store] = useState(() => ɵcreateThreadStore({ fetch: globalThis.fetch }));
4884
5033
  const coreThreads = useThreadStoreSelector(store, ɵselectThreads);
@@ -4895,6 +5044,7 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4895
5044
  const storeError = useThreadStoreSelector(store, ɵselectThreadsError);
4896
5045
  const hasMoreThreads = useThreadStoreSelector(store, ɵselectHasNextPage);
4897
5046
  const isFetchingMoreThreads = useThreadStoreSelector(store, ɵselectIsFetchingNextPage);
5047
+ const isMutating = useThreadStoreSelector(store, ɵselectIsMutating);
4898
5048
  const headersKey = useMemo(() => {
4899
5049
  return JSON.stringify(Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) => left.localeCompare(right)));
4900
5050
  }, [copilotkit.headers]);
@@ -4915,9 +5065,16 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4915
5065
  return /* @__PURE__ */ new Error("Thread mutations are not available on this CopilotKit runtime");
4916
5066
  }, [threadMutationsSupported]);
4917
5067
  const [hasDispatchedContext, setHasDispatchedContext] = useState(false);
4918
- const preConnectLoading = !!copilotkit.runtimeUrl && !threadEndpointsUnavailable && !hasDispatchedContext;
4919
- const isLoading = runtimeError || threadEndpointsError ? false : preConnectLoading || storeIsLoading;
4920
- const error = runtimeError ?? threadEndpointsError ?? storeError;
5068
+ const preConnectLoading = enabled && !!copilotkit.runtimeUrl && !threadEndpointsUnavailable && !hasDispatchedContext;
5069
+ const [configErrorDismissed, setConfigErrorDismissed] = useState(false);
5070
+ useEffect(() => {
5071
+ setConfigErrorDismissed(false);
5072
+ }, [runtimeError, threadEndpointsError]);
5073
+ const activeRuntimeError = configErrorDismissed ? null : runtimeError;
5074
+ const activeThreadEndpointsError = configErrorDismissed ? null : threadEndpointsError;
5075
+ const isLoading = activeRuntimeError || activeThreadEndpointsError ? false : preConnectLoading || storeIsLoading;
5076
+ const error = activeRuntimeError ?? activeThreadEndpointsError ?? storeError;
5077
+ const listError = storeError;
4921
5078
  useEffect(() => {
4922
5079
  store.start();
4923
5080
  return () => {
@@ -4925,6 +5082,7 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4925
5082
  };
4926
5083
  }, [store]);
4927
5084
  useEffect(() => {
5085
+ if (!enabled) return;
4928
5086
  copilotkit.registerThreadStore(agentId, store);
4929
5087
  return () => {
4930
5088
  copilotkit.unregisterThreadStore(agentId);
@@ -4932,9 +5090,15 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4932
5090
  }, [
4933
5091
  copilotkit,
4934
5092
  agentId,
4935
- store
5093
+ store,
5094
+ enabled
4936
5095
  ]);
4937
5096
  useEffect(() => {
5097
+ if (!enabled) {
5098
+ store.setContext(null);
5099
+ setHasDispatchedContext(false);
5100
+ return;
5101
+ }
4938
5102
  if (!copilotkit.runtimeUrl) {
4939
5103
  store.setContext(null);
4940
5104
  setHasDispatchedContext(false);
@@ -4958,6 +5122,7 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4958
5122
  setHasDispatchedContext(true);
4959
5123
  }, [
4960
5124
  store,
5125
+ enabled,
4961
5126
  copilotkit.runtimeUrl,
4962
5127
  runtimeStatus,
4963
5128
  headersKey,
@@ -4981,9 +5146,16 @@ function useThreads$1({ agentId, includeArchived, limit }) {
4981
5146
  threads,
4982
5147
  isLoading,
4983
5148
  error,
5149
+ listError,
4984
5150
  hasMoreThreads,
4985
5151
  isFetchingMoreThreads,
5152
+ isMutating,
4986
5153
  fetchMoreThreads: useCallback(() => store.fetchNextPage(), [store]),
5154
+ refetchThreads: useCallback(() => store.refetchThreads(), [store]),
5155
+ startNewThread: useCallback(() => {
5156
+ setConfigErrorDismissed(true);
5157
+ store.startNewThread();
5158
+ }, [store]),
4987
5159
  renameThread,
4988
5160
  archiveThread,
4989
5161
  unarchiveThread,
@@ -6170,7 +6342,7 @@ const DefaultContainer = React.forwardRef(function DefaultContainer({ className,
6170
6342
  ref,
6171
6343
  "data-copilotkit": true,
6172
6344
  "data-testid": "copilot-suggestions",
6173
- className: cn("cpk:flex cpk:flex-wrap cpk:items-center cpk:gap-1.5 cpk:sm:gap-2 cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:pointer-events-none", className),
6345
+ className: cn("cpk:flex cpk:flex-wrap cpk:items-center cpk:gap-1.5 cpk:sm:gap-2 cpk:pl-0 cpk:pr-4 cpk:@3xl:px-0 cpk:pointer-events-none", className),
6174
6346
  ...props
6175
6347
  });
6176
6348
  });
@@ -7275,7 +7447,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
7275
7447
  children: /* @__PURE__ */ jsxs("div", {
7276
7448
  className: "cpk:max-w-3xl cpk:mx-auto",
7277
7449
  children: [BoundMessageView, hasSuggestions ? /* @__PURE__ */ jsx("div", {
7278
- className: "cpk:pl-0 cpk:pr-4 cpk:sm:px-0 cpk:mt-4",
7450
+ className: "cpk:pl-0 cpk:pr-4 cpk:@3xl:px-0 cpk:mt-4",
7279
7451
  children: BoundSuggestionView
7280
7452
  }) : null]
7281
7453
  })
@@ -7318,7 +7490,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
7318
7490
  onDragOver,
7319
7491
  onDragLeave,
7320
7492
  onDrop,
7321
- className: cn("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
7493
+ className: cn("copilotKitChat cpk:@container cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
7322
7494
  ...props,
7323
7495
  children: [dragOver && /* @__PURE__ */ jsx(DropOverlay, {}), BoundWelcomeScreen]
7324
7496
  });
@@ -7340,7 +7512,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
7340
7512
  onDragOver,
7341
7513
  onDragLeave,
7342
7514
  onDrop,
7343
- className: cn("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
7515
+ className: cn("copilotKitChat cpk:@container cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
7344
7516
  ...props,
7345
7517
  children: [
7346
7518
  dragOver && /* @__PURE__ */ jsx(DropOverlay, {}),
@@ -7379,7 +7551,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
7379
7551
  minHeight: 0
7380
7552
  },
7381
7553
  children: /* @__PURE__ */ jsx("div", {
7382
- className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7554
+ className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7383
7555
  children
7384
7556
  })
7385
7557
  }),
@@ -7412,7 +7584,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
7412
7584
  ...props,
7413
7585
  children: [/* @__PURE__ */ jsx("div", {
7414
7586
  ref: contentRef,
7415
- className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7587
+ className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7416
7588
  children
7417
7589
  }), /* @__PURE__ */ jsx("div", {
7418
7590
  ref: spacerRef,
@@ -7474,7 +7646,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
7474
7646
  if (!hasMounted) return /* @__PURE__ */ jsx("div", {
7475
7647
  className: "cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-auto cpk:overflow-x-hidden",
7476
7648
  children: /* @__PURE__ */ jsx("div", {
7477
- className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7649
+ className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7478
7650
  children
7479
7651
  })
7480
7652
  });
@@ -7489,7 +7661,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
7489
7661
  children: [
7490
7662
  /* @__PURE__ */ jsx("div", {
7491
7663
  ref: contentRef,
7492
- className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7664
+ className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
7493
7665
  children
7494
7666
  }),
7495
7667
  BoundFeather,
@@ -7753,9 +7925,17 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7753
7925
  const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
7754
7926
  const [lastConnectedThreadId, setLastConnectedThreadId] = useState(null);
7755
7927
  const isConnecting = hasExplicitThreadId && lastConnectedThreadId !== resolvedThreadId;
7928
+ const previousThreadIdRef = useRef(null);
7929
+ const hasExplicitThreadIdRef = useRef(hasExplicitThreadId);
7930
+ hasExplicitThreadIdRef.current = hasExplicitThreadId;
7756
7931
  useEffect(() => {
7932
+ const threadChanged = previousThreadIdRef.current !== resolvedThreadId;
7933
+ previousThreadIdRef.current = resolvedThreadId;
7757
7934
  agent.threadId = resolvedThreadId;
7758
- if (!hasExplicitThreadId) return;
7935
+ if (!hasExplicitThreadId) {
7936
+ if (threadChanged && agent.messages.length > 0) agent.setMessages([]);
7937
+ return;
7938
+ }
7759
7939
  let detached = false;
7760
7940
  const connectAbortController = new AbortController();
7761
7941
  if (agent instanceof HttpAgent) agent.abortController = connectAbortController;
@@ -7769,6 +7949,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
7769
7949
  if (!detached) (typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 16))(() => {
7770
7950
  if (!detached) setLastConnectedThreadId(resolvedThreadId);
7771
7951
  });
7952
+ else if (!hasExplicitThreadIdRef.current) agentToConnect.setMessages([]);
7772
7953
  }
7773
7954
  };
7774
7955
  connect(agent);
@@ -8119,18 +8300,46 @@ CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
8119
8300
 
8120
8301
  //#endregion
8121
8302
  //#region src/v2/components/chat/CopilotModalHeader.tsx
8122
- function CopilotModalHeader({ title, titleContent, closeButton, children, className, ...rest }) {
8303
+ /**
8304
+ * Reactively tracks whether the viewport is in the mobile range (≤767px) — the
8305
+ * same breakpoint the drawer + chat coordination use. SSR-safe: starts `false`
8306
+ * (desktop) so the server render and first client render agree, then syncs on
8307
+ * mount and on resize.
8308
+ */
8309
+ function useIsMobileViewport() {
8310
+ const [isMobile, setIsMobile] = useState(false);
8311
+ useEffect(() => {
8312
+ if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
8313
+ const mql = window.matchMedia("(max-width: 767px)");
8314
+ const update = () => setIsMobile(mql.matches);
8315
+ update();
8316
+ mql.addEventListener("change", update);
8317
+ return () => mql.removeEventListener("change", update);
8318
+ }, []);
8319
+ return isMobile;
8320
+ }
8321
+ function CopilotModalHeader({ title, titleContent, closeButton, drawerLauncher, children, className, ...rest }) {
8123
8322
  const configuration = useCopilotChatConfiguration();
8124
8323
  const fallbackTitle = configuration?.labels.modalHeaderTitle ?? CopilotChatDefaultLabels.modalHeaderTitle;
8125
8324
  const resolvedTitle = title ?? fallbackTitle;
8325
+ const isMobile = useIsMobileViewport();
8326
+ const drawerRegistered = (configuration?.drawerRegistered ?? false) && isMobile;
8126
8327
  const handleClose = useCallback(() => {
8127
8328
  configuration?.setModalOpen?.(false);
8128
8329
  }, [configuration]);
8330
+ const handleToggleDrawer = useCallback(() => {
8331
+ configuration?.setDrawerOpen?.(!configuration.drawerOpen);
8332
+ }, [configuration]);
8129
8333
  const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, { children: resolvedTitle });
8130
8334
  const BoundCloseButton = renderSlot(closeButton, CopilotModalHeader.CloseButton, { onClick: handleClose });
8335
+ const BoundDrawerLauncher = drawerRegistered ? renderSlot(drawerLauncher, CopilotModalHeader.DrawerLauncher, {
8336
+ onClick: handleToggleDrawer,
8337
+ "aria-expanded": configuration?.drawerOpen ?? false
8338
+ }) : null;
8131
8339
  if (children) return children({
8132
8340
  titleContent: BoundTitle,
8133
8341
  closeButton: BoundCloseButton,
8342
+ drawerLauncher: BoundDrawerLauncher,
8134
8343
  title: resolvedTitle,
8135
8344
  ...rest
8136
8345
  });
@@ -8143,8 +8352,8 @@ function CopilotModalHeader({ title, titleContent, closeButton, children, classN
8143
8352
  className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-2",
8144
8353
  children: [
8145
8354
  /* @__PURE__ */ jsx("div", {
8146
- className: "cpk:flex-1",
8147
- "aria-hidden": "true"
8355
+ className: "cpk:flex cpk:flex-1 cpk:justify-start",
8356
+ children: BoundDrawerLauncher ?? /* @__PURE__ */ jsx("span", { "aria-hidden": "true" })
8148
8357
  }),
8149
8358
  /* @__PURE__ */ jsx("div", {
8150
8359
  className: "cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center",
@@ -8177,9 +8386,21 @@ CopilotModalHeader.displayName = "CopilotModalHeader";
8177
8386
  "aria-hidden": "true"
8178
8387
  })
8179
8388
  });
8389
+ _CopilotModalHeader.DrawerLauncher = ({ className, ...props }) => /* @__PURE__ */ jsx("button", {
8390
+ type: "button",
8391
+ "data-testid": "copilot-threads-drawer-launcher",
8392
+ className: cn("cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer", "cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring", className),
8393
+ "aria-label": "Open threads",
8394
+ ...props,
8395
+ children: /* @__PURE__ */ jsx(PanelLeftOpen, {
8396
+ className: "cpk:h-4 cpk:w-4",
8397
+ "aria-hidden": "true"
8398
+ })
8399
+ });
8180
8400
  })(CopilotModalHeader || (CopilotModalHeader = {}));
8181
8401
  CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
8182
8402
  CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
8403
+ CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLauncher";
8183
8404
 
8184
8405
  //#endregion
8185
8406
  //#region src/v2/components/chat/CopilotSidebarView.tsx
@@ -8537,6 +8758,322 @@ function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickO
8537
8758
  }
8538
8759
  CopilotPopup.displayName = "CopilotPopup";
8539
8760
 
8761
+ //#endregion
8762
+ //#region src/v2/components/chat/CopilotThreadsDrawer.tsx
8763
+ /**
8764
+ * Maps a {@link Thread} from {@link useThreads} to the element's
8765
+ * {@link DrawerThread} view shape. The shapes are structurally compatible; this
8766
+ * narrows to exactly the fields the element renders so the element never sees
8767
+ * platform-internal fields.
8768
+ */
8769
+ function toDrawerThread(thread) {
8770
+ return {
8771
+ id: thread.id,
8772
+ name: thread.name,
8773
+ archived: thread.archived,
8774
+ createdAt: thread.createdAt,
8775
+ updatedAt: thread.updatedAt,
8776
+ ...thread.lastRunAt !== void 0 ? { lastRunAt: thread.lastRunAt } : {}
8777
+ };
8778
+ }
8779
+ /** The chat input textarea's documented `data-testid`. */
8780
+ const CHAT_INPUT_TESTID = "copilot-chat-textarea";
8781
+ /** The chat view container's documented `data-testid`. */
8782
+ const CHAT_CONTAINER_TESTID = "copilot-chat";
8783
+ /**
8784
+ * Returns the chat input element for focus-return after a thread is selected.
8785
+ *
8786
+ * Best-effort and SCOPED: walks up from the drawer element looking for an
8787
+ * ancestor that contains a chat-view container (`data-testid="copilot-chat"`),
8788
+ * then returns the chat input within that subtree. This avoids focusing the
8789
+ * wrong composer on a page hosting more than one chat (multi-chat dashboards),
8790
+ * where a document-global lookup would grab whichever input appears first in
8791
+ * DOM order rather than the one this drawer drives.
8792
+ *
8793
+ * Falls back to a document-global lookup when no scoping ancestor is found
8794
+ * (e.g. the drawer and chat share no common container, or headless usage),
8795
+ * and returns `null` when there is no chat input at all.
8796
+ *
8797
+ * @param origin - The drawer element to scope the search from.
8798
+ */
8799
+ function findChatInput(origin) {
8800
+ if (typeof document === "undefined") return null;
8801
+ const container = origin?.closest?.(`[data-testid="${CHAT_CONTAINER_TESTID}"]`);
8802
+ if (container) {
8803
+ const scoped = container.querySelector(`[data-testid="${CHAT_INPUT_TESTID}"]`);
8804
+ if (scoped) return scoped;
8805
+ }
8806
+ return document.querySelector(`[data-testid="${CHAT_INPUT_TESTID}"]`);
8807
+ }
8808
+ /**
8809
+ * React wrapper for the shadow-DOM `<copilotkit-threads-drawer>` threads drawer.
8810
+ *
8811
+ * Responsibilities:
8812
+ * - Registers the custom element on the client (SSR-safe; nothing renders
8813
+ * during prerender to avoid hydration mismatch).
8814
+ * - Feeds the element domain data: `threads`, `loading`, `error`,
8815
+ * `activeThreadId`, `licensed`, fetch-more state.
8816
+ * - Routes the element's nine outbound events to core thread operations
8817
+ * ({@link useThreads}) and chat-configuration changes.
8818
+ * - Registers with the surrounding chat configuration so the header
8819
+ * thread-list launcher appears, and binds the element `open` state to the
8820
+ * configuration's `drawerOpen`.
8821
+ *
8822
+ * License gating is two-pronged: the locked view shows when no license is configured
8823
+ * (the runtime reported no license status) OR the `threads` feature is
8824
+ * explicitly unlicensed. While unlicensed, the thread fetch is skipped entirely
8825
+ * so an unlicensed drawer issues no network requests.
8826
+ *
8827
+ * Thread switching needs no host wiring: when `onThreadSelect`/`onNewThread`
8828
+ * are omitted, the wrapper drives the surrounding chat configuration directly
8829
+ * ({@link CopilotChatConfigurationValue.setActiveThreadId} /
8830
+ * {@link CopilotChatConfigurationValue.startNewThread}), so a bare drawer
8831
+ * connects to the picked thread and shows the welcome screen on "+ New". Pass
8832
+ * the callbacks only to take control yourself.
8833
+ *
8834
+ * @example
8835
+ * ```tsx
8836
+ * // Callback-free: the drawer drives the chat configuration itself.
8837
+ * <CopilotKitProvider runtimeUrl="/api/copilotkit" publicLicenseKey="ck_pub_...">
8838
+ * <CopilotChat />
8839
+ * <CopilotThreadsDrawer />
8840
+ * </CopilotKitProvider>
8841
+ * ```
8842
+ */
8843
+ function CopilotThreadsDrawer({ agentId, onThreadSelect, onNewThread, onLicensed, licenseUrl, renderRow, label, limit, "data-testid": dataTestId = "copilot-threads-drawer" }) {
8844
+ const configuration = useCopilotChatConfiguration();
8845
+ const { status, checkFeature } = useLicenseContext();
8846
+ const licensePresent = status === "valid" || status === "expiring";
8847
+ const featureLicensed = checkFeature("threads");
8848
+ const licensed = licensePresent && featureLicensed;
8849
+ const licensePending = status === null;
8850
+ const resolvedAgentId = agentId ?? configuration?.agentId ?? "default";
8851
+ const activeThreadId = configuration?.threadId ?? null;
8852
+ const { threads, isLoading, listError, hasMoreThreads, isFetchingMoreThreads, archiveThread, unarchiveThread, deleteThread, fetchMoreThreads, refetchThreads, startNewThread } = useThreads$1({
8853
+ agentId: resolvedAgentId,
8854
+ includeArchived: true,
8855
+ enabled: licensed,
8856
+ ...limit !== void 0 ? { limit } : {}
8857
+ });
8858
+ const drawerThreads = useMemo(() => threads.map(toDrawerThread), [threads]);
8859
+ const elementRef = useRef(null);
8860
+ const [mounted, setMounted] = useState(false);
8861
+ useEffect(() => {
8862
+ defineCopilotKitThreadsDrawer();
8863
+ setMounted(true);
8864
+ }, []);
8865
+ const registerDrawer = configuration?.registerDrawer;
8866
+ useEffect(() => {
8867
+ if (!registerDrawer) return;
8868
+ return registerDrawer();
8869
+ }, [registerDrawer]);
8870
+ const [localDrawerOpen, setLocalDrawerOpen] = useState(false);
8871
+ const drawerOpen = configuration ? configuration.drawerOpen : localDrawerOpen;
8872
+ const setDrawerOpen = configuration ? configuration.setDrawerOpen : setLocalDrawerOpen;
8873
+ const setActiveThreadId = configuration?.setActiveThreadId;
8874
+ const startNewThreadConfig = configuration?.startNewThread;
8875
+ const handleThreadSelected = useCallback((threadId) => {
8876
+ if (onThreadSelect) onThreadSelect(threadId);
8877
+ else setActiveThreadId?.(threadId, { explicit: true });
8878
+ findChatInput(elementRef.current)?.focus();
8879
+ }, [onThreadSelect, setActiveThreadId]);
8880
+ const handleNewThread = useCallback(() => {
8881
+ startNewThread();
8882
+ if (onNewThread) onNewThread();
8883
+ else startNewThreadConfig?.();
8884
+ }, [
8885
+ startNewThread,
8886
+ onNewThread,
8887
+ startNewThreadConfig
8888
+ ]);
8889
+ const handleArchive = useCallback((threadId) => {
8890
+ archiveThread(threadId).catch((err) => {
8891
+ console.error("CopilotThreadsDrawer: archiveThread failed", err);
8892
+ });
8893
+ }, [archiveThread]);
8894
+ const handleUnarchive = useCallback((threadId) => {
8895
+ unarchiveThread(threadId).catch((err) => {
8896
+ console.error("CopilotThreadsDrawer: unarchiveThread failed", err);
8897
+ });
8898
+ }, [unarchiveThread]);
8899
+ const handleDelete = useCallback((threadId) => {
8900
+ const isActive = threadId === activeThreadId;
8901
+ deleteThread(threadId).then(() => {
8902
+ if (isActive) {
8903
+ startNewThread();
8904
+ if (onNewThread) onNewThread();
8905
+ else startNewThreadConfig?.();
8906
+ }
8907
+ }).catch((err) => {
8908
+ console.error("CopilotThreadsDrawer: deleteThread failed", err);
8909
+ });
8910
+ }, [
8911
+ deleteThread,
8912
+ activeThreadId,
8913
+ startNewThread,
8914
+ onNewThread,
8915
+ startNewThreadConfig
8916
+ ]);
8917
+ const handleFilterChange = useCallback(() => {
8918
+ refetchThreads();
8919
+ }, [refetchThreads]);
8920
+ const handleRetry = useCallback((scope) => {
8921
+ if (scope === "fetch-more") fetchMoreThreads();
8922
+ else refetchThreads();
8923
+ }, [fetchMoreThreads, refetchThreads]);
8924
+ const handleOpenChange = useCallback((open) => {
8925
+ setDrawerOpen(open);
8926
+ }, [setDrawerOpen]);
8927
+ const handleLicensed = useCallback(() => {
8928
+ onLicensed?.();
8929
+ }, [onLicensed]);
8930
+ const handleLoadMore = useCallback(() => {
8931
+ fetchMoreThreads();
8932
+ }, [fetchMoreThreads]);
8933
+ const handlersRef = useRef({
8934
+ handleThreadSelected,
8935
+ handleNewThread,
8936
+ handleArchive,
8937
+ handleUnarchive,
8938
+ handleDelete,
8939
+ handleFilterChange,
8940
+ handleRetry,
8941
+ handleOpenChange,
8942
+ handleLicensed,
8943
+ handleLoadMore
8944
+ });
8945
+ handlersRef.current = {
8946
+ handleThreadSelected,
8947
+ handleNewThread,
8948
+ handleArchive,
8949
+ handleUnarchive,
8950
+ handleDelete,
8951
+ handleFilterChange,
8952
+ handleRetry,
8953
+ handleOpenChange,
8954
+ handleLicensed,
8955
+ handleLoadMore
8956
+ };
8957
+ useEffect(() => {
8958
+ const el = elementRef.current;
8959
+ if (!el) return;
8960
+ const onThreadSelected = (event) => {
8961
+ const detail = event.detail;
8962
+ handlersRef.current.handleThreadSelected(detail.threadId);
8963
+ };
8964
+ const onNewThreadEvent = () => handlersRef.current.handleNewThread();
8965
+ const onArchive = (event) => {
8966
+ const detail = event.detail;
8967
+ handlersRef.current.handleArchive(detail.threadId);
8968
+ };
8969
+ const onUnarchive = (event) => {
8970
+ const detail = event.detail;
8971
+ handlersRef.current.handleUnarchive(detail.threadId);
8972
+ };
8973
+ const onDelete = (event) => {
8974
+ const detail = event.detail;
8975
+ handlersRef.current.handleDelete(detail.threadId);
8976
+ };
8977
+ const onFilterChange = (_event) => {
8978
+ handlersRef.current.handleFilterChange();
8979
+ };
8980
+ const onOpenChangeEvent = (event) => {
8981
+ const detail = event.detail;
8982
+ handlersRef.current.handleOpenChange(detail.open);
8983
+ };
8984
+ const onRetry = (event) => {
8985
+ const detail = event.detail;
8986
+ handlersRef.current.handleRetry(detail.scope);
8987
+ };
8988
+ const onLicensedEvent = () => handlersRef.current.handleLicensed();
8989
+ const onLoadMore = () => handlersRef.current.handleLoadMore();
8990
+ el.addEventListener("thread-selected", onThreadSelected);
8991
+ el.addEventListener("new-thread", onNewThreadEvent);
8992
+ el.addEventListener("archive", onArchive);
8993
+ el.addEventListener("unarchive", onUnarchive);
8994
+ el.addEventListener("delete", onDelete);
8995
+ el.addEventListener("filter-change", onFilterChange);
8996
+ el.addEventListener("open-change", onOpenChangeEvent);
8997
+ el.addEventListener("retry", onRetry);
8998
+ el.addEventListener("licensed", onLicensedEvent);
8999
+ el.addEventListener("load-more", onLoadMore);
9000
+ return () => {
9001
+ el.removeEventListener("thread-selected", onThreadSelected);
9002
+ el.removeEventListener("new-thread", onNewThreadEvent);
9003
+ el.removeEventListener("archive", onArchive);
9004
+ el.removeEventListener("unarchive", onUnarchive);
9005
+ el.removeEventListener("delete", onDelete);
9006
+ el.removeEventListener("filter-change", onFilterChange);
9007
+ el.removeEventListener("open-change", onOpenChangeEvent);
9008
+ el.removeEventListener("retry", onRetry);
9009
+ el.removeEventListener("licensed", onLicensedEvent);
9010
+ el.removeEventListener("load-more", onLoadMore);
9011
+ };
9012
+ }, [mounted]);
9013
+ useEffect(() => {
9014
+ const el = elementRef.current;
9015
+ if (!el) return;
9016
+ el.threads = drawerThreads;
9017
+ }, [drawerThreads, mounted]);
9018
+ useEffect(() => {
9019
+ const el = elementRef.current;
9020
+ if (!el) return;
9021
+ el.loading = isLoading || licensePending;
9022
+ el.error = listError ? listError.message : null;
9023
+ el.activeThreadId = activeThreadId;
9024
+ el.licensed = licensed || licensePending;
9025
+ el.hasMore = hasMoreThreads;
9026
+ el.fetchingMore = isFetchingMoreThreads;
9027
+ }, [
9028
+ isLoading,
9029
+ listError,
9030
+ activeThreadId,
9031
+ licensed,
9032
+ licensePending,
9033
+ hasMoreThreads,
9034
+ isFetchingMoreThreads,
9035
+ mounted
9036
+ ]);
9037
+ useEffect(() => {
9038
+ const el = elementRef.current;
9039
+ if (!el) return;
9040
+ el.open = drawerOpen;
9041
+ }, [drawerOpen, mounted]);
9042
+ useEffect(() => {
9043
+ const el = elementRef.current;
9044
+ if (!el) return;
9045
+ if (label !== void 0) el.label = label;
9046
+ }, [label, mounted]);
9047
+ useEffect(() => {
9048
+ const el = elementRef.current;
9049
+ if (!el) return;
9050
+ if (licenseUrl !== void 0) el.licenseUrl = licenseUrl;
9051
+ }, [licenseUrl, mounted]);
9052
+ const rowChildren = useMemo(() => {
9053
+ if (!renderRow) return null;
9054
+ return drawerThreads.map((drawerThread) => {
9055
+ const fullThread = threads.find((t) => t.id === drawerThread.id);
9056
+ if (!fullThread) return null;
9057
+ const content = renderRow(fullThread);
9058
+ if (content === null || content === void 0) return null;
9059
+ return /* @__PURE__ */ jsx("div", {
9060
+ slot: `row:${drawerThread.id}`,
9061
+ children: content
9062
+ }, drawerThread.id);
9063
+ });
9064
+ }, [
9065
+ renderRow,
9066
+ drawerThreads,
9067
+ threads
9068
+ ]);
9069
+ if (!mounted) return null;
9070
+ return React.createElement(COPILOTKIT_THREADS_DRAWER_TAG, {
9071
+ ref: elementRef,
9072
+ "data-testid": dataTestId
9073
+ }, rowChildren);
9074
+ }
9075
+ CopilotThreadsDrawer.displayName = "CopilotThreadsDrawer";
9076
+
8540
9077
  //#endregion
8541
9078
  //#region src/v2/components/WildcardToolCallRender.tsx
8542
9079
  const WildcardToolCallRender = defineToolCallRenderer({
@@ -10719,5 +11256,5 @@ function validateProps(props) {
10719
11256
  }
10720
11257
 
10721
11258
  //#endregion
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 };
10723
- //# sourceMappingURL=copilotkit-Be-o2UaU.mjs.map
11259
+ export { UseAgentUpdate as $, CopilotChatMessageView as A, CopilotChatAssistantMessage_default as B, CopilotModalHeader as C, CopilotChatConfigurationProvider as Ct, CopilotChat as D, DefaultOpenIcon as E, CopilotChatSuggestionView as F, useLearnFromUserActionInCurrentThread as G, useLearningContainersInCurrentThread as H, CopilotChatSuggestionPill as I, useInterrupt as J, useLearnFromUserAction as K, CopilotChatReasoningMessage_default as L, IntelligenceIndicator as M, getIntelligenceTurnAnchors as N, CopilotChatView_default as O, IntelligenceIndicatorView as P, useCapabilities as Q, CopilotChatUserMessage_default as R, CopilotSidebarView as S, CopilotChatAudioRecorder as St, DefaultCloseIcon as T, useLearningContainers as U, CopilotChatToolCallsView as V, useAttachments as W, useSuggestions as X, useConfigureSuggestions as Y, useAgentContext as Z, WildcardToolCallRender as _, useRenderToolCall as _t, ThreadsProvider as a, useFrontendTool as at, CopilotSidebar as b, CopilotChatInput_default as bt, CoAgentStateRendersProvider as c, CopilotKitProvider as ct, shouldShowDevConsole as d, SandboxFunctionsContext as dt, useAgent as et, useToast as f, useSandboxFunctions as ft, useCopilotContext as g, CopilotKitInspector as gt, CopilotContext as h, MCPAppsActivityType as ht, ThreadsContext as i, useComponent as it, INTELLIGENCE_TURN_HEAD as j, CopilotChatAttachmentQueue as k, useCoAgentStateRenders as l, defineToolCallRenderer as lt, useCopilotMessagesContext as m, MCPAppsActivityRenderer as mt, defaultCopilotContextCategories as n, useDefaultRenderTool as nt, useThreads as o, useRenderActivityMessage as ot, CopilotMessagesContext as p, MCPAppsActivityContentSchema as pt, useThreads$1 as q, CoAgentStateRenderBridge as r, useRenderTool as rt, CoAgentStateRendersContext as s, useRenderCustomMessages as st, CopilotKit as t, useHumanInTheLoop as tt, useAsyncCallback as u, createA2UIMessageRenderer as ut, CopilotThreadsDrawer as v, useCopilotKit as vt, CopilotChatToggleButton as w, useCopilotChatConfiguration as wt, CopilotPopupView as x, AudioRecorderError as xt, CopilotPopup as y, CopilotKitCoreReact as yt, CopilotChatAttachmentRenderer as z };
11260
+ //# sourceMappingURL=copilotkit-BtRkFsNR.mjs.map