@copilotkit/react-core 1.57.0 → 1.57.1-canary.1778272612

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 (86) hide show
  1. package/dist/{copilotkit-CPe2-340.mjs → copilotkit-3XTEoVQO.mjs} +1367 -1200
  2. package/dist/copilotkit-3XTEoVQO.mjs.map +1 -0
  3. package/dist/{copilotkit-DFaI4j2r.d.mts → copilotkit-BCJ2yvV6.d.mts} +68 -8
  4. package/dist/copilotkit-BCJ2yvV6.d.mts.map +1 -0
  5. package/dist/{copilotkit-Dg4r4Gi_.d.cts → copilotkit-CBbSvze0.d.cts} +68 -8
  6. package/dist/copilotkit-CBbSvze0.d.cts.map +1 -0
  7. package/dist/{copilotkit-DGbvw8n2.cjs → copilotkit-Dnj9pi4m.cjs} +1369 -1196
  8. package/dist/copilotkit-Dnj9pi4m.cjs.map +1 -0
  9. package/dist/index.cjs +2 -5
  10. package/dist/index.cjs.map +1 -1
  11. package/dist/index.d.cts +1 -1
  12. package/dist/index.d.mts +1 -1
  13. package/dist/index.mjs +2 -5
  14. package/dist/index.mjs.map +1 -1
  15. package/dist/index.umd.js +733 -610
  16. package/dist/index.umd.js.map +1 -1
  17. package/dist/v2/context.cjs +135 -0
  18. package/dist/v2/context.cjs.map +1 -0
  19. package/dist/v2/context.d.cts +148 -0
  20. package/dist/v2/context.d.cts.map +1 -0
  21. package/dist/v2/context.d.mts +148 -0
  22. package/dist/v2/context.d.mts.map +1 -0
  23. package/dist/v2/context.mjs +129 -0
  24. package/dist/v2/context.mjs.map +1 -0
  25. package/dist/v2/headless.cjs +1043 -0
  26. package/dist/v2/headless.cjs.map +1 -0
  27. package/dist/v2/headless.d.cts +605 -0
  28. package/dist/v2/headless.d.cts.map +1 -0
  29. package/dist/v2/headless.d.mts +512 -0
  30. package/dist/v2/headless.d.mts.map +1 -0
  31. package/dist/v2/headless.mjs +997 -0
  32. package/dist/v2/headless.mjs.map +1 -0
  33. package/dist/v2/index.cjs +2 -1
  34. package/dist/v2/index.css +1 -1
  35. package/dist/v2/index.d.cts +2 -2
  36. package/dist/v2/index.d.mts +2 -2
  37. package/dist/v2/index.mjs +2 -2
  38. package/dist/v2/index.umd.js +1385 -1204
  39. package/dist/v2/index.umd.js.map +1 -1
  40. package/package.json +14 -6
  41. package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +5 -6
  42. package/src/hooks/use-copilot-chat_internal.ts +0 -1
  43. package/src/v2/components/chat/CopilotChat.tsx +2 -1
  44. package/src/v2/components/chat/CopilotChatMessageView.tsx +24 -9
  45. package/src/v2/components/chat/CopilotChatView.tsx +2 -2
  46. package/src/v2/components/chat/CopilotSidebar.tsx +5 -1
  47. package/src/v2/components/chat/CopilotSidebarView.tsx +24 -10
  48. package/src/v2/components/chat/__tests__/CopilotChat.welcomeGate.test.tsx +1 -3
  49. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +29 -25
  50. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.tsx +159 -0
  51. package/src/v2/components/chat/__tests__/MCPAppsUiMessage.e2e.test.tsx +5 -60
  52. package/src/v2/components/index.ts +1 -0
  53. package/src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx +286 -0
  54. package/src/v2/components/intelligence-indicator/__tests__/IntelligenceIndicator.e2e.test.tsx +464 -0
  55. package/src/v2/components/intelligence-indicator/index.ts +2 -0
  56. package/src/v2/context.ts +62 -0
  57. package/src/v2/headless.ts +42 -0
  58. package/src/v2/hooks/__tests__/standard-schema.test.tsx +2 -2
  59. package/src/v2/hooks/__tests__/use-agent-context.test.tsx +3 -3
  60. package/src/v2/hooks/__tests__/use-agent-stability.test.tsx +3 -3
  61. package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +85 -85
  62. package/src/v2/hooks/__tests__/use-interrupt.test.tsx +2 -2
  63. package/src/v2/hooks/__tests__/use-render-tool.test.tsx +2 -2
  64. package/src/v2/hooks/__tests__/use-threads.test.tsx +2 -2
  65. package/src/v2/hooks/__tests__/zod-regression.test.tsx +2 -2
  66. package/src/v2/hooks/use-agent-context.tsx +1 -1
  67. package/src/v2/hooks/use-agent.tsx +9 -118
  68. package/src/v2/hooks/use-configure-suggestions.tsx +1 -1
  69. package/src/v2/hooks/use-default-render-tool.tsx +18 -1
  70. package/src/v2/hooks/use-frontend-tool.tsx +2 -2
  71. package/src/v2/hooks/use-human-in-the-loop.tsx +1 -1
  72. package/src/v2/hooks/use-interrupt.tsx +1 -1
  73. package/src/v2/hooks/use-render-activity-message.tsx +3 -11
  74. package/src/v2/hooks/use-render-custom-messages.tsx +1 -6
  75. package/src/v2/hooks/use-render-tool-call.tsx +36 -6
  76. package/src/v2/hooks/use-render-tool.tsx +2 -2
  77. package/src/v2/hooks/use-suggestions.tsx +1 -1
  78. package/src/v2/hooks/use-threads.tsx +1 -1
  79. package/src/v2/providers/CopilotKitProvider.tsx +19 -59
  80. package/src/v2/styles/globals.css +118 -0
  81. package/tsdown.config.ts +75 -0
  82. package/dist/copilotkit-CPe2-340.mjs.map +0 -1
  83. package/dist/copilotkit-DFaI4j2r.d.mts.map +0 -1
  84. package/dist/copilotkit-DGbvw8n2.cjs.map +0 -1
  85. package/dist/copilotkit-Dg4r4Gi_.d.cts.map +0 -1
  86. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +0 -333
@@ -1325,351 +1325,842 @@ function useKatexStyles() {
1325
1325
  }
1326
1326
 
1327
1327
  //#endregion
1328
- //#region src/v2/components/CopilotKitInspector.tsx
1329
- const CopilotKitInspector = ({ core, ...rest }) => {
1330
- const [InspectorComponent, setInspectorComponent] = react.useState(null);
1331
- react.useEffect(() => {
1332
- let mounted = true;
1333
- import("@copilotkit/web-inspector").then((mod) => {
1334
- mod.defineWebInspector?.();
1335
- const Component = (0, _lit_labs_react.createComponent)({
1336
- tagName: mod.WEB_INSPECTOR_TAG,
1337
- elementClass: mod.WebInspectorElement,
1338
- react
1328
+ //#region src/v2/lib/react-core.ts
1329
+ var CopilotKitCoreReact = class extends _copilotkit_core.CopilotKitCore {
1330
+ constructor(config) {
1331
+ super(config);
1332
+ this._renderToolCalls = [];
1333
+ this._hookRenderToolCalls = /* @__PURE__ */ new Map();
1334
+ this._cachedMergedRenderToolCalls = null;
1335
+ this._renderCustomMessages = [];
1336
+ this._renderActivityMessages = [];
1337
+ this._interruptElement = null;
1338
+ this._renderToolCalls = config.renderToolCalls ?? [];
1339
+ this._renderCustomMessages = config.renderCustomMessages ?? [];
1340
+ this._renderActivityMessages = config.renderActivityMessages ?? [];
1341
+ }
1342
+ get renderCustomMessages() {
1343
+ return this._renderCustomMessages;
1344
+ }
1345
+ get renderActivityMessages() {
1346
+ return this._renderActivityMessages;
1347
+ }
1348
+ get renderToolCalls() {
1349
+ if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
1350
+ if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
1351
+ const merged = /* @__PURE__ */ new Map();
1352
+ for (const rc of this._renderToolCalls) merged.set(`${rc.agentId ?? ""}:${rc.name}`, rc);
1353
+ for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
1354
+ this._cachedMergedRenderToolCalls = Array.from(merged.values());
1355
+ return this._cachedMergedRenderToolCalls;
1356
+ }
1357
+ setRenderActivityMessages(renderers) {
1358
+ this._renderActivityMessages = renderers;
1359
+ }
1360
+ setRenderCustomMessages(renderers) {
1361
+ this._renderCustomMessages = renderers;
1362
+ }
1363
+ setRenderToolCalls(renderToolCalls) {
1364
+ this._renderToolCalls = renderToolCalls;
1365
+ this._cachedMergedRenderToolCalls = null;
1366
+ this._notifyRenderToolCallsChanged();
1367
+ }
1368
+ addHookRenderToolCall(entry) {
1369
+ const key = `${entry.agentId ?? ""}:${entry.name}`;
1370
+ this._hookRenderToolCalls.set(key, entry);
1371
+ this._cachedMergedRenderToolCalls = null;
1372
+ this._notifyRenderToolCallsChanged();
1373
+ }
1374
+ removeHookRenderToolCall(name, agentId) {
1375
+ const key = `${agentId ?? ""}:${name}`;
1376
+ if (this._hookRenderToolCalls.delete(key)) {
1377
+ this._cachedMergedRenderToolCalls = null;
1378
+ this._notifyRenderToolCallsChanged();
1379
+ }
1380
+ }
1381
+ _notifyRenderToolCallsChanged() {
1382
+ this.notifySubscribers((subscriber) => {
1383
+ const reactSubscriber = subscriber;
1384
+ if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
1385
+ copilotkit: this,
1386
+ renderToolCalls: this.renderToolCalls
1339
1387
  });
1340
- if (mounted) setInspectorComponent(() => Component);
1341
- });
1342
- return () => {
1343
- mounted = false;
1344
- };
1345
- }, []);
1346
- if (!InspectorComponent) return null;
1347
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InspectorComponent, {
1348
- ...rest,
1349
- core: core ?? null
1350
- });
1388
+ }, "Subscriber onRenderToolCallsChanged error:");
1389
+ }
1390
+ get interruptElement() {
1391
+ return this._interruptElement;
1392
+ }
1393
+ setInterruptElement(element) {
1394
+ this._interruptElement = element;
1395
+ this.notifySubscribers((subscriber) => {
1396
+ subscriber.onInterruptElementChanged?.({
1397
+ copilotkit: this,
1398
+ interruptElement: this._interruptElement
1399
+ });
1400
+ }, "Subscriber onInterruptElementChanged error:");
1401
+ }
1402
+ subscribe(subscriber) {
1403
+ return super.subscribe(subscriber);
1404
+ }
1405
+ /**
1406
+ * Wait for pending React state updates before the follow-up agent run.
1407
+ *
1408
+ * When a frontend tool handler calls setState(), React 18 batches the update
1409
+ * and schedules a commit via its internal scheduler (MessageChannel). The
1410
+ * useAgentContext hook registers context via useLayoutEffect, which runs
1411
+ * synchronously after React commits that batch.
1412
+ *
1413
+ * Awaiting a zero-delay timeout yields to the macrotask queue. React's
1414
+ * MessageChannel task runs first, committing the pending state and running
1415
+ * useLayoutEffect (which updates the context store). The follow-up runAgent
1416
+ * call then reads fresh context.
1417
+ */
1418
+ async waitForPendingFrameworkUpdates() {
1419
+ await new Promise((resolve) => setTimeout(resolve, 0));
1420
+ }
1351
1421
  };
1352
- CopilotKitInspector.displayName = "CopilotKitInspector";
1353
1422
 
1354
1423
  //#endregion
1355
- //#region src/v2/components/license-warning-banner.tsx
1356
- const LICENSE_BANNER_OFFSET_PX = 52;
1357
- const LICENSE_BANNER_OFFSET_VAR = "--copilotkit-license-banner-offset";
1358
- const BANNER_STYLES = {
1359
- base: {
1360
- position: "fixed",
1361
- bottom: "8px",
1362
- left: "50%",
1363
- transform: "translateX(-50%)",
1364
- zIndex: 99999,
1365
- display: "inline-flex",
1366
- alignItems: "center",
1367
- gap: "12px",
1368
- whiteSpace: "nowrap",
1369
- padding: "8px 16px",
1370
- fontSize: "13px",
1371
- fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif",
1372
- borderRadius: "6px",
1373
- boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)"
1374
- },
1375
- info: {
1376
- backgroundColor: "#eff6ff",
1377
- border: "1px solid #93c5fd",
1378
- color: "#1e40af"
1379
- },
1380
- warning: {
1381
- backgroundColor: "#fffbeb",
1382
- border: "1px solid #fbbf24",
1383
- color: "#92400e"
1384
- },
1385
- critical: {
1386
- backgroundColor: "#fef2f2",
1387
- border: "1px solid #fca5a5",
1388
- color: "#991b1b"
1389
- }
1390
- };
1391
- function getSeverityStyle(severity) {
1392
- switch (severity) {
1393
- case "warning": return BANNER_STYLES.warning;
1394
- case "critical": return BANNER_STYLES.critical;
1395
- default: return BANNER_STYLES.info;
1396
- }
1397
- }
1398
- function BannerShell({ severity, message, actionLabel, actionUrl, onDismiss }) {
1424
+ //#region src/v2/context.ts
1425
+ const CopilotKitContext = (0, react.createContext)(null);
1426
+ const useCopilotKit = () => {
1427
+ const context = (0, react.useContext)(CopilotKitContext);
1428
+ const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
1429
+ if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
1399
1430
  (0, react.useEffect)(() => {
1400
- if (typeof document === "undefined") return;
1401
- const root = document.documentElement;
1402
- root.style.setProperty(LICENSE_BANNER_OFFSET_VAR, `${LICENSE_BANNER_OFFSET_PX}px`);
1431
+ const subscription = context.copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
1432
+ forceUpdate();
1433
+ } });
1403
1434
  return () => {
1404
- root.style.removeProperty(LICENSE_BANNER_OFFSET_VAR);
1435
+ subscription.unsubscribe();
1405
1436
  };
1406
1437
  }, []);
