@copilotkit/react-core 1.57.1 → 1.57.3

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 (41) hide show
  1. package/dist/{copilotkit-sQWiKtxA.d.cts → copilotkit-BK9CVq9A.d.cts} +6 -1
  2. package/dist/{copilotkit-sQWiKtxA.d.cts.map → copilotkit-BK9CVq9A.d.cts.map} +1 -1
  3. package/dist/{copilotkit-DjxXMYHG.mjs → copilotkit-CC8DjOiC.mjs} +404 -367
  4. package/dist/copilotkit-CC8DjOiC.mjs.map +1 -0
  5. package/dist/{copilotkit-C3k13WZn.cjs → copilotkit-CtXcs1ea.cjs} +403 -366
  6. package/dist/copilotkit-CtXcs1ea.cjs.map +1 -0
  7. package/dist/{copilotkit-BN4I_y1n.d.mts → copilotkit-WlmeVijs.d.mts} +6 -1
  8. package/dist/{copilotkit-BN4I_y1n.d.mts.map → copilotkit-WlmeVijs.d.mts.map} +1 -1
  9. package/dist/index.cjs +1 -1
  10. package/dist/index.d.cts +1 -1
  11. package/dist/index.d.mts +1 -1
  12. package/dist/index.mjs +1 -1
  13. package/dist/index.umd.js +191 -15
  14. package/dist/index.umd.js.map +1 -1
  15. package/dist/v2/headless.cjs +110 -3
  16. package/dist/v2/headless.cjs.map +1 -1
  17. package/dist/v2/headless.d.cts +142 -2
  18. package/dist/v2/headless.d.cts.map +1 -1
  19. package/dist/v2/headless.d.mts +142 -1
  20. package/dist/v2/headless.d.mts.map +1 -1
  21. package/dist/v2/headless.mjs +108 -4
  22. package/dist/v2/headless.mjs.map +1 -1
  23. package/dist/v2/index.cjs +1 -1
  24. package/dist/v2/index.css +1 -1
  25. package/dist/v2/index.d.cts +1 -1
  26. package/dist/v2/index.d.mts +1 -1
  27. package/dist/v2/index.mjs +1 -1
  28. package/dist/v2/index.umd.js +403 -364
  29. package/dist/v2/index.umd.js.map +1 -1
  30. package/package.json +6 -6
  31. package/src/v2/components/chat/CopilotSidebar.tsx +5 -1
  32. package/src/v2/components/chat/CopilotSidebarView.tsx +24 -10
  33. package/src/v2/components/chat/__tests__/CopilotChatPerf.e2e.test.tsx +68 -0
  34. package/src/v2/components/chat/__tests__/CopilotSidebarView.position.test.tsx +159 -0
  35. package/src/v2/headless.ts +23 -1
  36. package/src/v2/hooks/__tests__/use-component.test.tsx +4 -1
  37. package/src/v2/hooks/use-component.tsx +2 -0
  38. package/src/v2/hooks/use-default-render-tool.tsx +18 -1
  39. package/src/v2/hooks/use-render-tool-call.tsx +35 -5
  40. package/dist/copilotkit-C3k13WZn.cjs.map +0 -1
  41. package/dist/copilotkit-DjxXMYHG.mjs.map +0 -1
@@ -1415,6 +1415,300 @@ const LicenseContext = createContext({
1415
1415
  });
1416
1416
  const useLicenseContext = () => useContext(LicenseContext);
1417
1417
 
