@copilotkit/react-core 1.55.0-next.8 → 1.55.0

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 (94) hide show
  1. package/CHANGELOG.md +48 -5
  2. package/dist/{copilotkit-DNYSFuz5.mjs → copilotkit-BY5S1-0P.mjs} +2772 -858
  3. package/dist/copilotkit-BY5S1-0P.mjs.map +1 -0
  4. package/dist/{copilotkit-Dy5w3qEV.d.mts → copilotkit-BuhSUZHb.d.mts} +230 -17
  5. package/dist/copilotkit-BuhSUZHb.d.mts.map +1 -0
  6. package/dist/{copilotkit-B3Mb1yVE.cjs → copilotkit-Bz5-ImDl.cjs} +2776 -832
  7. package/dist/copilotkit-Bz5-ImDl.cjs.map +1 -0
  8. package/dist/{copilotkit-DBzgOMby.d.cts → copilotkit-dwDWYpya.d.cts} +230 -17
  9. package/dist/copilotkit-dwDWYpya.d.cts.map +1 -0
  10. package/dist/index.cjs +9 -4
  11. package/dist/index.cjs.map +1 -1
  12. package/dist/index.d.cts +1 -1
  13. package/dist/index.d.mts +1 -1
  14. package/dist/index.mjs +9 -4
  15. package/dist/index.mjs.map +1 -1
  16. package/dist/index.umd.js +1624 -396
  17. package/dist/index.umd.js.map +1 -1
  18. package/dist/v2/index.cjs +13 -1
  19. package/dist/v2/index.css +1 -1
  20. package/dist/v2/index.d.cts +3 -3
  21. package/dist/v2/index.d.mts +3 -3
  22. package/dist/v2/index.mjs +3 -2
  23. package/dist/v2/index.umd.js +2746 -790
  24. package/dist/v2/index.umd.js.map +1 -1
  25. package/package.json +62 -54
  26. package/scripts/scope-preflight.mjs +1 -2
  27. package/src/components/CopilotListeners.tsx +41 -8
  28. package/src/components/copilot-provider/__tests__/copilot-messages-key.test.tsx +92 -0
  29. package/src/components/copilot-provider/copilotkit-props.tsx +4 -2
  30. package/src/components/copilot-provider/copilotkit.tsx +3 -3
  31. package/src/components/toast/toast-provider.tsx +269 -194
  32. package/src/hooks/__tests__/use-copilot-chat-internal-connect.test.tsx +27 -16
  33. package/src/hooks/use-copilot-chat_internal.ts +15 -4
  34. package/src/v2/__tests__/A2UIMessageRenderer.test.tsx +86 -22
  35. package/src/v2/__tests__/utils/test-helpers.tsx +107 -7
  36. package/src/v2/a2ui/A2UICatalogContext.tsx +79 -0
  37. package/src/v2/a2ui/A2UIMessageRenderer.tsx +125 -37
  38. package/src/v2/a2ui/A2UIToolCallRenderer.tsx +290 -0
  39. package/src/v2/components/CopilotKitInspector.tsx +2 -0
  40. package/src/v2/components/OpenGenerativeUIRenderer.tsx +598 -0
  41. package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.tsx +665 -0
  42. package/src/v2/components/chat/CopilotChat.tsx +197 -52
  43. package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +17 -2
  44. package/src/v2/components/chat/CopilotChatAttachmentQueue.tsx +481 -0
  45. package/src/v2/components/chat/CopilotChatAttachmentRenderer.tsx +139 -0
  46. package/src/v2/components/chat/CopilotChatInput.tsx +146 -77
  47. package/src/v2/components/chat/CopilotChatMessageView.tsx +260 -151
  48. package/src/v2/components/chat/CopilotChatSuggestionView.tsx +1 -0
  49. package/src/v2/components/chat/CopilotChatUserMessage.tsx +54 -0
  50. package/src/v2/components/chat/CopilotChatView.tsx +179 -66
  51. package/src/v2/components/chat/__tests__/CopilotChat.attachments.test.tsx +168 -0
  52. package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +63 -2
  53. package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +544 -1
  54. package/src/v2/components/chat/__tests__/CopilotChatPerf.e2e.test.tsx +268 -0
  55. package/src/v2/components/chat/__tests__/CopilotChatPropsRerender.e2e.test.tsx +249 -0
  56. package/src/v2/components/chat/__tests__/CopilotChatToolRendering.e2e.test.tsx +5 -2
  57. package/src/v2/components/chat/__tests__/CopilotChatToolRerenders.e2e.test.tsx +5 -2
  58. package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +60 -3
  59. package/src/v2/components/chat/__tests__/copilot-chat-throttle.test.tsx +138 -0
  60. package/src/v2/components/chat/index.ts +9 -0
  61. package/src/v2/components/chat/scroll-element-context.ts +13 -0
  62. package/src/v2/hooks/__tests__/use-agent-context-timing.e2e.test.tsx +8 -0
  63. package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +327 -0
  64. package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +1003 -0
  65. package/src/v2/hooks/__tests__/use-agent.e2e.test.tsx +13 -2
  66. package/src/v2/hooks/__tests__/use-attachments.test.tsx +169 -0
  67. package/src/v2/hooks/__tests__/use-frontend-tool.e2e.test.tsx +23 -4
  68. package/src/v2/hooks/__tests__/use-threads.test.tsx +54 -0
  69. package/src/v2/hooks/index.ts +5 -0
  70. package/src/v2/hooks/use-agent.tsx +220 -15
  71. package/src/v2/hooks/use-attachments.tsx +269 -0
  72. package/src/v2/hooks/use-frontend-tool.tsx +5 -2
  73. package/src/v2/hooks/use-render-activity-message.tsx +9 -2
  74. package/src/v2/hooks/use-render-custom-messages.tsx +6 -1
  75. package/src/v2/hooks/use-threads.tsx +35 -15
  76. package/src/v2/index.ts +5 -1
  77. package/src/v2/lib/__tests__/processPartialHtml.test.ts +112 -0
  78. package/src/v2/lib/__tests__/slots.test.ts +56 -0
  79. package/src/v2/lib/processPartialHtml.ts +45 -0
  80. package/src/v2/lib/slots.tsx +42 -1
  81. package/src/v2/providers/CopilotChatConfigurationProvider.tsx +9 -3
  82. package/src/v2/providers/CopilotKitProvider.tsx +268 -32
  83. package/src/v2/providers/SandboxFunctionsContext.ts +10 -0
  84. package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.tsx +198 -0
  85. package/src/v2/providers/__tests__/CopilotKitProvider.test.tsx +71 -0
  86. package/src/v2/providers/index.ts +7 -0
  87. package/src/v2/styles/globals.css +2 -1
  88. package/src/v2/types/index.ts +1 -0
  89. package/src/v2/types/sandbox-function.ts +11 -0
  90. package/dist/copilotkit-B3Mb1yVE.cjs.map +0 -1
  91. package/dist/copilotkit-DBzgOMby.d.cts.map +0 -1
  92. package/dist/copilotkit-DNYSFuz5.mjs.map +0 -1
  93. package/dist/copilotkit-Dy5w3qEV.d.mts.map +0 -1
  94. package/src/v2/components/__tests__/license-warning-banner.test.tsx +0 -46
package/dist/index.umd.js CHANGED
@@ -1,10 +1,10 @@
1
1
  "use client";
2
2
 
3
3
  (function(global, factory) {
4
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@copilotkit/core'), require('@ag-ui/client'), require('@copilotkit/shared'), require('react/jsx-runtime'), require('zod'), require('@lit-labs/react'), require('@copilotkit/a2ui-renderer'), require('react-dom'), require('react-markdown'), require('@copilotkit/runtime-client-gql')) :
5
- typeof define === 'function' && define.amd ? define(['exports', 'react', '@copilotkit/core', '@ag-ui/client', '@copilotkit/shared', 'react/jsx-runtime', 'zod', '@lit-labs/react', '@copilotkit/a2ui-renderer', 'react-dom', 'react-markdown', '@copilotkit/runtime-client-gql'], factory) :
6
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitReactCore = {}), global.React,global.CopilotKitCore,global.AgUIClient,global.CopilotKitShared,global.ReactJsxRuntime,global.Zod,global._lit_labs_react,global.CopilotKitA2UIRenderer,global.ReactDOM,global.ReactMarkdown,global.CopilotKitRuntimeClientGQL));
7
- })(this, function(exports, react, _copilotkit_core, _ag_ui_client, _copilotkit_shared, react_jsx_runtime, zod, _lit_labs_react, _copilotkit_a2ui_renderer, react_dom, react_markdown, _copilotkit_runtime_client_gql) {
4
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('react'), require('@copilotkit/core'), require('@ag-ui/client'), require('tailwind-merge'), require('@copilotkit/shared'), require('react/jsx-runtime'), require('zod'), require('@lit-labs/react'), require('@copilotkit/a2ui-renderer'), require('zod-to-json-schema'), require('react-dom'), require('react-markdown'), require('@copilotkit/runtime-client-gql')) :
5
+ typeof define === 'function' && define.amd ? define(['exports', 'react', '@copilotkit/core', '@ag-ui/client', 'tailwind-merge', '@copilotkit/shared', 'react/jsx-runtime', 'zod', '@lit-labs/react', '@copilotkit/a2ui-renderer', 'zod-to-json-schema', 'react-dom', 'react-markdown', '@copilotkit/runtime-client-gql'], factory) :
6
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitReactCore = {}), global.React,global.CopilotKitCore,global.AgUIClient,global.tailwind_merge,global.CopilotKitShared,global.ReactJsxRuntime,global.Zod,global._lit_labs_react,global.CopilotKitA2UIRenderer,global.zod_to_json_schema,global.ReactDOM,global.ReactMarkdown,global.CopilotKitRuntimeClientGQL));
7
+ })(this, function(exports, react, _copilotkit_core, _ag_ui_client, tailwind_merge, _copilotkit_shared, react_jsx_runtime, zod, _lit_labs_react, _copilotkit_a2ui_renderer, zod_to_json_schema, react_dom, react_markdown, _copilotkit_runtime_client_gql) {
8
8
  Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
9
9
  //#region \0rolldown/runtime.js
10
10
  var __create = Object.create;
@@ -36,13 +36,98 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
36
36
  react = __toESM(react);
37
37
  react_markdown = __toESM(react_markdown);
38
38
 
39
+ //#region src/v2/lib/slots.tsx
40
+ /**
41
+ * Shallow equality comparison for objects.
42
+ */
43
+ function shallowEqual(obj1, obj2) {
44
+ const keys1 = Object.keys(obj1);
45
+ const keys2 = Object.keys(obj2);
46
+ if (keys1.length !== keys2.length) return false;
47
+ for (const key of keys1) if (obj1[key] !== obj2[key]) return false;
48
+ return true;
49
+ }
50
+ /**
51
+ * Returns true only for plain JS objects (`{}`), excluding arrays, Dates,
52
+ * class instances, and other exotic objects that happen to have typeof "object".
53
+ */
54
+ function isPlainObject(obj) {
55
+ return obj !== null && typeof obj === "object" && Object.prototype.toString.call(obj) === "[object Object]";
56
+ }
57
+ /**
58
+ * Returns the same reference as long as the value is shallowly equal to the
59
+ * previous render's value.
60
+ *
61
+ * - Identical references bail out immediately (O(1)).
62
+ * - Plain objects ({}) are shallow-compared key-by-key.
63
+ * - Arrays, Dates, class instances, functions, and primitives are compared by
64
+ * reference only — shallowEqual is never called on non-plain objects, which
65
+ * avoids incorrect equality for e.g. [1,2] vs [1,2] (different arrays).
66
+ *
67
+ * Typical use: stabilize inline slot props so MemoizedSlotWrapper's shallow
68
+ * equality check isn't defeated by a new object reference on every render.
69
+ */
70
+ function useShallowStableRef(value) {
71
+ const ref = (0, react.useRef)(value);
72
+ if (ref.current === value) return ref.current;
73
+ if (isPlainObject(ref.current) && isPlainObject(value)) {
74
+ if (shallowEqual(ref.current, value)) return ref.current;
75
+ }
76
+ ref.current = value;
77
+ return ref.current;
78
+ }
79
+ /**
80
+ * Check if a value is a React component type (function, class, forwardRef, memo, etc.)
81
+ */
82
+ function isReactComponentType(value) {
83
+ if (typeof value === "function") return true;
84
+ if (value && typeof value === "object" && "$$typeof" in value && !react.default.isValidElement(value)) return true;
85
+ return false;
86
+ }
87
+ /**
88
+ * Internal function to render a slot value as a React element (non-memoized).
89
+ */
90
+ function renderSlotElement(slot, DefaultComponent, props) {
91
+ if (typeof slot === "string") {
92
+ const existingClassName = props.className;
93
+ return react.default.createElement(DefaultComponent, {
94
+ ...props,
95
+ className: (0, tailwind_merge.twMerge)(existingClassName, slot)
96
+ });
97
+ }
98
+ if (isReactComponentType(slot)) return react.default.createElement(slot, props);
99
+ if (slot && typeof slot === "object" && !react.default.isValidElement(slot)) return react.default.createElement(DefaultComponent, {
100
+ ...props,
101
+ ...slot
102
+ });
103
+ return react.default.createElement(DefaultComponent, props);
104
+ }
105
+ /**
106
+ * Internal memoized wrapper component for renderSlot.
107
+ * Uses forwardRef to support ref forwarding.
108
+ */
109
+ const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function MemoizedSlotWrapper(props, ref) {
110
+ const { $slot, $component, ...rest } = props;
111
+ return renderSlotElement($slot, $component, ref !== null ? {
112
+ ...rest,
113
+ ref
114
+ } : rest);
115
+ }), (prev, next) => {
116
+ if (prev.$slot !== next.$slot) return false;
117
+ if (prev.$component !== next.$component) return false;
118
+ const { $slot: _ps, $component: _pc, ...prevRest } = prev;
119
+ const { $slot: _ns, $component: _nc, ...nextRest } = next;
120
+ return shallowEqual(prevRest, nextRest);
121
+ });
122
+
123
+ //#endregion
39
124
  //#region src/v2/providers/CopilotChatConfigurationProvider.tsx