1407
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1408
- style: {
1409
- ...BANNER_STYLES.base,
1410
- ...getSeverityStyle(severity)
1411
- },
1412
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: message }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1413
- style: {
1414
- display: "flex",
1415
- gap: "8px",
1416
- alignItems: "center"
1417
- },
1418
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1419
- href: actionUrl,
1420
- target: "_blank",
1421
- rel: "noopener noreferrer",
1422
- style: {
1423
- fontWeight: 600,
1424
- textDecoration: "underline",
1425
- color: "inherit"
1426
- },
1427
- children: actionLabel
1428
- }), onDismiss && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1429
- onClick: onDismiss,
1430
- style: {
1431
- background: "none",
1432
- border: "none",
1433
- cursor: "pointer",
1434
- color: "inherit",
1435
- fontSize: "16px"
1436
- },
1437
- children: "×"
1438
- })]
1439
- })]
1440
- });
1441
- }
1442
- function LicenseWarningBanner({ type, featureName, expiryDate, graceRemaining, onDismiss }) {
1443
- switch (type) {
1444
- case "no_license": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1445
- severity: "info",
1446
- message: "Powered by CopilotKit",
1447
- actionLabel: "Get a license",
1448
- actionUrl: "https://copilotkit.ai/pricing",
1449
- onDismiss
1450
- });
1451
- case "feature_unlicensed": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1452
- severity: "warning",
1453
- message: `⚠ The "${featureName}" feature requires a CopilotKit license.`,
1454
- actionLabel: "Get a license",
1455
- actionUrl: "https://copilotkit.ai/pricing",
1456
- onDismiss
1457
- });
1458
- case "expiring": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1459
- severity: "warning",
1460
- message: `Your CopilotKit license expires in ${graceRemaining} day${graceRemaining !== 1 ? "s" : ""}. Please renew.`,
1461
- actionLabel: "Renew",
1462
- actionUrl: "https://cloud.copilotkit.ai",
1463
- onDismiss
1464
- });
1465
- case "expired": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1466
- severity: "critical",
1467
- message: `Your CopilotKit license expired${expiryDate ? ` on ${expiryDate}` : ""}. Please renew at copilotkit.ai/pricing`,
1468
- actionLabel: "Renew now",
1469
- actionUrl: "https://copilotkit.ai/pricing",
1470
- onDismiss
1471
- });
1472
- case "invalid": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1473
- severity: "critical",
1474
- message: "Invalid CopilotKit license token. Please check your configuration.",
1475
- actionLabel: "Get a license",
1476
- actionUrl: "https://copilotkit.ai/pricing",
1477
- onDismiss
1478
- });
1479
- default: return null;
1480
- }
1481
- }
1482
- function InlineFeatureWarning({ featureName }) {
1483
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1484
- style: {
1485
- padding: "8px 12px",
1486
- backgroundColor: "#fffbeb",
1487
- border: "1px solid #fbbf24",
1488
- borderRadius: "6px",
1489
- fontSize: "13px",
1490
- color: "#92400e",
1491
- fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"
1492
- },
1493
- children: [
1494
- "⚠ The \"",
1495
- featureName,
1496
- "\" feature requires a CopilotKit license.",
1497
- " ",
1498
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1499
- href: "https://copilotkit.ai/pricing",
1500
- target: "_blank",
1501
- rel: "noopener noreferrer",
1502
- style: {
1503
- color: "#b45309",
1504
- textDecoration: "underline"
1505
- },
1506
- children: "Get one at copilotkit.ai/pricing"
1507
- })
1508
- ]
1509
- });
1438
+ return context;
1439
+ };
1440
+ const LicenseContext = (0, react.createContext)({
1441
+ status: null,
1442
+ license: null,
1443
+ checkFeature: () => true,
1444
+ getLimit: () => null
1445
+ });
1446
+ const useLicenseContext = () => (0, react.useContext)(LicenseContext);
1447
+
1448
+ //#endregion
1449
+ //#region src/v2/types/defineToolCallRenderer.ts
1450
+ function defineToolCallRenderer(def) {
1451
+ const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
1452
+ return {
1453
+ name: def.name,
1454
+ args: argsSchema,
1455
+ render: def.render,
1456
+ ...def.agentId ? { agentId: def.agentId } : {}
1457
+ };
1510
1458
  }
1511
1459
 
1512
1460
  //#endregion
1513
- //#region src/v2/components/MCPAppsActivityRenderer.tsx
1514
- const PROTOCOL_VERSION = "2025-06-18";
1515
- function buildSandboxHTML(extraCspDomains) {
1516
- const baseScriptSrc = "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
1517
- const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
1518
- const extra = extraCspDomains?.length ? " " + extraCspDomains.join(" ") : "";
1519
- return `<!doctype html>
1520
- <html>
1521
- <head>
1522
- <meta charset="utf-8" />
1523
- <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data: blob: 'unsafe-inline'; media-src * blob: data:; font-src * blob: data:; script-src ${baseScriptSrc + extra}; style-src * blob: data: 'unsafe-inline'; connect-src *; frame-src ${baseFrameSrc + extra}; base-uri 'self';" />
1524
- <style>html,body{margin:0;padding:0;height:100%;width:100%;overflow:hidden}*{box-sizing:border-box}iframe{background-color:transparent;border:none;padding:0;overflow:hidden;width:100%;height:100%}</style>
1525
- </head>
1526
- <body>
1527
- <script>
1528
- if(window.self===window.top){throw new Error("This file must be used in an iframe.")}
1529
- const inner=document.createElement("iframe");
1530
- inner.style="width:100%;height:100%;border:none;";
1531
- inner.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms");
1532
- document.body.appendChild(inner);
1533
- window.addEventListener("message",async(event)=>{
1534
- if(event.source===window.parent){
1535
- if(event.data&&event.data.method==="ui/notifications/sandbox-resource-ready"){
1536
- const{html,sandbox}=event.data.params;
1537
- if(typeof sandbox==="string")inner.setAttribute("sandbox",sandbox);
1538
- if(typeof html==="string")inner.srcdoc=html;
1539
- }else if(inner&&inner.contentWindow){
1540
- inner.contentWindow.postMessage(event.data,"*");
1541
- }
1542
- }else if(event.source===inner.contentWindow){
1543
- window.parent.postMessage(event.data,"*");
1544
- }
1545
- });
1546
- window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-ready",params:{}},"*");
1547
- <\/script>
1548
- </body>
1549
- </html>`;
1550
- }
1461
+ //#region src/v2/hooks/use-render-tool.tsx
1462
+ const EMPTY_DEPS$1 = [];
1551
1463
  /**
1552
- * Queue for serializing MCP app requests to an agent.
1553
- * Ensures requests wait for the agent to stop running and are processed one at a time.
1464
+ * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
1465
+ *
1466
+ * Key behavior:
1467
+ * - deduplicates by `agentId:name` (latest registration wins),
1468
+ * - keeps renderer entries on cleanup so historical chat tool calls can still render,
1469
+ * - refreshes registration when `deps` change.
1470
+ *
1471
+ * @typeParam S - Schema type describing tool call parameters.
1472
+ * @param config - Renderer config for wildcard or named tools.
1473
+ * @param deps - Optional dependencies to refresh registration.
1474
+ *
1475
+ * @example
1476
+ * ```tsx
1477
+ * useRenderTool(
1478
+ * {
1479
+ * name: "searchDocs",
1480
+ * parameters: z.object({ query: z.string() }),
1481
+ * render: ({ status, parameters, result }) => {
1482
+ * if (status === "executing") return <div>Searching {parameters.query}</div>;
1483
+ * if (status === "complete") return <div>{result}</div>;
1484
+ * return <div>Preparing...</div>;
1485
+ * },
1486
+ * },
1487
+ * [],
1488
+ * );
1489
+ * ```
1490
+ *
1491
+ * @example
1492
+ * ```tsx
1493
+ * useRenderTool(
1494
+ * {
1495
+ * name: "summarize",
1496
+ * parameters: z.object({ text: z.string() }),
1497
+ * agentId: "research-agent",
1498
+ * render: ({ name, status }) => <div>{name}: {status}</div>,
1499
+ * },
1500
+ * [selectedAgentId],
1501
+ * );
1502
+ * ```
1554
1503
  */