1418
+ //#endregion
1419
+ //#region src/v2/types/defineToolCallRenderer.ts
1420
+ function defineToolCallRenderer(def) {
1421
+ const argsSchema = def.name === "*" && !def.args ? z.any() : def.args;
1422
+ return {
1423
+ name: def.name,
1424
+ args: argsSchema,
1425
+ render: def.render,
1426
+ ...def.agentId ? { agentId: def.agentId } : {}
1427
+ };
1428
+ }
1429
+
1430
+ //#endregion
1431
+ //#region src/v2/hooks/use-render-tool.tsx
1432
+ const EMPTY_DEPS$1 = [];
1433
+ /**
1434
+ * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
1435
+ *
1436
+ * Key behavior:
1437
+ * - deduplicates by `agentId:name` (latest registration wins),
1438
+ * - keeps renderer entries on cleanup so historical chat tool calls can still render,
1439
+ * - refreshes registration when `deps` change.
1440
+ *
1441
+ * @typeParam S - Schema type describing tool call parameters.
1442
+ * @param config - Renderer config for wildcard or named tools.
1443
+ * @param deps - Optional dependencies to refresh registration.
1444
+ *
1445
+ * @example
1446
+ * ```tsx
1447
+ * useRenderTool(
1448
+ * {
1449
+ * name: "searchDocs",
1450
+ * parameters: z.object({ query: z.string() }),
1451
+ * render: ({ status, parameters, result }) => {
1452
+ * if (status === "executing") return <div>Searching {parameters.query}</div>;
1453
+ * if (status === "complete") return <div>{result}</div>;
1454
+ * return <div>Preparing...</div>;
1455
+ * },
1456
+ * },
1457
+ * [],
1458
+ * );
1459
+ * ```
1460
+ *
1461
+ * @example
1462
+ * ```tsx
1463
+ * useRenderTool(
1464
+ * {
1465
+ * name: "summarize",
1466
+ * parameters: z.object({ text: z.string() }),
1467
+ * agentId: "research-agent",
1468
+ * render: ({ name, status }) => <div>{name}: {status}</div>,
1469
+ * },
1470
+ * [selectedAgentId],
1471
+ * );
1472
+ * ```
1473
+ */
1474
+ function useRenderTool(config, deps) {
1475
+ const { copilotkit } = useCopilotKit();
1476
+ const extraDeps = deps ?? EMPTY_DEPS$1;
1477
+ useEffect(() => {
1478
+ const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
1479
+ name: "*",
1480
+ render: (props) => config.render({
1481
+ ...props,
1482
+ parameters: props.args
1483
+ }),
1484
+ ...config.agentId ? { agentId: config.agentId } : {}
1485
+ }) : defineToolCallRenderer({
1486
+ name: config.name,
1487
+ args: config.parameters,
1488
+ render: (props) => config.render({
1489
+ ...props,
1490
+ parameters: props.args
1491
+ }),
1492
+ ...config.agentId ? { agentId: config.agentId } : {}
1493
+ });
1494
+ copilotkit.addHookRenderToolCall(renderer);
1495
+ }, [
1496
+ config.name,
1497
+ copilotkit,
1498
+ JSON.stringify(extraDeps)
1499
+ ]);
1500
+ }
1501
+
1502
+ //#endregion
1503
+ //#region src/v2/hooks/use-default-render-tool.tsx
1504
+ /**
1505
+ * Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
1506
+ *
1507
+ * - Call with no config to use CopilotKit's built-in default tool-call card.
1508
+ * - Pass `config.render` to replace the default UI with your own fallback renderer.
1509
+ *
1510
+ * This is useful when you want a generic renderer for tools that do not have a
1511
+ * dedicated `useRenderTool({ name: "..." })` registration.
1512
+ *
1513
+ * @param config - Optional custom wildcard render function.
1514
+ * @param deps - Optional dependencies to refresh registration.
1515
+ *
1516
+ * @example
1517
+ * ```tsx
1518
+ * useDefaultRenderTool();
1519
+ * ```
1520
+ *
1521
+ * @example
1522
+ * ```tsx
1523
+ * useDefaultRenderTool({
1524
+ * render: ({ name, status }) => <div>{name}: {status}</div>,
1525
+ * });
1526
+ * ```
1527
+ *
1528
+ * @example
1529
+ * ```tsx
1530
+ * useDefaultRenderTool(
1531
+ * {
1532
+ * render: ({ name, result }) => (
1533
+ * <ToolEventRow title={name} payload={result} compact={compactMode} />
1534
+ * ),
1535
+ * },
1536
+ * [compactMode],
1537
+ * );
1538
+ * ```
1539
+ */
1540
+ function useDefaultRenderTool(config, deps) {
1541
+ useRenderTool({
1542
+ name: "*",
1543
+ render: config?.render ?? DefaultToolCallRenderer
1544
+ }, deps);
1545
+ }
1546
+ function DefaultToolCallRenderer({ name, parameters, status, result }) {
1547
+ const [isExpanded, setIsExpanded] = useState(false);
1548
+ const statusString = String(status);
1549
+ const isActive = statusString === "inProgress" || statusString === "executing";
1550
+ const isComplete = statusString === "complete";
1551
+ const statusLabel = isActive ? "Running" : isComplete ? "Done" : status;
1552
+ const dotColor = isActive ? "#f59e0b" : isComplete ? "#10b981" : "#a1a1aa";
1553
+ const badgeBg = isActive ? "#fef3c7" : isComplete ? "#d1fae5" : "#f4f4f5";
1554
+ const badgeColor = isActive ? "#92400e" : isComplete ? "#065f46" : "#3f3f46";
1555
+ return /* @__PURE__ */ jsx("div", {
1556
+ "data-testid": "copilot-tool-render",
1557
+ "data-tool-name": name,
1558
+ "data-status": statusString,
1559
+ "data-args": safeStringifyForAttr(parameters),
1560
+ "data-result": safeStringifyForAttr(result),
1561
+ style: {
1562
+ marginTop: "8px",
1563
+ paddingBottom: "8px"
1564
+ },
1565
+ children: /* @__PURE__ */ jsxs("div", {
1566
+ style: {
1567
+ borderRadius: "12px",
1568
+ border: "1px solid #e4e4e7",
1569
+ backgroundColor: "#fafafa",
1570
+ padding: "14px 16px"
1571
+ },
1572
+ children: [/* @__PURE__ */ jsxs("div", {
1573
+ onClick: () => setIsExpanded(!isExpanded),
1574
+ style: {
1575
+ display: "flex",
1576
+ alignItems: "center",
1577
+ justifyContent: "space-between",
1578
+ gap: "10px",
1579
+ cursor: "pointer",
1580
+ userSelect: "none"
1581
+ },
1582
+ children: [/* @__PURE__ */ jsxs("div", {
1583
+ style: {
1584
+ display: "flex",
1585
+ alignItems: "center",
1586
+ gap: "8px",
1587
+ minWidth: 0
1588
+ },
1589
+ children: [
1590
+ /* @__PURE__ */ jsx("svg", {
1591
+ style: {
1592
+ height: "14px",
1593
+ width: "14px",
1594
+ color: "#71717a",
1595
+ transition: "transform 0.15s",
1596
+ transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
1597
+ flexShrink: 0
1598
+ },
1599
+ fill: "none",
1600
+ viewBox: "0 0 24 24",
1601
+ strokeWidth: 2,
1602
+ stroke: "currentColor",
1603
+ children: /* @__PURE__ */ jsx("path", {
1604
+ strokeLinecap: "round",
1605
+ strokeLinejoin: "round",
1606
+ d: "M8.25 4.5l7.5 7.5-7.5 7.5"
1607
+ })
1608
+ }),
1609
+ /* @__PURE__ */ jsx("span", { style: {
1610
+ display: "inline-block",
1611
+ height: "8px",
1612
+ width: "8px",
1613
+ borderRadius: "50%",
1614
+ backgroundColor: dotColor,
1615
+ flexShrink: 0
1616
+ } }),
1617
+ /* @__PURE__ */ jsx("span", {
1618
+ "data-testid": "copilot-tool-render-name",
1619
+ style: {
1620
+ fontSize: "13px",
1621
+ fontWeight: 600,
1622
+ color: "#18181b",
1623
+ overflow: "hidden",
1624
+ textOverflow: "ellipsis",
1625
+ whiteSpace: "nowrap"
1626
+ },
1627
+ children: name
1628
+ })
1629
+ ]
1630
+ }), /* @__PURE__ */ jsx("span", {
1631
+ "data-testid": "copilot-tool-render-status",
1632
+ style: {
1633
+ display: "inline-flex",
1634
+ alignItems: "center",
1635
+ borderRadius: "9999px",
1636
+ padding: "2px 8px",
1637
+ fontSize: "11px",
1638
+ fontWeight: 500,
1639
+ backgroundColor: badgeBg,
1640
+ color: badgeColor,
1641
+ flexShrink: 0
1642
+ },
1643
+ children: statusLabel
1644
+ })]
1645
+ }), isExpanded && /* @__PURE__ */ jsxs("div", {
1646
+ style: {
1647
+ marginTop: "12px",
1648
+ display: "grid",
1649
+ gap: "12px"
1650
+ },
1651
+ children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
1652
+ style: {
1653
+ fontSize: "10px",
1654
+ textTransform: "uppercase",
1655
+ letterSpacing: "0.05em",
1656
+ color: "#71717a"
1657
+ },
1658
+ children: "Arguments"
1659
+ }), /* @__PURE__ */ jsx("pre", {
1660
+ style: {
1661
+ marginTop: "6px",
1662
+ maxHeight: "200px",
1663
+ overflow: "auto",
1664
+ borderRadius: "6px",
1665
+ backgroundColor: "#f4f4f5",
1666
+ padding: "10px",
1667
+ fontSize: "11px",
1668
+ lineHeight: 1.6,
1669
+ color: "#27272a",
1670
+ whiteSpace: "pre-wrap",
1671
+ wordBreak: "break-word"
1672
+ },
1673
+ children: JSON.stringify(parameters ?? {}, null, 2)
1674
+ })] }), result !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
1675
+ style: {
1676
+ fontSize: "10px",
1677
+ textTransform: "uppercase",
1678
+ letterSpacing: "0.05em",
1679
+ color: "#71717a"
1680
+ },
1681
+ children: "Result"
1682
+ }), /* @__PURE__ */ jsx("pre", {
1683
+ style: {
1684
+ marginTop: "6px",
1685
+ maxHeight: "200px",
1686
+ overflow: "auto",
1687
+ borderRadius: "6px",
1688
+ backgroundColor: "#f4f4f5",
1689
+ padding: "10px",
1690
+ fontSize: "11px",
1691
+ lineHeight: 1.6,
1692
+ color: "#27272a",
1693
+ whiteSpace: "pre-wrap",
1694
+ wordBreak: "break-word"
1695
+ },
1696
+ children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
1697
+ })] })]
1698
+ })]
1699
+ })
1700
+ });
1701
+ }
1702
+ function safeStringifyForAttr(value) {
1703
+ if (value === void 0 || value === null) return "";
1704
+ if (typeof value === "string") return value;
1705
+ try {
1706
+ return JSON.stringify(value);
1707
+ } catch {
1708
+ return String(value);
1709
+ }
1710
+ }
1711
+
1418
1712
  //#endregion