40
125
  const CopilotChatDefaultLabels = {
41
126
  chatInputPlaceholder: "Type a message...",
42
127
  chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
43
128
  chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
44
129
  chatInputToolbarFinishTranscribeButtonLabel: "Finish",
45
- chatInputToolbarAddButtonLabel: "Add photos or files",
130
+ chatInputToolbarAddButtonLabel: "Add attachments",
46
131
  chatInputToolbarToolsButtonLabel: "Tools",
47
132
  assistantMessageToolbarCopyCodeLabel: "Copy",
48
133
  assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
@@ -63,14 +148,15 @@ react_markdown = __toESM(react_markdown);
63
148
  const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, isModalDefaultOpen }) => {
64
149
  var _ref, _parentConfig$isModal, _parentConfig$setModa;
65
150
  const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
151
+ const stableLabels = useShallowStableRef(labels);
66
152
  const mergedLabels = (0, react.useMemo)(() => {
67
153
  var _parentConfig$labels;
68
154
  return {
69
155
  ...CopilotChatDefaultLabels,
70
156
  ...(_parentConfig$labels = parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.labels) !== null && _parentConfig$labels !== void 0 ? _parentConfig$labels : {},
71
- ...labels !== null && labels !== void 0 ? labels : {}
157
+ ...stableLabels !== null && stableLabels !== void 0 ? stableLabels : {}
72
158
  };
73
- }, [labels, parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.labels]);
159
+ }, [stableLabels, parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.labels]);
74
160
  const resolvedAgentId = (_ref = agentId !== null && agentId !== void 0 ? agentId : parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.agentId) !== null && _ref !== void 0 ? _ref : _copilotkit_shared.DEFAULT_AGENT_ID;
75
161
  const resolvedThreadId = (0, react.useMemo)(() => {
76
162
  if (threadId) return threadId;
@@ -749,8 +835,417 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
749
835
  });
750
836
  };
751
837
 
838
+ //#endregion
839
+ //#region src/v2/providers/SandboxFunctionsContext.ts
840
+ const SandboxFunctionsContext = (0, react.createContext)([]);
841
+ function useSandboxFunctions() {
842
+ return (0, react.useContext)(SandboxFunctionsContext);
843
+ }
844
+
845
+ //#endregion
846
+ //#region src/v2/lib/processPartialHtml.ts
847
+ /**
848
+ * Extracts all complete `<style>` blocks from the raw HTML.
849
+ * Returns the concatenated style tags, suitable for injection into `<head>`.
850
+ */
851
+ function extractCompleteStyles(html) {
852
+ const matches = html.match(/<style\b[^>]*>[\s\S]*?<\/style>/gi);
853
+ return matches ? matches.join("") : "";
854
+ }
855
+ /**
856
+ * Processes raw accumulated HTML for safe preview via innerHTML injection.
857
+ * Pure function, no DOM dependencies.
858
+ *
859
+ * Pipeline (order matters):
860
+ * 1. Strip incomplete tag at end
861
+ * 2. Strip complete <style>, <script>, and <head> blocks
862
+ * 3. Strip incomplete <style>/<script>/<head> blocks
863
+ * 4. Strip incomplete HTML entities
864
+ * 5. Extract body content (or use full string if no <body>)
865
+ */
866
+ function processPartialHtml(html) {
867
+ let result = html;
868
+ result = result.replace(/<[^>]*$/, "");
869
+ result = result.replace(/<(style|script|head)\b[^>]*>[\s\S]*?<\/\1>/gi, "");
870
+ result = result.replace(/<(style|script|head)\b[^>]*>[\s\S]*$/gi, "");
871
+ result = result.replace(/&[a-zA-Z0-9#]*$/, "");
872
+ const bodyMatch = result.match(/<body[^>]*>([\s\S]*)/i);
873
+ if (bodyMatch) {
874
+ result = bodyMatch[1];
875
+ result = result.replace(/<\/body>[\s\S]*/i, "");
876
+ }
877
+ return result;
878
+ }
879
+
880
+ //#endregion
881
+ //#region src/v2/components/OpenGenerativeUIRenderer.tsx
882
+ const OpenGenerativeUIActivityType = "open-generative-ui";
883
+ const OpenGenerativeUIContentSchema = zod.z.object({
884
+ initialHeight: zod.z.number().optional(),
885
+ generating: zod.z.boolean().optional(),
886
+ css: zod.z.string().optional(),
887
+ cssComplete: zod.z.boolean().optional(),
888
+ html: zod.z.array(zod.z.string()).optional(),
889
+ htmlComplete: zod.z.boolean().optional(),
890
+ jsFunctions: zod.z.string().optional(),
891
+ jsFunctionsComplete: zod.z.boolean().optional(),
892
+ jsExpressions: zod.z.array(zod.z.string()).optional(),
893
+ jsExpressionsComplete: zod.z.boolean().optional()
894
+ });
895
+ /**
896
+ * Schema for the generateSandboxedUi tool call arguments.
897
+ * Used by the frontend tool renderer to display placeholder messages.
898
+ */
899
+ const GenerateSandboxedUiArgsSchema = zod.z.object({
900
+ initialHeight: zod.z.number().optional(),
901
+ placeholderMessages: zod.z.array(zod.z.string()).optional(),
902
+ css: zod.z.string().optional(),
903
+ html: zod.z.string().optional(),
904
+ jsFunctions: zod.z.string().optional(),
905
+ jsExpressions: zod.z.array(zod.z.string()).optional()
906
+ });
907
+ const THROTTLE_MS = 1e3;
908
+ /**
909
+ * Returns true when the inner component should re-render immediately
910
+ * (no throttle delay).
911
+ */
912
+ function shouldFlushImmediately(prev, next) {
913
+ var _next$jsExpressions$l, _next$jsExpressions, _prev$jsExpressions$l, _prev$jsExpressions, _next$html, _prev$html;
914
+ if (next.cssComplete && (!prev || !prev.cssComplete)) return true;
915
+ if (next.htmlComplete) return true;
916
+ if (next.generating === false) return true;
917
+ if (next.jsFunctions && (!prev || !prev.jsFunctions)) return true;
918
+ if (((_next$jsExpressions$l = (_next$jsExpressions = next.jsExpressions) === null || _next$jsExpressions === void 0 ? void 0 : _next$jsExpressions.length) !== null && _next$jsExpressions$l !== void 0 ? _next$jsExpressions$l : 0) > ((_prev$jsExpressions$l = prev === null || prev === void 0 || (_prev$jsExpressions = prev.jsExpressions) === null || _prev$jsExpressions === void 0 ? void 0 : _prev$jsExpressions.length) !== null && _prev$jsExpressions$l !== void 0 ? _prev$jsExpressions$l : 0)) return true;
919
+ if (((_next$html = next.html) === null || _next$html === void 0 ? void 0 : _next$html.length) && (!prev || !((_prev$html = prev.html) === null || _prev$html === void 0 ? void 0 : _prev$html.length))) return true;
920
+ return false;
921
+ }
922
+ /**
923
+ * Outer wrapper — absorbs every parent re-render but only forwards
924
+ * throttled content snapshots to the memoized inner component.
925
+ */
926
+ const OpenGenerativeUIActivityRenderer = function OpenGenerativeUIActivityRenderer({ content }) {
927
+ const latestContentRef = (0, react.useRef)(content);
928
+ latestContentRef.current = content;
929
+ const [throttledContent, setThrottledContent] = (0, react.useState)(content);
930
+ const throttledContentRef = (0, react.useRef)(throttledContent);
931
+ const timerRef = (0, react.useRef)(null);
932
+ if (throttledContentRef.current !== content) {
933
+ if (shouldFlushImmediately(throttledContentRef.current, content)) {
934
+ if (timerRef.current !== null) {
935
+ clearTimeout(timerRef.current);
936
+ timerRef.current = null;
937
+ }
938
+ throttledContentRef.current = content;
939
+ setThrottledContent(content);
940
+ }
941
+ }
942
+ const flush = (0, react.useCallback)(() => {
943
+ timerRef.current = null;
944
+ const latest = latestContentRef.current;
945
+ throttledContentRef.current = latest;
946
+ setThrottledContent(latest);
947
+ }, []);
948
+ (0, react.useEffect)(() => {
949
+ if (throttledContentRef.current === content) return;
950
+ if (timerRef.current === null) timerRef.current = setTimeout(flush, THROTTLE_MS);
951
+ }, [content, flush]);
952
+ (0, react.useEffect)(() => {
953
+ return () => {
954
+ if (timerRef.current !== null) clearTimeout(timerRef.current);
955
+ };
956
+ }, []);
957
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OpenGenerativeUIActivityRendererInner, { content: throttledContent });
958
+ };
959
+ function ensureHead(html) {
960
+ if (/<head[\s>]/i.test(html)) return html;
961
+ return `<head></head>${html}`;
962
+ }
963
+ function injectCssIntoHtml(html, css) {
964
+ const headCloseIdx = html.indexOf("</head>");
965
+ if (headCloseIdx !== -1) return html.slice(0, headCloseIdx) + `<style>${css}</style>` + html.slice(headCloseIdx);
966
+ return `<head><style>${css}</style></head>${html}`;
967
+ }
968
+ const OpenGenerativeUIActivityRendererInner = react.default.memo(function OpenGenerativeUIActivityRendererInner({ content }) {
969
+ var _content$initialHeigh, _content$html, _content$html2, _content$jsExpression;
970
+ const initialHeight = (_content$initialHeigh = content.initialHeight) !== null && _content$initialHeigh !== void 0 ? _content$initialHeigh : 200;
971
+ const [autoHeight, setAutoHeight] = (0, react.useState)(null);
972
+ const sandboxFunctions = useSandboxFunctions();
973
+ const localApi = (0, react.useMemo)(() => {
974
+ const api = {};
975
+ for (const fn of sandboxFunctions) api[fn.name] = fn.handler;
976
+ return api;
977
+ }, [sandboxFunctions]);
978
+ const fullHtml = content.htmlComplete && ((_content$html = content.html) === null || _content$html === void 0 ? void 0 : _content$html.length) ? content.html.join("") : void 0;
979
+ const css = content.cssComplete ? content.css : void 0;
980
+ const cssReady = !!content.cssComplete;
981
+ const partialHtml = !content.htmlComplete && ((_content$html2 = content.html) === null || _content$html2 === void 0 ? void 0 : _content$html2.length) ? content.html.join("") : void 0;
982
+ const previewBody = partialHtml ? processPartialHtml(partialHtml) : void 0;
983
+ const previewStyles = partialHtml ? extractCompleteStyles(partialHtml) : "";
984
+ const hasPreview = cssReady && !!(previewBody === null || previewBody === void 0 ? void 0 : previewBody.trim());
985
+ const hasVisibleSandbox = !!fullHtml || hasPreview;
986
+ const containerRef = (0, react.useRef)(null);
987
+ const sandboxRef = (0, react.useRef)(null);
988
+ const previewSandboxRef = (0, react.useRef)(null);
989
+ const previewReadyRef = (0, react.useRef)(false);
990
+ const sandboxReadyRef = (0, react.useRef)(false);
991
+ const executedIndexRef = (0, react.useRef)(0);
992
+ const pendingQueueRef = (0, react.useRef)([]);
993
+ const jsFunctionsInjectedRef = (0, react.useRef)(false);
994
+ (0, react.useEffect)(() => {
995
+ const container = containerRef.current;
996
+ if (!container || fullHtml || !hasPreview || previewSandboxRef.current) return;
997
+ let cancelled = false;
998
+ import("@jetbrains/websandbox").then((mod) => {
999
+ var _mod$default$default, _mod$default;
1000
+ if (cancelled) return;
1001
+ const sandbox = ((_mod$default$default = (_mod$default = mod.default) === null || _mod$default === void 0 ? void 0 : _mod$default.default) !== null && _mod$default$default !== void 0 ? _mod$default$default : mod.default).create({}, {
1002
+ frameContainer: container,
1003
+ frameContent: "<head></head><body></body>",
1004
+ allowAdditionalAttributes: ""
1005
+ });
1006
+ previewSandboxRef.current = sandbox;
1007
+ sandbox.iframe.style.width = "100%";
1008
+ sandbox.iframe.style.height = "100%";
1009
+ sandbox.iframe.style.border = "none";
1010
+ sandbox.iframe.style.backgroundColor = "transparent";
1011
+ sandbox.promise.then(() => {
1012
+ if (cancelled) return;
1013
+ previewReadyRef.current = true;
1014
+ sandbox.run(`
1015
+ var s = document.createElement('style');
1016
+ s.textContent = 'html, body { overflow: hidden !important; }';
1017
+ document.head.appendChild(s);
1018
+ `);
1019
+ const headParts = [];
1020
+ if (css) headParts.push(`<style>${css}</style>`);
1021
+ if (previewStyles) headParts.push(previewStyles);
1022
+ if (headParts.length) sandbox.run(`document.head.innerHTML = ${JSON.stringify(headParts.join(""))}`);
1023
+ if (previewBody) sandbox.run(`document.body.innerHTML = ${JSON.stringify(previewBody)}`);
1024
+ });
1025
+ }).catch((err) => {
1026
+ console.error("[OpenGenerativeUI] Failed to load sandbox module:", err);
1027
+ });
1028
+ return () => {
1029
+ cancelled = true;
1030
+ };
1031
+ }, [hasPreview, fullHtml]);
1032
+ (0, react.useEffect)(() => {
1033
+ if (!previewSandboxRef.current || !previewReadyRef.current) return;
1034
+ const headParts = [];
1035
+ if (css) headParts.push(`<style>${css}</style>`);
1036
+ if (previewStyles) headParts.push(previewStyles);
1037
+ if (headParts.length) previewSandboxRef.current.run(`document.head.innerHTML = ${JSON.stringify(headParts.join(""))}`);
1038
+ if (!previewBody) return;
1039
+ previewSandboxRef.current.run(`document.body.innerHTML = ${JSON.stringify(previewBody)}`);
1040
+ }, [
1041
+ previewBody,
1042
+ previewStyles,
1043
+ css
1044
+ ]);
1045
+ (0, react.useEffect)(() => {
1046
+ const container = containerRef.current;
1047
+ if (!container || !fullHtml) return;
1048
+ if (previewSandboxRef.current) {
1049
+ previewSandboxRef.current.destroy();
1050
+ previewSandboxRef.current = null;
1051
+ previewReadyRef.current = false;
1052
+ }
1053
+ let cancelled = false;
1054
+ executedIndexRef.current = 0;
1055
+ jsFunctionsInjectedRef.current = false;
1056
+ sandboxReadyRef.current = false;
1057
+ pendingQueueRef.current = [];
1058
+ const htmlContent = css ? injectCssIntoHtml(fullHtml, css) : fullHtml;
1059
+ import("@jetbrains/websandbox").then((mod) => {
1060
+ var _mod$default$default2, _mod$default2;
1061
+ if (cancelled) return;
1062
+ const sandbox = ((_mod$default$default2 = (_mod$default2 = mod.default) === null || _mod$default2 === void 0 ? void 0 : _mod$default2.default) !== null && _mod$default$default2 !== void 0 ? _mod$default$default2 : mod.default).create(localApi, {
1063
+ frameContainer: container,
1064
+ frameContent: ensureHead(htmlContent),
1065
+ allowAdditionalAttributes: ""
1066
+ });
1067
+ sandboxRef.current = sandbox;
1068
+ sandbox.iframe.style.width = "100%";
1069
+ sandbox.iframe.style.height = "100%";
1070
+ sandbox.iframe.style.border = "none";
1071
+ sandbox.iframe.style.backgroundColor = "transparent";
1072
+ sandbox.promise.then(() => {
1073
+ if (cancelled) return;
1074
+ sandboxReadyRef.current = true;
1075
+ sandbox.run(`
1076
+ var s = document.createElement('style');
1077
+ s.textContent = 'html, body { overflow: hidden !important; }';
1078
+ document.head.appendChild(s);
1079
+ `);
1080
+ const queue = pendingQueueRef.current;
1081
+ pendingQueueRef.current = [];
1082
+ for (const code of queue) sandbox.run(code);
1083
+ });
1084
+ }).catch((err) => {
1085
+ console.error("[OpenGenerativeUI] Failed to load sandbox module:", err);
1086
+ });
1087
+ return () => {
1088
+ cancelled = true;
1089
+ if (previewSandboxRef.current) {
1090
+ previewSandboxRef.current.destroy();
1091
+ previewSandboxRef.current = null;
1092
+ previewReadyRef.current = false;
1093
+ }
1094
+ if (sandboxRef.current) {
1095
+ sandboxRef.current.destroy();
1096
+ sandboxRef.current = null;
1097
+ }
1098
+ sandboxReadyRef.current = false;
1099
+ setAutoHeight(null);
1100
+ };
1101
+ }, [
1102
+ fullHtml,
1103
+ css,
1104
+ localApi
1105
+ ]);
1106
+ (0, react.useEffect)(() => {
1107
+ if (!content.jsFunctions || jsFunctionsInjectedRef.current) return;
1108
+ jsFunctionsInjectedRef.current = true;
1109
+ const sandbox = sandboxRef.current;
1110
+ if (sandboxReadyRef.current && sandbox) sandbox.run(content.jsFunctions);
1111
+ else pendingQueueRef.current.push(content.jsFunctions);
1112
+ }, [content.jsFunctions]);
1113
+ (0, react.useEffect)(() => {
1114
+ const expressions = content.jsExpressions;
1115
+ if (!expressions || expressions.length === 0) return;
1116
+ const startIndex = executedIndexRef.current;
1117
+ if (startIndex >= expressions.length) return;
1118
+ const newExprs = expressions.slice(startIndex);
1119
+ executedIndexRef.current = expressions.length;
1120
+ const sandbox = sandboxRef.current;
1121
+ if (sandboxReadyRef.current && sandbox) (async () => {
1122
+ for (const expr of newExprs) await sandbox.run(expr);
1123
+ })();
1124
+ else pendingQueueRef.current.push(...newExprs);
1125
+ }, [(_content$jsExpression = content.jsExpressions) === null || _content$jsExpression === void 0 ? void 0 : _content$jsExpression.length]);
1126
+ const generationDone = content.generating === false;
1127
+ (0, react.useEffect)(() => {
1128
+ const sandbox = sandboxRef.current;
1129
+ if (!generationDone || !sandbox) return;
1130
+ let handled = false;
1131
+ const onMessage = (e) => {
1132
+ var _e$data;
1133
+ if (handled) return;
1134
+ if (e.source === sandbox.iframe.contentWindow && ((_e$data = e.data) === null || _e$data === void 0 ? void 0 : _e$data.type) === "__ck_resize") {
1135
+ handled = true;
1136
+ setAutoHeight(e.data.height);
1137
+ window.removeEventListener("message", onMessage);
1138
+ }
1139
+ };
1140
+ window.addEventListener("message", onMessage);
1141
+ const measureOnce = `
1142
+ (function() {
1143
+ var s = document.createElement('style');
1144
+ s.textContent = 'body { height: auto !important; min-height: 0 !important; }';
1145
+ document.head.appendChild(s);
1146
+ var h = document.body.scrollHeight;
1147
+ var cs = getComputedStyle(document.body);
1148
+ h += parseFloat(cs.marginTop) || 0;
1149
+ h += parseFloat(cs.marginBottom) || 0;
1150
+ s.remove();
1151
+ parent.postMessage({ type: "__ck_resize", height: Math.ceil(h) }, "*");
1152
+ })();
1153
+ `;
1154
+ if (sandboxReadyRef.current) sandbox.run(measureOnce);
1155
+ else pendingQueueRef.current.push(measureOnce);
1156
+ return () => {
1157
+ window.removeEventListener("message", onMessage);
1158
+ };
1159
+ }, [generationDone]);
1160
+ const height = autoHeight !== null && autoHeight !== void 0 ? autoHeight : initialHeight;
1161
+ const isGenerating = content.generating !== false;
1162
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1163
+ ref: containerRef,
1164
+ style: {
1165
+ position: "relative",
1166
+ width: "100%",
1167
+ height: `${height}px`,
1168
+ borderRadius: "8px",
1169
+ backgroundColor: hasVisibleSandbox ? "transparent" : "#f5f5f5",
1170
+ border: hasVisibleSandbox ? "none" : "1px solid #e0e0e0",
1171
+ display: hasVisibleSandbox ? "block" : "flex",
1172
+ alignItems: hasVisibleSandbox ? void 0 : "center",
1173
+ justifyContent: hasVisibleSandbox ? void 0 : "center",
1174
+ overflow: "hidden"
1175
+ },
1176
+ children: isGenerating && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1177
+ style: {
1178
+ position: "absolute",
1179
+ inset: 0,
1180
+ zIndex: 10,
1181
+ pointerEvents: "all",
1182
+ backgroundColor: "rgba(255, 255, 255, 0.5)",
1183
+ display: "flex",
1184
+ alignItems: "center",
1185
+ justifyContent: "center"
1186
+ },
1187
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
1188
+ width: "48",
1189
+ height: "48",
1190
+ viewBox: "0 0 24 24",
1191
+ fill: "none",
1192
+ style: { animation: "ck-spin 1s linear infinite" },
1193
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
1194
+ cx: "12",
1195
+ cy: "12",
1196
+ r: "10",
1197
+ stroke: "#e0e0e0",
1198
+ strokeWidth: "3"
1199
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
1200
+ d: "M12 2a10 10 0 0 1 10 10",
1201
+ stroke: "#999",
1202
+ strokeWidth: "3",
1203
+ strokeLinecap: "round"
1204
+ })]
1205
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `@keyframes ck-spin { to { transform: rotate(360deg) } }` })]
1206
+ })
1207
+ });
1208
+ }, (prev, next) => prev.content === next.content);
1209
+ /**
1210
+ * Frontend tool renderer for generateSandboxedUi.
1211
+ * Displays placeholder messages while the UI is being generated.
1212
+ */
1213
+ const OpenGenerativeUIToolRenderer = function OpenGenerativeUIToolRenderer(props) {
1214
+ var _messages$visibleMess;
1215
+ const [visibleMessageIndex, setVisibleMessageIndex] = (0, react.useState)(0);
1216
+ const prevMessageCountRef = (0, react.useRef)(0);
1217
+ const messages = props.args.placeholderMessages;
1218
+ (0, react.useEffect)(() => {
1219
+ if (!messages || messages.length === 0) return;
1220
+ if (messages.length !== prevMessageCountRef.current) {
1221
+ prevMessageCountRef.current = messages.length;
1222
+ setVisibleMessageIndex(messages.length - 1);
1223
+ }
1224
+ if (props.status === _copilotkit_core.ToolCallStatus.Complete) return;
1225
+ const timer = setInterval(() => {
1226
+ setVisibleMessageIndex((i) => (i + 1) % messages.length);
1227
+ }, 5e3);
1228
+ return () => clearInterval(timer);
1229
+ }, [messages === null || messages === void 0 ? void 0 : messages.length, props.status]);
1230
+ if (props.status === _copilotkit_core.ToolCallStatus.Complete) return null;
1231
+ if (!messages || messages.length === 0) return null;
1232
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1233
+ style: {
1234
+ padding: "8px 12px",
1235
+ color: "#999",
1236
+ fontSize: "14px"
1237
+ },
1238
+ children: (_messages$visibleMess = messages[visibleMessageIndex]) !== null && _messages$visibleMess !== void 0 ? _messages$visibleMess : messages[0]
1239
+ });
1240
+ };
1241
+
752
1242
  //#endregion