1555
- var MCPAppsRequestQueue = class {
1556
- constructor() {
1557
- this.queues = /* @__PURE__ */ new Map();
1558
- this.processing = /* @__PURE__ */ new Map();
1559
- }
1560
- /**
1561
- * Add a request to the queue for a specific agent thread.
1562
- * Returns a promise that resolves when the request completes.
1563
- */
1564
- async enqueue(agent, request) {
1565
- const threadId = agent.threadId || "default";
1566
- return new Promise((resolve, reject) => {
1567
- let queue = this.queues.get(threadId);
1568
- if (!queue) {
1569
- queue = [];
1570
- this.queues.set(threadId, queue);
1571
- }
1572
- queue.push({
1573
- execute: request,
1574
- resolve,
1575
- reject
1576
- });
1577
- this.processQueue(threadId, agent);
1578
- });
1579
- }
1580
- async processQueue(threadId, agent) {
1581
- if (this.processing.get(threadId)) return;
1582
- this.processing.set(threadId, true);
1583
- try {
1584
- const queue = this.queues.get(threadId);
1585
- if (!queue) return;
1586
- while (queue.length > 0) {
1587
- const item = queue[0];
1588
- try {
1589
- await this.waitForAgentIdle(agent);
1590
- const result = await item.execute();
1591
- item.resolve(result);
1592
- } catch (error) {
1593
- item.reject(error instanceof Error ? error : new Error(String(error)));
1594
- }
1595
- queue.shift();
1596
- }
1597
- } finally {
1598
- this.processing.set(threadId, false);
1599
- }
1600
- }
1601
- waitForAgentIdle(agent) {
1602
- return new Promise((resolve) => {
1603
- if (!agent.isRunning) {
1604
- resolve();
1605
- return;
1606
- }
1607
- let done = false;
1608
- const finish = () => {
1609
- if (done) return;
1610
- done = true;
1611
- clearInterval(checkInterval);
1612
- sub.unsubscribe();
1613
- resolve();
1614
- };
1615
- const sub = agent.subscribe({
1616
- onRunFinalized: finish,
1617
- onRunFailed: finish
1618
- });
1619
- const checkInterval = setInterval(() => {
1620
- if (!agent.isRunning) finish();
1621
- }, 500);
1504
+ function useRenderTool(config, deps) {
1505
+ const { copilotkit } = useCopilotKit();
1506
+ const extraDeps = deps ?? EMPTY_DEPS$1;
1507
+ (0, react.useEffect)(() => {
1508
+ const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
1509
+ name: "*",
1510
+ render: (props) => config.render({
1511
+ ...props,
1512
+ parameters: props.args
1513
+ }),
1514
+ ...config.agentId ? { agentId: config.agentId } : {}
1515
+ }) : defineToolCallRenderer({
1516
+ name: config.name,
1517
+ args: config.parameters,
1518
+ render: (props) => config.render({
1519
+ ...props,
1520
+ parameters: props.args
1521
+ }),
1522
+ ...config.agentId ? { agentId: config.agentId } : {}
1622
1523
  });
1623
- }
1624
- };
1625
- const mcpAppsRequestQueue = new MCPAppsRequestQueue();
1626
- /**
1627
- * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType
1628
- */
1629
- const MCPAppsActivityType = "mcp-apps";
1630
- const MCPAppsActivityContentSchema = zod.z.object({
1631
- result: zod.z.object({
1632
- content: zod.z.array(zod.z.any()).optional(),
1633
- structuredContent: zod.z.any().optional(),
1634
- isError: zod.z.boolean().optional()
1635
- }),
1636
- resourceUri: zod.z.string(),
1637
- serverHash: zod.z.string(),
1638
- serverId: zod.z.string().optional(),
1639
- toolInput: zod.z.record(zod.z.unknown()).optional()
1640
- });
1641
- function isRequest(msg) {
1642
- return "id" in msg && "method" in msg;
1643
- }
1644
- function isNotification(msg) {
1645
- return !("id" in msg) && "method" in msg;
1524
+ copilotkit.addHookRenderToolCall(renderer);
1525
+ }, [
1526
+ config.name,
1527
+ copilotkit,
1528
+ JSON.stringify(extraDeps)
1529
+ ]);
1646
1530
  }
1531
+
1532
+ //#endregion
1533
+ //#region src/v2/hooks/use-default-render-tool.tsx
1647
1534
  /**
1648
- * MCP Apps Extension Activity Renderer
1535
+ * Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
1649
1536
  *
1650
- * Renders MCP Apps UI in a sandboxed iframe with full protocol support.
1651
- * Fetches resource content on-demand via proxied MCP requests.
1652
- */
1653
- const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agent }) {
1654
- const { copilotkit } = useCopilotKit();
1655
- const containerRef = (0, react.useRef)(null);
1656
- const iframeRef = (0, react.useRef)(null);
1657
- const [iframeReady, setIframeReady] = (0, react.useState)(false);
1658
- const [error, setError] = (0, react.useState)(null);
1659
- const [isLoading, setIsLoading] = (0, react.useState)(true);
1660
- const [iframeSize, setIframeSize] = (0, react.useState)({});
1661
- const [fetchedResource, setFetchedResource] = (0, react.useState)(null);
1662
- const contentRef = (0, react.useRef)(content);
1663
- contentRef.current = content;
1664
- const agentRef = (0, react.useRef)(agent);
1665
- agentRef.current = agent;
1666
- const fetchStateRef = (0, react.useRef)({
1667
- inProgress: false,
1668
- promise: null,
1669
- resourceUri: null
1670
- });
1671
- const sendToIframe = (0, react.useCallback)((msg) => {
1672
- if (iframeRef.current?.contentWindow) {
1537
+ * - Call with no config to use CopilotKit's built-in default tool-call card.
1538
+ * - Pass `config.render` to replace the default UI with your own fallback renderer.
1539
+ *
1540
+ * This is useful when you want a generic renderer for tools that do not have a
1541
+ * dedicated `useRenderTool({ name: "..." })` registration.
1542
+ *
1543
+ * @param config - Optional custom wildcard render function.
1544
+ * @param deps - Optional dependencies to refresh registration.
1545
+ *
1546
+ * @example
1547
+ * ```tsx
1548
+ * useDefaultRenderTool();
1549
+ * ```
1550
+ *
1551
+ * @example
1552
+ * ```tsx
1553
+ * useDefaultRenderTool({
1554
+ * render: ({ name, status }) => <div>{name}: {status}</div>,
1555
+ * });
1556
+ * ```
1557
+ *
1558
+ * @example
1559
+ * ```tsx
1560
+ * useDefaultRenderTool(
1561
+ * {
1562
+ * render: ({ name, result }) => (
1563
+ * <ToolEventRow title={name} payload={result} compact={compactMode} />
1564
+ * ),
1565
+ * },
1566
+ * [compactMode],
1567
+ * );
1568
+ * ```
1569
+ */
1570
+ function useDefaultRenderTool(config, deps) {
1571
+ useRenderTool({
1572
+ name: "*",
1573
+ render: config?.render ?? DefaultToolCallRenderer
1574
+ }, deps);
1575
+ }
1576
+ function DefaultToolCallRenderer({ name, parameters, status, result }) {
1577
+ const [isExpanded, setIsExpanded] = (0, react.useState)(false);
1578
+ const statusString = String(status);
1579
+ const isActive = statusString === "inProgress" || statusString === "executing";
1580
+ const isComplete = statusString === "complete";
1581
+ const statusLabel = isActive ? "Running" : isComplete ? "Done" : status;
1582
+ const dotColor = isActive ? "#f59e0b" : isComplete ? "#10b981" : "#a1a1aa";
1583
+ const badgeBg = isActive ? "#fef3c7" : isComplete ? "#d1fae5" : "#f4f4f5";
1584
+ const badgeColor = isActive ? "#92400e" : isComplete ? "#065f46" : "#3f3f46";
1585
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1586
+ "data-testid": "copilot-tool-render",
1587
+ "data-tool-name": name,
1588
+ "data-status": statusString,
1589
+ "data-args": safeStringifyForAttr(parameters),
1590
+ "data-result": safeStringifyForAttr(result),
1591
+ style: {
1592
+ marginTop: "8px",
1593
+ paddingBottom: "8px"
1594
+ },
1595
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1596
+ style: {
1597
+ borderRadius: "12px",
1598
+ border: "1px solid #e4e4e7",
1599
+ backgroundColor: "#fafafa",
1600
+ padding: "14px 16px"
1601
+ },
1602
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1603
+ onClick: () => setIsExpanded(!isExpanded),
1604
+ style: {
1605
+ display: "flex",
1606
+ alignItems: "center",
1607
+ justifyContent: "space-between",
1608
+ gap: "10px",
1609
+ cursor: "pointer",
1610
+ userSelect: "none"
1611
+ },
1612
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1613
+ style: {
1614
+ display: "flex",
1615
+ alignItems: "center",
1616
+ gap: "8px",
1617
+ minWidth: 0
1618
+ },
1619
+ children: [
1620
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
1621
+ style: {
1622
+ height: "14px",
1623
+ width: "14px",
1624
+ color: "#71717a",
1625
+ transition: "transform 0.15s",
1626
+ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
1627
+ flexShrink: 0
1628
+ },
1629
+ fill: "none",
1630
+ viewBox: "0 0 24 24",
1631
+ strokeWidth: 2,
1632
+ stroke: "currentColor",
1633
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1634
+ strokeLinecap: "round",
1635
+ strokeLinejoin: "round",
1636
+ d: "M8.25 4.5l7.5 7.5-7.5 7.5"
1637
+ })
1638
+ }),
1639
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: {
1640
+ display: "inline-block",
1641
+ height: "8px",
1642
+ width: "8px",
1643
+ borderRadius: "50%",
1644
+ backgroundColor: dotColor,
1645
+ flexShrink: 0
1646
+ } }),
1647
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1648
+ "data-testid": "copilot-tool-render-name",
1649
+ style: {
1650
+ fontSize: "13px",
1651
+ fontWeight: 600,
1652
+ color: "#18181b",
1653
+ overflow: "hidden",
1654
+ textOverflow: "ellipsis",
1655
+ whiteSpace: "nowrap"
1656
+ },
1657
+ children: name
1658
+ })
1659
+ ]
1660
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1661
+ "data-testid": "copilot-tool-render-status",
1662
+ style: {
1663
+ display: "inline-flex",
1664
+ alignItems: "center",
1665
+ borderRadius: "9999px",
1666
+ padding: "2px 8px",
1667
+ fontSize: "11px",
1668
+ fontWeight: 500,
1669
+ backgroundColor: badgeBg,
1670
+ color: badgeColor,
1671
+ flexShrink: 0
1672
+ },
1673
+ children: statusLabel
1674
+ })]
1675
+ }), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1676
+ style: {
1677
+ marginTop: "12px",
1678
+ display: "grid",
1679
+ gap: "12px"
1680
+ },
1681
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1682
+ style: {
1683
+ fontSize: "10px",
1684
+ textTransform: "uppercase",
1685
+ letterSpacing: "0.05em",
1686
+ color: "#71717a"
1687
+ },
1688
+ children: "Arguments"
1689
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
1690
+ style: {
1691
+ marginTop: "6px",
1692
+ maxHeight: "200px",
1693
+ overflow: "auto",
1694
+ borderRadius: "6px",
1695
+ backgroundColor: "#f4f4f5",
1696
+ padding: "10px",
1697
+ fontSize: "11px",
1698
+ lineHeight: 1.6,
1699
+ color: "#27272a",
1700
+ whiteSpace: "pre-wrap",
1701
+ wordBreak: "break-word"
1702
+ },
1703
+ children: JSON.stringify(parameters ?? {}, null, 2)
1704
+ })] }), result !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1705
+ style: {
1706
+ fontSize: "10px",
1707
+ textTransform: "uppercase",
1708
+ letterSpacing: "0.05em",
1709
+ color: "#71717a"
1710
+ },
1711
+ children: "Result"
1712
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
1713
+ style: {
1714
+ marginTop: "6px",
1715
+ maxHeight: "200px",
1716
+ overflow: "auto",
1717
+ borderRadius: "6px",
1718
+ backgroundColor: "#f4f4f5",
1719
+ padding: "10px",
1720
+ fontSize: "11px",
1721
+ lineHeight: 1.6,
1722
+ color: "#27272a",
1723
+ whiteSpace: "pre-wrap",
1724
+ wordBreak: "break-word"
1725
+ },
1726
+ children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
1727
+ })] })]
1728
+ })]
1729
+ })
1730
+ });
1731
+ }
1732
+ function safeStringifyForAttr(value) {
1733
+ if (value === void 0 || value === null) return "";
1734
+ if (typeof value === "string") return value;
1735
+ try {
1736
+ return JSON.stringify(value);
1737
+ } catch {
1738
+ return String(value);
1739
+ }
1740
+ }
1741
+
1742
+ //#endregion
1743
+ //#region src/v2/hooks/use-render-tool-call.tsx
1744
+ /**
1745
+ * Memoized component that renders a single tool call.
1746
+ * This prevents unnecessary re-renders when parent components update
1747
+ * but the tool call data hasn't changed.
1748
+ */
1749
+ const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
1750
+ const args = (0, react.useMemo)(() => (0, _copilotkit_shared.partialJSONParse)(toolCall.function.arguments), [toolCall.function.arguments]);
1751
+ const toolName = toolCall.function.name;
1752
+ if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1753
+ name: toolName,
1754
+ toolCallId: toolCall.id,
1755
+ args,
1756
+ status: _copilotkit_core.ToolCallStatus.Complete,
1757
+ result: toolMessage.content
1758
+ });
1759
+ else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1760
+ name: toolName,
1761
+ toolCallId: toolCall.id,
1762
+ args,
1763
+ status: _copilotkit_core.ToolCallStatus.Executing,
1764
+ result: void 0
1765
+ });
1766
+ else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1767
+ name: toolName,
1768
+ toolCallId: toolCall.id,
1769
+ args,
1770
+ status: _copilotkit_core.ToolCallStatus.InProgress,
1771
+ result: void 0
1772
+ });
1773
+ }, (prevProps, nextProps) => {
1774
+ if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
1775
+ if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
1776
+ if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
1777
+ if (prevProps.toolMessage?.content !== nextProps.toolMessage?.content) return false;
1778
+ if (prevProps.isExecuting !== nextProps.isExecuting) return false;
1779
+ if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
1780
+ return true;
1781
+ });
1782
+ /**
1783
+ * Hook that returns a function to render tool calls based on the render functions
1784
+ * defined in CopilotKitProvider.
1785
+ *
1786
+ * @returns A function that takes a tool call and optional tool message and returns the rendered component
1787
+ */
1788
+ function useRenderToolCall() {
1789
+ const { copilotkit, executingToolCallIds } = useCopilotKit();
1790
+ const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
1791
+ const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
1792
+ return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
1793
+ }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
1794
+ return (0, react.useCallback)(({ toolCall, toolMessage }) => {
1795
+ const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
1796
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
1797
+ toolCall,
1798
+ toolMessage,
1799
+ RenderComponent: (exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*"))?.render ?? defaultToolCallRenderAdapter,
1800
+ isExecuting: executingToolCallIds.has(toolCall.id)
1801
+ }, toolCall.id);
1802
+ }, [
1803
+ renderToolCalls,
1804
+ executingToolCallIds,
1805
+ agentId
1806
+ ]);
1807
+ }
1808
+ function defaultToolCallRenderAdapter(props) {
1809
+ const status = props.status === _copilotkit_core.ToolCallStatus.Complete ? "complete" : props.status === _copilotkit_core.ToolCallStatus.Executing ? "executing" : "inProgress";
1810
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultToolCallRenderer, {
1811
+ name: props.name,
1812
+ parameters: props.args,
1813
+ status,
1814
+ result: props.result
1815
+ });
1816
+ }
1817
+
1818
+ //#endregion
1819
+ //#region src/v2/components/CopilotKitInspector.tsx
1820
+ const CopilotKitInspector = ({ core, ...rest }) => {
1821
+ const [InspectorComponent, setInspectorComponent] = react.useState(null);
1822
+ react.useEffect(() => {
1823
+ let mounted = true;
1824
+ import("@copilotkit/web-inspector").then((mod) => {
1825
+ mod.defineWebInspector?.();
1826
+ const Component = (0, _lit_labs_react.createComponent)({
1827
+ tagName: mod.WEB_INSPECTOR_TAG,
1828
+ elementClass: mod.WebInspectorElement,
1829
+ react
1830
+ });
1831
+ if (mounted) setInspectorComponent(() => Component);
1832
+ });
1833
+ return () => {
1834
+ mounted = false;
1835
+ };
1836
+ }, []);
1837
+ if (!InspectorComponent) return null;
1838
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InspectorComponent, {
1839
+ ...rest,
1840
+ core: core ?? null
1841
+ });
1842
+ };
1843
+ CopilotKitInspector.displayName = "CopilotKitInspector";
1844
+
1845
+ //#endregion
1846
+ //#region src/v2/components/license-warning-banner.tsx
1847
+ const LICENSE_BANNER_OFFSET_PX = 52;
1848
+ const LICENSE_BANNER_OFFSET_VAR = "--copilotkit-license-banner-offset";
1849
+ const BANNER_STYLES = {
1850
+ base: {
1851
+ position: "fixed",
1852
+ bottom: "8px",
1853
+ left: "50%",
1854
+ transform: "translateX(-50%)",
1855
+ zIndex: 99999,
1856
+ display: "inline-flex",
1857
+ alignItems: "center",
1858
+ gap: "12px",
1859
+ whiteSpace: "nowrap",
1860
+ padding: "8px 16px",
1861
+ fontSize: "13px",
1862
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif",
1863
+ borderRadius: "6px",
1864
+ boxShadow: "0 2px 8px rgba(0, 0, 0, 0.15)"
1865
+ },
1866
+ info: {
1867
+ backgroundColor: "#eff6ff",
1868
+ border: "1px solid #93c5fd",
1869
+ color: "#1e40af"
1870
+ },
1871
+ warning: {
1872
+ backgroundColor: "#fffbeb",
1873
+ border: "1px solid #fbbf24",
1874
+ color: "#92400e"
1875
+ },
1876
+ critical: {
1877
+ backgroundColor: "#fef2f2",
1878
+ border: "1px solid #fca5a5",
1879
+ color: "#991b1b"
1880
+ }
1881
+ };
1882
+ function getSeverityStyle(severity) {
1883
+ switch (severity) {
1884
+ case "warning": return BANNER_STYLES.warning;
1885
+ case "critical": return BANNER_STYLES.critical;
1886
+ default: return BANNER_STYLES.info;
1887
+ }
1888
+ }
1889
+ function BannerShell({ severity, message, actionLabel, actionUrl, onDismiss }) {
1890
+ (0, react.useEffect)(() => {
1891
+ if (typeof document === "undefined") return;
1892
+ const root = document.documentElement;
1893
+ root.style.setProperty(LICENSE_BANNER_OFFSET_VAR, `${LICENSE_BANNER_OFFSET_PX}px`);
1894
+ return () => {
1895
+ root.style.removeProperty(LICENSE_BANNER_OFFSET_VAR);
1896
+ };
1897
+ }, []);
1898
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1899
+ style: {
1900
+ ...BANNER_STYLES.base,
1901
+ ...getSeverityStyle(severity)
1902
+ },
1903
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: message }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1904
+ style: {
1905
+ display: "flex",
1906
+ gap: "8px",
1907
+ alignItems: "center"
1908
+ },
1909
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1910
+ href: actionUrl,
1911
+ target: "_blank",
1912
+ rel: "noopener noreferrer",
1913
+ style: {
1914
+ fontWeight: 600,
1915
+ textDecoration: "underline",
1916
+ color: "inherit"
1917
+ },
1918
+ children: actionLabel
1919
+ }), onDismiss && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
1920
+ onClick: onDismiss,
1921
+ style: {
1922
+ background: "none",
1923
+ border: "none",
1924
+ cursor: "pointer",
1925
+ color: "inherit",
1926
+ fontSize: "16px"
1927
+ },
1928
+ children: "×"
1929
+ })]
1930
+ })]
1931
+ });
1932
+ }
1933
+ function LicenseWarningBanner({ type, featureName, expiryDate, graceRemaining, onDismiss }) {
1934
+ switch (type) {
1935
+ case "no_license": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1936
+ severity: "info",
1937
+ message: "Powered by CopilotKit",
1938
+ actionLabel: "Get a license",
1939
+ actionUrl: "https://copilotkit.ai/pricing",
1940
+ onDismiss
1941
+ });
1942
+ case "feature_unlicensed": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1943
+ severity: "warning",
1944
+ message: `⚠ The "${featureName}" feature requires a CopilotKit license.`,
1945
+ actionLabel: "Get a license",
1946
+ actionUrl: "https://copilotkit.ai/pricing",
1947
+ onDismiss
1948
+ });
1949
+ case "expiring": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1950
+ severity: "warning",
1951
+ message: `Your CopilotKit license expires in ${graceRemaining} day${graceRemaining !== 1 ? "s" : ""}. Please renew.`,
1952
+ actionLabel: "Renew",
1953
+ actionUrl: "https://cloud.copilotkit.ai",
1954
+ onDismiss
1955
+ });
1956
+ case "expired": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1957
+ severity: "critical",
1958
+ message: `Your CopilotKit license expired${expiryDate ? ` on ${expiryDate}` : ""}. Please renew at copilotkit.ai/pricing`,
1959
+ actionLabel: "Renew now",
1960
+ actionUrl: "https://copilotkit.ai/pricing",
1961
+ onDismiss
1962
+ });
1963
+ case "invalid": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerShell, {
1964
+ severity: "critical",
1965
+ message: "Invalid CopilotKit license token. Please check your configuration.",
1966
+ actionLabel: "Get a license",
1967
+ actionUrl: "https://copilotkit.ai/pricing",
1968
+ onDismiss
1969
+ });
1970
+ default: return null;
1971
+ }
1972
+ }
1973
+ function InlineFeatureWarning({ featureName }) {
1974
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1975
+ style: {
1976
+ padding: "8px 12px",
1977
+ backgroundColor: "#fffbeb",
1978
+ border: "1px solid #fbbf24",
1979
+ borderRadius: "6px",
1980
+ fontSize: "13px",
1981
+ color: "#92400e",
1982
+ fontFamily: "-apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif"
1983
+ },
1984
+ children: [
1985
+ "⚠ The \"",
1986
+ featureName,
1987
+ "\" feature requires a CopilotKit license.",
1988
+ " ",
1989
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("a", {
1990
+ href: "https://copilotkit.ai/pricing",
1991
+ target: "_blank",
1992
+ rel: "noopener noreferrer",
1993
+ style: {
1994
+ color: "#b45309",
1995
+ textDecoration: "underline"
1996
+ },
1997
+ children: "Get one at copilotkit.ai/pricing"
1998
+ })
1999
+ ]
2000
+ });
2001
+ }
2002
+
2003
+ //#endregion
2004
+ //#region src/v2/components/MCPAppsActivityRenderer.tsx
2005
+ const PROTOCOL_VERSION = "2025-06-18";
2006
+ function buildSandboxHTML(extraCspDomains) {
2007
+ const baseScriptSrc = "'self' 'wasm-unsafe-eval' 'unsafe-inline' 'unsafe-eval' blob: data: http://localhost:* https://localhost:*";
2008
+ const baseFrameSrc = "* blob: data: http://localhost:* https://localhost:*";
2009
+ const extra = extraCspDomains?.length ? " " + extraCspDomains.join(" ") : "";
2010
+ return `<!doctype html>
2011
+ <html>
2012
+ <head>
2013
+ <meta charset="utf-8" />
2014
+ <meta http-equiv="Content-Security-Policy" content="default-src 'self'; img-src * data: blob: 'unsafe-inline'; media-src * blob: data:; font-src * blob: data:; script-src ${baseScriptSrc + extra}; style-src * blob: data: 'unsafe-inline'; connect-src *; frame-src ${baseFrameSrc + extra}; base-uri 'self';" />
2015
+ <style>html,body{margin:0;padding:0;height:100%;width:100%;overflow:hidden}*{box-sizing:border-box}iframe{background-color:transparent;border:none;padding:0;overflow:hidden;width:100%;height:100%}</style>
2016
+ </head>
2017
+ <body>
2018
+ <script>
2019
+ if(window.self===window.top){throw new Error("This file must be used in an iframe.")}
2020
+ const inner=document.createElement("iframe");
2021
+ inner.style="width:100%;height:100%;border:none;";
2022
+ inner.setAttribute("sandbox","allow-scripts allow-same-origin allow-forms");
2023
+ document.body.appendChild(inner);
2024
+ window.addEventListener("message",async(event)=>{
2025
+ if(event.source===window.parent){
2026
+ if(event.data&&event.data.method==="ui/notifications/sandbox-resource-ready"){
2027
+ const{html,sandbox}=event.data.params;
2028
+ if(typeof sandbox==="string")inner.setAttribute("sandbox",sandbox);
2029
+ if(typeof html==="string")inner.srcdoc=html;
2030
+ }else if(inner&&inner.contentWindow){
2031
+ inner.contentWindow.postMessage(event.data,"*");
2032
+ }
2033
+ }else if(event.source===inner.contentWindow){
2034
+ window.parent.postMessage(event.data,"*");
2035
+ }
2036
+ });
2037
+ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-ready",params:{}},"*");
2038
+ <\/script>
2039
+ </body>
2040
+ </html>`;
2041
+ }
2042
+ /**
2043
+ * Queue for serializing MCP app requests to an agent.
2044
+ * Ensures requests wait for the agent to stop running and are processed one at a time.
2045
+ */
2046
+ var MCPAppsRequestQueue = class {
2047
+ constructor() {
2048
+ this.queues = /* @__PURE__ */ new Map();
2049
+ this.processing = /* @__PURE__ */ new Map();
2050
+ }
2051
+ /**
2052
+ * Add a request to the queue for a specific agent thread.
2053
+ * Returns a promise that resolves when the request completes.
2054
+ */
2055
+ async enqueue(agent, request) {
2056
+ const threadId = agent.threadId || "default";
2057
+ return new Promise((resolve, reject) => {
2058
+ let queue = this.queues.get(threadId);
2059
+ if (!queue) {
2060
+ queue = [];
2061
+ this.queues.set(threadId, queue);
2062
+ }
2063
+ queue.push({
2064
+ execute: request,
2065
+ resolve,
2066
+ reject
2067
+ });
2068
+ this.processQueue(threadId, agent);
2069
+ });
2070
+ }
2071
+ async processQueue(threadId, agent) {
2072
+ if (this.processing.get(threadId)) return;
2073
+ this.processing.set(threadId, true);
2074
+ try {
2075
+ const queue = this.queues.get(threadId);
2076
+ if (!queue) return;
2077
+ while (queue.length > 0) {
2078
+ const item = queue[0];
2079
+ try {
2080
+ await this.waitForAgentIdle(agent);
2081
+ const result = await item.execute();
2082
+ item.resolve(result);
2083
+ } catch (error) {
2084
+ item.reject(error instanceof Error ? error : new Error(String(error)));
2085
+ }
2086
+ queue.shift();
2087
+ }
2088
+ } finally {
2089
+ this.processing.set(threadId, false);
2090
+ }
2091
+ }
2092
+ waitForAgentIdle(agent) {
2093
+ return new Promise((resolve) => {
2094
+ if (!agent.isRunning) {
2095
+ resolve();
2096
+ return;
2097
+ }
2098
+ let done = false;
2099
+ const finish = () => {
2100
+ if (done) return;
2101
+ done = true;
2102
+ clearInterval(checkInterval);
2103
+ sub.unsubscribe();
2104
+ resolve();
2105
+ };
2106
+ const sub = agent.subscribe({
2107
+ onRunFinalized: finish,
2108
+ onRunFailed: finish
2109
+ });
2110
+ const checkInterval = setInterval(() => {
2111
+ if (!agent.isRunning) finish();
2112
+ }, 500);
2113
+ });
2114
+ }
2115
+ };
2116
+ const mcpAppsRequestQueue = new MCPAppsRequestQueue();
2117
+ /**
2118
+ * Activity type for MCP Apps events - must match the middleware's MCPAppsActivityType
2119
+ */
2120
+ const MCPAppsActivityType = "mcp-apps";
2121
+ const MCPAppsActivityContentSchema = zod.z.object({
2122
+ result: zod.z.object({
2123
+ content: zod.z.array(zod.z.any()).optional(),
2124
+ structuredContent: zod.z.any().optional(),
2125
+ isError: zod.z.boolean().optional()
2126
+ }),
2127
+ resourceUri: zod.z.string(),
2128
+ serverHash: zod.z.string(),
2129
+ serverId: zod.z.string().optional(),
2130
+ toolInput: zod.z.record(zod.z.unknown()).optional()
2131
+ });
2132
+ function isRequest(msg) {
2133
+ return "id" in msg && "method" in msg;
2134
+ }
2135
+ function isNotification(msg) {
2136
+ return !("id" in msg) && "method" in msg;
2137
+ }
2138
+ /**
2139
+ * MCP Apps Extension Activity Renderer
2140
+ *
2141
+ * Renders MCP Apps UI in a sandboxed iframe with full protocol support.
2142
+ * Fetches resource content on-demand via proxied MCP requests.
2143
+ */
2144
+ const MCPAppsActivityRenderer = function MCPAppsActivityRenderer({ content, agent }) {
2145
+ const { copilotkit } = useCopilotKit();
2146
+ const containerRef = (0, react.useRef)(null);
2147
+ const iframeRef = (0, react.useRef)(null);
2148
+ const [iframeReady, setIframeReady] = (0, react.useState)(false);
2149
+ const [error, setError] = (0, react.useState)(null);
2150
+ const [isLoading, setIsLoading] = (0, react.useState)(true);
2151
+ const [iframeSize, setIframeSize] = (0, react.useState)({});
2152
+ const [fetchedResource, setFetchedResource] = (0, react.useState)(null);
2153
+ const contentRef = (0, react.useRef)(content);
2154
+ contentRef.current = content;
2155
+ const agentRef = (0, react.useRef)(agent);
2156
+ agentRef.current = agent;
2157
+ const fetchStateRef = (0, react.useRef)({
2158
+ inProgress: false,
2159
+ promise: null,
2160
+ resourceUri: null
2161
+ });
2162
+ const sendToIframe = (0, react.useCallback)((msg) => {
2163
+ if (iframeRef.current?.contentWindow) {
1673
2164
  console.log("[MCPAppsRenderer] Sending to iframe:", msg);
1674
2165
  iframeRef.current.contentWindow.postMessage(msg, "*");
1675
2166
  }
@@ -2562,18 +3053,6 @@ function getOperationSurfaceId(operation) {
2562
3053
  return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
2563
3054
  }
2564
3055
 
2565
- //#endregion
2566
- //#region src/v2/types/defineToolCallRenderer.ts
2567
- function defineToolCallRenderer(def) {
2568
- const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
2569
- return {
2570
- name: def.name,
2571
- args: argsSchema,
2572
- render: def.render,
2573
- ...def.agentId ? { agentId: def.agentId } : {}
2574
- };
2575
- }
2576
-
2577
3056
  //#endregion
2578
3057
  //#region src/v2/a2ui/A2UIToolCallRenderer.tsx
2579
3058
  /**
@@ -2944,124 +3423,28 @@ function A2UICatalogContext({ catalog, includeSchema }) {
2944
3423
  value: (0, _copilotkit_a2ui_renderer.buildCatalogContextValue)(catalog)
2945
3424
  });
2946
3425
  const { copilotkit } = useCopilotKit();
2947
- const schemaValue = (0, react.useMemo)(() => includeSchema !== false ? JSON.stringify((0, _copilotkit_a2ui_renderer.extractCatalogComponentSchemas)(catalog)) : null, [catalog, includeSchema]);
2948
- (0, react.useLayoutEffect)(() => {
2949
- if (!copilotkit || !schemaValue) return;
2950
- const ids = [];
2951
- ids.push(copilotkit.addContext({
2952
- description: _copilotkit_a2ui_renderer.A2UI_SCHEMA_CONTEXT_DESCRIPTION,
2953
- value: schemaValue
2954
- }));
2955
- ids.push(copilotkit.addContext({
2956
- description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
2957
- value: _copilotkit_shared.A2UI_DEFAULT_GENERATION_GUIDELINES
2958
- }));
2959
- ids.push(copilotkit.addContext({
2960
- description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
2961
- value: _copilotkit_shared.A2UI_DEFAULT_DESIGN_GUIDELINES
2962
- }));
2963
- return () => {
2964
- for (const id of ids) copilotkit.removeContext(id);
2965
- };
2966
- }, [copilotkit, schemaValue]);
2967
- return null;
2968
- }
2969
-
2970
- //#endregion
2971
- //#region src/v2/lib/react-core.ts
2972
- var CopilotKitCoreReact = class extends _copilotkit_core.CopilotKitCore {
2973
- constructor(config) {
2974
- super(config);
2975
- this._renderToolCalls = [];
2976
- this._hookRenderToolCalls = /* @__PURE__ */ new Map();
2977
- this._cachedMergedRenderToolCalls = null;
2978
- this._renderCustomMessages = [];
2979
- this._renderActivityMessages = [];
2980
- this._interruptElement = null;
2981
- this._renderToolCalls = config.renderToolCalls ?? [];
2982
- this._renderCustomMessages = config.renderCustomMessages ?? [];
2983
- this._renderActivityMessages = config.renderActivityMessages ?? [];
2984
- }
2985
- get renderCustomMessages() {
2986
- return this._renderCustomMessages;
2987
- }
2988
- get renderActivityMessages() {
2989
- return this._renderActivityMessages;
2990
- }
2991
- get renderToolCalls() {
2992
- if (this._hookRenderToolCalls.size === 0) return this._renderToolCalls;
2993
- if (this._cachedMergedRenderToolCalls) return this._cachedMergedRenderToolCalls;
2994
- const merged = /* @__PURE__ */ new Map();
2995
- for (const rc of this._renderToolCalls) merged.set(`${rc.agentId ?? ""}:${rc.name}`, rc);
2996
- for (const [key, rc] of this._hookRenderToolCalls) merged.set(key, rc);
2997
- this._cachedMergedRenderToolCalls = Array.from(merged.values());
2998
- return this._cachedMergedRenderToolCalls;
2999
- }
3000
- setRenderActivityMessages(renderers) {
3001
- this._renderActivityMessages = renderers;
3002
- }
3003
- setRenderCustomMessages(renderers) {
3004
- this._renderCustomMessages = renderers;
3005
- }
3006
- setRenderToolCalls(renderToolCalls) {
3007
- this._renderToolCalls = renderToolCalls;
3008
- this._cachedMergedRenderToolCalls = null;
3009
- this._notifyRenderToolCallsChanged();
3010
- }
3011
- addHookRenderToolCall(entry) {
3012
- const key = `${entry.agentId ?? ""}:${entry.name}`;
3013
- this._hookRenderToolCalls.set(key, entry);
3014
- this._cachedMergedRenderToolCalls = null;
3015
- this._notifyRenderToolCallsChanged();
3016
- }
3017
- removeHookRenderToolCall(name, agentId) {
3018
- const key = `${agentId ?? ""}:${name}`;
3019
- if (this._hookRenderToolCalls.delete(key)) {
3020
- this._cachedMergedRenderToolCalls = null;
3021
- this._notifyRenderToolCallsChanged();
3022
- }
3023
- }
3024
- _notifyRenderToolCallsChanged() {
3025
- this.notifySubscribers((subscriber) => {
3026
- const reactSubscriber = subscriber;
3027
- if (reactSubscriber.onRenderToolCallsChanged) reactSubscriber.onRenderToolCallsChanged({
3028
- copilotkit: this,
3029
- renderToolCalls: this.renderToolCalls
3030
- });
3031
- }, "Subscriber onRenderToolCallsChanged error:");
3032
- }
3033
- get interruptElement() {
3034
- return this._interruptElement;
3035
- }
3036
- setInterruptElement(element) {
3037
- this._interruptElement = element;
3038
- this.notifySubscribers((subscriber) => {
3039
- subscriber.onInterruptElementChanged?.({
3040
- copilotkit: this,
3041
- interruptElement: this._interruptElement
3042
- });
3043
- }, "Subscriber onInterruptElementChanged error:");
3044
- }
3045
- subscribe(subscriber) {
3046
- return super.subscribe(subscriber);
3047
- }
3048
- /**
3049
- * Wait for pending React state updates before the follow-up agent run.
3050
- *
3051
- * When a frontend tool handler calls setState(), React 18 batches the update
3052
- * and schedules a commit via its internal scheduler (MessageChannel). The
3053
- * useAgentContext hook registers context via useLayoutEffect, which runs
3054
- * synchronously after React commits that batch.
3055
- *
3056
- * Awaiting a zero-delay timeout yields to the macrotask queue. React's
3057
- * MessageChannel task runs first, committing the pending state and running
3058
- * useLayoutEffect (which updates the context store). The follow-up runAgent
3059
- * call then reads fresh context.
3060
- */
3061
- async waitForPendingFrameworkUpdates() {
3062
- await new Promise((resolve) => setTimeout(resolve, 0));
3063
- }
3064
- };
3426
+ const schemaValue = (0, react.useMemo)(() => includeSchema !== false ? JSON.stringify((0, _copilotkit_a2ui_renderer.extractCatalogComponentSchemas)(catalog)) : null, [catalog, includeSchema]);
3427
+ (0, react.useLayoutEffect)(() => {
3428
+ if (!copilotkit || !schemaValue) return;
3429
+ const ids = [];
3430
+ ids.push(copilotkit.addContext({
3431
+ description: _copilotkit_a2ui_renderer.A2UI_SCHEMA_CONTEXT_DESCRIPTION,
3432
+ value: schemaValue
3433
+ }));
3434
+ ids.push(copilotkit.addContext({
3435
+ description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
3436
+ value: _copilotkit_shared.A2UI_DEFAULT_GENERATION_GUIDELINES
3437
+ }));
3438
+ ids.push(copilotkit.addContext({
3439
+ description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
3440
+ value: _copilotkit_shared.A2UI_DEFAULT_DESIGN_GUIDELINES
3441
+ }));
3442
+ return () => {
3443
+ for (const id of ids) copilotkit.removeContext(id);
3444
+ };
3445
+ }, [copilotkit, schemaValue]);
3446
+ return null;
3447
+ }
3065
3448
 