1419
1713
  //#region src/v2/hooks/use-render-tool-call.tsx
1420
1714
  /**
@@ -1469,13 +1763,10 @@ function useRenderToolCall() {
1469
1763
  }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
1470
1764
  return useCallback(({ toolCall, toolMessage }) => {
1471
1765
  const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
1472
- const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
1473
- if (!renderConfig) return null;
1474
- const RenderComponent = renderConfig.render;
1475
1766
  return /* @__PURE__ */ jsx(ToolCallRenderer, {
1476
1767
  toolCall,
1477
1768
  toolMessage,
1478
- RenderComponent,
1769
+ RenderComponent: (exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*"))?.render ?? defaultToolCallRenderAdapter,
1479
1770
  isExecuting: executingToolCallIds.has(toolCall.id)
1480
1771
  }, toolCall.id);
1481
1772
  }, [
@@ -1484,6 +1775,15 @@ function useRenderToolCall() {
1484
1775
  agentId
1485
1776
  ]);
1486
1777
  }
1778
+ function defaultToolCallRenderAdapter(props) {
1779
+ const status = props.status === ToolCallStatus.Complete ? "complete" : props.status === ToolCallStatus.Executing ? "executing" : "inProgress";
1780
+ return /* @__PURE__ */ jsx(DefaultToolCallRenderer, {
1781
+ name: props.name,
1782
+ parameters: props.args,
1783
+ status,
1784
+ result: props.result
1785
+ });
1786
+ }
1487
1787
 
1488
1788
  //#endregion
1489
1789
  //#region src/v2/components/CopilotKitInspector.tsx
@@ -2723,18 +3023,6 @@ function getOperationSurfaceId(operation) {
2723
3023
  return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
2724
3024
  }
2725
3025
 