753
1243
  //#region src/v2/a2ui/A2UIMessageRenderer.tsx
1244
+ /**
1245
+ * The container key used to wrap A2UI operations for explicit detection.
1246
+ * Must match A2UI_OPERATIONS_KEY in @ag-ui/a2ui-middleware and copilotkit.a2ui (Python).
1247
+ */
1248
+ const A2UI_OPERATIONS_KEY = "a2ui_operations";
754
1249
  let initialized = false;
755
1250
  function ensureInitialized() {
756
1251
  if (!initialized) {
@@ -760,25 +1255,23 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
760
1255
  }
761
1256
  }
762
1257
  function createA2UIMessageRenderer(options) {
763
- const { theme } = options;
1258
+ const { theme, catalog, loadingComponent } = options;
764
1259
  return {
765
1260
  activityType: "a2ui-surface",
766
1261
  content: zod.z.any(),
767
1262
  render: ({ content, agent }) => {
768
1263
  ensureInitialized();
769
1264
  const [operations, setOperations] = (0, react.useState)([]);
770
- const lastSignatureRef = (0, react.useRef)(null);
771
1265
  const { copilotkit } = useCopilotKit();
1266
+ const lastContentRef = (0, react.useRef)(null);
772
1267
  (0, react.useEffect)(() => {
773
- if (!content || !Array.isArray(content.operations)) {
774
- lastSignatureRef.current = null;
1268
+ if (content === lastContentRef.current) return;
1269
+ lastContentRef.current = content;
1270
+ const incoming = content === null || content === void 0 ? void 0 : content[A2UI_OPERATIONS_KEY];
1271
+ if (!content || !Array.isArray(incoming)) {
775
1272
  setOperations([]);
776
1273
  return;
777
1274
  }
778
- const incoming = content.operations;
779
- const signature = stringifyOperations(incoming);
780
- if (signature && signature === lastSignatureRef.current) return;
781
- lastSignatureRef.current = signature;
782
1275
  setOperations(incoming);
783
1276
  }, [content]);
784
1277
  const groupedOperations = (0, react.useMemo)(() => {
@@ -791,7 +1284,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
791
1284
  }
792
1285
  return groups;
793
1286
  }, [operations]);
794
- if (!groupedOperations.size) return null;
1287
+ if (!groupedOperations.size) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(loadingComponent !== null && loadingComponent !== void 0 ? loadingComponent : DefaultA2UILoading, {});
795
1288
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
796
1289
  className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
797
1290
  children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactSurfaceHost, {
@@ -799,7 +1292,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
799
1292
  operations: ops,
800
1293
  theme,
801
1294
  agent,
802
- copilotkit
1295
+ copilotkit,
1296
+ catalog
803
1297
  }, surfaceId))
804
1298
  });
805
1299
  }
@@ -809,15 +1303,15 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
809
1303
  * Renders a single A2UI surface using the React renderer.
810
1304
  * Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
811
1305
  */
812
- function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
1306
+ function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog }) {
813
1307
  return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
814
1308
  className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
815
1309
  children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
816
1310
  onAction: (0, react.useCallback)(async (message) => {
817
1311
  if (!agent) return;
1312
+ message.userAction;
818
1313
  try {
819
1314
  var _copilotkit$propertie;
820
- console.info("[A2UI] Action dispatched", message.userAction);
821
1315
  copilotkit.setProperties({
822
1316
  ...(_copilotkit$propertie = copilotkit.properties) !== null && _copilotkit$propertie !== void 0 ? _copilotkit$propertie : {},
823
1317
  a2uiAction: message
@@ -831,47 +1325,502 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
831
1325
  }
832
1326
  }, [agent, copilotkit]),
833
1327
  theme,
1328
+ catalog,
834
1329
  children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceMessageProcessor, {
835
1330
  surfaceId,
836
1331
  operations
837
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_a2ui_renderer.A2UIRenderer, {
838
- surfaceId,
839
- className: "cpk:flex cpk:flex-1"
840
- })]
1332
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UISurfaceOrError, { surfaceId })]
841
1333
  })
842
1334
  });
843
1335
  }
844
1336
  /**
1337
+ * Renders the A2UI surface, or an error message if processing failed.
1338
+ * Must be a child of A2UIProvider to access the error state.
1339
+ */
1340
+ function A2UISurfaceOrError({ surfaceId }) {
1341
+ const error = (0, _copilotkit_a2ui_renderer.useA2UIError)();
1342
+ if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1343
+ className: "cpk:rounded-lg cpk:border cpk:border-red-200 cpk:bg-red-50 cpk:p-3 cpk:text-sm cpk:text-red-700",
1344
+ children: ["A2UI render error: ", error]
1345
+ });
1346
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_a2ui_renderer.A2UIRenderer, {
1347
+ surfaceId,
1348
+ className: "cpk:flex cpk:flex-1"
1349
+ });
1350
+ }
1351
+ /**
845
1352
  * Processes A2UI operations into the provider's message processor.
846
1353
  * Must be a child of A2UIProvider to access the actions context.
847
1354
  */
848
1355
  function SurfaceMessageProcessor({ surfaceId, operations }) {
849
- const { processMessages } = (0, _copilotkit_a2ui_renderer.useA2UIActions)();
850
- const lastProcessedRef = (0, react.useRef)("");
1356
+ const { processMessages, getSurface } = (0, _copilotkit_a2ui_renderer.useA2UIActions)();
1357
+ const lastHashRef = (0, react.useRef)("");
851
1358
  (0, react.useEffect)(() => {
852
- const key = `${surfaceId}-${JSON.stringify(operations)}`;
853
- if (key === lastProcessedRef.current) return;
854
- lastProcessedRef.current = key;
855
- processMessages(operations);
1359
+ const hash = JSON.stringify(operations);
1360
+ if (hash === lastHashRef.current) return;
1361
+ lastHashRef.current = hash;
1362
+ processMessages(getSurface(surfaceId) ? operations.filter((op) => !(op === null || op === void 0 ? void 0 : op.createSurface)) : operations);
856
1363
  }, [
857
1364
  processMessages,
1365
+ getSurface,
858
1366
  surfaceId,
859
1367
  operations
860
1368
  ]);
861
1369
  return null;
862
1370
  }