3066
3449
  //#endregion
3067
3450
  //#region src/v2/providers/CopilotKitProvider.tsx
@@ -3078,12 +3461,6 @@ const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follo
3078
3461
  - Minimal transitions (150ms) for hover/focus states only. No decorative animations.
3079
3462
  - Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
3080
3463
  const GENERATE_SANDBOXED_UI_DESCRIPTION = "Generate sandboxed UI. IMPORTANT: The generated code runs in a sandboxed iframe WITHOUT same-origin access. Do NOT use localStorage, sessionStorage, document.cookie, IndexedDB, or fetch/XMLHttpRequest to same-origin URLs. To communicate with the host application, use Websandbox.connection.remote.<functionName>(args) which returns a Promise.\n\nYou CAN use external libraries from CDNs by including <script> or <link> tags in the HTML <head> (e.g., Chart.js, D3, Three.js, x-data-spreadsheet, etc.). CDN resources load normally inside the sandbox.\n\nPARAMETER ORDER IS CRITICAL — generate parameters in exactly this order:\n1. initialHeight + placeholderMessages (shown to user while generating)\n2. css (all styles FIRST — the user sees a placeholder until CSS is complete)\n3. html (streams in live — the user watches the UI build as HTML is generated)\n4. jsFunctions (reusable helper functions)\n5. jsExpressions (applied one-by-one — the user sees each expression take effect)";
