@copilotkit/react-core 1.55.0-next.9 → 1.55.1-next.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.
- package/CHANGELOG.md +46 -6
- package/dist/{copilotkit-DeOzjPsb.mjs → copilotkit-BY5S1-0P.mjs} +2402 -552
- package/dist/copilotkit-BY5S1-0P.mjs.map +1 -0
- package/dist/{copilotkit-BqcyhQjT.d.mts → copilotkit-BuhSUZHb.d.mts} +228 -17
- package/dist/copilotkit-BuhSUZHb.d.mts.map +1 -0
- package/dist/{copilotkit-BDNjFNmk.cjs → copilotkit-Bz5-ImDl.cjs} +2421 -541
- package/dist/copilotkit-Bz5-ImDl.cjs.map +1 -0
- package/dist/{copilotkit-l-IBF4Xp.d.cts → copilotkit-dwDWYpya.d.cts} +228 -17
- package/dist/copilotkit-dwDWYpya.d.cts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +1400 -238
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/index.cjs +13 -1
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +3 -3
- package/dist/v2/index.d.mts +3 -3
- package/dist/v2/index.mjs +3 -2
- package/dist/v2/index.umd.js +2442 -552
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +62 -54
- package/scripts/scope-preflight.mjs +1 -2
- package/src/components/CopilotListeners.tsx +41 -8
- package/src/components/copilot-provider/copilotkit-props.tsx +4 -2
- package/src/components/toast/toast-provider.tsx +269 -194
- package/src/v2/__tests__/A2UIMessageRenderer.test.tsx +86 -22
- package/src/v2/__tests__/utils/test-helpers.tsx +67 -0
- package/src/v2/a2ui/A2UICatalogContext.tsx +79 -0
- package/src/v2/a2ui/A2UIMessageRenderer.tsx +125 -37
- package/src/v2/a2ui/A2UIToolCallRenderer.tsx +290 -0
- package/src/v2/components/CopilotKitInspector.tsx +2 -0
- package/src/v2/components/OpenGenerativeUIRenderer.tsx +598 -0
- package/src/v2/components/__tests__/OpenGenerativeUIRenderer.test.tsx +665 -0
- package/src/v2/components/chat/CopilotChat.tsx +193 -50
- package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +17 -2
- package/src/v2/components/chat/CopilotChatAttachmentQueue.tsx +481 -0
- package/src/v2/components/chat/CopilotChatAttachmentRenderer.tsx +139 -0
- package/src/v2/components/chat/CopilotChatInput.tsx +146 -77
- package/src/v2/components/chat/CopilotChatMessageView.tsx +253 -149
- package/src/v2/components/chat/CopilotChatSuggestionView.tsx +1 -0
- package/src/v2/components/chat/CopilotChatUserMessage.tsx +54 -0
- package/src/v2/components/chat/CopilotChatView.tsx +179 -66
- package/src/v2/components/chat/__tests__/CopilotChat.attachments.test.tsx +168 -0
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +63 -2
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +544 -1
- package/src/v2/components/chat/__tests__/CopilotChatPerf.e2e.test.tsx +268 -0
- package/src/v2/components/chat/__tests__/CopilotChatPropsRerender.e2e.test.tsx +249 -0
- package/src/v2/components/chat/__tests__/MCPAppsActivityRenderer.e2e.test.tsx +43 -2
- package/src/v2/components/chat/__tests__/copilot-chat-throttle.test.tsx +138 -0
- package/src/v2/components/chat/index.ts +9 -0
- package/src/v2/components/chat/scroll-element-context.ts +13 -0
- package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +1003 -0
- package/src/v2/hooks/__tests__/use-attachments.test.tsx +169 -0
- package/src/v2/hooks/__tests__/use-threads.test.tsx +54 -0
- package/src/v2/hooks/index.ts +5 -0
- package/src/v2/hooks/use-agent.tsx +95 -10
- package/src/v2/hooks/use-attachments.tsx +269 -0
- package/src/v2/hooks/use-frontend-tool.tsx +5 -2
- package/src/v2/hooks/use-render-activity-message.tsx +9 -2
- package/src/v2/hooks/use-threads.tsx +35 -15
- package/src/v2/index.ts +5 -1
- package/src/v2/lib/__tests__/processPartialHtml.test.ts +112 -0
- package/src/v2/lib/__tests__/slots.test.ts +56 -0
- package/src/v2/lib/processPartialHtml.ts +45 -0
- package/src/v2/lib/slots.tsx +42 -1
- package/src/v2/providers/CopilotChatConfigurationProvider.tsx +9 -3
- package/src/v2/providers/CopilotKitProvider.tsx +268 -32
- package/src/v2/providers/SandboxFunctionsContext.ts +10 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.sandboxFunctions.test.tsx +198 -0
- package/src/v2/providers/__tests__/CopilotKitProvider.test.tsx +71 -0
- package/src/v2/providers/index.ts +7 -0
- package/src/v2/styles/globals.css +2 -1
- package/src/v2/types/index.ts +1 -0
- package/src/v2/types/sandbox-function.ts +11 -0
- package/dist/copilotkit-BDNjFNmk.cjs.map +0 -1
- package/dist/copilotkit-BqcyhQjT.d.mts.map +0 -1
- package/dist/copilotkit-DeOzjPsb.mjs.map +0 -1
- package/dist/copilotkit-l-IBF4Xp.d.cts.map +0 -1
- package/src/v2/components/__tests__/license-warning-banner.test.tsx +0 -46
package/dist/v2/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('./index.css'), require('@copilotkit/core'), require('@ag-ui/client'), require('react'), require('tailwind-merge'), require('lucide-react'), require('@copilotkit/shared'), require('react/jsx-runtime'), require('@radix-ui/react-slot'), require('class-variance-authority'), require('clsx'), require('@radix-ui/react-tooltip'), require('@radix-ui/react-dropdown-menu'), require('streamdown'), require('zod'), require('@lit-labs/react'), require('@copilotkit/a2ui-renderer'), require('
|
|
5
|
-
typeof define === 'function' && define.amd ? define(['exports', './index.css', '@copilotkit/core', '@ag-ui/client', 'react', 'tailwind-merge', 'lucide-react', '@copilotkit/shared', 'react/jsx-runtime', '@radix-ui/react-slot', 'class-variance-authority', 'clsx', '@radix-ui/react-tooltip', '@radix-ui/react-dropdown-menu', 'streamdown', 'zod', '@lit-labs/react', '@copilotkit/a2ui-renderer', '
|
|
6
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitReactCoreV2 = {}), global.src_v2_index_css,global.CopilotKitCore,global.AgUIClient,global.React,global.tailwindMerge,global.lucideReact,global.CopilotKitShared,global.ReactJsxRuntime,global.RadixReactSlot,global.classVarianceAuthority,global.clsx,global.RadixReactTooltip,global.RadixReactDropdownMenu,global.streamdown,global.Zod,global.LitLabsReact,global.CopilotKitA2UIRenderer,global.
|
|
7
|
-
})(this, function(exports, src_v2_index_css, _copilotkit_core, _ag_ui_client, react, tailwind_merge, lucide_react, _copilotkit_shared, react_jsx_runtime, _radix_ui_react_slot, class_variance_authority, clsx, _radix_ui_react_tooltip, _radix_ui_react_dropdown_menu, streamdown, zod, _lit_labs_react, _copilotkit_a2ui_renderer,
|
|
4
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('./index.css'), require('@copilotkit/core'), require('@ag-ui/client'), require('react'), require('tailwind-merge'), require('lucide-react'), require('@copilotkit/shared'), require('react/jsx-runtime'), require('@radix-ui/react-slot'), require('class-variance-authority'), require('clsx'), require('@radix-ui/react-tooltip'), require('@radix-ui/react-dropdown-menu'), require('streamdown'), require('zod'), require('@lit-labs/react'), require('@copilotkit/a2ui-renderer'), require('zod-to-json-schema'), require('@tanstack/react-virtual'), require('react-dom'), require('use-stick-to-bottom')) :
|
|
5
|
+
typeof define === 'function' && define.amd ? define(['exports', './index.css', '@copilotkit/core', '@ag-ui/client', 'react', 'tailwind-merge', 'lucide-react', '@copilotkit/shared', 'react/jsx-runtime', '@radix-ui/react-slot', 'class-variance-authority', 'clsx', '@radix-ui/react-tooltip', '@radix-ui/react-dropdown-menu', 'streamdown', 'zod', '@lit-labs/react', '@copilotkit/a2ui-renderer', 'zod-to-json-schema', '@tanstack/react-virtual', 'react-dom', 'use-stick-to-bottom'], factory) :
|
|
6
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitReactCoreV2 = {}), global.src_v2_index_css,global.CopilotKitCore,global.AgUIClient,global.React,global.tailwindMerge,global.lucideReact,global.CopilotKitShared,global.ReactJsxRuntime,global.RadixReactSlot,global.classVarianceAuthority,global.clsx,global.RadixReactTooltip,global.RadixReactDropdownMenu,global.streamdown,global.Zod,global.LitLabsReact,global.CopilotKitA2UIRenderer,global.zod_to_json_schema,global._tanstack_react_virtual,global.ReactDOM,global.useStickToBottom));
|
|
7
|
+
})(this, function(exports, src_v2_index_css, _copilotkit_core, _ag_ui_client, react, tailwind_merge, lucide_react, _copilotkit_shared, react_jsx_runtime, _radix_ui_react_slot, class_variance_authority, clsx, _radix_ui_react_tooltip, _radix_ui_react_dropdown_menu, streamdown, zod, _lit_labs_react, _copilotkit_a2ui_renderer, zod_to_json_schema, _tanstack_react_virtual, react_dom, use_stick_to_bottom) {
|
|
8
8
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
9
9
|
//#region \0rolldown/runtime.js
|
|
10
10
|
var __create = Object.create;
|
|
@@ -37,13 +37,113 @@ react = __toESM(react);
|
|
|
37
37
|
_radix_ui_react_tooltip = __toESM(_radix_ui_react_tooltip);
|
|
38
38
|
_radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
39
39
|
|
|
40
|
+
//#region src/v2/lib/slots.tsx
|
|
41
|
+
/**
|
|
42
|
+
* Shallow equality comparison for objects.
|
|
43
|
+
*/
|
|
44
|
+
function shallowEqual(obj1, obj2) {
|
|
45
|
+
const keys1 = Object.keys(obj1);
|
|
46
|
+
const keys2 = Object.keys(obj2);
|
|
47
|
+
if (keys1.length !== keys2.length) return false;
|
|
48
|
+
for (const key of keys1) if (obj1[key] !== obj2[key]) return false;
|
|
49
|
+
return true;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Returns true only for plain JS objects (`{}`), excluding arrays, Dates,
|
|
53
|
+
* class instances, and other exotic objects that happen to have typeof "object".
|
|
54
|
+
*/
|
|
55
|
+
function isPlainObject(obj) {
|
|
56
|
+
return obj !== null && typeof obj === "object" && Object.prototype.toString.call(obj) === "[object Object]";
|
|
57
|
+
}
|
|
58
|
+
/**
|
|
59
|
+
* Returns the same reference as long as the value is shallowly equal to the
|
|
60
|
+
* previous render's value.
|
|
61
|
+
*
|
|
62
|
+
* - Identical references bail out immediately (O(1)).
|
|
63
|
+
* - Plain objects ({}) are shallow-compared key-by-key.
|
|
64
|
+
* - Arrays, Dates, class instances, functions, and primitives are compared by
|
|
65
|
+
* reference only — shallowEqual is never called on non-plain objects, which
|
|
66
|
+
* avoids incorrect equality for e.g. [1,2] vs [1,2] (different arrays).
|
|
67
|
+
*
|
|
68
|
+
* Typical use: stabilize inline slot props so MemoizedSlotWrapper's shallow
|
|
69
|
+
* equality check isn't defeated by a new object reference on every render.
|
|
70
|
+
*/
|
|
71
|
+
function useShallowStableRef(value) {
|
|
72
|
+
const ref = (0, react.useRef)(value);
|
|
73
|
+
if (ref.current === value) return ref.current;
|
|
74
|
+
if (isPlainObject(ref.current) && isPlainObject(value)) {
|
|
75
|
+
if (shallowEqual(ref.current, value)) return ref.current;
|
|
76
|
+
}
|
|
77
|
+
ref.current = value;
|
|
78
|
+
return ref.current;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Check if a value is a React component type (function, class, forwardRef, memo, etc.)
|
|
82
|
+
*/
|
|
83
|
+
function isReactComponentType(value) {
|
|
84
|
+
if (typeof value === "function") return true;
|
|
85
|
+
if (value && typeof value === "object" && "$$typeof" in value && !react.default.isValidElement(value)) return true;
|
|
86
|
+
return false;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Internal function to render a slot value as a React element (non-memoized).
|
|
90
|
+
*/
|
|
91
|
+
function renderSlotElement(slot, DefaultComponent, props) {
|
|
92
|
+
if (typeof slot === "string") {
|
|
93
|
+
const existingClassName = props.className;
|
|
94
|
+
return react.default.createElement(DefaultComponent, {
|
|
95
|
+
...props,
|
|
96
|
+
className: (0, tailwind_merge.twMerge)(existingClassName, slot)
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
if (isReactComponentType(slot)) return react.default.createElement(slot, props);
|
|
100
|
+
if (slot && typeof slot === "object" && !react.default.isValidElement(slot)) return react.default.createElement(DefaultComponent, {
|
|
101
|
+
...props,
|
|
102
|
+
...slot
|
|
103
|
+
});
|
|
104
|
+
return react.default.createElement(DefaultComponent, props);
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Internal memoized wrapper component for renderSlot.
|
|
108
|
+
* Uses forwardRef to support ref forwarding.
|
|
109
|
+
*/
|
|
110
|
+
const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function MemoizedSlotWrapper(props, ref) {
|
|
111
|
+
const { $slot, $component, ...rest } = props;
|
|
112
|
+
return renderSlotElement($slot, $component, ref !== null ? {
|
|
113
|
+
...rest,
|
|
114
|
+
ref
|
|
115
|
+
} : rest);
|
|
116
|
+
}), (prev, next) => {
|
|
117
|
+
if (prev.$slot !== next.$slot) return false;
|
|
118
|
+
if (prev.$component !== next.$component) return false;
|
|
119
|
+
const { $slot: _ps, $component: _pc, ...prevRest } = prev;
|
|
120
|
+
const { $slot: _ns, $component: _nc, ...nextRest } = next;
|
|
121
|
+
return shallowEqual(prevRest, nextRest);
|
|
122
|
+
});
|
|
123
|
+
/**
|
|
124
|
+
* Renders a slot value as a memoized React element.
|
|
125
|
+
* Automatically prevents unnecessary re-renders using shallow prop comparison.
|
|
126
|
+
* Supports ref forwarding.
|
|
127
|
+
*
|
|
128
|
+
* @example
|
|
129
|
+
* renderSlot(customInput, CopilotChatInput, { onSubmit: handleSubmit })
|
|
130
|
+
*/
|
|
131
|
+
function renderSlot(slot, DefaultComponent, props) {
|
|
132
|
+
return react.default.createElement(MemoizedSlotWrapper, {
|
|
133
|
+
...props,
|
|
134
|
+
$slot: slot,
|
|
135
|
+
$component: DefaultComponent
|
|
136
|
+
});
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
//#endregion
|
|
40
140
|
//#region src/v2/providers/CopilotChatConfigurationProvider.tsx
|
|
41
141
|
const CopilotChatDefaultLabels = {
|
|
42
142
|
chatInputPlaceholder: "Type a message...",
|
|
43
143
|
chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
|
|
44
144
|
chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
|
|
45
145
|
chatInputToolbarFinishTranscribeButtonLabel: "Finish",
|
|
46
|
-
chatInputToolbarAddButtonLabel: "Add
|
|
146
|
+
chatInputToolbarAddButtonLabel: "Add attachments",
|
|
47
147
|
chatInputToolbarToolsButtonLabel: "Tools",
|
|
48
148
|
assistantMessageToolbarCopyCodeLabel: "Copy",
|
|
49
149
|
assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
|
|
@@ -64,14 +164,15 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
64
164
|
const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, isModalDefaultOpen }) => {
|
|
65
165
|
var _ref, _parentConfig$isModal, _parentConfig$setModa;
|
|
66
166
|
const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
|
|
167
|
+
const stableLabels = useShallowStableRef(labels);
|
|
67
168
|
const mergedLabels = (0, react.useMemo)(() => {
|
|
68
169
|
var _parentConfig$labels;
|
|
69
170
|
return {
|
|
70
171
|
...CopilotChatDefaultLabels,
|
|
71
172
|
...(_parentConfig$labels = parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.labels) !== null && _parentConfig$labels !== void 0 ? _parentConfig$labels : {},
|
|
72
|
-
...
|
|
173
|
+
...stableLabels !== null && stableLabels !== void 0 ? stableLabels : {}
|
|
73
174
|
};
|
|
74
|
-
}, [
|
|
175
|
+
}, [stableLabels, parentConfig === null || parentConfig === void 0 ? void 0 : parentConfig.labels]);
|
|
75
176
|
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;
|
|
76
177
|
const resolvedThreadId = (0, react.useMemo)(() => {
|
|
77
178
|
if (threadId) return threadId;
|
|
@@ -120,9 +221,9 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
120
221
|
|
|
121
222
|
//#endregion
|
|
122
223
|
//#region src/v2/lib/utils.ts
|
|
123
|
-
const twMerge$
|
|
224
|
+
const twMerge$7 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
|
|
124
225
|
function cn(...inputs) {
|
|
125
|
-
return twMerge$
|
|
226
|
+
return twMerge$7((0, clsx.clsx)(inputs));
|
|
126
227
|
}
|
|
127
228
|
|
|
128
229
|
//#endregion
|
|
@@ -496,82 +597,11 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
496
597
|
});
|
|
497
598
|
CopilotChatAudioRecorder.displayName = "CopilotChatAudioRecorder";
|
|
498
599
|
|
|
499
|
-
//#endregion
|
|
500
|
-
//#region src/v2/lib/slots.tsx
|
|
501
|
-
/**
|
|
502
|
-
* Shallow equality comparison for objects.
|
|
503
|
-
*/
|
|
504
|
-
function shallowEqual(obj1, obj2) {
|
|
505
|
-
const keys1 = Object.keys(obj1);
|
|
506
|
-
const keys2 = Object.keys(obj2);
|
|
507
|
-
if (keys1.length !== keys2.length) return false;
|
|
508
|
-
for (const key of keys1) if (obj1[key] !== obj2[key]) return false;
|
|
509
|
-
return true;
|
|
510
|
-
}
|
|
511
|
-
/**
|
|
512
|
-
* Check if a value is a React component type (function, class, forwardRef, memo, etc.)
|
|
513
|
-
*/
|
|
514
|
-
function isReactComponentType(value) {
|
|
515
|
-
if (typeof value === "function") return true;
|
|
516
|
-
if (value && typeof value === "object" && "$$typeof" in value && !react.default.isValidElement(value)) return true;
|
|
517
|
-
return false;
|
|
518
|
-
}
|
|
519
|
-
/**
|
|
520
|
-
* Internal function to render a slot value as a React element (non-memoized).
|
|
521
|
-
*/
|
|
522
|
-
function renderSlotElement(slot, DefaultComponent, props) {
|
|
523
|
-
if (typeof slot === "string") {
|
|
524
|
-
const existingClassName = props.className;
|
|
525
|
-
return react.default.createElement(DefaultComponent, {
|
|
526
|
-
...props,
|
|
527
|
-
className: (0, tailwind_merge.twMerge)(existingClassName, slot)
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
if (isReactComponentType(slot)) return react.default.createElement(slot, props);
|
|
531
|
-
if (slot && typeof slot === "object" && !react.default.isValidElement(slot)) return react.default.createElement(DefaultComponent, {
|
|
532
|
-
...props,
|
|
533
|
-
...slot
|
|
534
|
-
});
|
|
535
|
-
return react.default.createElement(DefaultComponent, props);
|
|
536
|
-
}
|
|
537
|
-
/**
|
|
538
|
-
* Internal memoized wrapper component for renderSlot.
|
|
539
|
-
* Uses forwardRef to support ref forwarding.
|
|
540
|
-
*/
|
|
541
|
-
const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function MemoizedSlotWrapper(props, ref) {
|
|
542
|
-
const { $slot, $component, ...rest } = props;
|
|
543
|
-
return renderSlotElement($slot, $component, ref !== null ? {
|
|
544
|
-
...rest,
|
|
545
|
-
ref
|
|
546
|
-
} : rest);
|
|
547
|
-
}), (prev, next) => {
|
|
548
|
-
if (prev.$slot !== next.$slot) return false;
|
|
549
|
-
if (prev.$component !== next.$component) return false;
|
|
550
|
-
const { $slot: _ps, $component: _pc, ...prevRest } = prev;
|
|
551
|
-
const { $slot: _ns, $component: _nc, ...nextRest } = next;
|
|
552
|
-
return shallowEqual(prevRest, nextRest);
|
|
553
|
-
});
|
|
554
|
-
/**
|
|
555
|
-
* Renders a slot value as a memoized React element.
|
|
556
|
-
* Automatically prevents unnecessary re-renders using shallow prop comparison.
|
|
557
|
-
* Supports ref forwarding.
|
|
558
|
-
*
|
|
559
|
-
* @example
|
|
560
|
-
* renderSlot(customInput, CopilotChatInput, { onSubmit: handleSubmit })
|
|
561
|
-
*/
|
|
562
|
-
function renderSlot(slot, DefaultComponent, props) {
|
|
563
|
-
return react.default.createElement(MemoizedSlotWrapper, {
|
|
564
|
-
...props,
|
|
565
|
-
$slot: slot,
|
|
566
|
-
$component: DefaultComponent
|
|
567
|
-
});
|
|
568
|
-
}
|
|
569
|
-
|
|
570
600
|
//#endregion
|
|
571
601
|
//#region src/v2/components/chat/CopilotChatInput.tsx
|
|
572
602
|
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
573
603
|
const SLASH_MENU_ITEM_HEIGHT_PX = 40;
|
|
574
|
-
function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning = false, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, onAddFile, onChange, value, toolsMenu, autoFocus =
|
|
604
|
+
function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning = false, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, onAddFile, onChange, value, toolsMenu, autoFocus = false, positioning = "static", keyboardHeight = 0, containerRef, showDisclaimer, textArea, sendButton, startTranscribeButton, cancelTranscribeButton, finishTranscribeButton, addMenuButton, audioRecorder, disclaimer, children, className, ...props }) {
|
|
575
605
|
var _config$labels;
|
|
576
606
|
const isControlled = value !== void 0;
|
|
577
607
|
const [internalValue, setInternalValue] = (0, react.useState)(() => value !== null && value !== void 0 ? value : "");
|
|
@@ -601,6 +631,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
601
631
|
paddingLeft: 0,
|
|
602
632
|
paddingRight: 0
|
|
603
633
|
});
|
|
634
|
+
const containerCacheRef = (0, react.useRef)(null);
|
|
604
635
|
const commandItems = (0, react.useMemo)(() => {
|
|
605
636
|
const entries = [];
|
|
606
637
|
const seen = /* @__PURE__ */ new Set();
|
|
@@ -647,7 +678,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
647
678
|
}
|
|
648
679
|
if ((config === null || config === void 0 ? void 0 : config.isModalOpen) && !previousModalStateRef.current) {
|
|
649
680
|
var _inputRef$current;
|
|
650
|
-
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus();
|
|
681
|
+
(_inputRef$current = inputRef.current) === null || _inputRef$current === void 0 || _inputRef$current.focus({ preventScroll: true });
|
|
651
682
|
}
|
|
652
683
|
previousModalStateRef.current = config === null || config === void 0 ? void 0 : config.isModalOpen;
|
|
653
684
|
}, [config === null || config === void 0 ? void 0 : config.isModalOpen, autoFocus]);
|
|
@@ -894,6 +925,25 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
894
925
|
return nextLayout;
|
|
895
926
|
});
|
|
896
927
|
}, []);
|
|
928
|
+
const updateContainerCache = (0, react.useCallback)(() => {
|
|
929
|
+
const grid = gridRef.current;
|
|
930
|
+
const addContainer = addButtonContainerRef.current;
|
|
931
|
+
const actionsContainer = actionsContainerRef.current;
|
|
932
|
+
if (!grid || !addContainer || !actionsContainer) return null;
|
|
933
|
+
const gridStyles = window.getComputedStyle(grid);
|
|
934
|
+
const paddingLeft = parseFloat(gridStyles.paddingLeft) || 0;
|
|
935
|
+
const paddingRight = parseFloat(gridStyles.paddingRight) || 0;
|
|
936
|
+
const columnGap = parseFloat(gridStyles.columnGap) || 0;
|
|
937
|
+
const gridAvailableWidth = grid.clientWidth - paddingLeft - paddingRight;
|
|
938
|
+
if (gridAvailableWidth <= 0) return null;
|
|
939
|
+
const addWidth = addContainer.getBoundingClientRect().width;
|
|
940
|
+
const actionsWidth = actionsContainer.getBoundingClientRect().width;
|
|
941
|
+
const compactWidth = Math.max(gridAvailableWidth - addWidth - actionsWidth - columnGap * 2, 0);
|
|
942
|
+
if (compactWidth <= 0) return null;
|
|
943
|
+
const result = { compactWidth };
|
|
944
|
+
containerCacheRef.current = result;
|
|
945
|
+
return result;
|
|
946
|
+
}, []);
|
|
897
947
|
const evaluateLayout = (0, react.useCallback)(() => {
|
|
898
948
|
if (mode !== "input") {
|
|
899
949
|
updateLayout("compact");
|
|
@@ -919,32 +969,33 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
919
969
|
const renderedMultiline = baseline > 0 ? scrollHeight > baseline + 1 : false;
|
|
920
970
|
let shouldExpand = hasExplicitBreak || renderedMultiline;
|
|
921
971
|
if (!shouldExpand) {
|
|
922
|
-
|
|
923
|
-
const
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
if (gridAvailableWidth > 0) {
|
|
928
|
-
var _measurementCanvasRef;
|
|
929
|
-
const addWidth = addContainer.getBoundingClientRect().width;
|
|
930
|
-
const actionsWidth = actionsContainer.getBoundingClientRect().width;
|
|
931
|
-
const compactWidth = Math.max(gridAvailableWidth - addWidth - actionsWidth - columnGap * 2, 0);
|
|
932
|
-
const canvas = (_measurementCanvasRef = measurementCanvasRef.current) !== null && _measurementCanvasRef !== void 0 ? _measurementCanvasRef : document.createElement("canvas");
|
|
933
|
-
if (!measurementCanvasRef.current) measurementCanvasRef.current = canvas;
|
|
934
|
-
const context = canvas.getContext("2d");
|
|
935
|
-
if (context) {
|
|
972
|
+
var _containerCacheRef$cu;
|
|
973
|
+
const cache = (_containerCacheRef$cu = containerCacheRef.current) !== null && _containerCacheRef$cu !== void 0 ? _containerCacheRef$cu : updateContainerCache();
|
|
974
|
+
if (cache && cache.compactWidth > 0) {
|
|
975
|
+
const compactInnerWidth = Math.max(cache.compactWidth - (measurementsRef.current.paddingLeft || 0) - (measurementsRef.current.paddingRight || 0), 0);
|
|
976
|
+
if (compactInnerWidth > 0) {
|
|
936
977
|
const textareaStyles = window.getComputedStyle(textarea);
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
let longestWidth = 0;
|
|
942
|
-
for (const line of lines) {
|
|
943
|
-
const metrics = context.measureText(line || " ");
|
|
944
|
-
if (metrics.width > longestWidth) longestWidth = metrics.width;
|
|
945
|
-
}
|
|
946
|
-
if (longestWidth > compactInnerWidth) shouldExpand = true;
|
|
978
|
+
let font = textareaStyles.font;
|
|
979
|
+
if (!font) {
|
|
980
|
+
const { fontStyle, fontVariant, fontWeight, fontSize, lineHeight, fontFamily } = textareaStyles;
|
|
981
|
+
if (fontSize && fontFamily) font = `${fontStyle} ${fontVariant} ${fontWeight} ${fontSize}/${lineHeight} ${fontFamily}`;
|
|
947
982
|
}
|
|
983
|
+
if (font === null || font === void 0 ? void 0 : font.trim()) {
|
|
984
|
+
var _measurementCanvasRef;
|
|
985
|
+
const canvas = (_measurementCanvasRef = measurementCanvasRef.current) !== null && _measurementCanvasRef !== void 0 ? _measurementCanvasRef : document.createElement("canvas");
|
|
986
|
+
if (!measurementCanvasRef.current) measurementCanvasRef.current = canvas;
|
|
987
|
+
const context = canvas.getContext("2d");
|
|
988
|
+
if (context) {
|
|
989
|
+
context.font = font;
|
|
990
|
+
const lines = resolvedValue.length > 0 ? resolvedValue.split("\n") : [""];
|
|
991
|
+
let longestWidth = 0;
|
|
992
|
+
for (const line of lines) {
|
|
993
|
+
const metrics = context.measureText(line || " ");
|
|
994
|
+
if (metrics.width > longestWidth) longestWidth = metrics.width;
|
|
995
|
+
}
|
|
996
|
+
if (longestWidth > compactInnerWidth) shouldExpand = true;
|
|
997
|
+
} else if (process.env.NODE_ENV !== "production") console.warn("[CopilotChatInput] canvas.getContext('2d') returned null. Text-width-based expansion will be unavailable.");
|
|
998
|
+
} else if (process.env.NODE_ENV !== "production") console.warn("[CopilotChatInput] Could not resolve textarea font for layout measurement. Text-width-based expansion will be skipped until the next evaluation.");
|
|
948
999
|
}
|
|
949
1000
|
}
|
|
950
1001
|
}
|
|
@@ -954,6 +1005,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
954
1005
|
ensureMeasurements,
|
|
955
1006
|
mode,
|
|
956
1007
|
resolvedValue,
|
|
1008
|
+
updateContainerCache,
|
|
957
1009
|
updateLayout
|
|
958
1010
|
]);
|
|
959
1011
|
(0, react.useLayoutEffect)(() => {
|
|
@@ -966,11 +1018,17 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
966
1018
|
const addContainer = addButtonContainerRef.current;
|
|
967
1019
|
const actionsContainer = actionsContainerRef.current;
|
|
968
1020
|
if (!textarea || !grid || !addContainer || !actionsContainer) return;
|
|
969
|
-
const
|
|
1021
|
+
const containerTargets = new Set([
|
|
1022
|
+
grid,
|
|
1023
|
+
addContainer,
|
|
1024
|
+
actionsContainer
|
|
1025
|
+
]);
|
|
1026
|
+
const scheduleEvaluation = (invalidateCache) => {
|
|
970
1027
|
if (ignoreResizeRef.current) {
|
|
971
1028
|
ignoreResizeRef.current = false;
|
|
972
1029
|
return;
|
|
973
1030
|
}
|
|
1031
|
+
if (invalidateCache) containerCacheRef.current = null;
|
|
974
1032
|
if (typeof window === "undefined") {
|
|
975
1033
|
evaluateLayout();
|
|
976
1034
|
return;
|
|
@@ -981,8 +1039,13 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
981
1039
|
evaluateLayout();
|
|
982
1040
|
});
|
|
983
1041
|
};
|
|
984
|
-
const observer = new ResizeObserver(() => {
|
|
985
|
-
|
|
1042
|
+
const observer = new ResizeObserver((entries) => {
|
|
1043
|
+
let shouldInvalidate = false;
|
|
1044
|
+
for (const entry of entries) if (containerTargets.has(entry.target)) {
|
|
1045
|
+
shouldInvalidate = true;
|
|
1046
|
+
break;
|
|
1047
|
+
}
|
|
1048
|
+
scheduleEvaluation(shouldInvalidate);
|
|
986
1049
|
});
|
|
987
1050
|
observer.observe(grid);
|
|
988
1051
|
observer.observe(addContainer);
|
|
@@ -1133,6 +1196,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1133
1196
|
var _config$labels3;
|
|
1134
1197
|
const config = useCopilotChatConfiguration();
|
|
1135
1198
|
const labels = (_config$labels3 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels3 !== void 0 ? _config$labels3 : CopilotChatDefaultLabels;
|
|
1199
|
+
const [mounted, setMounted] = (0, react.useState)(false);
|
|
1200
|
+
(0, react.useEffect)(() => setMounted(true), []);
|
|
1136
1201
|
const menuItems = (0, react.useMemo)(() => {
|
|
1137
1202
|
const items = [];
|
|
1138
1203
|
if (onAddFile) items.push({
|
|
@@ -1163,26 +1228,28 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1163
1228
|
}), []);
|
|
1164
1229
|
const hasMenuItems = menuItems.length > 0;
|
|
1165
1230
|
const isDisabled = disabled || !hasMenuItems;
|
|
1231
|
+
const button = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
1232
|
+
type: "button",
|
|
1233
|
+
"data-testid": "copilot-add-menu-button",
|
|
1234
|
+
variant: "chatInputToolbarSecondary",
|
|
1235
|
+
size: "chatInputToolbarIcon",
|
|
1236
|
+
className: (0, tailwind_merge.twMerge)("cpk:ml-1", className),
|
|
1237
|
+
disabled: isDisabled,
|
|
1238
|
+
...props,
|
|
1239
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Plus, { className: "cpk:size-[20px]" })
|
|
1240
|
+
});
|
|
1241
|
+
if (!mounted) return button;
|
|
1166
1242
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(DropdownMenu, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
|
|
1167
1243
|
asChild: true,
|
|
1168
1244
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropdownMenuTrigger, {
|
|
1169
1245
|
asChild: true,
|
|
1170
|
-
children:
|
|
1171
|
-
type: "button",
|
|
1172
|
-
"data-testid": "copilot-add-menu-button",
|
|
1173
|
-
variant: "chatInputToolbarSecondary",
|
|
1174
|
-
size: "chatInputToolbarIcon",
|
|
1175
|
-
className: (0, tailwind_merge.twMerge)("cpk:ml-1", className),
|
|
1176
|
-
disabled: isDisabled,
|
|
1177
|
-
...props,
|
|
1178
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Plus, { className: "cpk:size-[20px]" })
|
|
1179
|
-
})
|
|
1246
|
+
children: button
|
|
1180
1247
|
})
|
|
1181
1248
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipContent, {
|
|
1182
1249
|
side: "bottom",
|
|
1183
1250
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("p", {
|
|
1184
1251
|
className: "cpk:flex cpk:items-center cpk:gap-1 cpk:text-xs cpk:font-medium",
|
|
1185
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Add
|
|
1252
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Add attachments" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("code", {
|
|
1186
1253
|
className: "cpk:rounded cpk:bg-[#4a4a4a] cpk:px-1 cpk:py-[1px] cpk:font-mono cpk:text-[11px] cpk:text-white cpk:dark:bg-[#e0e0e0] cpk:dark:text-black",
|
|
1187
1254
|
children: "/"
|
|
1188
1255
|
})]
|
|
@@ -1199,24 +1266,10 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1199
1266
|
const config = useCopilotChatConfiguration();
|
|
1200
1267
|
const labels = (_config$labels4 = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels4 !== void 0 ? _config$labels4 : CopilotChatDefaultLabels;
|
|
1201
1268
|
(0, react.useImperativeHandle)(ref, () => internalTextareaRef.current);
|
|
1202
|
-
(0, react.useEffect)(() => {
|
|
1203
|
-
const textarea = internalTextareaRef.current;
|
|
1204
|
-
if (!textarea) return;
|
|
1205
|
-
const handleFocus = () => {
|
|
1206
|
-
setTimeout(() => {
|
|
1207
|
-
textarea.scrollIntoView({
|
|
1208
|
-
behavior: "smooth",
|
|
1209
|
-
block: "nearest"
|
|
1210
|
-
});
|
|
1211
|
-
}, 300);
|
|
1212
|
-
};
|
|
1213
|
-
textarea.addEventListener("focus", handleFocus);
|
|
1214
|
-
return () => textarea.removeEventListener("focus", handleFocus);
|
|
1215
|
-
}, []);
|
|
1216
1269
|
(0, react.useEffect)(() => {
|
|
1217
1270
|
if (autoFocus) {
|
|
1218
1271
|
var _internalTextareaRef$;
|
|
1219
|
-
(_internalTextareaRef$ = internalTextareaRef.current) === null || _internalTextareaRef$ === void 0 || _internalTextareaRef$.focus();
|
|
1272
|
+
(_internalTextareaRef$ = internalTextareaRef.current) === null || _internalTextareaRef$ === void 0 || _internalTextareaRef$.focus({ preventScroll: true });
|
|
1220
1273
|
}
|
|
1221
1274
|
}, [autoFocus]);
|
|
1222
1275
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("textarea", {
|
|
@@ -1935,8 +1988,417 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
1935
1988
|
});
|
|
1936
1989
|
};
|
|
1937
1990
|
|
|
1991
|
+
//#endregion
|
|
1992
|
+
//#region src/v2/providers/SandboxFunctionsContext.ts
|
|
1993
|
+
const SandboxFunctionsContext = (0, react.createContext)([]);
|
|
1994
|
+
function useSandboxFunctions() {
|
|
1995
|
+
return (0, react.useContext)(SandboxFunctionsContext);
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
//#endregion
|
|
1999
|
+
//#region src/v2/lib/processPartialHtml.ts
|
|
2000
|
+
/**
|
|
2001
|
+
* Extracts all complete `<style>` blocks from the raw HTML.
|
|
2002
|
+
* Returns the concatenated style tags, suitable for injection into `<head>`.
|
|
2003
|
+
*/
|
|
2004
|
+
function extractCompleteStyles(html) {
|
|
2005
|
+
const matches = html.match(/<style\b[^>]*>[\s\S]*?<\/style>/gi);
|
|
2006
|
+
return matches ? matches.join("") : "";
|
|
2007
|
+
}
|
|
2008
|
+
/**
|
|
2009
|
+
* Processes raw accumulated HTML for safe preview via innerHTML injection.
|
|
2010
|
+
* Pure function, no DOM dependencies.
|
|
2011
|
+
*
|
|
2012
|
+
* Pipeline (order matters):
|
|
2013
|
+
* 1. Strip incomplete tag at end
|
|
2014
|
+
* 2. Strip complete <style>, <script>, and <head> blocks
|
|
2015
|
+
* 3. Strip incomplete <style>/<script>/<head> blocks
|
|
2016
|
+
* 4. Strip incomplete HTML entities
|
|
2017
|
+
* 5. Extract body content (or use full string if no <body>)
|
|
2018
|
+
*/
|
|
2019
|
+
function processPartialHtml(html) {
|
|
2020
|
+
let result = html;
|
|
2021
|
+
result = result.replace(/<[^>]*$/, "");
|
|
2022
|
+
result = result.replace(/<(style|script|head)\b[^>]*>[\s\S]*?<\/\1>/gi, "");
|
|
2023
|
+
result = result.replace(/<(style|script|head)\b[^>]*>[\s\S]*$/gi, "");
|
|
2024
|
+
result = result.replace(/&[a-zA-Z0-9#]*$/, "");
|
|
2025
|
+
const bodyMatch = result.match(/<body[^>]*>([\s\S]*)/i);
|
|
2026
|
+
if (bodyMatch) {
|
|
2027
|
+
result = bodyMatch[1];
|
|
2028
|
+
result = result.replace(/<\/body>[\s\S]*/i, "");
|
|
2029
|
+
}
|
|
2030
|
+
return result;
|
|
2031
|
+
}
|
|
2032
|
+
|
|
2033
|
+
//#endregion
|
|
2034
|
+
//#region src/v2/components/OpenGenerativeUIRenderer.tsx
|
|
2035
|
+
const OpenGenerativeUIActivityType = "open-generative-ui";
|
|
2036
|
+
const OpenGenerativeUIContentSchema = zod.z.object({
|
|
2037
|
+
initialHeight: zod.z.number().optional(),
|
|
2038
|
+
generating: zod.z.boolean().optional(),
|
|
2039
|
+
css: zod.z.string().optional(),
|
|
2040
|
+
cssComplete: zod.z.boolean().optional(),
|
|
2041
|
+
html: zod.z.array(zod.z.string()).optional(),
|
|
2042
|
+
htmlComplete: zod.z.boolean().optional(),
|
|
2043
|
+
jsFunctions: zod.z.string().optional(),
|
|
2044
|
+
jsFunctionsComplete: zod.z.boolean().optional(),
|
|
2045
|
+
jsExpressions: zod.z.array(zod.z.string()).optional(),
|
|
2046
|
+
jsExpressionsComplete: zod.z.boolean().optional()
|
|
2047
|
+
});
|
|
2048
|
+
/**
|
|
2049
|
+
* Schema for the generateSandboxedUi tool call arguments.
|
|
2050
|
+
* Used by the frontend tool renderer to display placeholder messages.
|
|
2051
|
+
*/
|
|
2052
|
+
const GenerateSandboxedUiArgsSchema = zod.z.object({
|
|
2053
|
+
initialHeight: zod.z.number().optional(),
|
|
2054
|
+
placeholderMessages: zod.z.array(zod.z.string()).optional(),
|
|
2055
|
+
css: zod.z.string().optional(),
|
|
2056
|
+
html: zod.z.string().optional(),
|
|
2057
|
+
jsFunctions: zod.z.string().optional(),
|
|
2058
|
+
jsExpressions: zod.z.array(zod.z.string()).optional()
|
|
2059
|
+
});
|
|
2060
|
+
const THROTTLE_MS = 1e3;
|
|
2061
|
+
/**
|
|
2062
|
+
* Returns true when the inner component should re-render immediately
|
|
2063
|
+
* (no throttle delay).
|
|
2064
|
+
*/
|
|
2065
|
+
function shouldFlushImmediately(prev, next) {
|
|
2066
|
+
var _next$jsExpressions$l, _next$jsExpressions, _prev$jsExpressions$l, _prev$jsExpressions, _next$html, _prev$html;
|
|
2067
|
+
if (next.cssComplete && (!prev || !prev.cssComplete)) return true;
|
|
2068
|
+
if (next.htmlComplete) return true;
|
|
2069
|
+
if (next.generating === false) return true;
|
|
2070
|
+
if (next.jsFunctions && (!prev || !prev.jsFunctions)) return true;
|
|
2071
|
+
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;
|
|
2072
|
+
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;
|
|
2073
|
+
return false;
|
|
2074
|
+
}
|
|
2075
|
+
/**
|
|
2076
|
+
* Outer wrapper — absorbs every parent re-render but only forwards
|
|
2077
|
+
* throttled content snapshots to the memoized inner component.
|
|
2078
|
+
*/
|
|
2079
|
+
const OpenGenerativeUIActivityRenderer = function OpenGenerativeUIActivityRenderer({ content }) {
|
|
2080
|
+
const latestContentRef = (0, react.useRef)(content);
|
|
2081
|
+
latestContentRef.current = content;
|
|
2082
|
+
const [throttledContent, setThrottledContent] = (0, react.useState)(content);
|
|
2083
|
+
const throttledContentRef = (0, react.useRef)(throttledContent);
|
|
2084
|
+
const timerRef = (0, react.useRef)(null);
|
|
2085
|
+
if (throttledContentRef.current !== content) {
|
|
2086
|
+
if (shouldFlushImmediately(throttledContentRef.current, content)) {
|
|
2087
|
+
if (timerRef.current !== null) {
|
|
2088
|
+
clearTimeout(timerRef.current);
|
|
2089
|
+
timerRef.current = null;
|
|
2090
|
+
}
|
|
2091
|
+
throttledContentRef.current = content;
|
|
2092
|
+
setThrottledContent(content);
|
|
2093
|
+
}
|
|
2094
|
+
}
|
|
2095
|
+
const flush = (0, react.useCallback)(() => {
|
|
2096
|
+
timerRef.current = null;
|
|
2097
|
+
const latest = latestContentRef.current;
|
|
2098
|
+
throttledContentRef.current = latest;
|
|
2099
|
+
setThrottledContent(latest);
|
|
2100
|
+
}, []);
|
|
2101
|
+
(0, react.useEffect)(() => {
|
|
2102
|
+
if (throttledContentRef.current === content) return;
|
|
2103
|
+
if (timerRef.current === null) timerRef.current = setTimeout(flush, THROTTLE_MS);
|
|
2104
|
+
}, [content, flush]);
|
|
2105
|
+
(0, react.useEffect)(() => {
|
|
2106
|
+
return () => {
|
|
2107
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
2108
|
+
};
|
|
2109
|
+
}, []);
|
|
2110
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(OpenGenerativeUIActivityRendererInner, { content: throttledContent });
|
|
2111
|
+
};
|
|
2112
|
+
function ensureHead(html) {
|
|
2113
|
+
if (/<head[\s>]/i.test(html)) return html;
|
|
2114
|
+
return `<head></head>${html}`;
|
|
2115
|
+
}
|
|
2116
|
+
function injectCssIntoHtml(html, css) {
|
|
2117
|
+
const headCloseIdx = html.indexOf("</head>");
|
|
2118
|
+
if (headCloseIdx !== -1) return html.slice(0, headCloseIdx) + `<style>${css}</style>` + html.slice(headCloseIdx);
|
|
2119
|
+
return `<head><style>${css}</style></head>${html}`;
|
|
2120
|
+
}
|
|
2121
|
+
const OpenGenerativeUIActivityRendererInner = react.default.memo(function OpenGenerativeUIActivityRendererInner({ content }) {
|
|
2122
|
+
var _content$initialHeigh, _content$html, _content$html2, _content$jsExpression;
|
|
2123
|
+
const initialHeight = (_content$initialHeigh = content.initialHeight) !== null && _content$initialHeigh !== void 0 ? _content$initialHeigh : 200;
|
|
2124
|
+
const [autoHeight, setAutoHeight] = (0, react.useState)(null);
|
|
2125
|
+
const sandboxFunctions = useSandboxFunctions();
|
|
2126
|
+
const localApi = (0, react.useMemo)(() => {
|
|
2127
|
+
const api = {};
|
|
2128
|
+
for (const fn of sandboxFunctions) api[fn.name] = fn.handler;
|
|
2129
|
+
return api;
|
|
2130
|
+
}, [sandboxFunctions]);
|
|
2131
|
+
const fullHtml = content.htmlComplete && ((_content$html = content.html) === null || _content$html === void 0 ? void 0 : _content$html.length) ? content.html.join("") : void 0;
|
|
2132
|
+
const css = content.cssComplete ? content.css : void 0;
|
|
2133
|
+
const cssReady = !!content.cssComplete;
|
|
2134
|
+
const partialHtml = !content.htmlComplete && ((_content$html2 = content.html) === null || _content$html2 === void 0 ? void 0 : _content$html2.length) ? content.html.join("") : void 0;
|
|
2135
|
+
const previewBody = partialHtml ? processPartialHtml(partialHtml) : void 0;
|
|
2136
|
+
const previewStyles = partialHtml ? extractCompleteStyles(partialHtml) : "";
|
|
2137
|
+
const hasPreview = cssReady && !!(previewBody === null || previewBody === void 0 ? void 0 : previewBody.trim());
|
|
2138
|
+
const hasVisibleSandbox = !!fullHtml || hasPreview;
|
|
2139
|
+
const containerRef = (0, react.useRef)(null);
|
|
2140
|
+
const sandboxRef = (0, react.useRef)(null);
|
|
2141
|
+
const previewSandboxRef = (0, react.useRef)(null);
|
|
2142
|
+
const previewReadyRef = (0, react.useRef)(false);
|
|
2143
|
+
const sandboxReadyRef = (0, react.useRef)(false);
|
|
2144
|
+
const executedIndexRef = (0, react.useRef)(0);
|
|
2145
|
+
const pendingQueueRef = (0, react.useRef)([]);
|
|
2146
|
+
const jsFunctionsInjectedRef = (0, react.useRef)(false);
|
|
2147
|
+
(0, react.useEffect)(() => {
|
|
2148
|
+
const container = containerRef.current;
|
|
2149
|
+
if (!container || fullHtml || !hasPreview || previewSandboxRef.current) return;
|
|
2150
|
+
let cancelled = false;
|
|
2151
|
+
import("@jetbrains/websandbox").then((mod) => {
|
|
2152
|
+
var _mod$default$default, _mod$default;
|
|
2153
|
+
if (cancelled) return;
|
|
2154
|
+
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({}, {
|
|
2155
|
+
frameContainer: container,
|
|
2156
|
+
frameContent: "<head></head><body></body>",
|
|
2157
|
+
allowAdditionalAttributes: ""
|
|
2158
|
+
});
|
|
2159
|
+
previewSandboxRef.current = sandbox;
|
|
2160
|
+
sandbox.iframe.style.width = "100%";
|
|
2161
|
+
sandbox.iframe.style.height = "100%";
|
|
2162
|
+
sandbox.iframe.style.border = "none";
|
|
2163
|
+
sandbox.iframe.style.backgroundColor = "transparent";
|
|
2164
|
+
sandbox.promise.then(() => {
|
|
2165
|
+
if (cancelled) return;
|
|
2166
|
+
previewReadyRef.current = true;
|
|
2167
|
+
sandbox.run(`
|
|
2168
|
+
var s = document.createElement('style');
|
|
2169
|
+
s.textContent = 'html, body { overflow: hidden !important; }';
|
|
2170
|
+
document.head.appendChild(s);
|
|
2171
|
+
`);
|
|
2172
|
+
const headParts = [];
|
|
2173
|
+
if (css) headParts.push(`<style>${css}</style>`);
|
|
2174
|
+
if (previewStyles) headParts.push(previewStyles);
|
|
2175
|
+
if (headParts.length) sandbox.run(`document.head.innerHTML = ${JSON.stringify(headParts.join(""))}`);
|
|
2176
|
+
if (previewBody) sandbox.run(`document.body.innerHTML = ${JSON.stringify(previewBody)}`);
|
|
2177
|
+
});
|
|
2178
|
+
}).catch((err) => {
|
|
2179
|
+
console.error("[OpenGenerativeUI] Failed to load sandbox module:", err);
|
|
2180
|
+
});
|
|
2181
|
+
return () => {
|
|
2182
|
+
cancelled = true;
|
|
2183
|
+
};
|
|
2184
|
+
}, [hasPreview, fullHtml]);
|
|
2185
|
+
(0, react.useEffect)(() => {
|
|
2186
|
+
if (!previewSandboxRef.current || !previewReadyRef.current) return;
|
|
2187
|
+
const headParts = [];
|
|
2188
|
+
if (css) headParts.push(`<style>${css}</style>`);
|
|
2189
|
+
if (previewStyles) headParts.push(previewStyles);
|
|
2190
|
+
if (headParts.length) previewSandboxRef.current.run(`document.head.innerHTML = ${JSON.stringify(headParts.join(""))}`);
|
|
2191
|
+
if (!previewBody) return;
|
|
2192
|
+
previewSandboxRef.current.run(`document.body.innerHTML = ${JSON.stringify(previewBody)}`);
|
|
2193
|
+
}, [
|
|
2194
|
+
previewBody,
|
|
2195
|
+
previewStyles,
|
|
2196
|
+
css
|
|
2197
|
+
]);
|
|
2198
|
+
(0, react.useEffect)(() => {
|
|
2199
|
+
const container = containerRef.current;
|
|
2200
|
+
if (!container || !fullHtml) return;
|
|
2201
|
+
if (previewSandboxRef.current) {
|
|
2202
|
+
previewSandboxRef.current.destroy();
|
|
2203
|
+
previewSandboxRef.current = null;
|
|
2204
|
+
previewReadyRef.current = false;
|
|
2205
|
+
}
|
|
2206
|
+
let cancelled = false;
|
|
2207
|
+
executedIndexRef.current = 0;
|
|
2208
|
+
jsFunctionsInjectedRef.current = false;
|
|
2209
|
+
sandboxReadyRef.current = false;
|
|
2210
|
+
pendingQueueRef.current = [];
|
|
2211
|
+
const htmlContent = css ? injectCssIntoHtml(fullHtml, css) : fullHtml;
|
|
2212
|
+
import("@jetbrains/websandbox").then((mod) => {
|
|
2213
|
+
var _mod$default$default2, _mod$default2;
|
|
2214
|
+
if (cancelled) return;
|
|
2215
|
+
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, {
|
|
2216
|
+
frameContainer: container,
|
|
2217
|
+
frameContent: ensureHead(htmlContent),
|
|
2218
|
+
allowAdditionalAttributes: ""
|
|
2219
|
+
});
|
|
2220
|
+
sandboxRef.current = sandbox;
|
|
2221
|
+
sandbox.iframe.style.width = "100%";
|
|
2222
|
+
sandbox.iframe.style.height = "100%";
|
|
2223
|
+
sandbox.iframe.style.border = "none";
|
|
2224
|
+
sandbox.iframe.style.backgroundColor = "transparent";
|
|
2225
|
+
sandbox.promise.then(() => {
|
|
2226
|
+
if (cancelled) return;
|
|
2227
|
+
sandboxReadyRef.current = true;
|
|
2228
|
+
sandbox.run(`
|
|
2229
|
+
var s = document.createElement('style');
|
|
2230
|
+
s.textContent = 'html, body { overflow: hidden !important; }';
|
|
2231
|
+
document.head.appendChild(s);
|
|
2232
|
+
`);
|
|
2233
|
+
const queue = pendingQueueRef.current;
|
|
2234
|
+
pendingQueueRef.current = [];
|
|
2235
|
+
for (const code of queue) sandbox.run(code);
|
|
2236
|
+
});
|
|
2237
|
+
}).catch((err) => {
|
|
2238
|
+
console.error("[OpenGenerativeUI] Failed to load sandbox module:", err);
|
|
2239
|
+
});
|
|
2240
|
+
return () => {
|
|
2241
|
+
cancelled = true;
|
|
2242
|
+
if (previewSandboxRef.current) {
|
|
2243
|
+
previewSandboxRef.current.destroy();
|
|
2244
|
+
previewSandboxRef.current = null;
|
|
2245
|
+
previewReadyRef.current = false;
|
|
2246
|
+
}
|
|
2247
|
+
if (sandboxRef.current) {
|
|
2248
|
+
sandboxRef.current.destroy();
|
|
2249
|
+
sandboxRef.current = null;
|
|
2250
|
+
}
|
|
2251
|
+
sandboxReadyRef.current = false;
|
|
2252
|
+
setAutoHeight(null);
|
|
2253
|
+
};
|
|
2254
|
+
}, [
|
|
2255
|
+
fullHtml,
|
|
2256
|
+
css,
|
|
2257
|
+
localApi
|
|
2258
|
+
]);
|
|
2259
|
+
(0, react.useEffect)(() => {
|
|
2260
|
+
if (!content.jsFunctions || jsFunctionsInjectedRef.current) return;
|
|
2261
|
+
jsFunctionsInjectedRef.current = true;
|
|
2262
|
+
const sandbox = sandboxRef.current;
|
|
2263
|
+
if (sandboxReadyRef.current && sandbox) sandbox.run(content.jsFunctions);
|
|
2264
|
+
else pendingQueueRef.current.push(content.jsFunctions);
|
|
2265
|
+
}, [content.jsFunctions]);
|
|
2266
|
+
(0, react.useEffect)(() => {
|
|
2267
|
+
const expressions = content.jsExpressions;
|
|
2268
|
+
if (!expressions || expressions.length === 0) return;
|
|
2269
|
+
const startIndex = executedIndexRef.current;
|
|
2270
|
+
if (startIndex >= expressions.length) return;
|
|
2271
|
+
const newExprs = expressions.slice(startIndex);
|
|
2272
|
+
executedIndexRef.current = expressions.length;
|
|
2273
|
+
const sandbox = sandboxRef.current;
|
|
2274
|
+
if (sandboxReadyRef.current && sandbox) (async () => {
|
|
2275
|
+
for (const expr of newExprs) await sandbox.run(expr);
|
|
2276
|
+
})();
|
|
2277
|
+
else pendingQueueRef.current.push(...newExprs);
|
|
2278
|
+
}, [(_content$jsExpression = content.jsExpressions) === null || _content$jsExpression === void 0 ? void 0 : _content$jsExpression.length]);
|
|
2279
|
+
const generationDone = content.generating === false;
|
|
2280
|
+
(0, react.useEffect)(() => {
|
|
2281
|
+
const sandbox = sandboxRef.current;
|
|
2282
|
+
if (!generationDone || !sandbox) return;
|
|
2283
|
+
let handled = false;
|
|
2284
|
+
const onMessage = (e) => {
|
|
2285
|
+
var _e$data;
|
|
2286
|
+
if (handled) return;
|
|
2287
|
+
if (e.source === sandbox.iframe.contentWindow && ((_e$data = e.data) === null || _e$data === void 0 ? void 0 : _e$data.type) === "__ck_resize") {
|
|
2288
|
+
handled = true;
|
|
2289
|
+
setAutoHeight(e.data.height);
|
|
2290
|
+
window.removeEventListener("message", onMessage);
|
|
2291
|
+
}
|
|
2292
|
+
};
|
|
2293
|
+
window.addEventListener("message", onMessage);
|
|
2294
|
+
const measureOnce = `
|
|
2295
|
+
(function() {
|
|
2296
|
+
var s = document.createElement('style');
|
|
2297
|
+
s.textContent = 'body { height: auto !important; min-height: 0 !important; }';
|
|
2298
|
+
document.head.appendChild(s);
|
|
2299
|
+
var h = document.body.scrollHeight;
|
|
2300
|
+
var cs = getComputedStyle(document.body);
|
|
2301
|
+
h += parseFloat(cs.marginTop) || 0;
|
|
2302
|
+
h += parseFloat(cs.marginBottom) || 0;
|
|
2303
|
+
s.remove();
|
|
2304
|
+
parent.postMessage({ type: "__ck_resize", height: Math.ceil(h) }, "*");
|
|
2305
|
+
})();
|
|
2306
|
+
`;
|
|
2307
|
+
if (sandboxReadyRef.current) sandbox.run(measureOnce);
|
|
2308
|
+
else pendingQueueRef.current.push(measureOnce);
|
|
2309
|
+
return () => {
|
|
2310
|
+
window.removeEventListener("message", onMessage);
|
|
2311
|
+
};
|
|
2312
|
+
}, [generationDone]);
|
|
2313
|
+
const height = autoHeight !== null && autoHeight !== void 0 ? autoHeight : initialHeight;
|
|
2314
|
+
const isGenerating = content.generating !== false;
|
|
2315
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2316
|
+
ref: containerRef,
|
|
2317
|
+
style: {
|
|
2318
|
+
position: "relative",
|
|
2319
|
+
width: "100%",
|
|
2320
|
+
height: `${height}px`,
|
|
2321
|
+
borderRadius: "8px",
|
|
2322
|
+
backgroundColor: hasVisibleSandbox ? "transparent" : "#f5f5f5",
|
|
2323
|
+
border: hasVisibleSandbox ? "none" : "1px solid #e0e0e0",
|
|
2324
|
+
display: hasVisibleSandbox ? "block" : "flex",
|
|
2325
|
+
alignItems: hasVisibleSandbox ? void 0 : "center",
|
|
2326
|
+
justifyContent: hasVisibleSandbox ? void 0 : "center",
|
|
2327
|
+
overflow: "hidden"
|
|
2328
|
+
},
|
|
2329
|
+
children: isGenerating && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2330
|
+
style: {
|
|
2331
|
+
position: "absolute",
|
|
2332
|
+
inset: 0,
|
|
2333
|
+
zIndex: 10,
|
|
2334
|
+
pointerEvents: "all",
|
|
2335
|
+
backgroundColor: "rgba(255, 255, 255, 0.5)",
|
|
2336
|
+
display: "flex",
|
|
2337
|
+
alignItems: "center",
|
|
2338
|
+
justifyContent: "center"
|
|
2339
|
+
},
|
|
2340
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("svg", {
|
|
2341
|
+
width: "48",
|
|
2342
|
+
height: "48",
|
|
2343
|
+
viewBox: "0 0 24 24",
|
|
2344
|
+
fill: "none",
|
|
2345
|
+
style: { animation: "ck-spin 1s linear infinite" },
|
|
2346
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("circle", {
|
|
2347
|
+
cx: "12",
|
|
2348
|
+
cy: "12",
|
|
2349
|
+
r: "10",
|
|
2350
|
+
stroke: "#e0e0e0",
|
|
2351
|
+
strokeWidth: "3"
|
|
2352
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
2353
|
+
d: "M12 2a10 10 0 0 1 10 10",
|
|
2354
|
+
stroke: "#999",
|
|
2355
|
+
strokeWidth: "3",
|
|
2356
|
+
strokeLinecap: "round"
|
|
2357
|
+
})]
|
|
2358
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `@keyframes ck-spin { to { transform: rotate(360deg) } }` })]
|
|
2359
|
+
})
|
|
2360
|
+
});
|
|
2361
|
+
}, (prev, next) => prev.content === next.content);
|
|
2362
|
+
/**
|
|
2363
|
+
* Frontend tool renderer for generateSandboxedUi.
|
|
2364
|
+
* Displays placeholder messages while the UI is being generated.
|
|
2365
|
+
*/
|
|
2366
|
+
const OpenGenerativeUIToolRenderer = function OpenGenerativeUIToolRenderer(props) {
|
|
2367
|
+
var _messages$visibleMess;
|
|
2368
|
+
const [visibleMessageIndex, setVisibleMessageIndex] = (0, react.useState)(0);
|
|
2369
|
+
const prevMessageCountRef = (0, react.useRef)(0);
|
|
2370
|
+
const messages = props.args.placeholderMessages;
|
|
2371
|
+
(0, react.useEffect)(() => {
|
|
2372
|
+
if (!messages || messages.length === 0) return;
|
|
2373
|
+
if (messages.length !== prevMessageCountRef.current) {
|
|
2374
|
+
prevMessageCountRef.current = messages.length;
|
|
2375
|
+
setVisibleMessageIndex(messages.length - 1);
|
|
2376
|
+
}
|
|
2377
|
+
if (props.status === _copilotkit_core.ToolCallStatus.Complete) return;
|
|
2378
|
+
const timer = setInterval(() => {
|
|
2379
|
+
setVisibleMessageIndex((i) => (i + 1) % messages.length);
|
|
2380
|
+
}, 5e3);
|
|
2381
|
+
return () => clearInterval(timer);
|
|
2382
|
+
}, [messages === null || messages === void 0 ? void 0 : messages.length, props.status]);
|
|
2383
|
+
if (props.status === _copilotkit_core.ToolCallStatus.Complete) return null;
|
|
2384
|
+
if (!messages || messages.length === 0) return null;
|
|
2385
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2386
|
+
style: {
|
|
2387
|
+
padding: "8px 12px",
|
|
2388
|
+
color: "#999",
|
|
2389
|
+
fontSize: "14px"
|
|
2390
|
+
},
|
|
2391
|
+
children: (_messages$visibleMess = messages[visibleMessageIndex]) !== null && _messages$visibleMess !== void 0 ? _messages$visibleMess : messages[0]
|
|
2392
|
+
});
|
|
2393
|
+
};
|
|
2394
|
+
|
|
1938
2395
|
//#endregion
|
|
1939
2396
|
//#region src/v2/a2ui/A2UIMessageRenderer.tsx
|
|
2397
|
+
/**
|
|
2398
|
+
* The container key used to wrap A2UI operations for explicit detection.
|
|
2399
|
+
* Must match A2UI_OPERATIONS_KEY in @ag-ui/a2ui-middleware and copilotkit.a2ui (Python).
|
|
2400
|
+
*/
|
|
2401
|
+
const A2UI_OPERATIONS_KEY = "a2ui_operations";
|
|
1940
2402
|
let initialized = false;
|
|
1941
2403
|
function ensureInitialized() {
|
|
1942
2404
|
if (!initialized) {
|
|
@@ -1946,25 +2408,23 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
1946
2408
|
}
|
|
1947
2409
|
}
|
|
1948
2410
|
function createA2UIMessageRenderer(options) {
|
|
1949
|
-
const { theme } = options;
|
|
2411
|
+
const { theme, catalog, loadingComponent } = options;
|
|
1950
2412
|
return {
|
|
1951
2413
|
activityType: "a2ui-surface",
|
|
1952
2414
|
content: zod.z.any(),
|
|
1953
2415
|
render: ({ content, agent }) => {
|
|
1954
2416
|
ensureInitialized();
|
|
1955
2417
|
const [operations, setOperations] = (0, react.useState)([]);
|
|
1956
|
-
const lastSignatureRef = (0, react.useRef)(null);
|
|
1957
2418
|
const { copilotkit } = useCopilotKit();
|
|
2419
|
+
const lastContentRef = (0, react.useRef)(null);
|
|
1958
2420
|
(0, react.useEffect)(() => {
|
|
1959
|
-
if (
|
|
1960
|
-
|
|
2421
|
+
if (content === lastContentRef.current) return;
|
|
2422
|
+
lastContentRef.current = content;
|
|
2423
|
+
const incoming = content === null || content === void 0 ? void 0 : content[A2UI_OPERATIONS_KEY];
|
|
2424
|
+
if (!content || !Array.isArray(incoming)) {
|
|
1961
2425
|
setOperations([]);
|
|
1962
2426
|
return;
|
|
1963
2427
|
}
|
|
1964
|
-
const incoming = content.operations;
|
|
1965
|
-
const signature = stringifyOperations(incoming);
|
|
1966
|
-
if (signature && signature === lastSignatureRef.current) return;
|
|
1967
|
-
lastSignatureRef.current = signature;
|
|
1968
2428
|
setOperations(incoming);
|
|
1969
2429
|
}, [content]);
|
|
1970
2430
|
const groupedOperations = (0, react.useMemo)(() => {
|
|
@@ -1977,7 +2437,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
1977
2437
|
}
|
|
1978
2438
|
return groups;
|
|
1979
2439
|
}, [operations]);
|
|
1980
|
-
if (!groupedOperations.size) return null;
|
|
2440
|
+
if (!groupedOperations.size) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(loadingComponent !== null && loadingComponent !== void 0 ? loadingComponent : DefaultA2UILoading, {});
|
|
1981
2441
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1982
2442
|
className: "cpk:flex cpk:min-h-0 cpk:flex-1 cpk:flex-col cpk:gap-6 cpk:overflow-auto cpk:py-6",
|
|
1983
2443
|
children: Array.from(groupedOperations.entries()).map(([surfaceId, ops]) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ReactSurfaceHost, {
|
|
@@ -1985,7 +2445,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
1985
2445
|
operations: ops,
|
|
1986
2446
|
theme,
|
|
1987
2447
|
agent,
|
|
1988
|
-
copilotkit
|
|
2448
|
+
copilotkit,
|
|
2449
|
+
catalog
|
|
1989
2450
|
}, surfaceId))
|
|
1990
2451
|
});
|
|
1991
2452
|
}
|
|
@@ -1995,15 +2456,15 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
1995
2456
|
* Renders a single A2UI surface using the React renderer.
|
|
1996
2457
|
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
1997
2458
|
*/
|
|
1998
|
-
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit }) {
|
|
2459
|
+
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog }) {
|
|
1999
2460
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2000
2461
|
className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
|
|
2001
2462
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
|
|
2002
2463
|
onAction: (0, react.useCallback)(async (message) => {
|
|
2003
2464
|
if (!agent) return;
|
|
2465
|
+
message.userAction;
|
|
2004
2466
|
try {
|
|
2005
2467
|
var _copilotkit$propertie;
|
|
2006
|
-
console.info("[A2UI] Action dispatched", message.userAction);
|
|
2007
2468
|
copilotkit.setProperties({
|
|
2008
2469
|
...(_copilotkit$propertie = copilotkit.properties) !== null && _copilotkit$propertie !== void 0 ? _copilotkit$propertie : {},
|
|
2009
2470
|
a2uiAction: message
|
|
@@ -2017,48 +2478,503 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2017
2478
|
}
|
|
2018
2479
|
}, [agent, copilotkit]),
|
|
2019
2480
|
theme,
|
|
2481
|
+
catalog,
|
|
2020
2482
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceMessageProcessor, {
|
|
2021
2483
|
surfaceId,
|
|
2022
2484
|
operations
|
|
2023
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2024
|
-
surfaceId,
|
|
2025
|
-
className: "cpk:flex cpk:flex-1"
|
|
2026
|
-
})]
|
|
2485
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UISurfaceOrError, { surfaceId })]
|
|
2027
2486
|
})
|
|
2028
2487
|
});
|
|
2029
2488
|
}
|
|
2030
2489
|
/**
|
|
2490
|
+
* Renders the A2UI surface, or an error message if processing failed.
|
|
2491
|
+
* Must be a child of A2UIProvider to access the error state.
|
|
2492
|
+
*/
|
|
2493
|
+
function A2UISurfaceOrError({ surfaceId }) {
|
|
2494
|
+
const error = (0, _copilotkit_a2ui_renderer.useA2UIError)();
|
|
2495
|
+
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2496
|
+
className: "cpk:rounded-lg cpk:border cpk:border-red-200 cpk:bg-red-50 cpk:p-3 cpk:text-sm cpk:text-red-700",
|
|
2497
|
+
children: ["A2UI render error: ", error]
|
|
2498
|
+
});
|
|
2499
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_a2ui_renderer.A2UIRenderer, {
|
|
2500
|
+
surfaceId,
|
|
2501
|
+
className: "cpk:flex cpk:flex-1"
|
|
2502
|
+
});
|
|
2503
|
+
}
|
|
2504
|
+
/**
|
|
2031
2505
|
* Processes A2UI operations into the provider's message processor.
|
|
2032
2506
|
* Must be a child of A2UIProvider to access the actions context.
|
|
2033
2507
|
*/
|
|
2034
2508
|
function SurfaceMessageProcessor({ surfaceId, operations }) {
|
|
2035
|
-
const { processMessages } = (0, _copilotkit_a2ui_renderer.useA2UIActions)();
|
|
2036
|
-
const
|
|
2509
|
+
const { processMessages, getSurface } = (0, _copilotkit_a2ui_renderer.useA2UIActions)();
|
|
2510
|
+
const lastHashRef = (0, react.useRef)("");
|
|
2037
2511
|
(0, react.useEffect)(() => {
|
|
2038
|
-
const
|
|
2039
|
-
if (
|
|
2040
|
-
|
|
2041
|
-
processMessages(operations);
|
|
2512
|
+
const hash = JSON.stringify(operations);
|
|
2513
|
+
if (hash === lastHashRef.current) return;
|
|
2514
|
+
lastHashRef.current = hash;
|
|
2515
|
+
processMessages(getSurface(surfaceId) ? operations.filter((op) => !(op === null || op === void 0 ? void 0 : op.createSurface)) : operations);
|
|
2042
2516
|
}, [
|
|
2043
2517
|
processMessages,
|
|
2518
|
+
getSurface,
|
|
2044
2519
|
surfaceId,
|
|
2045
2520
|
operations
|
|
2046
2521
|
]);
|
|
2047
2522
|
return null;
|
|
2048
2523
|
}
|
|
2049
|
-
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
|
|
2054
|
-
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2524
|
+
/**
|
|
2525
|
+
* Default loading component shown while an A2UI surface is generating.
|
|
2526
|
+
* Displays an animated shimmer skeleton.
|
|
2527
|
+
*/
|
|
2528
|
+
function DefaultA2UILoading() {
|
|
2529
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2530
|
+
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",
|
|
2531
|
+
style: { minHeight: 120 },
|
|
2532
|
+
children: [
|
|
2533
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2534
|
+
className: "cpk:flex cpk:items-center cpk:gap-2",
|
|
2535
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2536
|
+
className: "cpk:h-3 cpk:w-3 cpk:rounded-full cpk:bg-gray-200",
|
|
2537
|
+
style: { animation: "cpk-a2ui-pulse 1.5s ease-in-out infinite" }
|
|
2538
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2539
|
+
className: "cpk:text-xs cpk:font-medium cpk:text-gray-400",
|
|
2540
|
+
children: "Generating UI..."
|
|
2541
|
+
})]
|
|
2542
|
+
}),
|
|
2543
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2544
|
+
className: "cpk:flex cpk:flex-col cpk:gap-2",
|
|
2545
|
+
children: [
|
|
2546
|
+
.8,
|
|
2547
|
+
.6,
|
|
2548
|
+
.4
|
|
2549
|
+
].map((width, i) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2550
|
+
className: "cpk:h-3 cpk:rounded cpk:bg-gray-200/70",
|
|
2551
|
+
style: {
|
|
2552
|
+
width: `${width * 100}%`,
|
|
2553
|
+
animation: `cpk-a2ui-pulse 1.5s ease-in-out ${i * .15}s infinite`
|
|
2554
|
+
}
|
|
2555
|
+
}, i))
|
|
2556
|
+
}),
|
|
2557
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
|
|
2558
|
+
@keyframes cpk-a2ui-pulse {
|
|
2559
|
+
0%, 100% { opacity: 0.4; }
|
|
2560
|
+
50% { opacity: 1; }
|
|
2561
|
+
}
|
|
2562
|
+
` })
|
|
2563
|
+
]
|
|
2564
|
+
});
|
|
2565
|
+
}
|
|
2566
|
+
function getOperationSurfaceId(operation) {
|
|
2567
|
+
var _ref, _ref2, _ref3, _operation$createSurf, _operation$createSurf2, _operation$updateComp, _operation$updateData, _operation$deleteSurf;
|
|
2568
|
+
if (!operation || typeof operation !== "object") return null;
|
|
2569
|
+
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
2570
|
+
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;
|
|
2571
|
+
}
|
|
2572
|
+
|
|
2573
|
+
//#endregion
|
|
2574
|
+
//#region src/v2/types/defineToolCallRenderer.ts
|
|
2575
|
+
function defineToolCallRenderer(def) {
|
|
2576
|
+
const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
|
|
2577
|
+
return {
|
|
2578
|
+
name: def.name,
|
|
2579
|
+
args: argsSchema,
|
|
2580
|
+
render: def.render,
|
|
2581
|
+
...def.agentId ? { agentId: def.agentId } : {}
|
|
2582
|
+
};
|
|
2583
|
+
}
|
|
2584
|
+
|
|
2585
|
+
//#endregion
|
|
2586
|
+
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
2587
|
+
/**
|
|
2588
|
+
* Tool name used by the dynamic A2UI generation secondary LLM.
|
|
2589
|
+
* This renderer is auto-registered when A2UI is enabled.
|
|
2590
|
+
*/
|
|
2591
|
+
const RENDER_A2UI_TOOL_NAME = "render_a2ui";
|
|
2592
|
+
/**
|
|
2593
|
+
* Built-in progress indicator for dynamic A2UI generation.
|
|
2594
|
+
* Shows a skeleton wireframe that progressively reveals as tokens stream in.
|
|
2595
|
+
*
|
|
2596
|
+
* Registered automatically when A2UI is enabled. Users can override by
|
|
2597
|
+
* providing their own `useRenderTool({ name: "render_a2ui", ... })`.
|
|
2598
|
+
*/
|
|
2599
|
+
function A2UIProgressIndicator({ parameters }) {
|
|
2600
|
+
const lastRef = (0, react.useRef)({
|
|
2601
|
+
time: 0,
|
|
2602
|
+
tokens: 0
|
|
2603
|
+
});
|
|
2604
|
+
const now = Date.now();
|
|
2605
|
+
let { tokens } = lastRef.current;
|
|
2606
|
+
if (now - lastRef.current.time > 200) {
|
|
2607
|
+
const chars = JSON.stringify(parameters !== null && parameters !== void 0 ? parameters : {}).length;
|
|
2608
|
+
tokens = Math.round(chars / 4);
|
|
2609
|
+
lastRef.current = {
|
|
2610
|
+
time: now,
|
|
2611
|
+
tokens
|
|
2612
|
+
};
|
|
2613
|
+
}
|
|
2614
|
+
const phase = tokens < 50 ? 0 : tokens < 200 ? 1 : tokens < 400 ? 2 : 3;
|
|
2615
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2616
|
+
style: {
|
|
2617
|
+
margin: "12px 0",
|
|
2618
|
+
maxWidth: 320
|
|
2619
|
+
},
|
|
2620
|
+
children: [
|
|
2621
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2622
|
+
style: {
|
|
2623
|
+
position: "relative",
|
|
2624
|
+
overflow: "hidden",
|
|
2625
|
+
borderRadius: 12,
|
|
2626
|
+
border: "1px solid rgba(228,228,231,0.8)",
|
|
2627
|
+
backgroundColor: "#fff",
|
|
2628
|
+
boxShadow: "0 1px 2px rgba(0,0,0,0.04)",
|
|
2629
|
+
padding: "16px 18px 14px"
|
|
2630
|
+
},
|
|
2631
|
+
children: [
|
|
2632
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2633
|
+
style: {
|
|
2634
|
+
display: "flex",
|
|
2635
|
+
alignItems: "center",
|
|
2636
|
+
gap: 8,
|
|
2637
|
+
marginBottom: 12
|
|
2638
|
+
},
|
|
2639
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2640
|
+
style: {
|
|
2641
|
+
display: "flex",
|
|
2642
|
+
gap: 4
|
|
2643
|
+
},
|
|
2644
|
+
children: [
|
|
2645
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
|
|
2646
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
|
|
2647
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {})
|
|
2648
|
+
]
|
|
2649
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2650
|
+
w: 64,
|
|
2651
|
+
h: 6,
|
|
2652
|
+
bg: "#e4e4e7",
|
|
2653
|
+
opacity: phase >= 1 ? 1 : .4,
|
|
2654
|
+
transition: "opacity 0.5s"
|
|
2655
|
+
})]
|
|
2656
|
+
}),
|
|
2657
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2658
|
+
style: {
|
|
2659
|
+
display: "grid",
|
|
2660
|
+
gap: 7
|
|
2661
|
+
},
|
|
2662
|
+
children: [
|
|
2663
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
|
|
2664
|
+
show: phase >= 0,
|
|
2665
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2666
|
+
w: 36,
|
|
2667
|
+
h: 7,
|
|
2668
|
+
bg: "rgba(147,197,253,0.7)",
|
|
2669
|
+
anim: 0
|
|
2670
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2671
|
+
w: 80,
|
|
2672
|
+
h: 7,
|
|
2673
|
+
bg: "rgba(219,234,254,0.8)",
|
|
2674
|
+
anim: .2
|
|
2675
|
+
})]
|
|
2676
|
+
}),
|
|
2677
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
|
|
2678
|
+
show: phase >= 0,
|
|
2679
|
+
delay: .1,
|
|
2680
|
+
children: [
|
|
2681
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spacer, {}),
|
|
2682
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
|
|
2683
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2684
|
+
w: 100,
|
|
2685
|
+
h: 7,
|
|
2686
|
+
bg: "rgba(24,24,27,0.2)",
|
|
2687
|
+
anim: .3
|
|
2688
|
+
})
|
|
2689
|
+
]
|
|
2690
|
+
}),
|
|
2691
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
|
|
2692
|
+
show: phase >= 1,
|
|
2693
|
+
delay: .15,
|
|
2694
|
+
children: [
|
|
2695
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spacer, {}),
|
|
2696
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2697
|
+
w: 48,
|
|
2698
|
+
h: 7,
|
|
2699
|
+
bg: "rgba(24,24,27,0.15)",
|
|
2700
|
+
anim: .1
|
|
2701
|
+
}),
|
|
2702
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2703
|
+
w: 40,
|
|
2704
|
+
h: 7,
|
|
2705
|
+
bg: "rgba(153,246,228,0.6)",
|
|
2706
|
+
anim: .5
|
|
2707
|
+
}),
|
|
2708
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2709
|
+
w: 56,
|
|
2710
|
+
h: 7,
|
|
2711
|
+
bg: "rgba(147,197,253,0.6)",
|
|
2712
|
+
anim: .3
|
|
2713
|
+
})
|
|
2714
|
+
]
|
|
2715
|
+
}),
|
|
2716
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
|
|
2717
|
+
show: phase >= 1,
|
|
2718
|
+
delay: .2,
|
|
2719
|
+
children: [
|
|
2720
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Spacer, {}),
|
|
2721
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
|
|
2722
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2723
|
+
w: 60,
|
|
2724
|
+
h: 7,
|
|
2725
|
+
bg: "rgba(24,24,27,0.15)",
|
|
2726
|
+
anim: .4
|
|
2727
|
+
})
|
|
2728
|
+
]
|
|
2729
|
+
}),
|
|
2730
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
|
|
2731
|
+
show: phase >= 2,
|
|
2732
|
+
delay: .25,
|
|
2733
|
+
children: [
|
|
2734
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2735
|
+
w: 40,
|
|
2736
|
+
h: 7,
|
|
2737
|
+
bg: "rgba(153,246,228,0.5)",
|
|
2738
|
+
anim: .2
|
|
2739
|
+
}),
|
|
2740
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
|
|
2741
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2742
|
+
w: 48,
|
|
2743
|
+
h: 7,
|
|
2744
|
+
bg: "rgba(24,24,27,0.15)",
|
|
2745
|
+
anim: .6
|
|
2746
|
+
}),
|
|
2747
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2748
|
+
w: 64,
|
|
2749
|
+
h: 7,
|
|
2750
|
+
bg: "rgba(147,197,253,0.5)",
|
|
2751
|
+
anim: .1
|
|
2752
|
+
})
|
|
2753
|
+
]
|
|
2754
|
+
}),
|
|
2755
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
|
|
2756
|
+
show: phase >= 2,
|
|
2757
|
+
delay: .3,
|
|
2758
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2759
|
+
w: 36,
|
|
2760
|
+
h: 7,
|
|
2761
|
+
bg: "rgba(147,197,253,0.6)",
|
|
2762
|
+
anim: .5
|
|
2763
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2764
|
+
w: 36,
|
|
2765
|
+
h: 7,
|
|
2766
|
+
bg: "rgba(24,24,27,0.12)",
|
|
2767
|
+
anim: .7
|
|
2768
|
+
})]
|
|
2769
|
+
}),
|
|
2770
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Row, {
|
|
2771
|
+
show: phase >= 3,
|
|
2772
|
+
delay: .35,
|
|
2773
|
+
children: [
|
|
2774
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
|
|
2775
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2776
|
+
w: 44,
|
|
2777
|
+
h: 7,
|
|
2778
|
+
bg: "rgba(24,24,27,0.18)",
|
|
2779
|
+
anim: .3
|
|
2780
|
+
}),
|
|
2781
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Dot, {}),
|
|
2782
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2783
|
+
w: 56,
|
|
2784
|
+
h: 7,
|
|
2785
|
+
bg: "rgba(153,246,228,0.5)",
|
|
2786
|
+
anim: .8
|
|
2787
|
+
}),
|
|
2788
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Bar, {
|
|
2789
|
+
w: 48,
|
|
2790
|
+
h: 7,
|
|
2791
|
+
bg: "rgba(147,197,253,0.5)",
|
|
2792
|
+
anim: .4
|
|
2793
|
+
})
|
|
2794
|
+
]
|
|
2795
|
+
})
|
|
2796
|
+
]
|
|
2797
|
+
}),
|
|
2798
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
2799
|
+
pointerEvents: "none",
|
|
2800
|
+
position: "absolute",
|
|
2801
|
+
inset: 0,
|
|
2802
|
+
background: "linear-gradient(105deg, transparent 0%, transparent 40%, rgba(255,255,255,0.6) 50%, transparent 60%, transparent 100%)",
|
|
2803
|
+
backgroundSize: "250% 100%",
|
|
2804
|
+
animation: "cpk-a2ui-sweep 3s ease-in-out infinite"
|
|
2805
|
+
} })
|
|
2806
|
+
]
|
|
2807
|
+
}),
|
|
2808
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
2809
|
+
style: {
|
|
2810
|
+
display: "flex",
|
|
2811
|
+
alignItems: "center",
|
|
2812
|
+
justifyContent: "center",
|
|
2813
|
+
gap: 8,
|
|
2814
|
+
marginTop: 8
|
|
2815
|
+
},
|
|
2816
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
2817
|
+
style: {
|
|
2818
|
+
fontSize: 12,
|
|
2819
|
+
color: "#a1a1aa",
|
|
2820
|
+
letterSpacing: "0.025em"
|
|
2821
|
+
},
|
|
2822
|
+
children: "Building interface"
|
|
2823
|
+
}), tokens > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
2824
|
+
style: {
|
|
2825
|
+
fontSize: 11,
|
|
2826
|
+
color: "#d4d4d8",
|
|
2827
|
+
fontVariantNumeric: "tabular-nums"
|
|
2828
|
+
},
|
|
2829
|
+
children: [
|
|
2830
|
+
"~",
|
|
2831
|
+
tokens.toLocaleString(),
|
|
2832
|
+
" tokens"
|
|
2833
|
+
]
|
|
2834
|
+
})]
|
|
2835
|
+
}),
|
|
2836
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("style", { children: `
|
|
2837
|
+
@keyframes cpk-a2ui-fade {
|
|
2838
|
+
0%, 100% { opacity: 1; }
|
|
2839
|
+
50% { opacity: 0.5; }
|
|
2840
|
+
}
|
|
2841
|
+
@keyframes cpk-a2ui-sweep {
|
|
2842
|
+
0% { background-position: 250% 0; }
|
|
2843
|
+
100% { background-position: -250% 0; }
|
|
2844
|
+
}
|
|
2845
|
+
` })
|
|
2846
|
+
]
|
|
2847
|
+
});
|
|
2848
|
+
}
|
|
2849
|
+
function Dot() {
|
|
2850
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
2851
|
+
width: 7,
|
|
2852
|
+
height: 7,
|
|
2853
|
+
borderRadius: "50%",
|
|
2854
|
+
backgroundColor: "#d4d4d8",
|
|
2855
|
+
flexShrink: 0
|
|
2856
|
+
} });
|
|
2857
|
+
}
|
|
2858
|
+
function Spacer() {
|
|
2859
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: { width: 12 } });
|
|
2860
|
+
}
|
|
2861
|
+
function Bar({ w, h, bg, anim, opacity, transition }) {
|
|
2862
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
2863
|
+
width: w,
|
|
2864
|
+
height: h,
|
|
2865
|
+
borderRadius: 9999,
|
|
2866
|
+
backgroundColor: bg,
|
|
2867
|
+
...anim !== void 0 ? { animation: `cpk-a2ui-fade 2.4s ease-in-out ${anim}s infinite` } : {},
|
|
2868
|
+
...opacity !== void 0 ? { opacity } : {},
|
|
2869
|
+
...transition ? { transition } : {}
|
|
2870
|
+
} });
|
|
2871
|
+
}
|
|
2872
|
+
function Row({ children, show, delay = 0 }) {
|
|
2873
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
2874
|
+
style: {
|
|
2875
|
+
display: "flex",
|
|
2876
|
+
alignItems: "center",
|
|
2877
|
+
gap: 6,
|
|
2878
|
+
opacity: show ? 1 : 0,
|
|
2879
|
+
transition: `opacity 0.4s ${delay}s`
|
|
2880
|
+
},
|
|
2881
|
+
children
|
|
2882
|
+
});
|
|
2883
|
+
}
|
|
2884
|
+
/**
|
|
2885
|
+
* Registers the built-in `render_a2ui` tool call renderer via the props-based
|
|
2886
|
+
* `setRenderToolCalls` mechanism (not `useRenderTool`).
|
|
2887
|
+
*
|
|
2888
|
+
* This ensures user-registered `useRenderTool({ name: "render_a2ui", ... })`
|
|
2889
|
+
* hooks automatically override the built-in, since the merge logic in
|
|
2890
|
+
* react-core.ts gives hook-based entries priority over prop-based entries.
|
|
2891
|
+
*/
|
|
2892
|
+
function A2UIBuiltInToolCallRenderer() {
|
|
2893
|
+
const { copilotkit } = useCopilotKit();
|
|
2894
|
+
(0, react.useEffect)(() => {
|
|
2895
|
+
var _renderToolCalls;
|
|
2896
|
+
const renderer = defineToolCallRenderer({
|
|
2897
|
+
name: RENDER_A2UI_TOOL_NAME,
|
|
2898
|
+
args: zod.z.any(),
|
|
2899
|
+
render: ({ status, args: parameters }) => {
|
|
2900
|
+
if (status === "complete") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
|
|
2901
|
+
const params = parameters;
|
|
2902
|
+
const items = params === null || params === void 0 ? void 0 : params.items;
|
|
2903
|
+
if (Array.isArray(items) && items.length > 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
|
|
2904
|
+
const components = params === null || params === void 0 ? void 0 : params.components;
|
|
2905
|
+
if (Array.isArray(components) && components.length > 2) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {});
|
|
2906
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIProgressIndicator, { parameters });
|
|
2907
|
+
}
|
|
2908
|
+
});
|
|
2909
|
+
const existing = (_renderToolCalls = copilotkit._renderToolCalls) !== null && _renderToolCalls !== void 0 ? _renderToolCalls : [];
|
|
2910
|
+
copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
|
|
2911
|
+
}, [copilotkit]);
|
|
2912
|
+
return null;
|
|
2913
|
+
}
|
|
2914
|
+
|
|
2915
|
+
//#endregion
|
|
2916
|
+
//#region src/v2/hooks/use-agent-context.tsx
|
|
2917
|
+
function useAgentContext(context) {
|
|
2918
|
+
const { description, value } = context;
|
|
2919
|
+
const { copilotkit } = useCopilotKit();
|
|
2920
|
+
const stringValue = (0, react.useMemo)(() => {
|
|
2921
|
+
if (typeof value === "string") return value;
|
|
2922
|
+
return JSON.stringify(value);
|
|
2923
|
+
}, [value]);
|
|
2924
|
+
(0, react.useLayoutEffect)(() => {
|
|
2925
|
+
if (!copilotkit) return;
|
|
2926
|
+
const id = copilotkit.addContext({
|
|
2927
|
+
description,
|
|
2928
|
+
value: stringValue
|
|
2929
|
+
});
|
|
2930
|
+
return () => {
|
|
2931
|
+
copilotkit.removeContext(id);
|
|
2932
|
+
};
|
|
2933
|
+
}, [
|
|
2934
|
+
description,
|
|
2935
|
+
stringValue,
|
|
2936
|
+
copilotkit
|
|
2937
|
+
]);
|
|
2938
|
+
}
|
|
2939
|
+
|
|
2940
|
+
//#endregion
|
|
2941
|
+
//#region src/v2/a2ui/A2UICatalogContext.tsx
|
|
2942
|
+
/**
|
|
2943
|
+
* Renders agent context describing the available A2UI catalog and custom components.
|
|
2944
|
+
* Only mount this component when A2UI is enabled.
|
|
2945
|
+
*
|
|
2946
|
+
* When `includeSchema` is true, the full component schemas (JSON Schema) are also
|
|
2947
|
+
* sent as context using the same description key as the A2UI middleware, so the
|
|
2948
|
+
* middleware can optionally overwrite it with a server-side schema.
|
|
2949
|
+
*/
|
|
2950
|
+
function A2UICatalogContext({ catalog, includeSchema }) {
|
|
2951
|
+
useAgentContext({
|
|
2952
|
+
description: "A2UI catalog capabilities: available catalog IDs and custom component definitions the client can render.",
|
|
2953
|
+
value: (0, _copilotkit_a2ui_renderer.buildCatalogContextValue)(catalog)
|
|
2954
|
+
});
|
|
2955
|
+
const { copilotkit } = useCopilotKit();
|
|
2956
|
+
const schemaValue = (0, react.useMemo)(() => includeSchema !== false ? JSON.stringify((0, _copilotkit_a2ui_renderer.extractCatalogComponentSchemas)(catalog)) : null, [catalog, includeSchema]);
|
|
2957
|
+
(0, react.useLayoutEffect)(() => {
|
|
2958
|
+
if (!copilotkit || !schemaValue) return;
|
|
2959
|
+
const ids = [];
|
|
2960
|
+
ids.push(copilotkit.addContext({
|
|
2961
|
+
description: _copilotkit_a2ui_renderer.A2UI_SCHEMA_CONTEXT_DESCRIPTION,
|
|
2962
|
+
value: schemaValue
|
|
2963
|
+
}));
|
|
2964
|
+
ids.push(copilotkit.addContext({
|
|
2965
|
+
description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
|
|
2966
|
+
value: _copilotkit_shared.A2UI_DEFAULT_GENERATION_GUIDELINES
|
|
2967
|
+
}));
|
|
2968
|
+
ids.push(copilotkit.addContext({
|
|
2969
|
+
description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
|
|
2970
|
+
value: _copilotkit_shared.A2UI_DEFAULT_DESIGN_GUIDELINES
|
|
2971
|
+
}));
|
|
2972
|
+
return () => {
|
|
2973
|
+
for (const id of ids) copilotkit.removeContext(id);
|
|
2974
|
+
};
|
|
2975
|
+
}, [copilotkit, schemaValue]);
|
|
2976
|
+
return null;
|
|
2977
|
+
}
|
|
2062
2978
|
|
|
2063
2979
|
//#endregion
|
|
2064
2980
|
//#region src/v2/lib/react-core.ts
|
|
@@ -2167,6 +3083,17 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2167
3083
|
//#region src/v2/providers/CopilotKitProvider.tsx
|
|
2168
3084
|
const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
|
|
2169
3085
|
const COPILOT_CLOUD_CHAT_URL$1 = "https://api.cloud.copilotkit.ai/copilotkit/v1";
|
|
3086
|
+
const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follow these design principles inspired by shadcn/ui:
|
|
3087
|
+
|
|
3088
|
+
- Use a minimal, flat aesthetic. Avoid drop shadows and gradients — rely on subtle borders (1px solid, light gray like #e5e7eb) to define surfaces.
|
|
3089
|
+
- Neutral base palette: white backgrounds, zinc/slate gray text (#09090b for headings, #71717a for secondary text). One accent color for interactive elements.
|
|
3090
|
+
- Use system font stacks (system-ui, -apple-system, sans-serif) at readable sizes (14px body, 600 weight for headings). Tight line-heights.
|
|
3091
|
+
- Small, consistent border-radius (6–8px). Cards and containers use border, not shadow, for separation.
|
|
3092
|
+
- Buttons: solid fill for primary (dark bg, white text), outline for secondary (border + transparent bg). Subtle hover state (slight opacity or background shift).
|
|
3093
|
+
- Use CSS Grid or Flexbox for layout. Ensure the UI looks good at any width.
|
|
3094
|
+
- Minimal transitions (150ms) for hover/focus states only. No decorative animations.
|
|
3095
|
+
- Keep the UI focused and dense — avoid excessive padding. Use compact spacing (8–12px gaps, 10–14px padding in controls).`;
|
|
3096
|
+
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)";
|
|
2170
3097
|
const CopilotKitContext = (0, react.createContext)({
|
|
2171
3098
|
copilotkit: null,
|
|
2172
3099
|
executingToolCallIds: /* @__PURE__ */ new Set()
|
|
@@ -2182,9 +3109,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2182
3109
|
}, [value, warningMessage]);
|
|
2183
3110
|
return value;
|
|
2184
3111
|
}
|
|
2185
|
-
const CopilotKitProvider = ({ children, runtimeUrl, headers = {}, credentials, publicApiKey, publicLicenseKey, licenseToken, properties = {}, agents__unsafe_dev_only: agents = {}, selfManagedAgents = {}, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, showDevConsole = false, useSingleEndpoint
|
|
3112
|
+
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 }) => {
|
|
3113
|
+
var _openGenerativeUI$des;
|
|
2186
3114
|
const [shouldRenderInspector, setShouldRenderInspector] = (0, react.useState)(false);
|
|
2187
3115
|
const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = (0, react.useState)(false);
|
|
3116
|
+
const [runtimeOpenGenUIEnabled, setRuntimeOpenGenUIEnabled] = (0, react.useState)(false);
|
|
3117
|
+
const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
|
|
2188
3118
|
const [runtimeLicenseStatus, setRuntimeLicenseStatus] = (0, react.useState)(void 0);
|
|
2189
3119
|
(0, react.useEffect)(() => {
|
|
2190
3120
|
if (typeof window === "undefined") return;
|
|
@@ -2213,12 +3143,25 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2213
3143
|
content: MCPAppsActivityContentSchema,
|
|
2214
3144
|
render: MCPAppsActivityRenderer
|
|
2215
3145
|
}];
|
|
3146
|
+
if (openGenUIActive) renderers.push({
|
|
3147
|
+
activityType: OpenGenerativeUIActivityType,
|
|
3148
|
+
content: OpenGenerativeUIContentSchema,
|
|
3149
|
+
render: OpenGenerativeUIActivityRenderer
|
|
3150
|
+
});
|
|
2216
3151
|
if (runtimeA2UIEnabled) {
|
|
2217
3152
|
var _a2ui$theme;
|
|
2218
|
-
renderers.unshift(createA2UIMessageRenderer({
|
|
3153
|
+
renderers.unshift(createA2UIMessageRenderer({
|
|
3154
|
+
theme: (_a2ui$theme = a2ui === null || a2ui === void 0 ? void 0 : a2ui.theme) !== null && _a2ui$theme !== void 0 ? _a2ui$theme : _copilotkit_a2ui_renderer.viewerTheme,
|
|
3155
|
+
catalog: a2ui === null || a2ui === void 0 ? void 0 : a2ui.catalog,
|
|
3156
|
+
loadingComponent: a2ui === null || a2ui === void 0 ? void 0 : a2ui.loadingComponent
|
|
3157
|
+
}));
|
|
2219
3158
|
}
|
|
2220
3159
|
return renderers;
|
|
2221
|
-
}, [
|
|
3160
|
+
}, [
|
|
3161
|
+
runtimeA2UIEnabled,
|
|
3162
|
+
openGenUIActive,
|
|
3163
|
+
a2ui
|
|
3164
|
+
]);
|
|
2222
3165
|
const allActivityRenderers = (0, react.useMemo)(() => {
|
|
2223
3166
|
return [...renderActivityMessagesList, ...builtInActivityRenderers];
|
|
2224
3167
|
}, [renderActivityMessagesList, builtInActivityRenderers]);
|
|
@@ -2244,6 +3187,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2244
3187
|
const chatApiEndpoint = runtimeUrl !== null && runtimeUrl !== void 0 ? runtimeUrl : resolvedPublicKey ? COPILOT_CLOUD_CHAT_URL$1 : void 0;
|
|
2245
3188
|
const frontendToolsList = useStableArrayProp(frontendTools, "frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.");
|
|
2246
3189
|
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.");
|
|
3190
|
+
const sandboxFunctionsList = useStableArrayProp(openGenerativeUI === null || openGenerativeUI === void 0 ? void 0 : openGenerativeUI.sandboxFunctions, "openGenerativeUI.sandboxFunctions must be a stable array.");
|
|
2247
3191
|
const processedHumanInTheLoopTools = (0, react.useMemo)(() => {
|
|
2248
3192
|
const processedTools = [];
|
|
2249
3193
|
const processedRenderToolCalls = [];
|
|
@@ -2274,15 +3218,31 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2274
3218
|
renderToolCalls: processedRenderToolCalls
|
|
2275
3219
|
};
|
|
2276
3220
|
}, [humanInTheLoopList]);
|
|
3221
|
+
const builtInFrontendTools = (0, react.useMemo)(() => {
|
|
3222
|
+
if (!openGenUIActive) return [];
|
|
3223
|
+
return [{
|
|
3224
|
+
name: "generateSandboxedUi",
|
|
3225
|
+
description: GENERATE_SANDBOXED_UI_DESCRIPTION,
|
|
3226
|
+
parameters: GenerateSandboxedUiArgsSchema,
|
|
3227
|
+
handler: async () => "UI generated",
|
|
3228
|
+
followUp: true,
|
|
3229
|
+
render: OpenGenerativeUIToolRenderer
|
|
3230
|
+
}];
|
|
3231
|
+
}, [openGenUIActive]);
|
|
2277
3232
|
const allTools = (0, react.useMemo)(() => {
|
|
2278
3233
|
const tools = [];
|
|
2279
3234
|
tools.push(...frontendToolsList);
|
|
3235
|
+
tools.push(...builtInFrontendTools);
|
|
2280
3236
|
tools.push(...processedHumanInTheLoopTools.tools);
|
|
2281
3237
|
return tools;
|
|
2282
|
-
}, [
|
|
3238
|
+
}, [
|
|
3239
|
+
frontendToolsList,
|
|
3240
|
+
builtInFrontendTools,
|
|
3241
|
+
processedHumanInTheLoopTools
|
|
3242
|
+
]);
|
|
2283
3243
|
const allRenderToolCalls = (0, react.useMemo)(() => {
|
|
2284
3244
|
const combined = [...renderToolCallsList];
|
|
2285
|
-
frontendToolsList.forEach((tool) => {
|
|
3245
|
+
[...frontendToolsList, ...builtInFrontendTools].forEach((tool) => {
|
|
2286
3246
|
if (tool.render) {
|
|
2287
3247
|
const args = tool.parameters || (tool.name === "*" ? zod.z.any() : void 0);
|
|
2288
3248
|
if (args) combined.push({
|
|
@@ -2297,25 +3257,31 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2297
3257
|
}, [
|
|
2298
3258
|
renderToolCallsList,
|
|
2299
3259
|
frontendToolsList,
|
|
3260
|
+
builtInFrontendTools,
|
|
2300
3261
|
processedHumanInTheLoopTools
|
|
2301
3262
|
]);
|
|
2302
3263
|
const copilotkitRef = (0, react.useRef)(null);
|
|
2303
|
-
if (copilotkitRef.current === null)
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
2309
|
-
|
|
2310
|
-
|
|
2311
|
-
|
|
2312
|
-
|
|
2313
|
-
|
|
2314
|
-
|
|
3264
|
+
if (copilotkitRef.current === null) {
|
|
3265
|
+
copilotkitRef.current = new CopilotKitCoreReact({
|
|
3266
|
+
runtimeUrl: chatApiEndpoint,
|
|
3267
|
+
runtimeTransport: useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto",
|
|
3268
|
+
headers: mergedHeaders,
|
|
3269
|
+
credentials,
|
|
3270
|
+
properties,
|
|
3271
|
+
agents__unsafe_dev_only: mergedAgents,
|
|
3272
|
+
tools: allTools,
|
|
3273
|
+
renderToolCalls: allRenderToolCalls,
|
|
3274
|
+
renderActivityMessages: allActivityRenderers,
|
|
3275
|
+
renderCustomMessages: renderCustomMessagesList
|
|
3276
|
+
});
|
|
3277
|
+
if (defaultThrottleMs !== void 0) copilotkitRef.current.setDefaultThrottleMs(defaultThrottleMs);
|
|
3278
|
+
}
|
|
2315
3279
|
const copilotkit = copilotkitRef.current;
|
|
2316
3280
|
(0, react.useEffect)(() => {
|
|
3281
|
+
setRuntimeA2UIEnabled(copilotkit.a2uiEnabled);
|
|
2317
3282
|
const subscription = copilotkit.subscribe({ onRuntimeConnectionStatusChanged: () => {
|
|
2318
3283
|
setRuntimeA2UIEnabled(copilotkit.a2uiEnabled);
|
|
3284
|
+
setRuntimeOpenGenUIEnabled(copilotkit.openGenerativeUIEnabled);
|
|
2319
3285
|
setRuntimeLicenseStatus(copilotkit.licenseStatus);
|
|
2320
3286
|
} });
|
|
2321
3287
|
return () => {
|
|
@@ -2375,7 +3341,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2375
3341
|
}, [copilotkit]);
|
|
2376
3342
|
(0, react.useEffect)(() => {
|
|
2377
3343
|
copilotkit.setRuntimeUrl(chatApiEndpoint);
|
|
2378
|
-
copilotkit.setRuntimeTransport(useSingleEndpoint ? "single" : "rest");
|
|
3344
|
+
copilotkit.setRuntimeTransport(useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto");
|
|
2379
3345
|
copilotkit.setHeaders(mergedHeaders);
|
|
2380
3346
|
copilotkit.setCredentials(credentials);
|
|
2381
3347
|
copilotkit.setProperties(properties);
|
|
@@ -2409,23 +3375,75 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2409
3375
|
(0, react.useEffect)(() => {
|
|
2410
3376
|
didMountRef.current = true;
|
|
2411
3377
|
}, []);
|
|
3378
|
+
(0, react.useEffect)(() => {
|
|
3379
|
+
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.`);
|
|
3380
|
+
copilotkit.setDefaultThrottleMs(defaultThrottleMs);
|
|
3381
|
+
}, [copilotkit, defaultThrottleMs]);
|
|
3382
|
+
const designSkill = (_openGenerativeUI$des = openGenerativeUI === null || openGenerativeUI === void 0 ? void 0 : openGenerativeUI.designSkill) !== null && _openGenerativeUI$des !== void 0 ? _openGenerativeUI$des : DEFAULT_DESIGN_SKILL;
|
|
3383
|
+
(0, react.useLayoutEffect)(() => {
|
|
3384
|
+
if (!copilotkit || !openGenUIActive) return;
|
|
3385
|
+
const id = copilotkit.addContext({
|
|
3386
|
+
description: "Design guidelines for the generateSandboxedUi tool. Follow these when building UI.",
|
|
3387
|
+
value: designSkill
|
|
3388
|
+
});
|
|
3389
|
+
return () => {
|
|
3390
|
+
copilotkit.removeContext(id);
|
|
3391
|
+
};
|
|
3392
|
+
}, [
|
|
3393
|
+
copilotkit,
|
|
3394
|
+
designSkill,
|
|
3395
|
+
openGenUIActive
|
|
3396
|
+
]);
|
|
3397
|
+
const sandboxFunctionsDescriptors = (0, react.useMemo)(() => {
|
|
3398
|
+
if (sandboxFunctionsList.length === 0) return null;
|
|
3399
|
+
return JSON.stringify(sandboxFunctionsList.map((fn) => ({
|
|
3400
|
+
name: fn.name,
|
|
3401
|
+
description: fn.description,
|
|
3402
|
+
parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zod_to_json_schema.zodToJsonSchema })
|
|
3403
|
+
})));
|
|
3404
|
+
}, [sandboxFunctionsList]);
|
|
3405
|
+
(0, react.useLayoutEffect)(() => {
|
|
3406
|
+
if (!copilotkit || !sandboxFunctionsDescriptors || !openGenUIActive) return;
|
|
3407
|
+
const id = copilotkit.addContext({
|
|
3408
|
+
description: "Sandbox functions available in generated sandboxed UI code. Call via: await Websandbox.connection.remote.<functionName>(args)",
|
|
3409
|
+
value: sandboxFunctionsDescriptors
|
|
3410
|
+
});
|
|
3411
|
+
return () => {
|
|
3412
|
+
copilotkit.removeContext(id);
|
|
3413
|
+
};
|
|
3414
|
+
}, [
|
|
3415
|
+
copilotkit,
|
|
3416
|
+
sandboxFunctionsDescriptors,
|
|
3417
|
+
openGenUIActive
|
|
3418
|
+
]);
|
|
2412
3419
|
const contextValue = (0, react.useMemo)(() => ({
|
|
2413
3420
|
copilotkit,
|
|
2414
3421
|
executingToolCallIds
|
|
2415
3422
|
}), [copilotkit, executingToolCallIds]);
|
|
2416
3423
|
const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(null), []);
|
|
2417
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
2418
|
-
value:
|
|
2419
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.
|
|
2420
|
-
value:
|
|
2421
|
-
children:
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
|
|
2427
|
-
|
|
2428
|
-
|
|
3424
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
|
|
3425
|
+
value: sandboxFunctionsList,
|
|
3426
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
|
|
3427
|
+
value: contextValue,
|
|
3428
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
|
|
3429
|
+
value: licenseContextValue,
|
|
3430
|
+
children: [
|
|
3431
|
+
runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
|
|
3432
|
+
runtimeA2UIEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
|
|
3433
|
+
catalog: a2ui === null || a2ui === void 0 ? void 0 : a2ui.catalog,
|
|
3434
|
+
includeSchema: a2ui === null || a2ui === void 0 ? void 0 : a2ui.includeSchema
|
|
3435
|
+
}),
|
|
3436
|
+
children,
|
|
3437
|
+
shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, {
|
|
3438
|
+
core: copilotkit,
|
|
3439
|
+
defaultAnchor: inspectorDefaultAnchor
|
|
3440
|
+
}) : null,
|
|
3441
|
+
runtimeLicenseStatus === "none" && !resolvedPublicKey && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "no_license" }),
|
|
3442
|
+
runtimeLicenseStatus === "expired" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expired" }),
|
|
3443
|
+
runtimeLicenseStatus === "invalid" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "invalid" }),
|
|
3444
|
+
runtimeLicenseStatus === "expiring" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(LicenseWarningBanner, { type: "expiring" })
|
|
3445
|
+
]
|
|
3446
|
+
})
|
|
2429
3447
|
})
|
|
2430
3448
|
});
|
|
2431
3449
|
};
|
|
@@ -2570,12 +3588,23 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2570
3588
|
byThread.set(threadId, clone);
|
|
2571
3589
|
return clone;
|
|
2572
3590
|
}
|
|
2573
|
-
function useAgent({ agentId, threadId, updates } = {}) {
|
|
3591
|
+
function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
2574
3592
|
var _agentId, _threadId;
|
|
2575
3593
|
(_agentId = agentId) !== null && _agentId !== void 0 || (agentId = _copilotkit_shared.DEFAULT_AGENT_ID);
|
|
2576
3594
|
const { copilotkit } = useCopilotKit();
|
|
3595
|
+
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
2577
3596
|
const chatConfig = useCopilotChatConfiguration();
|
|
2578
3597
|
(_threadId = threadId) !== null && _threadId !== void 0 || (threadId = chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.threadId);
|
|
3598
|
+
const effectiveThrottleMs = (0, react.useMemo)(() => {
|
|
3599
|
+
var _ref;
|
|
3600
|
+
const resolved = (_ref = throttleMs !== null && throttleMs !== void 0 ? throttleMs : providerThrottleMs) !== null && _ref !== void 0 ? _ref : 0;
|
|
3601
|
+
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
3602
|
+
const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
|
|
3603
|
+
console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
|
|
3604
|
+
return 0;
|
|
3605
|
+
}
|
|
3606
|
+
return resolved;
|
|
3607
|
+
}, [throttleMs, providerThrottleMs]);
|
|
2579
3608
|
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
2580
3609
|
const updateFlags = (0, react.useMemo)(() => updates !== null && updates !== void 0 ? updates : ALL_UPDATES, [JSON.stringify(updates)]);
|
|
2581
3610
|
const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
@@ -2640,9 +3669,32 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2640
3669
|
(0, react.useEffect)(() => {
|
|
2641
3670
|
if (updateFlags.length === 0) return;
|
|
2642
3671
|
const handlers = {};
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
3672
|
+
let timerId = null;
|
|
3673
|
+
let active = true;
|
|
3674
|
+
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) {
|
|
3675
|
+
const ms = effectiveThrottleMs;
|
|
3676
|
+
if (ms > 0) {
|
|
3677
|
+
let throttleActive = false;
|
|
3678
|
+
let pending = false;
|
|
3679
|
+
const throttledNotify = () => {
|
|
3680
|
+
if (!active) return;
|
|
3681
|
+
if (!throttleActive) {
|
|
3682
|
+
throttleActive = true;
|
|
3683
|
+
pending = false;
|
|
3684
|
+
forceUpdate();
|
|
3685
|
+
timerId = setTimeout(function trailingEdge() {
|
|
3686
|
+
timerId = null;
|
|
3687
|
+
if (active && pending) {
|
|
3688
|
+
pending = false;
|
|
3689
|
+
forceUpdate();
|
|
3690
|
+
timerId = setTimeout(trailingEdge, ms);
|
|
3691
|
+
} else throttleActive = false;
|
|
3692
|
+
}, ms);
|
|
3693
|
+
} else pending = true;
|
|
3694
|
+
};
|
|
3695
|
+
handlers.onMessagesChanged = throttledNotify;
|
|
3696
|
+
} else handlers.onMessagesChanged = forceUpdate;
|
|
3697
|
+
}
|
|
2646
3698
|
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = forceUpdate;
|
|
2647
3699
|
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
2648
3700
|
handlers.onRunInitialized = forceUpdate;
|
|
@@ -2650,11 +3702,16 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2650
3702
|
handlers.onRunFailed = forceUpdate;
|
|
2651
3703
|
}
|
|
2652
3704
|
const subscription = agent.subscribe(handlers);
|
|
2653
|
-
return () =>
|
|
3705
|
+
return () => {
|
|
3706
|
+
active = false;
|
|
3707
|
+
if (timerId !== null) clearTimeout(timerId);
|
|
3708
|
+
subscription.unsubscribe();
|
|
3709
|
+
};
|
|
2654
3710
|
}, [
|
|
2655
3711
|
agent,
|
|
2656
3712
|
forceUpdate,
|
|
2657
|
-
|
|
3713
|
+
effectiveThrottleMs,
|
|
3714
|
+
updateFlags
|
|
2658
3715
|
]);
|
|
2659
3716
|
(0, react.useEffect)(() => {
|
|
2660
3717
|
if (agent instanceof _ag_ui_client.HttpAgent) agent.headers = { ...copilotkit.headers };
|
|
@@ -2724,6 +3781,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2724
3781
|
return (_ref = (_ref2 = (_matches$find = matches.find((candidate) => candidate.agentId === agentId)) !== null && _matches$find !== void 0 ? _matches$find : matches.find((candidate) => candidate.agentId === void 0)) !== null && _ref2 !== void 0 ? _ref2 : renderers.find((candidate) => candidate.activityType === "*")) !== null && _ref !== void 0 ? _ref : null;
|
|
2725
3782
|
}, [agentId, renderers]);
|
|
2726
3783
|
const renderActivityMessage = (0, react.useCallback)((message) => {
|
|
3784
|
+
var _getThreadClone;
|
|
2727
3785
|
const renderer = findRenderer(message.activityType);
|
|
2728
3786
|
if (!renderer) return null;
|
|
2729
3787
|
const parseResult = renderer.content.safeParse(message.content);
|
|
@@ -2732,7 +3790,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2732
3790
|
return null;
|
|
2733
3791
|
}
|
|
2734
3792
|
const Component = renderer.render;
|
|
2735
|
-
const
|
|
3793
|
+
const registryAgent = copilotkit.getAgent(agentId);
|
|
3794
|
+
const agent = (_getThreadClone = getThreadClone(registryAgent, config === null || config === void 0 ? void 0 : config.threadId)) !== null && _getThreadClone !== void 0 ? _getThreadClone : registryAgent;
|
|
2736
3795
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
|
|
2737
3796
|
activityType: message.activityType,
|
|
2738
3797
|
content: parseResult.data,
|
|
@@ -2741,6 +3800,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2741
3800
|
}, message.id);
|
|
2742
3801
|
}, [
|
|
2743
3802
|
agentId,
|
|
3803
|
+
config === null || config === void 0 ? void 0 : config.threadId,
|
|
2744
3804
|
copilotkit,
|
|
2745
3805
|
findRenderer
|
|
2746
3806
|
]);
|
|
@@ -2766,7 +3826,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2766
3826
|
copilotkit.removeTool(name, tool.agentId);
|
|
2767
3827
|
}
|
|
2768
3828
|
copilotkit.addTool(tool);
|
|
2769
|
-
if (tool.render
|
|
3829
|
+
if (tool.render) copilotkit.addHookRenderToolCall({
|
|
2770
3830
|
name,
|
|
2771
3831
|
args: tool.parameters,
|
|
2772
3832
|
agentId: tool.agentId,
|
|
@@ -2851,18 +3911,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
2851
3911
|
}, deps);
|
|
2852
3912
|
}
|
|
2853
3913
|
|
|
2854
|
-
//#endregion
|
|
2855
|
-
//#region src/v2/types/defineToolCallRenderer.ts
|
|
2856
|
-
function defineToolCallRenderer(def) {
|
|
2857
|
-
const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
|
|
2858
|
-
return {
|
|
2859
|
-
name: def.name,
|
|
2860
|
-
args: argsSchema,
|
|
2861
|
-
render: def.render,
|
|
2862
|
-
...def.agentId ? { agentId: def.agentId } : {}
|
|
2863
|
-
};
|
|
2864
|
-
}
|
|
2865
|
-
|
|
2866
3914
|
//#endregion
|
|
2867
3915
|
//#region src/v2/hooks/use-render-tool.tsx
|
|
2868
3916
|
const EMPTY_DEPS = [];
|
|
@@ -3193,31 +4241,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3193
4241
|
]);
|
|
3194
4242
|
}
|
|
3195
4243
|
|
|
3196
|
-
//#endregion
|
|
3197
|
-
//#region src/v2/hooks/use-agent-context.tsx
|
|
3198
|
-
function useAgentContext(context) {
|
|
3199
|
-
const { description, value } = context;
|
|
3200
|
-
const { copilotkit } = useCopilotKit();
|
|
3201
|
-
const stringValue = (0, react.useMemo)(() => {
|
|
3202
|
-
if (typeof value === "string") return value;
|
|
3203
|
-
return JSON.stringify(value);
|
|
3204
|
-
}, [value]);
|
|
3205
|
-
(0, react.useLayoutEffect)(() => {
|
|
3206
|
-
if (!copilotkit) return;
|
|
3207
|
-
const id = copilotkit.addContext({
|
|
3208
|
-
description,
|
|
3209
|
-
value: stringValue
|
|
3210
|
-
});
|
|
3211
|
-
return () => {
|
|
3212
|
-
copilotkit.removeContext(id);
|
|
3213
|
-
};
|
|
3214
|
-
}, [
|
|
3215
|
-
description,
|
|
3216
|
-
stringValue,
|
|
3217
|
-
copilotkit
|
|
3218
|
-
]);
|
|
3219
|
-
}
|
|
3220
|
-
|
|
3221
4244
|
//#endregion
|
|
3222
4245
|
//#region src/v2/hooks/use-suggestions.tsx
|
|
3223
4246
|
function useSuggestions({ agentId } = {}) {
|
|
@@ -3639,11 +4662,19 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3639
4662
|
var _copilotkit$intellige2;
|
|
3640
4663
|
const { copilotkit } = useCopilotKit();
|
|
3641
4664
|
const [store] = (0, react.useState)(() => (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: globalThis.fetch }));
|
|
3642
|
-
const
|
|
4665
|
+
const coreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreads);
|
|
4666
|
+
const threads = (0, react.useMemo)(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt }) => ({
|
|
4667
|
+
id,
|
|
4668
|
+
agentId,
|
|
4669
|
+
name,
|
|
4670
|
+
archived,
|
|
4671
|
+
createdAt,
|
|
4672
|
+
updatedAt
|
|
4673
|
+
})), [coreThreads]);
|
|
3643
4674
|
const storeIsLoading = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsIsLoading);
|
|
3644
4675
|
const storeError = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsError);
|
|
3645
|
-
const
|
|
3646
|
-
const
|
|
4676
|
+
const hasMoreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectHasNextPage);
|
|
4677
|
+
const isFetchingMoreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectIsFetchingNextPage);
|
|
3647
4678
|
const headersKey = (0, react.useMemo)(() => {
|
|
3648
4679
|
var _copilotkit$headers;
|
|
3649
4680
|
return JSON.stringify(Object.entries((_copilotkit$headers = copilotkit.headers) !== null && _copilotkit$headers !== void 0 ? _copilotkit$headers : {}).sort(([left], [right]) => left.localeCompare(right)));
|
|
@@ -3688,15 +4719,184 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3688
4719
|
threads,
|
|
3689
4720
|
isLoading,
|
|
3690
4721
|
error,
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
|
|
4722
|
+
hasMoreThreads,
|
|
4723
|
+
isFetchingMoreThreads,
|
|
4724
|
+
fetchMoreThreads: (0, react.useCallback)(() => store.fetchNextPage(), [store]),
|
|
3694
4725
|
renameThread,
|
|
3695
4726
|
archiveThread,
|
|
3696
4727
|
deleteThread
|
|
3697
4728
|
};
|
|
3698
4729
|
}
|
|
3699
4730
|
|
|
4731
|
+
//#endregion
|
|
4732
|
+
//#region src/v2/hooks/use-attachments.tsx
|
|
4733
|
+
/**
|
|
4734
|
+
* Hook that manages file attachment state — uploads, drag-and-drop, paste,
|
|
4735
|
+
* and lifecycle. All returned callbacks are referentially stable across
|
|
4736
|
+
* renders (via useCallback) to avoid destabilizing downstream memoization.
|
|
4737
|
+
*/
|
|
4738
|
+
function useAttachments({ config }) {
|
|
4739
|
+
var _config$enabled;
|
|
4740
|
+
const enabled = (_config$enabled = config === null || config === void 0 ? void 0 : config.enabled) !== null && _config$enabled !== void 0 ? _config$enabled : false;
|
|
4741
|
+
const [attachments, setAttachments] = (0, react.useState)([]);
|
|
4742
|
+
const [dragOver, setDragOver] = (0, react.useState)(false);
|
|
4743
|
+
const fileInputRef = (0, react.useRef)(null);
|
|
4744
|
+
const containerRef = (0, react.useRef)(null);
|
|
4745
|
+
const configRef = (0, react.useRef)(config);
|
|
4746
|
+
configRef.current = config;
|
|
4747
|
+
const attachmentsRef = (0, react.useRef)([]);
|
|
4748
|
+
attachmentsRef.current = attachments;
|
|
4749
|
+
const processFiles = (0, react.useCallback)(async (files) => {
|
|
4750
|
+
var _cfg$accept, _cfg$maxSize;
|
|
4751
|
+
const cfg = configRef.current;
|
|
4752
|
+
const accept = (_cfg$accept = cfg === null || cfg === void 0 ? void 0 : cfg.accept) !== null && _cfg$accept !== void 0 ? _cfg$accept : "*/*";
|
|
4753
|
+
const maxSize = (_cfg$maxSize = cfg === null || cfg === void 0 ? void 0 : cfg.maxSize) !== null && _cfg$maxSize !== void 0 ? _cfg$maxSize : 20 * 1024 * 1024;
|
|
4754
|
+
const rejectedFiles = files.filter((file) => !(0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
|
|
4755
|
+
for (const file of rejectedFiles) {
|
|
4756
|
+
var _cfg$onUploadFailed;
|
|
4757
|
+
cfg === null || cfg === void 0 || (_cfg$onUploadFailed = cfg.onUploadFailed) === null || _cfg$onUploadFailed === void 0 || _cfg$onUploadFailed.call(cfg, {
|
|
4758
|
+
reason: "invalid-type",
|
|
4759
|
+
file,
|
|
4760
|
+
message: `File "${file.name}" is not accepted. Supported types: ${accept}`
|
|
4761
|
+
});
|
|
4762
|
+
}
|
|
4763
|
+
const validFiles = files.filter((file) => (0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
|
|
4764
|
+
for (const file of validFiles) {
|
|
4765
|
+
if ((0, _copilotkit_shared.exceedsMaxSize)(file, maxSize)) {
|
|
4766
|
+
var _cfg$onUploadFailed2;
|
|
4767
|
+
cfg === null || cfg === void 0 || (_cfg$onUploadFailed2 = cfg.onUploadFailed) === null || _cfg$onUploadFailed2 === void 0 || _cfg$onUploadFailed2.call(cfg, {
|
|
4768
|
+
reason: "file-too-large",
|
|
4769
|
+
file,
|
|
4770
|
+
message: `File "${file.name}" exceeds the maximum size of ${(0, _copilotkit_shared.formatFileSize)(maxSize)}`
|
|
4771
|
+
});
|
|
4772
|
+
continue;
|
|
4773
|
+
}
|
|
4774
|
+
const modality = (0, _copilotkit_shared.getModalityFromMimeType)(file.type);
|
|
4775
|
+
const placeholderId = (0, _copilotkit_shared.randomUUID)();
|
|
4776
|
+
const placeholder = {
|
|
4777
|
+
id: placeholderId,
|
|
4778
|
+
type: modality,
|
|
4779
|
+
source: {
|
|
4780
|
+
type: "data",
|
|
4781
|
+
value: "",
|
|
4782
|
+
mimeType: file.type
|
|
4783
|
+
},
|
|
4784
|
+
filename: file.name,
|
|
4785
|
+
size: file.size,
|
|
4786
|
+
status: "uploading"
|
|
4787
|
+
};
|
|
4788
|
+
setAttachments((prev) => [...prev, placeholder]);
|
|
4789
|
+
try {
|
|
4790
|
+
let source;
|
|
4791
|
+
let uploadMetadata;
|
|
4792
|
+
if (cfg === null || cfg === void 0 ? void 0 : cfg.onUpload) {
|
|
4793
|
+
const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
|
|
4794
|
+
source = uploadSource;
|
|
4795
|
+
uploadMetadata = meta;
|
|
4796
|
+
} else source = {
|
|
4797
|
+
type: "data",
|
|
4798
|
+
value: await (0, _copilotkit_shared.readFileAsBase64)(file),
|
|
4799
|
+
mimeType: file.type
|
|
4800
|
+
};
|
|
4801
|
+
let thumbnail;
|
|
4802
|
+
if (modality === "video") thumbnail = await (0, _copilotkit_shared.generateVideoThumbnail)(file);
|
|
4803
|
+
setAttachments((prev) => prev.map((att) => att.id === placeholderId ? {
|
|
4804
|
+
...att,
|
|
4805
|
+
source,
|
|
4806
|
+
status: "ready",
|
|
4807
|
+
thumbnail,
|
|
4808
|
+
metadata: uploadMetadata
|
|
4809
|
+
} : att));
|
|
4810
|
+
} catch (error) {
|
|
4811
|
+
var _cfg$onUploadFailed3;
|
|
4812
|
+
setAttachments((prev) => prev.filter((att) => att.id !== placeholderId));
|
|
4813
|
+
console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
|
|
4814
|
+
cfg === null || cfg === void 0 || (_cfg$onUploadFailed3 = cfg.onUploadFailed) === null || _cfg$onUploadFailed3 === void 0 || _cfg$onUploadFailed3.call(cfg, {
|
|
4815
|
+
reason: "upload-failed",
|
|
4816
|
+
file,
|
|
4817
|
+
message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
|
|
4818
|
+
});
|
|
4819
|
+
}
|
|
4820
|
+
}
|
|
4821
|
+
}, []);
|
|
4822
|
+
const handleFileUpload = (0, react.useCallback)(async (e) => {
|
|
4823
|
+
var _e$target$files;
|
|
4824
|
+
if (!((_e$target$files = e.target.files) === null || _e$target$files === void 0 ? void 0 : _e$target$files.length)) return;
|
|
4825
|
+
try {
|
|
4826
|
+
await processFiles(Array.from(e.target.files));
|
|
4827
|
+
} catch (error) {
|
|
4828
|
+
console.error("[CopilotKit] Upload error:", error);
|
|
4829
|
+
}
|
|
4830
|
+
}, [processFiles]);
|
|
4831
|
+
const handleDragOver = (0, react.useCallback)((e) => {
|
|
4832
|
+
var _configRef$current;
|
|
4833
|
+
if (!((_configRef$current = configRef.current) === null || _configRef$current === void 0 ? void 0 : _configRef$current.enabled)) return;
|
|
4834
|
+
e.preventDefault();
|
|
4835
|
+
e.stopPropagation();
|
|
4836
|
+
setDragOver(true);
|
|
4837
|
+
}, []);
|
|
4838
|
+
const handleDragLeave = (0, react.useCallback)((e) => {
|
|
4839
|
+
e.preventDefault();
|
|
4840
|
+
e.stopPropagation();
|
|
4841
|
+
setDragOver(false);
|
|
4842
|
+
}, []);
|
|
4843
|
+
const handleDrop = (0, react.useCallback)(async (e) => {
|
|
4844
|
+
var _configRef$current2;
|
|
4845
|
+
e.preventDefault();
|
|
4846
|
+
e.stopPropagation();
|
|
4847
|
+
setDragOver(false);
|
|
4848
|
+
if (!((_configRef$current2 = configRef.current) === null || _configRef$current2 === void 0 ? void 0 : _configRef$current2.enabled)) return;
|
|
4849
|
+
const files = Array.from(e.dataTransfer.files);
|
|
4850
|
+
if (files.length > 0) try {
|
|
4851
|
+
await processFiles(files);
|
|
4852
|
+
} catch (error) {
|
|
4853
|
+
console.error("[CopilotKit] Drop error:", error);
|
|
4854
|
+
}
|
|
4855
|
+
}, [processFiles]);
|
|
4856
|
+
(0, react.useEffect)(() => {
|
|
4857
|
+
if (!enabled) return;
|
|
4858
|
+
const handlePaste = async (e) => {
|
|
4859
|
+
var _containerRef$current, _configRef$current$ac, _configRef$current3, _e$clipboardData;
|
|
4860
|
+
const target = e.target;
|
|
4861
|
+
if (!target || !((_containerRef$current = containerRef.current) === null || _containerRef$current === void 0 ? void 0 : _containerRef$current.contains(target))) return;
|
|
4862
|
+
const accept = (_configRef$current$ac = (_configRef$current3 = configRef.current) === null || _configRef$current3 === void 0 ? void 0 : _configRef$current3.accept) !== null && _configRef$current$ac !== void 0 ? _configRef$current$ac : "*/*";
|
|
4863
|
+
const fileItems = Array.from(((_e$clipboardData = e.clipboardData) === null || _e$clipboardData === void 0 ? void 0 : _e$clipboardData.items) || []).filter((item) => item.kind === "file" && item.getAsFile() !== null && (0, _copilotkit_shared.matchesAcceptFilter)(item.getAsFile(), accept));
|
|
4864
|
+
if (fileItems.length === 0) return;
|
|
4865
|
+
e.preventDefault();
|
|
4866
|
+
const files = fileItems.map((item) => item.getAsFile()).filter((f) => f !== null);
|
|
4867
|
+
try {
|
|
4868
|
+
await processFiles(files);
|
|
4869
|
+
} catch (error) {
|
|
4870
|
+
console.error("[CopilotKit] Paste error:", error);
|
|
4871
|
+
}
|
|
4872
|
+
};
|
|
4873
|
+
document.addEventListener("paste", handlePaste);
|
|
4874
|
+
return () => document.removeEventListener("paste", handlePaste);
|
|
4875
|
+
}, [enabled, processFiles]);
|
|
4876
|
+
return {
|
|
4877
|
+
attachments,
|
|
4878
|
+
enabled,
|
|
4879
|
+
dragOver,
|
|
4880
|
+
fileInputRef,
|
|
4881
|
+
containerRef,
|
|
4882
|
+
processFiles,
|
|
4883
|
+
handleFileUpload,
|
|
4884
|
+
handleDragOver,
|
|
4885
|
+
handleDragLeave,
|
|
4886
|
+
handleDrop,
|
|
4887
|
+
removeAttachment: (0, react.useCallback)((id) => {
|
|
4888
|
+
setAttachments((prev) => prev.filter((a) => a.id !== id));
|
|
4889
|
+
}, []),
|
|
4890
|
+
consumeAttachments: (0, react.useCallback)(() => {
|
|
4891
|
+
const ready = attachmentsRef.current.filter((a) => a.status === "ready");
|
|
4892
|
+
if (ready.length === 0) return ready;
|
|
4893
|
+
setAttachments((prev) => prev.filter((a) => a.status !== "ready"));
|
|
4894
|
+
if (fileInputRef.current) fileInputRef.current.value = "";
|
|
4895
|
+
return ready;
|
|
4896
|
+
}, [])
|
|
4897
|
+
};
|
|
4898
|
+
}
|
|
4899
|
+
|
|
3700
4900
|
//#endregion
|
|
3701
4901
|
//#region src/v2/components/chat/CopilotChatToolCallsView.tsx
|
|
3702
4902
|
function CopilotChatToolCallsView({ message, messages = [] }) {
|
|
@@ -3816,9 +5016,19 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3816
5016
|
const config = useCopilotChatConfiguration();
|
|
3817
5017
|
const labels = (_config$labels = config === null || config === void 0 ? void 0 : config.labels) !== null && _config$labels !== void 0 ? _config$labels : CopilotChatDefaultLabels;
|
|
3818
5018
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
5019
|
+
const timerRef = (0, react.useRef)(null);
|
|
5020
|
+
(0, react.useEffect)(() => {
|
|
5021
|
+
return () => {
|
|
5022
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
5023
|
+
};
|
|
5024
|
+
}, []);
|
|
3819
5025
|
const handleClick = (event) => {
|
|
3820
5026
|
setCopied(true);
|
|
3821
|
-
|
|
5027
|
+
if (timerRef.current !== null) clearTimeout(timerRef.current);
|
|
5028
|
+
timerRef.current = setTimeout(() => {
|
|
5029
|
+
timerRef.current = null;
|
|
5030
|
+
setCopied(false);
|
|
5031
|
+
}, 2e3);
|
|
3822
5032
|
if (onClick) onClick(event);
|
|
3823
5033
|
};
|
|
3824
5034
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
@@ -3884,6 +5094,80 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3884
5094
|
CopilotChatAssistantMessage.RegenerateButton.displayName = "CopilotChatAssistantMessage.RegenerateButton";
|
|
3885
5095
|
var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
|
|
3886
5096
|
|
|
5097
|
+
//#endregion
|
|
5098
|
+
//#region src/v2/components/chat/CopilotChatAttachmentRenderer.tsx
|
|
5099
|
+
const ImageAttachment = (0, react.memo)(function ImageAttachment({ src, className }) {
|
|
5100
|
+
const [error, setError] = (0, react.useState)(false);
|
|
5101
|
+
if (error) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5102
|
+
className: cn("cpk:flex cpk:flex-col cpk:items-center cpk:justify-center cpk:rounded-lg cpk:bg-muted cpk:p-4 cpk:text-sm cpk:text-muted-foreground", className),
|
|
5103
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { children: "Failed to load image" })
|
|
5104
|
+
});
|
|
5105
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
5106
|
+
src,
|
|
5107
|
+
alt: "Image attachment",
|
|
5108
|
+
className: cn("cpk:max-w-full cpk:h-auto cpk:rounded-lg", className),
|
|
5109
|
+
onError: () => setError(true)
|
|
5110
|
+
});
|
|
5111
|
+
});
|
|
5112
|
+
const AudioAttachment = (0, react.memo)(function AudioAttachment({ src, filename, className }) {
|
|
5113
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5114
|
+
className: cn("cpk:flex cpk:flex-col cpk:gap-1", className),
|
|
5115
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("audio", {
|
|
5116
|
+
src,
|
|
5117
|
+
controls: true,
|
|
5118
|
+
preload: "metadata",
|
|
5119
|
+
className: "cpk:max-w-[300px] cpk:w-full cpk:h-10"
|
|
5120
|
+
}), filename && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5121
|
+
className: "cpk:text-xs cpk:text-muted-foreground cpk:truncate cpk:max-w-[300px]",
|
|
5122
|
+
children: filename
|
|
5123
|
+
})]
|
|
5124
|
+
});
|
|
5125
|
+
});
|
|
5126
|
+
const VideoAttachment = (0, react.memo)(function VideoAttachment({ src, className }) {
|
|
5127
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
|
|
5128
|
+
src,
|
|
5129
|
+
controls: true,
|
|
5130
|
+
preload: "metadata",
|
|
5131
|
+
className: cn("cpk:max-w-[400px] cpk:w-full cpk:rounded-lg", className)
|
|
5132
|
+
});
|
|
5133
|
+
});
|
|
5134
|
+
const DocumentAttachment = (0, react.memo)(function DocumentAttachment({ source, filename, className }) {
|
|
5135
|
+
var _source$mimeType;
|
|
5136
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5137
|
+
className: cn("cpk:inline-flex cpk:items-center cpk:gap-2 cpk:px-3 cpk:py-2 cpk:border cpk:border-border cpk:rounded-lg cpk:bg-muted", className),
|
|
5138
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5139
|
+
className: "cpk:text-xs cpk:font-bold cpk:uppercase",
|
|
5140
|
+
children: (0, _copilotkit_shared.getDocumentIcon)((_source$mimeType = source.mimeType) !== null && _source$mimeType !== void 0 ? _source$mimeType : "")
|
|
5141
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
5142
|
+
className: "cpk:text-sm cpk:text-muted-foreground cpk:truncate",
|
|
5143
|
+
children: filename || source.mimeType || "Unknown type"
|
|
5144
|
+
})]
|
|
5145
|
+
});
|
|
5146
|
+
});
|
|
5147
|
+
const CopilotChatAttachmentRenderer = ({ type, source, filename, className }) => {
|
|
5148
|
+
const src = (0, _copilotkit_shared.getSourceUrl)(source);
|
|
5149
|
+
switch (type) {
|
|
5150
|
+
case "image": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImageAttachment, {
|
|
5151
|
+
src,
|
|
5152
|
+
className
|
|
5153
|
+
});
|
|
5154
|
+
case "audio": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AudioAttachment, {
|
|
5155
|
+
src,
|
|
5156
|
+
filename,
|
|
5157
|
+
className
|
|
5158
|
+
});
|
|
5159
|
+
case "video": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VideoAttachment, {
|
|
5160
|
+
src,
|
|
5161
|
+
className
|
|
5162
|
+
});
|
|
5163
|
+
case "document": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocumentAttachment, {
|
|
5164
|
+
source,
|
|
5165
|
+
filename,
|
|
5166
|
+
className
|
|
5167
|
+
});
|
|
5168
|
+
}
|
|
5169
|
+
};
|
|
5170
|
+
|
|
3887
5171
|
//#endregion
|
|
3888
5172
|
//#region src/v2/components/chat/CopilotChatUserMessage.tsx
|
|
3889
5173
|
function flattenUserMessageContent(content) {
|
|
@@ -3894,8 +5178,17 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3894
5178
|
return "";
|
|
3895
5179
|
}).filter((text) => text.length > 0).join("\n");
|
|
3896
5180
|
}
|
|
5181
|
+
function getMediaParts(content) {
|
|
5182
|
+
if (!content || typeof content === "string") return [];
|
|
5183
|
+
return content.filter((part) => part.type === "image" || part.type === "audio" || part.type === "video" || part.type === "document");
|
|
5184
|
+
}
|
|
5185
|
+
function getFilename(part) {
|
|
5186
|
+
const meta = part.metadata;
|
|
5187
|
+
if (meta != null && typeof meta === "object" && "filename" in meta && typeof meta.filename === "string") return meta.filename;
|
|
5188
|
+
}
|
|
3897
5189
|
function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfBranches, onSwitchToBranch, additionalToolbarItems, messageRenderer, toolbar, copyButton, editButton, branchNavigation, children, className, ...props }) {
|
|
3898
5190
|
const flattenedContent = (0, react.useMemo)(() => flattenUserMessageContent(message.content), [message.content]);
|
|
5191
|
+
const mediaParts = (0, react.useMemo)(() => getMediaParts(message.content), [message.content]);
|
|
3899
5192
|
const BoundMessageRenderer = renderSlot(messageRenderer, CopilotChatUserMessage.MessageRenderer, { content: flattenedContent });
|
|
3900
5193
|
const BoundCopyButton = renderSlot(copyButton, CopilotChatUserMessage.CopyButton, { onClick: async () => {
|
|
3901
5194
|
if (flattenedContent) try {
|
|
@@ -3942,7 +5235,18 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3942
5235
|
className: (0, tailwind_merge.twMerge)("copilotKitMessage copilotKitUserMessage cpk:flex cpk:flex-col cpk:items-end cpk:group cpk:pt-10", className),
|
|
3943
5236
|
"data-message-id": message.id,
|
|
3944
5237
|
...props,
|
|
3945
|
-
children: [
|
|
5238
|
+
children: [
|
|
5239
|
+
BoundMessageRenderer,
|
|
5240
|
+
mediaParts.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5241
|
+
className: "cpk:flex cpk:flex-col cpk:items-end cpk:gap-2 cpk:mt-2",
|
|
5242
|
+
children: mediaParts.map((part, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatAttachmentRenderer, {
|
|
5243
|
+
type: part.type,
|
|
5244
|
+
source: part.source,
|
|
5245
|
+
filename: getFilename(part)
|
|
5246
|
+
}, index))
|
|
5247
|
+
}),
|
|
5248
|
+
BoundToolbar
|
|
5249
|
+
]
|
|
3946
5250
|
});
|
|
3947
5251
|
}
|
|
3948
5252
|
(function(_CopilotChatUserMessage) {
|
|
@@ -4245,6 +5549,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4245
5549
|
const isLoading = loadingSet.has(index) || suggestion.isLoading === true;
|
|
4246
5550
|
const pill = renderSlot(suggestionSlot, CopilotChatSuggestionPill, {
|
|
4247
5551
|
children: suggestion.title,
|
|
5552
|
+
className: suggestion.className,
|
|
4248
5553
|
isLoading,
|
|
4249
5554
|
type: "button",
|
|
4250
5555
|
onClick: () => onSelectSuggestion === null || onSelectSuggestion === void 0 ? void 0 : onSelectSuggestion(suggestion, index)
|
|
@@ -4282,9 +5587,43 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4282
5587
|
});
|
|
4283
5588
|
CopilotChatSuggestionView.displayName = "CopilotChatSuggestionView";
|
|
4284
5589
|
|
|
5590
|
+
//#endregion
|
|
5591
|
+
//#region src/v2/components/chat/scroll-element-context.ts
|
|
5592
|
+
/**
|
|
5593
|
+
* Provides the scroll container element to child components that need it for
|
|
5594
|
+
* virtualization. Set by CopilotChatView.ScrollView; consumed by
|
|
5595
|
+
* CopilotChatMessageView to feed useVirtualizer's getScrollElement.
|
|
5596
|
+
*
|
|
5597
|
+
* Carries the element itself (not a ref) so that context consumers re-render
|
|
5598
|
+
* reactively when the scroll container is first mounted.
|
|
5599
|
+
*/
|
|
5600
|
+
const ScrollElementContext = react.default.createContext(null);
|
|
5601
|
+
|
|
4285
5602
|
//#endregion
|
|
4286
5603
|
//#region src/v2/components/chat/CopilotChatMessageView.tsx
|
|
4287
5604
|
/**
|
|
5605
|
+
* Resolves a slot value into a { Component, slotProps } pair, handling the three
|
|
5606
|
+
* slot forms: a component type, a className string, or a partial-props object.
|
|
5607
|
+
*/
|
|
5608
|
+
function resolveSlotComponent(slot, DefaultComponent) {
|
|
5609
|
+
if (isReactComponentType(slot)) return {
|
|
5610
|
+
Component: slot,
|
|
5611
|
+
slotProps: void 0
|
|
5612
|
+
};
|
|
5613
|
+
if (typeof slot === "string") return {
|
|
5614
|
+
Component: DefaultComponent,
|
|
5615
|
+
slotProps: { className: slot }
|
|
5616
|
+
};
|
|
5617
|
+
if (slot && typeof slot === "object") return {
|
|
5618
|
+
Component: DefaultComponent,
|
|
5619
|
+
slotProps: slot
|
|
5620
|
+
};
|
|
5621
|
+
return {
|
|
5622
|
+
Component: DefaultComponent,
|
|
5623
|
+
slotProps: void 0
|
|
5624
|
+
};
|
|
5625
|
+
}
|
|
5626
|
+
/**
|
|
4288
5627
|
* Memoized wrapper for assistant messages to prevent re-renders when other messages change.
|
|
4289
5628
|
*/
|
|
4290
5629
|
const MemoizedAssistantMessage = react.default.memo(function MemoizedAssistantMessage({ message, messages, isRunning, AssistantMessageComponent, slotProps }) {
|
|
@@ -4304,7 +5643,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4304
5643
|
if (prevToolCalls && nextToolCalls) for (let i = 0; i < prevToolCalls.length; i++) {
|
|
4305
5644
|
const prevTc = prevToolCalls[i];
|
|
4306
5645
|
const nextTc = nextToolCalls[i];
|
|
4307
|
-
if (!prevTc || !nextTc) return false;
|
|
4308
5646
|
if (prevTc.id !== nextTc.id) return false;
|
|
4309
5647
|
if (prevTc.function.arguments !== nextTc.function.arguments) return false;
|
|
4310
5648
|
}
|
|
@@ -4384,7 +5722,9 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4384
5722
|
if (JSON.stringify(prevProps.stateSnapshot) !== JSON.stringify(nextProps.stateSnapshot)) return false;
|
|
4385
5723
|
return true;
|
|
4386
5724
|
});
|
|
5725
|
+
const VIRTUALIZE_THRESHOLD = 50;
|
|
4387
5726
|
function CopilotChatMessageView({ messages = [], assistantMessage, userMessage, reasoningMessage, cursor, isRunning = false, children, className, ...props }) {
|
|
5727
|
+
var _deduplicatedMessages;
|
|
4388
5728
|
const renderCustomMessage = useRenderCustomMessages();
|
|
4389
5729
|
const { renderActivityMessage } = useRenderActivityMessage();
|
|
4390
5730
|
const { copilotkit } = useCopilotKit();
|
|
@@ -4419,9 +5759,36 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4419
5759
|
if (!resolvedRunId) return void 0;
|
|
4420
5760
|
return copilotkit.getStateByRun(config.agentId, config.threadId, resolvedRunId);
|
|
4421
5761
|
};
|
|
4422
|
-
const deduplicatedMessages = [...new Map(messages.map((m) => [m.id, m])).values()];
|
|
5762
|
+
const deduplicatedMessages = (0, react.useMemo)(() => [...new Map(messages.map((m) => [m.id, m])).values()], [messages]);
|
|
4423
5763
|
if (process.env.NODE_ENV === "development" && deduplicatedMessages.length < messages.length) console.warn(`CopilotChatMessageView: Deduplicated ${messages.length - deduplicatedMessages.length} message(s) with duplicate IDs.`);
|
|
4424
|
-
const
|
|
5764
|
+
const { Component: AssistantComponent, slotProps: assistantSlotProps } = (0, react.useMemo)(() => resolveSlotComponent(assistantMessage, CopilotChatAssistantMessage_default), [assistantMessage]);
|
|
5765
|
+
const { Component: UserComponent, slotProps: userSlotProps } = (0, react.useMemo)(() => resolveSlotComponent(userMessage, CopilotChatUserMessage_default), [userMessage]);
|
|
5766
|
+
const { Component: ReasoningComponent, slotProps: reasoningSlotProps } = (0, react.useMemo)(() => resolveSlotComponent(reasoningMessage, CopilotChatReasoningMessage_default), [reasoningMessage]);
|
|
5767
|
+
const scrollElementFromCtx = (0, react.useContext)(ScrollElementContext);
|
|
5768
|
+
const scrollElement = scrollElementFromCtx && scrollElementFromCtx.clientHeight > 0 ? scrollElementFromCtx : null;
|
|
5769
|
+
(0, react.useEffect)(() => {
|
|
5770
|
+
if (process.env.NODE_ENV !== "production" && scrollElementFromCtx && scrollElementFromCtx.clientHeight === 0) console.warn("[CopilotKit] Chat scroll container has clientHeight=0 — virtualization disabled. Ensure the chat is rendered in a visible container with a non-zero height.");
|
|
5771
|
+
}, [scrollElementFromCtx]);
|
|
5772
|
+
const shouldVirtualize = !!scrollElement && !children && deduplicatedMessages.length > VIRTUALIZE_THRESHOLD;
|
|
5773
|
+
const virtualizer = (0, _tanstack_react_virtual.useVirtualizer)({
|
|
5774
|
+
count: shouldVirtualize ? deduplicatedMessages.length : 0,
|
|
5775
|
+
getScrollElement: () => scrollElement,
|
|
5776
|
+
estimateSize: () => 100,
|
|
5777
|
+
overscan: 5,
|
|
5778
|
+
measureElement: (el) => {
|
|
5779
|
+
var _el$getBoundingClient;
|
|
5780
|
+
return (_el$getBoundingClient = el === null || el === void 0 ? void 0 : el.getBoundingClientRect().height) !== null && _el$getBoundingClient !== void 0 ? _el$getBoundingClient : 0;
|
|
5781
|
+
},
|
|
5782
|
+
initialRect: {
|
|
5783
|
+
width: 0,
|
|
5784
|
+
height: 600
|
|
5785
|
+
}
|
|
5786
|
+
});
|
|
5787
|
+
(0, react.useLayoutEffect)(() => {
|
|
5788
|
+
if (!shouldVirtualize || !deduplicatedMessages.length) return;
|
|
5789
|
+
virtualizer.scrollToIndex(deduplicatedMessages.length - 1, { align: "end" });
|
|
5790
|
+
}, [shouldVirtualize, (_deduplicatedMessages = deduplicatedMessages[0]) === null || _deduplicatedMessages === void 0 ? void 0 : _deduplicatedMessages.id]);
|
|
5791
|
+
const renderMessageBlock = (message) => {
|
|
4425
5792
|
const elements = [];
|
|
4426
5793
|
const stateSnapshot = getStateSnapshotForMessage(message.id);
|
|
4427
5794
|
if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
|
|
@@ -4430,58 +5797,38 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4430
5797
|
renderCustomMessage,
|
|
4431
5798
|
stateSnapshot
|
|
4432
5799
|
}, `${message.id}-custom-before`));
|
|
4433
|
-
if (message.role === "assistant") {
|
|
4434
|
-
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
|
|
4438
|
-
|
|
4439
|
-
|
|
4440
|
-
|
|
4441
|
-
|
|
4442
|
-
|
|
4443
|
-
|
|
4444
|
-
|
|
4445
|
-
|
|
4446
|
-
|
|
4447
|
-
|
|
4448
|
-
|
|
4449
|
-
|
|
4450
|
-
|
|
4451
|
-
|
|
4452
|
-
|
|
4453
|
-
|
|
4454
|
-
|
|
4455
|
-
|
|
4456
|
-
}, message.id));
|
|
4457
|
-
} else if (message.role === "activity") {
|
|
4458
|
-
const activityMsg = message;
|
|
4459
|
-
elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedActivityMessage, {
|
|
4460
|
-
message: activityMsg,
|
|
4461
|
-
renderActivityMessage
|
|
4462
|
-
}, message.id));
|
|
4463
|
-
} else if (message.role === "reasoning") {
|
|
4464
|
-
let ReasoningComponent = CopilotChatReasoningMessage_default;
|
|
4465
|
-
let reasoningSlotProps;
|
|
4466
|
-
if (isReactComponentType(reasoningMessage)) ReasoningComponent = reasoningMessage;
|
|
4467
|
-
else if (typeof reasoningMessage === "string") reasoningSlotProps = { className: reasoningMessage };
|
|
4468
|
-
else if (reasoningMessage && typeof reasoningMessage === "object") reasoningSlotProps = reasoningMessage;
|
|
4469
|
-
elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedReasoningMessage, {
|
|
4470
|
-
message,
|
|
4471
|
-
messages,
|
|
4472
|
-
isRunning,
|
|
4473
|
-
ReasoningMessageComponent: ReasoningComponent,
|
|
4474
|
-
slotProps: reasoningSlotProps
|
|
4475
|
-
}, message.id));
|
|
4476
|
-
}
|
|
5800
|
+
if (message.role === "assistant") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedAssistantMessage, {
|
|
5801
|
+
message,
|
|
5802
|
+
messages,
|
|
5803
|
+
isRunning,
|
|
5804
|
+
AssistantMessageComponent: AssistantComponent,
|
|
5805
|
+
slotProps: assistantSlotProps
|
|
5806
|
+
}, message.id));
|
|
5807
|
+
else if (message.role === "user") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedUserMessage, {
|
|
5808
|
+
message,
|
|
5809
|
+
UserMessageComponent: UserComponent,
|
|
5810
|
+
slotProps: userSlotProps
|
|
5811
|
+
}, message.id));
|
|
5812
|
+
else if (message.role === "activity") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedActivityMessage, {
|
|
5813
|
+
message,
|
|
5814
|
+
renderActivityMessage
|
|
5815
|
+
}, message.id));
|
|
5816
|
+
else if (message.role === "reasoning") elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedReasoningMessage, {
|
|
5817
|
+
message,
|
|
5818
|
+
messages,
|
|
5819
|
+
isRunning,
|
|
5820
|
+
ReasoningMessageComponent: ReasoningComponent,
|
|
5821
|
+
slotProps: reasoningSlotProps
|
|
5822
|
+
}, message.id));
|
|
4477
5823
|
if (renderCustomMessage) elements.push(/* @__PURE__ */ (0, react_jsx_runtime.jsx)(MemoizedCustomMessage, {
|
|
4478
5824
|
message,
|
|
4479
5825
|
position: "after",
|
|
4480
5826
|
renderCustomMessage,
|
|
4481
5827
|
stateSnapshot
|
|
4482
5828
|
}, `${message.id}-custom-after`));
|
|
4483
|
-
return elements;
|
|
4484
|
-
}
|
|
5829
|
+
return elements.filter(Boolean);
|
|
5830
|
+
};
|
|
5831
|
+
const messageElements = shouldVirtualize ? [] : deduplicatedMessages.flatMap(renderMessageBlock);
|
|
4485
5832
|
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4486
5833
|
"data-copilotkit": true,
|
|
4487
5834
|
style: { display: "contents" },
|
|
@@ -4492,30 +5839,356 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4492
5839
|
interruptElement
|
|
4493
5840
|
})
|
|
4494
5841
|
});
|
|
4495
|
-
const lastMessage = messages[messages.length - 1];
|
|
4496
|
-
const showCursor = isRunning && (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) !== "reasoning";
|
|
5842
|
+
const lastMessage = messages[messages.length - 1];
|
|
5843
|
+
const showCursor = isRunning && (lastMessage === null || lastMessage === void 0 ? void 0 : lastMessage.role) !== "reasoning";
|
|
5844
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5845
|
+
"data-copilotkit": true,
|
|
5846
|
+
"data-testid": "copilot-message-list",
|
|
5847
|
+
className: (0, tailwind_merge.twMerge)("copilotKitMessages cpk:flex cpk:flex-col", className),
|
|
5848
|
+
...props,
|
|
5849
|
+
children: [
|
|
5850
|
+
shouldVirtualize ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5851
|
+
style: {
|
|
5852
|
+
height: virtualizer.getTotalSize(),
|
|
5853
|
+
position: "relative"
|
|
5854
|
+
},
|
|
5855
|
+
children: virtualizer.getVirtualItems().map((virtualItem) => {
|
|
5856
|
+
const message = deduplicatedMessages[virtualItem.index];
|
|
5857
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5858
|
+
"data-index": virtualItem.index,
|
|
5859
|
+
ref: virtualizer.measureElement,
|
|
5860
|
+
style: {
|
|
5861
|
+
position: "absolute",
|
|
5862
|
+
top: 0,
|
|
5863
|
+
left: 0,
|
|
5864
|
+
width: "100%",
|
|
5865
|
+
transform: `translateY(${virtualItem.start}px)`
|
|
5866
|
+
},
|
|
5867
|
+
children: renderMessageBlock(message)
|
|
5868
|
+
}, message.id);
|
|
5869
|
+
})
|
|
5870
|
+
}) : messageElements,
|
|
5871
|
+
interruptElement,
|
|
5872
|
+
showCursor && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5873
|
+
className: "cpk:mt-2",
|
|
5874
|
+
children: renderSlot(cursor, CopilotChatMessageView.Cursor, {})
|
|
5875
|
+
})
|
|
5876
|
+
]
|
|
5877
|
+
});
|
|
5878
|
+
}
|
|
5879
|
+
CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
|
|
5880
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5881
|
+
"data-testid": "copilot-loading-cursor",
|
|
5882
|
+
className: (0, tailwind_merge.twMerge)("cpk:w-[11px] cpk:h-[11px] cpk:rounded-full cpk:bg-foreground cpk:animate-pulse-cursor cpk:ml-1", className),
|
|
5883
|
+
...props
|
|
5884
|
+
});
|
|
5885
|
+
};
|
|
5886
|
+
|
|
5887
|
+
//#endregion
|
|
5888
|
+
//#region src/v2/components/chat/CopilotChatAttachmentQueue.tsx
|
|
5889
|
+
const CopilotChatAttachmentQueue = ({ attachments, onRemoveAttachment, className }) => {
|
|
5890
|
+
if (attachments.length === 0) return null;
|
|
5891
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5892
|
+
className: cn("cpk:flex cpk:flex-wrap cpk:gap-2 cpk:p-2", className),
|
|
5893
|
+
children: attachments.map((attachment) => {
|
|
5894
|
+
const isMedia = attachment.type === "image" || attachment.type === "video";
|
|
5895
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5896
|
+
className: cn("cpk:relative cpk:inline-flex cpk:rounded-lg cpk:overflow-hidden cpk:border cpk:border-border", isMedia ? "cpk:w-[72px] cpk:h-[72px]" : attachment.type === "audio" ? "cpk:min-w-[200px] cpk:max-w-[280px] cpk:flex-col cpk:p-1 cpk:pr-8" : "cpk:p-2 cpk:px-3 cpk:pr-8 cpk:max-w-[240px]"),
|
|
5897
|
+
children: [
|
|
5898
|
+
attachment.status === "uploading" && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(UploadingOverlay, {}),
|
|
5899
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(AttachmentPreview, { attachment }),
|
|
5900
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5901
|
+
onClick: () => onRemoveAttachment(attachment.id),
|
|
5902
|
+
className: cn("cpk:absolute cpk:bg-black/60 cpk:text-white cpk:border-none cpk:rounded-full cpk:w-5 cpk:h-5 cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer cpk:text-[10px] cpk:z-20", isMedia ? "cpk:top-1 cpk:right-1" : "cpk:top-1.5 cpk:right-1.5"),
|
|
5903
|
+
"aria-label": "Remove attachment",
|
|
5904
|
+
children: "✕"
|
|
5905
|
+
})
|
|
5906
|
+
]
|
|
5907
|
+
}, attachment.id);
|
|
5908
|
+
})
|
|
5909
|
+
});
|
|
5910
|
+
};
|
|
5911
|
+
function UploadingOverlay() {
|
|
5912
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5913
|
+
className: "cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:bg-black/40 cpk:z-10",
|
|
5914
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "cpk:w-5 cpk:h-5 cpk:border-2 cpk:border-white cpk:border-t-transparent cpk:rounded-full cpk:animate-spin" })
|
|
5915
|
+
});
|
|
5916
|
+
}
|
|
5917
|
+
function AttachmentPreview({ attachment }) {
|
|
5918
|
+
if (attachment.status === "uploading") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { className: "cpk:w-full cpk:h-full" });
|
|
5919
|
+
switch (attachment.type) {
|
|
5920
|
+
case "image": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ImagePreview, { attachment });
|
|
5921
|
+
case "audio": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(AudioPreview, { attachment });
|
|
5922
|
+
case "video": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(VideoPreview, { attachment });
|
|
5923
|
+
case "document": return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocumentPreview, { attachment });
|
|
5924
|
+
}
|
|
5925
|
+
}
|
|
5926
|
+
function Lightbox({ onClose, children }) {
|
|
5927
|
+
(0, react.useEffect)(() => {
|
|
5928
|
+
const handleKey = (e) => {
|
|
5929
|
+
if (e.key === "Escape") onClose();
|
|
5930
|
+
};
|
|
5931
|
+
document.addEventListener("keydown", handleKey);
|
|
5932
|
+
return () => document.removeEventListener("keydown", handleKey);
|
|
5933
|
+
}, [onClose]);
|
|
5934
|
+
if (typeof document === "undefined") return null;
|
|
5935
|
+
return (0, react_dom.createPortal)(/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
5936
|
+
className: "cpk:fixed cpk:inset-0 cpk:z-[9999] cpk:flex cpk:items-center cpk:justify-center cpk:bg-black/80 cpk:animate-fade-in",
|
|
5937
|
+
onClick: onClose,
|
|
5938
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
5939
|
+
onClick: onClose,
|
|
5940
|
+
className: "cpk:absolute cpk:top-4 cpk:right-4 cpk:text-white cpk:bg-white/10 cpk:hover:bg-white/20 cpk:rounded-full cpk:w-10 cpk:h-10 cpk:flex cpk:items-center cpk:justify-center cpk:cursor-pointer cpk:border-none cpk:z-10",
|
|
5941
|
+
"aria-label": "Close preview",
|
|
5942
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "cpk:w-5 cpk:h-5" })
|
|
5943
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
5944
|
+
onClick: (e) => e.stopPropagation(),
|
|
5945
|
+
children
|
|
5946
|
+
})]
|
|
5947
|
+
}), document.body);
|
|
5948
|
+
}
|
|
5949
|
+
/**
|
|
5950
|
+
* Hook that manages lightbox open/close and uses the View Transition API to
|
|
5951
|
+
* morph the thumbnail into fullscreen content.
|
|
5952
|
+
*
|
|
5953
|
+
* The trick: `view-transition-name` must live on exactly ONE element at a time.
|
|
5954
|
+
* - Old state (thumbnail visible): name is on the thumbnail.
|
|
5955
|
+
* - New state (lightbox visible): name moves to the lightbox content.
|
|
5956
|
+
* `flushSync` ensures React commits the DOM change synchronously inside the
|
|
5957
|
+
* `startViewTransition` callback so the API can snapshot old → new correctly.
|
|
5958
|
+
*/
|
|
5959
|
+
function useLightbox() {
|
|
5960
|
+
const thumbnailRef = (0, react.useRef)(null);
|
|
5961
|
+
const [open, setOpen] = (0, react.useState)(false);
|
|
5962
|
+
const vtName = (0, react.useId)();
|
|
5963
|
+
return {
|
|
5964
|
+
thumbnailRef,
|
|
5965
|
+
vtName,
|
|
5966
|
+
open,
|
|
5967
|
+
openLightbox: (0, react.useCallback)(() => {
|
|
5968
|
+
const thumb = thumbnailRef.current;
|
|
5969
|
+
const doc = document;
|
|
5970
|
+
if (doc.startViewTransition && thumb) {
|
|
5971
|
+
thumb.style.viewTransitionName = vtName;
|
|
5972
|
+
doc.startViewTransition(() => {
|
|
5973
|
+
thumb.style.viewTransitionName = "";
|
|
5974
|
+
(0, react_dom.flushSync)(() => setOpen(true));
|
|
5975
|
+
});
|
|
5976
|
+
} else setOpen(true);
|
|
5977
|
+
}, []),
|
|
5978
|
+
closeLightbox: (0, react.useCallback)(() => {
|
|
5979
|
+
const thumb = thumbnailRef.current;
|
|
5980
|
+
const doc = document;
|
|
5981
|
+
if (doc.startViewTransition && thumb) doc.startViewTransition(() => {
|
|
5982
|
+
(0, react_dom.flushSync)(() => setOpen(false));
|
|
5983
|
+
thumb.style.viewTransitionName = vtName;
|
|
5984
|
+
}).finished.then(() => {
|
|
5985
|
+
thumb.style.viewTransitionName = "";
|
|
5986
|
+
}).catch(() => {
|
|
5987
|
+
thumb.style.viewTransitionName = "";
|
|
5988
|
+
});
|
|
5989
|
+
else setOpen(false);
|
|
5990
|
+
}, [])
|
|
5991
|
+
};
|
|
5992
|
+
}
|
|
5993
|
+
function ImagePreview({ attachment }) {
|
|
5994
|
+
const src = (0, _copilotkit_shared.getSourceUrl)(attachment.source);
|
|
5995
|
+
const { thumbnailRef, vtName, open, openLightbox, closeLightbox } = useLightbox();
|
|
5996
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
5997
|
+
ref: thumbnailRef,
|
|
5998
|
+
src,
|
|
5999
|
+
alt: attachment.filename || "Image attachment",
|
|
6000
|
+
className: "cpk:w-full cpk:h-full cpk:object-cover cpk:cursor-pointer",
|
|
6001
|
+
onClick: openLightbox
|
|
6002
|
+
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Lightbox, {
|
|
6003
|
+
onClose: closeLightbox,
|
|
6004
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
6005
|
+
style: { viewTransitionName: vtName },
|
|
6006
|
+
src,
|
|
6007
|
+
alt: attachment.filename || "Image attachment",
|
|
6008
|
+
className: "cpk:max-w-[90vw] cpk:max-h-[90vh] cpk:object-contain cpk:rounded-lg"
|
|
6009
|
+
})
|
|
6010
|
+
})] });
|
|
6011
|
+
}
|
|
6012
|
+
function AudioPreview({ attachment }) {
|
|
6013
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6014
|
+
className: "cpk:flex cpk:flex-col cpk:gap-1 cpk:w-full",
|
|
6015
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("audio", {
|
|
6016
|
+
src: (0, _copilotkit_shared.getSourceUrl)(attachment.source),
|
|
6017
|
+
controls: true,
|
|
6018
|
+
preload: "metadata",
|
|
6019
|
+
className: "cpk:w-full cpk:h-8"
|
|
6020
|
+
}), attachment.filename && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6021
|
+
className: "cpk:text-xs cpk:font-medium cpk:overflow-hidden cpk:text-ellipsis cpk:whitespace-nowrap",
|
|
6022
|
+
children: attachment.filename
|
|
6023
|
+
})]
|
|
6024
|
+
});
|
|
6025
|
+
}
|
|
6026
|
+
function VideoPreview({ attachment }) {
|
|
6027
|
+
const src = (0, _copilotkit_shared.getSourceUrl)(attachment.source);
|
|
6028
|
+
const { thumbnailRef, vtName, open, openLightbox, closeLightbox } = useLightbox();
|
|
6029
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6030
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6031
|
+
ref: thumbnailRef,
|
|
6032
|
+
className: "cpk:w-full cpk:h-full",
|
|
6033
|
+
children: attachment.thumbnail ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("img", {
|
|
6034
|
+
src: attachment.thumbnail,
|
|
6035
|
+
alt: attachment.filename || "Video thumbnail",
|
|
6036
|
+
className: "cpk:w-full cpk:h-full cpk:object-cover"
|
|
6037
|
+
}) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
|
|
6038
|
+
src,
|
|
6039
|
+
preload: "metadata",
|
|
6040
|
+
muted: true,
|
|
6041
|
+
className: "cpk:w-full cpk:h-full cpk:object-cover"
|
|
6042
|
+
})
|
|
6043
|
+
}),
|
|
6044
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6045
|
+
onClick: openLightbox,
|
|
6046
|
+
className: "cpk:absolute cpk:inset-0 cpk:flex cpk:items-center cpk:justify-center cpk:z-10 cpk:cursor-pointer cpk:bg-black/20 cpk:border-none cpk:p-0",
|
|
6047
|
+
"aria-label": "Play video",
|
|
6048
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6049
|
+
className: "cpk:w-8 cpk:h-8 cpk:rounded-full cpk:bg-black/60 cpk:flex cpk:items-center cpk:justify-center",
|
|
6050
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Play, { className: "cpk:w-4 cpk:h-4 cpk:text-white cpk:ml-0.5" })
|
|
6051
|
+
})
|
|
6052
|
+
}),
|
|
6053
|
+
open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Lightbox, {
|
|
6054
|
+
onClose: closeLightbox,
|
|
6055
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("video", {
|
|
6056
|
+
style: { viewTransitionName: vtName },
|
|
6057
|
+
src,
|
|
6058
|
+
controls: true,
|
|
6059
|
+
autoPlay: true,
|
|
6060
|
+
className: "cpk:max-w-[90vw] cpk:max-h-[90vh] cpk:rounded-lg"
|
|
6061
|
+
})
|
|
6062
|
+
})
|
|
6063
|
+
] });
|
|
6064
|
+
}
|
|
6065
|
+
function isPdf(mimeType) {
|
|
6066
|
+
return !!mimeType && mimeType.includes("pdf");
|
|
6067
|
+
}
|
|
6068
|
+
function isText(mimeType) {
|
|
6069
|
+
return !!mimeType && mimeType.startsWith("text/");
|
|
6070
|
+
}
|
|
6071
|
+
function canPreviewInBrowser(mimeType) {
|
|
6072
|
+
return isPdf(mimeType) || isText(mimeType);
|
|
6073
|
+
}
|
|
6074
|
+
/**
|
|
6075
|
+
* Convert a base64-encoded data source to a blob: URL that browsers will
|
|
6076
|
+
* render inside an iframe (data: URLs are blocked for PDFs in most browsers).
|
|
6077
|
+
*/
|
|
6078
|
+
function useBlobUrl(attachment) {
|
|
6079
|
+
const [url, setUrl] = (0, react.useState)(null);
|
|
6080
|
+
(0, react.useEffect)(() => {
|
|
6081
|
+
if (attachment.source.type !== "data") return;
|
|
6082
|
+
try {
|
|
6083
|
+
const binary = atob(attachment.source.value);
|
|
6084
|
+
const bytes = new Uint8Array(binary.length);
|
|
6085
|
+
for (let i = 0; i < binary.length; i++) bytes[i] = binary.charCodeAt(i);
|
|
6086
|
+
const blob = new Blob([bytes], { type: attachment.source.mimeType || "application/octet-stream" });
|
|
6087
|
+
const blobUrl = URL.createObjectURL(blob);
|
|
6088
|
+
setUrl(blobUrl);
|
|
6089
|
+
return () => URL.revokeObjectURL(blobUrl);
|
|
6090
|
+
} catch (error) {
|
|
6091
|
+
console.error("[CopilotKit] Failed to decode attachment data:", error);
|
|
6092
|
+
setUrl(null);
|
|
6093
|
+
}
|
|
6094
|
+
}, [
|
|
6095
|
+
attachment.source.type,
|
|
6096
|
+
attachment.source.value,
|
|
6097
|
+
attachment.source.mimeType
|
|
6098
|
+
]);
|
|
6099
|
+
if (attachment.source.type === "url") return attachment.source.value;
|
|
6100
|
+
return url;
|
|
6101
|
+
}
|
|
6102
|
+
function DocumentLightboxContent({ attachment, vtName }) {
|
|
6103
|
+
const mimeType = attachment.source.mimeType;
|
|
6104
|
+
const blobUrl = useBlobUrl(attachment);
|
|
6105
|
+
if (isPdf(mimeType)) {
|
|
6106
|
+
if (!blobUrl) return null;
|
|
6107
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
|
|
6108
|
+
style: { viewTransitionName: vtName },
|
|
6109
|
+
src: blobUrl,
|
|
6110
|
+
title: attachment.filename || "PDF preview",
|
|
6111
|
+
className: "cpk:w-[90vw] cpk:h-[90vh] cpk:max-w-[1000px] cpk:rounded-lg cpk:bg-white"
|
|
6112
|
+
});
|
|
6113
|
+
}
|
|
6114
|
+
if (isText(mimeType)) {
|
|
6115
|
+
const textContent = attachment.source.type === "data" ? (() => {
|
|
6116
|
+
try {
|
|
6117
|
+
return atob(attachment.source.value);
|
|
6118
|
+
} catch (_unused) {
|
|
6119
|
+
return attachment.source.value;
|
|
6120
|
+
}
|
|
6121
|
+
})() : null;
|
|
6122
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6123
|
+
style: { viewTransitionName: vtName },
|
|
6124
|
+
className: "cpk:w-[90vw] cpk:max-w-[800px] cpk:max-h-[90vh] cpk:overflow-auto cpk:rounded-lg cpk:bg-white cpk:dark:bg-gray-900 cpk:p-6",
|
|
6125
|
+
children: [attachment.filename && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6126
|
+
className: "cpk:text-sm cpk:font-medium cpk:text-gray-500 cpk:dark:text-gray-400 cpk:mb-4 cpk:pb-2 cpk:border-b cpk:border-gray-200 cpk:dark:border-gray-700",
|
|
6127
|
+
children: attachment.filename
|
|
6128
|
+
}), textContent ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
6129
|
+
className: "cpk:text-sm cpk:whitespace-pre-wrap cpk:break-words cpk:text-gray-800 cpk:dark:text-gray-200 cpk:font-mono cpk:m-0",
|
|
6130
|
+
children: textContent
|
|
6131
|
+
}) : blobUrl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("iframe", {
|
|
6132
|
+
src: blobUrl,
|
|
6133
|
+
title: attachment.filename || "Text preview",
|
|
6134
|
+
className: "cpk:w-full cpk:h-[80vh] cpk:border-none"
|
|
6135
|
+
}) : null]
|
|
6136
|
+
});
|
|
6137
|
+
}
|
|
4497
6138
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4498
|
-
|
|
4499
|
-
"
|
|
4500
|
-
className: (0, tailwind_merge.twMerge)("copilotKitMessages cpk:flex cpk:flex-col", className),
|
|
4501
|
-
...props,
|
|
6139
|
+
style: { viewTransitionName: vtName },
|
|
6140
|
+
className: "cpk:flex cpk:flex-col cpk:items-center cpk:gap-4 cpk:p-8 cpk:rounded-lg cpk:bg-white cpk:dark:bg-gray-900",
|
|
4502
6141
|
children: [
|
|
4503
|
-
|
|
4504
|
-
|
|
4505
|
-
|
|
4506
|
-
|
|
4507
|
-
|
|
6142
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6143
|
+
className: "cpk:w-16 cpk:h-16 cpk:rounded-xl cpk:bg-primary cpk:text-primary-foreground cpk:flex cpk:items-center cpk:justify-center cpk:text-xl cpk:font-bold",
|
|
6144
|
+
children: (0, _copilotkit_shared.getDocumentIcon)(mimeType !== null && mimeType !== void 0 ? mimeType : "")
|
|
6145
|
+
}),
|
|
6146
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6147
|
+
className: "cpk:text-center",
|
|
6148
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6149
|
+
className: "cpk:text-base cpk:font-medium cpk:text-gray-800 cpk:dark:text-gray-200",
|
|
6150
|
+
children: attachment.filename || "Document"
|
|
6151
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6152
|
+
className: "cpk:text-sm cpk:text-gray-500 cpk:dark:text-gray-400 cpk:mt-1",
|
|
6153
|
+
children: [mimeType || "Unknown type", attachment.size != null && ` · ${(0, _copilotkit_shared.formatFileSize)(attachment.size)}`]
|
|
6154
|
+
})]
|
|
6155
|
+
}),
|
|
6156
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6157
|
+
className: "cpk:text-xs cpk:text-gray-400 cpk:dark:text-gray-500",
|
|
6158
|
+
children: "No preview available for this file type"
|
|
4508
6159
|
})
|
|
4509
6160
|
]
|
|
4510
6161
|
});
|
|
4511
6162
|
}
|
|
4512
|
-
|
|
4513
|
-
|
|
4514
|
-
|
|
4515
|
-
|
|
4516
|
-
|
|
4517
|
-
|
|
4518
|
-
|
|
6163
|
+
function DocumentPreview({ attachment }) {
|
|
6164
|
+
const { thumbnailRef, vtName, open, openLightbox, closeLightbox } = useLightbox();
|
|
6165
|
+
const mimeType = attachment.source.mimeType;
|
|
6166
|
+
const previewable = canPreviewInBrowser(mimeType);
|
|
6167
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6168
|
+
ref: thumbnailRef,
|
|
6169
|
+
className: cn("cpk:flex cpk:items-center cpk:gap-2", previewable && "cpk:cursor-pointer"),
|
|
6170
|
+
onClick: previewable ? openLightbox : void 0,
|
|
6171
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6172
|
+
className: "cpk:w-8 cpk:h-8 cpk:rounded-md cpk:bg-primary cpk:text-primary-foreground cpk:flex cpk:items-center cpk:justify-center cpk:text-[10px] cpk:font-semibold cpk:shrink-0",
|
|
6173
|
+
children: (0, _copilotkit_shared.getDocumentIcon)(mimeType !== null && mimeType !== void 0 ? mimeType : "")
|
|
6174
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6175
|
+
className: "cpk:flex cpk:flex-col cpk:min-w-0",
|
|
6176
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6177
|
+
className: "cpk:text-xs cpk:font-medium cpk:break-all cpk:leading-tight",
|
|
6178
|
+
children: attachment.filename || "Document"
|
|
6179
|
+
}), attachment.size != null && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6180
|
+
className: "cpk:text-[11px] cpk:text-muted-foreground",
|
|
6181
|
+
children: (0, _copilotkit_shared.formatFileSize)(attachment.size)
|
|
6182
|
+
})]
|
|
6183
|
+
})]
|
|
6184
|
+
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Lightbox, {
|
|
6185
|
+
onClose: closeLightbox,
|
|
6186
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DocumentLightboxContent, {
|
|
6187
|
+
attachment,
|
|
6188
|
+
vtName
|
|
6189
|
+
})
|
|
6190
|
+
})] });
|
|
6191
|
+
}
|
|
4519
6192
|
|
|
4520
6193
|
//#endregion
|
|
4521
6194
|
//#region src/v2/hooks/use-keyboard-height.tsx
|
|
@@ -4561,7 +6234,19 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4561
6234
|
//#endregion
|
|
4562
6235
|
//#region src/v2/components/chat/CopilotChatView.tsx
|
|
4563
6236
|
const FEATHER_HEIGHT = 96;
|
|
4564
|
-
function
|
|
6237
|
+
function DropOverlay() {
|
|
6238
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6239
|
+
className: cn("cpk:absolute cpk:inset-0 cpk:z-50 cpk:pointer-events-none", "cpk:flex cpk:items-center cpk:justify-center", "cpk:bg-primary/5 cpk:backdrop-blur-[2px]", "cpk:border-2 cpk:border-dashed cpk:border-primary/40 cpk:rounded-lg cpk:m-2"),
|
|
6240
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6241
|
+
className: "cpk:flex cpk:flex-col cpk:items-center cpk:gap-2 cpk:text-primary/70",
|
|
6242
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Upload, { className: "cpk:w-8 cpk:h-8" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6243
|
+
className: "cpk:text-sm cpk:font-medium",
|
|
6244
|
+
children: "Drop files here"
|
|
6245
|
+
})]
|
|
6246
|
+
})
|
|
6247
|
+
});
|
|
6248
|
+
}
|
|
6249
|
+
function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, attachments, onRemoveAttachment, onAddFile, dragOver, onDragOver, onDragLeave, onDrop, disclaimer, children, className, ...props }) {
|
|
4565
6250
|
const inputContainerRef = (0, react.useRef)(null);
|
|
4566
6251
|
const [inputContainerHeight, setInputContainerHeight] = (0, react.useState)(0);
|
|
4567
6252
|
const [isResizing, setIsResizing] = (0, react.useState)(false);
|
|
@@ -4608,6 +6293,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4608
6293
|
onCancelTranscribe,
|
|
4609
6294
|
onFinishTranscribe,
|
|
4610
6295
|
onFinishTranscribeWithAudio,
|
|
6296
|
+
onAddFile,
|
|
4611
6297
|
positioning: "static",
|
|
4612
6298
|
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
4613
6299
|
containerRef: inputContainerRef,
|
|
@@ -4648,21 +6334,34 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4648
6334
|
onCancelTranscribe,
|
|
4649
6335
|
onFinishTranscribe,
|
|
4650
6336
|
onFinishTranscribeWithAudio,
|
|
6337
|
+
onAddFile,
|
|
4651
6338
|
positioning: "static",
|
|
4652
6339
|
showDisclaimer: true,
|
|
4653
6340
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
4654
6341
|
});
|
|
4655
|
-
const
|
|
4656
|
-
|
|
6342
|
+
const welcomeScreenSlot = welcomeScreen === true ? void 0 : welcomeScreen;
|
|
6343
|
+
const inputWithAttachments = /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6344
|
+
className: "cpk:w-full",
|
|
6345
|
+
children: [attachments && attachments.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatAttachmentQueue, {
|
|
6346
|
+
attachments,
|
|
6347
|
+
onRemoveAttachment: (id) => onRemoveAttachment === null || onRemoveAttachment === void 0 ? void 0 : onRemoveAttachment(id),
|
|
6348
|
+
className: "cpk:mb-2"
|
|
6349
|
+
}), BoundInputForWelcome]
|
|
6350
|
+
});
|
|
6351
|
+
const BoundWelcomeScreen = renderSlot(welcomeScreenSlot, CopilotChatView.WelcomeScreen, {
|
|
6352
|
+
input: inputWithAttachments,
|
|
4657
6353
|
suggestionView: BoundSuggestionView !== null && BoundSuggestionView !== void 0 ? BoundSuggestionView : /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {})
|
|
4658
6354
|
});
|
|
4659
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
6355
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4660
6356
|
"data-copilotkit": true,
|
|
4661
6357
|
"data-testid": "copilot-chat",
|
|
4662
6358
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
4663
|
-
|
|
6359
|
+
onDragOver,
|
|
6360
|
+
onDragLeave,
|
|
6361
|
+
onDrop,
|
|
6362
|
+
className: cn("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
4664
6363
|
...props,
|
|
4665
|
-
children: BoundWelcomeScreen
|
|
6364
|
+
children: [dragOver && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropOverlay, {}), BoundWelcomeScreen]
|
|
4666
6365
|
});
|
|
4667
6366
|
}
|
|
4668
6367
|
if (children) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -4679,39 +6378,67 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4679
6378
|
"data-copilotkit": true,
|
|
4680
6379
|
"data-testid": "copilot-chat",
|
|
4681
6380
|
"data-copilot-running": isRunning ? "true" : "false",
|
|
4682
|
-
|
|
6381
|
+
onDragOver,
|
|
6382
|
+
onDragLeave,
|
|
6383
|
+
onDrop,
|
|
6384
|
+
className: cn("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
4683
6385
|
...props,
|
|
4684
|
-
children: [
|
|
6386
|
+
children: [
|
|
6387
|
+
dragOver && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropOverlay, {}),
|
|
6388
|
+
BoundScrollView,
|
|
6389
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6390
|
+
className: "cpk:max-w-3xl cpk:mx-auto cpk:w-full",
|
|
6391
|
+
children: attachments && attachments.length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatAttachmentQueue, {
|
|
6392
|
+
attachments,
|
|
6393
|
+
onRemoveAttachment: (id) => onRemoveAttachment === null || onRemoveAttachment === void 0 ? void 0 : onRemoveAttachment(id),
|
|
6394
|
+
className: "cpk:px-4"
|
|
6395
|
+
})
|
|
6396
|
+
}),
|
|
6397
|
+
BoundInput
|
|
6398
|
+
]
|
|
4685
6399
|
});
|
|
4686
6400
|
}
|
|
4687
6401
|
(function(_CopilotChatView) {
|
|
4688
6402
|
const ScrollContent = ({ children, scrollToBottomButton, feather, inputContainerHeight, isResizing }) => {
|
|
4689
|
-
const { isAtBottom, scrollToBottom } = (0, use_stick_to_bottom.useStickToBottomContext)();
|
|
6403
|
+
const { isAtBottom, scrollToBottom, scrollRef } = (0, use_stick_to_bottom.useStickToBottomContext)();
|
|
6404
|
+
const [scrollEl, setScrollEl] = (0, react.useState)(null);
|
|
6405
|
+
(0, react.useLayoutEffect)(() => {
|
|
6406
|
+
var _scrollRef$current;
|
|
6407
|
+
setScrollEl((_scrollRef$current = scrollRef.current) !== null && _scrollRef$current !== void 0 ? _scrollRef$current : null);
|
|
6408
|
+
}, []);
|
|
4690
6409
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
4691
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
|
|
4696
|
-
|
|
4697
|
-
|
|
4698
|
-
|
|
4699
|
-
|
|
4700
|
-
children
|
|
6410
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
|
|
6411
|
+
value: scrollEl,
|
|
6412
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6413
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom.Content, {
|
|
6414
|
+
className: "cpk:overflow-y-auto cpk:overflow-x-hidden",
|
|
6415
|
+
style: {
|
|
6416
|
+
flex: "1 1 0%",
|
|
6417
|
+
minHeight: 0
|
|
6418
|
+
},
|
|
6419
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6420
|
+
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
6421
|
+
children
|
|
6422
|
+
})
|
|
6423
|
+
}),
|
|
6424
|
+
BoundFeather,
|
|
6425
|
+
!isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6426
|
+
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6427
|
+
style: { bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px` },
|
|
6428
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
4701
6429
|
})
|
|
4702
|
-
})
|
|
4703
|
-
|
|
4704
|
-
!isAtBottom && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4705
|
-
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
4706
|
-
style: { bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px` },
|
|
4707
|
-
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
4708
|
-
})
|
|
4709
|
-
] });
|
|
6430
|
+
] })
|
|
6431
|
+
});
|
|
4710
6432
|
};
|
|
4711
6433
|
_CopilotChatView.ScrollView = ({ children, autoScroll = true, scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
4712
6434
|
const [hasMounted, setHasMounted] = (0, react.useState)(false);
|
|
4713
6435
|
const { scrollRef, contentRef, scrollToBottom } = (0, use_stick_to_bottom.useStickToBottom)();
|
|
4714
6436
|
const [showScrollButton, setShowScrollButton] = (0, react.useState)(false);
|
|
6437
|
+
const [nonAutoScrollEl, setNonAutoScrollEl] = (0, react.useState)(null);
|
|
6438
|
+
const nonAutoScrollRefCallback = (0, react.useCallback)((el) => {
|
|
6439
|
+
scrollRef.current = el;
|
|
6440
|
+
setNonAutoScrollEl(el);
|
|
6441
|
+
}, []);
|
|
4715
6442
|
(0, react.useEffect)(() => {
|
|
4716
6443
|
setHasMounted(true);
|
|
4717
6444
|
}, []);
|
|
@@ -4740,23 +6467,26 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4740
6467
|
});
|
|
4741
6468
|
if (!autoScroll) {
|
|
4742
6469
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
4743
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.
|
|
4744
|
-
|
|
4745
|
-
|
|
4746
|
-
|
|
4747
|
-
|
|
4748
|
-
|
|
4749
|
-
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
6470
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
|
|
6471
|
+
value: nonAutoScrollEl,
|
|
6472
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6473
|
+
ref: nonAutoScrollRefCallback,
|
|
6474
|
+
className: cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-auto cpk:overflow-x-hidden cpk:relative", className),
|
|
6475
|
+
...props,
|
|
6476
|
+
children: [
|
|
6477
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6478
|
+
ref: contentRef,
|
|
6479
|
+
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
6480
|
+
children
|
|
6481
|
+
}),
|
|
6482
|
+
BoundFeather,
|
|
6483
|
+
showScrollButton && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6484
|
+
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6485
|
+
style: { bottom: `${inputContainerHeight + FEATHER_HEIGHT + 16}px` },
|
|
6486
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
6487
|
+
})
|
|
6488
|
+
]
|
|
6489
|
+
})
|
|
4760
6490
|
});
|
|
4761
6491
|
}
|
|
4762
6492
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom, {
|
|
@@ -4951,8 +6681,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4951
6681
|
|
|
4952
6682
|
//#endregion
|
|
4953
6683
|
//#region src/v2/components/chat/CopilotChat.tsx
|
|
4954
|
-
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, onError, ...props }) {
|
|
4955
|
-
var _ref;
|
|
6684
|
+
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
6685
|
+
var _ref, _attachmentsConfig$ac;
|
|
4956
6686
|
const existingConfig = useCopilotChatConfiguration();
|
|
4957
6687
|
const resolvedAgentId = (_ref = agentId !== null && agentId !== void 0 ? agentId : existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.agentId) !== null && _ref !== void 0 ? _ref : _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
4958
6688
|
const resolvedThreadId = (0, react.useMemo)(() => {
|
|
@@ -4961,7 +6691,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4961
6691
|
}, [threadId, existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId]);
|
|
4962
6692
|
const { agent } = useAgent({
|
|
4963
6693
|
agentId: resolvedAgentId,
|
|
4964
|
-
threadId: resolvedThreadId
|
|
6694
|
+
threadId: resolvedThreadId,
|
|
6695
|
+
throttleMs
|
|
4965
6696
|
});
|
|
4966
6697
|
const { copilotkit } = useCopilotKit();
|
|
4967
6698
|
const { suggestions: autoSuggestions } = useSuggestions({ agentId: resolvedAgentId });
|
|
@@ -4995,6 +6726,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4995
6726
|
const [inputValue, setInputValue] = (0, react.useState)("");
|
|
4996
6727
|
const [transcriptionError, setTranscriptionError] = (0, react.useState)(null);
|
|
4997
6728
|
const [isTranscribing, setIsTranscribing] = (0, react.useState)(false);
|
|
6729
|
+
const { attachments: selectedAttachments, enabled: attachmentsEnabled, dragOver, fileInputRef, containerRef: chatContainerRef, handleFileUpload, handleDragOver, handleDragLeave, handleDrop, removeAttachment, consumeAttachments } = useAttachments({ config: attachmentsConfig });
|
|
4998
6730
|
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
|
|
4999
6731
|
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
|
|
5000
6732
|
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
|
|
@@ -5022,7 +6754,31 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
5022
6754
|
resolvedAgentId
|
|
5023
6755
|
]);
|
|
5024
6756
|
const onSubmitInput = (0, react.useCallback)(async (value) => {
|
|
5025
|
-
|
|
6757
|
+
if (selectedAttachments.some((a) => a.status === "uploading")) {
|
|
6758
|
+
console.error("[CopilotKit] Cannot send while attachments are uploading");
|
|
6759
|
+
return;
|
|
6760
|
+
}
|
|
6761
|
+
const readyAttachments = consumeAttachments();
|
|
6762
|
+
if (readyAttachments.length > 0) {
|
|
6763
|
+
const contentParts = [];
|
|
6764
|
+
if (value.trim()) contentParts.push({
|
|
6765
|
+
type: "text",
|
|
6766
|
+
text: value
|
|
6767
|
+
});
|
|
6768
|
+
for (const att of readyAttachments) contentParts.push({
|
|
6769
|
+
type: att.type,
|
|
6770
|
+
source: att.source,
|
|
6771
|
+
metadata: {
|
|
6772
|
+
...att.filename ? { filename: att.filename } : {},
|
|
6773
|
+
...att.metadata
|
|
6774
|
+
}
|
|
6775
|
+
});
|
|
6776
|
+
agent.addMessage({
|
|
6777
|
+
id: (0, _copilotkit_shared.randomUUID)(),
|
|
6778
|
+
role: "user",
|
|
6779
|
+
content: contentParts
|
|
6780
|
+
});
|
|
6781
|
+
} else agent.addMessage({
|
|
5026
6782
|
id: (0, _copilotkit_shared.randomUUID)(),
|
|
5027
6783
|
role: "user",
|
|
5028
6784
|
content: value
|
|
@@ -5033,7 +6789,11 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
5033
6789
|
} catch (error) {
|
|
5034
6790
|
console.error("CopilotChat: runAgent failed", error);
|
|
5035
6791
|
}
|
|
5036
|
-
}, [
|
|
6792
|
+
}, [
|
|
6793
|
+
agent,
|
|
6794
|
+
selectedAttachments,
|
|
6795
|
+
consumeAttachments
|
|
6796
|
+
]);
|
|
5037
6797
|
const handleSelectSuggestion = (0, react.useCallback)(async (suggestion) => {
|
|
5038
6798
|
agent.addMessage({
|
|
5039
6799
|
id: (0, _copilotkit_shared.randomUUID)(),
|
|
@@ -5120,21 +6880,37 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
5120
6880
|
return () => clearTimeout(timer);
|
|
5121
6881
|
}
|
|
5122
6882
|
}, [transcriptionError]);
|
|
5123
|
-
const
|
|
6883
|
+
const stableMessageView = useShallowStableRef(typeof providedMessageView === "string" ? { className: providedMessageView } : providedMessageView);
|
|
6884
|
+
const stableSuggestionView = useShallowStableRef(providedSuggestionView);
|
|
6885
|
+
const handleAddFile = (0, react.useCallback)(() => {
|
|
6886
|
+
setTimeout(() => {
|
|
6887
|
+
var _fileInputRef$current;
|
|
6888
|
+
(_fileInputRef$current = fileInputRef.current) === null || _fileInputRef$current === void 0 || _fileInputRef$current.click();
|
|
6889
|
+
}, 100);
|
|
6890
|
+
}, []);
|
|
6891
|
+
const mergedProps = {
|
|
5124
6892
|
isRunning: agent.isRunning,
|
|
5125
6893
|
suggestions: autoSuggestions,
|
|
5126
6894
|
onSelectSuggestion: handleSelectSuggestion,
|
|
5127
|
-
suggestionView:
|
|
5128
|
-
|
|
5129
|
-
|
|
5130
|
-
|
|
5131
|
-
});
|
|
6895
|
+
suggestionView: stableSuggestionView,
|
|
6896
|
+
...restProps
|
|
6897
|
+
};
|
|
6898
|
+
if (stableMessageView !== void 0) mergedProps.messageView = stableMessageView;
|
|
5132
6899
|
const hasMessages = agent.messages.length > 0;
|
|
5133
6900
|
const effectiveStopHandler = agent.isRunning && hasMessages ? providedStopHandler !== null && providedStopHandler !== void 0 ? providedStopHandler : stopCurrentRun : providedStopHandler;
|
|
5134
6901
|
const showTranscription = isTranscriptionEnabled && isMediaRecorderSupported;
|
|
5135
6902
|
const effectiveMode = isTranscribing ? "processing" : transcribeMode;
|
|
5136
|
-
const
|
|
5137
|
-
|
|
6903
|
+
const messages = (0, react.useMemo)(() => [...agent.messages], [agent.messages.map((m) => {
|
|
6904
|
+
const contentKey = typeof m.content === "string" ? m.content.length : Array.isArray(m.content) ? m.content.length : 0;
|
|
6905
|
+
const toolCallsKey = "toolCalls" in m && Array.isArray(m.toolCalls) ? m.toolCalls.map((tc) => {
|
|
6906
|
+
var _tc$function$argument, _tc$function;
|
|
6907
|
+
return `${tc.id}:${(_tc$function$argument = (_tc$function = tc.function) === null || _tc$function === void 0 || (_tc$function = _tc$function.arguments) === null || _tc$function === void 0 ? void 0 : _tc$function.length) !== null && _tc$function$argument !== void 0 ? _tc$function$argument : 0}`;
|
|
6908
|
+
}).join(";") : "";
|
|
6909
|
+
return `${m.id}:${m.role}:${contentKey}:${toolCallsKey}`;
|
|
6910
|
+
}).join(",")]);
|
|
6911
|
+
const RenderedChatView = renderSlot(chatView, CopilotChatView, {
|
|
6912
|
+
...mergedProps,
|
|
6913
|
+
messages,
|
|
5138
6914
|
onSubmitMessage: onSubmitInput,
|
|
5139
6915
|
onStop: effectiveStopHandler,
|
|
5140
6916
|
inputMode: effectiveMode,
|
|
@@ -5143,32 +6919,51 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
5143
6919
|
onStartTranscribe: showTranscription ? handleStartTranscribe : void 0,
|
|
5144
6920
|
onCancelTranscribe: showTranscription ? handleCancelTranscribe : void 0,
|
|
5145
6921
|
onFinishTranscribe: showTranscription ? handleFinishTranscribe : void 0,
|
|
5146
|
-
onFinishTranscribeWithAudio: showTranscription ? handleFinishTranscribeWithAudio : void 0
|
|
5147
|
-
|
|
5148
|
-
|
|
6922
|
+
onFinishTranscribeWithAudio: showTranscription ? handleFinishTranscribeWithAudio : void 0,
|
|
6923
|
+
attachments: selectedAttachments,
|
|
6924
|
+
onRemoveAttachment: removeAttachment,
|
|
6925
|
+
onAddFile: attachmentsEnabled ? handleAddFile : void 0,
|
|
6926
|
+
dragOver,
|
|
6927
|
+
onDragOver: handleDragOver,
|
|
6928
|
+
onDragLeave: handleDragLeave,
|
|
6929
|
+
onDrop: handleDrop
|
|
6930
|
+
});
|
|
6931
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
5149
6932
|
agentId: resolvedAgentId,
|
|
5150
6933
|
threadId: resolvedThreadId,
|
|
5151
6934
|
labels,
|
|
5152
6935
|
isModalDefaultOpen,
|
|
5153
|
-
children:
|
|
5154
|
-
|
|
5155
|
-
|
|
5156
|
-
|
|
5157
|
-
|
|
5158
|
-
|
|
5159
|
-
|
|
5160
|
-
|
|
5161
|
-
|
|
5162
|
-
|
|
5163
|
-
|
|
5164
|
-
|
|
5165
|
-
|
|
5166
|
-
|
|
5167
|
-
|
|
5168
|
-
|
|
5169
|
-
|
|
5170
|
-
|
|
5171
|
-
|
|
6936
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6937
|
+
ref: chatContainerRef,
|
|
6938
|
+
style: { display: "contents" },
|
|
6939
|
+
children: [
|
|
6940
|
+
attachmentsEnabled && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("input", {
|
|
6941
|
+
type: "file",
|
|
6942
|
+
multiple: true,
|
|
6943
|
+
ref: fileInputRef,
|
|
6944
|
+
onChange: handleFileUpload,
|
|
6945
|
+
accept: (_attachmentsConfig$ac = attachmentsConfig === null || attachmentsConfig === void 0 ? void 0 : attachmentsConfig.accept) !== null && _attachmentsConfig$ac !== void 0 ? _attachmentsConfig$ac : "*/*",
|
|
6946
|
+
style: { display: "none" }
|
|
6947
|
+
}),
|
|
6948
|
+
!isChatLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Chat" }),
|
|
6949
|
+
transcriptionError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6950
|
+
style: {
|
|
6951
|
+
position: "absolute",
|
|
6952
|
+
bottom: "100px",
|
|
6953
|
+
left: "50%",
|
|
6954
|
+
transform: "translateX(-50%)",
|
|
6955
|
+
backgroundColor: "#ef4444",
|
|
6956
|
+
color: "white",
|
|
6957
|
+
padding: "8px 16px",
|
|
6958
|
+
borderRadius: "8px",
|
|
6959
|
+
fontSize: "14px",
|
|
6960
|
+
zIndex: 50
|
|
6961
|
+
},
|
|
6962
|
+
children: transcriptionError
|
|
6963
|
+
}),
|
|
6964
|
+
RenderedChatView
|
|
6965
|
+
]
|
|
6966
|
+
})
|
|
5172
6967
|
});
|
|
5173
6968
|
}
|
|
5174
6969
|
(function(_CopilotChat) {
|
|
@@ -6035,6 +7830,227 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6035
7830
|
if (!context) throw new Error("useToast must be used within a ToastProvider");
|
|
6036
7831
|
return context;
|
|
6037
7832
|
}
|
|
7833
|
+
function formatBannerMessage(message) {
|
|
7834
|
+
const jsonMatch = message.match(/'message':\s*'([^']+)'/);
|
|
7835
|
+
if (jsonMatch) return jsonMatch[1];
|
|
7836
|
+
let cleaned = message.split(" - ")[0];
|
|
7837
|
+
cleaned = cleaned.split(": Error code")[0];
|
|
7838
|
+
cleaned = cleaned.replace(/:\s*\d{3}$/, "");
|
|
7839
|
+
cleaned = cleaned.replace(/See more:.*$/g, "");
|
|
7840
|
+
cleaned = cleaned.trim();
|
|
7841
|
+
return cleaned || "An error occurred.";
|
|
7842
|
+
}
|
|
7843
|
+
function extractUrl(message) {
|
|
7844
|
+
const markdownMatch = /\[([^\]]+)\]\(([^)]+)\)/.exec(message);
|
|
7845
|
+
if (markdownMatch) return {
|
|
7846
|
+
url: markdownMatch[2],
|
|
7847
|
+
text: "See More"
|
|
7848
|
+
};
|
|
7849
|
+
const plainMatch = /(https?:\/\/[^\s)]+)/.exec(message);
|
|
7850
|
+
if (plainMatch) return {
|
|
7851
|
+
url: plainMatch[0].replace(/[.,;:'"]*$/, ""),
|
|
7852
|
+
text: "See More"
|
|
7853
|
+
};
|
|
7854
|
+
return null;
|
|
7855
|
+
}
|
|
7856
|
+
function BannerErrorDisplay({ bannerError, onDismiss }) {
|
|
7857
|
+
const [detailsExpanded, setDetailsExpanded] = (0, react.useState)(false);
|
|
7858
|
+
const colors = getErrorColors(getErrorSeverity(bannerError));
|
|
7859
|
+
const details = bannerError.details;
|
|
7860
|
+
const link = extractUrl(bannerError.message);
|
|
7861
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7862
|
+
style: {
|
|
7863
|
+
position: "fixed",
|
|
7864
|
+
bottom: "20px",
|
|
7865
|
+
left: "50%",
|
|
7866
|
+
transform: "translateX(-50%)",
|
|
7867
|
+
zIndex: 9999,
|
|
7868
|
+
backgroundColor: colors.background,
|
|
7869
|
+
border: `1px solid ${colors.border}`,
|
|
7870
|
+
borderLeft: `4px solid ${colors.border}`,
|
|
7871
|
+
borderRadius: "8px",
|
|
7872
|
+
padding: "12px 16px",
|
|
7873
|
+
fontSize: "13px",
|
|
7874
|
+
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
7875
|
+
backdropFilter: "blur(8px)",
|
|
7876
|
+
maxWidth: "min(90vw, 700px)",
|
|
7877
|
+
width: "100%",
|
|
7878
|
+
boxSizing: "border-box",
|
|
7879
|
+
overflow: "hidden"
|
|
7880
|
+
},
|
|
7881
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7882
|
+
style: {
|
|
7883
|
+
display: "flex",
|
|
7884
|
+
justifyContent: "space-between",
|
|
7885
|
+
alignItems: "center",
|
|
7886
|
+
gap: "10px"
|
|
7887
|
+
},
|
|
7888
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7889
|
+
style: {
|
|
7890
|
+
display: "flex",
|
|
7891
|
+
alignItems: "center",
|
|
7892
|
+
gap: "8px",
|
|
7893
|
+
flex: 1,
|
|
7894
|
+
minWidth: 0
|
|
7895
|
+
},
|
|
7896
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
7897
|
+
width: "12px",
|
|
7898
|
+
height: "12px",
|
|
7899
|
+
borderRadius: "50%",
|
|
7900
|
+
backgroundColor: colors.border,
|
|
7901
|
+
flexShrink: 0
|
|
7902
|
+
} }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7903
|
+
style: {
|
|
7904
|
+
display: "flex",
|
|
7905
|
+
alignItems: "center",
|
|
7906
|
+
gap: "10px",
|
|
7907
|
+
flex: 1,
|
|
7908
|
+
minWidth: 0
|
|
7909
|
+
},
|
|
7910
|
+
children: [
|
|
7911
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7912
|
+
style: {
|
|
7913
|
+
color: colors.text,
|
|
7914
|
+
lineHeight: "1.4",
|
|
7915
|
+
fontWeight: "400",
|
|
7916
|
+
fontSize: "13px",
|
|
7917
|
+
flex: 1,
|
|
7918
|
+
wordBreak: "break-all",
|
|
7919
|
+
overflowWrap: "break-word",
|
|
7920
|
+
maxWidth: "550px",
|
|
7921
|
+
overflow: "hidden",
|
|
7922
|
+
display: "-webkit-box",
|
|
7923
|
+
WebkitLineClamp: 10,
|
|
7924
|
+
WebkitBoxOrient: "vertical"
|
|
7925
|
+
},
|
|
7926
|
+
children: formatBannerMessage(bannerError.message)
|
|
7927
|
+
}),
|
|
7928
|
+
link && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7929
|
+
onClick: () => window.open(link.url, "_blank", "noopener,noreferrer"),
|
|
7930
|
+
style: {
|
|
7931
|
+
background: colors.border,
|
|
7932
|
+
color: "white",
|
|
7933
|
+
border: "none",
|
|
7934
|
+
borderRadius: "5px",
|
|
7935
|
+
padding: "4px 10px",
|
|
7936
|
+
fontSize: "11px",
|
|
7937
|
+
fontWeight: "500",
|
|
7938
|
+
cursor: "pointer",
|
|
7939
|
+
transition: "all 0.2s ease",
|
|
7940
|
+
flexShrink: 0
|
|
7941
|
+
},
|
|
7942
|
+
onMouseEnter: (e) => {
|
|
7943
|
+
e.currentTarget.style.opacity = "0.9";
|
|
7944
|
+
e.currentTarget.style.transform = "translateY(-1px)";
|
|
7945
|
+
},
|
|
7946
|
+
onMouseLeave: (e) => {
|
|
7947
|
+
e.currentTarget.style.opacity = "1";
|
|
7948
|
+
e.currentTarget.style.transform = "translateY(0)";
|
|
7949
|
+
},
|
|
7950
|
+
children: link.text
|
|
7951
|
+
}),
|
|
7952
|
+
details && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7953
|
+
onClick: () => setDetailsExpanded(!detailsExpanded),
|
|
7954
|
+
style: {
|
|
7955
|
+
background: "transparent",
|
|
7956
|
+
border: `1px solid ${colors.border}`,
|
|
7957
|
+
borderRadius: "5px",
|
|
7958
|
+
padding: "4px 10px",
|
|
7959
|
+
fontSize: "11px",
|
|
7960
|
+
fontWeight: "500",
|
|
7961
|
+
cursor: "pointer",
|
|
7962
|
+
color: colors.text,
|
|
7963
|
+
flexShrink: 0,
|
|
7964
|
+
transition: "all 0.2s ease"
|
|
7965
|
+
},
|
|
7966
|
+
onMouseEnter: (e) => {
|
|
7967
|
+
e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
|
|
7968
|
+
},
|
|
7969
|
+
onMouseLeave: (e) => {
|
|
7970
|
+
e.currentTarget.style.background = "transparent";
|
|
7971
|
+
},
|
|
7972
|
+
children: detailsExpanded ? "Hide Details" : "Show Details"
|
|
7973
|
+
})
|
|
7974
|
+
]
|
|
7975
|
+
})]
|
|
7976
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7977
|
+
onClick: onDismiss,
|
|
7978
|
+
style: {
|
|
7979
|
+
background: "transparent",
|
|
7980
|
+
border: "none",
|
|
7981
|
+
color: colors.text,
|
|
7982
|
+
cursor: "pointer",
|
|
7983
|
+
padding: "2px",
|
|
7984
|
+
borderRadius: "3px",
|
|
7985
|
+
fontSize: "14px",
|
|
7986
|
+
lineHeight: "1",
|
|
7987
|
+
opacity: .6,
|
|
7988
|
+
transition: "all 0.2s ease",
|
|
7989
|
+
flexShrink: 0
|
|
7990
|
+
},
|
|
7991
|
+
title: "Dismiss",
|
|
7992
|
+
onMouseEnter: (e) => {
|
|
7993
|
+
e.currentTarget.style.opacity = "1";
|
|
7994
|
+
e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
|
|
7995
|
+
},
|
|
7996
|
+
onMouseLeave: (e) => {
|
|
7997
|
+
e.currentTarget.style.opacity = "0.6";
|
|
7998
|
+
e.currentTarget.style.background = "transparent";
|
|
7999
|
+
},
|
|
8000
|
+
children: "x"
|
|
8001
|
+
})]
|
|
8002
|
+
}), detailsExpanded && details && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8003
|
+
style: {
|
|
8004
|
+
marginTop: "10px",
|
|
8005
|
+
padding: "10px",
|
|
8006
|
+
background: "rgba(0, 0, 0, 0.04)",
|
|
8007
|
+
borderRadius: "6px",
|
|
8008
|
+
fontSize: "11px",
|
|
8009
|
+
fontFamily: "monospace",
|
|
8010
|
+
color: colors.text,
|
|
8011
|
+
lineHeight: "1.5",
|
|
8012
|
+
maxHeight: "200px",
|
|
8013
|
+
overflowY: "auto",
|
|
8014
|
+
whiteSpace: "pre-wrap",
|
|
8015
|
+
wordBreak: "break-all"
|
|
8016
|
+
},
|
|
8017
|
+
children: [
|
|
8018
|
+
details.code && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [
|
|
8019
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Code:" }),
|
|
8020
|
+
" ",
|
|
8021
|
+
details.code
|
|
8022
|
+
] }),
|
|
8023
|
+
details.originalMessage && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8024
|
+
style: { marginTop: "4px" },
|
|
8025
|
+
children: [
|
|
8026
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Message:" }),
|
|
8027
|
+
" ",
|
|
8028
|
+
details.originalMessage
|
|
8029
|
+
]
|
|
8030
|
+
}),
|
|
8031
|
+
details.context && Object.keys(details.context).length > 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8032
|
+
style: { marginTop: "4px" },
|
|
8033
|
+
children: [
|
|
8034
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Context:" }),
|
|
8035
|
+
" ",
|
|
8036
|
+
JSON.stringify(details.context, null, 2)
|
|
8037
|
+
]
|
|
8038
|
+
}),
|
|
8039
|
+
details.stack && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
8040
|
+
style: {
|
|
8041
|
+
marginTop: "4px",
|
|
8042
|
+
opacity: .7
|
|
8043
|
+
},
|
|
8044
|
+
children: [
|
|
8045
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("strong", { children: "Stack:" }),
|
|
8046
|
+
"\n",
|
|
8047
|
+
details.stack
|
|
8048
|
+
]
|
|
8049
|
+
})
|
|
8050
|
+
]
|
|
8051
|
+
})]
|
|
8052
|
+
});
|
|
8053
|
+
}
|
|
6038
8054
|
function ToastProvider({ enabled, children }) {
|
|
6039
8055
|
const [toasts, setToasts] = (0, react.useState)([]);
|
|
6040
8056
|
const [bannerError, setBannerErrorState] = (0, react.useState)(null);
|
|
@@ -6073,156 +8089,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6073
8089
|
};
|
|
6074
8090
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(ToastContext.Provider, {
|
|
6075
8091
|
value,
|
|
6076
|
-
children: [bannerError && ((
|
|
6077
|
-
|
|
6078
|
-
|
|
6079
|
-
|
|
6080
|
-
position: "fixed",
|
|
6081
|
-
bottom: "20px",
|
|
6082
|
-
left: "50%",
|
|
6083
|
-
transform: "translateX(-50%)",
|
|
6084
|
-
zIndex: 9999,
|
|
6085
|
-
backgroundColor: colors.background,
|
|
6086
|
-
border: `1px solid ${colors.border}`,
|
|
6087
|
-
borderLeft: `4px solid ${colors.border}`,
|
|
6088
|
-
borderRadius: "8px",
|
|
6089
|
-
padding: "12px 16px",
|
|
6090
|
-
fontSize: "13px",
|
|
6091
|
-
boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)",
|
|
6092
|
-
backdropFilter: "blur(8px)",
|
|
6093
|
-
maxWidth: "min(90vw, 700px)",
|
|
6094
|
-
width: "100%",
|
|
6095
|
-
boxSizing: "border-box",
|
|
6096
|
-
overflow: "hidden"
|
|
6097
|
-
},
|
|
6098
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6099
|
-
style: {
|
|
6100
|
-
display: "flex",
|
|
6101
|
-
justifyContent: "space-between",
|
|
6102
|
-
alignItems: "center",
|
|
6103
|
-
gap: "10px"
|
|
6104
|
-
},
|
|
6105
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6106
|
-
style: {
|
|
6107
|
-
display: "flex",
|
|
6108
|
-
alignItems: "center",
|
|
6109
|
-
gap: "8px",
|
|
6110
|
-
flex: 1,
|
|
6111
|
-
minWidth: 0
|
|
6112
|
-
},
|
|
6113
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", { style: {
|
|
6114
|
-
width: "12px",
|
|
6115
|
-
height: "12px",
|
|
6116
|
-
borderRadius: "50%",
|
|
6117
|
-
backgroundColor: colors.border,
|
|
6118
|
-
flexShrink: 0
|
|
6119
|
-
} }), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6120
|
-
style: {
|
|
6121
|
-
display: "flex",
|
|
6122
|
-
alignItems: "center",
|
|
6123
|
-
gap: "10px",
|
|
6124
|
-
flex: 1,
|
|
6125
|
-
minWidth: 0
|
|
6126
|
-
},
|
|
6127
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6128
|
-
style: {
|
|
6129
|
-
color: colors.text,
|
|
6130
|
-
lineHeight: "1.4",
|
|
6131
|
-
fontWeight: "400",
|
|
6132
|
-
fontSize: "13px",
|
|
6133
|
-
flex: 1,
|
|
6134
|
-
wordBreak: "break-all",
|
|
6135
|
-
overflowWrap: "break-word",
|
|
6136
|
-
maxWidth: "550px",
|
|
6137
|
-
overflow: "hidden",
|
|
6138
|
-
display: "-webkit-box",
|
|
6139
|
-
WebkitLineClamp: 10,
|
|
6140
|
-
WebkitBoxOrient: "vertical"
|
|
6141
|
-
},
|
|
6142
|
-
children: (() => {
|
|
6143
|
-
let message = bannerError.message;
|
|
6144
|
-
const jsonMatch = message.match(/'message':\s*'([^']+)'/);
|
|
6145
|
-
if (jsonMatch) return jsonMatch[1];
|
|
6146
|
-
message = message.split(" - ")[0];
|
|
6147
|
-
message = message.split(": Error code")[0];
|
|
6148
|
-
message = message.replace(/:\s*\d{3}$/, "");
|
|
6149
|
-
message = message.replace(/See more:.*$/g, "");
|
|
6150
|
-
message = message.trim();
|
|
6151
|
-
return message || "Configuration error occurred.";
|
|
6152
|
-
})()
|
|
6153
|
-
}), (() => {
|
|
6154
|
-
const message = bannerError.message;
|
|
6155
|
-
const markdownLinkRegex = /\[([^\]]+)\]\(([^)]+)\)/g;
|
|
6156
|
-
const plainUrlRegex = /(https?:\/\/[^\s)]+)/g;
|
|
6157
|
-
let url = null;
|
|
6158
|
-
let buttonText = "See More";
|
|
6159
|
-
const markdownMatch = markdownLinkRegex.exec(message);
|
|
6160
|
-
if (markdownMatch) {
|
|
6161
|
-
url = markdownMatch[2];
|
|
6162
|
-
buttonText = "See More";
|
|
6163
|
-
} else {
|
|
6164
|
-
const urlMatch = plainUrlRegex.exec(message);
|
|
6165
|
-
if (urlMatch) {
|
|
6166
|
-
url = urlMatch[0].replace(/[.,;:'"]*$/, "");
|
|
6167
|
-
buttonText = "See More";
|
|
6168
|
-
}
|
|
6169
|
-
}
|
|
6170
|
-
if (!url) return null;
|
|
6171
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6172
|
-
onClick: () => window.open(url, "_blank", "noopener,noreferrer"),
|
|
6173
|
-
style: {
|
|
6174
|
-
background: colors.border,
|
|
6175
|
-
color: "white",
|
|
6176
|
-
border: "none",
|
|
6177
|
-
borderRadius: "5px",
|
|
6178
|
-
padding: "4px 10px",
|
|
6179
|
-
fontSize: "11px",
|
|
6180
|
-
fontWeight: "500",
|
|
6181
|
-
cursor: "pointer",
|
|
6182
|
-
transition: "all 0.2s ease",
|
|
6183
|
-
flexShrink: 0
|
|
6184
|
-
},
|
|
6185
|
-
onMouseEnter: (e) => {
|
|
6186
|
-
e.currentTarget.style.opacity = "0.9";
|
|
6187
|
-
e.currentTarget.style.transform = "translateY(-1px)";
|
|
6188
|
-
},
|
|
6189
|
-
onMouseLeave: (e) => {
|
|
6190
|
-
e.currentTarget.style.opacity = "1";
|
|
6191
|
-
e.currentTarget.style.transform = "translateY(0)";
|
|
6192
|
-
},
|
|
6193
|
-
children: buttonText
|
|
6194
|
-
});
|
|
6195
|
-
})()]
|
|
6196
|
-
})]
|
|
6197
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6198
|
-
onClick: () => setBannerError(null),
|
|
6199
|
-
style: {
|
|
6200
|
-
background: "transparent",
|
|
6201
|
-
border: "none",
|
|
6202
|
-
color: colors.text,
|
|
6203
|
-
cursor: "pointer",
|
|
6204
|
-
padding: "2px",
|
|
6205
|
-
borderRadius: "3px",
|
|
6206
|
-
fontSize: "14px",
|
|
6207
|
-
lineHeight: "1",
|
|
6208
|
-
opacity: .6,
|
|
6209
|
-
transition: "all 0.2s ease",
|
|
6210
|
-
flexShrink: 0
|
|
6211
|
-
},
|
|
6212
|
-
title: "Dismiss",
|
|
6213
|
-
onMouseEnter: (e) => {
|
|
6214
|
-
e.currentTarget.style.opacity = "1";
|
|
6215
|
-
e.currentTarget.style.background = "rgba(0, 0, 0, 0.05)";
|
|
6216
|
-
},
|
|
6217
|
-
onMouseLeave: (e) => {
|
|
6218
|
-
e.currentTarget.style.opacity = "0.6";
|
|
6219
|
-
e.currentTarget.style.background = "transparent";
|
|
6220
|
-
},
|
|
6221
|
-
children: "×"
|
|
6222
|
-
})]
|
|
6223
|
-
})
|
|
6224
|
-
});
|
|
6225
|
-
})(), children]
|
|
8092
|
+
children: [bannerError && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(BannerErrorDisplay, {
|
|
8093
|
+
bannerError,
|
|
8094
|
+
onDismiss: () => setBannerError(null)
|
|
8095
|
+
}), children]
|
|
6226
8096
|
});
|
|
6227
8097
|
}
|
|
6228
8098
|
|
|
@@ -7141,12 +9011,21 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7141
9011
|
const { agent } = useAgent({ agentId: resolvedAgentId });
|
|
7142
9012
|
usePredictStateSubscription(agent);
|
|
7143
9013
|
(0, react.useEffect)(() => {
|
|
7144
|
-
const subscription = copilotkit.subscribe({ onError: ({ error }) => {
|
|
7145
|
-
|
|
9014
|
+
const subscription = copilotkit.subscribe({ onError: ({ error, code, context }) => {
|
|
9015
|
+
if (error.name === "AbortError" || error.message === "Fetch is aborted" || error.message === "signal is aborted without reason" || error.message === "component unmounted" || !error.message) return;
|
|
9016
|
+
if (process.env.NODE_ENV === "development") console.error("[CopilotKit] Agent error:", error.message, "\n Code:", code, "\n Context:", context, "\n Stack:", error.stack);
|
|
9017
|
+
const ckError = new _copilotkit_shared.CopilotKitLowLevelError({
|
|
7146
9018
|
error,
|
|
7147
9019
|
message: error.message,
|
|
7148
9020
|
url: typeof window !== "undefined" ? window.location.href : ""
|
|
7149
|
-
})
|
|
9021
|
+
});
|
|
9022
|
+
ckError.details = {
|
|
9023
|
+
code,
|
|
9024
|
+
context,
|
|
9025
|
+
stack: error.stack,
|
|
9026
|
+
originalMessage: error.message
|
|
9027
|
+
};
|
|
9028
|
+
setBannerError(ckError);
|
|
7150
9029
|
} });
|
|
7151
9030
|
return () => {
|
|
7152
9031
|
subscription.unsubscribe();
|
|
@@ -7685,6 +9564,8 @@ Object.defineProperty(exports, 'CopilotChat', {
|
|
|
7685
9564
|
}
|
|
7686
9565
|
});
|
|
7687
9566
|
exports.CopilotChatAssistantMessage = CopilotChatAssistantMessage_default;
|
|
9567
|
+
exports.CopilotChatAttachmentQueue = CopilotChatAttachmentQueue;
|
|
9568
|
+
exports.CopilotChatAttachmentRenderer = CopilotChatAttachmentRenderer;
|
|
7688
9569
|
exports.CopilotChatAudioRecorder = CopilotChatAudioRecorder;
|
|
7689
9570
|
exports.CopilotChatConfigurationProvider = CopilotChatConfigurationProvider;
|
|
7690
9571
|
exports.CopilotChatInput = CopilotChatInput_default;
|
|
@@ -7725,12 +9606,20 @@ Object.defineProperty(exports, 'CopilotSidebarView', {
|
|
|
7725
9606
|
exports.MCPAppsActivityContentSchema = MCPAppsActivityContentSchema;
|
|
7726
9607
|
exports.MCPAppsActivityRenderer = MCPAppsActivityRenderer;
|
|
7727
9608
|
exports.MCPAppsActivityType = MCPAppsActivityType;
|
|
9609
|
+
exports.SandboxFunctionsContext = SandboxFunctionsContext;
|
|
7728
9610
|
exports.UseAgentUpdate = UseAgentUpdate;
|
|
7729
9611
|
exports.WildcardToolCallRender = WildcardToolCallRender;
|
|
9612
|
+
Object.defineProperty(exports, 'a2uiDefaultTheme', {
|
|
9613
|
+
enumerable: true,
|
|
9614
|
+
get: function () {
|
|
9615
|
+
return _copilotkit_a2ui_renderer.defaultTheme;
|
|
9616
|
+
}
|
|
9617
|
+
});
|
|
7730
9618
|
exports.createA2UIMessageRenderer = createA2UIMessageRenderer;
|
|
7731
9619
|
exports.defineToolCallRenderer = defineToolCallRenderer;
|
|
7732
9620
|
exports.useAgent = useAgent;
|
|
7733
9621
|
exports.useAgentContext = useAgentContext;
|
|
9622
|
+
exports.useAttachments = useAttachments;
|
|
7734
9623
|
exports.useComponent = useComponent;
|
|
7735
9624
|
exports.useConfigureSuggestions = useConfigureSuggestions;
|
|
7736
9625
|
exports.useCopilotChatConfiguration = useCopilotChatConfiguration;
|
|
@@ -7743,6 +9632,7 @@ exports.useRenderActivityMessage = useRenderActivityMessage;
|
|
|
7743
9632
|
exports.useRenderCustomMessages = useRenderCustomMessages;
|
|
7744
9633
|
exports.useRenderTool = useRenderTool;
|
|
7745
9634
|
exports.useRenderToolCall = useRenderToolCall;
|
|
9635
|
+
exports.useSandboxFunctions = useSandboxFunctions;
|
|
7746
9636
|
exports.useSuggestions = useSuggestions;
|
|
7747
9637
|
exports.useThreads = useThreads;
|
|
7748
9638
|
Object.keys(_copilotkit_core).forEach(function (k) {
|