2726
- //#endregion
2727
- //#region src/v2/types/defineToolCallRenderer.ts
2728
- function defineToolCallRenderer(def) {
2729
- const argsSchema = def.name === "*" && !def.args ? z.any() : def.args;
2730
- return {
2731
- name: def.name,
2732
- args: argsSchema,
2733
- render: def.render,
2734
- ...def.agentId ? { agentId: def.agentId } : {}
2735
- };
2736
- }
2737
-
2738
3026
  //#endregion
2739
3027
  //#region src/v2/a2ui/A2UIToolCallRenderer.tsx
2740
3028
  /**
@@ -3557,374 +3845,113 @@ function useRenderActivityMessage() {
3557
3845
  }, [
3558
3846
  agentId,
3559
3847
  copilotkit,
3560
- findRenderer
3561
- ]);
3562
- return useMemo(() => ({
3563
- renderActivityMessage,
3564
- findRenderer
3565
- }), [renderActivityMessage, findRenderer]);
3566
- }
3567
-
3568
- //#endregion
3569
- //#region src/v2/hooks/use-frontend-tool.tsx
3570
- const EMPTY_DEPS$1 = [];
3571
- function useFrontendTool(tool, deps) {
3572
- const { copilotkit } = useCopilotKit();
3573
- const extraDeps = deps ?? EMPTY_DEPS$1;
3574
- useEffect(() => {
3575
- const name = tool.name;
3576
- if (copilotkit.getTool({
3577
- toolName: name,
3578
- agentId: tool.agentId
3579
- })) {
3580
- console.warn(`Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`);
3581
- copilotkit.removeTool(name, tool.agentId);
3582
- }
3583
- copilotkit.addTool(tool);
3584
- if (tool.render) copilotkit.addHookRenderToolCall({
3585
- name,
3586
- args: tool.parameters,
3587
- agentId: tool.agentId,
3588
- render: tool.render
3589
- });
3590
- return () => {
3591
- copilotkit.removeTool(name, tool.agentId);
3592
- };
3593
- }, [
3594
- tool.name,
3595
- tool.available,
3596
- copilotkit,
3597
- JSON.stringify(extraDeps)
3598
- ]);
3599
- }
3600
-
3601
- //#endregion
3602
- //#region src/v2/hooks/use-component.tsx
3603
- /**
3604
- * Registers a React component as a frontend tool renderer in chat.
3605
- *
3606
- * This hook is a convenience wrapper around `useFrontendTool` that:
3607
- * - builds a model-facing tool description,
3608
- * - forwards optional schema parameters (any Standard Schema V1 compatible library),
3609
- * - renders your component with tool call parameters.
3610
- *
3611
- * Use this when you want to display a typed visual component for a tool call
3612
- * without manually wiring a full frontend tool object.
3613
- *
3614
- * When `parameters` is provided, render props are inferred from the schema.
3615
- * When omitted, the render component may accept any props.
3616
- *
3617
- * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
3618
- * @param config - Tool registration config.
3619
- * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
3620
- *
3621
- * @example
3622
- * ```tsx
3623
- * // Without parameters — render accepts any props
3624
- * useComponent({
3625
- * name: "showGreeting",
3626
- * render: ({ message }: { message: string }) => <div>{message}</div>,
3627
- * });
3628
- * ```
3629
- *
3630
- * @example
3631
- * ```tsx
3632
- * // With parameters — render props inferred from schema
3633
- * useComponent({
3634
- * name: "showWeatherCard",
3635
- * parameters: z.object({ city: z.string() }),
3636
- * render: ({ city }) => <div>{city}</div>,
3637
- * });
3638
- * ```
3639
- *
3640
- * @example
3641
- * ```tsx
3642
- * useComponent(
3643
- * {
3644
- * name: "renderProfile",
3645
- * parameters: z.object({ userId: z.string() }),
3646
- * render: ProfileCard,
3647
- * agentId: "support-agent",
3648
- * },
3649
- * [selectedAgentId],
3650
- * );
3651
- * ```
3652
- */
3653
- function useComponent(config, deps) {
3654
- const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
3655
- const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
3656
- useFrontendTool({
3657
- name: config.name,
3658
- description: fullDescription,
3659
- parameters: config.parameters,
3660
- render: ({ args }) => {
3661
- const Component = config.render;
3662
- return /* @__PURE__ */ jsx(Component, { ...args });
3663
- },
3664
- agentId: config.agentId
3665
- }, deps);
3666
- }
3667
-
3668
- //#endregion
3669
- //#region src/v2/hooks/use-render-tool.tsx
3670
- const EMPTY_DEPS = [];
3671
- /**
3672
- * Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
3673
- *
3674
- * Key behavior:
3675
- * - deduplicates by `agentId:name` (latest registration wins),
3676
- * - keeps renderer entries on cleanup so historical chat tool calls can still render,
3677
- * - refreshes registration when `deps` change.
3678
- *
3679
- * @typeParam S - Schema type describing tool call parameters.
3680
- * @param config - Renderer config for wildcard or named tools.
3681
- * @param deps - Optional dependencies to refresh registration.
3682
- *
3683
- * @example
3684
- * ```tsx
3685
- * useRenderTool(
3686
- * {
3687
- * name: "searchDocs",
3688
- * parameters: z.object({ query: z.string() }),
3689
- * render: ({ status, parameters, result }) => {
3690
- * if (status === "executing") return <div>Searching {parameters.query}</div>;
3691
- * if (status === "complete") return <div>{result}</div>;
3692
- * return <div>Preparing...</div>;
3693
- * },
3694
- * },
3695
- * [],
3696
- * );
3697
- * ```
3698
- *
3699
- * @example
3700
- * ```tsx
3701
- * useRenderTool(
3702
- * {
3703
- * name: "summarize",
3704
- * parameters: z.object({ text: z.string() }),
3705
- * agentId: "research-agent",
3706
- * render: ({ name, status }) => <div>{name}: {status}</div>,
3707
- * },
3708
- * [selectedAgentId],
3709
- * );
3710
- * ```
3711
- */
3712
- function useRenderTool(config, deps) {
3848
+ findRenderer
3849
+ ]);
3850
+ return useMemo(() => ({
3851
+ renderActivityMessage,
3852
+ findRenderer
3853
+ }), [renderActivityMessage, findRenderer]);
3854
+ }
3855
+
3856
+ //#endregion
3857
+ //#region src/v2/hooks/use-frontend-tool.tsx
3858
+ const EMPTY_DEPS = [];
3859
+ function useFrontendTool(tool, deps) {
3713
3860
  const { copilotkit } = useCopilotKit();
3714
3861
  const extraDeps = deps ?? EMPTY_DEPS;
3715
3862
  useEffect(() => {
3716
- const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
3717
- name: "*",
3718
- render: (props) => config.render({
3719
- ...props,
3720
- parameters: props.args
3721
- }),
3722
- ...config.agentId ? { agentId: config.agentId } : {}
3723
- }) : defineToolCallRenderer({
3724
- name: config.name,
3725
- args: config.parameters,
3726
- render: (props) => config.render({
3727
- ...props,
3728
- parameters: props.args
3729
- }),
3730
- ...config.agentId ? { agentId: config.agentId } : {}
3863
+ const name = tool.name;
3864
+ if (copilotkit.getTool({
3865
+ toolName: name,
3866
+ agentId: tool.agentId
3867
+ })) {
3868
+ console.warn(`Tool '${name}' already exists for agent '${tool.agentId || "global"}'. Overriding with latest registration.`);
3869
+ copilotkit.removeTool(name, tool.agentId);
3870
+ }
3871
+ copilotkit.addTool(tool);
3872
+ if (tool.render) copilotkit.addHookRenderToolCall({
3873
+ name,
3874
+ args: tool.parameters,
3875
+ agentId: tool.agentId,
3876
+ render: tool.render
3731
3877
  });
3732
- copilotkit.addHookRenderToolCall(renderer);
3878
+ return () => {
3879
+ copilotkit.removeTool(name, tool.agentId);
3880
+ };
3733
3881
  }, [
3734
- config.name,
3882
+ tool.name,
3883
+ tool.available,
3735
3884
  copilotkit,
3736
3885
  JSON.stringify(extraDeps)
3737
3886
  ]);
3738
3887
  }