3081
- const CopilotKitContext = (0, react.createContext)({
3082
- copilotkit: null,
3083
- executingToolCallIds: /* @__PURE__ */ new Set()
3084
- });
3085
- const LicenseContext = (0, react.createContext)((0, _copilotkit_shared.createLicenseContextValue)(null));
3086
- const useLicenseContext = () => (0, react.useContext)(LicenseContext);
3087
3464
  function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
3088
3465
  const empty = (0, react.useMemo)(() => [], []);
3089
3466
  const value = prop ?? empty;
@@ -3305,13 +3682,9 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
3305
3682
  onErrorRef.current = onError;
3306
3683
  }, [onError]);
3307
3684
  (0, react.useEffect)(() => {
3308
- if (!onErrorRef.current) return;
3309
3685
  const subscription = copilotkit.subscribe({ onError: (event) => {
3310
- onErrorRef.current?.({
3311
- error: event.error,
3312
- code: event.code,
3313
- context: event.context
3314
- });
3686
+ if (onErrorRef.current) onErrorRef.current(event);
3687
+ else console.error(`[CopilotKit] Error (${event.code}):`, event.error, event.context ?? {});
3315
3688
  } });
3316
3689
  return () => {
3317
3690
  subscription.unsubscribe();
@@ -3379,299 +3752,53 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
3379
3752
  name: fn.name,
3380
3753
  description: fn.description,
3381
3754
  parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema })
3382
- })));
3383
- }, [sandboxFunctionsList]);
3384
- (0, react.useLayoutEffect)(() => {
3385
- if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
3386
- const id = copilotkit.addContext({
3387
- description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
3388
- value: sandboxFunctionsDescriptors
3389
- });
3390
- return () => {
3391
- copilotkit.removeContext(id);
3392
- };
3393
- }, [
3394
- copilotkit,
3395
- sandboxFunctionsDescriptors,
3396
- openGenUIActive
3397
- ]);
3398
- const contextValue = (0, react.useMemo)(() => ({
3399
- copilotkit,
3400
- executingToolCallIds
3401
- }), [copilotkit, executingToolCallIds]);
3402
- const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
3403
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
3404
- value: sandboxFunctionsList,
3405
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
3406
- value: contextValue,
3407
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
3408
- value: licenseContextValue,
3409
- children: [
3410
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
3411
- runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
3412
- catalog: a2ui?.catalog,
3413
- includeSchema: a2ui?.includeSchema
3414
- }),
3415
- children,
3416
- shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, {
3417
- core: copilotkit,
3418
- defaultAnchor: inspectorDefaultAnchor
3419
- }) : null,
3420
- runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "no_license" }),
3421
- runtimeLicenseStatus === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expired" }),
3422
- runtimeLicenseStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "invalid" }),
3423
- runtimeLicenseStatus === "expiring" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expiring" })
3424
- ]
3425
- })
3426
- })
3427
- });
3428
- };
3429
- const useCopilotKit = () => {
3430
- const context = (0, react.useContext)(CopilotKitContext);
3431
- const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
3432
- if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
3433
- (0, react.useEffect)(() => {
3434
- const subscription = context.copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
3435
- forceUpdate();
3436
- } });
3437
- return () => {
3438
- subscription.unsubscribe();
3439
- };
3440
- }, []);
3441
- return context;
3442
- };
3443
-
3444
- //#endregion
3445
- //#region src/v2/hooks/use-render-tool-call.tsx
3446
- /**
3447
- * Memoized component that renders a single tool call.
3448
- * This prevents unnecessary re-renders when parent components update
3449
- * but the tool call data hasn't changed.
3450
- */
3451
- const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
3452
- const args = (0, react.useMemo)(() => (0, _copilotkit_shared.partialJSONParse)(toolCall.function.arguments), [toolCall.function.arguments]);
3453
- const toolName = toolCall.function.name;
3454
- if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
3455
- name: toolName,
3456
- toolCallId: toolCall.id,
3457
- args,
3458
- status: _copilotkit_core.ToolCallStatus.Complete,
3459
- result: toolMessage.content
3460
- });
3461
- else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
3462
- name: toolName,
3463
- toolCallId: toolCall.id,
3464
- args,
3465
- status: _copilotkit_core.ToolCallStatus.Executing,
3466
- result: void 0
3467
- });
3468
- else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
3469
- name: toolName,
3470
- toolCallId: toolCall.id,
3471
- args,
3472
- status: _copilotkit_core.ToolCallStatus.InProgress,
3473
- result: void 0
3474
- });
3475
- }, (prevProps, nextProps) => {
3476
- if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
3477
- if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
3478
- if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
3479
- if (prevProps.toolMessage?.content !== nextProps.toolMessage?.content) return false;
3480
- if (prevProps.isExecuting !== nextProps.isExecuting) return false;
3481
- if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
3482
- return true;
3483
- });
3484
- /**
3485
- * Hook that returns a function to render tool calls based on the render functions
3486
- * defined in CopilotKitProvider.
3487
- *
3488
- * @returns A function that takes a tool call and optional tool message and returns the rendered component
3489
- */
3490
- function useRenderToolCall() {
3491
- const { copilotkit, executingToolCallIds } = useCopilotKit();
3492
- const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3493
- const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
3494
- return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
3495
- }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
3496
- return (0, react.useCallback)(({ toolCall, toolMessage }) => {
3497
- const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
3498
- const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
3499
- if (!renderConfig) return null;
3500
- const RenderComponent = renderConfig.render;
3501
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
3502
- toolCall,
3503
- toolMessage,
3504
- RenderComponent,
3505
- isExecuting: executingToolCallIds.has(toolCall.id)
3506
- }, toolCall.id);
3507
- }, [
3508
- renderToolCalls,
3509
- executingToolCallIds,
3510
- agentId
3511
- ]);
3512
- }
3513
-
3514
- //#endregion
3515
- //#region src/v2/hooks/use-agent.tsx
3516
- let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
3517
- UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
3518
- UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
3519
- UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
3520
- return UseAgentUpdate;
3521
- }({});
3522
- const ALL_UPDATES = [
3523
- UseAgentUpdate.OnMessagesChanged,
3524
- UseAgentUpdate.OnStateChanged,
3525
- UseAgentUpdate.OnRunStatusChanged
3526
- ];
3527
- /**
3528
- * Clone a registry agent for per-thread isolation.
3529
- * Copies agent configuration (transport, headers, etc.) but resets conversation
3530
- * state (messages, threadId, state) so each thread starts fresh.
3531
- */
3532
- function cloneForThread(source, threadId, headers) {
3533
- const clone = source.clone();
3534
- if (clone === source) throw new Error(`useAgent: ${source.constructor.name}.clone() returned the same instance. clone() must return a new, independent object.`);
3535
- clone.threadId = threadId;
3536
- clone.setMessages([]);
3537
- clone.setState({});
3538
- if (clone instanceof _ag_ui_client.HttpAgent) clone.headers = { ...headers };
3539
- return clone;
3540
- }
3541
- /**
3542
- * Module-level WeakMap: registryAgent → (threadId → clone).
3543
- * Shared across all useAgent() calls so that every component using the same
3544
- * (agentId, threadId) pair receives the same agent instance. Using WeakMap
3545
- * ensures the clone map is garbage-collected when the registry agent is
3546
- * replaced (e.g. after reconnect or hot-reload).
3547
- */
3548
- const globalThreadCloneMap = /* @__PURE__ */ new WeakMap();
3549
- /**
3550
- * Look up an existing per-thread clone without creating one.
3551
- * Returns undefined when no clone has been created yet for this pair.
3552
- */
3553
- function getThreadClone(registryAgent, threadId) {
3554
- if (!registryAgent || !threadId) return void 0;
3555
- return globalThreadCloneMap.get(registryAgent)?.get(threadId);
3556
- }
3557
- function getOrCreateThreadClone(existing, threadId, headers) {
3558
- let byThread = globalThreadCloneMap.get(existing);
3559
- if (!byThread) {
3560
- byThread = /* @__PURE__ */ new Map();
3561
- globalThreadCloneMap.set(existing, byThread);
3562
- }
3563
- const cached = byThread.get(threadId);
3564
- if (cached) return cached;
3565
- const clone = cloneForThread(existing, threadId, headers);
3566
- byThread.set(threadId, clone);
3567
- return clone;
3568
- }
3569
- function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
3570
- agentId ??= _copilotkit_shared.DEFAULT_AGENT_ID;
3571
- const { copilotkit } = useCopilotKit();
3572
- const providerThrottleMs = copilotkit.defaultThrottleMs;
3573
- const chatConfig = useCopilotChatConfiguration();
3574
- threadId ??= chatConfig?.threadId;
3575
- const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
3576
- const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
3577
- const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
3578
- const agent = (0, react.useMemo)(() => {
3579
- const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
3580
- const existing = copilotkit.getAgent(agentId);
3581
- if (existing) {
3582
- provisionalAgentCache.current.delete(cacheKey);
3583
- provisionalAgentCache.current.delete(agentId);
3584
- if (!threadId) return existing;
3585
- return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
3586
- }
3587
- const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
3588
- const status = copilotkit.runtimeConnectionStatus;
3589
- if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
3590
- const cached = provisionalAgentCache.current.get(cacheKey);
3591
- if (cached) {
3592
- cached.headers = { ...copilotkit.headers };
3593
- return cached;
3594
- }
3595
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
3596
- runtimeUrl: copilotkit.runtimeUrl,
3597
- agentId,
3598
- transport: copilotkit.runtimeTransport,
3599
- runtimeMode: "pending"
3600
- });
3601
- provisional.headers = { ...copilotkit.headers };
3602
- if (threadId) provisional.threadId = threadId;
3603
- provisionalAgentCache.current.set(cacheKey, provisional);
3604
- return provisional;
3605
- }
3606
- if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
3607
- const cached = provisionalAgentCache.current.get(cacheKey);
3608
- if (cached) {
3609
- cached.headers = { ...copilotkit.headers };
3610
- return cached;
3611
- }
3612
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
3613
- runtimeUrl: copilotkit.runtimeUrl,
3614
- agentId,
3615
- transport: copilotkit.runtimeTransport,
3616
- runtimeMode: "pending"
3617
- });
3618
- provisional.headers = { ...copilotkit.headers };
3619
- if (threadId) provisional.threadId = threadId;
3620
- provisionalAgentCache.current.set(cacheKey, provisional);
3621
- return provisional;
3622
- }
3623
- const knownAgents = Object.keys(copilotkit.agents ?? {});
3624
- const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
3625
- throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
3626
- }, [
3627
- agentId,
3628
- threadId,
3629
- copilotkit.agents,
3630
- copilotkit.runtimeConnectionStatus,
3631
- copilotkit.runtimeUrl,
3632
- copilotkit.runtimeTransport,
3633
- JSON.stringify(copilotkit.headers)
3634
- ]);
3635
- (0, react.useEffect)(() => {
3636
- if (updateFlags.length === 0) return;
3637
- let active = true;
3638
- const handlers = {};
3639
- let batchScheduled = false;
3640
- const batchedForceUpdate = () => {
3641
- if (!active) return;
3642
- if (!batchScheduled) {
3643
- batchScheduled = true;
3644
- queueMicrotask(() => {
3645
- batchScheduled = false;
3646
- if (active) forceUpdate();
3647
- });
3648
- }
3649
- };
3650
- if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
3651
- if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
3652
- if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
3653
- handlers.onRunInitialized = batchedForceUpdate;
3654
- handlers.onRunFinalized = batchedForceUpdate;
3655
- handlers.onRunFailed = batchedForceUpdate;
3656
- handlers.onRunErrorEvent = batchedForceUpdate;
3657
- }
3658
- const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
3755
+ })));
3756
+ }, [sandboxFunctionsList]);
3757
+ (0, react.useLayoutEffect)(() => {
3758
+ if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
3759
+ const id = copilotkit.addContext({
3760
+ description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
3761
+ value: sandboxFunctionsDescriptors
3762
+ });
3659
3763
  return () => {
3660
- active = false;
3661
- subscription.unsubscribe();
3764
+ copilotkit.removeContext(id);
3662
3765
  };
3663
3766
  }, [
3664
- agent,
3665
- forceUpdate,
3666
- throttleMs,
3667
- providerThrottleMs,
3668
- updateFlags
3767
+ copilotkit,
3768
+ sandboxFunctionsDescriptors,
3769
+ openGenUIActive
3669
3770
  ]);