1371
+ /**
1372
+ * Default loading component shown while an A2UI surface is generating.
1373
+ * Displays an animated shimmer skeleton.
1374
+ */
1375
+ function DefaultA2UILoading() {
1376
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1377
+ className: "cpk:flex cpk:flex-col cpk:gap-3 cpk:rounded-xl cpk:border cpk:border-gray-100 cpk:bg-gray-50/50 cpk:p-5",
1378
+ style: { minHeight: 120 },
1379
+ children: [
1380
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1381
+ className: "cpk:flex cpk:items-center cpk:gap-2",
1382
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1383
+ className: "cpk:h-3 cpk:w-3 cpk:rounded-full cpk:bg-gray-200",
1384
+ style: { animation: "cpk-a2ui-pulse 1.5s ease-in-out infinite" }
1385
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1386
+ className: "cpk:text-xs cpk:font-medium cpk:text-gray-400",
1387
+ children: "Generating UI..."
1388
+ })]
1389
+ }),
1390
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1391
+ className: "cpk:flex cpk:flex-col cpk:gap-2",
1392
+ children: [
1393
+ .8,
1394
+ .6,
1395
+ .4
1396
+ ].map((width, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1397
+ className: "cpk:h-3 cpk:rounded cpk:bg-gray-200/70",
1398
+ style: {
1399
+ width: `${width * 100}%`,
1400
+ animation: `cpk-a2ui-pulse 1.5s ease-in-out ${i * .15}s infinite`
1401
+ }
1402
+ }, i))
1403
+ }),
1404
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
1405
+ @keyframes cpk-a2ui-pulse {
1406
+ 0%, 100% { opacity: 0.4; }
1407
+ 50% { opacity: 1; }
1408
+ }
1409
+ ` })
1410
+ ]
1411
+ });
1412
+ }
863
1413
  function getOperationSurfaceId(operation) {
864
- var _ref, _ref2, _ref3, _operation$beginRende, _operation$beginRende2, _operation$surfaceUpd, _operation$dataModelU, _operation$deleteSurf;
1414
+ var _ref, _ref2, _ref3, _operation$createSurf, _operation$createSurf2, _operation$updateComp, _operation$updateData, _operation$deleteSurf;
865
1415
  if (!operation || typeof operation !== "object") return null;
866
1416
  if (typeof operation.surfaceId === "string") return operation.surfaceId;
867
- return (_ref = (_ref2 = (_ref3 = (_operation$beginRende = operation === null || operation === void 0 || (_operation$beginRende2 = operation.beginRendering) === null || _operation$beginRende2 === void 0 ? void 0 : _operation$beginRende2.surfaceId) !== null && _operation$beginRende !== void 0 ? _operation$beginRende : operation === null || operation === void 0 || (_operation$surfaceUpd = operation.surfaceUpdate) === null || _operation$surfaceUpd === void 0 ? void 0 : _operation$surfaceUpd.surfaceId) !== null && _ref3 !== void 0 ? _ref3 : operation === null || operation === void 0 || (_operation$dataModelU = operation.dataModelUpdate) === null || _operation$dataModelU === void 0 ? void 0 : _operation$dataModelU.surfaceId) !== null && _ref2 !== void 0 ? _ref2 : operation === null || operation === void 0 || (_operation$deleteSurf = operation.deleteSurface) === null || _operation$deleteSurf === void 0 ? void 0 : _operation$deleteSurf.surfaceId) !== null && _ref !== void 0 ? _ref : null;
1417
+ return (_ref = (_ref2 = (_ref3 = (_operation$createSurf = operation === null || operation === void 0 || (_operation$createSurf2 = operation.createSurface) === null || _operation$createSurf2 === void 0 ? void 0 : _operation$createSurf2.surfaceId) !== null && _operation$createSurf !== void 0 ? _operation$createSurf : operation === null || operation === void 0 || (_operation$updateComp = operation.updateComponents) === null || _operation$updateComp === void 0 ? void 0 : _operation$updateComp.surfaceId) !== null && _ref3 !== void 0 ? _ref3 : operation === null || operation === void 0 || (_operation$updateData = operation.updateDataModel) === null || _operation$updateData === void 0 ? void 0 : _operation$updateData.surfaceId) !== null && _ref2 !== void 0 ? _ref2 : operation === null || operation === void 0 || (_operation$deleteSurf = operation.deleteSurface) === null || _operation$deleteSurf === void 0 ? void 0 : _operation$deleteSurf.surfaceId) !== null && _ref !== void 0 ? _ref : null;
868
1418
  }
869
- function stringifyOperations(ops) {
870
- try {
871
- return JSON.stringify(ops);
872
- } catch (error) {
873
- return null;
1419
+
1420
+ //#endregion
1421
+ //#region src/v2/types/defineToolCallRenderer.ts
1422
+ function defineToolCallRenderer(def) {
1423
+ const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
1424
+ return {
1425
+ name: def.name,
1426
+ args: argsSchema,
1427
+ render: def.render,
1428
+ ...def.agentId ? { agentId: def.agentId } : {}
1429
+ };
1430
+ }
1431
+
1432
+ //#endregion
1433
+ //#region src/v2/a2ui/A2UIToolCallRenderer.tsx
1434
+ /**
1435
+ * Tool name used by the dynamic A2UI generation secondary LLM.
1436
+ * This renderer is auto-registered when A2UI is enabled.
1437
+ */
1438
+ const RENDER_A2UI_TOOL_NAME = "render_a2ui";
1439
+ /**
1440
+ * Built-in progress indicator for dynamic A2UI generation.
1441
+ * Shows a skeleton wireframe that progressively reveals as tokens stream in.
1442
+ *
1443
+ * Registered automatically when A2UI is enabled. Users can override by
1444
+ * providing their own `useRenderTool({ name: "render_a2ui", ... })`.
1445
+ */
1446
+ function A2UIProgressIndicator({ parameters }) {
1447
+ const lastRef = (0, react.useRef)({
1448
+ time: 0,
1449
+ tokens: 0
1450
+ });
1451
+ const now = Date.now();
1452
+ let { tokens } = lastRef.current;
1453
+ if (now - lastRef.current.time > 200) {
1454
+ const chars = JSON.stringify(parameters !== null && parameters !== void 0 ? parameters : {}).length;
1455
+ tokens = Math.round(chars / 4);
1456
+ lastRef.current = {
1457
+ time: now,
1458
+ tokens
1459
+ };
874
1460
  }
1461
+ const phase = tokens < 50 ? 0 : tokens < 200 ? 1 : tokens < 400 ? 2 : 3;
1462
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1463
+ style: {
1464
+ margin: "12px 0",
1465
+ maxWidth: 320
1466
+ },
1467
+ children: [
1468
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1469
+ style: {
1470
+ position: "relative",
1471
+ overflow: "hidden",
1472
+ borderRadius: 12,
1473
+ border: "1px solid rgba(228,228,231,0.8)",
1474
+ backgroundColor: "#fff",
1475
+ boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
1476
+ padding: "16px 18px 14px"
1477
+ },
1478
+ children: [
1479
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1480
+ style: {
1481
+ display: "flex",
1482
+ alignItems: "center",
1483
+ gap: 8,
1484
+ marginBottom: 12
1485
+ },
1486
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1487
+ style: {
1488
+ display: "flex",
1489
+ gap: 4
1490
+ },
1491
+ children: [
1492
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
1493
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
1494
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {})
1495
+ ]
1496
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1497
+ w: 64,
1498
+ h: 6,
1499
+ bg: "#e4e4e7",
1500
+ opacity: phase >= 1 ? 1 : .4,
1501
+ transition: "opacity 0.5s"
1502
+ })]
1503
+ }),
1504
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1505
+ style: {
1506
+ display: "grid",
1507
+ gap: 7
1508
+ },
1509
+ children: [
1510
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1511
+ show: phase >= 0,
1512
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1513
+ w: 36,
1514
+ h: 7,
1515
+ bg: "rgba(147,197,253,0.7)",
1516
+ anim: 0
1517
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1518
+ w: 80,
1519
+ h: 7,
1520
+ bg: "rgba(219,234,254,0.8)",
1521
+ anim: .2
1522
+ })]
1523
+ }),
1524
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1525
+ show: phase >= 0,
1526
+ delay: .1,
1527
+ children: [
1528
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spacer, {}),
1529
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
1530
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1531
+ w: 100,
1532
+ h: 7,
1533
+ bg: "rgba(24,24,27,0.2)",
1534
+ anim: .3
1535
+ })
1536
+ ]
1537
+ }),
1538
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1539
+ show: phase >= 1,
1540
+ delay: .15,
1541
+ children: [
1542
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spacer, {}),
1543
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1544
+ w: 48,
1545
+ h: 7,
1546
+ bg: "rgba(24,24,27,0.15)",
1547
+ anim: .1
1548
+ }),
1549
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1550
+ w: 40,
1551
+ h: 7,
1552
+ bg: "rgba(153,246,228,0.6)",
1553
+ anim: .5
1554
+ }),
1555
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1556
+ w: 56,
1557
+ h: 7,
1558
+ bg: "rgba(147,197,253,0.6)",
1559
+ anim: .3
1560
+ })
1561
+ ]
1562
+ }),
1563
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1564
+ show: phase >= 1,
1565
+ delay: .2,
1566
+ children: [
1567
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spacer, {}),
1568
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
1569
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1570
+ w: 60,
1571
+ h: 7,
1572
+ bg: "rgba(24,24,27,0.15)",
1573
+ anim: .4
1574
+ })
1575
+ ]
1576
+ }),
1577
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1578
+ show: phase >= 2,
1579
+ delay: .25,
1580
+ children: [
1581
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1582
+ w: 40,
1583
+ h: 7,
1584
+ bg: "rgba(153,246,228,0.5)",
1585
+ anim: .2
1586
+ }),
1587
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
1588
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1589
+ w: 48,
1590
+ h: 7,
1591
+ bg: "rgba(24,24,27,0.15)",
1592
+ anim: .6
1593
+ }),
1594
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1595
+ w: 64,
1596
+ h: 7,
1597
+ bg: "rgba(147,197,253,0.5)",
1598
+ anim: .1
1599
+ })
1600
+ ]
1601
+ }),
1602
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1603
+ show: phase >= 2,
1604
+ delay: .3,
1605
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1606
+ w: 36,
1607
+ h: 7,
1608
+ bg: "rgba(147,197,253,0.6)",
1609
+ anim: .5
1610
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1611
+ w: 36,
1612
+ h: 7,
1613
+ bg: "rgba(24,24,27,0.12)",
1614
+ anim: .7
1615
+ })]
1616
+ }),
1617
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
1618
+ show: phase >= 3,
1619
+ delay: .35,
1620
+ children: [
1621
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
1622
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1623
+ w: 44,
1624
+ h: 7,
1625
+ bg: "rgba(24,24,27,0.18)",
1626
+ anim: .3
1627
+ }),
1628
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
1629
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1630
+ w: 56,
1631
+ h: 7,
1632
+ bg: "rgba(153,246,228,0.5)",
1633
+ anim: .8
1634
+ }),
1635
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
1636
+ w: 48,
1637
+ h: 7,
1638
+ bg: "rgba(147,197,253,0.5)",
1639
+ anim: .4
1640
+ })
1641
+ ]
1642
+ })
1643
+ ]
1644
+ }),
1645
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
1646
+ pointerEvents: "none",
1647
+ position: "absolute",
1648
+ inset: 0,
1649
+ background: "linear-gradient(105deg, transparent 0%, transparent 40%, rgba(255,255,255,0.6) 50%, transparent 60%, transparent 100%)",
1650
+ backgroundSize: "250% 100%",
1651
+ animation: "cpk-a2ui-sweep 3s ease-in-out infinite"
1652
+ } })
1653
+ ]
1654
+ }),
1655
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
1656
+ style: {
1657
+ display: "flex",
1658
+ alignItems: "center",
1659
+ justifyContent: "center",
1660
+ gap: 8,
1661
+ marginTop: 8
1662
+ },
1663
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
1664
+ style: {
1665
+ fontSize: 12,
1666
+ color: "#a1a1aa",
1667
+ letterSpacing: "0.025em"
1668
+ },
1669
+ children: "Building interface"
1670
+ }), tokens > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
1671
+ style: {
1672
+ fontSize: 11,
1673
+ color: "#d4d4d8",
1674
+ fontVariantNumeric: "tabular-nums"
1675
+ },
1676
+ children: [
1677
+ "~",
1678
+ tokens.toLocaleString(),
1679
+ " tokens"
1680
+ ]
1681
+ })]
1682
+ }),
1683
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
1684
+ @keyframes cpk-a2ui-fade {
1685
+ 0%, 100% { opacity: 1; }
1686
+ 50% { opacity: 0.5; }
1687
+ }
1688
+ @keyframes cpk-a2ui-sweep {
1689
+ 0% { background-position: 250% 0; }
1690
+ 100% { background-position: -250% 0; }
1691
+ }
1692
+ ` })
1693
+ ]
1694
+ });
1695
+ }
1696
+ function Dot() {
1697
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
1698
+ width: 7,
1699
+ height: 7,
1700
+ borderRadius: "50%",
1701
+ backgroundColor: "#d4d4d8",
1702
+ flexShrink: 0
1703
+ } });
1704
+ }
1705
+ function Spacer() {
1706
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: { width: 12 } });
1707
+ }
1708
+ function Bar({ w, h, bg, anim, opacity, transition }) {
1709
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
1710
+ width: w,
1711
+ height: h,
1712
+ borderRadius: 9999,
1713
+ backgroundColor: bg,
1714
+ ...anim !== void 0 ? { animation: `cpk-a2ui-fade 2.4s ease-in-out ${anim}s infinite` } : {},
1715
+ ...opacity !== void 0 ? { opacity } : {},
1716
+ ...transition ? { transition } : {}
1717
+ } });
1718
+ }
1719
+ function Row({ children, show, delay = 0 }) {
1720
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
1721
+ style: {
1722
+ display: "flex",
1723
+ alignItems: "center",
1724
+ gap: 6,
1725
+ opacity: show ? 1 : 0,
1726
+ transition: `opacity 0.4s ${delay}s`
1727
+ },
1728
+ children
1729
+ });
1730
+ }
1731
+ /**
1732
+ * Registers the built-in `render_a2ui` tool call renderer via the props-based
1733
+ * `setRenderToolCalls` mechanism (not `useRenderTool`).
1734
+ *
1735
+ * This ensures user-registered `useRenderTool({ name: "render_a2ui", ... })`
1736
+ * hooks automatically override the built-in, since the merge logic in
1737
+ * react-core.ts gives hook-based entries priority over prop-based entries.
1738
+ */
1739
+ function A2UIBuiltInToolCallRenderer() {
1740
+ const { copilotkit } = useCopilotKit();
1741
+ (0, react.useEffect)(() => {
1742
+ var _renderToolCalls;
1743
+ const renderer = defineToolCallRenderer({
1744
+ name: RENDER_A2UI_TOOL_NAME,
1745
+ args: zod.z.any(),
1746
+ render: ({ status, args: parameters }) => {
1747
+ if (status === "complete") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
1748
+ const params = parameters;
1749
+ const items = params === null || params === void 0 ? void 0 : params.items;
1750
+ if (Array.isArray(items) && items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
1751
+ const components = params === null || params === void 0 ? void 0 : params.components;
1752
+ if (Array.isArray(components) && components.length > 2) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
1753
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIProgressIndicator, { parameters });
1754
+ }
1755
+ });
1756
+ const existing = (_renderToolCalls = copilotkit._renderToolCalls) !== null && _renderToolCalls !== void 0 ? _renderToolCalls : [];
1757
+ copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
1758
+ }, [copilotkit]);
1759
+ return null;
1760
+ }
1761
+
1762
+ //#endregion
1763
+ //#region src/v2/hooks/use-agent-context.tsx
1764
+ function useAgentContext(context) {
1765
+ const { description, value } = context;
1766
+ const { copilotkit } = useCopilotKit();
1767
+ const stringValue = (0, react.useMemo)(() => {
1768
+ if (typeof value === "string") return value;
1769
+ return JSON.stringify(value);
1770
+ }, [value]);
1771
+ (0, react.useLayoutEffect)(() => {
1772
+ if (!copilotkit) return;
1773
+ const id = copilotkit.addContext({
1774
+ description,
1775
+ value: stringValue
1776
+ });
1777
+ return () => {
1778
+ copilotkit.removeContext(id);
1779
+ };
1780
+ }, [
1781
+ description,
1782
+ stringValue,
1783
+ copilotkit
1784
+ ]);
1785
+ }
1786
+
1787
+ //#endregion
1788
+ //#region src/v2/a2ui/A2UICatalogContext.tsx
1789
+ /**
1790
+ * Renders agent context describing the available A2UI catalog and custom components.
1791
+ * Only mount this component when A2UI is enabled.
1792
+ *
1793
+ * When `includeSchema` is true, the full component schemas (JSON Schema) are also
1794
+ * sent as context using the same description key as the A2UI middleware, so the
1795
+ * middleware can optionally overwrite it with a server-side schema.
1796
+ */
1797
+ function A2UICatalogContext({ catalog, includeSchema }) {
1798
+ useAgentContext({
1799
+ description: "A2UI catalog capabilities: available catalog IDs and custom component definitions the client can render.",
1800
+ value: (0, _copilotkit_a2ui_renderer.buildCatalogContextValue)(catalog)
1801
+ });
1802
+ const { copilotkit } = useCopilotKit();
1803
+ const schemaValue = (0, react.useMemo)(() => includeSchema !== false ? JSON.stringify((0, _copilotkit_a2ui_renderer.extractCatalogComponentSchemas)(catalog)) : null, [catalog, includeSchema]);
1804
+ (0, react.useLayoutEffect)(() => {
1805
+ if (!copilotkit || !schemaValue) return;
1806
+ const ids = [];
1807
+ ids.push(copilotkit.addContext({
1808
+ description: _copilotkit_a2ui_renderer.A2UI_SCHEMA_CONTEXT_DESCRIPTION,
1809
+ value: schemaValue
1810
+ }));
1811
+ ids.push(copilotkit.addContext({
1812
+ description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
1813
+ value: _copilotkit_shared.A2UI_DEFAULT_GENERATION_GUIDELINES
1814
+ }));
1815
+ ids.push(copilotkit.addContext({
1816
+ description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
1817
+ value: _copilotkit_shared.A2UI_DEFAULT_DESIGN_GUIDELINES
1818
+ }));
1819
+ return () => {
1820
+ for (const id of ids) copilotkit.removeContext(id);
1821
+ };
1822
+ }, [copilotkit, schemaValue]);
1823
+ return null;
875
1824
  }