3739
3888
 
3740
3889
  //#endregion
3741
- //#region src/v2/hooks/use-default-render-tool.tsx
3890
+ //#region src/v2/hooks/use-component.tsx
3742
3891
  /**
3743
- * Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
3892
+ * Registers a React component as a frontend tool renderer in chat.
3744
3893
  *
3745
- * - Call with no config to use CopilotKit's built-in default tool-call card.
3746
- * - Pass `config.render` to replace the default UI with your own fallback renderer.
3894
+ * This hook is a convenience wrapper around `useFrontendTool` that:
3895
+ * - builds a model-facing tool description,
3896
+ * - forwards optional schema parameters (any Standard Schema V1 compatible library),
3897
+ * - renders your component with tool call parameters.
3747
3898
  *
3748
- * This is useful when you want a generic renderer for tools that do not have a
3749
- * dedicated `useRenderTool({ name: "..." })` registration.
3899
+ * Use this when you want to display a typed visual component for a tool call
3900
+ * without manually wiring a full frontend tool object.
3750
3901
  *
3751
- * @param config - Optional custom wildcard render function.
3752
- * @param deps - Optional dependencies to refresh registration.
3902
+ * When `parameters` is provided, render props are inferred from the schema.
3903
+ * When omitted, the render component may accept any props.
3904
+ *
3905
+ * @typeParam TSchema - Schema describing tool parameters, or `undefined` when no schema is given.
3906
+ * @param config - Tool registration config.
3907
+ * @param deps - Optional dependencies to refresh registration (same semantics as `useEffect`).
3753
3908
  *
3754
3909
  * @example
3755
3910
  * ```tsx
3756
- * useDefaultRenderTool();
3911
+ * // Without parameters — render accepts any props
3912
+ * useComponent({
3913
+ * name: "showGreeting",
3914
+ * render: ({ message }: { message: string }) => <div>{message}</div>,
3915
+ * });
3757
3916
  * ```
3758
3917
  *
3759
3918
  * @example
3760
3919
  * ```tsx
3761
- * useDefaultRenderTool({
3762
- * render: ({ name, status }) => <div>{name}: {status}</div>,
3920
+ * // With parameters — render props inferred from schema
3921
+ * useComponent({
3922
+ * name: "showWeatherCard",
3923
+ * parameters: z.object({ city: z.string() }),
3924
+ * render: ({ city }) => <div>{city}</div>,
3763
3925
  * });
3764
3926
  * ```
3765
3927
  *
3766
3928
  * @example
3767
3929
  * ```tsx
3768
- * useDefaultRenderTool(
3930
+ * useComponent(
3769
3931
  * {
3770
- * render: ({ name, result }) => (
3771
- * <ToolEventRow title={name} payload={result} compact={compactMode} />
3772
- * ),
3932
+ * name: "renderProfile",
3933
+ * parameters: z.object({ userId: z.string() }),
3934
+ * render: ProfileCard,
3935
+ * agentId: "support-agent",
3773
3936
  * },
3774
- * [compactMode],
3937
+ * [selectedAgentId],
3775
3938
  * );
3776
3939
  * ```
3777
3940
  */