3670
- (0, react.useEffect)(() => {
3671
- if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
3672
- }, [agent, JSON.stringify(copilotkit.headers)]);
3673
- return { agent };
3674
- }
3771
+ const contextValue = (0, react.useMemo)(() => ({
3772
+ copilotkit,
3773
+ executingToolCallIds
3774
+ }), [copilotkit, executingToolCallIds]);
3775
+ const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
3776
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
3777
+ value: sandboxFunctionsList,
3778
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
3779
+ value: contextValue,
3780
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
3781
+ value: licenseContextValue,
3782
+ children: [
3783
+ runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
3784
+ runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
3785
+ catalog: a2ui?.catalog,
3786
+ includeSchema: a2ui?.includeSchema
3787
+ }),
3788
+ children,
3789
+ shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, {
3790
+ core: copilotkit,
3791
+ defaultAnchor: inspectorDefaultAnchor
3792
+ }) : null,
3793
+ runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "no_license" }),
3794
+ runtimeLicenseStatus === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expired" }),
3795
+ runtimeLicenseStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "invalid" }),
3796
+ runtimeLicenseStatus === "expiring" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expiring" })
3797
+ ]
3798
+ })
3799
+ })
3800
+ });
3801
+ };
3675
3802
 
3676
3803
  //#endregion
3677
3804
  //#region src/v2/hooks/use-render-custom-messages.tsx
@@ -3690,8 +3817,7 @@ function useRenderCustomMessages() {
3690
3817
  const { message, position } = params;
3691
3818
  const resolvedRunId = copilotkit.getRunIdForMessage(agentId, threadId, message.id) ?? copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
3692
3819
  const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
3693
- const registryAgent = copilotkit.getAgent(agentId);
3694
- const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
3820
+ const agent = copilotkit.getAgent(agentId);
3695
3821
  if (!agent) return null;
3696
3822
  const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
3697
3823
  const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
@@ -3701,427 +3827,160 @@ function useRenderCustomMessages() {
3701
3827
  const stateSnapshot = resolvedRunId ? copilotkit.getStateByRun(agentId, threadId, resolvedRunId) : void 0;
3702
3828
  let result = null;
3703
3829
  for (const renderer of customMessageRenderers) {
3704
- if (!renderer.render) continue;
3705
- const Component = renderer.render;
3706
- result = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3707
- message,
3708
- position,
3709
- runId,
3710
- messageIndex,
3711
- messageIndexInRun,
3712
- numberOfMessagesInRun,
3713
- agentId,
3714
- stateSnapshot
3715
- }, `${runId}-${message.id}-${position}`);
3716
- if (result) break;
3717
- }
3718
- return result;
3719
- };
3720
- }
3721
-
3722
- //#endregion
3723
- //#region src/v2/hooks/use-render-activity-message.tsx
3724
- function useRenderActivityMessage() {
3725
- const { copilotkit } = useCopilotKit();
3726
- const config = useCopilotChatConfiguration();
3727
- const agentId = config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3728
- const renderers = copilotkit.renderActivityMessages;
3729
- const findRenderer = (0, react.useCallback)((activityType) => {
3730
- if (!renderers.length) return null;
3731
- const matches = renderers.filter((renderer) => renderer.activityType === activityType);
3732
- return matches.find((candidate) => candidate.agentId === agentId) ?? matches.find((candidate) => candidate.agentId === void 0) ?? renderers.find((candidate) => candidate.activityType === "*") ?? null;
3733
- }, [agentId, renderers]);
3734
- const renderActivityMessage = (0, react.useCallback)((message) => {
3735
- const renderer = findRenderer(message.activityType);
3736
- if (!renderer) return null;
3737
- const parseResult = renderer.content.safeParse(message.content);
3738
- if (!parseResult.success) {
3739
- console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.error);
3740
- return null;
3741
- }
3742
- const Component = renderer.render;
3743
- const registryAgent = copilotkit.getAgent(agentId);
3744
- const agent = getThreadClone(registryAgent, config?.threadId) ?? registryAgent;
3745
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3746
- activityType: message.activityType,
3747
- content: parseResult.data,
3748
- message,
3749
- agent
3750
- }, message.id);
3751
- }, [
3752
- agentId,
3753
- config?.threadId,
3754
- copilotkit,
3755
- findRenderer
3756
- ]);
3757
- return (0, react.useMemo)(() => ({
3758
- renderActivityMessage,
3759
- findRenderer
3760
- }), [renderActivityMessage, findRenderer]);
3761
- }
3762
-
3763
- //#endregion
3764
- //#region src/v2/hooks/use-frontend-tool.tsx
3765
- const EMPTY_DEPS$1 = [];
3766
- function useFrontendTool(tool, deps) {
3767
- const { copilotkit } = useCopilotKit();
3768
- const extraDeps = deps ?? EMPTY_DEPS$1;
3769
- (0, react.useEffect)(() => {
3770
- const name = tool.name;
3771
- if (copilotkit.getTool({
3772
- toolName: name,
3773
- agentId: tool.agentId
3774
- })) {
3775
- console.warn(`Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`);
3776
- copilotkit.removeTool(name, tool.agentId);
3777
- }
3778
- copilotkit.addTool(tool);
3779
- if (tool.render) copilotkit.addHookRenderToolCall({
3780
- name,
3781
- args: tool.parameters,
3782
- agentId: tool.agentId,
3783
- render: tool.render
3784
- });
3785
- return () => {
3786
- copilotkit.removeTool(name, tool.agentId);
3787
- };
3788
- }, [
3789
- tool.name,
3790
- tool.available,
3791
- copilotkit,
3792
- extraDeps.length,
3793
- ...extraDeps
3794
- ]);
3795
- }
3796
-
3797
- //#endregion
3798
- //#region src/v2/hooks/use-component.tsx
3799
- /**
3800
- * Registers a React component as a frontend tool renderer in chat.
3801
- *
3802
- * This hook is a convenience wrapper around `useFrontendTool` that:
3803
- * - builds a model-facing tool description,
3804
- * - forwards optional schema parameters (any Standard Schema V1 compatible library),
3805
- * - renders your component with tool call parameters.
3806
- *
3807
- * Use this when you want to display a typed visual component for a tool call
3808
- * without manually wiring a full frontend tool object.
3809
- *
3810
- * When `parameters` is provided, render props are inferred from the schema.
3811
- * When omitted, the render component may accept any props.
3812
- *
3813
- * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
3814
- * @param config - Tool registration config.
3815
- * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
3816
- *
3817
- * @example
3818
- * ```tsx
3819
- * // Without parameters — render accepts any props
3820
- * useComponent({
3821
- * name: "showGreeting",
3822
- * render: ({ message }: { message: string }) => <div>{message}</div>,
3823
- * });
3824
- * ```
3825
- *
3826
- * @example
3827
- * ```tsx
3828
- * // With parameters — render props inferred from schema
3829
- * useComponent({
3830
- * name: "showWeatherCard",
3831
- * parameters: z.object({ city: z.string() }),
3832
- * render: ({ city }) => <div>{city}</div>,
3833
- * });
3834
- * ```
3835
- *
3836
- * @example
3837
- * ```tsx
3838
- * useComponent(
3839
- * {
3840
- * name: "renderProfile",
3841
- * parameters: z.object({ userId: z.string() }),
3842
- * render: ProfileCard,
3843
- * agentId: "support-agent",
3844
- * },
3845
- * [selectedAgentId],
3846
- * );
3847
- * ```
3848
- */
3849
- function useComponent(config, deps) {
3850
- const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
3851
- const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
3852
- useFrontendTool({
3853
- name: config.name,
3854
- description: fullDescription,
3855
- parameters: config.parameters,
3856
- render: ({ args }) => {
3857
- const Component = config.render;
3858
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { ...args });
3859
- },
3860
- agentId: config.agentId
3861
- }, deps);
3862
- }
3863
-
3864
- //#endregion
3865
- //#region src/v2/hooks/use-render-tool.tsx
3866
- const EMPTY_DEPS = [];
3867
- /**
3868
- * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
3869
- *
3870
- * Key behavior:
3871
- * - deduplicates by `agentId:name` (latest registration wins),
3872
- * - keeps renderer entries on cleanup so historical chat tool calls can still render,
3873
- * - refreshes registration when `deps` change.
3874
- *
3875
- * @typeParam S - Schema type describing tool call parameters.
3876
- * @param config - Renderer config for wildcard or named tools.
3877
- * @param deps - Optional dependencies to refresh registration.
3878
- *
3879
- * @example
3880
- * ```tsx
3881
- * useRenderTool(
3882
- * {
3883
- * name: "searchDocs",
3884
- * parameters: z.object({ query: z.string() }),
3885
- * render: ({ status, parameters, result }) => {
3886
- * if (status === "executing") return <div>Searching {parameters.query}</div>;
3887
- * if (status === "complete") return <div>{result}</div>;
3888
- * return <div>Preparing...</div>;
3889
- * },
3890
- * },
3891
- * [],
3892
- * );
3893
- * ```
3894
- *
3895
- * @example
3896
- * ```tsx
3897
- * useRenderTool(
3898
- * {
3899
- * name: "summarize",
3900
- * parameters: z.object({ text: z.string() }),
3901
- * agentId: "research-agent",
3902
- * render: ({ name, status }) => <div>{name}: {status}</div>,
3903
- * },
3904
- * [selectedAgentId],
3905
- * );
3906
- * ```
3907
- */
3908
- function useRenderTool(config, deps) {
3830
+ if (!renderer.render) continue;
3831
+ const Component = renderer.render;
3832
+ result = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3833
+ message,
3834
+ position,
3835
+ runId,
3836
+ messageIndex,
3837
+ messageIndexInRun,
3838
+ numberOfMessagesInRun,
3839
+ agentId,
3840
+ stateSnapshot
3841
+ }, `${runId}-${message.id}-${position}`);
3842
+ if (result) break;
3843
+ }
3844
+ return result;
3845
+ };
3846
+ }
3847
+
3848
+ //#endregion
3849
+ //#region src/v2/hooks/use-render-activity-message.tsx
3850
+ function useRenderActivityMessage() {
3909
3851
  const { copilotkit } = useCopilotKit();
3910
- const extraDeps = deps ?? EMPTY_DEPS;
3911
- (0, react.useEffect)(() => {
3912
- const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
3913
- name: "*",
3914
- render: (props) => config.render({
3915
- ...props,
3916
- parameters: props.args
3917
- }),
3918
- ...config.agentId ? { agentId: config.agentId } : {}
3919
- }) : defineToolCallRenderer({
3920
- name: config.name,
3921
- args: config.parameters,
3922
- render: (props) => config.render({
3923
- ...props,
3924
- parameters: props.args
3925
- }),
3926
- ...config.agentId ? { agentId: config.agentId } : {}
3927
- });
3928
- copilotkit.addHookRenderToolCall(renderer);
3852
+ const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
3853
+ const renderers = copilotkit.renderActivityMessages;
3854
+ const findRenderer = (0, react.useCallback)((activityType) => {
3855
+ if (!renderers.length) return null;
3856
+ const matches = renderers.filter((renderer) => renderer.activityType === activityType);
3857
+ return matches.find((candidate) => candidate.agentId === agentId) ?? matches.find((candidate) => candidate.agentId === void 0) ?? renderers.find((candidate) => candidate.activityType === "*") ?? null;
3858
+ }, [agentId, renderers]);
3859
+ const renderActivityMessage = (0, react.useCallback)((message) => {
3860
+ const renderer = findRenderer(message.activityType);
3861
+ if (!renderer) return null;
3862
+ const parseResult = renderer.content.safeParse(message.content);
3863
+ if (!parseResult.success) {
3864
+ console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.error);
3865
+ return null;
3866
+ }
3867
+ const Component = renderer.render;
3868
+ const agent = copilotkit.getAgent(agentId);
3869
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
3870
+ activityType: message.activityType,
3871
+ content: parseResult.data,
3872
+ message,
3873
+ agent
3874
+ }, message.id);
3929
3875
  }, [
3930
- config.name,
3876
+ agentId,
3931
3877
  copilotkit,
3932
- extraDeps.length,
3933
- ...extraDeps
3878
+ findRenderer
3934
3879
  ]);
3880
+ return (0, react.useMemo)(() => ({
3881
+ renderActivityMessage,
3882
+ findRenderer
3883
+ }), [renderActivityMessage, findRenderer]);
3935
3884
  }