876
1825
 
877
1826
  //#endregion
@@ -981,6 +1930,17 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
981
1930
  //#region src/v2/providers/CopilotKitProvider.tsx
982
1931
  const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
983
1932
  const COPILOT_CLOUD_CHAT_URL$1 = "https://api.cloud.copilotkit.ai/copilotkit/v1";
1933
+ const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follow these design principles inspired by shadcn/ui:
1934
+
1935
+ - Use a minimal, flat aesthetic. Avoid drop shadows and gradients — rely on subtle borders (1px solid, light gray like #e5e7eb) to define surfaces.
1936
+ - Neutral base palette: white backgrounds, zinc/slate gray text (#09090b for headings, #71717a for secondary text). One accent color for interactive elements.
1937
+ - Use system font stacks (system-ui, -apple-system, sans-serif) at readable sizes (14px body, 600 weight for headings). Tight line-heights.
1938
+ - Small, consistent border-radius (6–8px). Cards and containers use border, not shadow, for separation.
1939
+ - Buttons: solid fill for primary (dark bg, white text), outline for secondary (border + transparent bg). Subtle hover state (slight opacity or background shift).
1940
+ - Use CSS Grid or Flexbox for layout. Ensure the UI looks good at any width.
1941
+ - Minimal transitions (150ms) for hover/focus states only. No decorative animations.
1942
+ - Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
1943
+ 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)";
984
1944
  const CopilotKitContext = (0, react.createContext)({
985
1945
  copilotkit: null,
986
1946
  executingToolCallIds: /* @__PURE__ */ new Set()
@@ -995,9 +1955,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
995
1955
  }, [value, warningMessage]);
996
1956
  return value;
997
1957
  }
998
- const CopilotKitProvider = ({ children, runtimeUrl, headers = {}, credentials, publicApiKey, publicLicenseKey, licenseToken, properties = {}, agents__unsafe_dev_only: agents = {}, selfManagedAgents = {}, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, showDevConsole = false, useSingleEndpoint = false, onError, a2ui }) => {
1958
+ const CopilotKitProvider = ({ children, runtimeUrl, headers = {}, credentials, publicApiKey, publicLicenseKey, licenseToken, properties = {}, agents__unsafe_dev_only: agents = {}, selfManagedAgents = {}, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, openGenerativeUI, showDevConsole = false, useSingleEndpoint, onError, a2ui, defaultThrottleMs, inspectorDefaultAnchor }) => {
1959
+ var _openGenerativeUI$des;
999
1960
  const [shouldRenderInspector, setShouldRenderInspector] = (0, react.useState)(false);
1000
1961
  const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = (0, react.useState)(false);
1962
+ const [runtimeOpenGenUIEnabled, setRuntimeOpenGenUIEnabled] = (0, react.useState)(false);
1963
+ const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
1001
1964
  const [runtimeLicenseStatus, setRuntimeLicenseStatus] = (0, react.useState)(void 0);
1002
1965
  (0, react.useEffect)(() => {
1003
1966
  if (typeof window === "undefined") return;
@@ -1026,12 +1989,25 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1026
1989
  content: MCPAppsActivityContentSchema,
1027
1990
  render: MCPAppsActivityRenderer
1028
1991
  }];
1992
+ if (openGenUIActive) renderers.push({
1993
+ activityType: OpenGenerativeUIActivityType,
1994
+ content: OpenGenerativeUIContentSchema,
1995
+ render: OpenGenerativeUIActivityRenderer
1996
+ });
1029
1997
  if (runtimeA2UIEnabled) {
1030
1998
  var _a2ui$theme;
1031
- renderers.unshift(createA2UIMessageRenderer({ theme: (_a2ui$theme = a2ui === null || a2ui === void 0 ? void 0 : a2ui.theme) !== null && _a2ui$theme !== void 0 ? _a2ui$theme : _copilotkit_a2ui_renderer.viewerTheme }));
1999
+ renderers.unshift(createA2UIMessageRenderer({
2000
+ theme: (_a2ui$theme = a2ui === null || a2ui === void 0 ? void 0 : a2ui.theme) !== null && _a2ui$theme !== void 0 ? _a2ui$theme : _copilotkit_a2ui_renderer.viewerTheme,
2001
+ catalog: a2ui === null || a2ui === void 0 ? void 0 : a2ui.catalog,
2002
+ loadingComponent: a2ui === null || a2ui === void 0 ? void 0 : a2ui.loadingComponent
2003
+ }));
1032
2004
  }
1033
2005
  return renderers;
1034
- }, [runtimeA2UIEnabled, a2ui]);
2006
+ }, [
2007
+ runtimeA2UIEnabled,
2008
+ openGenUIActive,
2009
+ a2ui
2010
+ ]);
1035
2011
  const allActivityRenderers = (0, react.useMemo)(() => {
1036
2012
  return [...renderActivityMessagesList, ...builtInActivityRenderers];
1037
2013
  }, [renderActivityMessagesList, builtInActivityRenderers]);
@@ -1057,6 +2033,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1057
2033
  const chatApiEndpoint = runtimeUrl !== null && runtimeUrl !== void 0 ? runtimeUrl : resolvedPublicKey ? COPILOT_CLOUD_CHAT_URL$1 : void 0;
1058
2034
  const frontendToolsList = useStableArrayProp(frontendTools, "frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.");
1059
2035
  const humanInTheLoopList = useStableArrayProp(humanInTheLoop, "humanInTheLoop must be a stable array. If you want to dynamically add or remove human-in-the-loop tools, use `useHumanInTheLoop` instead.");
2036
+ const sandboxFunctionsList = useStableArrayProp(openGenerativeUI === null || openGenerativeUI === void 0 ? void 0 : openGenerativeUI.sandboxFunctions, "openGenerativeUI.sandboxFunctions must be a stable array.");
1060
2037
  const processedHumanInTheLoopTools = (0, react.useMemo)(() => {
1061
2038
  const processedTools = [];
1062
2039
  const processedRenderToolCalls = [];
@@ -1087,15 +2064,31 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1087
2064
  renderToolCalls: processedRenderToolCalls
1088
2065
  };
1089
2066
  }, [humanInTheLoopList]);
2067
+ const builtInFrontendTools = (0, react.useMemo)(() => {
2068
+ if (!openGenUIActive) return [];
2069
+ return [{
2070
+ name: "generateSandboxedUi",
2071
+ description: GENERATE_SANDBOXED_UI_DESCRIPTION,
2072
+ parameters: GenerateSandboxedUiArgsSchema,
2073
+ handler: async () => "UI generated",
2074
+ followUp: true,
2075
+ render: OpenGenerativeUIToolRenderer
2076
+ }];
2077
+ }, [openGenUIActive]);
1090
2078
  const allTools = (0, react.useMemo)(() => {
1091
2079
  const tools = [];
1092
2080
  tools.push(...frontendToolsList);
2081
+ tools.push(...builtInFrontendTools);
1093
2082
  tools.push(...processedHumanInTheLoopTools.tools);
1094
2083
  return tools;
1095
- }, [frontendToolsList, processedHumanInTheLoopTools]);
2084
+ }, [
2085
+ frontendToolsList,
2086
+ builtInFrontendTools,
2087
+ processedHumanInTheLoopTools
2088
+ ]);
1096
2089
  const allRenderToolCalls = (0, react.useMemo)(() => {
1097
2090
  const combined = [...renderToolCallsList];
1098
- frontendToolsList.forEach((tool) => {
2091
+ [...frontendToolsList, ...builtInFrontendTools].forEach((tool) => {
1099
2092
  if (tool.render) {
1100
2093
  const args = tool.parameters || (tool.name === "*" ? zod.z.any() : void 0);
1101
2094
  if (args) combined.push({
@@ -1110,25 +2103,31 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1110
2103
  }, [
1111
2104
  renderToolCallsList,
1112
2105
  frontendToolsList,
2106
+ builtInFrontendTools,
1113
2107
  processedHumanInTheLoopTools
1114
2108
  ]);
1115
2109
  const copilotkitRef = (0, react.useRef)(null);
1116
- if (copilotkitRef.current === null) copilotkitRef.current = new CopilotKitCoreReact({
1117
- runtimeUrl: chatApiEndpoint,
1118
- runtimeTransport: useSingleEndpoint ? "single" : "rest",
1119
- headers: mergedHeaders,
1120
- credentials,
1121
- properties,
1122
- agents__unsafe_dev_only: mergedAgents,
1123
- tools: allTools,
1124
- renderToolCalls: allRenderToolCalls,
1125
- renderActivityMessages: allActivityRenderers,
1126
- renderCustomMessages: renderCustomMessagesList
1127
- });
2110
+ if (copilotkitRef.current === null) {
2111
+ copilotkitRef.current = new CopilotKitCoreReact({
2112
+ runtimeUrl: chatApiEndpoint,
2113
+ runtimeTransport: useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto",
2114
+ headers: mergedHeaders,
2115
+ credentials,
2116
+ properties,
2117
+ agents__unsafe_dev_only: mergedAgents,
2118
+ tools: allTools,
2119
+ renderToolCalls: allRenderToolCalls,
2120
+ renderActivityMessages: allActivityRenderers,
2121
+ renderCustomMessages: renderCustomMessagesList
2122
+ });
2123
+ if (defaultThrottleMs !== void 0) copilotkitRef.current.setDefaultThrottleMs(defaultThrottleMs);
2124
+ }
1128
2125
  const copilotkit = copilotkitRef.current;
1129
2126
  (0, react.useEffect)(() => {
2127
+ setRuntimeA2UIEnabled(copilotkit.a2uiEnabled);
1130
2128
  const subscription = copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
1131
2129
  setRuntimeA2UIEnabled(copilotkit.a2uiEnabled);
2130
+ setRuntimeOpenGenUIEnabled(copilotkit.openGenerativeUIEnabled);
1132
2131
  setRuntimeLicenseStatus(copilotkit.licenseStatus);
1133
2132
  } });
1134
2133
  return () => {
@@ -1188,7 +2187,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1188
2187
  }, [copilotkit]);
1189
2188
  (0, react.useEffect)(() => {
1190
2189
  copilotkit.setRuntimeUrl(chatApiEndpoint);
1191
- copilotkit.setRuntimeTransport(useSingleEndpoint ? "single" : "rest");
2190
+ copilotkit.setRuntimeTransport(useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto");
1192
2191
  copilotkit.setHeaders(mergedHeaders);
1193
2192
  copilotkit.setCredentials(credentials);
1194
2193
  copilotkit.setProperties(properties);
@@ -1222,23 +2221,75 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1222
2221
  (0, react.useEffect)(() => {
1223
2222
  didMountRef.current = true;
1224
2223
  }, []);
2224
+ (0, react.useEffect)(() => {
2225
+ if (defaultThrottleMs !== void 0 && (!Number.isFinite(defaultThrottleMs) || defaultThrottleMs < 0)) console.error(`CopilotKitProvider: defaultThrottleMs must be a non-negative finite number, got ${defaultThrottleMs}. useAgent hooks without an explicit throttleMs will fall back to unthrottled.`);
2226
+ copilotkit.setDefaultThrottleMs(defaultThrottleMs);
2227
+ }, [copilotkit, defaultThrottleMs]);
2228
+ const designSkill = (_openGenerativeUI$des = openGenerativeUI === null || openGenerativeUI === void 0 ? void 0 : openGenerativeUI.designSkill) !== null && _openGenerativeUI$des !== void 0 ? _openGenerativeUI$des : DEFAULT_DESIGN_SKILL;
2229
+ (0, react.useLayoutEffect)(() => {
2230
+ if (!copilotkit || !openGenUIActive) return;
2231
+ const id = copilotkit.addContext({
2232
+ description: "Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
2233
+ value: designSkill
2234
+ });
2235
+ return () => {
2236
+ copilotkit.removeContext(id);
2237
+ };
2238
+ }, [
2239
+ copilotkit,
2240
+ designSkill,
2241
+ openGenUIActive
2242
+ ]);
2243
+ const sandboxFunctionsDescriptors = (0, react.useMemo)(() => {
2244
+ if (sandboxFunctionsList.length === 0) return null;
2245
+ return JSON.stringify(sandboxFunctionsList.map((fn) => ({
2246
+ name: fn.name,
2247
+ description: fn.description,
2248
+ parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema })
2249
+ })));
2250
+ }, [sandboxFunctionsList]);
2251
+ (0, react.useLayoutEffect)(() => {
2252
+ if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
2253
+ const id = copilotkit.addContext({
2254
+ description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
2255
+ value: sandboxFunctionsDescriptors
2256
+ });
2257
+ return () => {
2258
+ copilotkit.removeContext(id);
2259
+ };
2260
+ }, [
2261
+ copilotkit,
2262
+ sandboxFunctionsDescriptors,
2263
+ openGenUIActive
2264
+ ]);
1225
2265
  const contextValue = (0, react.useMemo)(() => ({
1226
2266
  copilotkit,
1227
2267
  executingToolCallIds
1228
2268
  }), [copilotkit, executingToolCallIds]);
1229
2269
  const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
1230
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
1231
- value: contextValue,
1232
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
1233
- value: licenseContextValue,
1234
- children: [
1235
- children,
1236
- shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, { core: copilotkit }) : null,
1237
- runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "no_license" }),
1238
- runtimeLicenseStatus === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expired" }),
1239
- runtimeLicenseStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "invalid" }),
1240
- runtimeLicenseStatus === "expiring" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expiring" })
1241
- ]
2270
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
2271
+ value: sandboxFunctionsList,
2272
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
2273
+ value: contextValue,
2274
+ children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
2275
+ value: licenseContextValue,
2276
+ children: [
2277
+ runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
2278
+ runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
2279
+ catalog: a2ui === null || a2ui === void 0 ? void 0 : a2ui.catalog,
2280
+ includeSchema: a2ui === null || a2ui === void 0 ? void 0 : a2ui.includeSchema
2281
+ }),
2282
+ children,
2283
+ shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, {
2284
+ core: copilotkit,
2285
+ defaultAnchor: inspectorDefaultAnchor
2286
+ }) : null,
2287
+ runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "no_license" }),
2288
+ runtimeLicenseStatus === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expired" }),
2289
+ runtimeLicenseStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "invalid" }),
2290
+ runtimeLicenseStatus === "expiring" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expiring" })
2291
+ ]
2292
+ })
1242
2293
  })