3778
- function useDefaultRenderTool(config, deps) {
3779
- useRenderTool({
3780
- name: "*",
3781
- render: config?.render ?? DefaultToolCallRenderer
3782
- }, deps);
3783
- }
3784
- function DefaultToolCallRenderer({ name, parameters, status, result }) {
3785
- const [isExpanded, setIsExpanded] = useState(false);
3786
- const statusString = String(status);
3787
- const isActive = statusString === "inProgress" || statusString === "executing";
3788
- const isComplete = statusString === "complete";
3789
- return /* @__PURE__ */ jsx("div", {
3790
- style: {
3791
- marginTop: "8px",
3792
- paddingBottom: "8px"
3941
+ function useComponent(config, deps) {
3942
+ const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
3943
+ const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
3944
+ useFrontendTool({
3945
+ name: config.name,
3946
+ description: fullDescription,
3947
+ parameters: config.parameters,
3948
+ render: ({ args }) => {
3949
+ const Component = config.render;
3950
+ return /* @__PURE__ */ jsx(Component, { ...args });
3793
3951
  },
3794
- children: /* @__PURE__ */ jsxs("div", {
3795
- style: {
3796
- borderRadius: "12px",
3797
- border: "1px solid #e4e4e7",
3798
- backgroundColor: "#fafafa",
3799
- padding: "14px 16px"
3800
- },
3801
- children: [/* @__PURE__ */ jsxs("div", {
3802
- onClick: () => setIsExpanded(!isExpanded),
3803
- style: {
3804
- display: "flex",
3805
- alignItems: "center",
3806
- justifyContent: "space-between",
3807
- gap: "10px",
3808
- cursor: "pointer",
3809
- userSelect: "none"
3810
- },
3811
- children: [/* @__PURE__ */ jsxs("div", {
3812
- style: {
3813
- display: "flex",
3814
- alignItems: "center",
3815
- gap: "8px",
3816
- minWidth: 0
3817
- },
3818
- children: [
3819
- /* @__PURE__ */ jsx("svg", {
3820
- style: {
3821
- height: "14px",
3822
- width: "14px",
3823
- color: "#71717a",
3824
- transition: "transform 0.15s",
3825
- transform: isExpanded ? "rotate(90deg)" : "rotate(0deg)",
3826
- flexShrink: 0
3827
- },
3828
- fill: "none",
3829
- viewBox: "0 0 24 24",
3830
- strokeWidth: 2,
3831
- stroke: "currentColor",
3832
- children: /* @__PURE__ */ jsx("path", {
3833
- strokeLinecap: "round",
3834
- strokeLinejoin: "round",
3835
- d: "M8.25 4.5l7.5 7.5-7.5 7.5"
3836
- })
3837
- }),
3838
- /* @__PURE__ */ jsx("span", { style: {
3839
- display: "inline-block",
3840
- height: "8px",
3841
- width: "8px",
3842
- borderRadius: "50%",
3843
- backgroundColor: isActive ? "#f59e0b" : isComplete ? "#10b981" : "#a1a1aa",
3844
- flexShrink: 0
3845
- } }),
3846
- /* @__PURE__ */ jsx("span", {
3847
- style: {
3848
- fontSize: "13px",
3849
- fontWeight: 600,
3850
- color: "#18181b",
3851
- overflow: "hidden",
3852
- textOverflow: "ellipsis",
3853
- whiteSpace: "nowrap"
3854
- },
3855
- children: name
3856
- })
3857
- ]
3858
- }), /* @__PURE__ */ jsx("span", {
3859
- style: {
3860
- display: "inline-flex",
3861
- alignItems: "center",
3862
- borderRadius: "9999px",
3863
- padding: "2px 8px",
3864
- fontSize: "11px",
3865
- fontWeight: 500,
3866
- backgroundColor: isActive ? "#fef3c7" : isComplete ? "#d1fae5" : "#f4f4f5",
3867
- color: isActive ? "#92400e" : isComplete ? "#065f46" : "#3f3f46",
3868
- flexShrink: 0
3869
- },
3870
- children: isActive ? "Running" : isComplete ? "Done" : status
3871
- })]
3872
- }), isExpanded && /* @__PURE__ */ jsxs("div", {
3873
- style: {
3874
- marginTop: "12px",
3875
- display: "grid",
3876
- gap: "12px"
3877
- },
3878
- children: [/* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
3879
- style: {
3880
- fontSize: "10px",
3881
- textTransform: "uppercase",
3882
- letterSpacing: "0.05em",
3883
- color: "#71717a"
3884
- },
3885
- children: "Arguments"
3886
- }), /* @__PURE__ */ jsx("pre", {
3887
- style: {
3888
- marginTop: "6px",
3889
- maxHeight: "200px",
3890
- overflow: "auto",
3891
- borderRadius: "6px",
3892
- backgroundColor: "#f4f4f5",
3893
- padding: "10px",
3894
- fontSize: "11px",
3895
- lineHeight: 1.6,
3896
- color: "#27272a",
3897
- whiteSpace: "pre-wrap",
3898
- wordBreak: "break-word"
3899
- },
3900
- children: JSON.stringify(parameters ?? {}, null, 2)
3901
- })] }), result !== void 0 && /* @__PURE__ */ jsxs("div", { children: [/* @__PURE__ */ jsx("div", {
3902
- style: {
3903
- fontSize: "10px",
3904
- textTransform: "uppercase",
3905
- letterSpacing: "0.05em",
3906
- color: "#71717a"
3907
- },
3908
- children: "Result"
3909
- }), /* @__PURE__ */ jsx("pre", {
3910
- style: {
3911
- marginTop: "6px",
3912
- maxHeight: "200px",
3913
- overflow: "auto",
3914
- borderRadius: "6px",
3915
- backgroundColor: "#f4f4f5",
3916
- padding: "10px",
3917
- fontSize: "11px",
3918
- lineHeight: 1.6,
3919
- color: "#27272a",
3920
- whiteSpace: "pre-wrap",
3921
- wordBreak: "break-word"
3922
- },
3923
- children: typeof result === "string" ? result : JSON.stringify(result, null, 2)
3924
- })] })]
3925
- })]
3926
- })
3927
- });
3952
+ agentId: config.agentId,
3953
+ followUp: config.followUp
3954
+ }, deps);
3928
3955
  }