3936
-
3937
- //#endregion
3938
- //#region src/v2/hooks/use-default-render-tool.tsx
3939
- /**
3940
- * Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
3941
- *
3942
- * - Call with no config to use CopilotKit's built-in default tool-call card.
3943
- * - Pass `config.render` to replace the default UI with your own fallback renderer.
3944
- *
3945
- * This is useful when you want a generic renderer for tools that do not have a
3946
- * dedicated `useRenderTool({ name: "..." })` registration.
3947
- *
3948
- * @param config - Optional custom wildcard render function.
3949
- * @param deps - Optional dependencies to refresh registration.
3950
- *
3951
- * @example
3952
- * ```tsx
3953
- * useDefaultRenderTool();
3954
- * ```
3955
- *
3956
- * @example
3957
- * ```tsx
3958
- * useDefaultRenderTool({
3959
- * render: ({ name, status }) => <div>{name}: {status}</div>,
3960
- * });
3961
- * ```
3962
- *
3963
- * @example
3964
- * ```tsx
3965
- * useDefaultRenderTool(
3966
- * {
3967
- * render: ({ name, result }) => (
3968
- * <ToolEventRow title={name} payload={result} compact={compactMode} />
3969
- * ),
3970
- * },
3971
- * [compactMode],
3972
- * );
3973
- * ```
3974
- */
3975
- function useDefaultRenderTool(config, deps) {
3976
- useRenderTool({
3977
- name: "*",
3978
- render: config?.render ?? DefaultToolCallRenderer
3979
- }, deps);
3980
- }
3981
- function DefaultToolCallRenderer({ name, parameters, status, result }) {
3982
- const [isExpanded, setIsExpanded] = (0, react.useState)(false);
3983
- const statusString = String(status);
3984
- const isActive = statusString === "inProgress" || statusString === "executing";
3985
- const isComplete = statusString === "complete";
3986
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3987
- style: {
3988
- marginTop: "8px",
3989
- paddingBottom: "8px"
3990
- },
3991
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3992
- style: {
3993
- borderRadius: "12px",
3994
- border: "1px solid #e4e4e7",
3995
- backgroundColor: "#fafafa",
3996
- padding: "14px 16px"
3997
- },
3998
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3999
- onClick: () => setIsExpanded(!isExpanded),
4000
- style: {
4001
- display: "flex",
4002
- alignItems: "center",
4003
- justifyContent: "space-between",
4004
- gap: "10px",
4005
- cursor: "pointer",
4006
- userSelect: "none"
4007
- },
4008
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4009
- style: {
4010
- display: "flex",
4011
- alignItems: "center",
4012
- gap: "8px",
4013
- minWidth: 0
4014
- },
4015
- children: [
4016
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
4017
- style: {
4018
- height: "14px",
4019
- width: "14px",
4020
- color: "#71717a",
4021
- transition: "transform 0.15s",
4022
- transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
4023
- flexShrink: 0
4024
- },
4025
- fill: "none",
4026
- viewBox: "0 0 24 24",
4027
- strokeWidth: 2,
4028
- stroke: "currentColor",
4029
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
4030
- strokeLinecap: "round",
4031
- strokeLinejoin: "round",
4032
- d: "M8.25 4.5l7.5 7.5-7.5 7.5"
4033
- })
4034
- }),
4035
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { style: {
4036
- display: "inline-block",
4037
- height: "8px",
4038
- width: "8px",
4039
- borderRadius: "50%",
4040
- backgroundColor: isActive ? "#f59e0b" : isComplete ? "#10b981" : "#a1a1aa",
4041
- flexShrink: 0
4042
- } }),
4043
- /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4044
- style: {
4045
- fontSize: "13px",
4046
- fontWeight: 600,
4047
- color: "#18181b",
4048
- overflow: "hidden",
4049
- textOverflow: "ellipsis",
4050
- whiteSpace: "nowrap"
4051
- },
4052
- children: name
4053
- })
4054
- ]
4055
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
4056
- style: {
4057
- display: "inline-flex",
4058
- alignItems: "center",
4059
- borderRadius: "9999px",
4060
- padding: "2px 8px",
4061
- fontSize: "11px",
4062
- fontWeight: 500,
4063
- backgroundColor: isActive ? "#fef3c7" : isComplete ? "#d1fae5" : "#f4f4f5",
4064
- color: isActive ? "#92400e" : isComplete ? "#065f46" : "#3f3f46",
4065
- flexShrink: 0
4066
- },
4067
- children: isActive ? "Running" : isComplete ? "Done" : status
4068
- })]
4069
- }), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
4070
- style: {
4071
- marginTop: "12px",
4072
- display: "grid",
4073
- gap: "12px"
4074
- },
4075
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4076
- style: {
4077
- fontSize: "10px",
4078
- textTransform: "uppercase",
4079
- letterSpacing: "0.05em",
4080
- color: "#71717a"
4081
- },
4082
- children: "Arguments"
4083
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
4084
- style: {
4085
- marginTop: "6px",
4086
- maxHeight: "200px",
4087
- overflow: "auto",
4088
- borderRadius: "6px",
4089
- backgroundColor: "#f4f4f5",
4090
- padding: "10px",
4091
- fontSize: "11px",
4092
- lineHeight: 1.6,
4093
- color: "#27272a",
4094
- whiteSpace: "pre-wrap",
4095
- wordBreak: "break-word"
4096
- },
4097
- children: JSON.stringify(parameters ?? {}, null, 2)
4098
- })] }), result !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
4099
- style: {
4100
- fontSize: "10px",
4101
- textTransform: "uppercase",
4102
- letterSpacing: "0.05em",
4103
- color: "#71717a"
4104
- },
4105
- children: "Result"
4106
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
4107
- style: {
4108
- marginTop: "6px",
4109
- maxHeight: "200px",
4110
- overflow: "auto",
4111
- borderRadius: "6px",
4112
- backgroundColor: "#f4f4f5",
4113
- padding: "10px",
4114
- fontSize: "11px",
4115
- lineHeight: 1.6,
4116
- color: "#27272a",
4117
- whiteSpace: "pre-wrap",
4118
- wordBreak: "break-word"
4119
- },
4120
- children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
4121
- })] })]
4122
- })]
4123
- })
4124
- });
3885
+
3886
+ //#endregion
3887
+ //#region src/v2/hooks/use-frontend-tool.tsx
3888
+ const EMPTY_DEPS = [];
3889
+ function useFrontendTool(tool, deps) {
3890
+ const { copilotkit } = useCopilotKit();
3891
+ const extraDeps = deps ?? EMPTY_DEPS;
3892
+ (0, react.useEffect)(() => {
3893
+ const name = tool.name;
3894
+ if (copilotkit.getTool({
3895
+ toolName: name,
3896
+ agentId: tool.agentId
3897
+ })) {
3898
+ console.warn(`Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`);
3899
+ copilotkit.removeTool(name, tool.agentId);
3900
+ }
3901
+ copilotkit.addTool(tool);
3902
+ if (tool.render) copilotkit.addHookRenderToolCall({
3903
+ name,
3904
+ args: tool.parameters,
3905
+ agentId: tool.agentId,
3906
+ render: tool.render
3907
+ });
3908
+ return () => {
3909
+ copilotkit.removeTool(name, tool.agentId);
3910
+ };
3911
+ }, [
3912
+ tool.name,
3913
+ tool.available,
3914
+ copilotkit,
3915
+ JSON.stringify(extraDeps)
3916
+ ]);
3917
+ }
3918
+
3919
+ //#endregion
3920
+ //#region src/v2/hooks/use-component.tsx
3921
+ /**
3922
+ * Registers a React component as a frontend tool renderer in chat.
3923
+ *
3924
+ * This hook is a convenience wrapper around `useFrontendTool` that:
3925
+ * - builds a model-facing tool description,
3926
+ * - forwards optional schema parameters (any Standard Schema V1 compatible library),
3927
+ * - renders your component with tool call parameters.
3928
+ *
3929
+ * Use this when you want to display a typed visual component for a tool call
3930
+ * without manually wiring a full frontend tool object.
3931
+ *
3932
+ * When `parameters` is provided, render props are inferred from the schema.
3933
+ * When omitted, the render component may accept any props.
3934
+ *
3935
+ * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
3936
+ * @param config - Tool registration config.
3937
+ * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
3938
+ *
3939
+ * @example
3940
+ * ```tsx
3941
+ * // Without parameters — render accepts any props
3942
+ * useComponent({
3943
+ * name: "showGreeting",
3944
+ * render: ({ message }: { message: string }) => <div>{message}</div>,
3945
+ * });
3946
+ * ```
3947
+ *
3948
+ * @example
3949
+ * ```tsx
3950
+ * // With parameters — render props inferred from schema
3951
+ * useComponent({
3952
+ * name: "showWeatherCard",
3953
+ * parameters: z.object({ city: z.string() }),
3954
+ * render: ({ city }) => <div>{city}</div>,
3955
+ * });
3956
+ * ```
3957
+ *
3958
+ * @example
3959
+ * ```tsx
3960
+ * useComponent(
3961
+ * {
3962
+ * name: "renderProfile",
3963
+ * parameters: z.object({ userId: z.string() }),
3964
+ * render: ProfileCard,
3965
+ * agentId: "support-agent",
3966
+ * },
3967
+ * [selectedAgentId],
3968
+ * );
3969
+ * ```
3970
+ */
3971
+ function useComponent(config, deps) {
3972
+ const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
3973
+ const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
3974
+ useFrontendTool({
3975
+ name: config.name,
3976
+ description: fullDescription,
3977
+ parameters: config.parameters,
3978
+ render: ({ args }) => {
3979
+ const Component = config.render;
3980
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { ...args });
3981
+ },
3982
+ agentId: config.agentId
3983
+ }, deps);
4125
3984
  }
4126
3985
 
4127
3986
  //#endregion
@@ -4190,6 +4049,118 @@ function useHumanInTheLoop(tool, deps) {
4190
4049
  ]);
4191
4050
  }
4192
4051
 
4052
+ //#endregion
4053
+ //#region src/v2/hooks/use-agent.tsx
4054
+ let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
4055
+ UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
4056
+ UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
4057
+ UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
4058
+ return UseAgentUpdate;
4059
+ }({});
4060
+ const ALL_UPDATES = [
4061
+ UseAgentUpdate.OnMessagesChanged,
4062
+ UseAgentUpdate.OnStateChanged,
4063
+ UseAgentUpdate.OnRunStatusChanged
4064
+ ];
4065
+ function useAgent({ agentId, updates, throttleMs } = {}) {
4066
+ agentId ??= _copilotkit_shared.DEFAULT_AGENT_ID;
4067
+ const { copilotkit } = useCopilotKit();
4068
+ const providerThrottleMs = copilotkit.defaultThrottleMs;
4069
+ const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
4070
+ const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
4071
+ const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
4072
+ const agent = (0, react.useMemo)(() => {
4073
+ const existing = copilotkit.getAgent(agentId);
4074
+ if (existing) {
4075
+ provisionalAgentCache.current.delete(agentId);
4076
+ return existing;
4077
+ }
4078
+ const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
4079
+ const status = copilotkit.runtimeConnectionStatus;
4080
+ if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
4081
+ const cached = provisionalAgentCache.current.get(agentId);
4082
+ if (cached) {
4083
+ cached.headers = { ...copilotkit.headers };
4084
+ return cached;
4085
+ }
4086
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4087
+ runtimeUrl: copilotkit.runtimeUrl,
4088
+ agentId,
4089
+ transport: copilotkit.runtimeTransport,
4090
+ runtimeMode: "pending"
4091
+ });
4092
+ provisional.headers = { ...copilotkit.headers };
4093
+ provisionalAgentCache.current.set(agentId, provisional);
4094
+ return provisional;
4095
+ }
4096
+ if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
4097
+ const cached = provisionalAgentCache.current.get(agentId);
4098
+ if (cached) {
4099
+ cached.headers = { ...copilotkit.headers };
4100
+ return cached;
4101
+ }
4102
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
4103
+ runtimeUrl: copilotkit.runtimeUrl,
4104
+ agentId,
4105
+ transport: copilotkit.runtimeTransport,
4106
+ runtimeMode: "pending"
4107
+ });
4108
+ provisional.headers = { ...copilotkit.headers };
4109
+ provisionalAgentCache.current.set(agentId, provisional);
4110
+ return provisional;
4111
+ }
4112
+ const knownAgents = Object.keys(copilotkit.agents ?? {});
4113
+ const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
4114
+ throw new Error(`useAgent: Agent '${agentId}' not found after runtime sync (${runtimePart}). ` + (knownAgents.length ? `Known agents: [${knownAgents.join(", ")}]` : "No agents registered.") + " Verify your runtime /info and/or agents__unsafe_dev_only.");
4115
+ }, [
4116
+ agentId,
4117
+ copilotkit.agents,
4118
+ copilotkit.runtimeConnectionStatus,
4119
+ copilotkit.runtimeUrl,
4120
+ copilotkit.runtimeTransport,
4121
+ JSON.stringify(copilotkit.headers)
4122
+ ]);
4123
+ (0, react.useEffect)(() => {
4124
+ if (updateFlags.length === 0) return;
4125
+ let active = true;
4126
+ const handlers = {};
4127
+ let batchScheduled = false;
4128
+ const batchedForceUpdate = () => {
4129
+ if (!active) return;
4130
+ if (!batchScheduled) {
4131
+ batchScheduled = true;
4132
+ queueMicrotask(() => {
4133
+ batchScheduled = false;
4134
+ if (active) forceUpdate();
4135
+ });
4136
+ }
4137
+ };
4138
+ if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = batchedForceUpdate;
4139
+ if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
4140
+ if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
4141
+ handlers.onRunInitialized = batchedForceUpdate;
4142
+ handlers.onRunFinalized = batchedForceUpdate;
4143
+ handlers.onRunFailed = batchedForceUpdate;
4144
+ handlers.onRunErrorEvent = batchedForceUpdate;
4145
+ }
4146
+ const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
4147
+ return () => {
4148
+ active = false;
4149
+ subscription.unsubscribe();
4150
+ };
4151
+ }, [
4152
+ agent,
4153
+ forceUpdate,
4154
+ throttleMs,
4155
+ providerThrottleMs,
4156
+ updateFlags
4157
+ ]);
4158
+ (0, react.useEffect)(() => {
4159
+ if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
4160
+ }, [agent, JSON.stringify(copilotkit.headers)]);
4161
+ return { agent };
4162
+ }
4163
+
4193
4164
  //#endregion
4194
4165
  //#region src/v2/hooks/use-capabilities.tsx
4195
4166
  /**
@@ -5655,6 +5626,190 @@ CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
5655
5626
  */
5656
5627
  const ScrollElementContext = react.default.createContext(null);
5657
5628
 