1243
2294
  });
1244
2295
  };
@@ -1253,78 +2304,265 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1253
2304
  return () => {
1254
2305
  subscription.unsubscribe();
1255
2306
  };
1256
- }, []);
1257
- return context;
1258
- };
1259
-
1260
- //#endregion
1261
- //#region src/v2/hooks/use-render-tool-call.tsx
1262
- /**
1263
- * Memoized component that renders a single tool call.
1264
- * This prevents unnecessary re-renders when parent components update
1265
- * but the tool call data hasn't changed.
1266
- */
1267
- const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
1268
- const args = (0, react.useMemo)(() => (0, _copilotkit_shared.partialJSONParse)(toolCall.function.arguments), [toolCall.function.arguments]);
1269
- const toolName = toolCall.function.name;
1270
- if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1271
- name: toolName,
1272
- args,
1273
- status: _copilotkit_core.ToolCallStatus.Complete,
1274
- result: toolMessage.content
1275
- });
1276
- else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1277
- name: toolName,
1278
- args,
1279
- status: _copilotkit_core.ToolCallStatus.Executing,
1280
- result: void 0
1281
- });
1282
- else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
1283
- name: toolName,
1284
- args,
1285
- status: _copilotkit_core.ToolCallStatus.InProgress,
1286
- result: void 0
1287
- });
1288
- }, (prevProps, nextProps) => {
1289
- var _prevProps$toolMessag, _nextProps$toolMessag;
1290
- if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
1291
- if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
1292
- if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
1293
- if (((_prevProps$toolMessag = prevProps.toolMessage) === null || _prevProps$toolMessag === void 0 ? void 0 : _prevProps$toolMessag.content) !== ((_nextProps$toolMessag = nextProps.toolMessage) === null || _nextProps$toolMessag === void 0 ? void 0 : _nextProps$toolMessag.content)) return false;
1294
- if (prevProps.isExecuting !== nextProps.isExecuting) return false;
1295
- if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
1296
- return true;
1297
- });
1298
- /**
1299
- * Hook that returns a function to render tool calls based on the render functions
1300
- * defined in CopilotKitProvider.
1301
- *
1302
- * @returns A function that takes a tool call and optional tool message and returns the rendered component
1303
- */
1304
- function useRenderToolCall$1() {
1305
- var _config$agentId;
1306
- const { copilotkit, executingToolCallIds } = useCopilotKit();
1307
- const config = useCopilotChatConfiguration();
1308
- const agentId = (_config$agentId = config === null || config === void 0 ? void 0 : config.agentId) !== null && _config$agentId !== void 0 ? _config$agentId : _copilotkit_shared.DEFAULT_AGENT_ID;
1309
- const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
1310
- return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
1311
- }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
1312
- return (0, react.useCallback)(({ toolCall, toolMessage }) => {
1313
- const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
1314
- const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
1315
- if (!renderConfig) return null;
1316
- const RenderComponent = renderConfig.render;
1317
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
1318
- toolCall,
1319
- toolMessage,
1320
- RenderComponent,
1321
- isExecuting: executingToolCallIds.has(toolCall.id)
1322
- }, toolCall.id);
2307
+ }, []);
2308
+ return context;
2309
+ };
2310
+
2311
+ //#endregion
2312
+ //#region src/v2/hooks/use-render-tool-call.tsx
2313
+ /**
2314
+ * Memoized component that renders a single tool call.
2315
+ * This prevents unnecessary re-renders when parent components update
2316
+ * but the tool call data hasn't changed.
2317
+ */
2318
+ const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall, toolMessage, RenderComponent, isExecuting }) {
2319
+ const args = (0, react.useMemo)(() => (0, _copilotkit_shared.partialJSONParse)(toolCall.function.arguments), [toolCall.function.arguments]);
2320
+ const toolName = toolCall.function.name;
2321
+ if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
2322
+ name: toolName,
2323
+ args,
2324
+ status: _copilotkit_core.ToolCallStatus.Complete,
2325
+ result: toolMessage.content
2326
+ });
2327
+ else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
2328
+ name: toolName,
2329
+ args,
2330
+ status: _copilotkit_core.ToolCallStatus.Executing,
2331
+ result: void 0
2332
+ });
2333
+ else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
2334
+ name: toolName,
2335
+ args,
2336
+ status: _copilotkit_core.ToolCallStatus.InProgress,
2337
+ result: void 0
2338
+ });
2339
+ }, (prevProps, nextProps) => {
2340
+ var _prevProps$toolMessag, _nextProps$toolMessag;
2341
+ if (prevProps.toolCall.id !== nextProps.toolCall.id) return false;
2342
+ if (prevProps.toolCall.function.name !== nextProps.toolCall.function.name) return false;
2343
+ if (prevProps.toolCall.function.arguments !== nextProps.toolCall.function.arguments) return false;
2344
+ if (((_prevProps$toolMessag = prevProps.toolMessage) === null || _prevProps$toolMessag === void 0 ? void 0 : _prevProps$toolMessag.content) !== ((_nextProps$toolMessag = nextProps.toolMessage) === null || _nextProps$toolMessag === void 0 ? void 0 : _nextProps$toolMessag.content)) return false;
2345
+ if (prevProps.isExecuting !== nextProps.isExecuting) return false;
2346
+ if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
2347
+ return true;
2348
+ });
2349
+ /**
2350
+ * Hook that returns a function to render tool calls based on the render functions
2351
+ * defined in CopilotKitProvider.
2352
+ *
2353
+ * @returns A function that takes a tool call and optional tool message and returns the rendered component
2354
+ */
2355
+ function useRenderToolCall$1() {
2356
+ var _config$agentId;
2357
+ const { copilotkit, executingToolCallIds } = useCopilotKit();
2358
+ const config = useCopilotChatConfiguration();
2359
+ const agentId = (_config$agentId = config === null || config === void 0 ? void 0 : config.agentId) !== null && _config$agentId !== void 0 ? _config$agentId : _copilotkit_shared.DEFAULT_AGENT_ID;
2360
+ const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
2361
+ return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
2362
+ }, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
2363
+ return (0, react.useCallback)(({ toolCall, toolMessage }) => {
2364
+ const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
2365
+ const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
2366
+ if (!renderConfig) return null;
2367
+ const RenderComponent = renderConfig.render;
2368
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
2369
+ toolCall,
2370
+ toolMessage,
2371
+ RenderComponent,
2372
+ isExecuting: executingToolCallIds.has(toolCall.id)
2373
+ }, toolCall.id);
2374
+ }, [
2375
+ renderToolCalls,
2376
+ executingToolCallIds,
2377
+ agentId
2378
+ ]);
2379
+ }
2380
+
2381
+ //#endregion
2382
+ //#region src/v2/hooks/use-agent.tsx
2383
+ let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
2384
+ UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
2385
+ UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
2386
+ UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
2387
+ return UseAgentUpdate;
2388
+ }({});
2389
+ const ALL_UPDATES = [
2390
+ UseAgentUpdate.OnMessagesChanged,
2391
+ UseAgentUpdate.OnStateChanged,
2392
+ UseAgentUpdate.OnRunStatusChanged
2393
+ ];
2394
+ /**
2395
+ * Clone a registry agent for per-thread isolation.
2396
+ * Copies agent configuration (transport, headers, etc.) but resets conversation
2397
+ * state (messages, threadId, state) so each thread starts fresh.
2398
+ */
2399
+ function cloneForThread(source, threadId, headers) {
2400
+ const clone = source.clone();
2401
+ if (clone === source) throw new Error(`useAgent: ${source.constructor.name}.clone() returned the same instance. clone() must return a new, independent object.`);
2402
+ clone.threadId = threadId;
2403
+ clone.setMessages([]);
2404
+ clone.setState({});
2405
+ if (clone instanceof _ag_ui_client.HttpAgent) clone.headers = { ...headers };
2406
+ return clone;
2407
+ }
2408
+ /**
2409
+ * Module-level WeakMap: registryAgent → (threadId → clone).
2410
+ * Shared across all useAgent() calls so that every component using the same
2411
+ * (agentId, threadId) pair receives the same agent instance. Using WeakMap
2412
+ * ensures the clone map is garbage-collected when the registry agent is
2413
+ * replaced (e.g. after reconnect or hot-reload).
2414
+ */
2415
+ const globalThreadCloneMap = /* @__PURE__ */ new WeakMap();
2416
+ /**
2417
+ * Look up an existing per-thread clone without creating one.
2418
+ * Returns undefined when no clone has been created yet for this pair.
2419
+ */
2420
+ function getThreadClone(registryAgent, threadId) {
2421
+ var _globalThreadCloneMap;
2422
+ if (!registryAgent || !threadId) return void 0;
2423
+ return (_globalThreadCloneMap = globalThreadCloneMap.get(registryAgent)) === null || _globalThreadCloneMap === void 0 ? void 0 : _globalThreadCloneMap.get(threadId);
2424
+ }
2425
+ function getOrCreateThreadClone(existing, threadId, headers) {
2426
+ let byThread = globalThreadCloneMap.get(existing);
2427
+ if (!byThread) {
2428
+ byThread = /* @__PURE__ */ new Map();
2429
+ globalThreadCloneMap.set(existing, byThread);
2430
+ }
2431
+ const cached = byThread.get(threadId);
2432
+ if (cached) return cached;
2433
+ const clone = cloneForThread(existing, threadId, headers);
2434
+ byThread.set(threadId, clone);
2435
+ return clone;
2436
+ }
2437
+ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
2438
+ var _agentId, _threadId;
2439
+ (_agentId = agentId) !== null && _agentId !== void 0 || (agentId = _copilotkit_shared.DEFAULT_AGENT_ID);
2440
+ const { copilotkit } = useCopilotKit();
2441
+ const providerThrottleMs = copilotkit.defaultThrottleMs;
2442
+ const chatConfig = useCopilotChatConfiguration();
2443
+ (_threadId = threadId) !== null && _threadId !== void 0 || (threadId = chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.threadId);
2444
+ const effectiveThrottleMs = (0, react.useMemo)(() => {
2445
+ var _ref;
2446
+ const resolved = (_ref = throttleMs !== null && throttleMs !== void 0 ? throttleMs : providerThrottleMs) !== null && _ref !== void 0 ? _ref : 0;
2447
+ if (!Number.isFinite(resolved) || resolved < 0) {
2448
+ const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
2449
+ console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
2450
+ return 0;
2451
+ }
2452
+ return resolved;
2453
+ }, [throttleMs, providerThrottleMs]);
2454
+ const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
2455
+ const updateFlags = (0, react.useMemo)(() => updates !== null && updates !== void 0 ? updates : ALL_UPDATES, [JSON.stringify(updates)]);
2456
+ const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
2457
+ const agent = (0, react.useMemo)(() => {
2458
+ var _copilotkit$agents;
2459
+ const cacheKey = threadId ? `${agentId}:${threadId}` : agentId;
2460
+ const existing = copilotkit.getAgent(agentId);
2461
+ if (existing) {
2462
+ provisionalAgentCache.current.delete(cacheKey);
2463
+ provisionalAgentCache.current.delete(agentId);
2464
+ if (!threadId) return existing;
2465
+ return getOrCreateThreadClone(existing, threadId, copilotkit.headers);
2466
+ }
2467
+ const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
2468
+ const status = copilotkit.runtimeConnectionStatus;
2469
+ if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
2470
+ const cached = provisionalAgentCache.current.get(cacheKey);
2471
+ if (cached) {
2472
+ cached.headers = { ...copilotkit.headers };
2473
+ return cached;
2474
+ }
2475
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
2476
+ runtimeUrl: copilotkit.runtimeUrl,
2477
+ agentId,
2478
+ transport: copilotkit.runtimeTransport,
2479
+ runtimeMode: "pending"
2480
+ });
2481
+ provisional.headers = { ...copilotkit.headers };
2482
+ if (threadId) provisional.threadId = threadId;
2483
+ provisionalAgentCache.current.set(cacheKey, provisional);
2484
+ return provisional;
2485
+ }
2486
+ if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
2487
+ const cached = provisionalAgentCache.current.get(cacheKey);
2488
+ if (cached) {
2489
+ cached.headers = { ...copilotkit.headers };
2490
+ return cached;
2491
+ }
2492
+ const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
2493
+ runtimeUrl: copilotkit.runtimeUrl,
2494
+ agentId,
2495
+ transport: copilotkit.runtimeTransport,
2496
+ runtimeMode: "pending"
2497
+ });
2498
+ provisional.headers = { ...copilotkit.headers };
2499
+ if (threadId) provisional.threadId = threadId;
2500
+ provisionalAgentCache.current.set(cacheKey, provisional);
2501
+ return provisional;
2502
+ }
2503
+ const knownAgents = Object.keys((_copilotkit$agents = copilotkit.agents) !== null && _copilotkit$agents !== void 0 ? _copilotkit$agents : {});
2504
+ const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
2505
+ 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.");
2506
+ }, [
2507
+ agentId,
2508
+ threadId,
2509
+ copilotkit.agents,
2510
+ copilotkit.runtimeConnectionStatus,
2511
+ copilotkit.runtimeUrl,
2512
+ copilotkit.runtimeTransport,
2513
+ JSON.stringify(copilotkit.headers)
2514
+ ]);
2515
+ (0, react.useEffect)(() => {
2516
+ if (updateFlags.length === 0) return;
2517
+ const handlers = {};
2518
+ let timerId = null;
2519
+ let active = true;
2520
+ if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) {
2521
+ const ms = effectiveThrottleMs;
2522
+ if (ms > 0) {
2523
+ let throttleActive = false;
2524
+ let pending = false;
2525
+ const throttledNotify = () => {
2526
+ if (!active) return;
2527
+ if (!throttleActive) {
2528
+ throttleActive = true;
2529
+ pending = false;
2530
+ forceUpdate();
2531
+ timerId = setTimeout(function trailingEdge() {
2532
+ timerId = null;
2533
+ if (active && pending) {
2534
+ pending = false;
2535
+ forceUpdate();
2536
+ timerId = setTimeout(trailingEdge, ms);
2537
+ } else throttleActive = false;
2538
+ }, ms);
2539
+ } else pending = true;
2540
+ };
2541
+ handlers.onMessagesChanged = throttledNotify;
2542
+ } else handlers.onMessagesChanged = forceUpdate;
2543
+ }
2544
+ if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = forceUpdate;
2545
+ if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
2546
+ handlers.onRunInitialized = forceUpdate;
2547
+ handlers.onRunFinalized = forceUpdate;
2548
+ handlers.onRunFailed = forceUpdate;
2549
+ }
2550
+ const subscription = agent.subscribe(handlers);
2551
+ return () => {
2552
+ active = false;
2553
+ if (timerId !== null) clearTimeout(timerId);
2554
+ subscription.unsubscribe();
2555
+ };
1323
2556
  }, [
1324
- renderToolCalls,
1325
- executingToolCallIds,
1326
- agentId
2557
+ agent,
2558
+ forceUpdate,
2559
+ effectiveThrottleMs,
2560
+ updateFlags
1327
2561
  ]);