3929
3956
 
3930
3957
  //#endregion
@@ -7401,18 +7428,19 @@ CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
7401
7428
  //#region src/v2/components/chat/CopilotSidebarView.tsx
7402
7429
  const DEFAULT_SIDEBAR_WIDTH = 480;
7403
7430
  const SIDEBAR_TRANSITION_MS = 260;
7404
- function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, ...props }) {
7431
+ function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
7405
7432
  return /* @__PURE__ */ jsx(CopilotChatConfigurationProvider, {
7406
7433
  isModalDefaultOpen: defaultOpen,
7407
7434
  children: /* @__PURE__ */ jsx(CopilotSidebarViewInternal, {
7408
7435
  header,
7409
7436
  toggleButton,
7410
7437
  width,
7438
+ position,
7411
7439
  ...props
7412
7440
  })
7413
7441
  });
7414
7442
  }
7415
- function CopilotSidebarViewInternal({ header, toggleButton, width, ...props }) {
7443
+ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
7416
7444
  const isSidebarOpen = useCopilotChatConfiguration()?.isModalOpen ?? false;
7417
7445
  const sidebarRef = useRef(null);
7418
7446
  const [sidebarWidth, setSidebarWidth] = useState(width ?? DEFAULT_SIDEBAR_WIDTH);
@@ -7445,26 +7473,33 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, ...props }) {
7445
7473
  useLayoutEffect(() => {
7446
7474
  if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
7447
7475
  if (!window.matchMedia("(min-width: 768px)").matches) return;
7476
+ const marginStyleProp = position === "left" ? "marginInlineStart" : "marginInlineEnd";
7477
+ const transitionCssProp = position === "left" ? "margin-inline-start" : "margin-inline-end";
7448
7478
  if (isSidebarOpen) {
7449
- if (hasMounted.current) document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
7450
- document.body.style.marginInlineEnd = widthToMargin(sidebarWidth);
7479
+ if (hasMounted.current) document.body.style.transition = `${transitionCssProp} ${SIDEBAR_TRANSITION_MS}ms ease`;
7480
+ document.body.style[marginStyleProp] = widthToMargin(sidebarWidth);
7451
7481
  } else if (hasMounted.current) {
7452
- document.body.style.transition = `margin-inline-end ${SIDEBAR_TRANSITION_MS}ms ease`;
7453
- document.body.style.marginInlineEnd = "";
7482
+ document.body.style.transition = `${transitionCssProp} ${SIDEBAR_TRANSITION_MS}ms ease`;
7483
+ document.body.style[marginStyleProp] = "";
7454
7484
  }
7455
7485
  hasMounted.current = true;
7456
7486
  return () => {
7457
- document.body.style.marginInlineEnd = "";
7487
+ document.body.style[marginStyleProp] = "";
7458
7488
  document.body.style.transition = "";
7459
7489
  };
7460
- }, [isSidebarOpen, sidebarWidth]);
7490
+ }, [
7491
+ isSidebarOpen,
7492
+ sidebarWidth,
7493
+ position
7494
+ ]);
7461
7495
  const headerElement = renderSlot(header, CopilotModalHeader, {});