5629
+ //#endregion
5630
+ //#region src/v2/components/intelligence-indicator/IntelligenceIndicator.tsx
5631
+ /**
5632
+ * Grace window before showing the spinner. A matching tool call must
5633
+ * remain unresolved (no `tool`-role result message in `agent.messages`)
5634
+ * for at least this long before the pill appears. This filters out
5635
+ * history-replay flashes — during `connectAgent` replay, tool calls and
5636
+ * their results arrive back-to-back in sub-millisecond bursts, so the
5637
+ * timer is cancelled before it fires. Live runs cross the threshold
5638
+ * easily because the tool actually has to execute.
5639
+ */
5640
+ const PENDING_THRESHOLD_MS = 100;
5641
+ /** Hold the checkmark briefly before fading out. */
5642
+ const CHECK_HOLD_MS = 800;
5643
+ /**
5644
+ * Duration of the fade-out animation. Must match
5645
+ * `cpk-intelligence-pill-fade-out` keyframes in `v2/styles/globals.css`.
5646
+ */
5647
+ const FADE_OUT_ANIMATION_MS = 480;
5648
+ /**
5649
+ * Tool-name regex patterns that trigger the indicator. Currently
5650
+ * hardcoded to the Intelligence MCP server's canonical tool name. If
5651
+ * we add per-instance customization later (e.g. a `CopilotKitProvider`
5652
+ * prop or a runtime-info field), this constant becomes the fallback.
5653
+ */
5654
+ const DEFAULT_TOOL_PATTERNS = [/^copilotkit_knowledge_base_shell$/];
5655
+ const isMatchingToolCallName = (name) => typeof name === "string" && DEFAULT_TOOL_PATTERNS.some((p) => p.test(name));
5656
+ /**
5657
+ * "Tool-call-like" messages do NOT count as a real follow-up: tool
5658
+ * result messages, assistant messages that carry tool calls, and
5659
+ * empty-content assistant messages (which some providers emit as a
5660
+ * standalone wrapper around a batch of tool calls). A real follow-up
5661
+ * is anything else — most importantly an assistant message with prose
5662
+ * content, or a fresh user message.
5663
+ */
5664
+ const isToolCallLikeMessage = (m) => {
5665
+ if (m.role === "tool") return true;
5666
+ if (m.role === "assistant") {
5667
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).length > 0) return true;
5668
+ const content = m.content;
5669
+ return typeof content !== "string" || content.trim().length === 0;
5670
+ }
5671
+ return false;
5672
+ };
5673
+ /**
5674
+ * The "Using CopilotKit Intelligence" pill. Auto-mounted by
5675
+ * `CopilotChatMessageView` for every message slot when
5676
+ * `copilotkit.intelligence` is configured — callers do not register
5677
+ * this themselves. Self-gates so only the canonical message renders a
5678
+ * pill.
5679
+ *
5680
+ * Render gates (all must hold):
5681
+ * 1. `copilotkit.intelligence !== undefined`
5682
+ * 2. The message is an assistant message with at least one tool call
5683
+ * whose name matches {@link DEFAULT_TOOL_PATTERNS}
5684
+ * 3. The message is the *latest* such matching-assistant message in
5685
+ * `agent.messages` — tool-result messages and prose-only assistant
5686
+ * messages don't invalidate the slot, so the pill stays
5687
+ * continuously through a multi-step tool chain.
5688
+ * 4. The phase machine is past `idle` (the pending-grace timer fired)
5689
+ * and not yet `hidden`.
5690
+ *
5691
+ * Phase machine (per-instance, all timers local):
5692
+ * - Starts in `idle` — nothing rendered.
5693
+ * - `idle → spinner` once a matching tool call has been pending
5694
+ * (no `tool`-role result with a matching `toolCallId`) for
5695
+ * {@link PENDING_THRESHOLD_MS}. Replay flashes (tool call + result
5696
+ * in the same tick) never cross this threshold.
5697
+ * - `spinner → check` as soon as EITHER `agent.isRunning` flips
5698
+ * false OR a non-tool-call-like message appears later in
5699
+ * `agent.messages` (i.e. the agent has produced a "real"
5700
+ * follow-up — prose answer or a new user turn).
5701
+ * - `check → fading` after {@link CHECK_HOLD_MS}.
5702
+ * - `fading → hidden` after {@link FADE_OUT_ANIMATION_MS}.
5703
+ *
5704
+ * Once `hidden`, the phase is sticky — a finished pill never re-spawns
5705
+ * on the same message. New runs mount fresh indicator instances on
5706
+ * their own assistant messages.
5707
+ *
5708
+ * The "exactly one pill at a time" guarantee is structural: only one
5709
+ * message satisfies the latest-matching-assistant gate at any moment.
5710
+ */
5711
+ function IntelligenceIndicator(props) {
5712
+ const { message, agentId, label = "Using CopilotKit Intelligence" } = props;
5713
+ const { copilotkit } = useCopilotKit();
5714
+ const config = useCopilotChatConfiguration();
5715
+ const { agent } = useAgent({
5716
+ agentId,
5717
+ updates: [UseAgentUpdate.OnRunStatusChanged, UseAgentUpdate.OnMessagesChanged]
5718
+ });
5719
+ const matchingToolCallIds = (0, react.useMemo)(() => {
5720
+ if (message.role !== "assistant") return [];
5721
+ const tcs = Array.isArray(message.toolCalls) ? message.toolCalls : [];
5722
+ const ids = [];
5723
+ for (const tc of tcs) if (isMatchingToolCallName(tc?.function?.name) && tc?.id) ids.push(tc.id);
5724
+ return ids;
5725
+ }, [message]);
5726
+ const hasPending = (0, react.useMemo)(() => {
5727
+ if (matchingToolCallIds.length === 0) return false;
5728
+ const resolved = /* @__PURE__ */ new Set();
5729
+ for (const m of agent.messages) if (m.role === "tool" && m.toolCallId) resolved.add(m.toolCallId);
5730
+ return matchingToolCallIds.some((id) => !resolved.has(id));
5731
+ }, [matchingToolCallIds, agent.messages]);
5732
+ const sawRealFollowup = (0, react.useMemo)(() => {
5733
+ const idx = agent.messages.findIndex((m) => m.id === message.id);
5734
+ if (idx < 0) return false;
5735
+ for (let i = idx + 1; i < agent.messages.length; i += 1) if (!isToolCallLikeMessage(agent.messages[i])) return true;
5736
+ return false;
5737
+ }, [agent.messages, message.id]);
5738
+ const [phase, setPhase] = (0, react.useState)("idle");
5739
+ (0, react.useEffect)(() => {
5740
+ if (phase !== "idle") return void 0;
5741
+ if (!hasPending) return void 0;
5742
+ const t = setTimeout(() => setPhase("spinner"), PENDING_THRESHOLD_MS);
5743
+ return () => clearTimeout(t);
5744
+ }, [phase, hasPending]);
5745
+ (0, react.useEffect)(() => {
5746
+ if (phase !== "spinner") return void 0;
5747
+ if (!agent.isRunning || sawRealFollowup) setPhase("check");
5748
+ }, [
5749
+ phase,
5750
+ agent.isRunning,
5751
+ sawRealFollowup
5752
+ ]);
5753
+ (0, react.useEffect)(() => {
5754
+ if (phase !== "check") return void 0;
5755
+ const t = setTimeout(() => setPhase("fading"), CHECK_HOLD_MS);
5756
+ return () => clearTimeout(t);
5757
+ }, [phase]);
5758
+ (0, react.useEffect)(() => {
5759
+ if (phase !== "fading") return void 0;
5760
+ const t = setTimeout(() => setPhase("hidden"), FADE_OUT_ANIMATION_MS);
5761
+ return () => clearTimeout(t);
5762
+ }, [phase]);
5763
+ if (copilotkit.intelligence === void 0) return null;
5764
+ if (!config) return null;
5765
+ if (phase === "idle" || phase === "hidden") return null;
5766
+ if (message.role !== "assistant") return null;
5767
+ if (!(Array.isArray(message.toolCalls) ? message.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) return null;
5768
+ let latestMatchingAssistantId;
5769
+ for (let i = agent.messages.length - 1; i >= 0; i -= 1) {
5770
+ const m = agent.messages[i];
5771
+ if (m.role !== "assistant") continue;
5772
+ if ((Array.isArray(m.toolCalls) ? m.toolCalls : []).some((tc) => isMatchingToolCallName(tc?.function?.name))) {
5773
+ latestMatchingAssistantId = m.id;
5774
+ break;
5775
+ }
5776
+ }
5777
+ if (latestMatchingAssistantId !== message.id) return null;
5778
+ const showSpinner = phase === "spinner";
5779
+ const isFading = phase === "fading";
5780
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
5781
+ className: "cpk-intelligence-pill" + (isFading ? " cpk-intelligence-pill--fading" : ""),
5782
+ role: "status",
5783
+ "aria-live": "polite",
5784
+ "aria-hidden": isFading || void 0,
5785
+ "data-testid": `cpk-intelligence-pill-${message.id}`,
5786
+ title: label,
5787
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
5788
+ className: "cpk-intelligence-pill__icon",
5789
+ viewBox: "0 0 24 24",
5790
+ width: "14",
5791
+ height: "14",
5792
+ "aria-hidden": "true",
5793
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
5794
+ cx: "12",
5795
+ cy: "12",
5796
+ r: "9",
5797
+ fill: "none",
5798
+ strokeWidth: "2.5",
5799
+ strokeLinecap: "round",
5800
+ className: "cpk-intelligence-pill__ring" + (showSpinner ? "" : " cpk-intelligence-pill__ring--done")
5801
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
5802
+ d: "M8 12.5l3 3 5-6",
5803
+ fill: "none",
5804
+ strokeWidth: "2.5",
5805
+ strokeLinecap: "round",
5806
+ strokeLinejoin: "round",
5807
+ className: "cpk-intelligence-pill__check" + (showSpinner ? "" : " cpk-intelligence-pill__check--shown")
5808
+ })]
5809
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: label })]
5810
+ });
5811
+ }
5812
+
5658
5813
  //#endregion
5659
5814
  //#region src/v2/components/chat/CopilotChatMessageView.tsx
5660
5815
  /**
@@ -5812,14 +5967,12 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5812
5967
  const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
5813
5968
  (0, react.useEffect)(() => {
5814
5969
  if (!config?.agentId) return;
5815
- const registryAgent = copilotkit.getAgent(config.agentId);
5816
- const agent = getThreadClone(registryAgent, config.threadId) ?? registryAgent;
5970
+ const agent = copilotkit.getAgent(config.agentId);
5817
5971
  if (!agent) return;
5818
5972
  const subscription = agent.subscribe({ onStateChanged: forceUpdate });
5819
5973
  return () => subscription.unsubscribe();
5820
5974
  }, [
5821
5975
  config?.agentId,
5822
- config?.threadId,
5823
5976
  copilotkit,
5824
5977
  forceUpdate
5825
5978
  ]);
@@ -5902,6 +6055,10 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
5902
6055
  renderCustomMessage,
5903
6056
  stateSnapshot
5904
6057
  }, `${message.id}-custom-after`));
6058
+ if (copilotkit.intelligence !== void 0 && message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(IntelligenceIndicator, {
6059
+ message,
6060
+ agentId: config?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID
6061
+ }, `${message.id}-intelligence`));
5905
6062
  return elements.filter(Boolean);
5906
6063
  };
5907
6064
  const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
@@ -6850,7 +7007,6 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6850
7007
  const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
6851
7008
  const { agent } = useAgent({
6852
7009
  agentId: resolvedAgentId,
6853
- threadId: resolvedThreadId,
6854
7010
  throttleMs
6855
7011
  });
6856
7012
  const { copilotkit } = useCopilotKit();
@@ -6892,6 +7048,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
6892
7048
  let detached = false;
6893
7049
  const connectAbortController = new AbortController();
6894
7050
  if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
7051
+ agent.threadId = resolvedThreadId;
6895
7052
  const connect = async (agent) => {
6896
7053
  try {
6897
7054
  await copilotkit.connectAgent({ agent });
@@ -7300,18 +7457,19 @@ CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
7300
7457
  //#region src/v2/components/chat/CopilotSidebarView.tsx
7301
7458
  const DEFAULT_SIDEBAR_WIDTH = 480;
7302
7459
  const SIDEBAR_TRANSITION_MS = 260;
7303
- function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, ...props }) {
7460
+ function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
7304
7461
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
7305
7462
  isModalDefaultOpen: defaultOpen,
7306
7463
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarViewInternal, {
7307
7464
  header,
7308
7465
  toggleButton,
7309
7466
  width,
7467
+ position,
7310
7468
  ...props
7311
7469
  })
7312
7470
  });
7313
7471
  }
7314
- function CopilotSidebarViewInternal({ header, toggleButton, width, ...props }) {
7472
+ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
7315
7473
  const isSidebarOpen = useCopilotChatConfiguration()?.isModalOpen ?? false;
7316
7474
  const sidebarRef = (0, react.useRef)(null);
7317
7475
  const [sidebarWidth, setSidebarWidth] = (0, react.useState)(width ?? DEFAULT_SIDEBAR_WIDTH);
@@ -7344,26 +7502,33 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, ...props }) {
7344
7502
  (0, react.useLayoutEffect)(() => {
7345
7503
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
7346
7504
  if (!window.matchMedia("(min-width: 768px)").matches) return;
7505
+ const marginStyleProp = position === "left" ? "marginInlineStart" : "marginInlineEnd";
7506
+ const transitionCssProp = position === "left" ? "margin-inline-start" : "margin-inline-end";
7347
7507
  if (isSidebarOpen) {
7348
- if (hasMounted.current) document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
7349
- document.body.style.marginInlineEnd = widthToMargin(sidebarWidth);
7508
+ if (hasMounted.current) document.body.style.transition = `${transitionCssProp} ${SIDEBAR_TRANSITION_MS}ms ease`;
7509
+ document.body.style[marginStyleProp] = widthToMargin(sidebarWidth);
7350
7510
  } else if (hasMounted.current) {
7351
- document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
7352
- document.body.style.marginInlineEnd = "";
7511
+ document.body.style.transition = `${transitionCssProp} ${SIDEBAR_TRANSITION_MS}ms ease`;
7512
+ document.body.style[marginStyleProp] = "";
7353
7513
  }
7354
7514
  hasMounted.current = true;
7355
7515
  return () => {
7356
- document.body.style.marginInlineEnd = "";
7516
+ document.body.style[marginStyleProp] = "";
7357
7517
  document.body.style.transition = "";
7358
7518
  };
7359
- }, [isSidebarOpen, sidebarWidth]);
7519
+ }, [
7520
+ isSidebarOpen,
7521
+ sidebarWidth,
7522
+ position
7523
+ ]);
7360
7524
  const headerElement = renderSlot(header, CopilotModalHeader, {});
7361
- return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [renderSlot(toggleButton, CopilotChatToggleButton, {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
7525
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [renderSlot(toggleButton, CopilotChatToggleButton, position === "left" ? { className: "cpk:left-6 cpk:right-auto" } : {}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("aside", {
7362
7526
  ref: sidebarRef,
7363
7527
  "data-copilotkit": true,
7364
7528
  "data-testid": "copilot-sidebar",
7365
7529
  "data-copilot-sidebar": true,
7366
- className: cn("copilotKitSidebar copilotKitWindow", "cpk:fixed cpk:right-0 cpk:top-0 cpk:z-[1200] cpk:flex", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", "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" : "cpk:translate-x-full cpk:pointer-events-none"),
7530
+ "data-position": position,
7531
+ 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"),
7367
7532
  style: {
7368
7533
  ["--sidebar-width"]: widthToCss(sidebarWidth),
7369
7534
  paddingTop: "env(safe-area-inset-top)",
@@ -7570,7 +7735,7 @@ var CopilotPopupView_default = CopilotPopupView;
7570
7735
 
7571
7736
  //#endregion
7572
7737
  //#region src/v2/components/chat/CopilotSidebar.tsx
7573
- function CopilotSidebar({ header, toggleButton, defaultOpen, width, ...chatProps }) {
7738
+ function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ...chatProps }) {
7574
7739
  const { checkFeature } = useLicenseContext();
7575
7740
  const isSidebarLicensed = checkFeature("sidebar");
7576
7741
  (0, react.useEffect)(() => {
@@ -7578,13 +7743,14 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, ...chatProps
7578
7743
  }, [isSidebarLicensed]);
7579
7744
  const SidebarViewOverride = (0, react.useMemo)(() => {
7580
7745
  const Component = (viewProps) => {
7581
- const { header: viewHeader, toggleButton: viewToggleButton, width: viewWidth, defaultOpen: viewDefaultOpen, ...restProps } = viewProps;
7746
+ const { header: viewHeader, toggleButton: viewToggleButton, width: viewWidth, defaultOpen: viewDefaultOpen, position: viewPosition, ...restProps } = viewProps;
7582
7747
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarView, {
7583
7748
  ...restProps,
7584
7749
  header: header ?? viewHeader,
7585
7750
  toggleButton: toggleButton ?? viewToggleButton,
7586
7751
  width: width ?? viewWidth,
7587
- defaultOpen: defaultOpen ?? viewDefaultOpen
7752
+ defaultOpen: defaultOpen ?? viewDefaultOpen,
7753
+ position: position ?? viewPosition
7588
7754
  });
7589
7755
  };
7590
7756
  return Object.assign(Component, CopilotChatView_default);
@@ -7592,7 +7758,8 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, ...chatProps
7592
7758
  header,
7593
7759
  toggleButton,
7594
7760
  width,
7595
- defaultOpen
7761
+ defaultOpen,
7762
+ position
7596
7763
  ]);
7597
7764
  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, {
7598
7765
  welcomeScreen: CopilotSidebarView.WelcomeScreen,
@@ -10024,6 +10191,12 @@ Object.defineProperty(exports, 'DefaultOpenIcon', {
10024
10191
  return DefaultOpenIcon;
10025
10192
  }
10026
10193
  });
10194
+ Object.defineProperty(exports, 'IntelligenceIndicator', {
10195
+ enumerable: true,
10196
+ get: function () {
10197
+ return IntelligenceIndicator;
10198
+ }
10199
+ });
10027
10200
  Object.defineProperty(exports, 'MCPAppsActivityContentSchema', {
10028
10201
  enumerable: true,
10029
10202
  get: function () {
@@ -10252,4 +10425,4 @@ Object.defineProperty(exports, 'useToast', {
10252
10425
  return useToast;
10253
10426
  }
10254
10427
  });
10255
- //# sourceMappingURL=copilotkit-DGbvw8n2.cjs.map
10428
+ //# sourceMappingURL=copilotkit-Dnj9pi4m.cjs.map