2562
+ (0, react.useEffect)(() => {
2563
+ if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
2564
+ }, [agent, JSON.stringify(copilotkit.headers)]);
2565
+ return { agent };
1328
2566
  }
1329
2567
 
1330
2568
  //#endregion
@@ -1340,12 +2578,13 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1340
2578
  return aHasAgent ? -1 : 1;
1341
2579
  });
1342
2580
  return function(params) {
1343
- var _copilotkit$getRunIdF;
2581
+ var _copilotkit$getRunIdF, _getThreadClone;
1344
2582
  if (!customMessageRenderers.length) return null;
1345
2583
  const { message, position } = params;
1346
2584
  const resolvedRunId = (_copilotkit$getRunIdF = copilotkit.getRunIdForMessage(agentId, threadId, message.id)) !== null && _copilotkit$getRunIdF !== void 0 ? _copilotkit$getRunIdF : copilotkit.getRunIdsForThread(agentId, threadId).slice(-1)[0];
1347
2585
  const runId = resolvedRunId !== null && resolvedRunId !== void 0 ? resolvedRunId : `missing-run-id:${message.id}`;
1348
- const agent = copilotkit.getAgent(agentId);
2586
+ const registryAgent = copilotkit.getAgent(agentId);
2587
+ const agent = (_getThreadClone = getThreadClone(registryAgent, threadId)) !== null && _getThreadClone !== void 0 ? _getThreadClone : registryAgent;
1349
2588
  if (!agent) throw new Error("Agent not found");
1350
2589
  const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
1351
2590
  const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
@@ -1389,7 +2628,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1389
2628
  copilotkit.removeTool(name, tool.agentId);
1390
2629
  }
1391
2630
  copilotkit.addTool(tool);
1392
- if (tool.render && tool.parameters) copilotkit.addHookRenderToolCall({
2631
+ if (tool.render) copilotkit.addHookRenderToolCall({
1393
2632
  name,
1394
2633
  args: tool.parameters,
1395
2634
  agentId: tool.agentId,
@@ -1407,18 +2646,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1407
2646
  ]);
1408
2647
  }
1409
2648
 
1410
- //#endregion
1411
- //#region src/v2/types/defineToolCallRenderer.ts
1412
- function defineToolCallRenderer(def) {
1413
- const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
1414
- return {
1415
- name: def.name,
1416
- args: argsSchema,
1417
- render: def.render,
1418
- ...def.agentId ? { agentId: def.agentId } : {}
1419
- };
1420
- }
1421
-
1422
2649
  //#endregion
1423
2650
  //#region src/v2/hooks/use-human-in-the-loop.tsx
1424
2651
  function useHumanInTheLoop$1(tool, deps) {
@@ -1485,94 +2712,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
1485
2712
  ]);
1486
2713
  }
1487
2714
 
1488
- //#endregion
1489
- //#region src/v2/hooks/use-agent.tsx
1490
- let UseAgentUpdate = /* @__PURE__ */ function(UseAgentUpdate) {
1491
- UseAgentUpdate["OnMessagesChanged"] = "OnMessagesChanged";
1492
- UseAgentUpdate["OnStateChanged"] = "OnStateChanged";
1493
- UseAgentUpdate["OnRunStatusChanged"] = "OnRunStatusChanged";
1494
- return UseAgentUpdate;
1495
- }({});
1496
- const ALL_UPDATES = [
1497
- UseAgentUpdate.OnMessagesChanged,
1498
- UseAgentUpdate.OnStateChanged,
1499
- UseAgentUpdate.OnRunStatusChanged
1500
- ];
1501
- function useAgent({ agentId, updates } = {}) {
1502
- var _agentId;
1503
- (_agentId = agentId) !== null && _agentId !== void 0 || (agentId = _copilotkit_shared.DEFAULT_AGENT_ID);
1504
- const { copilotkit } = useCopilotKit();
1505
- const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
1506
- const updateFlags = (0, react.useMemo)(() => updates !== null && updates !== void 0 ? updates : ALL_UPDATES, [JSON.stringify(updates)]);
1507
- const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
1508
- const agent = (0, react.useMemo)(() => {
1509
- var _copilotkit$agents;
1510
- const existing = copilotkit.getAgent(agentId);
1511
- if (existing) {
1512
- provisionalAgentCache.current.delete(agentId);
1513
- return existing;
1514
- }
1515
- const isRuntimeConfigured = copilotkit.runtimeUrl !== void 0;
1516
- const status = copilotkit.runtimeConnectionStatus;
1517
- if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
1518
- const cached = provisionalAgentCache.current.get(agentId);
1519
- if (cached) {
1520
- cached.headers = { ...copilotkit.headers };
1521
- return cached;
1522
- }
1523
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
1524
- runtimeUrl: copilotkit.runtimeUrl,
1525
- agentId,
1526
- transport: copilotkit.runtimeTransport,
1527
- runtimeMode: "pending"
1528
- });
1529
- provisional.headers = { ...copilotkit.headers };
1530
- provisionalAgentCache.current.set(agentId, provisional);
1531
- return provisional;
1532
- }
1533
- if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
1534
- const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
1535
- runtimeUrl: copilotkit.runtimeUrl,
1536
- agentId,
1537
- transport: copilotkit.runtimeTransport,
1538
- runtimeMode: "pending"
1539
- });
1540
- provisional.headers = { ...copilotkit.headers };
1541
- return provisional;
1542
- }
1543
- const knownAgents = Object.keys((_copilotkit$agents = copilotkit.agents) !== null && _copilotkit$agents !== void 0 ? _copilotkit$agents : {});
1544
- const runtimePart = isRuntimeConfigured ? `runtimeUrl=${copilotkit.runtimeUrl}` : "no runtimeUrl";
1545
- 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.");
1546
- }, [
1547
- agentId,
1548
- copilotkit.agents,
1549
- copilotkit.runtimeConnectionStatus,
1550
- copilotkit.runtimeUrl,
1551
- copilotkit.runtimeTransport,
1552
- JSON.stringify(copilotkit.headers)
1553
- ]);
1554
- (0, react.useEffect)(() => {
1555
- if (updateFlags.length === 0) return;
1556
- const handlers = {};
1557
- if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = () => {
1558
- forceUpdate();
1559
- };
1560
- if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = forceUpdate;
1561
- if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
1562
- handlers.onRunInitialized = forceUpdate;
1563
- handlers.onRunFinalized = forceUpdate;
1564
- handlers.onRunFailed = forceUpdate;
1565
- }
1566
- const subscription = agent.subscribe(handlers);
1567
- return () => subscription.unsubscribe();
1568
- }, [
1569
- agent,
1570
- forceUpdate,
1571
- JSON.stringify(updateFlags)
1572
- ]);
1573
- return { agent };
1574
- }
1575
-
1576
2715
  //#endregion
1577
2716
  //#region src/v2/hooks/use-suggestions.tsx
1578
2717
  function useSuggestions({ agentId } = {}) {
@@ -2248,6 +3387,227 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2248
3387
  if (!context) throw new Error("useToast must be used within a ToastProvider");
2249
3388
  return context;
2250
3389
  }