7462
- return /* @__PURE__ */ jsxs(Fragment$1, { children: [renderSlot(toggleButton, CopilotChatToggleButton, {}), /* @__PURE__ */ jsx("aside", {
7496
+ return /* @__PURE__ */ jsxs(Fragment$1, { children: [renderSlot(toggleButton, CopilotChatToggleButton, position === "left" ? { className: "cpk:left-6 cpk:right-auto" } : {}), /* @__PURE__ */ jsx("aside", {
7463
7497
  ref: sidebarRef,
7464
7498
  "data-copilotkit": true,
7465
7499
  "data-testid": "copilot-sidebar",
7466
7500
  "data-copilot-sidebar": true,
7467
- 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"),
7501
+ "data-position": position,
7502
+ 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"),
7468
7503
  style: {
7469
7504
  ["--sidebar-width"]: widthToCss(sidebarWidth),
7470
7505
  paddingTop: "env(safe-area-inset-top)",
@@ -7671,7 +7706,7 @@ var CopilotPopupView_default = CopilotPopupView;
7671
7706
 
7672
7707
  //#endregion
7673
7708
  //#region src/v2/components/chat/CopilotSidebar.tsx
7674
- function CopilotSidebar({ header, toggleButton, defaultOpen, width, ...chatProps }) {
7709
+ function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ...chatProps }) {
7675
7710
  const { checkFeature } = useLicenseContext();
7676
7711
  const isSidebarLicensed = checkFeature("sidebar");
7677
7712
  useEffect(() => {
@@ -7679,13 +7714,14 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, ...chatProps
7679
7714
  }, [isSidebarLicensed]);
7680
7715
  const SidebarViewOverride = useMemo(() => {
7681
7716
  const Component = (viewProps) => {
7682
- const { header: viewHeader, toggleButton: viewToggleButton, width: viewWidth, defaultOpen: viewDefaultOpen, ...restProps } = viewProps;
7717
+ const { header: viewHeader, toggleButton: viewToggleButton, width: viewWidth, defaultOpen: viewDefaultOpen, position: viewPosition, ...restProps } = viewProps;
7683
7718
  return /* @__PURE__ */ jsx(CopilotSidebarView, {
7684
7719
  ...restProps,
7685
7720
  header: header ?? viewHeader,
7686
7721
  toggleButton: toggleButton ?? viewToggleButton,
7687
7722
  width: width ?? viewWidth,
7688
- defaultOpen: defaultOpen ?? viewDefaultOpen
7723
+ defaultOpen: defaultOpen ?? viewDefaultOpen,
7724
+ position: position ?? viewPosition
7689
7725
  });
7690
7726
  };
7691
7727
  return Object.assign(Component, CopilotChatView_default);
@@ -7693,7 +7729,8 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, ...chatProps
7693
7729
  header,
7694
7730
  toggleButton,
7695
7731
  width,
7696
- defaultOpen
7732
+ defaultOpen,
7733
+ position
7697
7734
  ]);
7698
7735
  return /* @__PURE__ */ jsxs(Fragment$1, { children: [!isSidebarLicensed && /* @__PURE__ */ jsx(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ jsx(CopilotChat, {
7699
7736
  welcomeScreen: CopilotSidebarView.WelcomeScreen,
@@ -9933,5 +9970,5 @@ function validateProps(props) {
9933
9970
  }
9934
9971
 
9935
9972
  //#endregion
9936
- export { CopilotKitProvider as $, IntelligenceIndicator as A, useInterrupt as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAttachmentRenderer as F, useAgent as G, useSuggestions as H, CopilotChatAssistantMessage_default as I, useRenderTool as J, useHumanInTheLoop as K, CopilotChatToolCallsView as L, CopilotChatSuggestionPill as M, CopilotChatReasoningMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatUserMessage_default as P, useRenderCustomMessages as Q, useAttachments as R, CopilotModalHeader as S, DefaultOpenIcon as T, useCapabilities as U, useConfigureSuggestions as V, UseAgentUpdate as W, useFrontendTool as X, useComponent as Y, useRenderActivityMessage as Z, WildcardToolCallRender as _, ThreadsProvider as a, MCPAppsActivityContentSchema as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, CopilotKitInspector as ct, shouldShowDevConsole as d, CopilotKitCoreReact as dt, useAgentContext as et, useToast as f, CopilotChatInput_default as ft, useCopilotContext as g, useCopilotChatConfiguration as gt, CopilotContext as h, CopilotChatConfigurationProvider as ht, ThreadsContext as i, useSandboxFunctions as it, CopilotChatSuggestionView as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, useRenderToolCall as lt, useCopilotMessagesContext as m, CopilotChatAudioRecorder as mt, defaultCopilotContextCategories as n, createA2UIMessageRenderer as nt, useThreads as o, MCPAppsActivityRenderer as ot, CopilotMessagesContext as p, AudioRecorderError as pt, useDefaultRenderTool as q, CoAgentStateRenderBridge as r, SandboxFunctionsContext as rt, CoAgentStateRendersContext as s, MCPAppsActivityType as st, CopilotKit as t, defineToolCallRenderer as tt, useAsyncCallback as u, useCopilotKit as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useThreads$1 as z };
9937
- //# sourceMappingURL=copilotkit-DjxXMYHG.mjs.map
9973
+ export { createA2UIMessageRenderer as $, IntelligenceIndicator as A, useInterrupt as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAttachmentRenderer as F, useAgent as G, useSuggestions as H, CopilotChatAssistantMessage_default as I, useFrontendTool as J, useHumanInTheLoop as K, CopilotChatToolCallsView as L, CopilotChatSuggestionPill as M, CopilotChatReasoningMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatUserMessage_default as P, useAgentContext as Q, useAttachments as R, CopilotModalHeader as S, DefaultOpenIcon as T, useCapabilities as U, useConfigureSuggestions as V, UseAgentUpdate as W, useRenderCustomMessages as X, useRenderActivityMessage as Y, CopilotKitProvider as Z, WildcardToolCallRender as _, ThreadsProvider as a, CopilotKitInspector as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, useRenderTool as ct, shouldShowDevConsole as d, CopilotKitCoreReact as dt, SandboxFunctionsContext as et, useToast as f, CopilotChatInput_default as ft, useCopilotContext as g, useCopilotChatConfiguration as gt, CopilotContext as h, CopilotChatConfigurationProvider as ht, ThreadsContext as i, MCPAppsActivityType as it, CopilotChatSuggestionView as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, defineToolCallRenderer as lt, useCopilotMessagesContext as m, CopilotChatAudioRecorder as mt, defaultCopilotContextCategories as n, MCPAppsActivityContentSchema as nt, useThreads as o, useRenderToolCall as ot, CopilotMessagesContext as p, AudioRecorderError as pt, useComponent as q, CoAgentStateRenderBridge as r, MCPAppsActivityRenderer as rt, CoAgentStateRendersContext as s, useDefaultRenderTool as st, CopilotKit as t, useSandboxFunctions as tt, useAsyncCallback as u, useCopilotKit as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useThreads$1 as z };
9974
+ //# sourceMappingURL=copilotkit-CC8DjOiC.mjs.map