3390
+ function formatBannerMessage(message) {
3391
+ const jsonMatch = message.match(/'message':\s*'([^']+)'/);
3392
+ if (jsonMatch) return jsonMatch[1];
3393
+ let cleaned = message.split(" - ")[0];
3394
+ cleaned = cleaned.split(": Error code")[0];
3395
+ cleaned = cleaned.replace(/:\s*\d{3}$/, "");
3396
+ cleaned = cleaned.replace(/See more:.*$/g, "");
3397
+ cleaned = cleaned.trim();
3398
+ return cleaned || "An error occurred.";
3399
+ }
3400
+ function extractUrl(message) {
3401
+ const markdownMatch = /\[([^\]]+)\]\(([^)]+)\)/.exec(message);
3402
+ if (markdownMatch) return {
3403
+ url: markdownMatch[2],
3404
+ text: "See More"
3405
+ };
3406
+ const plainMatch = /(https?:\/\/[^\s)]+)/.exec(message);
3407
+ if (plainMatch) return {
3408
+ url: plainMatch[0].replace(/[.,;:'"]*$/, ""),
3409
+ text: "See More"
3410
+ };
3411
+ return null;
3412
+ }
3413
+ function BannerErrorDisplay({ bannerError, onDismiss }) {
3414
+ const [detailsExpanded, setDetailsExpanded] = (0, react.useState)(false);
3415
+ const colors = getErrorColors(getErrorSeverity(bannerError));
3416
+ const details = bannerError.details;
3417
+ const link = extractUrl(bannerError.message);
3418
+ return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3419
+ style: {
3420
+ position: "fixed",
3421
+ bottom: "20px",
3422
+ left: "50%",
3423
+ transform: "translateX(-50%)",
3424
+ zIndex: 9999,
3425
+ backgroundColor: colors.background,
3426
+ border: `1px solid ${colors.border}`,
3427
+ borderLeft: `4px solid ${colors.border}`,
3428
+ borderRadius: "8px",
3429
+ padding: "12px 16px",
3430
+ fontSize: "13px",
3431
+ boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
3432
+ backdropFilter: "blur(8px)",
3433
+ maxWidth: "min(90vw, 700px)",
3434
+ width: "100%",
3435
+ boxSizing: "border-box",
3436
+ overflow: "hidden"
3437
+ },
3438
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3439
+ style: {
3440
+ display: "flex",
3441
+ justifyContent: "space-between",
3442
+ alignItems: "center",
3443
+ gap: "10px"
3444
+ },
3445
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3446
+ style: {
3447
+ display: "flex",
3448
+ alignItems: "center",
3449
+ gap: "8px",
3450
+ flex: 1,
3451
+ minWidth: 0
3452
+ },
3453
+ children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
3454
+ width: "12px",
3455
+ height: "12px",
3456
+ borderRadius: "50%",
3457
+ backgroundColor: colors.border,
3458
+ flexShrink: 0
3459
+ } }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3460
+ style: {
3461
+ display: "flex",
3462
+ alignItems: "center",
3463
+ gap: "10px",
3464
+ flex: 1,
3465
+ minWidth: 0
3466
+ },
3467
+ children: [
3468
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
3469
+ style: {
3470
+ color: colors.text,
3471
+ lineHeight: "1.4",
3472
+ fontWeight: "400",
3473
+ fontSize: "13px",
3474
+ flex: 1,
3475
+ wordBreak: "break-all",
3476
+ overflowWrap: "break-word",
3477
+ maxWidth: "550px",
3478
+ overflow: "hidden",
3479
+ display: "-webkit-box",
3480
+ WebkitLineClamp: 10,
3481
+ WebkitBoxOrient: "vertical"
3482
+ },
3483
+ children: formatBannerMessage(bannerError.message)
3484
+ }),
3485
+ link && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3486
+ onClick: () => window.open(link.url, "_blank", "noopener,noreferrer"),
3487
+ style: {
3488
+ background: colors.border,
3489
+ color: "white",
3490
+ border: "none",
3491
+ borderRadius: "5px",
3492
+ padding: "4px 10px",
3493
+ fontSize: "11px",
3494
+ fontWeight: "500",
3495
+ cursor: "pointer",
3496
+ transition: "all 0.2s ease",
3497
+ flexShrink: 0
3498
+ },
3499
+ onMouseEnter: (e) => {
3500
+ e.currentTarget.style.opacity = "0.9";
3501
+ e.currentTarget.style.transform = "translateY(-1px)";
3502
+ },
3503
+ onMouseLeave: (e) => {
3504
+ e.currentTarget.style.opacity = "1";
3505
+ e.currentTarget.style.transform = "translateY(0)";
3506
+ },
3507
+ children: link.text
3508
+ }),
3509
+ details && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3510
+ onClick: () => setDetailsExpanded(!detailsExpanded),
3511
+ style: {
3512
+ background: "transparent",
3513
+ border: `1px solid ${colors.border}`,
3514
+ borderRadius: "5px",
3515
+ padding: "4px 10px",
3516
+ fontSize: "11px",
3517
+ fontWeight: "500",
3518
+ cursor: "pointer",
3519
+ color: colors.text,
3520
+ flexShrink: 0,
3521
+ transition: "all 0.2s ease"
3522
+ },
3523
+ onMouseEnter: (e) => {
3524
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
3525
+ },
3526
+ onMouseLeave: (e) => {
3527
+ e.currentTarget.style.background = "transparent";
3528
+ },
3529
+ children: detailsExpanded ? "Hide Details" : "Show Details"
3530
+ })
3531
+ ]
3532
+ })]
3533
+ }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
3534
+ onClick: onDismiss,
3535
+ style: {
3536
+ background: "transparent",
3537
+ border: "none",
3538
+ color: colors.text,
3539
+ cursor: "pointer",
3540
+ padding: "2px",
3541
+ borderRadius: "3px",
3542
+ fontSize: "14px",
3543
+ lineHeight: "1",
3544
+ opacity: .6,
3545
+ transition: "all 0.2s ease",
3546
+ flexShrink: 0
3547
+ },
3548
+ title: "Dismiss",
3549
+ onMouseEnter: (e) => {
3550
+ e.currentTarget.style.opacity = "1";
3551
+ e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
3552
+ },
3553
+ onMouseLeave: (e) => {
3554
+ e.currentTarget.style.opacity = "0.6";
3555
+ e.currentTarget.style.background = "transparent";
3556
+ },
3557
+ children: "x"
3558
+ })]
3559
+ }), detailsExpanded && details && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3560
+ style: {
3561
+ marginTop: "10px",
3562
+ padding: "10px",
3563
+ background: "rgba(0, 0, 0, 0.04)",
3564
+ borderRadius: "6px",
3565
+ fontSize: "11px",
3566
+ fontFamily: "monospace",
3567
+ color: colors.text,
3568
+ lineHeight: "1.5",
3569
+ maxHeight: "200px",
3570
+ overflowY: "auto",
3571
+ whiteSpace: "pre-wrap",
3572
+ wordBreak: "break-all"
3573
+ },
3574
+ children: [
3575
+ details.code && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
3576
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Code:" }),
3577
+ " ",
3578
+ details.code
3579
+ ] }),
3580
+ details.originalMessage && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3581
+ style: { marginTop: "4px" },
3582
+ children: [
3583
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Message:" }),
3584
+ " ",
3585
+ details.originalMessage
3586
+ ]
3587
+ }),
3588
+ details.context && Object.keys(details.context).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3589
+ style: { marginTop: "4px" },
3590
+ children: [
3591
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Context:" }),
3592
+ " ",
3593
+ JSON.stringify(details.context, null, 2)
3594
+ ]
3595
+ }),
3596
+ details.stack && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
3597
+ style: {
3598
+ marginTop: "4px",
3599
+ opacity: .7
3600
+ },
3601
+ children: [
3602
+ /* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Stack:" }),
3603
+ "\n",
3604
+ details.stack
3605
+ ]
3606
+ })
3607
+ ]
3608
+ })]
3609
+ });
3610
+ }
2251
3611
  function ToastProvider({ enabled, children }) {
2252
3612
  const [toasts, setToasts] = (0, react.useState)([]);
2253
3613
  const [bannerError, setBannerErrorState] = (0, react.useState)(null);
@@ -2286,156 +3646,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
2286
3646
  };
2287
3647
  return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ToastContext.Provider, {
2288
3648
  value,
2289
- children: [bannerError && (() => {
2290
- const colors = getErrorColors(getErrorSeverity(bannerError));
2291
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2292
- style: {
2293
- position: "fixed",
2294
- bottom: "20px",
2295
- left: "50%",
2296
- transform: "translateX(-50%)",
2297
- zIndex: 9999,
2298
- backgroundColor: colors.background,
2299
- border: `1px solid ${colors.border}`,
2300
- borderLeft: `4px solid ${colors.border}`,
2301
- borderRadius: "8px",
2302
- padding: "12px 16px",
2303
- fontSize: "13px",
2304
- boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
2305
- backdropFilter: "blur(8px)",
2306
- maxWidth: "min(90vw, 700px)",
2307
- width: "100%",
2308
- boxSizing: "border-box",
2309
- overflow: "hidden"
2310
- },
2311
- children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2312
- style: {
2313
- display: "flex",
2314
- justifyContent: "space-between",
2315
- alignItems: "center",
2316
- gap: "10px"
2317
- },
2318
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2319
- style: {
2320
- display: "flex",
2321
- alignItems: "center",
2322
- gap: "8px",
2323
- flex: 1,
2324
- minWidth: 0
2325
- },
2326
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
2327
- width: "12px",
2328
- height: "12px",
2329
- borderRadius: "50%",
2330
- backgroundColor: colors.border,
2331
- flexShrink: 0
2332
- } }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
2333
- style: {
2334
- display: "flex",
2335
- alignItems: "center",
2336
- gap: "10px",
2337
- flex: 1,
2338
- minWidth: 0
2339
- },
2340
- children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
2341
- style: {
2342
- color: colors.text,
2343
- lineHeight: "1.4",
2344
- fontWeight: "400",
2345
- fontSize: "13px",
2346
- flex: 1,
2347
- wordBreak: "break-all",
2348
- overflowWrap: "break-word",
2349
- maxWidth: "550px",
2350
- overflow: "hidden",
2351
- display: "-webkit-box",
2352
- WebkitLineClamp: 10,
2353
- WebkitBoxOrient: "vertical"
2354
- },
2355
- children: (() => {
2356
- let message = bannerError.message;
2357
- const jsonMatch = message.match(/'message':\s*'([^']+)'/);
2358
- if (jsonMatch) return jsonMatch[1];
2359
- message = message.split(" - ")[0];
2360
- message = message.split(": Error code")[0];
2361
- message = message.replace(/:\s*\d{3}$/, "");
2362
- message = message.replace(/See more:.*$/g, "");
2363
- message = message.trim();
2364
- return message || "Configuration error occurred.";
2365
- })()
2366
- }), (() => {
2367
- const message = bannerError.message;
2368
- const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
2369
- const plainUrlRegex = /(https?:\/\/[^\s)]+)/g;
2370
- let url = null;
2371
- let buttonText = "See More";
2372
- const markdownMatch = markdownLinkRegex.exec(message);
2373
- if (markdownMatch) {
2374
- url = markdownMatch[2];
2375
- buttonText = "See More";
2376
- } else {
2377
- const urlMatch = plainUrlRegex.exec(message);
2378
- if (urlMatch) {
2379
- url = urlMatch[0].replace(/[.,;:'"]*$/, "");
2380
- buttonText = "See More";
2381
- }
2382
- }
2383
- if (!url) return null;
2384
- return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2385
- onClick: () => window.open(url, "_blank", "noopener,noreferrer"),
2386
- style: {
2387
- background: colors.border,
2388
- color: "white",
2389
- border: "none",
2390
- borderRadius: "5px",
2391
- padding: "4px 10px",
2392
- fontSize: "11px",
2393
- fontWeight: "500",
2394
- cursor: "pointer",
2395
- transition: "all 0.2s ease",
2396
- flexShrink: 0
2397
- },
2398
- onMouseEnter: (e) => {
2399
- e.currentTarget.style.opacity = "0.9";
2400
- e.currentTarget.style.transform = "translateY(-1px)";
2401
- },
2402
- onMouseLeave: (e) => {
2403
- e.currentTarget.style.opacity = "1";
2404
- e.currentTarget.style.transform = "translateY(0)";
2405
- },
2406
- children: buttonText
2407
- });
2408
- })()]
2409
- })]
2410
- }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
2411
- onClick: () => setBannerError(null),
2412
- style: {
2413
- background: "transparent",
2414
- border: "none",
2415
- color: colors.text,
2416
- cursor: "pointer",
2417
- padding: "2px",
2418
- borderRadius: "3px",
2419
- fontSize: "14px",
2420
- lineHeight: "1",
2421
- opacity: .6,
2422
- transition: "all 0.2s ease",
2423
- flexShrink: 0
2424
- },
2425
- title: "Dismiss",
2426
- onMouseEnter: (e) => {
2427
- e.currentTarget.style.opacity = "1";
2428
- e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
2429
- },
2430
- onMouseLeave: (e) => {
2431
- e.currentTarget.style.opacity = "0.6";
2432
- e.currentTarget.style.background = "transparent";
2433
- },
2434
- children: "×"
2435
- })]
2436
- })
2437
- });
2438
- })(), children]
3649
+ children: [bannerError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerErrorDisplay, {
3650
+ bannerError,
3651
+ onDismiss: () => setBannerError(null)
3652
+ }), children]
2439
3653
  });
2440
3654
  }
2441
3655
 
@@ -3476,12 +4690,21 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3476
4690
  const { agent } = useAgent({ agentId: resolvedAgentId });
3477
4691
  usePredictStateSubscription(agent);
3478
4692
  (0, react.useEffect)(() => {
3479
- const subscription = copilotkit.subscribe({ onError: ({ error }) => {
3480
- setBannerError(new _copilotkit_shared.CopilotKitLowLevelError({
4693
+ const subscription = copilotkit.subscribe({ onError: ({ error, code, context }) => {
4694
+ if (error.name === "AbortError" || error.message === "Fetch is aborted" || error.message === "signal is aborted without reason" || error.message === "component unmounted" || !error.message) return;
4695
+ if (process.env.NODE_ENV === "development") console.error("[CopilotKit] Agent error:", error.message, "\n Code:", code, "\n Context:", context, "\n Stack:", error.stack);
4696
+ const ckError = new _copilotkit_shared.CopilotKitLowLevelError({
3481
4697
  error,
3482
4698
  message: error.message,
3483
4699
  url: typeof window !== "undefined" ? window.location.href : ""
3484
- }));
4700
+ });
4701
+ ckError.details = {
4702
+ code,
4703
+ context,
4704
+ stack: error.stack,
4705
+ originalMessage: error.message
4706
+ };
4707
+ setBannerError(ckError);
3485
4708
  } });
3486
4709
  return () => {
3487
4710
  subscription.unsubscribe();
@@ -3967,7 +5190,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
3967
5190
  children: [
3968
5191
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotListeners, {}),
3969
5192
  /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitErrorBridge, {}),
3970
- /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CoAgentStateRendersProvider, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessagesTapProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CopilotMessages, { children: [memoizedChildren, /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RegisteredActionsRenderer, {})] }) }), bannerError && showDevConsole && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBanner, {
5193
+ /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CoAgentStateRendersProvider, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MessagesTapProvider, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(CopilotMessages, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(react.default.Fragment, { children: memoizedChildren }, "children"), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RegisteredActionsRenderer, {}, "actions")] }) }), bannerError && showDevConsole && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UsageBanner, {
3971
5194
  severity: bannerError.severity,
3972
5195
  message: bannerError.message,
3973
5196
  onClose: () => setBannerError(null),
@@ -4037,7 +5260,11 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4037
5260
  const existingConfig = useCopilotChatConfiguration();
4038
5261
  const [agentAvailable, setAgentAvailable] = (0, react.useState)(false);
4039
5262
  const resolvedAgentId = (_existingConfig$agent = existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.agentId) !== null && _existingConfig$agent !== void 0 ? _existingConfig$agent : "default";
4040
- const { agent } = useAgent({ agentId: resolvedAgentId });
5263
+ const { agent } = useAgent({
5264
+ agentId: resolvedAgentId,
5265
+ threadId: existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId
5266
+ });
5267
+ const lastConnectedAgentRef = (0, react.useRef)(null);
4041
5268
  (0, react.useEffect)(() => {
4042
5269
  let detached = false;
4043
5270
  const connectAbortController = new AbortController();
@@ -4052,11 +5279,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
4052
5279
  if (error instanceof _ag_ui_client.AGUIConnectNotImplementedError) {} else console.error("CopilotChat: connectAgent failed", error);
4053
5280
  }
4054
5281
  };
4055
- if (agent && (existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId) && agent.threadId !== existingConfig.threadId && copilotkit.runtimeConnectionStatus === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) {
4056
- agent.threadId = existingConfig.threadId;
5282
+ if (agent && agent !== lastConnectedAgentRef.current && copilotkit.runtimeConnectionStatus === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) {
5283
+ lastConnectedAgentRef.current = agent;
4057
5284
  connect(agent);
4058
5285
  }
4059
5286
  return () => {
5287
+ lastConnectedAgentRef.current = null;
4060
5288
  detached = true;
4061
5289
  connectAbortController.abort();
4062
5290
  agent === null || agent === void 0 || agent.detachActiveRun();