@copilotkit/react-core 1.80.0 → 1.82.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/dist/MarkdownSurfaces-DGpjmPaB.mjs +3531 -0
- package/dist/MarkdownSurfaces-DGpjmPaB.mjs.map +1 -0
- package/dist/MarkdownSurfaces-FF5za2kU.cjs +3816 -0
- package/dist/MarkdownSurfaces-FF5za2kU.cjs.map +1 -0
- package/dist/{copilotkit-CWOSXhRO.d.mts → copilotkit-C765tOUi.d.mts} +70 -36
- package/dist/copilotkit-C765tOUi.d.mts.map +1 -0
- package/dist/{copilotkit-DKICi3nC.cjs → copilotkit-CVvbU9lV.cjs} +2162 -675
- package/dist/copilotkit-CVvbU9lV.cjs.map +1 -0
- package/dist/{copilotkit-BNLtgOyD.mjs → copilotkit-DDReN1Px.mjs} +2106 -568
- package/dist/copilotkit-DDReN1Px.mjs.map +1 -0
- package/dist/{copilotkit-Dfw9HzO9.d.cts → copilotkit-wqaNanhw.d.cts} +70 -36
- package/dist/copilotkit-wqaNanhw.d.cts.map +1 -0
- package/dist/index.cjs +8 -7
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +2 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +4474 -11
- package/dist/index.umd.js.map +1 -1
- package/dist/runtime-context-CrHq-iTf.d.mts +924 -0
- package/dist/runtime-context-CrHq-iTf.d.mts.map +1 -0
- package/dist/runtime-context-D3NcP9oE.d.cts +924 -0
- package/dist/runtime-context-D3NcP9oE.d.cts.map +1 -0
- package/dist/v2/generative-ui.cjs +8154 -0
- package/dist/v2/generative-ui.cjs.map +1 -0
- package/dist/v2/generative-ui.d.cts +4950 -0
- package/dist/v2/generative-ui.d.cts.map +1 -0
- package/dist/v2/generative-ui.d.mts +4950 -0
- package/dist/v2/generative-ui.d.mts.map +1 -0
- package/dist/v2/generative-ui.mjs +8140 -0
- package/dist/v2/generative-ui.mjs.map +1 -0
- package/dist/v2/headless.cjs +10 -1
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.d.cts +9 -0
- package/dist/v2/headless.d.cts.map +1 -1
- package/dist/v2/headless.d.mts +9 -0
- package/dist/v2/headless.d.mts.map +1 -1
- package/dist/v2/headless.mjs +10 -1
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +65 -4
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +3 -2
- package/dist/v2/index.d.mts +3 -2
- package/dist/v2/index.mjs +3 -2
- package/dist/v2/index.umd.js +4962 -236
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +21 -8
- package/dist/copilotkit-BNLtgOyD.mjs.map +0 -1
- package/dist/copilotkit-CWOSXhRO.d.mts.map +0 -1
- package/dist/copilotkit-DKICi3nC.cjs.map +0 -1
- package/dist/copilotkit-Dfw9HzO9.d.cts.map +0 -1
|
@@ -1,32 +1,6 @@
|
|
|
1
|
-
|
|
2
|
-
var __create = Object.create;
|
|
3
|
-
var __defProp = Object.defineProperty;
|
|
4
|
-
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
5
|
-
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
6
|
-
var __getProtoOf = Object.getPrototypeOf;
|
|
7
|
-
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
|
-
var __copyProps = (to, from, except, desc) => {
|
|
9
|
-
if (from && typeof from === "object" || typeof from === "function") {
|
|
10
|
-
for (var keys = __getOwnPropNames(from), i = 0, n = keys.length, key; i < n; i++) {
|
|
11
|
-
key = keys[i];
|
|
12
|
-
if (!__hasOwnProp.call(to, key) && key !== except) {
|
|
13
|
-
__defProp(to, key, {
|
|
14
|
-
get: ((k) => from[k]).bind(null, key),
|
|
15
|
-
enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
}
|
|
20
|
-
return to;
|
|
21
|
-
};
|
|
22
|
-
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", {
|
|
23
|
-
value: mod,
|
|
24
|
-
enumerable: true
|
|
25
|
-
}) : target, mod));
|
|
26
|
-
|
|
27
|
-
//#endregion
|
|
1
|
+
const require_MarkdownSurfaces = require('./MarkdownSurfaces-FF5za2kU.cjs');
|
|
28
2
|
let react = require("react");
|
|
29
|
-
react = __toESM(react);
|
|
3
|
+
react = require_MarkdownSurfaces.__toESM(react);
|
|
30
4
|
let _copilotkit_core = require("@copilotkit/core");
|
|
31
5
|
let _ag_ui_client = require("@ag-ui/client");
|
|
32
6
|
let tailwind_merge = require("tailwind-merge");
|
|
@@ -38,360 +12,25 @@ let _radix_ui_react_slot = require("@radix-ui/react-slot");
|
|
|
38
12
|
let class_variance_authority = require("class-variance-authority");
|
|
39
13
|
let clsx = require("clsx");
|
|
40
14
|
let _radix_ui_react_tooltip = require("@radix-ui/react-tooltip");
|
|
41
|
-
_radix_ui_react_tooltip = __toESM(_radix_ui_react_tooltip);
|
|
15
|
+
_radix_ui_react_tooltip = require_MarkdownSurfaces.__toESM(_radix_ui_react_tooltip);
|
|
42
16
|
let _radix_ui_react_dropdown_menu = require("@radix-ui/react-dropdown-menu");
|
|
43
|
-
_radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
17
|
+
_radix_ui_react_dropdown_menu = require_MarkdownSurfaces.__toESM(_radix_ui_react_dropdown_menu);
|
|
44
18
|
let streamdown = require("streamdown");
|
|
45
19
|
let _ag_ui_core = require("@ag-ui/core");
|
|
46
20
|
let zod = require("zod");
|
|
47
21
|
let _copilotkit_mcp_apps_renderer_activity = require("@copilotkit/mcp-apps-renderer/activity");
|
|
48
22
|
let _copilotkit_a2ui_renderer = require("@copilotkit/a2ui-renderer");
|
|
49
23
|
let zod_to_json_schema = require("zod-to-json-schema");
|
|
24
|
+
let _a2ui_web_core_v0_9 = require("@a2ui/web_core/v0_9");
|
|
50
25
|
let _radix_ui_react_popover = require("@radix-ui/react-popover");
|
|
51
|
-
_radix_ui_react_popover = __toESM(_radix_ui_react_popover);
|
|
26
|
+
_radix_ui_react_popover = require_MarkdownSurfaces.__toESM(_radix_ui_react_popover);
|
|
52
27
|
let react_dom = require("react-dom");
|
|
53
28
|
let _tanstack_react_virtual = require("@tanstack/react-virtual");
|
|
54
29
|
let use_stick_to_bottom = require("use-stick-to-bottom");
|
|
55
30
|
let _copilotkit_web_components_threads_drawer = require("@copilotkit/web-components/threads-drawer");
|
|
56
31
|
let react_markdown = require("react-markdown");
|
|
57
|
-
react_markdown = __toESM(react_markdown);
|
|
58
|
-
|
|
59
|
-
//#region src/v2/lib/shallow-stable-ref.ts
|
|
60
|
-
/**
|
|
61
|
-
* Shallow equality comparison for objects.
|
|
62
|
-
*/
|
|
63
|
-
function shallowEqual(obj1, obj2) {
|
|
64
|
-
const keys1 = Object.keys(obj1);
|
|
65
|
-
const keys2 = Object.keys(obj2);
|
|
66
|
-
if (keys1.length !== keys2.length) return false;
|
|
67
|
-
for (const key of keys1) if (obj1[key] !== obj2[key]) return false;
|
|
68
|
-
return true;
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Returns true only for plain JS objects (`{}`), excluding arrays, Dates,
|
|
72
|
-
* class instances, and other exotic objects that happen to have typeof "object".
|
|
73
|
-
*/
|
|
74
|
-
function isPlainObject$1(obj) {
|
|
75
|
-
return obj !== null && typeof obj === "object" && Object.prototype.toString.call(obj) === "[object Object]";
|
|
76
|
-
}
|
|
77
|
-
/**
|
|
78
|
-
* Returns the same reference as long as the value is shallowly equal to the
|
|
79
|
-
* previous render's value.
|
|
80
|
-
*
|
|
81
|
-
* - Identical references bail out immediately (O(1)).
|
|
82
|
-
* - Plain objects ({}) are shallow-compared key-by-key.
|
|
83
|
-
* - Arrays, Dates, class instances, functions, and primitives are compared by
|
|
84
|
-
* reference only — shallowEqual is never called on non-plain objects, which
|
|
85
|
-
* avoids incorrect equality for e.g. [1,2] vs [1,2] (different arrays).
|
|
86
|
-
*
|
|
87
|
-
* Typical use: stabilize inline slot props so MemoizedSlotWrapper's shallow
|
|
88
|
-
* equality check isn't defeated by a new object reference on every render.
|
|
89
|
-
*/
|
|
90
|
-
function useShallowStableRef(value) {
|
|
91
|
-
const ref = (0, react.useRef)(value);
|
|
92
|
-
if (ref.current === value) return ref.current;
|
|
93
|
-
if (isPlainObject$1(ref.current) && isPlainObject$1(value)) {
|
|
94
|
-
if (shallowEqual(ref.current, value)) return ref.current;
|
|
95
|
-
}
|
|
96
|
-
ref.current = value;
|
|
97
|
-
return ref.current;
|
|
98
|
-
}
|
|
99
|
-
|
|
100
|
-
//#endregion
|
|
101
|
-
//#region src/v2/providers/CopilotChatConfigurationProvider.tsx
|
|
102
|
-
const CopilotChatDefaultLabels = {
|
|
103
|
-
chatInputPlaceholder: "Type a message...",
|
|
104
|
-
chatInputToolbarStartTranscribeButtonLabel: "Transcribe",
|
|
105
|
-
chatInputToolbarCancelTranscribeButtonLabel: "Cancel",
|
|
106
|
-
chatInputToolbarFinishTranscribeButtonLabel: "Finish",
|
|
107
|
-
chatInputToolbarAddButtonLabel: "Add attachments",
|
|
108
|
-
chatInputToolbarToolsButtonLabel: "Tools",
|
|
109
|
-
chatInputToolbarSendButtonLabel: "Send message",
|
|
110
|
-
chatInputToolbarStopButtonLabel: "Stop",
|
|
111
|
-
assistantMessageToolbarCopyCodeLabel: "Copy",
|
|
112
|
-
assistantMessageToolbarCopyCodeCopiedLabel: "Copied",
|
|
113
|
-
assistantMessageToolbarCopyMessageLabel: "Copy",
|
|
114
|
-
assistantMessageToolbarInspectorLabel: "View in Inspector",
|
|
115
|
-
assistantMessageToolbarInspectorDescription: "Open this message in the Inspector",
|
|
116
|
-
assistantMessageToolbarInspectorLocalOnlyLabel: "Local only",
|
|
117
|
-
assistantMessageToolbarInspectorLocalOnlyDescription: "Only visible on localhost or loopback hosts in development. Never shown in production.",
|
|
118
|
-
assistantMessageToolbarInspectorTitle: "CopilotKit Inspector",
|
|
119
|
-
assistantMessageToolbarInspectorHideLabel: "Hide this icon",
|
|
120
|
-
assistantMessageToolbarInspectorHideDescription: "Until you reload this page",
|
|
121
|
-
assistantMessageToolbarThumbsUpLabel: "Good response",
|
|
122
|
-
assistantMessageToolbarThumbsDownLabel: "Bad response",
|
|
123
|
-
assistantMessageFeedbackCommentPlaceholder: "Add a comment (optional)",
|
|
124
|
-
assistantMessageFeedbackCommentSubmitLabel: "Send comment",
|
|
125
|
-
assistantMessageToolbarReadAloudLabel: "Read aloud",
|
|
126
|
-
assistantMessageToolbarRegenerateLabel: "Regenerate",
|
|
127
|
-
userMessageToolbarCopyMessageLabel: "Copy",
|
|
128
|
-
userMessageToolbarEditMessageLabel: "Edit",
|
|
129
|
-
userMessageToolbarPreviousBranchLabel: "Previous branch",
|
|
130
|
-
userMessageToolbarNextBranchLabel: "Next branch",
|
|
131
|
-
chatDisclaimerText: "AI can make mistakes. Please verify important information.",
|
|
132
|
-
chatToggleOpenLabel: "Open chat",
|
|
133
|
-
chatToggleCloseLabel: "Close chat",
|
|
134
|
-
chatScrollToBottomLabel: "Scroll to bottom",
|
|
135
|
-
modalHeaderTitle: "CopilotKit Chat",
|
|
136
|
-
welcomeMessageText: "How can I help you today?"
|
|
137
|
-
};
|
|
138
|
-
/**
|
|
139
|
-
* Mobile breakpoint below which the chat modal and the thread-list drawer are
|
|
140
|
-
* mutually exclusive. At or above this width both surfaces may coexist. This
|
|
141
|
-
* mirrors the `(max-width: 767px)` / `(min-width: 768px)` split already used by
|
|
142
|
-
* CopilotChatInput and CopilotSidebarView.
|
|
143
|
-
*/
|
|
144
|
-
const MOBILE_MAX_WIDTH_PX = 767;
|
|
145
|
-
/**
|
|
146
|
-
* Reports whether the current viewport is in the mobile range (`<768px`), where
|
|
147
|
-
* the chat modal and drawer must not be open simultaneously. SSR-safe and
|
|
148
|
-
* defensive against environments without `matchMedia` (treated as desktop, so
|
|
149
|
-
* no mutual-exclusion constraint is applied).
|
|
150
|
-
*
|
|
151
|
-
* @returns `true` when the viewport is mobile-width, `false` otherwise.
|
|
152
|
-
*/
|
|
153
|
-
function isMobileViewport() {
|
|
154
|
-
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
155
|
-
return window.matchMedia(`(max-width: ${MOBILE_MAX_WIDTH_PX}px)`).matches;
|
|
156
|
-
}
|
|
157
|
-
const CopilotChatConfiguration = (0, react.createContext)(null);
|
|
158
|
-
const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, hasExplicitThreadId, isModalDefaultOpen }) => {
|
|
159
|
-
const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
|
|
160
|
-
const stableLabels = useShallowStableRef(labels);
|
|
161
|
-
const mergedLabels = (0, react.useMemo)(() => ({
|
|
162
|
-
...CopilotChatDefaultLabels,
|
|
163
|
-
...parentConfig?.labels,
|
|
164
|
-
...stableLabels
|
|
165
|
-
}), [stableLabels, parentConfig?.labels]);
|
|
166
|
-
const providerAgentId = (0, _copilotkit_react_core_v2_context.useDefaultAgentId)();
|
|
167
|
-
const resolvedAgentId = agentId ?? parentConfig?.agentId ?? providerAgentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
168
|
-
const threadIdPropIsAuthoritative = threadId !== void 0 && hasExplicitThreadId !== false;
|
|
169
|
-
const isThreadIdControlled = threadIdPropIsAuthoritative;
|
|
170
|
-
const [activeThreadOverride, setActiveThreadOverride] = (0, react.useState)(null);
|
|
171
|
-
const resolvedThreadId = (0, react.useMemo)(() => {
|
|
172
|
-
if (threadIdPropIsAuthoritative) return threadId;
|
|
173
|
-
if (activeThreadOverride) return activeThreadOverride.threadId;
|
|
174
|
-
if (parentConfig?.threadId) return parentConfig.threadId;
|
|
175
|
-
if (threadId) return threadId;
|
|
176
|
-
return (0, _copilotkit_shared.randomUUID)();
|
|
177
|
-
}, [
|
|
178
|
-
threadIdPropIsAuthoritative,
|
|
179
|
-
threadId,
|
|
180
|
-
parentConfig?.threadId,
|
|
181
|
-
activeThreadOverride
|
|
182
|
-
]);
|
|
183
|
-
const copilotkit = (0, react.useContext)(_copilotkit_react_core_v2_context.CopilotKitContext)?.copilotkit;
|
|
184
|
-
const openThreadRef = (0, react.useRef)(null);
|
|
185
|
-
const latestThreadIdRef = (0, react.useRef)(resolvedThreadId);
|
|
186
|
-
latestThreadIdRef.current = resolvedThreadId;
|
|
187
|
-
(0, react.useEffect)(() => {
|
|
188
|
-
if (copilotkit === void 0) return;
|
|
189
|
-
const registration = copilotkit.registerOpenThread({
|
|
190
|
-
agentId: resolvedAgentId,
|
|
191
|
-
threadId: latestThreadIdRef.current
|
|
192
|
-
});
|
|
193
|
-
openThreadRef.current = registration;
|
|
194
|
-
return () => {
|
|
195
|
-
registration.unregister();
|
|
196
|
-
openThreadRef.current = null;
|
|
197
|
-
};
|
|
198
|
-
}, [copilotkit, resolvedAgentId]);
|
|
199
|
-
(0, react.useEffect)(() => {
|
|
200
|
-
openThreadRef.current?.update(resolvedThreadId);
|
|
201
|
-
}, [resolvedThreadId]);
|
|
202
|
-
const resolvedHasExplicitThreadId = (threadIdPropIsAuthoritative ? true : activeThreadOverride?.explicit ?? hasExplicitThreadId ?? false) || !!parentConfig?.hasExplicitThreadId;
|
|
203
|
-
const [internalModalOpen, setInternalModalOpen] = (0, react.useState)(isModalDefaultOpen ?? true);
|
|
204
|
-
const hasExplicitDefault = isModalDefaultOpen !== void 0;
|
|
205
|
-
const setAndSync = (0, react.useCallback)((open) => {
|
|
206
|
-
setInternalModalOpen(open);
|
|
207
|
-
parentConfig?.setModalOpen(open);
|
|
208
|
-
}, [parentConfig?.setModalOpen]);
|
|
209
|
-
const isMounted = (0, react.useRef)(false);
|
|
210
|
-
(0, react.useEffect)(() => {
|
|
211
|
-
if (!hasExplicitDefault) return;
|
|
212
|
-
if (!isMounted.current) {
|
|
213
|
-
isMounted.current = true;
|
|
214
|
-
return;
|
|
215
|
-
}
|
|
216
|
-
if (parentConfig?.isModalOpen === void 0) return;
|
|
217
|
-
setInternalModalOpen(parentConfig.isModalOpen);
|
|
218
|
-
}, [parentConfig?.isModalOpen, hasExplicitDefault]);
|
|
219
|
-
const resolvedIsModalOpen = hasExplicitDefault ? internalModalOpen : parentConfig?.isModalOpen ?? internalModalOpen;
|
|
220
|
-
const resolvedSetModalOpen = hasExplicitDefault ? setAndSync : parentConfig?.setModalOpen ?? setInternalModalOpen;
|
|
221
|
-
const [ownDrawerOpen, setOwnDrawerOpen] = (0, react.useState)(false);
|
|
222
|
-
const [ownDrawerCount, setOwnDrawerCount] = (0, react.useState)(0);
|
|
223
|
-
const modalCloseRef = (0, react.useRef)(() => {});
|
|
224
|
-
modalCloseRef.current = resolvedSetModalOpen;
|
|
225
|
-
const registeredModalClosersRef = (0, react.useRef)([]);
|
|
226
|
-
const ownRegisterModalCloser = (0, react.useCallback)((closeModal) => {
|
|
227
|
-
registeredModalClosersRef.current.push(closeModal);
|
|
228
|
-
return () => {
|
|
229
|
-
registeredModalClosersRef.current = registeredModalClosersRef.current.filter((entry) => entry !== closeModal);
|
|
230
|
-
};
|
|
231
|
-
}, []);
|
|
232
|
-
const ownSetDrawerOpen = (0, react.useCallback)((open) => {
|
|
233
|
-
setOwnDrawerOpen(open);
|
|
234
|
-
if (open && isMobileViewport()) {
|
|
235
|
-
const registered = registeredModalClosersRef.current;
|
|
236
|
-
(registered.length > 0 ? registered[registered.length - 1] : modalCloseRef.current)(false);
|
|
237
|
-
}
|
|
238
|
-
}, []);
|
|
239
|
-
const ownRegisterDrawer = (0, react.useCallback)(() => {
|
|
240
|
-
setOwnDrawerCount((count) => count + 1);
|
|
241
|
-
return () => {
|
|
242
|
-
setOwnDrawerCount((count) => Math.max(0, count - 1));
|
|
243
|
-
};
|
|
244
|
-
}, []);
|
|
245
|
-
const resolvedDrawerOpen = parentConfig ? parentConfig.drawerOpen : ownDrawerOpen;
|
|
246
|
-
const resolvedSetDrawerOpen = parentConfig ? parentConfig.setDrawerOpen : ownSetDrawerOpen;
|
|
247
|
-
const resolvedDrawerRegistered = parentConfig ? parentConfig.drawerRegistered : ownDrawerCount > 0;
|
|
248
|
-
const resolvedRegisterDrawer = parentConfig ? parentConfig.registerDrawer : ownRegisterDrawer;
|
|
249
|
-
const resolvedRegisterModalCloser = parentConfig ? parentConfig.ɵregisterModalCloser : ownRegisterModalCloser;
|
|
250
|
-
(0, react.useEffect)(() => {
|
|
251
|
-
if (!hasExplicitDefault) return;
|
|
252
|
-
return resolvedRegisterModalCloser(resolvedSetModalOpen);
|
|
253
|
-
}, [
|
|
254
|
-
hasExplicitDefault,
|
|
255
|
-
resolvedRegisterModalCloser,
|
|
256
|
-
resolvedSetModalOpen
|
|
257
|
-
]);
|
|
258
|
-
const isThreadIdControlledRef = (0, react.useRef)(isThreadIdControlled);
|
|
259
|
-
isThreadIdControlledRef.current = isThreadIdControlled;
|
|
260
|
-
const ownSetActiveThreadId = (0, react.useCallback)((id, options) => {
|
|
261
|
-
setActiveThreadOverride({
|
|
262
|
-
threadId: id,
|
|
263
|
-
explicit: options?.explicit ?? true
|
|
264
|
-
});
|
|
265
|
-
}, []);
|
|
266
|
-
const ownStartNewThread = (0, react.useCallback)(() => {
|
|
267
|
-
setActiveThreadOverride({
|
|
268
|
-
threadId: (0, _copilotkit_shared.randomUUID)(),
|
|
269
|
-
explicit: false
|
|
270
|
-
});
|
|
271
|
-
}, []);
|
|
272
|
-
const parentSetActiveThreadId = parentConfig?.setActiveThreadId;
|
|
273
|
-
const parentStartNewThread = parentConfig?.startNewThread;
|
|
274
|
-
const resolvedSetActiveThreadId = (0, react.useCallback)((id, options) => {
|
|
275
|
-
if (isThreadIdControlledRef.current) {
|
|
276
|
-
console.warn("[CopilotKit] Ignoring setActiveThreadId(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
|
|
277
|
-
return;
|
|
278
|
-
}
|
|
279
|
-
if (parentSetActiveThreadId) {
|
|
280
|
-
parentSetActiveThreadId(id, options);
|
|
281
|
-
return;
|
|
282
|
-
}
|
|
283
|
-
ownSetActiveThreadId(id, options);
|
|
284
|
-
}, [parentSetActiveThreadId, ownSetActiveThreadId]);
|
|
285
|
-
const resolvedStartNewThread = (0, react.useCallback)(() => {
|
|
286
|
-
if (isThreadIdControlledRef.current) {
|
|
287
|
-
console.warn("[CopilotKit] Ignoring startNewThread(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
|
|
288
|
-
return;
|
|
289
|
-
}
|
|
290
|
-
if (parentStartNewThread) {
|
|
291
|
-
parentStartNewThread();
|
|
292
|
-
return;
|
|
293
|
-
}
|
|
294
|
-
ownStartNewThread();
|
|
295
|
-
}, [parentStartNewThread, ownStartNewThread]);
|
|
296
|
-
const setModalOpenWithDrawerExclusion = (0, react.useCallback)((open) => {
|
|
297
|
-
if (open && isMobileViewport()) resolvedSetDrawerOpen(false);
|
|
298
|
-
resolvedSetModalOpen(open);
|
|
299
|
-
}, [resolvedSetModalOpen, resolvedSetDrawerOpen]);
|
|
300
|
-
const configurationValue = (0, react.useMemo)(() => ({
|
|
301
|
-
labels: mergedLabels,
|
|
302
|
-
agentId: resolvedAgentId,
|
|
303
|
-
threadId: resolvedThreadId,
|
|
304
|
-
hasExplicitThreadId: resolvedHasExplicitThreadId,
|
|
305
|
-
isModalOpen: resolvedIsModalOpen,
|
|
306
|
-
setModalOpen: setModalOpenWithDrawerExclusion,
|
|
307
|
-
drawerOpen: resolvedDrawerOpen,
|
|
308
|
-
setDrawerOpen: resolvedSetDrawerOpen,
|
|
309
|
-
drawerRegistered: resolvedDrawerRegistered,
|
|
310
|
-
registerDrawer: resolvedRegisterDrawer,
|
|
311
|
-
ɵregisterModalCloser: resolvedRegisterModalCloser,
|
|
312
|
-
setActiveThreadId: resolvedSetActiveThreadId,
|
|
313
|
-
startNewThread: resolvedStartNewThread
|
|
314
|
-
}), [
|
|
315
|
-
mergedLabels,
|
|
316
|
-
resolvedAgentId,
|
|
317
|
-
resolvedThreadId,
|
|
318
|
-
resolvedHasExplicitThreadId,
|
|
319
|
-
resolvedIsModalOpen,
|
|
320
|
-
setModalOpenWithDrawerExclusion,
|
|
321
|
-
resolvedDrawerOpen,
|
|
322
|
-
resolvedSetDrawerOpen,
|
|
323
|
-
resolvedDrawerRegistered,
|
|
324
|
-
resolvedRegisterDrawer,
|
|
325
|
-
resolvedRegisterModalCloser,
|
|
326
|
-
resolvedSetActiveThreadId,
|
|
327
|
-
resolvedStartNewThread
|
|
328
|
-
]);
|
|
329
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
|
|
330
|
-
value: configurationValue,
|
|
331
|
-
children
|
|
332
|
-
});
|
|
333
|
-
};
|
|
334
|
-
const useCopilotChatConfiguration = () => {
|
|
335
|
-
return (0, react.useContext)(CopilotChatConfiguration);
|
|
336
|
-
};
|
|
337
|
-
/**
|
|
338
|
-
* Reports modal open/close requests to the host, and — when `open` is
|
|
339
|
-
* supplied — makes the modal state of an already-established chat
|
|
340
|
-
* configuration **controlled** for the subtree it wraps.
|
|
341
|
-
*
|
|
342
|
-
* This is deliberately a scope component rather than another mode inside
|
|
343
|
-
* {@link CopilotChatConfigurationProvider}. The provider resolves modal state
|
|
344
|
-
* across a nested chain (own state, parent sync, drawer mutual-exclusion, the
|
|
345
|
-
* modal-closer registry); a controlled branch inside that resolution would add
|
|
346
|
-
* a fourth interacting mode. Overriding the context for the subtree instead
|
|
347
|
-
* leaves every one of those paths untouched:
|
|
348
|
-
*
|
|
349
|
-
* - `isModalOpen` is replaced with the host's `open`, so the rendered surface
|
|
350
|
-
* follows the prop from the very first frame (no open-then-close flash).
|
|
351
|
-
* - `setModalOpen` still calls the underlying setter, so the existing
|
|
352
|
-
* parent-sync and drawer mutual-exclusion side effects continue to run, and
|
|
353
|
-
* *then* reports the request through `onOpenChange`.
|
|
354
|
-
* - The wrapped setter is registered as the modal closer, so the drawer's
|
|
355
|
-
* mobile mutual-exclusion reaches the host instead of silently flipping
|
|
356
|
-
* state that nothing displays.
|
|
357
|
-
*
|
|
358
|
-
* A host that supplies `open` and ignores `onOpenChange` gets a modal pinned
|
|
359
|
-
* to `open`, which is the standard controlled-component contract. A host that
|
|
360
|
-
* supplies only `onOpenChange` is notified while the modal keeps managing
|
|
361
|
-
* itself.
|
|
362
|
-
*
|
|
363
|
-
* Renders `children` unchanged when no chat configuration is in scope.
|
|
364
|
-
*/
|
|
365
|
-
const ControlledModalOpenScope = ({ children, open, onOpenChange }) => {
|
|
366
|
-
const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
|
|
367
|
-
const parentSetModalOpen = parentConfig?.setModalOpen;
|
|
368
|
-
const registerModalCloser = parentConfig?.ɵregisterModalCloser;
|
|
369
|
-
const setModalOpen = (0, react.useCallback)((next) => {
|
|
370
|
-
parentSetModalOpen?.(next);
|
|
371
|
-
onOpenChange?.(next);
|
|
372
|
-
}, [parentSetModalOpen, onOpenChange]);
|
|
373
|
-
(0, react.useEffect)(() => {
|
|
374
|
-
if (!registerModalCloser) return;
|
|
375
|
-
return registerModalCloser(setModalOpen);
|
|
376
|
-
}, [registerModalCloser, setModalOpen]);
|
|
377
|
-
const configurationValue = (0, react.useMemo)(() => parentConfig ? {
|
|
378
|
-
...parentConfig,
|
|
379
|
-
isModalOpen: open ?? parentConfig.isModalOpen,
|
|
380
|
-
setModalOpen
|
|
381
|
-
} : null, [
|
|
382
|
-
parentConfig,
|
|
383
|
-
open,
|
|
384
|
-
setModalOpen
|
|
385
|
-
]);
|
|
386
|
-
if (!configurationValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
|
|
387
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
|
|
388
|
-
value: configurationValue,
|
|
389
|
-
children
|
|
390
|
-
});
|
|
391
|
-
};
|
|
392
|
-
ControlledModalOpenScope.displayName = "ControlledModalOpenScope";
|
|
32
|
+
react_markdown = require_MarkdownSurfaces.__toESM(react_markdown);
|
|
393
33
|
|
|
394
|
-
//#endregion
|
|
395
34
|
//#region src/v2/lib/utils.ts
|
|
396
35
|
const twMerge$12 = (0, tailwind_merge.extendTailwindMerge)({ prefix: "cpk" });
|
|
397
36
|
function cn(...inputs) {
|
|
@@ -821,7 +460,7 @@ const MemoizedSlotWrapper = react.default.memo(react.default.forwardRef(function
|
|
|
821
460
|
if (prev.$component !== next.$component) return false;
|
|
822
461
|
const { $slot: _ps, $component: _pc, ...prevRest } = prev;
|
|
823
462
|
const { $slot: _ns, $component: _nc, ...nextRest } = next;
|
|
824
|
-
return shallowEqual(prevRest, nextRest);
|
|
463
|
+
return require_MarkdownSurfaces.shallowEqual(prevRest, nextRest);
|
|
825
464
|
});
|
|
826
465
|
/**
|
|
827
466
|
* Renders a slot value as a memoized React element.
|
|
@@ -867,8 +506,8 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
867
506
|
const actionsContainerRef = (0, react.useRef)(null);
|
|
868
507
|
const audioRecorderRef = (0, react.useRef)(null);
|
|
869
508
|
const slashMenuRef = (0, react.useRef)(null);
|
|
870
|
-
const config = useCopilotChatConfiguration();
|
|
871
|
-
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
509
|
+
const config = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
510
|
+
const labels = config?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
872
511
|
const previousModalStateRef = (0, react.useRef)(void 0);
|
|
873
512
|
const measurementCanvasRef = (0, react.useRef)(null);
|
|
874
513
|
const measurementsRef = (0, react.useRef)({
|
|
@@ -1094,37 +733,6 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1094
733
|
});
|
|
1095
734
|
const BoundDisclaimer = renderSlot(disclaimer, CopilotChatInput.Disclaimer, {});
|
|
1096
735
|
const shouldShowDisclaimer = showDisclaimer ?? positioning === "absolute";
|
|
1097
|
-
if (children) {
|
|
1098
|
-
const childProps = {
|
|
1099
|
-
textArea: BoundTextArea,
|
|
1100
|
-
audioRecorder: BoundAudioRecorder,
|
|
1101
|
-
sendButton: BoundSendButton,
|
|
1102
|
-
startTranscribeButton: BoundStartTranscribeButton,
|
|
1103
|
-
cancelTranscribeButton: BoundCancelTranscribeButton,
|
|
1104
|
-
finishTranscribeButton: BoundFinishTranscribeButton,
|
|
1105
|
-
addMenuButton: BoundAddMenuButton,
|
|
1106
|
-
disclaimer: BoundDisclaimer,
|
|
1107
|
-
onSubmitMessage,
|
|
1108
|
-
onStop,
|
|
1109
|
-
isRunning,
|
|
1110
|
-
onStartTranscribe,
|
|
1111
|
-
onCancelTranscribe,
|
|
1112
|
-
onFinishTranscribe,
|
|
1113
|
-
onAddFile,
|
|
1114
|
-
mode,
|
|
1115
|
-
toolsMenu,
|
|
1116
|
-
autoFocus,
|
|
1117
|
-
positioning,
|
|
1118
|
-
keyboardHeight,
|
|
1119
|
-
showDisclaimer: shouldShowDisclaimer,
|
|
1120
|
-
containerRef
|
|
1121
|
-
};
|
|
1122
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1123
|
-
"data-copilotkit": true,
|
|
1124
|
-
style: { display: "contents" },
|
|
1125
|
-
children: children(childProps)
|
|
1126
|
-
});
|
|
1127
|
-
}
|
|
1128
736
|
const handleContainerClick = (e) => {
|
|
1129
737
|
const target = e.target;
|
|
1130
738
|
if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") inputRef.current.focus();
|
|
@@ -1208,7 +816,11 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1208
816
|
const grid = gridRef.current;
|
|
1209
817
|
const addContainer = addButtonContainerRef.current;
|
|
1210
818
|
const actionsContainer = actionsContainerRef.current;
|
|
1211
|
-
if (!textarea
|
|
819
|
+
if (!textarea) return;
|
|
820
|
+
if (!grid || !addContainer || !actionsContainer) {
|
|
821
|
+
adjustTextareaHeight();
|
|
822
|
+
return;
|
|
823
|
+
}
|
|
1212
824
|
if (measurementsRef.current.singleLineHeight === 0) ensureMeasurements();
|
|
1213
825
|
const scrollHeight = adjustTextareaHeight();
|
|
1214
826
|
const baseline = measurementsRef.current.singleLineHeight;
|
|
@@ -1312,13 +924,13 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1312
924
|
const slashMenu = slashMenuVisible ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1313
925
|
"data-testid": "copilot-slash-menu",
|
|
1314
926
|
role: "listbox",
|
|
1315
|
-
"aria-label":
|
|
927
|
+
"aria-label": labels.chatInputSlashMenuLabel,
|
|
1316
928
|
ref: slashMenuRef,
|
|
1317
929
|
className: "cpk:absolute cpk:bottom-full cpk:left-0 cpk:right-0 cpk:z-30 cpk:mb-2 cpk:max-h-64 cpk:overflow-y-auto cpk:rounded-lg cpk:border cpk:border-border cpk:bg-white cpk:shadow-lg cpk:dark:border-[#3a3a3a] cpk:dark:bg-[#1f1f1f]",
|
|
1318
930
|
style: { maxHeight: `${SLASH_MENU_MAX_VISIBLE_ITEMS * SLASH_MENU_ITEM_HEIGHT_PX}px` },
|
|
1319
931
|
children: filteredCommands.length === 0 ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1320
932
|
className: "cpk:px-3 cpk:py-2 cpk:text-sm cpk:text-muted-foreground",
|
|
1321
|
-
children:
|
|
933
|
+
children: labels.chatInputSlashMenuEmptyText
|
|
1322
934
|
}) : filteredCommands.map((item, index) => {
|
|
1323
935
|
const isActive = index === slashHighlightIndex;
|
|
1324
936
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
@@ -1367,6 +979,37 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1367
979
|
]
|
|
1368
980
|
})
|
|
1369
981
|
});
|
|
982
|
+
if (children) {
|
|
983
|
+
const childProps = {
|
|
984
|
+
textArea: BoundTextArea,
|
|
985
|
+
audioRecorder: BoundAudioRecorder,
|
|
986
|
+
sendButton: BoundSendButton,
|
|
987
|
+
startTranscribeButton: BoundStartTranscribeButton,
|
|
988
|
+
cancelTranscribeButton: BoundCancelTranscribeButton,
|
|
989
|
+
finishTranscribeButton: BoundFinishTranscribeButton,
|
|
990
|
+
addMenuButton: BoundAddMenuButton,
|
|
991
|
+
disclaimer: BoundDisclaimer,
|
|
992
|
+
onSubmitMessage,
|
|
993
|
+
onStop,
|
|
994
|
+
isRunning,
|
|
995
|
+
onStartTranscribe,
|
|
996
|
+
onCancelTranscribe,
|
|
997
|
+
onFinishTranscribe,
|
|
998
|
+
onAddFile,
|
|
999
|
+
mode,
|
|
1000
|
+
toolsMenu,
|
|
1001
|
+
autoFocus,
|
|
1002
|
+
positioning,
|
|
1003
|
+
keyboardHeight,
|
|
1004
|
+
showDisclaimer: shouldShowDisclaimer,
|
|
1005
|
+
containerRef
|
|
1006
|
+
};
|
|
1007
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1008
|
+
"data-copilotkit": true,
|
|
1009
|
+
style: { display: "contents" },
|
|
1010
|
+
children: children(childProps)
|
|
1011
|
+
});
|
|
1012
|
+
}
|
|
1370
1013
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1371
1014
|
"data-copilotkit": true,
|
|
1372
1015
|
ref: containerRef,
|
|
@@ -1385,7 +1028,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1385
1028
|
}
|
|
1386
1029
|
(function(_CopilotChatInput) {
|
|
1387
1030
|
_CopilotChatInput.SendButton = ({ className, children, ...props }) => {
|
|
1388
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
1031
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
1389
1032
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1390
1033
|
className: "cpk:mr-[10px]",
|
|
1391
1034
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
@@ -1401,7 +1044,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1401
1044
|
});
|
|
1402
1045
|
};
|
|
1403
1046
|
const ToolbarButton = _CopilotChatInput.ToolbarButton = ({ icon, labelKey, defaultClassName, className, ...props }) => {
|
|
1404
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
1047
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
1405
1048
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(Tooltip, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(TooltipTrigger, {
|
|
1406
1049
|
asChild: true,
|
|
1407
1050
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
@@ -1440,7 +1083,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1440
1083
|
...props
|
|
1441
1084
|
});
|
|
1442
1085
|
_CopilotChatInput.AddMenuButton = ({ className, toolsMenu, onAddFile, disabled, ...props }) => {
|
|
1443
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
1086
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
1444
1087
|
const [mounted, setMounted] = (0, react.useState)(false);
|
|
1445
1088
|
(0, react.useEffect)(() => setMounted(true), []);
|
|
1446
1089
|
const menuItems = (0, react.useMemo)(() => {
|
|
@@ -1508,7 +1151,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1508
1151
|
};
|
|
1509
1152
|
_CopilotChatInput.TextArea = (0, react.forwardRef)(function TextArea({ style, className, autoFocus, placeholder, ...props }, ref) {
|
|
1510
1153
|
const internalTextareaRef = (0, react.useRef)(null);
|
|
1511
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
1154
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
1512
1155
|
(0, react.useImperativeHandle)(ref, () => internalTextareaRef.current);
|
|
1513
1156
|
(0, react.useEffect)(() => {
|
|
1514
1157
|
if (autoFocus) internalTextareaRef.current?.focus({ preventScroll: true });
|
|
@@ -1529,7 +1172,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1529
1172
|
});
|
|
1530
1173
|
_CopilotChatInput.AudioRecorder = CopilotChatAudioRecorder;
|
|
1531
1174
|
_CopilotChatInput.Disclaimer = ({ className, ...props }) => {
|
|
1532
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
1175
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
1533
1176
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1534
1177
|
className: cn("cpk:text-center cpk:text-xs cpk:text-muted-foreground cpk:py-3 cpk:px-4 cpk:max-w-3xl cpk:mx-auto", className),
|
|
1535
1178
|
...props,
|
|
@@ -1547,25 +1190,6 @@ CopilotChatInput.AddMenuButton.displayName = "CopilotChatInput.AddMenuButton";
|
|
|
1547
1190
|
CopilotChatInput.Disclaimer.displayName = "CopilotChatInput.Disclaimer";
|
|
1548
1191
|
var CopilotChatInput_default = CopilotChatInput;
|
|
1549
1192
|
|
|
1550
|
-
//#endregion
|
|
1551
|
-
//#region src/v2/hooks/useKatexStyles.ts
|
|
1552
|
-
let injected = false;
|
|
1553
|
-
/**
|
|
1554
|
-
* Dynamically injects KaTeX CSS at runtime to avoid the Next.js
|
|
1555
|
-
* "Global CSS cannot be imported from within node_modules" build error.
|
|
1556
|
-
*
|
|
1557
|
-
* Uses a singleton flag so the stylesheet is only injected once.
|
|
1558
|
-
*/
|
|
1559
|
-
function useKatexStyles() {
|
|
1560
|
-
(0, react.useEffect)(() => {
|
|
1561
|
-
if (injected || typeof document === "undefined") return;
|
|
1562
|
-
injected = true;
|
|
1563
|
-
import("katex/dist/katex.min.css").catch(() => {
|
|
1564
|
-
console.warn("[CopilotKit] Failed to load katex styles — math content may render without formatting");
|
|
1565
|
-
});
|
|
1566
|
-
}, []);
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
1193
|
//#endregion
|
|
1570
1194
|
//#region src/v2/hooks/use-render-tool-call.tsx
|
|
1571
1195
|
/**
|
|
@@ -1663,7 +1287,7 @@ function useToolCallRendererNames() {
|
|
|
1663
1287
|
*/
|
|
1664
1288
|
function useRenderToolCall() {
|
|
1665
1289
|
const { copilotkit, executingToolCallIds } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
1666
|
-
const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
1290
|
+
const agentId = require_MarkdownSurfaces.useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
1667
1291
|
const unrenderedToolNames = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
1668
1292
|
const warnedToolNames = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
1669
1293
|
const renderToolCalls = useToolCallRenderers();
|
|
@@ -1701,7 +1325,7 @@ function useRenderToolCall() {
|
|
|
1701
1325
|
|
|
1702
1326
|
//#endregion
|
|
1703
1327
|
//#region package.json
|
|
1704
|
-
var version = "1.
|
|
1328
|
+
var version = "1.82.0";
|
|
1705
1329
|
|
|
1706
1330
|
//#endregion
|
|
1707
1331
|
//#region src/v2/components/CopilotKitInspector.tsx
|
|
@@ -3006,7 +2630,7 @@ function createA2UIMessageRenderer(options) {
|
|
|
3006
2630
|
const groupedOperations = (0, react.useMemo)(() => {
|
|
3007
2631
|
const groups = /* @__PURE__ */ new Map();
|
|
3008
2632
|
for (const operation of operations) {
|
|
3009
|
-
const surfaceId = getOperationSurfaceId(operation) ?? _copilotkit_a2ui_renderer.DEFAULT_SURFACE_ID;
|
|
2633
|
+
const surfaceId = getOperationSurfaceId$1(operation) ?? _copilotkit_a2ui_renderer.DEFAULT_SURFACE_ID;
|
|
3010
2634
|
if (!groups.has(surfaceId)) groups.set(surfaceId, []);
|
|
3011
2635
|
groups.get(surfaceId).push(operation);
|
|
3012
2636
|
}
|
|
@@ -3228,7 +2852,7 @@ function surfaceHasRenderableContent(operations) {
|
|
|
3228
2852
|
* @param operation - One A2UI operation, of any shape.
|
|
3229
2853
|
* @returns The surface id, or null when the operation names none.
|
|
3230
2854
|
*/
|
|
3231
|
-
function getOperationSurfaceId(operation) {
|
|
2855
|
+
function getOperationSurfaceId$1(operation) {
|
|
3232
2856
|
if (!operation || typeof operation !== "object") return null;
|
|
3233
2857
|
const nested = operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId;
|
|
3234
2858
|
if (typeof nested === "string") return nested;
|
|
@@ -3236,19 +2860,6 @@ function getOperationSurfaceId(operation) {
|
|
|
3236
2860
|
return null;
|
|
3237
2861
|
}
|
|
3238
2862
|
|
|
3239
|
-
//#endregion
|
|
3240
|
-
//#region src/v2/types/defineToolCallRenderer.ts
|
|
3241
|
-
function defineToolCallRenderer(def) {
|
|
3242
|
-
const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
|
|
3243
|
-
return {
|
|
3244
|
-
name: def.name,
|
|
3245
|
-
args: argsSchema,
|
|
3246
|
-
render: def.render,
|
|
3247
|
-
...def.agentId ? { agentId: def.agentId } : {},
|
|
3248
|
-
...def.group ? { group: true } : {}
|
|
3249
|
-
};
|
|
3250
|
-
}
|
|
3251
|
-
|
|
3252
2863
|
//#endregion
|
|
3253
2864
|
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3254
2865
|
/**
|
|
@@ -3272,73 +2883,1886 @@ const RENDER_A2UI_TOOL_NAME = "render_a2ui";
|
|
|
3272
2883
|
function A2UIBuiltInToolCallRenderer() {
|
|
3273
2884
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
3274
2885
|
(0, react.useEffect)(() => {
|
|
3275
|
-
const renderer = defineToolCallRenderer({
|
|
2886
|
+
const renderer = require_MarkdownSurfaces.defineToolCallRenderer({
|
|
3276
2887
|
name: RENDER_A2UI_TOOL_NAME,
|
|
3277
2888
|
args: zod.z.any(),
|
|
3278
2889
|
render: () => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, {})
|
|
3279
2890
|
});
|
|
3280
|
-
const existing = copilotkit._renderToolCalls ?? [];
|
|
3281
|
-
copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
|
|
3282
|
-
}, [copilotkit]);
|
|
3283
|
-
return null;
|
|
2891
|
+
const existing = copilotkit._renderToolCalls ?? [];
|
|
2892
|
+
copilotkit.setRenderToolCalls([...existing.filter((rc) => rc.name !== RENDER_A2UI_TOOL_NAME), renderer]);
|
|
2893
|
+
}, [copilotkit]);
|
|
2894
|
+
return null;
|
|
2895
|
+
}
|
|
2896
|
+
|
|
2897
|
+
//#endregion
|
|
2898
|
+
//#region src/v2/a2ui/A2UICatalogContext.tsx
|
|
2899
|
+
/**
|
|
2900
|
+
* Renders agent context describing the available A2UI catalog and custom components.
|
|
2901
|
+
* Only mount this component when A2UI is enabled.
|
|
2902
|
+
*
|
|
2903
|
+
* The entries are scoped to the agents the runtime applies A2UI to
|
|
2904
|
+
* (`copilotkit.a2uiAgents`, #5369), so agents outside that list don't receive
|
|
2905
|
+
* the catalog/schema/guidelines payload on their runs.
|
|
2906
|
+
*
|
|
2907
|
+
* When `includeSchema` is true, the full component schemas (JSON Schema) are also
|
|
2908
|
+
* sent as context using the same description key as the A2UI middleware, so the
|
|
2909
|
+
* middleware can optionally overwrite it with a server-side schema.
|
|
2910
|
+
*/
|
|
2911
|
+
function A2UICatalogContext({ catalog, includeSchema }) {
|
|
2912
|
+
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
2913
|
+
const capabilitiesValue = (0, react.useMemo)(() => (0, _copilotkit_a2ui_renderer.buildCatalogContextValue)(catalog, { includeSchema: includeSchema !== false }), [catalog, includeSchema]);
|
|
2914
|
+
const schemaValue = (0, react.useMemo)(() => includeSchema !== false ? JSON.stringify((0, _copilotkit_a2ui_renderer.extractCatalogComponentSchemas)(catalog)) : null, [catalog, includeSchema]);
|
|
2915
|
+
const a2uiAgentsKey = copilotkit?.a2uiAgents?.join(",");
|
|
2916
|
+
(0, react.useLayoutEffect)(() => {
|
|
2917
|
+
if (!copilotkit) return;
|
|
2918
|
+
const agentIds = copilotkit.a2uiAgents;
|
|
2919
|
+
const scope = agentIds ? { agentIds } : {};
|
|
2920
|
+
const ids = [];
|
|
2921
|
+
ids.push(copilotkit.addContext({
|
|
2922
|
+
description: "A2UI catalog capabilities: available catalog IDs and custom component definitions the client can render.",
|
|
2923
|
+
value: capabilitiesValue,
|
|
2924
|
+
...scope
|
|
2925
|
+
}));
|
|
2926
|
+
if (schemaValue) {
|
|
2927
|
+
ids.push(copilotkit.addContext({
|
|
2928
|
+
description: _copilotkit_a2ui_renderer.A2UI_SCHEMA_CONTEXT_DESCRIPTION,
|
|
2929
|
+
value: schemaValue,
|
|
2930
|
+
...scope
|
|
2931
|
+
}));
|
|
2932
|
+
ids.push(copilotkit.addContext({
|
|
2933
|
+
description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
|
|
2934
|
+
value: _copilotkit_shared.A2UI_DEFAULT_GENERATION_GUIDELINES,
|
|
2935
|
+
...scope
|
|
2936
|
+
}));
|
|
2937
|
+
ids.push(copilotkit.addContext({
|
|
2938
|
+
description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
|
|
2939
|
+
value: _copilotkit_shared.A2UI_DEFAULT_DESIGN_GUIDELINES,
|
|
2940
|
+
...scope
|
|
2941
|
+
}));
|
|
2942
|
+
}
|
|
2943
|
+
return () => {
|
|
2944
|
+
for (const id of ids) copilotkit.removeContext(id);
|
|
2945
|
+
};
|
|
2946
|
+
}, [
|
|
2947
|
+
copilotkit,
|
|
2948
|
+
capabilitiesValue,
|
|
2949
|
+
schemaValue,
|
|
2950
|
+
a2uiAgentsKey
|
|
2951
|
+
]);
|
|
2952
|
+
return null;
|
|
2953
|
+
}
|
|
2954
|
+
|
|
2955
|
+
//#endregion
|
|
2956
|
+
//#region src/v2/generative-ui/action-message.ts
|
|
2957
|
+
/** Context keys that supply the message's first line, in priority order. */
|
|
2958
|
+
const TEXT_KEYS = ["message", "label"];
|
|
2959
|
+
function isNonEmptyString(value) {
|
|
2960
|
+
return typeof value === "string" && value.trim().length > 0;
|
|
2961
|
+
}
|
|
2962
|
+
/** `choose_plan`, `choose-plan` and `choosePlan` all become "Choose plan". */
|
|
2963
|
+
function humanize(name) {
|
|
2964
|
+
const spaced = name.replace(/[_-]+/g, " ").replace(/([a-z])([A-Z])/g, "$1 $2").trim();
|
|
2965
|
+
return spaced.charAt(0).toUpperCase() + spaced.slice(1).toLowerCase();
|
|
2966
|
+
}
|
|
2967
|
+
function formatContextValue(value) {
|
|
2968
|
+
return typeof value === "object" ? JSON.stringify(value) : String(value);
|
|
2969
|
+
}
|
|
2970
|
+
/**
|
|
2971
|
+
* Turns a user event that no function handles into the text of a visible
|
|
2972
|
+
* user message.
|
|
2973
|
+
*
|
|
2974
|
+
* The first line is, in order: `userMessage`, `context.message`,
|
|
2975
|
+
* `context.label`, the label of the source component (from `resolveLabel`),
|
|
2976
|
+
* or the event name made readable (`choose_plan` becomes "Choose plan").
|
|
2977
|
+
* Each other context field follows as one `key: value` line. Objects are
|
|
2978
|
+
* written as JSON. `null` and `undefined` fields are skipped.
|
|
2979
|
+
*
|
|
2980
|
+
* @param event - The user event, as sent by a surface.
|
|
2981
|
+
* @param resolveLabel - Finds the visible label of a component by id. Build
|
|
2982
|
+
* one with {@link createComponentLabelResolver}.
|
|
2983
|
+
*
|
|
2984
|
+
* @example
|
|
2985
|
+
* ```ts
|
|
2986
|
+
* buildActionMessageText({
|
|
2987
|
+
* name: "choose_plan",
|
|
2988
|
+
* surfaceId: "plans",
|
|
2989
|
+
* componentId: "team-button",
|
|
2990
|
+
* userMessage: "I pick the Team plan",
|
|
2991
|
+
* context: { seats: 12 },
|
|
2992
|
+
* });
|
|
2993
|
+
* // "I pick the Team plan\n\nseats: 12"
|
|
2994
|
+
* ```
|
|
2995
|
+
*/
|
|
2996
|
+
function buildActionMessageText(event, resolveLabel) {
|
|
2997
|
+
const { context, userMessage } = event;
|
|
2998
|
+
const explicit = [userMessage, ...TEXT_KEYS.map((key) => context[key])].find(isNonEmptyString);
|
|
2999
|
+
const resolved = explicit ? void 0 : resolveLabel?.(event.componentId);
|
|
3000
|
+
const head = explicit ?? (isNonEmptyString(resolved) ? resolved.trim() : humanize(event.name));
|
|
3001
|
+
const lines = Object.entries(context).filter(([key, value]) => !TEXT_KEYS.includes(key) && value !== void 0 && value !== null).map(([key, value]) => `${key}: ${formatContextValue(value)}`);
|
|
3002
|
+
return lines.length > 0 ? `${head}\n\n${lines.join("\n")}` : head;
|
|
3003
|
+
}
|
|
3004
|
+
function ownText(component) {
|
|
3005
|
+
if (!component) return void 0;
|
|
3006
|
+
if (isNonEmptyString(component.label)) return component.label;
|
|
3007
|
+
if (isNonEmptyString(component.text)) return component.text;
|
|
3008
|
+
}
|
|
3009
|
+
function childIds(component) {
|
|
3010
|
+
const { child, children } = component;
|
|
3011
|
+
const single = typeof child === "string" ? [child] : [];
|
|
3012
|
+
const multiple = Array.isArray(children) ? children.filter((id) => typeof id === "string") : [];
|
|
3013
|
+
return [...single, ...multiple];
|
|
3014
|
+
}
|
|
3015
|
+
/** The components that an operation adds, inline or in an update. */
|
|
3016
|
+
function componentsOf(operation) {
|
|
3017
|
+
if ("createSurface" in operation) return operation.createSurface.components ?? [];
|
|
3018
|
+
if ("updateComponents" in operation) return operation.updateComponents.components;
|
|
3019
|
+
return [];
|
|
3020
|
+
}
|
|
3021
|
+
/**
|
|
3022
|
+
* Builds a function that finds the visible label of a component on a surface.
|
|
3023
|
+
*
|
|
3024
|
+
* The label is the component's own string `label`, else its string `text`,
|
|
3025
|
+
* else the first `child` or `children` component that has a string `label`
|
|
3026
|
+
* or `text`. When a component id is defined more than once, the last
|
|
3027
|
+
* definition wins, as in the renderer.
|
|
3028
|
+
*
|
|
3029
|
+
* @param operations - The committed operations of the surface.
|
|
3030
|
+
*
|
|
3031
|
+
* @example
|
|
3032
|
+
* ```ts
|
|
3033
|
+
* const resolveLabel = createComponentLabelResolver(surface.operations);
|
|
3034
|
+
* buildActionMessageText(event, resolveLabel);
|
|
3035
|
+
* ```
|
|
3036
|
+
*/
|
|
3037
|
+
function createComponentLabelResolver(operations) {
|
|
3038
|
+
const byId = /* @__PURE__ */ new Map();
|
|
3039
|
+
for (const operation of operations) {
|
|
3040
|
+
const components = componentsOf(operation);
|
|
3041
|
+
for (const component of components) byId.set(component.id, component);
|
|
3042
|
+
}
|
|
3043
|
+
return (componentId) => {
|
|
3044
|
+
const component = byId.get(componentId);
|
|
3045
|
+
if (!component) return void 0;
|
|
3046
|
+
const own = ownText(component);
|
|
3047
|
+
if (own) return own;
|
|
3048
|
+
const ids = childIds(component);
|
|
3049
|
+
for (const id of ids) {
|
|
3050
|
+
const text = ownText(byId.get(id));
|
|
3051
|
+
if (text) return text;
|
|
3052
|
+
}
|
|
3053
|
+
};
|
|
3054
|
+
}
|
|
3055
|
+
|
|
3056
|
+
//#endregion
|
|
3057
|
+
//#region src/v2/generative-ui/manifest.ts
|
|
3058
|
+
/**
|
|
3059
|
+
* The built-in functions (the A2UI basic catalog plus calc and series) as
|
|
3060
|
+
* manifest entries. Their args are described by the short signature, not
|
|
3061
|
+
* by a full JSON Schema: the renderer checks them when they run. An app
|
|
3062
|
+
* function of the same name replaces the entry.
|
|
3063
|
+
*/
|
|
3064
|
+
function builtInFunctionManifests() {
|
|
3065
|
+
return Object.fromEntries(Object.entries(_copilotkit_shared.GENERATIVE_UI_FUNCTIONS).map(([name, fn]) => [name, {
|
|
3066
|
+
description: fn.description,
|
|
3067
|
+
parameters: {
|
|
3068
|
+
type: "object",
|
|
3069
|
+
description: fn.parameters
|
|
3070
|
+
},
|
|
3071
|
+
returnType: fn.returnType,
|
|
3072
|
+
allowedCallers: fn.allowedCallers,
|
|
3073
|
+
...fn.requiresUserActivation ? { requiresUserActivation: true } : {}
|
|
3074
|
+
}]));
|
|
3075
|
+
}
|
|
3076
|
+
/**
|
|
3077
|
+
* Builds the per-run manifest. Never contains handlers or renderers.
|
|
3078
|
+
*
|
|
3079
|
+
* - `functions`: the built-in functions, then the declared functions with
|
|
3080
|
+
* exactly one mounted handler.
|
|
3081
|
+
* - `targets`: the chat first, then each mounted `<GenerativeUISurface>`,
|
|
3082
|
+
* with its `description` and its `components` when it has them.
|
|
3083
|
+
*/
|
|
3084
|
+
function buildGenerativeUIManifest(runtime, threadId) {
|
|
3085
|
+
const { ui, manager, dispatcher } = runtime;
|
|
3086
|
+
const inlineTargets = manager.getMountedTargets().filter((target) => target.id !== _copilotkit_shared.GENERATIVE_UI_CHAT_TARGET).map(({ id, ...rest }) => ({
|
|
3087
|
+
id,
|
|
3088
|
+
kind: "inline",
|
|
3089
|
+
...rest
|
|
3090
|
+
}));
|
|
3091
|
+
return {
|
|
3092
|
+
catalogId: ui.id,
|
|
3093
|
+
catalogIds: require_MarkdownSurfaces.catalogIdsOf(ui),
|
|
3094
|
+
components: ui.manifestComponents,
|
|
3095
|
+
functions: {
|
|
3096
|
+
...Object.fromEntries(Object.entries(builtInFunctionManifests()).filter(([name]) => !ui.functions.has(name))),
|
|
3097
|
+
...dispatcher.listExposed()
|
|
3098
|
+
},
|
|
3099
|
+
targets: [{
|
|
3100
|
+
id: _copilotkit_shared.GENERATIVE_UI_CHAT_TARGET,
|
|
3101
|
+
kind: "chat"
|
|
3102
|
+
}, ...inlineTargets],
|
|
3103
|
+
surfaces: threadId ? manager.describeSurfaces(threadId) : {}
|
|
3104
|
+
};
|
|
3105
|
+
}
|
|
3106
|
+
/**
|
|
3107
|
+
* Builds the envelope that a run sends as `forwardedProps.copilotkit.ui`,
|
|
3108
|
+
* from the per-run manifest. It has the A2UI v1.0 renderer capabilities
|
|
3109
|
+
* shape: one inline catalog with the id of the UI, and the CopilotKit data
|
|
3110
|
+
* in `metadata.extensions`.
|
|
3111
|
+
*
|
|
3112
|
+
* The inline catalog has no `components` only for the markdown transport
|
|
3113
|
+
* with `includeCatalog: false`. It has `instructions` for the markdown
|
|
3114
|
+
* transport, or when given.
|
|
3115
|
+
*
|
|
3116
|
+
* @param runtime - The generative UI runtime of the provider.
|
|
3117
|
+
* @param threadId - The thread of the run. Its surfaces go in `copilotkit_surfaces`.
|
|
3118
|
+
* @param options - The transport and what to send.
|
|
3119
|
+
*
|
|
3120
|
+
* @example
|
|
3121
|
+
* ```ts
|
|
3122
|
+
* const envelope = buildGenerativeUIEnvelope(runtime, agent.threadId, {
|
|
3123
|
+
* transport: "tool",
|
|
3124
|
+
* includeCatalog: true,
|
|
3125
|
+
* contextSent: false,
|
|
3126
|
+
* });
|
|
3127
|
+
* envelope["v1.0"].supportedCatalogIds; // [runtime.ui.id]
|
|
3128
|
+
* ```
|
|
3129
|
+
*/
|
|
3130
|
+
function buildGenerativeUIEnvelope(runtime, threadId, options) {
|
|
3131
|
+
const { transport, includeCatalog, contextSent, action } = options;
|
|
3132
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3133
|
+
const instructions = options.instructions ?? (transport === "markdown" ? (0, _copilotkit_shared.buildGenerativeUIMarkdownGuidelines)((0, _copilotkit_shared.generativeUIGuideFeatures)(manifest)) : void 0);
|
|
3134
|
+
const omitComponents = transport === "markdown" && !includeCatalog;
|
|
3135
|
+
return {
|
|
3136
|
+
"v1.0": {
|
|
3137
|
+
supportedCatalogIds: manifest.catalogIds ?? [manifest.catalogId],
|
|
3138
|
+
inlineCatalogs: [{
|
|
3139
|
+
catalogId: manifest.catalogId,
|
|
3140
|
+
protocolVersion: "1.0",
|
|
3141
|
+
...omitComponents ? {} : { components: manifest.components },
|
|
3142
|
+
functions: manifest.functions,
|
|
3143
|
+
...instructions === void 0 ? {} : { instructions }
|
|
3144
|
+
}]
|
|
3145
|
+
},
|
|
3146
|
+
metadata: { extensions: {
|
|
3147
|
+
copilotkit_format: _copilotkit_shared.COPILOTKIT_UI_ENVELOPE_FORMAT,
|
|
3148
|
+
copilotkit_transport: transport,
|
|
3149
|
+
copilotkit_targets: manifest.targets,
|
|
3150
|
+
copilotkit_surfaces: manifest.surfaces,
|
|
3151
|
+
copilotkit_contextSent: contextSent,
|
|
3152
|
+
...action === void 0 ? {} : { copilotkit_action: action }
|
|
3153
|
+
} }
|
|
3154
|
+
};
|
|
3155
|
+
}
|
|
3156
|
+
|
|
3157
|
+
//#endregion
|
|
3158
|
+
//#region src/v2/generative-ui/markdown/context.ts
|
|
3159
|
+
/** Objects nested deeper than this show as `object`. */
|
|
3160
|
+
const MAX_OBJECT_DEPTH = 2;
|
|
3161
|
+
/** A prop must appear verbatim in at least this many components to be hoisted. */
|
|
3162
|
+
const COMMON_PROP_MIN_COMPONENTS = 8;
|
|
3163
|
+
/** A JSON Schema of a list of schemas (`anyOf`, `oneOf`), else an empty list. */
|
|
3164
|
+
function schemaList(value) {
|
|
3165
|
+
return Array.isArray(value) ? value.filter(require_MarkdownSurfaces.isRecord) : [];
|
|
3166
|
+
}
|
|
3167
|
+
/**
|
|
3168
|
+
* Puts a top-level union in parentheses, so that `[]` applies to all of
|
|
3169
|
+
* it. A union inside braces needs none.
|
|
3170
|
+
*/
|
|
3171
|
+
function asArrayItem(type) {
|
|
3172
|
+
let outside = type;
|
|
3173
|
+
for (let inner = outside.replace(/\{[^{}]*\}/g, ""); inner !== outside;) {
|
|
3174
|
+
outside = inner;
|
|
3175
|
+
inner = outside.replace(/\{[^{}]*\}/g, "");
|
|
3176
|
+
}
|
|
3177
|
+
return outside.includes(" | ") ? `(${type})[]` : `${type}[]`;
|
|
3178
|
+
}
|
|
3179
|
+
/**
|
|
3180
|
+
* A JSON Schema as a short TypeScript-like type, for example
|
|
3181
|
+
* `{ label: string; size?: "sm" | "md" }`.
|
|
3182
|
+
*/
|
|
3183
|
+
function compactType(schema, depth) {
|
|
3184
|
+
const ref = (0, _copilotkit_shared.childRefKind)(schema);
|
|
3185
|
+
if (ref === "single") return "componentId";
|
|
3186
|
+
if (ref === "multiple") return "componentId[] | { componentId: string; path: string }";
|
|
3187
|
+
if ("const" in schema) return JSON.stringify(schema.const);
|
|
3188
|
+
if (Array.isArray(schema.enum)) return schema.enum.map((value) => JSON.stringify(value)).join(" | ");
|
|
3189
|
+
const variants = [...schemaList(schema.anyOf), ...schemaList(schema.oneOf)];
|
|
3190
|
+
if (variants.length > 0) return variants.map((variant) => compactType(variant, depth)).join(" | ");
|
|
3191
|
+
return (Array.isArray(schema.type) ? schema.type : [schema.type]).map((type) => {
|
|
3192
|
+
switch (type) {
|
|
3193
|
+
case "string":
|
|
3194
|
+
case "boolean":
|
|
3195
|
+
case "null": return type;
|
|
3196
|
+
case "number":
|
|
3197
|
+
case "integer": return "number";
|
|
3198
|
+
case "array": return require_MarkdownSurfaces.isRecord(schema.items) ? asArrayItem(compactType(schema.items, depth)) : "unknown[]";
|
|
3199
|
+
case "object": return compactObject(schema, depth);
|
|
3200
|
+
default: return "unknown";
|
|
3201
|
+
}
|
|
3202
|
+
}).join(" | ");
|
|
3203
|
+
}
|
|
3204
|
+
/** An object schema as `{ key: type; other?: type }`. */
|
|
3205
|
+
function compactObject(schema, depth) {
|
|
3206
|
+
const properties = require_MarkdownSurfaces.isRecord(schema.properties) ? schema.properties : {};
|
|
3207
|
+
const entries = Object.entries(properties);
|
|
3208
|
+
if (entries.length === 0) return require_MarkdownSurfaces.isRecord(schema.additionalProperties) ? `Record<string, ${compactType(schema.additionalProperties, depth + 1)}>` : "object";
|
|
3209
|
+
if (depth >= MAX_OBJECT_DEPTH) return "object";
|
|
3210
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
3211
|
+
return `{ ${entries.map(([key, value]) => {
|
|
3212
|
+
const type = require_MarkdownSurfaces.isRecord(value) ? compactType(value, depth + 1) : "unknown";
|
|
3213
|
+
return `${key}${required.includes(key) ? "" : "?"}: ${type}`;
|
|
3214
|
+
}).join("; ")} }`;
|
|
3215
|
+
}
|
|
3216
|
+
/** A schema as its type, with its description after `//`. */
|
|
3217
|
+
function describedType(schema, depth) {
|
|
3218
|
+
const type = compactType(schema, depth);
|
|
3219
|
+
return typeof schema.description === "string" ? `${type} // ${schema.description}` : type;
|
|
3220
|
+
}
|
|
3221
|
+
/** The props of a component: `{ "label": "string", "size?": "..." }`. */
|
|
3222
|
+
function compactProps(schema) {
|
|
3223
|
+
const properties = require_MarkdownSurfaces.isRecord(schema.properties) ? schema.properties : {};
|
|
3224
|
+
const required = Array.isArray(schema.required) ? schema.required : [];
|
|
3225
|
+
const props = {};
|
|
3226
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
3227
|
+
if (!require_MarkdownSurfaces.isRecord(value)) continue;
|
|
3228
|
+
const name = required.includes(key) ? key : `${key}?`;
|
|
3229
|
+
props[name] = describedType(value, 1);
|
|
3230
|
+
}
|
|
3231
|
+
return props;
|
|
3232
|
+
}
|
|
3233
|
+
/**
|
|
3234
|
+
* The prop set worth listing once. Candidates are (key, type) pairs that at
|
|
3235
|
+
* least {@link COMMON_PROP_MIN_COMPONENTS} components carry verbatim. The
|
|
3236
|
+
* candidate subset of each component is a possible common set, scored by
|
|
3237
|
+
* the characters it saves (set size times the components that contain all
|
|
3238
|
+
* of it). `undefined` when no set is shared by enough components.
|
|
3239
|
+
*/
|
|
3240
|
+
function findCommonProps(propsList) {
|
|
3241
|
+
const pairKey = (key, type) => `${key}\u0000${type}`;
|
|
3242
|
+
const counts = /* @__PURE__ */ new Map();
|
|
3243
|
+
for (const props of propsList) for (const [key, type] of Object.entries(props)) {
|
|
3244
|
+
const id = pairKey(key, type);
|
|
3245
|
+
counts.set(id, (counts.get(id) ?? 0) + 1);
|
|
3246
|
+
}
|
|
3247
|
+
let best;
|
|
3248
|
+
let bestScore = 0;
|
|
3249
|
+
const seen = /* @__PURE__ */ new Set();
|
|
3250
|
+
for (const props of propsList) {
|
|
3251
|
+
const subset = Object.entries(props).filter(([key, type]) => (counts.get(pairKey(key, type)) ?? 0) >= COMMON_PROP_MIN_COMPONENTS);
|
|
3252
|
+
if (subset.length < 2) continue;
|
|
3253
|
+
const signature = subset.map(([key, type]) => pairKey(key, type)).join("\n");
|
|
3254
|
+
if (seen.has(signature)) continue;
|
|
3255
|
+
seen.add(signature);
|
|
3256
|
+
const members = propsList.filter((other) => subset.every(([key, type]) => other[key] === type)).length;
|
|
3257
|
+
if (members < COMMON_PROP_MIN_COMPONENTS) continue;
|
|
3258
|
+
const score = subset.reduce((total, [key, type]) => total + key.length + type.length, 0) * (members - 1);
|
|
3259
|
+
if (score > bestScore) {
|
|
3260
|
+
bestScore = score;
|
|
3261
|
+
best = Object.fromEntries(subset);
|
|
3262
|
+
}
|
|
3263
|
+
}
|
|
3264
|
+
return best;
|
|
3265
|
+
}
|
|
3266
|
+
/**
|
|
3267
|
+
* The component schema of the markdown transport, from the per-run
|
|
3268
|
+
* manifest. It is smaller than the manifest: each prop is one short type,
|
|
3269
|
+
* and the props that many components share verbatim (the layout props of
|
|
3270
|
+
* the containers) are listed once in `commonProps`; a component that takes
|
|
3271
|
+
* them is flagged `includesCommonProps`.
|
|
3272
|
+
* It has the catalog id, the targets with their descriptions and their
|
|
3273
|
+
* component lists, the functions with their parameters, the components
|
|
3274
|
+
* with their props, events and slots, and the surfaces of the thread. A surface lists the
|
|
3275
|
+
* values that the user set and the operations that the client dropped.
|
|
3276
|
+
*
|
|
3277
|
+
* @param manifest - The manifest from `buildGenerativeUIManifest`.
|
|
3278
|
+
* @returns A JSON-ready object.
|
|
3279
|
+
*
|
|
3280
|
+
* @example
|
|
3281
|
+
* ```ts
|
|
3282
|
+
* const value = JSON.stringify(
|
|
3283
|
+
* buildCompactGenerativeUISchema(buildGenerativeUIManifest(runtime, threadId)),
|
|
3284
|
+
* );
|
|
3285
|
+
* ```
|
|
3286
|
+
*/
|
|
3287
|
+
function buildCompactGenerativeUISchema(manifest) {
|
|
3288
|
+
const components = {};
|
|
3289
|
+
for (const [name, component] of Object.entries(manifest.components)) {
|
|
3290
|
+
const events = Object.entries(component.events ?? {}).map(([event, definition]) => [event, definition.description ?? compactType(definition.parameters, 0)]);
|
|
3291
|
+
components[name] = {
|
|
3292
|
+
...component.description ? { description: component.description } : {},
|
|
3293
|
+
props: compactProps(component.props),
|
|
3294
|
+
...events.length > 0 ? { events: Object.fromEntries(events) } : {},
|
|
3295
|
+
...component.slots ? { slots: component.slots } : {}
|
|
3296
|
+
};
|
|
3297
|
+
}
|
|
3298
|
+
const common = findCommonProps(Object.values(components).map((component) => component.props));
|
|
3299
|
+
if (common) {
|
|
3300
|
+
const commonKeys = Object.keys(common);
|
|
3301
|
+
for (const component of Object.values(components)) {
|
|
3302
|
+
if (!commonKeys.every((key) => component.props[key] === common[key])) continue;
|
|
3303
|
+
component.includesCommonProps = true;
|
|
3304
|
+
component.props = Object.fromEntries(Object.entries(component.props).filter(([key]) => !(key in common)));
|
|
3305
|
+
}
|
|
3306
|
+
}
|
|
3307
|
+
const functions = Object.fromEntries(Object.entries(manifest.functions).map(([name, fn]) => {
|
|
3308
|
+
const signature = fn.parameters.description;
|
|
3309
|
+
const hasSignature = typeof signature === "string" && signature.startsWith("{") && Object.keys(fn.parameters).length === 2;
|
|
3310
|
+
const callers = (0, _copilotkit_shared.functionCallers)(fn);
|
|
3311
|
+
return [name, {
|
|
3312
|
+
...fn.description ? { description: fn.description } : {},
|
|
3313
|
+
parameters: hasSignature ? signature : compactType(fn.parameters, 0),
|
|
3314
|
+
...callers.agent && _copilotkit_shared.GENERATIVE_UI_AGENT_FUNCTION_CALLS ? { callers: callers.renderer ? "UI or agent" : "agent only" } : {}
|
|
3315
|
+
}];
|
|
3316
|
+
}));
|
|
3317
|
+
return {
|
|
3318
|
+
catalogId: manifest.catalogId,
|
|
3319
|
+
targets: manifest.targets,
|
|
3320
|
+
functions,
|
|
3321
|
+
...common ? { commonProps: common } : {},
|
|
3322
|
+
components,
|
|
3323
|
+
surfaces: manifest.surfaces
|
|
3324
|
+
};
|
|
3325
|
+
}
|
|
3326
|
+
/**
|
|
3327
|
+
* Registers the two context entries of the markdown transport: the compact
|
|
3328
|
+
* component schema and the fence guideline. Both go only to `agentIds`.
|
|
3329
|
+
*
|
|
3330
|
+
* The schema is built again at each run start and when a
|
|
3331
|
+
* `<GenerativeUISurface>` mounts, unmounts, or changes its description or
|
|
3332
|
+
* its components, so its targets, functions, and surfaces stay current. The surfaces are those of the running thread.
|
|
3333
|
+
*
|
|
3334
|
+
* @param copilotkit - The CopilotKit core of the provider.
|
|
3335
|
+
* @param runtime - The generative UI runtime parts, or null without one.
|
|
3336
|
+
* @param options - `enabled` and `agentIds`.
|
|
3337
|
+
*
|
|
3338
|
+
* @example
|
|
3339
|
+
* ```ts
|
|
3340
|
+
* useGenerativeUIMarkdownContext(copilotkit, core, {
|
|
3341
|
+
* enabled: config?.transport === "markdown" && config.sendContext !== false,
|
|
3342
|
+
* agentIds: config?.agentIds,
|
|
3343
|
+
* });
|
|
3344
|
+
* ```
|
|
3345
|
+
*/
|
|
3346
|
+
function useGenerativeUIMarkdownContext(copilotkit, runtime, options) {
|
|
3347
|
+
const { enabled, agentIds } = options;
|
|
3348
|
+
const agentIdsKey = agentIds === void 0 ? "" : JSON.stringify(agentIds);
|
|
3349
|
+
(0, react.useEffect)(() => {
|
|
3350
|
+
if (!runtime || !enabled) return;
|
|
3351
|
+
const scopedAgentIds = agentIdsKey ? JSON.parse(agentIdsKey) : void 0;
|
|
3352
|
+
const scope = scopedAgentIds ? { agentIds: scopedAgentIds } : {};
|
|
3353
|
+
let guidelineId;
|
|
3354
|
+
let guidelineValue;
|
|
3355
|
+
let schemaId;
|
|
3356
|
+
let schemaValue;
|
|
3357
|
+
const refreshSchema = (threadId) => {
|
|
3358
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3359
|
+
const guideline = (0, _copilotkit_shared.buildGenerativeUIMarkdownGuidelines)((0, _copilotkit_shared.generativeUIGuideFeatures)(manifest));
|
|
3360
|
+
if (guideline !== guidelineValue) {
|
|
3361
|
+
if (guidelineId !== void 0) copilotkit.removeContext(guidelineId);
|
|
3362
|
+
guidelineValue = guideline;
|
|
3363
|
+
guidelineId = copilotkit.addContext({
|
|
3364
|
+
description: _copilotkit_shared.GENERATIVE_UI_MARKDOWN_GUIDELINES_DESCRIPTION,
|
|
3365
|
+
value: guideline,
|
|
3366
|
+
...scope
|
|
3367
|
+
});
|
|
3368
|
+
}
|
|
3369
|
+
const value = JSON.stringify(buildCompactGenerativeUISchema(manifest));
|
|
3370
|
+
if (value === schemaValue) return;
|
|
3371
|
+
if (schemaId !== void 0) copilotkit.removeContext(schemaId);
|
|
3372
|
+
schemaValue = value;
|
|
3373
|
+
schemaId = copilotkit.addContext({
|
|
3374
|
+
description: _copilotkit_shared.GENERATIVE_UI_MARKDOWN_SCHEMA_CONTEXT_DESCRIPTION,
|
|
3375
|
+
value,
|
|
3376
|
+
...scope
|
|
3377
|
+
});
|
|
3378
|
+
};
|
|
3379
|
+
refreshSchema(runtime.manager.getActiveThread());
|
|
3380
|
+
let targetsKey = JSON.stringify(runtime.manager.getMountedTargets());
|
|
3381
|
+
const unsubscribeManager = runtime.manager.subscribe(() => {
|
|
3382
|
+
const nextKey = JSON.stringify(runtime.manager.getMountedTargets());
|
|
3383
|
+
if (nextKey === targetsKey) return;
|
|
3384
|
+
targetsKey = nextKey;
|
|
3385
|
+
refreshSchema(runtime.manager.getActiveThread());
|
|
3386
|
+
});
|
|
3387
|
+
const subscription = copilotkit.subscribe({ onAgentRunStarted: ({ agent }) => refreshSchema(agent.threadId) });
|
|
3388
|
+
return () => {
|
|
3389
|
+
subscription.unsubscribe();
|
|
3390
|
+
unsubscribeManager();
|
|
3391
|
+
if (guidelineId !== void 0) copilotkit.removeContext(guidelineId);
|
|
3392
|
+
if (schemaId !== void 0) copilotkit.removeContext(schemaId);
|
|
3393
|
+
};
|
|
3394
|
+
}, [
|
|
3395
|
+
copilotkit,
|
|
3396
|
+
runtime,
|
|
3397
|
+
enabled,
|
|
3398
|
+
agentIdsKey
|
|
3399
|
+
]);
|
|
3400
|
+
}
|
|
3401
|
+
|
|
3402
|
+
//#endregion
|
|
3403
|
+
//#region src/v2/generative-ui/debug-source.ts
|
|
3404
|
+
/**
|
|
3405
|
+
* What a run of `threadId` sends: its envelope, and the text that goes into
|
|
3406
|
+
* the prompt of the model because of it.
|
|
3407
|
+
*
|
|
3408
|
+
* - Tool transport: the runtime adds the `render_ui` guide. It builds it
|
|
3409
|
+
* from the envelope with `buildGenerativeUIPrompt`, as done here.
|
|
3410
|
+
* - Markdown transport: the provider sends the guideline and the compact
|
|
3411
|
+
* schema as context entries. With `sendContext: false`, the backend builds
|
|
3412
|
+
* its own prompt, usually from the `instructions` of the envelope.
|
|
3413
|
+
*/
|
|
3414
|
+
function describeGenerativeUIRun(runtime, threadId, options) {
|
|
3415
|
+
const envelope = buildGenerativeUIEnvelope(runtime, threadId, options);
|
|
3416
|
+
if (options.transport === "tool") return {
|
|
3417
|
+
envelope,
|
|
3418
|
+
prompt: [{
|
|
3419
|
+
title: "render_ui guide",
|
|
3420
|
+
source: "runtime",
|
|
3421
|
+
text: (0, _copilotkit_shared.buildGenerativeUIPrompt)((0, _copilotkit_shared.envelopeToManifest)(envelope))
|
|
3422
|
+
}]
|
|
3423
|
+
};
|
|
3424
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3425
|
+
if (!options.contextSent) return {
|
|
3426
|
+
envelope,
|
|
3427
|
+
prompt: [{
|
|
3428
|
+
title: "Envelope instructions",
|
|
3429
|
+
source: "backend",
|
|
3430
|
+
text: (0, _copilotkit_shared.envelopeToManifest)(envelope).instructions ?? ""
|
|
3431
|
+
}]
|
|
3432
|
+
};
|
|
3433
|
+
const guideline = (0, _copilotkit_shared.buildGenerativeUIMarkdownGuidelines)((0, _copilotkit_shared.generativeUIGuideFeatures)(manifest));
|
|
3434
|
+
const schema = JSON.stringify(buildCompactGenerativeUISchema(manifest));
|
|
3435
|
+
return {
|
|
3436
|
+
envelope,
|
|
3437
|
+
prompt: [{
|
|
3438
|
+
title: "Markdown guideline",
|
|
3439
|
+
source: "context",
|
|
3440
|
+
text: guideline
|
|
3441
|
+
}, {
|
|
3442
|
+
title: "Component schema",
|
|
3443
|
+
source: "context",
|
|
3444
|
+
text: schema
|
|
3445
|
+
}]
|
|
3446
|
+
};
|
|
3447
|
+
}
|
|
3448
|
+
/** The declared functions, with the JSON Schema of their parameters. */
|
|
3449
|
+
function debugFunctions(runtime) {
|
|
3450
|
+
const functions = {};
|
|
3451
|
+
for (const [name, declared] of runtime.ui.functions) {
|
|
3452
|
+
let parameters = {};
|
|
3453
|
+
try {
|
|
3454
|
+
parameters = require_MarkdownSurfaces.toJsonSchema(declared.parameters);
|
|
3455
|
+
} catch {}
|
|
3456
|
+
functions[name] = {
|
|
3457
|
+
...declared.description ? { description: declared.description } : {},
|
|
3458
|
+
parameters,
|
|
3459
|
+
handlers: runtime.dispatcher.handlerCount(name)
|
|
3460
|
+
};
|
|
3461
|
+
}
|
|
3462
|
+
return functions;
|
|
3463
|
+
}
|
|
3464
|
+
/**
|
|
3465
|
+
* The debug source that the provider gives core for the inspector. It builds
|
|
3466
|
+
* a snapshot only when the inspector reads one.
|
|
3467
|
+
*
|
|
3468
|
+
* @param runtime - The generative UI parts of the provider.
|
|
3469
|
+
* @param getOptions - The envelope options and agent ids of the current config.
|
|
3470
|
+
* @returns The source, and `recordRun` for each run start.
|
|
3471
|
+
*/
|
|
3472
|
+
function createGenerativeUIDebugSource(runtime, getOptions) {
|
|
3473
|
+
const listeners = /* @__PURE__ */ new Set();
|
|
3474
|
+
let lastRun;
|
|
3475
|
+
const notify = () => {
|
|
3476
|
+
for (const listener of [...listeners]) listener();
|
|
3477
|
+
};
|
|
3478
|
+
return {
|
|
3479
|
+
source: {
|
|
3480
|
+
getSnapshot() {
|
|
3481
|
+
const { options, agentIds } = getOptions();
|
|
3482
|
+
const threadId = runtime.manager.getActiveThread();
|
|
3483
|
+
const manifest = buildGenerativeUIManifest(runtime, threadId);
|
|
3484
|
+
return {
|
|
3485
|
+
catalogId: runtime.ui.id,
|
|
3486
|
+
transport: options.transport,
|
|
3487
|
+
...agentIds ? { agentIds } : {},
|
|
3488
|
+
components: runtime.ui.manifestComponents,
|
|
3489
|
+
componentCatalogs: Object.fromEntries(require_MarkdownSurfaces.componentCatalogIds(runtime.ui)),
|
|
3490
|
+
functions: debugFunctions(runtime),
|
|
3491
|
+
state: { ...runtime.manager.getState() },
|
|
3492
|
+
targets: manifest.targets,
|
|
3493
|
+
activeThreadId: threadId,
|
|
3494
|
+
surfaces: runtime.manager.debugSurfaces(),
|
|
3495
|
+
lastRun,
|
|
3496
|
+
nextRun: {
|
|
3497
|
+
agentId: void 0,
|
|
3498
|
+
threadId,
|
|
3499
|
+
...describeGenerativeUIRun(runtime, threadId, options)
|
|
3500
|
+
}
|
|
3501
|
+
};
|
|
3502
|
+
},
|
|
3503
|
+
subscribe(listener) {
|
|
3504
|
+
listeners.add(listener);
|
|
3505
|
+
const unsubscribe = runtime.manager.subscribe(listener);
|
|
3506
|
+
return () => {
|
|
3507
|
+
listeners.delete(listener);
|
|
3508
|
+
unsubscribe();
|
|
3509
|
+
};
|
|
3510
|
+
}
|
|
3511
|
+
},
|
|
3512
|
+
recordRun(run) {
|
|
3513
|
+
lastRun = run;
|
|
3514
|
+
notify();
|
|
3515
|
+
}
|
|
3516
|
+
};
|
|
3517
|
+
}
|
|
3518
|
+
|
|
3519
|
+
//#endregion
|
|
3520
|
+
//#region src/v2/generative-ui/dispatcher.ts
|
|
3521
|
+
const messageOf = (error) => error instanceof Error ? error.message : String(error);
|
|
3522
|
+
/**
|
|
3523
|
+
* Creates the registry of functions that generated UI may call.
|
|
3524
|
+
*
|
|
3525
|
+
* A function is callable when it is declared in `getDeclared()` and exactly
|
|
3526
|
+
* one handler is mounted for it with `register`. Names are resolved at call
|
|
3527
|
+
* time and fail closed. Nothing is sent to the agent.
|
|
3528
|
+
* Neither `invoke` nor `listExposed` throws.
|
|
3529
|
+
*
|
|
3530
|
+
* @param options.getDeclared - Returns the declared functions.
|
|
3531
|
+
* @param options.onError - Gets each failed call.
|
|
3532
|
+
*
|
|
3533
|
+
* @example
|
|
3534
|
+
* ```ts
|
|
3535
|
+
* const dispatcher = createGenerativeUIDispatcher({
|
|
3536
|
+
* getDeclared: () => new Map(Object.entries(ui.functions)),
|
|
3537
|
+
* });
|
|
3538
|
+
* const unregister = dispatcher.register("addToCart", handlerRef);
|
|
3539
|
+
* await dispatcher.invoke("addToCart", { productId: "p1" }, origin);
|
|
3540
|
+
* unregister();
|
|
3541
|
+
* ```
|
|
3542
|
+
*/
|
|
3543
|
+
/**
|
|
3544
|
+
* True while the browser counts the current task as user-activated (a
|
|
3545
|
+
* click, a key press). Where the API is missing (older browsers, test
|
|
3546
|
+
* environments), the gesture is assumed.
|
|
3547
|
+
*/
|
|
3548
|
+
function hasUserActivation() {
|
|
3549
|
+
if (typeof navigator === "undefined") return true;
|
|
3550
|
+
const activation = navigator.userActivation;
|
|
3551
|
+
return activation === void 0 || activation.isActive;
|
|
3552
|
+
}
|
|
3553
|
+
/**
|
|
3554
|
+
* The permissions of a declared function as the manifest states them: the
|
|
3555
|
+
* callers always written out, so a reader needs no default.
|
|
3556
|
+
*/
|
|
3557
|
+
function permissionsOf(fn) {
|
|
3558
|
+
const callers = (0, _copilotkit_shared.functionCallers)(fn);
|
|
3559
|
+
return {
|
|
3560
|
+
allowedCallers: callers.renderer && callers.agent ? "rendererOrAgent" : callers.agent ? "agentOnly" : "rendererOnly",
|
|
3561
|
+
...fn.requiresUserActivation ? { requiresUserActivation: true } : {}
|
|
3562
|
+
};
|
|
3563
|
+
}
|
|
3564
|
+
function createGenerativeUIDispatcher(options) {
|
|
3565
|
+
const handlers = /* @__PURE__ */ new Map();
|
|
3566
|
+
const resolveUnchecked = (name) => {
|
|
3567
|
+
const declared = options.getDeclared().get(name);
|
|
3568
|
+
if (!declared) return {
|
|
3569
|
+
ok: false,
|
|
3570
|
+
error: new require_MarkdownSurfaces.GenerativeUIError("function_not_found", `No generative UI function named "${name}" is declared in createGenerativeUI({ functions })`)
|
|
3571
|
+
};
|
|
3572
|
+
const mounted = [...handlers.get(name) ?? []];
|
|
3573
|
+
const [ref] = mounted;
|
|
3574
|
+
if (!ref) return {
|
|
3575
|
+
ok: false,
|
|
3576
|
+
error: new require_MarkdownSurfaces.GenerativeUIError("function_not_found", `"${name}" is declared, but no useGenerativeUIFunction handler is mounted for it`)
|
|
3577
|
+
};
|
|
3578
|
+
if (mounted.length > 1) return {
|
|
3579
|
+
ok: false,
|
|
3580
|
+
error: new require_MarkdownSurfaces.GenerativeUIError("function_conflict", `"${name}" has ${mounted.length} useGenerativeUIFunction handlers mounted. Mount exactly one.`)
|
|
3581
|
+
};
|
|
3582
|
+
return {
|
|
3583
|
+
ok: true,
|
|
3584
|
+
declared,
|
|
3585
|
+
ref
|
|
3586
|
+
};
|
|
3587
|
+
};
|
|
3588
|
+
const isDeclared = (name) => {
|
|
3589
|
+
try {
|
|
3590
|
+
return options.getDeclared().has(name);
|
|
3591
|
+
} catch {
|
|
3592
|
+
return false;
|
|
3593
|
+
}
|
|
3594
|
+
};
|
|
3595
|
+
const resolve = (name) => {
|
|
3596
|
+
try {
|
|
3597
|
+
return resolveUnchecked(name);
|
|
3598
|
+
} catch (error) {
|
|
3599
|
+
return {
|
|
3600
|
+
ok: false,
|
|
3601
|
+
error: new require_MarkdownSurfaces.GenerativeUIError("handler_failed", `"${name}" could not be resolved: ${messageOf(error)}`)
|
|
3602
|
+
};
|
|
3603
|
+
}
|
|
3604
|
+
};
|
|
3605
|
+
const validateArgs = async (name, schema, args) => {
|
|
3606
|
+
try {
|
|
3607
|
+
const validation = await schema["~standard"].validate(args);
|
|
3608
|
+
if (!validation.issues) return {
|
|
3609
|
+
ok: true,
|
|
3610
|
+
value: validation.value
|
|
3611
|
+
};
|
|
3612
|
+
return {
|
|
3613
|
+
ok: false,
|
|
3614
|
+
error: new require_MarkdownSurfaces.GenerativeUIError("invalid_arguments", `Invalid arguments for "${name}": ${validation.issues.map((i) => `${(i.path ?? []).map((p) => typeof p === "object" ? p.key : p).join(".") || "args"}: ${i.message}`).join("; ")}`)
|
|
3615
|
+
};
|
|
3616
|
+
} catch (error) {
|
|
3617
|
+
return {
|
|
3618
|
+
ok: false,
|
|
3619
|
+
error: new require_MarkdownSurfaces.GenerativeUIError("invalid_arguments", `Invalid arguments for "${name}": ${messageOf(error)}`)
|
|
3620
|
+
};
|
|
3621
|
+
}
|
|
3622
|
+
};
|
|
3623
|
+
const failWith = (name, origin, error) => {
|
|
3624
|
+
try {
|
|
3625
|
+
options.onError?.({
|
|
3626
|
+
name,
|
|
3627
|
+
origin,
|
|
3628
|
+
error
|
|
3629
|
+
});
|
|
3630
|
+
} catch {}
|
|
3631
|
+
return {
|
|
3632
|
+
ok: false,
|
|
3633
|
+
error
|
|
3634
|
+
};
|
|
3635
|
+
};
|
|
3636
|
+
/**
|
|
3637
|
+
* Why `origin` may not call a function with these permissions now, as an
|
|
3638
|
+
* error, or `undefined` when it may. The agent is refused what is for the
|
|
3639
|
+
* renderer; a component is refused what is for the agent, and a gesture
|
|
3640
|
+
* function when the browser counts no user activation.
|
|
3641
|
+
*/
|
|
3642
|
+
const callerError = (name, fn, origin) => {
|
|
3643
|
+
const isComponent = "componentId" in origin;
|
|
3644
|
+
if (!isComponent && !_copilotkit_shared.GENERATIVE_UI_AGENT_FUNCTION_CALLS) return new require_MarkdownSurfaces.GenerativeUIError("invalid_function_call", _copilotkit_shared.GENERATIVE_UI_AGENT_FUNCTION_CALLS_OFF_REASON);
|
|
3645
|
+
const problem = (0, _copilotkit_shared.callerProblem)(name, fn, isComponent ? "renderer" : "agent");
|
|
3646
|
+
if (problem !== void 0) return new require_MarkdownSurfaces.GenerativeUIError("invalid_function_call", problem);
|
|
3647
|
+
if (isComponent && fn.requiresUserActivation && !hasUserActivation()) return new require_MarkdownSurfaces.GenerativeUIError("invalid_function_call", `function "${name}" runs only from a user gesture; this event was not one`);
|
|
3648
|
+
};
|
|
3649
|
+
/**
|
|
3650
|
+
* Runs a basic function of the A2UI catalog. They are value functions of
|
|
3651
|
+
* the renderer: the agent cannot call them, and one that needs a user
|
|
3652
|
+
* gesture runs only from an event binding.
|
|
3653
|
+
*/
|
|
3654
|
+
const invokeBasic = (name, args, origin) => {
|
|
3655
|
+
const refused = callerError(name, _copilotkit_shared.GENERATIVE_UI_FUNCTIONS[name], origin);
|
|
3656
|
+
if (refused) return failWith(name, origin, refused);
|
|
3657
|
+
if (args !== void 0 && !(typeof args === "object" && args !== null && !Array.isArray(args))) return failWith(name, origin, new require_MarkdownSurfaces.GenerativeUIError("invalid_arguments", `Invalid arguments for "${name}": args must be an object`));
|
|
3658
|
+
try {
|
|
3659
|
+
return {
|
|
3660
|
+
ok: true,
|
|
3661
|
+
result: require_MarkdownSurfaces.BASIC_FUNCTIONS[name](args ?? {})
|
|
3662
|
+
};
|
|
3663
|
+
} catch (error) {
|
|
3664
|
+
return failWith(name, origin, new require_MarkdownSurfaces.GenerativeUIError(error instanceof require_MarkdownSurfaces.ExpressionError ? "invalid_arguments" : "handler_failed", `"${name}" failed: ${messageOf(error)}`));
|
|
3665
|
+
}
|
|
3666
|
+
};
|
|
3667
|
+
return {
|
|
3668
|
+
async invoke(name, args, origin) {
|
|
3669
|
+
const resolved = resolve(name);
|
|
3670
|
+
if (!resolved.ok && resolved.error.code === "function_not_found" && !isDeclared(name) && Object.prototype.hasOwnProperty.call(require_MarkdownSurfaces.BASIC_FUNCTIONS, name)) return invokeBasic(name, args, origin);
|
|
3671
|
+
if (!resolved.ok) return failWith(name, origin, resolved.error);
|
|
3672
|
+
const refused = callerError(name, resolved.declared, origin);
|
|
3673
|
+
if (refused) return failWith(name, origin, refused);
|
|
3674
|
+
const validated = await validateArgs(name, resolved.declared.parameters, args ?? {});
|
|
3675
|
+
if (!validated.ok) return failWith(name, origin, validated.error);
|
|
3676
|
+
try {
|
|
3677
|
+
return {
|
|
3678
|
+
ok: true,
|
|
3679
|
+
result: await resolved.ref.current(validated.value)
|
|
3680
|
+
};
|
|
3681
|
+
} catch (error) {
|
|
3682
|
+
return failWith(name, origin, new require_MarkdownSurfaces.GenerativeUIError("handler_failed", `"${name}" failed: ${messageOf(error)}`));
|
|
3683
|
+
}
|
|
3684
|
+
},
|
|
3685
|
+
listExposed() {
|
|
3686
|
+
let names;
|
|
3687
|
+
try {
|
|
3688
|
+
names = [...options.getDeclared().keys()];
|
|
3689
|
+
} catch {
|
|
3690
|
+
return {};
|
|
3691
|
+
}
|
|
3692
|
+
const listed = {};
|
|
3693
|
+
for (const name of names) {
|
|
3694
|
+
const resolved = resolve(name);
|
|
3695
|
+
if (!resolved.ok) continue;
|
|
3696
|
+
if (!(0, _copilotkit_shared.functionCallers)(resolved.declared).renderer && !_copilotkit_shared.GENERATIVE_UI_AGENT_FUNCTION_CALLS) continue;
|
|
3697
|
+
const { description, parameters, returnType } = resolved.declared;
|
|
3698
|
+
try {
|
|
3699
|
+
listed[name] = {
|
|
3700
|
+
...description ? { description } : {},
|
|
3701
|
+
parameters: require_MarkdownSurfaces.toJsonSchema(parameters),
|
|
3702
|
+
...returnType ? { returnType } : {},
|
|
3703
|
+
...permissionsOf(resolved.declared)
|
|
3704
|
+
};
|
|
3705
|
+
} catch {}
|
|
3706
|
+
}
|
|
3707
|
+
return listed;
|
|
3708
|
+
},
|
|
3709
|
+
register(name, ref) {
|
|
3710
|
+
const mounted = handlers.get(name) ?? /* @__PURE__ */ new Set();
|
|
3711
|
+
mounted.add(ref);
|
|
3712
|
+
handlers.set(name, mounted);
|
|
3713
|
+
return () => {
|
|
3714
|
+
mounted.delete(ref);
|
|
3715
|
+
};
|
|
3716
|
+
},
|
|
3717
|
+
handlerCount: (name) => handlers.get(name)?.size ?? 0
|
|
3718
|
+
};
|
|
3719
|
+
}
|
|
3720
|
+
|
|
3721
|
+
//#endregion
|
|
3722
|
+
//#region src/v2/generative-ui/surface-manager.ts
|
|
3723
|
+
function surfaceKey(threadId, surfaceId) {
|
|
3724
|
+
return `${threadId}::${surfaceId}`;
|
|
3725
|
+
}
|
|
3726
|
+
let creationCounter = 0;
|
|
3727
|
+
const FORBIDDEN_SEGMENTS = new Set([
|
|
3728
|
+
"__proto__",
|
|
3729
|
+
"constructor",
|
|
3730
|
+
"prototype"
|
|
3731
|
+
]);
|
|
3732
|
+
/** "/a/b/" to "/a/b". The root stays "/". */
|
|
3733
|
+
function normalizePath(path) {
|
|
3734
|
+
return (path.length > 1 && path.endsWith("/") ? path.slice(0, -1) : path) || "/";
|
|
3735
|
+
}
|
|
3736
|
+
/** True when `path` is `ancestor` or below it. */
|
|
3737
|
+
function isAtOrBelow(path, ancestor) {
|
|
3738
|
+
if (ancestor === "/") return true;
|
|
3739
|
+
return path === ancestor || path.startsWith(`${ancestor}/`);
|
|
3740
|
+
}
|
|
3741
|
+
/**
|
|
3742
|
+
* Rejections as `"operation <index>: <reason>"` lines, cut to the size that
|
|
3743
|
+
* the envelope reader accepts.
|
|
3744
|
+
*/
|
|
3745
|
+
function summarizeRejections(rejections) {
|
|
3746
|
+
return rejections.slice(0, _copilotkit_shared.GENERATIVE_UI_MAX_SUMMARY_REJECTIONS).map(({ index, reason }) => `operation ${index}: ${reason}`.slice(0, _copilotkit_shared.GENERATIVE_UI_MAX_REJECTION_LENGTH));
|
|
3747
|
+
}
|
|
3748
|
+
/**
|
|
3749
|
+
* Framework-agnostic store of generated surfaces. One web_core SurfaceModel per
|
|
3750
|
+
* (threadId, surfaceId), shared by every mount. Applies only newly committed
|
|
3751
|
+
* operations, validates each before applying it, and owns app state and the
|
|
3752
|
+
* data model paths that the user wrote, so agent updates cannot overwrite
|
|
3753
|
+
* them. App state never goes into a surface's data model. Selectors read it
|
|
3754
|
+
* with `getState()`.
|
|
3755
|
+
*/
|
|
3756
|
+
var GenerativeUISurfaceManager = class {
|
|
3757
|
+
constructor(ui, options = {}) {
|
|
3758
|
+
this.ui = ui;
|
|
3759
|
+
this.options = options;
|
|
3760
|
+
this.surfaces = /* @__PURE__ */ new Map();
|
|
3761
|
+
this.bookkeeping = /* @__PURE__ */ new Map();
|
|
3762
|
+
this.listeners = /* @__PURE__ */ new Set();
|
|
3763
|
+
this.targets = /* @__PURE__ */ new Map();
|
|
3764
|
+
this.state = {};
|
|
3765
|
+
this.owned = /* @__PURE__ */ new Map();
|
|
3766
|
+
this.deletedKeys = /* @__PURE__ */ new Set();
|
|
3767
|
+
this.linked = /* @__PURE__ */ new Map();
|
|
3768
|
+
this.version = 0;
|
|
3769
|
+
this.subscribe = (listener) => {
|
|
3770
|
+
this.listeners.add(listener);
|
|
3771
|
+
return () => {
|
|
3772
|
+
this.listeners.delete(listener);
|
|
3773
|
+
};
|
|
3774
|
+
};
|
|
3775
|
+
this.getVersion = () => this.version;
|
|
3776
|
+
this.getState = () => this.state;
|
|
3777
|
+
this.webCoreCatalog = new _a2ui_web_core_v0_9.Catalog(ui.id, [...ui.components.keys()].map((name) => ({
|
|
3778
|
+
name,
|
|
3779
|
+
schema: zod.z.any()
|
|
3780
|
+
})), []);
|
|
3781
|
+
}
|
|
3782
|
+
notify() {
|
|
3783
|
+
this.version++;
|
|
3784
|
+
for (const listener of [...this.listeners]) listener();
|
|
3785
|
+
}
|
|
3786
|
+
setActiveThread(threadId) {
|
|
3787
|
+
if (threadId === this.activeThreadId) return;
|
|
3788
|
+
this.activeThreadId = threadId;
|
|
3789
|
+
this.notify();
|
|
3790
|
+
}
|
|
3791
|
+
getActiveThread() {
|
|
3792
|
+
return this.activeThreadId;
|
|
3793
|
+
}
|
|
3794
|
+
ingest(threadId, agentId, content) {
|
|
3795
|
+
const key = surfaceKey(threadId, content.surfaceId);
|
|
3796
|
+
const operations = content.operations ?? [];
|
|
3797
|
+
let surface = this.surfaces.get(key);
|
|
3798
|
+
let book = this.bookkeeping.get(key);
|
|
3799
|
+
let changed = false;
|
|
3800
|
+
if (surface && book && !this.extendsApplied(book, operations)) {
|
|
3801
|
+
this.disposeSurface(key);
|
|
3802
|
+
surface = void 0;
|
|
3803
|
+
book = void 0;
|
|
3804
|
+
}
|
|
3805
|
+
if (!surface || !book) {
|
|
3806
|
+
surface = this.createSurface(key, threadId, agentId, content);
|
|
3807
|
+
this.restoreOwnedValues(surface);
|
|
3808
|
+
book = {
|
|
3809
|
+
appliedCount: 0,
|
|
3810
|
+
lastFingerprint: void 0
|
|
3811
|
+
};
|
|
3812
|
+
this.surfaces.set(key, surface);
|
|
3813
|
+
this.bookkeeping.set(key, book);
|
|
3814
|
+
changed = true;
|
|
3815
|
+
}
|
|
3816
|
+
const serverRejected = content.rejected ?? [];
|
|
3817
|
+
if (surface.clientRejected.length > 0 && (surface.status !== "streaming" && content.status === "streaming" || serverRejected.length < surface.serverRejected.length)) {
|
|
3818
|
+
surface.clientRejected = [];
|
|
3819
|
+
changed = true;
|
|
3820
|
+
}
|
|
3821
|
+
if (operations.length > 0) {
|
|
3822
|
+
const lastFingerprint = JSON.stringify(operations[operations.length - 1]);
|
|
3823
|
+
const isReplay = operations.some((op) => (0, _copilotkit_shared.getOperationKind)(op) === "deleteSurface");
|
|
3824
|
+
for (let index = book.appliedCount; index < operations.length; index++) {
|
|
3825
|
+
this.applyOperation(surface, operations[index], {
|
|
3826
|
+
index,
|
|
3827
|
+
isReplay
|
|
3828
|
+
});
|
|
3829
|
+
changed = true;
|
|
3830
|
+
}
|
|
3831
|
+
book.appliedCount = operations.length;
|
|
3832
|
+
surface.operations = operations;
|
|
3833
|
+
book.lastFingerprint = lastFingerprint;
|
|
3834
|
+
}
|
|
3835
|
+
if (surface.status !== content.status || surface.target !== content.target || surface.serverRejected.length !== serverRejected.length) {
|
|
3836
|
+
surface.status = content.status;
|
|
3837
|
+
surface.target = content.target;
|
|
3838
|
+
surface.serverRejected = serverRejected;
|
|
3839
|
+
changed = true;
|
|
3840
|
+
}
|
|
3841
|
+
if (changed) this.notify();
|
|
3842
|
+
}
|
|
3843
|
+
/** The surface of a `key` (see `surfaceKey`), unless it is deleted. */
|
|
3844
|
+
getSurfaceByKey(key) {
|
|
3845
|
+
const surface = this.surfaces.get(key);
|
|
3846
|
+
return surface && !surface.deleted ? surface : void 0;
|
|
3847
|
+
}
|
|
3848
|
+
getSurface(threadId, surfaceId) {
|
|
3849
|
+
const surface = this.surfaces.get(surfaceKey(threadId, surfaceId));
|
|
3850
|
+
return surface && !surface.deleted ? surface : void 0;
|
|
3851
|
+
}
|
|
3852
|
+
getSurfaceForTarget(target, threadId = this.activeThreadId) {
|
|
3853
|
+
if (!threadId) return void 0;
|
|
3854
|
+
let latest;
|
|
3855
|
+
for (const surface of this.surfaces.values()) {
|
|
3856
|
+
if (surface.threadId !== threadId || surface.target !== target || surface.deleted) continue;
|
|
3857
|
+
if (!latest || surface.createdAt > latest.createdAt) latest = surface;
|
|
3858
|
+
}
|
|
3859
|
+
return latest;
|
|
3860
|
+
}
|
|
3861
|
+
/**
|
|
3862
|
+
* A surface whose first createSurface was rejected, so the chat can show
|
|
3863
|
+
* the error where the surface would be. `undefined` for any other surface.
|
|
3864
|
+
*/
|
|
3865
|
+
getFailedSurface(threadId, surfaceId) {
|
|
3866
|
+
const surface = this.surfaces.get(surfaceKey(threadId, surfaceId));
|
|
3867
|
+
return surface?.failed ? surface : void 0;
|
|
3868
|
+
}
|
|
3869
|
+
/**
|
|
3870
|
+
* The surfaces of a thread, for the model. A surface with user-owned
|
|
3871
|
+
* values lists them in `dataModel`, so the model can read what the user
|
|
3872
|
+
* entered. A surface with dropped operations lists them in `rejected`, so
|
|
3873
|
+
* the model can fix them on the next run. A deleted surface, or one that
|
|
3874
|
+
* was never created, has a `status`, so the model knows that the id is
|
|
3875
|
+
* not a live surface.
|
|
3876
|
+
*/
|
|
3877
|
+
describeSurfaces(threadId) {
|
|
3878
|
+
const described = {};
|
|
3879
|
+
for (const surface of this.surfaces.values()) {
|
|
3880
|
+
if (surface.threadId !== threadId) continue;
|
|
3881
|
+
const owned = this.owned.get(surface.key);
|
|
3882
|
+
const rejections = [...surface.serverRejected, ...surface.clientRejected];
|
|
3883
|
+
const status = this.deletedKeys.has(surface.key) ? "deleted" : surface.failed ? "failed" : void 0;
|
|
3884
|
+
described[surface.surfaceId] = {
|
|
3885
|
+
target: surface.target,
|
|
3886
|
+
...owned && owned.size > 0 ? { dataModel: Object.fromEntries(owned) } : {},
|
|
3887
|
+
...rejections.length > 0 && status !== "deleted" ? { rejected: summarizeRejections(rejections) } : {},
|
|
3888
|
+
...status ? { status } : {}
|
|
3889
|
+
};
|
|
3890
|
+
}
|
|
3891
|
+
return described;
|
|
3892
|
+
}
|
|
3893
|
+
/** Every surface that is not deleted, oldest first, for the inspector. */
|
|
3894
|
+
debugSurfaces() {
|
|
3895
|
+
return [...this.surfaces.values()].filter((surface) => !surface.deleted).sort((a, b) => a.createdAt - b.createdAt).map((surface) => ({
|
|
3896
|
+
surfaceId: surface.surfaceId,
|
|
3897
|
+
threadId: surface.threadId,
|
|
3898
|
+
agentId: surface.agentId,
|
|
3899
|
+
target: surface.target,
|
|
3900
|
+
status: surface.status,
|
|
3901
|
+
operations: surface.operations,
|
|
3902
|
+
dataModel: surface.model.dataModel.get("/"),
|
|
3903
|
+
userValues: Object.fromEntries(this.owned.get(surface.key) ?? []),
|
|
3904
|
+
rejected: [...surface.serverRejected.map((r) => ({
|
|
3905
|
+
...r,
|
|
3906
|
+
source: "runtime"
|
|
3907
|
+
})), ...surface.clientRejected.map((r) => ({
|
|
3908
|
+
...r,
|
|
3909
|
+
source: "browser"
|
|
3910
|
+
}))]
|
|
3911
|
+
}));
|
|
3912
|
+
}
|
|
3913
|
+
/**
|
|
3914
|
+
* Marks a target as mounted. Returns the function that unmounts it. Calling
|
|
3915
|
+
* that function more than once has no effect.
|
|
3916
|
+
*
|
|
3917
|
+
* @param id - The target id.
|
|
3918
|
+
* @param options - The description and the allowed components of this mount.
|
|
3919
|
+
*/
|
|
3920
|
+
registerTarget(id, options = {}) {
|
|
3921
|
+
const registration = { ...options };
|
|
3922
|
+
const registrations = this.targets.get(id) ?? /* @__PURE__ */ new Set();
|
|
3923
|
+
registrations.add(registration);
|
|
3924
|
+
this.targets.set(id, registrations);
|
|
3925
|
+
this.notify();
|
|
3926
|
+
let released = false;
|
|
3927
|
+
return () => {
|
|
3928
|
+
if (released) return;
|
|
3929
|
+
released = true;
|
|
3930
|
+
registrations.delete(registration);
|
|
3931
|
+
if (registrations.size === 0) this.targets.delete(id);
|
|
3932
|
+
this.notify();
|
|
3933
|
+
};
|
|
3934
|
+
}
|
|
3935
|
+
/**
|
|
3936
|
+
* The mounted targets. Each has the description and the component list of
|
|
3937
|
+
* its earliest mount that has one.
|
|
3938
|
+
*/
|
|
3939
|
+
getMountedTargets() {
|
|
3940
|
+
const mounted = [];
|
|
3941
|
+
for (const [id, registrations] of this.targets) {
|
|
3942
|
+
const description = [...registrations].find((registration) => registration.description !== void 0)?.description;
|
|
3943
|
+
const components = this.targetComponents(id);
|
|
3944
|
+
mounted.push({
|
|
3945
|
+
id,
|
|
3946
|
+
...description === void 0 ? {} : { description },
|
|
3947
|
+
...components === void 0 ? {} : { components: [...components] }
|
|
3948
|
+
});
|
|
3949
|
+
}
|
|
3950
|
+
return mounted;
|
|
3951
|
+
}
|
|
3952
|
+
/**
|
|
3953
|
+
* The component list of the earliest mount of `id` that has one.
|
|
3954
|
+
* `undefined` when no mount of `id` limits its components.
|
|
3955
|
+
*/
|
|
3956
|
+
targetComponents(id) {
|
|
3957
|
+
return [...this.targets.get(id) ?? /* @__PURE__ */ new Set()].find((registration) => registration.components !== void 0)?.components;
|
|
3958
|
+
}
|
|
3959
|
+
/** The components that `validateOperation` allows on a surface. */
|
|
3960
|
+
allowedComponentsFor(surface) {
|
|
3961
|
+
const components = this.targetComponents(surface.target);
|
|
3962
|
+
return components === void 0 ? void 0 : {
|
|
3963
|
+
target: surface.target,
|
|
3964
|
+
names: new Set(components)
|
|
3965
|
+
};
|
|
3966
|
+
}
|
|
3967
|
+
/** Sets one state key. Notifies only when the value changed. */
|
|
3968
|
+
setState(key, value) {
|
|
3969
|
+
if (Object.hasOwn(this.state, key) && Object.is(this.state[key], value)) return;
|
|
3970
|
+
this.state = {
|
|
3971
|
+
...this.state,
|
|
3972
|
+
[key]: value
|
|
3973
|
+
};
|
|
3974
|
+
this.notify();
|
|
3975
|
+
}
|
|
3976
|
+
/** Removes one state key. Notifies only when the key was set. */
|
|
3977
|
+
removeState(key) {
|
|
3978
|
+
if (!Object.hasOwn(this.state, key)) return;
|
|
3979
|
+
const { [key]: _removed, ...rest } = this.state;
|
|
3980
|
+
this.state = rest;
|
|
3981
|
+
this.notify();
|
|
3982
|
+
}
|
|
3983
|
+
/**
|
|
3984
|
+
* Makes the surfaces of `surfaceIds` share their data model: a user write
|
|
3985
|
+
* to one of them goes to all of them (see `setOwnedValue`). The markdown
|
|
3986
|
+
* transport links the parts of a chat surface that the prose lift split.
|
|
3987
|
+
* A later call for one of the surfaces replaces its group.
|
|
3988
|
+
*
|
|
3989
|
+
* @param threadId - The thread of the surfaces.
|
|
3990
|
+
* @param surfaceIds - The surface ids of the group. One id clears a link.
|
|
3991
|
+
*/
|
|
3992
|
+
linkSurfaces(threadId, surfaceIds) {
|
|
3993
|
+
const keys = new Set(surfaceIds.map((id) => surfaceKey(threadId, id)));
|
|
3994
|
+
for (const key of keys) if (keys.size > 1) this.linked.set(key, keys);
|
|
3995
|
+
else this.linked.delete(key);
|
|
3996
|
+
}
|
|
3997
|
+
/**
|
|
3998
|
+
* Writes a user value into the data model of a surface, and marks `path`
|
|
3999
|
+
* as user-owned. Then agent writes to that path, or below it, are ignored.
|
|
4000
|
+
* An agent write above it keeps the user value. Ownership ends when the
|
|
4001
|
+
* surface is deleted. Does nothing for an unknown or deleted surface. The
|
|
4002
|
+
* surfaces linked to it (see `linkSurfaces`) get the same write.
|
|
4003
|
+
*
|
|
4004
|
+
* @param key - The `key` of the surface.
|
|
4005
|
+
* @param path - An absolute JSON pointer, for example "/form/email".
|
|
4006
|
+
* @param value - The new value. It is copied.
|
|
4007
|
+
* @throws Error when a path segment is "__proto__", "constructor" or
|
|
4008
|
+
* "prototype", or when the path does not fit the data (for example, a
|
|
4009
|
+
* segment above it holds a string).
|
|
4010
|
+
*/
|
|
4011
|
+
setOwnedValue(key, path, value) {
|
|
4012
|
+
const normalized = normalizePath(path);
|
|
4013
|
+
const forbidden = normalized.split("/").find((segment) => FORBIDDEN_SEGMENTS.has(segment));
|
|
4014
|
+
if (forbidden !== void 0) throw new Error(`[generativeUI] path segment "${forbidden}" is not allowed in "${path}".`);
|
|
4015
|
+
for (const target of this.linked.get(key) ?? [key]) this.writeOwnedValue(target, normalized, value);
|
|
4016
|
+
}
|
|
4017
|
+
writeOwnedValue(key, path, value) {
|
|
4018
|
+
const surface = this.surfaces.get(key);
|
|
4019
|
+
if (!surface || surface.deleted) return;
|
|
4020
|
+
surface.model.dataModel.set(path, structuredClone(value));
|
|
4021
|
+
const owned = this.owned.get(key) ?? /* @__PURE__ */ new Map();
|
|
4022
|
+
owned.set(path, structuredClone(value));
|
|
4023
|
+
this.owned.set(key, owned);
|
|
4024
|
+
}
|
|
4025
|
+
/**
|
|
4026
|
+
* Writes the user-owned values into the new, empty data model of a rebuilt
|
|
4027
|
+
* surface. The agent operations are applied after it.
|
|
4028
|
+
*/
|
|
4029
|
+
restoreOwnedValues(surface) {
|
|
4030
|
+
const owned = this.owned.get(surface.key) ?? /* @__PURE__ */ new Map();
|
|
4031
|
+
for (const [path, value] of owned) surface.model.dataModel.set(path, structuredClone(value));
|
|
4032
|
+
}
|
|
4033
|
+
/**
|
|
4034
|
+
* The value that an agent write puts at `path`, with the user-owned values
|
|
4035
|
+
* below `path` written back into it. `undefined` when `path` is user-owned
|
|
4036
|
+
* or below a user-owned path, so the agent cannot write it. Throws when a
|
|
4037
|
+
* user value does not fit the new value.
|
|
4038
|
+
*/
|
|
4039
|
+
mergeOwnedValues(key, path, value) {
|
|
4040
|
+
const merged = { value: structuredClone(value) };
|
|
4041
|
+
const owned = this.owned.get(key);
|
|
4042
|
+
if (!owned) return merged;
|
|
4043
|
+
const ownedPaths = [...owned.keys()];
|
|
4044
|
+
if (ownedPaths.some((ownedPath) => isAtOrBelow(path, ownedPath))) return void 0;
|
|
4045
|
+
const below = ownedPaths.filter((ownedPath) => isAtOrBelow(ownedPath, path));
|
|
4046
|
+
if (below.length === 0) return merged;
|
|
4047
|
+
const scratch = new _a2ui_web_core_v0_9.DataModel({ value: merged.value });
|
|
4048
|
+
const prefix = path === "/" ? "" : path;
|
|
4049
|
+
for (const ownedPath of below) {
|
|
4050
|
+
const relative = ownedPath.slice(prefix.length);
|
|
4051
|
+
scratch.set(`/value${relative}`, structuredClone(owned.get(ownedPath)));
|
|
4052
|
+
}
|
|
4053
|
+
return { value: scratch.get("/value") };
|
|
4054
|
+
}
|
|
4055
|
+
extendsApplied(book, operations) {
|
|
4056
|
+
if (operations.length < book.appliedCount) return false;
|
|
4057
|
+
if (book.appliedCount === 0) return true;
|
|
4058
|
+
return JSON.stringify(operations[book.appliedCount - 1]) === book.lastFingerprint;
|
|
4059
|
+
}
|
|
4060
|
+
createSurface(key, threadId, agentId, content) {
|
|
4061
|
+
return {
|
|
4062
|
+
key,
|
|
4063
|
+
threadId,
|
|
4064
|
+
surfaceId: content.surfaceId,
|
|
4065
|
+
agentId,
|
|
4066
|
+
model: new _a2ui_web_core_v0_9.SurfaceModel(content.surfaceId, this.webCoreCatalog),
|
|
4067
|
+
createdAt: ++creationCounter,
|
|
4068
|
+
target: content.target,
|
|
4069
|
+
status: content.status,
|
|
4070
|
+
deleted: false,
|
|
4071
|
+
failed: false,
|
|
4072
|
+
serverRejected: content.rejected ?? [],
|
|
4073
|
+
clientRejected: [],
|
|
4074
|
+
operations: []
|
|
4075
|
+
};
|
|
4076
|
+
}
|
|
4077
|
+
disposeSurface(key) {
|
|
4078
|
+
this.surfaces.get(key)?.model.dispose();
|
|
4079
|
+
this.surfaces.delete(key);
|
|
4080
|
+
this.bookkeeping.delete(key);
|
|
4081
|
+
}
|
|
4082
|
+
/**
|
|
4083
|
+
* Marks a surface deleted and frees its components and data. The record
|
|
4084
|
+
* stays, so the model is still told about the id and the bookkeeping does
|
|
4085
|
+
* not rebuild the surface for content that was already applied.
|
|
4086
|
+
*/
|
|
4087
|
+
closeSurface(surface) {
|
|
4088
|
+
surface.deleted = true;
|
|
4089
|
+
surface.model.dispose();
|
|
4090
|
+
surface.model = new _a2ui_web_core_v0_9.SurfaceModel(surface.surfaceId, this.webCoreCatalog);
|
|
4091
|
+
this.owned.delete(surface.key);
|
|
4092
|
+
this.linked.delete(surface.key);
|
|
4093
|
+
}
|
|
4094
|
+
/** The surfaces of a thread that a part of `surfaceId` reads, for tests. */
|
|
4095
|
+
getLinkedSurfaceIds(threadId, surfaceId) {
|
|
4096
|
+
const keys = this.linked.get(surfaceKey(threadId, surfaceId));
|
|
4097
|
+
if (!keys) return [surfaceId];
|
|
4098
|
+
const prefix = `${threadId}::`;
|
|
4099
|
+
return [...keys].map((key) => key.slice(prefix.length));
|
|
4100
|
+
}
|
|
4101
|
+
/**
|
|
4102
|
+
* Drops the node keys that the app sets: bound props and matched events.
|
|
4103
|
+
* The model does not see them, so a model value for one is ignored, not
|
|
4104
|
+
* rejected. This runs before validation, because validation rejects keys
|
|
4105
|
+
* that are not in the manifest. It never changes the given operation.
|
|
4106
|
+
*/
|
|
4107
|
+
dropAppSetKeys(op) {
|
|
4108
|
+
const kind = (0, _copilotkit_shared.getOperationKind)(op);
|
|
4109
|
+
if (kind !== "updateComponents" && kind !== "createSurface") return op;
|
|
4110
|
+
const record = op;
|
|
4111
|
+
const payload = record[kind];
|
|
4112
|
+
const nodes = payload?.components;
|
|
4113
|
+
if (!Array.isArray(nodes)) return op;
|
|
4114
|
+
return {
|
|
4115
|
+
...record,
|
|
4116
|
+
[kind]: {
|
|
4117
|
+
...payload,
|
|
4118
|
+
components: nodes.map((node) => this.dropAppSetNodeKeys(node))
|
|
4119
|
+
}
|
|
4120
|
+
};
|
|
4121
|
+
}
|
|
4122
|
+
dropAppSetNodeKeys(node) {
|
|
4123
|
+
if (typeof node !== "object" || node === null || !("component" in node)) return node;
|
|
4124
|
+
const { component } = node;
|
|
4125
|
+
if (typeof component !== "string") return node;
|
|
4126
|
+
const definition = this.ui.components.get(component);
|
|
4127
|
+
if (!definition) return node;
|
|
4128
|
+
return Object.fromEntries(Object.entries(node).filter(([key]) => !Object.hasOwn(definition.selectors, key) && !Object.hasOwn(definition.eventFunctions, key)));
|
|
4129
|
+
}
|
|
4130
|
+
/**
|
|
4131
|
+
* The surfaces that `validateOperation` gets for one operation of the
|
|
4132
|
+
* content of `surface`.
|
|
4133
|
+
*
|
|
4134
|
+
* - `knownSurfaces`: the surface, when it exists before the operation. It
|
|
4135
|
+
* does not exist before its first createSurface, or after a delete.
|
|
4136
|
+
* - `createdSurfaces`: the surface, when a createSurface at this position
|
|
4137
|
+
* uses its id again. That is the case after the first operation, and for
|
|
4138
|
+
* a surface that was deleted before, unless the content replays that
|
|
4139
|
+
* delete.
|
|
4140
|
+
*/
|
|
4141
|
+
surfacesFor(surface, kind, position) {
|
|
4142
|
+
const isFirstCreate = kind === "createSurface" && position.index === 0;
|
|
4143
|
+
const exists = !surface.deleted && !isFirstCreate;
|
|
4144
|
+
const isRecreate = this.deletedKeys.has(surface.key) && !position.isReplay;
|
|
4145
|
+
const isUsedAgain = position.index > 0 || isRecreate;
|
|
4146
|
+
return {
|
|
4147
|
+
knownSurfaces: new Set(exists ? [surface.surfaceId] : []),
|
|
4148
|
+
createdSurfaces: new Set(isUsedAgain ? [surface.surfaceId] : [])
|
|
4149
|
+
};
|
|
4150
|
+
}
|
|
4151
|
+
applyOperation(surface, received, position) {
|
|
4152
|
+
const { index } = position;
|
|
4153
|
+
const kind = (0, _copilotkit_shared.getOperationKind)(received);
|
|
4154
|
+
if (kind === "callRendererFunction") return;
|
|
4155
|
+
const reject = (reason) => {
|
|
4156
|
+
if (kind === "createSurface" && index === 0) {
|
|
4157
|
+
this.closeSurface(surface);
|
|
4158
|
+
surface.failed = true;
|
|
4159
|
+
}
|
|
4160
|
+
surface.clientRejected.push({
|
|
4161
|
+
index,
|
|
4162
|
+
reason
|
|
4163
|
+
});
|
|
4164
|
+
this.options.onOperationRejected?.({
|
|
4165
|
+
surfaceId: surface.surfaceId,
|
|
4166
|
+
index,
|
|
4167
|
+
reason
|
|
4168
|
+
});
|
|
4169
|
+
};
|
|
4170
|
+
const targetId = (0, _copilotkit_shared.getOperationSurfaceId)(received);
|
|
4171
|
+
if (targetId !== void 0 && targetId !== surface.surfaceId) return reject(`operation is for surface "${targetId}", not "${surface.surfaceId}"`);
|
|
4172
|
+
const op = this.dropAppSetKeys(received);
|
|
4173
|
+
const validation = (0, _copilotkit_shared.validateOperation)(op, {
|
|
4174
|
+
manifest: {
|
|
4175
|
+
catalogId: this.ui.id,
|
|
4176
|
+
catalogIds: require_MarkdownSurfaces.catalogIdsOf(this.ui),
|
|
4177
|
+
components: this.ui.manifestComponents
|
|
4178
|
+
},
|
|
4179
|
+
...this.surfacesFor(surface, kind, position),
|
|
4180
|
+
allowedComponents: this.allowedComponentsFor(surface)
|
|
4181
|
+
});
|
|
4182
|
+
if (!validation.ok) return reject(validation.reason);
|
|
4183
|
+
const typed = op;
|
|
4184
|
+
if ("createSurface" in typed) {
|
|
4185
|
+
const { dataModel, components = [] } = typed.createSurface;
|
|
4186
|
+
const problem = this.nodesProblem(components);
|
|
4187
|
+
if (problem) return reject(problem);
|
|
4188
|
+
if (dataModel) {
|
|
4189
|
+
const failure = this.writeAgentData(surface, "/", dataModel);
|
|
4190
|
+
if (failure) return reject(failure);
|
|
4191
|
+
}
|
|
4192
|
+
for (const node of components) this.upsertNode(surface.model, node);
|
|
4193
|
+
return;
|
|
4194
|
+
}
|
|
4195
|
+
if ("updateComponents" in typed) {
|
|
4196
|
+
const nodes = typed.updateComponents.components;
|
|
4197
|
+
const problem = this.nodesProblem(nodes);
|
|
4198
|
+
if (problem) return reject(problem);
|
|
4199
|
+
for (const node of nodes) this.upsertNode(surface.model, node);
|
|
4200
|
+
return;
|
|
4201
|
+
}
|
|
4202
|
+
if ("updateDataModel" in typed) {
|
|
4203
|
+
const { path = "/", value } = typed.updateDataModel;
|
|
4204
|
+
const written = value === null ? void 0 : value;
|
|
4205
|
+
const failure = this.writeAgentData(surface, normalizePath(path), written);
|
|
4206
|
+
if (failure) return reject(failure);
|
|
4207
|
+
return;
|
|
4208
|
+
}
|
|
4209
|
+
if ("deleteSurface" in typed) {
|
|
4210
|
+
this.closeSurface(surface);
|
|
4211
|
+
this.deletedKeys.add(surface.key);
|
|
4212
|
+
}
|
|
4213
|
+
}
|
|
4214
|
+
/** The first node with props of the wrong type, as a reason. */
|
|
4215
|
+
nodesProblem(nodes) {
|
|
4216
|
+
for (const node of nodes) {
|
|
4217
|
+
const problem = this.checkNodeProps(node);
|
|
4218
|
+
if (problem) return `component "${node.id}": ${problem}`;
|
|
4219
|
+
}
|
|
4220
|
+
}
|
|
4221
|
+
/**
|
|
4222
|
+
* Writes an agent value at `path` and keeps the user-owned values. A write
|
|
4223
|
+
* to a user-owned path is ignored, not rejected. Gives the reason when the
|
|
4224
|
+
* value does not fit the data, else `undefined`.
|
|
4225
|
+
*/
|
|
4226
|
+
writeAgentData(surface, path, value) {
|
|
4227
|
+
try {
|
|
4228
|
+
const merged = this.mergeOwnedValues(surface.key, path, value);
|
|
4229
|
+
if (merged) surface.model.dataModel.set(path, merged.value);
|
|
4230
|
+
return;
|
|
4231
|
+
} catch (error) {
|
|
4232
|
+
return error instanceof Error ? error.message : String(error);
|
|
4233
|
+
}
|
|
4234
|
+
}
|
|
4235
|
+
checkNodeProps(node) {
|
|
4236
|
+
const definition = this.ui.components.get(node.component);
|
|
4237
|
+
if (!definition) return `unknown component "${node.component}"`;
|
|
4238
|
+
const { id: _id, component: _component, ...rest } = node;
|
|
4239
|
+
const dataProps = Object.fromEntries(Object.entries(rest).filter(([key]) => !definition.events?.[key] && !definition.slots?.[key] && !_copilotkit_shared.A2UI_COMPONENT_ENVELOPE_KEYS.has(key)));
|
|
4240
|
+
if (!definition.props) return void 0;
|
|
4241
|
+
const unknownNow = new Set(Object.keys(definition.selectors));
|
|
4242
|
+
const literals = {};
|
|
4243
|
+
for (const [key, value] of Object.entries(dataProps)) if (require_MarkdownSurfaces.containsDynamicValue(value)) unknownNow.add(key);
|
|
4244
|
+
else literals[key] = value;
|
|
4245
|
+
let result = require_MarkdownSurfaces.validateSchemaSync(definition.props, literals);
|
|
4246
|
+
if (!result.success) {
|
|
4247
|
+
const unset = require_MarkdownSurfaces.withoutRejectedNulls(literals, result.issues);
|
|
4248
|
+
if (unset) result = require_MarkdownSurfaces.validateSchemaSync(definition.props, unset);
|
|
4249
|
+
}
|
|
4250
|
+
if (result.success) return void 0;
|
|
4251
|
+
const issues = result.issues.filter((issue) => {
|
|
4252
|
+
const key = require_MarkdownSurfaces.issueKey(issue);
|
|
4253
|
+
return key === void 0 ? require_MarkdownSurfaces.isAsyncIssue(issue) : !unknownNow.has(key);
|
|
4254
|
+
});
|
|
4255
|
+
return issues.length > 0 ? require_MarkdownSurfaces.formatIssues(issues) : void 0;
|
|
4256
|
+
}
|
|
4257
|
+
upsertNode(model, node) {
|
|
4258
|
+
const { id, component, ...rest } = node;
|
|
4259
|
+
const properties = structuredClone(rest);
|
|
4260
|
+
const existing = model.componentsModel.get(id);
|
|
4261
|
+
if (existing && existing.type === component) {
|
|
4262
|
+
existing.properties = properties;
|
|
4263
|
+
return;
|
|
4264
|
+
}
|
|
4265
|
+
if (existing) model.componentsModel.removeComponent(id);
|
|
4266
|
+
model.componentsModel.addComponent(new _a2ui_web_core_v0_9.ComponentModel(id, component, properties));
|
|
4267
|
+
}
|
|
4268
|
+
};
|
|
4269
|
+
|
|
4270
|
+
//#endregion
|
|
4271
|
+
//#region src/v2/generative-ui/use-generative-ui-root.ts
|
|
4272
|
+
const isDevelopment = () => process.env.NODE_ENV !== "production";
|
|
4273
|
+
/** At most this many function follow-up runs for each user turn. */
|
|
4274
|
+
const MAX_FUNCTION_FOLLOW_UPS = 5;
|
|
4275
|
+
function ingestMessages(manager, agent, messages) {
|
|
4276
|
+
if (!agent.threadId) return;
|
|
4277
|
+
for (const message of messages) if (message.role === "activity" && message.activityType === _copilotkit_shared.GENERATIVE_UI_ACTIVITY_TYPE) manager.ingest(agent.threadId, agent.agentId, message.content);
|
|
4278
|
+
}
|
|
4279
|
+
/** What the envelope of a run says, from the provider config. */
|
|
4280
|
+
function envelopeOptionsFor(config) {
|
|
4281
|
+
if (config.transport === "markdown") return {
|
|
4282
|
+
transport: "markdown",
|
|
4283
|
+
includeCatalog: config.includeCatalog !== false,
|
|
4284
|
+
contextSent: config.sendContext !== false
|
|
4285
|
+
};
|
|
4286
|
+
return {
|
|
4287
|
+
transport: "tool",
|
|
4288
|
+
includeCatalog: true,
|
|
4289
|
+
contextSent: false
|
|
4290
|
+
};
|
|
4291
|
+
}
|
|
4292
|
+
/**
|
|
4293
|
+
* The components of a surface as one `updateComponents` operation, so that
|
|
4294
|
+
* the label of the component that sent an event can be found.
|
|
4295
|
+
*/
|
|
4296
|
+
function surfaceComponents(surface) {
|
|
4297
|
+
const components = [...surface.model.componentsModel.entries].map(([id, model]) => ({
|
|
4298
|
+
...model.properties,
|
|
4299
|
+
id,
|
|
4300
|
+
component: model.type
|
|
4301
|
+
}));
|
|
4302
|
+
return [{
|
|
4303
|
+
version: _copilotkit_shared.A2UI_VERSION,
|
|
4304
|
+
updateComponents: {
|
|
4305
|
+
surfaceId: surface.surfaceId,
|
|
4306
|
+
components
|
|
4307
|
+
}
|
|
4308
|
+
}];
|
|
4309
|
+
}
|
|
4310
|
+
/** True when `value` names a `functionCallId`. */
|
|
4311
|
+
function hasFunctionCallId(value) {
|
|
4312
|
+
return typeof value === "object" && value !== null && "functionCallId" in value && typeof value.functionCallId === "string" && value.functionCallId !== "";
|
|
4313
|
+
}
|
|
4314
|
+
/** The `functionCallId` that a developer message answers, if any. */
|
|
4315
|
+
function answeredCallId(content) {
|
|
4316
|
+
if (!content.includes("rendererFunctionResponse")) return void 0;
|
|
4317
|
+
try {
|
|
4318
|
+
const parsed = JSON.parse(content);
|
|
4319
|
+
const response = typeof parsed === "object" && parsed !== null && "rendererFunctionResponse" in parsed ? parsed.rendererFunctionResponse : void 0;
|
|
4320
|
+
return hasFunctionCallId(response) ? response.functionCallId : void 0;
|
|
4321
|
+
} catch {
|
|
4322
|
+
return;
|
|
4323
|
+
}
|
|
4324
|
+
}
|
|
4325
|
+
/** The function calls that a developer message in `messages` answers. */
|
|
4326
|
+
function answeredCallIds(messages) {
|
|
4327
|
+
const ids = /* @__PURE__ */ new Set();
|
|
4328
|
+
for (const message of messages) {
|
|
4329
|
+
if (message.role !== "developer") continue;
|
|
4330
|
+
const id = answeredCallId(message.content);
|
|
4331
|
+
if (id !== void 0) ids.add(id);
|
|
4332
|
+
}
|
|
4333
|
+
return ids;
|
|
4334
|
+
}
|
|
4335
|
+
/** The id of the last user message. A user turn starts with it. */
|
|
4336
|
+
function lastUserMessageId(messages) {
|
|
4337
|
+
for (let index = messages.length - 1; index >= 0; index--) {
|
|
4338
|
+
const message = messages[index];
|
|
4339
|
+
if (message?.role === "user") return message.id;
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
/** The function calls of the tool transport: its function-call activities. */
|
|
4343
|
+
function activityFunctionCalls(messages) {
|
|
4344
|
+
const requests = [];
|
|
4345
|
+
for (const message of messages) {
|
|
4346
|
+
if (!(message.role === "activity" && message.activityType === _copilotkit_shared.GENERATIVE_UI_FUNCTION_CALL_ACTIVITY_TYPE) || !hasFunctionCallId(message.content)) continue;
|
|
4347
|
+
requests.push({
|
|
4348
|
+
functionCallId: message.content.functionCallId,
|
|
4349
|
+
operation: {
|
|
4350
|
+
version: _copilotkit_shared.A2UI_VERSION,
|
|
4351
|
+
callRendererFunction: message.content
|
|
4352
|
+
}
|
|
4353
|
+
});
|
|
4354
|
+
}
|
|
4355
|
+
return requests;
|
|
4356
|
+
}
|
|
4357
|
+
/** The function calls of the markdown transport: its fence lines. */
|
|
4358
|
+
function markdownFunctionCalls(calls) {
|
|
4359
|
+
const requests = [];
|
|
4360
|
+
for (const { operation } of calls) {
|
|
4361
|
+
const payload = operation.callRendererFunction;
|
|
4362
|
+
if (!hasFunctionCallId(payload)) continue;
|
|
4363
|
+
requests.push({
|
|
4364
|
+
functionCallId: payload.functionCallId,
|
|
4365
|
+
operation
|
|
4366
|
+
});
|
|
4367
|
+
}
|
|
4368
|
+
return requests;
|
|
3284
4369
|
}
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
|
|
4370
|
+
/** The text of a `rendererFunctionResponse` developer message. */
|
|
4371
|
+
function responseContent(response) {
|
|
4372
|
+
return JSON.stringify({
|
|
4373
|
+
version: _copilotkit_shared.A2UI_VERSION,
|
|
4374
|
+
rendererFunctionResponse: response
|
|
4375
|
+
});
|
|
4376
|
+
}
|
|
4377
|
+
function errorAnswer(functionCallId, code, message) {
|
|
4378
|
+
return {
|
|
4379
|
+
content: responseContent({
|
|
4380
|
+
functionCallId,
|
|
4381
|
+
error: {
|
|
4382
|
+
code,
|
|
4383
|
+
message
|
|
4384
|
+
}
|
|
4385
|
+
}),
|
|
4386
|
+
followUp: true
|
|
4387
|
+
};
|
|
4388
|
+
}
|
|
4389
|
+
const overCapAnswer = (functionCallId) => ({
|
|
4390
|
+
content: responseContent({
|
|
4391
|
+
functionCallId,
|
|
4392
|
+
error: {
|
|
4393
|
+
code: "follow_up_limit",
|
|
4394
|
+
message: `The function did not run. A user turn can have at most ${MAX_FUNCTION_FOLLOW_UPS} function follow-up runs. Wait for the next user message.`
|
|
4395
|
+
}
|
|
4396
|
+
}),
|
|
4397
|
+
followUp: false
|
|
4398
|
+
});
|
|
3288
4399
|
/**
|
|
3289
|
-
*
|
|
3290
|
-
*
|
|
3291
|
-
*
|
|
3292
|
-
* The entries are scoped to the agents the runtime applies A2UI to
|
|
3293
|
-
* (`copilotkit.a2uiAgents`, #5369), so agents outside that list don't receive
|
|
3294
|
-
* the catalog/schema/guidelines payload on their runs.
|
|
4400
|
+
* Runs the functions that the agent calls with `callRendererFunction`, for
|
|
4401
|
+
* both transports, and answers each call.
|
|
3295
4402
|
*
|
|
3296
|
-
*
|
|
3297
|
-
*
|
|
3298
|
-
*
|
|
4403
|
+
* - Each `functionCallId` runs once for each thread. A replay, a sync of
|
|
4404
|
+
* the same messages again, or a call that already has an answer message
|
|
4405
|
+
* does not run it again.
|
|
4406
|
+
* - The answer is a hidden developer message with a `rendererFunctionResponse`.
|
|
4407
|
+
* The answers go to the agent only when it is not running. Then one
|
|
4408
|
+
* follow-up run starts for all of them.
|
|
4409
|
+
* - A user turn has at most {@link MAX_FUNCTION_FOLLOW_UPS} follow-up runs.
|
|
4410
|
+
* A call after that does not run. It gets a `follow_up_limit` error and
|
|
4411
|
+
* starts no follow-up run.
|
|
3299
4412
|
*/
|
|
3300
|
-
function
|
|
3301
|
-
const { copilotkit } =
|
|
3302
|
-
const
|
|
3303
|
-
const
|
|
3304
|
-
|
|
3305
|
-
|
|
3306
|
-
|
|
3307
|
-
|
|
3308
|
-
|
|
3309
|
-
|
|
3310
|
-
|
|
3311
|
-
|
|
3312
|
-
|
|
3313
|
-
|
|
3314
|
-
}));
|
|
3315
|
-
if (schemaValue) {
|
|
3316
|
-
ids.push(copilotkit.addContext({
|
|
3317
|
-
description: _copilotkit_a2ui_renderer.A2UI_SCHEMA_CONTEXT_DESCRIPTION,
|
|
3318
|
-
value: schemaValue,
|
|
3319
|
-
...scope
|
|
3320
|
-
}));
|
|
3321
|
-
ids.push(copilotkit.addContext({
|
|
3322
|
-
description: "A2UI generation guidelines — protocol rules, tool arguments, path rules, data model format, and form/two-way-binding instructions.",
|
|
3323
|
-
value: _copilotkit_shared.A2UI_DEFAULT_GENERATION_GUIDELINES,
|
|
3324
|
-
...scope
|
|
3325
|
-
}));
|
|
3326
|
-
ids.push(copilotkit.addContext({
|
|
3327
|
-
description: "A2UI design guidelines — visual design rules, component hierarchy tips, and action handler patterns.",
|
|
3328
|
-
value: _copilotkit_shared.A2UI_DEFAULT_DESIGN_GUIDELINES,
|
|
3329
|
-
...scope
|
|
3330
|
-
}));
|
|
4413
|
+
function createFunctionCallRunner(options) {
|
|
4414
|
+
const { copilotkit, dispatcher, manifest } = options;
|
|
4415
|
+
const threads = /* @__PURE__ */ new Map();
|
|
4416
|
+
const threadState = (threadId) => {
|
|
4417
|
+
let state = threads.get(threadId);
|
|
4418
|
+
if (!state) {
|
|
4419
|
+
state = {
|
|
4420
|
+
done: /* @__PURE__ */ new Set(),
|
|
4421
|
+
pending: [],
|
|
4422
|
+
turn: void 0,
|
|
4423
|
+
followUps: 0,
|
|
4424
|
+
flushing: false
|
|
4425
|
+
};
|
|
4426
|
+
threads.set(threadId, state);
|
|
3331
4427
|
}
|
|
3332
|
-
return
|
|
3333
|
-
|
|
4428
|
+
return state;
|
|
4429
|
+
};
|
|
4430
|
+
const answer = async (request) => {
|
|
4431
|
+
const { functionCallId } = request;
|
|
4432
|
+
const validation = (0, _copilotkit_shared.validateOperation)(request.operation, {
|
|
4433
|
+
manifest,
|
|
4434
|
+
knownSurfaces: /* @__PURE__ */ new Set()
|
|
4435
|
+
});
|
|
4436
|
+
if (!validation.ok) return errorAnswer(functionCallId, "invalid_arguments", validation.reason);
|
|
4437
|
+
const operation = request.operation;
|
|
4438
|
+
if (!("callRendererFunction" in operation)) return errorAnswer(functionCallId, "invalid_arguments", "the operation is not a callRendererFunction");
|
|
4439
|
+
const { callFunction } = operation.callRendererFunction;
|
|
4440
|
+
const name = callFunction["@call"];
|
|
4441
|
+
const result = await dispatcher.invoke(name, callFunction.args ?? {}, { functionCallId });
|
|
4442
|
+
if (!result.ok) return errorAnswer(functionCallId, result.error.code, result.error.message);
|
|
4443
|
+
try {
|
|
4444
|
+
return {
|
|
4445
|
+
content: responseContent({
|
|
4446
|
+
functionCallId,
|
|
4447
|
+
value: result.result ?? null
|
|
4448
|
+
}),
|
|
4449
|
+
followUp: true
|
|
4450
|
+
};
|
|
4451
|
+
} catch (cause) {
|
|
4452
|
+
return errorAnswer(functionCallId, "handler_failed", `The result of "${name}" is not JSON: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
4453
|
+
}
|
|
4454
|
+
};
|
|
4455
|
+
/**
|
|
4456
|
+
* Adds the pending answers of a thread to the agent, then starts one
|
|
4457
|
+
* follow-up run. It waits while the agent runs: the next read of the
|
|
4458
|
+
* thread, at the end of the run, flushes again.
|
|
4459
|
+
*/
|
|
4460
|
+
const flush = async (agent, threadId, state) => {
|
|
4461
|
+
if (state.flushing) return;
|
|
4462
|
+
state.flushing = true;
|
|
4463
|
+
try {
|
|
4464
|
+
while (state.pending.length > 0) {
|
|
4465
|
+
const batch = [...state.pending];
|
|
4466
|
+
const answers = await Promise.all(batch);
|
|
4467
|
+
await copilotkit.waitForPendingFrameworkUpdates();
|
|
4468
|
+
if (agent.isRunning || agent.threadId !== threadId) return;
|
|
4469
|
+
if (state.pending.length > batch.length) continue;
|
|
4470
|
+
state.pending = [];
|
|
4471
|
+
for (const { content } of answers) agent.addMessage({
|
|
4472
|
+
id: (0, _copilotkit_shared.randomUUID)(),
|
|
4473
|
+
role: "developer",
|
|
4474
|
+
content
|
|
4475
|
+
});
|
|
4476
|
+
if (!answers.some((item) => item.followUp)) continue;
|
|
4477
|
+
state.followUps++;
|
|
4478
|
+
await copilotkit.runAgent({ agent });
|
|
4479
|
+
}
|
|
4480
|
+
} catch (error) {
|
|
4481
|
+
if (isDevelopment()) console.warn("[generativeUI] function follow-up run failed:", error);
|
|
4482
|
+
} finally {
|
|
4483
|
+
state.flushing = false;
|
|
4484
|
+
}
|
|
4485
|
+
};
|
|
4486
|
+
return { run(agent, requests, messages, running) {
|
|
4487
|
+
const { threadId } = agent;
|
|
4488
|
+
if (!threadId) return;
|
|
4489
|
+
const state = threadState(threadId);
|
|
4490
|
+
const turn = lastUserMessageId(messages);
|
|
4491
|
+
if (turn !== state.turn) {
|
|
4492
|
+
state.turn = turn;
|
|
4493
|
+
state.followUps = 0;
|
|
4494
|
+
}
|
|
4495
|
+
const isNew = (request) => !state.done.has(request.functionCallId);
|
|
4496
|
+
const fresh = requests.filter(isNew);
|
|
4497
|
+
const answered = fresh.length > 0 ? answeredCallIds(messages) : /* @__PURE__ */ new Set();
|
|
4498
|
+
for (const request of fresh) {
|
|
4499
|
+
const { functionCallId } = request;
|
|
4500
|
+
if (state.done.has(functionCallId)) continue;
|
|
4501
|
+
state.done.add(functionCallId);
|
|
4502
|
+
if (answered.has(functionCallId)) continue;
|
|
4503
|
+
const isOverCap = state.followUps >= MAX_FUNCTION_FOLLOW_UPS;
|
|
4504
|
+
state.pending.push(isOverCap ? Promise.resolve(overCapAnswer(functionCallId)) : answer(request));
|
|
4505
|
+
}
|
|
4506
|
+
if (!running) flush(agent, threadId, state);
|
|
4507
|
+
} };
|
|
4508
|
+
}
|
|
4509
|
+
/** Provider-side wiring: manager, dispatcher, agent subscriptions, envelope. */
|
|
4510
|
+
function useGenerativeUIRoot(copilotkit, config) {
|
|
4511
|
+
const configRef = (0, react.useRef)(config);
|
|
4512
|
+
configRef.current = config;
|
|
4513
|
+
const ui = config?.ui;
|
|
4514
|
+
const transport = config?.transport ?? "tool";
|
|
4515
|
+
const theme = require_MarkdownSurfaces.useShallowStableRef(config?.theme);
|
|
4516
|
+
const core = (0, react.useMemo)(() => {
|
|
4517
|
+
if (!ui) return null;
|
|
4518
|
+
const reportError = (info) => {
|
|
4519
|
+
try {
|
|
4520
|
+
configRef.current?.errorBoundary?.onError?.(info);
|
|
4521
|
+
} catch (hostError) {
|
|
4522
|
+
if (isDevelopment()) console.error("[generativeUI] errorBoundary.onError threw:", hostError);
|
|
4523
|
+
}
|
|
4524
|
+
if (isDevelopment()) console.warn(`[generativeUI] ${info.kind} error in ${info.surfaceId}${info.componentId ? `/${info.componentId}` : ""}: ${info.error?.message}`);
|
|
4525
|
+
};
|
|
4526
|
+
const manager = new GenerativeUISurfaceManager(ui, { onOperationRejected: ({ surfaceId, index, reason }) => reportError({
|
|
4527
|
+
kind: "operation",
|
|
4528
|
+
surfaceId,
|
|
4529
|
+
error: /* @__PURE__ */ new Error(`operation ${index} rejected: ${reason}`)
|
|
4530
|
+
}) });
|
|
4531
|
+
const dispatcher = createGenerativeUIDispatcher({
|
|
4532
|
+
getDeclared: () => ui.functions,
|
|
4533
|
+
onError: ({ name, origin, error }) => {
|
|
4534
|
+
if ("functionCallId" in origin) {
|
|
4535
|
+
if (isDevelopment()) console.warn(`[generativeUI] function call ${origin.functionCallId} to "${name}" failed: ${error.message}`);
|
|
4536
|
+
return;
|
|
4537
|
+
}
|
|
4538
|
+
reportError({
|
|
4539
|
+
kind: "function",
|
|
4540
|
+
...origin,
|
|
4541
|
+
error
|
|
4542
|
+
});
|
|
4543
|
+
}
|
|
4544
|
+
});
|
|
4545
|
+
const functionCalls = createFunctionCallRunner({
|
|
4546
|
+
copilotkit,
|
|
4547
|
+
dispatcher,
|
|
4548
|
+
manifest: {
|
|
4549
|
+
catalogId: ui.id,
|
|
4550
|
+
catalogIds: require_MarkdownSurfaces.catalogIdsOf(ui),
|
|
4551
|
+
components: ui.manifestComponents
|
|
4552
|
+
}
|
|
4553
|
+
});
|
|
4554
|
+
const forwardingAgents = /* @__PURE__ */ new Set();
|
|
4555
|
+
/**
|
|
4556
|
+
* The action of a user event, as an envelope entry scoped to the agent
|
|
4557
|
+
* the user acted on, for the run that the event starts: the structured
|
|
4558
|
+
* form of the user message. It is set before the run starts and dropped
|
|
4559
|
+
* when the run is over, so a suggestion request or a follow-up run
|
|
4560
|
+
* (both read the properties with no run start) does not carry the same
|
|
4561
|
+
* action again, and another agent never gets a click meant for this one.
|
|
4562
|
+
* The entry comes after the shared envelope, so it wins for its agent;
|
|
4563
|
+
* `refreshActions` keeps it last when the shared envelope is set again.
|
|
4564
|
+
*/
|
|
4565
|
+
const actions = /* @__PURE__ */ new Map();
|
|
4566
|
+
const dropAction = (agent) => {
|
|
4567
|
+
const entry = actions.get(agent);
|
|
4568
|
+
if (!entry) return;
|
|
4569
|
+
entry.subscription.unsubscribe();
|
|
4570
|
+
copilotkit.removeScopedProperties(entry.id);
|
|
4571
|
+
actions.delete(agent);
|
|
4572
|
+
};
|
|
4573
|
+
const setAction = (agent, action) => {
|
|
4574
|
+
const previous = actions.get(agent);
|
|
4575
|
+
previous?.subscription.unsubscribe();
|
|
4576
|
+
if (previous) copilotkit.removeScopedProperties(previous.id);
|
|
4577
|
+
actions.delete(agent);
|
|
4578
|
+
const latest = configRef.current;
|
|
4579
|
+
if (!latest) return;
|
|
4580
|
+
const envelope = buildGenerativeUIEnvelope({
|
|
4581
|
+
ui,
|
|
4582
|
+
manager,
|
|
4583
|
+
dispatcher
|
|
4584
|
+
}, agent.threadId, {
|
|
4585
|
+
...envelopeOptionsFor(latest),
|
|
4586
|
+
action
|
|
4587
|
+
});
|
|
4588
|
+
const id = copilotkit.addScopedProperties({
|
|
4589
|
+
properties: { [_copilotkit_shared.COPILOTKIT_FORWARDED_PROPS_KEY]: { ui: envelope } },
|
|
4590
|
+
agentIds: agent.agentId === void 0 ? latest.agentIds : [agent.agentId]
|
|
4591
|
+
});
|
|
4592
|
+
const subscription = agent.subscribe({
|
|
4593
|
+
onRunFinalized: () => dropAction(agent),
|
|
4594
|
+
onRunFailed: () => dropAction(agent)
|
|
4595
|
+
});
|
|
4596
|
+
actions.set(agent, {
|
|
4597
|
+
id,
|
|
4598
|
+
action,
|
|
4599
|
+
subscription
|
|
4600
|
+
});
|
|
4601
|
+
};
|
|
4602
|
+
const refreshActions = () => {
|
|
4603
|
+
for (const [agent, { action }] of [...actions]) setAction(agent, action);
|
|
4604
|
+
};
|
|
4605
|
+
const dropAllActions = () => {
|
|
4606
|
+
for (const agent of [...actions.keys()]) dropAction(agent);
|
|
4607
|
+
};
|
|
4608
|
+
const forwardEvent = async (event, agentId) => {
|
|
4609
|
+
const fail = (message) => {
|
|
4610
|
+
const error = new require_MarkdownSurfaces.GenerativeUIError("event_forward_failed", message);
|
|
4611
|
+
reportError({
|
|
4612
|
+
kind: "event",
|
|
4613
|
+
surfaceId: event.surfaceId,
|
|
4614
|
+
componentId: event.componentId,
|
|
4615
|
+
error
|
|
4616
|
+
});
|
|
4617
|
+
return {
|
|
4618
|
+
ok: false,
|
|
4619
|
+
error
|
|
4620
|
+
};
|
|
4621
|
+
};
|
|
4622
|
+
const agent = copilotkit.getAgent(agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID);
|
|
4623
|
+
if (!agent) return fail(`No agent "${agentId}" to receive "${event.name}"`);
|
|
4624
|
+
if (agent.isRunning || forwardingAgents.has(agent)) return {
|
|
4625
|
+
ok: false,
|
|
4626
|
+
error: new require_MarkdownSurfaces.GenerativeUIError("agent_busy", `"${event.name}" was not sent: the agent is running`)
|
|
4627
|
+
};
|
|
4628
|
+
forwardingAgents.add(agent);
|
|
4629
|
+
try {
|
|
4630
|
+
const surface = agent.threadId ? manager.getSurface(agent.threadId, event.surfaceId) : void 0;
|
|
4631
|
+
const resolveLabel = surface ? createComponentLabelResolver(surfaceComponents(surface)) : void 0;
|
|
4632
|
+
agent.addMessage({
|
|
4633
|
+
id: (0, _copilotkit_shared.randomUUID)(),
|
|
4634
|
+
role: "user",
|
|
4635
|
+
content: buildActionMessageText(event, resolveLabel)
|
|
4636
|
+
});
|
|
4637
|
+
setAction(agent, (0, _copilotkit_shared.toA2UIActionMessage)(event));
|
|
4638
|
+
await copilotkit.runAgent({ agent });
|
|
4639
|
+
return {
|
|
4640
|
+
ok: true,
|
|
4641
|
+
result: void 0
|
|
4642
|
+
};
|
|
4643
|
+
} catch (cause) {
|
|
4644
|
+
return fail(`Forwarding "${event.name}" failed: ${cause instanceof Error ? cause.message : String(cause)}`);
|
|
4645
|
+
} finally {
|
|
4646
|
+
forwardingAgents.delete(agent);
|
|
4647
|
+
dropAction(agent);
|
|
4648
|
+
}
|
|
4649
|
+
};
|
|
4650
|
+
return {
|
|
4651
|
+
manager,
|
|
4652
|
+
dispatcher,
|
|
4653
|
+
ui,
|
|
4654
|
+
forwardEvent,
|
|
4655
|
+
reportError,
|
|
4656
|
+
functionCalls,
|
|
4657
|
+
refreshActions,
|
|
4658
|
+
dropAllActions
|
|
4659
|
+
};
|
|
4660
|
+
}, [ui, copilotkit]);
|
|
4661
|
+
const runtime = (0, react.useMemo)(() => {
|
|
4662
|
+
if (!core) return null;
|
|
4663
|
+
const { manager, dispatcher, forwardEvent, reportError } = core;
|
|
4664
|
+
return {
|
|
4665
|
+
manager,
|
|
4666
|
+
dispatcher,
|
|
4667
|
+
ui: core.ui,
|
|
4668
|
+
forwardEvent,
|
|
4669
|
+
reportError,
|
|
4670
|
+
transport,
|
|
4671
|
+
theme,
|
|
4672
|
+
get config() {
|
|
4673
|
+
return configRef.current ?? { ui: core.ui };
|
|
4674
|
+
},
|
|
4675
|
+
get errorFallback() {
|
|
4676
|
+
return configRef.current?.errorBoundary?.fallback;
|
|
4677
|
+
}
|
|
3334
4678
|
};
|
|
3335
4679
|
}, [
|
|
3336
|
-
|
|
3337
|
-
|
|
3338
|
-
|
|
3339
|
-
a2uiAgentsKey
|
|
4680
|
+
core,
|
|
4681
|
+
transport,
|
|
4682
|
+
theme
|
|
3340
4683
|
]);
|
|
3341
|
-
|
|
4684
|
+
(0, react.useEffect)(() => {
|
|
4685
|
+
if (!core) return;
|
|
4686
|
+
const watched = /* @__PURE__ */ new WeakSet();
|
|
4687
|
+
const agentSubscriptions = [];
|
|
4688
|
+
let envelopeId;
|
|
4689
|
+
const debug = createGenerativeUIDebugSource(core, () => {
|
|
4690
|
+
const latest = configRef.current ?? { ui: core.ui };
|
|
4691
|
+
return {
|
|
4692
|
+
options: envelopeOptionsFor(latest),
|
|
4693
|
+
agentIds: latest.agentIds
|
|
4694
|
+
};
|
|
4695
|
+
});
|
|
4696
|
+
copilotkit.ɵsetGenerativeUIDebugSource(debug.source);
|
|
4697
|
+
const removeEnvelope = () => {
|
|
4698
|
+
if (envelopeId === void 0) return;
|
|
4699
|
+
copilotkit.removeScopedProperties(envelopeId);
|
|
4700
|
+
envelopeId = void 0;
|
|
4701
|
+
};
|
|
4702
|
+
/**
|
|
4703
|
+
* Sets the shared envelope of the run. The action entries of the agents
|
|
4704
|
+
* with a user event under way (see `forwardEvent`) are set again after
|
|
4705
|
+
* it, so they stay the last entries and win for their agents.
|
|
4706
|
+
*/
|
|
4707
|
+
const setEnvelope = (agent, latest) => {
|
|
4708
|
+
removeEnvelope();
|
|
4709
|
+
const run = describeGenerativeUIRun(core, agent.threadId, envelopeOptionsFor(latest));
|
|
4710
|
+
envelopeId = copilotkit.addScopedProperties({
|
|
4711
|
+
properties: { [_copilotkit_shared.COPILOTKIT_FORWARDED_PROPS_KEY]: { ui: run.envelope } },
|
|
4712
|
+
agentIds: latest.agentIds
|
|
4713
|
+
});
|
|
4714
|
+
core.refreshActions();
|
|
4715
|
+
if (!latest.agentIds || latest.agentIds.includes(agent.agentId ?? "")) debug.recordRun({
|
|
4716
|
+
...run,
|
|
4717
|
+
agentId: agent.agentId,
|
|
4718
|
+
threadId: agent.threadId,
|
|
4719
|
+
startedAt: Date.now()
|
|
4720
|
+
});
|
|
4721
|
+
};
|
|
4722
|
+
/**
|
|
4723
|
+
* The tool transport reads the surface activity messages. The markdown
|
|
4724
|
+
* transport reads the ```a2ui fences of the assistant messages, and
|
|
4725
|
+
* builds the surfaces of the thread from them again on each change.
|
|
4726
|
+
* Both give their function calls to the one runner.
|
|
4727
|
+
*/
|
|
4728
|
+
const readMessages = (agent, messages, running) => {
|
|
4729
|
+
const requests = activityFunctionCalls(messages);
|
|
4730
|
+
const { threadId } = agent;
|
|
4731
|
+
if (configRef.current?.transport !== "markdown") ingestMessages(core.manager, agent, messages);
|
|
4732
|
+
else if (threadId) {
|
|
4733
|
+
core.manager.setActiveThread(threadId);
|
|
4734
|
+
const calls = require_MarkdownSurfaces.getMarkdownSurfaceSource(core).sync(threadId, agent.agentId, messages, { running });
|
|
4735
|
+
requests.push(...markdownFunctionCalls(calls));
|
|
4736
|
+
}
|
|
4737
|
+
core.functionCalls.run(agent, requests, messages, running);
|
|
4738
|
+
};
|
|
4739
|
+
const subscription = copilotkit.subscribe({ onAgentRunStarted: ({ agent }) => {
|
|
4740
|
+
core.manager.setActiveThread(agent.threadId);
|
|
4741
|
+
const latest = configRef.current;
|
|
4742
|
+
if (latest) setEnvelope(agent, latest);
|
|
4743
|
+
if (!watched.has(agent)) {
|
|
4744
|
+
watched.add(agent);
|
|
4745
|
+
agentSubscriptions.push(agent.subscribe({
|
|
4746
|
+
onMessagesChanged: ({ messages }) => readMessages(agent, messages, agent.isRunning),
|
|
4747
|
+
onRunFinalized: () => readMessages(agent, agent.messages, false),
|
|
4748
|
+
onRunFailed: () => readMessages(agent, agent.messages, false)
|
|
4749
|
+
}));
|
|
4750
|
+
}
|
|
4751
|
+
readMessages(agent, agent.messages, true);
|
|
4752
|
+
} });
|
|
4753
|
+
return () => {
|
|
4754
|
+
subscription.unsubscribe();
|
|
4755
|
+
for (const s of agentSubscriptions) s.unsubscribe();
|
|
4756
|
+
core.dropAllActions();
|
|
4757
|
+
removeEnvelope();
|
|
4758
|
+
if (copilotkit.ɵgenerativeUIDebugSource === debug.source) copilotkit.ɵsetGenerativeUIDebugSource(void 0);
|
|
4759
|
+
};
|
|
4760
|
+
}, [core, copilotkit]);
|
|
4761
|
+
useGenerativeUIMarkdownContext(copilotkit, core, {
|
|
4762
|
+
enabled: config?.transport === "markdown" && config.sendContext !== false,
|
|
4763
|
+
agentIds: config?.agentIds
|
|
4764
|
+
});
|
|
4765
|
+
return runtime;
|
|
3342
4766
|
}
|
|
3343
4767
|
|
|
3344
4768
|
//#endregion
|
|
@@ -3483,7 +4907,7 @@ function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
|
|
|
3483
4907
|
return value;
|
|
3484
4908
|
}
|
|
3485
4909
|
/** Provide a shared core instance and synchronize runtime, tool, and UI configuration. */
|
|
3486
|
-
const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY_HEADERS, credentials, messageFilter, publicApiKey, publicLicenseKey, licenseToken, properties = EMPTY_PROPERTIES, agents__unsafe_dev_only: agents = EMPTY_AGENTS, selfManagedAgents = EMPTY_AGENTS, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, openGenerativeUI, enableInspector, agentId, showIntelligenceIndicator = true, useSingleEndpoint, onError, a2ui, mcpApps, defaultThrottleMs, debug, learning }) => {
|
|
4910
|
+
const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY_HEADERS, credentials, messageFilter, publicApiKey, publicLicenseKey, licenseToken, properties = EMPTY_PROPERTIES, agents__unsafe_dev_only: agents = EMPTY_AGENTS, selfManagedAgents = EMPTY_AGENTS, renderToolCalls, renderActivityMessages, renderCustomMessages, frontendTools, humanInTheLoop, openGenerativeUI, enableInspector, agentId, showIntelligenceIndicator = true, useSingleEndpoint, onError, a2ui, generativeUI, mcpApps, defaultThrottleMs, debug, learning }) => {
|
|
3487
4911
|
const learningConfig = (0, react.useMemo)(() => toLearningConfig(learning), [learning]);
|
|
3488
4912
|
const [shouldRenderInspector, setShouldRenderInspector] = (0, react.useState)(false);
|
|
3489
4913
|
const [inspectorVisible, setInspectorVisible] = (0, react.useState)(false);
|
|
@@ -3505,6 +4929,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3505
4929
|
const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
|
|
3506
4930
|
const a2uiCatalogProvided = !!a2ui?.catalog;
|
|
3507
4931
|
const a2uiActive = runtimeA2UIEnabled || a2uiCatalogProvided;
|
|
4932
|
+
const generativeUIActive = !!generativeUI?.ui;
|
|
3508
4933
|
const [runtimeLicenseStatus, setRuntimeLicenseStatus] = (0, react.useState)(void 0);
|
|
3509
4934
|
const [runtimeEntitlements, setRuntimeEntitlements] = (0, react.useState)(void 0);
|
|
3510
4935
|
const [runtimeEntitlementRetryPending, setRuntimeEntitlementRetryPending] = (0, react.useState)(false);
|
|
@@ -3558,10 +4983,12 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3558
4983
|
loadingComponent: a2ui?.loadingComponent,
|
|
3559
4984
|
recovery: a2ui?.recovery
|
|
3560
4985
|
}));
|
|
4986
|
+
if (generativeUIActive) renderers.push(require_MarkdownSurfaces.createGenerativeUIActivityRenderer(), require_MarkdownSurfaces.createGenerativeUIFunctionCallActivityRenderer());
|
|
3561
4987
|
return renderers;
|
|
3562
4988
|
}, [
|
|
3563
4989
|
a2uiActive,
|
|
3564
4990
|
openGenUIActive,
|
|
4991
|
+
generativeUIActive,
|
|
3565
4992
|
a2ui,
|
|
3566
4993
|
filteredCatalog,
|
|
3567
4994
|
mcpAppsAllowSameOrigin
|
|
@@ -3728,6 +5155,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3728
5155
|
if (defaultThrottleMs !== void 0) copilotkitRef.current.setDefaultThrottleMs(defaultThrottleMs);
|
|
3729
5156
|
}
|
|
3730
5157
|
const copilotkit = copilotkitRef.current;
|
|
5158
|
+
const generativeUIRuntime = useGenerativeUIRoot(copilotkit, generativeUI);
|
|
3731
5159
|
(0, react.useEffect)(() => {
|
|
3732
5160
|
if (!rawCatalog) return;
|
|
3733
5161
|
if (!(rawCatalog instanceof _copilotkit_a2ui_renderer.Catalog)) return;
|
|
@@ -3966,6 +5394,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3966
5394
|
value: licenseContextValue,
|
|
3967
5395
|
children: [
|
|
3968
5396
|
a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
|
|
5397
|
+
generativeUIActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.GenerativeUIToolCallRenderer, {}),
|
|
3969
5398
|
a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
|
|
3970
5399
|
catalog: filteredCatalog,
|
|
3971
5400
|
includeSchema: a2ui?.includeSchema
|
|
@@ -3974,7 +5403,10 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3974
5403
|
value: inspectorContextValue,
|
|
3975
5404
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(_copilotkit_react_core_v2_context.CopilotKitAgentIdContext.Provider, {
|
|
3976
5405
|
value: agentId,
|
|
3977
|
-
children
|
|
5406
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.GenerativeUIRuntimeContext.Provider, {
|
|
5407
|
+
value: generativeUIRuntime,
|
|
5408
|
+
children
|
|
5409
|
+
})
|
|
3978
5410
|
}), shouldRenderInspector ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspector, {
|
|
3979
5411
|
core: copilotkit,
|
|
3980
5412
|
openRequest: inspectorOpenRequest,
|
|
@@ -3995,7 +5427,7 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3995
5427
|
//#region src/v2/hooks/use-render-custom-messages.tsx
|
|
3996
5428
|
function useRenderCustomMessages() {
|
|
3997
5429
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
3998
|
-
const config = useCopilotChatConfiguration();
|
|
5430
|
+
const config = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
3999
5431
|
if (!config) return null;
|
|
4000
5432
|
const { agentId, threadId } = config;
|
|
4001
5433
|
const customMessageRenderers = copilotkit.renderCustomMessages.filter((renderer) => renderer.agentId === void 0 || renderer.agentId === agentId).sort((a, b) => {
|
|
@@ -4040,7 +5472,7 @@ function useRenderCustomMessages() {
|
|
|
4040
5472
|
//#region src/v2/hooks/use-render-activity-message.tsx
|
|
4041
5473
|
function useRenderActivityMessage() {
|
|
4042
5474
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
4043
|
-
const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
5475
|
+
const agentId = require_MarkdownSurfaces.useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
4044
5476
|
const renderers = copilotkit.renderActivityMessages;
|
|
4045
5477
|
const findRenderer = (0, react.useCallback)((activityType) => {
|
|
4046
5478
|
if (!renderers.length) return null;
|
|
@@ -4398,7 +5830,7 @@ function useRenderTool(config, deps) {
|
|
|
4398
5830
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
4399
5831
|
const depsVersion = useDepsVersion(deps);
|
|
4400
5832
|
(0, react.useEffect)(() => {
|
|
4401
|
-
const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
|
|
5833
|
+
const renderer = config.name === "*" && !config.parameters ? require_MarkdownSurfaces.defineToolCallRenderer({
|
|
4402
5834
|
name: "*",
|
|
4403
5835
|
render: (props) => config.render({
|
|
4404
5836
|
...props,
|
|
@@ -4406,7 +5838,7 @@ function useRenderTool(config, deps) {
|
|
|
4406
5838
|
}),
|
|
4407
5839
|
...config.agentId ? { agentId: config.agentId } : {},
|
|
4408
5840
|
group: config.group
|
|
4409
|
-
}) : defineToolCallRenderer({
|
|
5841
|
+
}) : require_MarkdownSurfaces.defineToolCallRenderer({
|
|
4410
5842
|
name: config.name,
|
|
4411
5843
|
args: config.parameters,
|
|
4412
5844
|
render: (props) => {
|
|
@@ -4572,14 +6004,14 @@ function ToolCallRow({ name, parameters, result, status, appearance, className,
|
|
|
4572
6004
|
const line = appearance === "line";
|
|
4573
6005
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4574
6006
|
"data-copilotkit": true,
|
|
4575
|
-
className: (0, tailwind_merge.twMerge)(
|
|
6007
|
+
className: (0, tailwind_merge.twMerge)(appearance === "card" && "cpk:border-t cpk:border-border", className),
|
|
4576
6008
|
...props,
|
|
4577
6009
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4578
6010
|
type: "button",
|
|
4579
6011
|
"aria-expanded": open,
|
|
4580
6012
|
"aria-controls": detailsId,
|
|
4581
6013
|
onClick: () => setOpen((value) => !value),
|
|
4582
|
-
className: (0, tailwind_merge.twMerge)("cpk:group/row cpk:m-0 cpk:flex cpk:min-w-0 cpk:cursor-pointer cpk:items-center cpk:gap-2 cpk:border-none cpk:bg-transparent cpk:text-left cpk:text-[13px] cpk:text-inherit cpk:transition-colors cpk:hover:bg-accent/60 cpk:focus-visible:outline-2 cpk:focus-visible:-outline-offset-2 cpk:focus-visible:outline-ring", line ? "cpk:-mx-1.5 cpk:w-[calc(100%+0.75rem)] cpk:rounded-md cpk:px-1.5 cpk:py-1" : "cpk:w-full cpk:px-3.5 cpk:py-2"),
|
|
6014
|
+
className: (0, tailwind_merge.twMerge)("cpk:group/row cpk:m-0 cpk:flex cpk:min-w-0 cpk:cursor-pointer cpk:items-center cpk:gap-2 cpk:border-none cpk:bg-transparent cpk:text-left cpk:text-[13px] cpk:text-inherit cpk:transition-colors cpk:hover:bg-accent/60 cpk:focus-visible:outline-2 cpk:focus-visible:-outline-offset-2 cpk:focus-visible:outline-ring", line ? "cpk:-mx-1.5 cpk:w-[calc(100%+0.75rem)] cpk:rounded-md cpk:px-1.5 cpk:py-1" : appearance === "stack" ? "cpk:w-full cpk:px-3.5 cpk:py-2.5" : "cpk:w-full cpk:px-3.5 cpk:py-2"),
|
|
4583
6015
|
children: [
|
|
4584
6016
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusIcon, { status }),
|
|
4585
6017
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
@@ -4619,7 +6051,8 @@ function ToolCallRow({ name, parameters, result, status, appearance, className,
|
|
|
4619
6051
|
*
|
|
4620
6052
|
* Each call is drawn by its registered renderer. CopilotKit's built-in card
|
|
4621
6053
|
* (`useDefaultRenderTool`) draws a compact row inside the card and line
|
|
4622
|
-
* appearances; a custom wildcard renderer draws whatever it
|
|
6054
|
+
* appearances and an open stack; a custom wildcard renderer draws whatever it
|
|
6055
|
+
* draws.
|
|
4623
6056
|
*/
|
|
4624
6057
|
function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isActive = false, className, ...props }) {
|
|
4625
6058
|
const [open, setOpen] = (0, react.useState)(false);
|
|
@@ -4698,11 +6131,6 @@ function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isAc
|
|
|
4698
6131
|
});
|
|
4699
6132
|
}
|
|
4700
6133
|
if (appearance === "stack") {
|
|
4701
|
-
if (calls.length === 1) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4702
|
-
...groupProps,
|
|
4703
|
-
className: (0, tailwind_merge.twMerge)("cpk:py-1", className),
|
|
4704
|
-
children: renderCall(latest)
|
|
4705
|
-
});
|
|
4706
6134
|
const behind = open ? 0 : Math.min(calls.length - 1, 2);
|
|
4707
6135
|
const layer = "cpk:rounded-xl cpk:border cpk:border-border cpk:bg-card cpk:text-card-foreground";
|
|
4708
6136
|
const latestStatus = entryStatus(latest, isActive);
|
|
@@ -4716,68 +6144,88 @@ function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isAc
|
|
|
4716
6144
|
},
|
|
4717
6145
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4718
6146
|
className: "cpk:relative cpk:isolate",
|
|
4719
|
-
children: [
|
|
4720
|
-
|
|
4721
|
-
|
|
4722
|
-
|
|
4723
|
-
|
|
4724
|
-
|
|
4725
|
-
|
|
4726
|
-
|
|
4727
|
-
|
|
4728
|
-
|
|
4729
|
-
"
|
|
4730
|
-
|
|
4731
|
-
|
|
4732
|
-
|
|
4733
|
-
|
|
4734
|
-
|
|
4735
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4736
|
-
|
|
4737
|
-
open: true,
|
|
4738
|
-
className: "cpk:-rotate-90"
|
|
4739
|
-
}),
|
|
4740
|
-
"Collapse"
|
|
4741
|
-
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4742
|
-
className: "cpk:flex cpk:min-w-0 cpk:flex-1 cpk:items-center cpk:gap-2 cpk:animate-[cpk-stack-drop_260ms_cubic-bezier(0.16,1,0.3,1)] cpk:motion-reduce:animate-none",
|
|
4743
|
-
children: [
|
|
4744
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusIcon, { status: latestStatus }),
|
|
4745
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4746
|
-
className: (0, tailwind_merge.twMerge)("cpk:shrink-0 cpk:font-mono cpk:font-medium cpk:text-foreground", latestStatus === "running" && "cpk-shimmer"),
|
|
4747
|
-
children: latest.toolCall.function.name
|
|
4748
|
-
}),
|
|
4749
|
-
latestPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4750
|
-
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-muted-foreground",
|
|
4751
|
-
children: latestPreview
|
|
4752
|
-
})
|
|
4753
|
-
]
|
|
4754
|
-
}, latest.toolCall.id), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
4755
|
-
className: "cpk:ml-2 cpk:inline-flex cpk:shrink-0 cpk:items-center cpk:gap-2 cpk:text-xs cpk:text-muted-foreground",
|
|
4756
|
-
children: [
|
|
6147
|
+
children: [
|
|
6148
|
+
Array.from({ length: behind }, (_, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6149
|
+
"aria-hidden": "true",
|
|
6150
|
+
className: (0, tailwind_merge.twMerge)(layer, "cpk:absolute cpk:inset-0"),
|
|
6151
|
+
style: {
|
|
6152
|
+
transform: `translateY(${(index + 1) * 6}px) scaleX(${1 - (index + 1) * .045})`,
|
|
6153
|
+
zIndex: -1 - index,
|
|
6154
|
+
opacity: 1 - (index + 1) * .28
|
|
6155
|
+
}
|
|
6156
|
+
}, index)),
|
|
6157
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
6158
|
+
type: "button",
|
|
6159
|
+
"aria-expanded": open,
|
|
6160
|
+
"aria-controls": open ? bodyId : void 0,
|
|
6161
|
+
onClick: () => setOpen((value) => !value),
|
|
6162
|
+
className: (0, tailwind_merge.twMerge)("cpk:relative cpk:m-0 cpk:flex cpk:min-w-0 cpk:cursor-pointer cpk:items-center cpk:text-left cpk:transition-colors cpk:focus-visible:outline-2 cpk:focus-visible:outline-ring", open ? "cpk:mb-1.5 cpk:w-full cpk:gap-1.5 cpk:rounded-md cpk:border-none cpk:bg-transparent cpk:p-0 cpk:py-0.5 cpk:text-xs cpk:text-muted-foreground cpk:hover:text-foreground" : (0, tailwind_merge.twMerge)(layer, "cpk:w-full cpk:gap-2 cpk:px-3.5 cpk:py-2.5 cpk:text-[13px] cpk:shadow-[0_1px_2px_rgb(0_0_0/0.04)] cpk:hover:bg-accent")),
|
|
6163
|
+
children: open ? /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
6164
|
+
pluralize(calls.length, "tool call"),
|
|
4757
6165
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FailedCount, { calls }),
|
|
4758
|
-
/* @__PURE__ */ (0, react_jsx_runtime.
|
|
4759
|
-
className: "cpk:
|
|
4760
|
-
children:
|
|
4761
|
-
|
|
4762
|
-
|
|
4763
|
-
|
|
4764
|
-
className: "cpk:rotate-90"
|
|
6166
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6167
|
+
className: "cpk:ml-auto cpk:inline-flex cpk:items-center cpk:gap-1",
|
|
6168
|
+
children: ["Collapse", /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chevron, {
|
|
6169
|
+
open: true,
|
|
6170
|
+
className: "cpk:-rotate-90"
|
|
6171
|
+
})]
|
|
4765
6172
|
})
|
|
4766
|
-
]
|
|
4767
|
-
|
|
4768
|
-
|
|
6173
|
+
] }) : /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6174
|
+
className: "cpk:flex cpk:min-w-0 cpk:flex-1 cpk:items-center cpk:gap-2 cpk:animate-[cpk-stack-drop_260ms_cubic-bezier(0.16,1,0.3,1)] cpk:motion-reduce:animate-none",
|
|
6175
|
+
children: [
|
|
6176
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(StatusIcon, { status: latestStatus }),
|
|
6177
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6178
|
+
className: (0, tailwind_merge.twMerge)("cpk:shrink-0 cpk:font-mono cpk:font-medium cpk:text-foreground", latestStatus === "running" && "cpk-shimmer"),
|
|
6179
|
+
children: latest.toolCall.function.name
|
|
6180
|
+
}),
|
|
6181
|
+
latestPreview && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6182
|
+
className: "cpk:min-w-0 cpk:truncate cpk:font-mono cpk:text-muted-foreground",
|
|
6183
|
+
children: latestPreview
|
|
6184
|
+
}),
|
|
6185
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6186
|
+
className: "cpk:sr-only",
|
|
6187
|
+
children: statusLabels[latestStatus]
|
|
6188
|
+
})
|
|
6189
|
+
]
|
|
6190
|
+
}, latest.toolCall.id), /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("span", {
|
|
6191
|
+
className: "cpk:ml-2 cpk:inline-flex cpk:shrink-0 cpk:items-center cpk:gap-2 cpk:text-xs cpk:text-muted-foreground",
|
|
6192
|
+
children: [
|
|
6193
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(FailedCount, { calls }),
|
|
6194
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6195
|
+
className: "cpk:tabular-nums",
|
|
6196
|
+
children: pluralize(calls.length, "call")
|
|
6197
|
+
}),
|
|
6198
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chevron, {
|
|
6199
|
+
open: false,
|
|
6200
|
+
className: "cpk:rotate-90"
|
|
6201
|
+
})
|
|
6202
|
+
]
|
|
6203
|
+
})] })
|
|
6204
|
+
}),
|
|
6205
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
6206
|
+
"aria-live": "polite",
|
|
6207
|
+
className: "cpk:sr-only",
|
|
6208
|
+
children: open ? "" : `${latest.toolCall.function.name}: ${statusLabels[latestStatus]}`
|
|
6209
|
+
})
|
|
6210
|
+
]
|
|
4769
6211
|
}), open && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4770
6212
|
id: bodyId,
|
|
4771
|
-
className: "cpk:
|
|
4772
|
-
children:
|
|
6213
|
+
className: "cpk:grid cpk:gap-1.5",
|
|
6214
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallGroupContext.Provider, {
|
|
6215
|
+
value: {
|
|
6216
|
+
appearance: "stack",
|
|
6217
|
+
failedIds,
|
|
6218
|
+
active: isActive
|
|
6219
|
+
},
|
|
6220
|
+
children: calls.map((call, index) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6221
|
+
className: (0, tailwind_merge.twMerge)(layer, "cpk:overflow-hidden cpk:shadow-[0_1px_2px_rgb(0_0_0/0.04)] cpk:animate-[cpk-stack-fan_240ms_cubic-bezier(0.16,1,0.3,1)_both] cpk:motion-reduce:animate-none"),
|
|
6222
|
+
style: { animationDelay: `${index * 30}ms` },
|
|
6223
|
+
children: renderCall(call)
|
|
6224
|
+
}, call.toolCall.id))
|
|
6225
|
+
})
|
|
4773
6226
|
})]
|
|
4774
6227
|
});
|
|
4775
6228
|
}
|
|
4776
|
-
if (calls.length === 1) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4777
|
-
...groupProps,
|
|
4778
|
-
className: (0, tailwind_merge.twMerge)("cpk:py-1", className),
|
|
4779
|
-
children: renderCall(latest)
|
|
4780
|
-
});
|
|
4781
6229
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4782
6230
|
...groupProps,
|
|
4783
6231
|
className: (0, tailwind_merge.twMerge)("cpk:my-3 cpk:overflow-hidden cpk:rounded-xl cpk:border cpk:border-border cpk:bg-card cpk:text-card-foreground", className),
|
|
@@ -4800,7 +6248,7 @@ function CopilotChatToolCallGroup({ calls, renderCall, appearance = "card", isAc
|
|
|
4800
6248
|
className: "cpk:ml-auto cpk:flex cpk:shrink-0 cpk:items-center cpk:gap-2 cpk:pl-2 cpk:text-xs cpk:text-muted-foreground",
|
|
4801
6249
|
children: [status === "failed" ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(FailedCount, { calls }) : /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4802
6250
|
className: "cpk:tabular-nums",
|
|
4803
|
-
children: status
|
|
6251
|
+
children: status !== "running" ? statusLabels[status] : done > 0 && `${done} done`
|
|
4804
6252
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Chevron, { open })]
|
|
4805
6253
|
})
|
|
4806
6254
|
]
|
|
@@ -5125,7 +6573,7 @@ function useAgent({ agentId, threadId, runtimeAgentId, updates, throttleMs } = {
|
|
|
5125
6573
|
if (threadId != null && runtimeAgentId == null) throw new Error(`useAgent: \`threadId\` requires \`runtimeAgentId\`. A threadId is written onto a single agent, but an agent resolved by agentId alone is shared, so scoping a thread to it would clobber other useAgent callers. Pass a distinct local \`agentId\` and the runtime agent to route to, e.g. useAgent({ agentId: "chat-1", runtimeAgentId: "${agentId ?? "default"}", threadId }).`);
|
|
5126
6574
|
if (runtimeAgentId != null && threadId == null) throw new Error(`useAgent: \`runtimeAgentId\` requires \`threadId\`. A proxied agent exists to scope a thread to a private instance; without a threadId it behaves like the shared agent while adding a registration and a local agentId to keep unique. Either pass the thread, e.g. useAgent({ agentId: "${agentId ?? "chat-1"}", runtimeAgentId: "${runtimeAgentId}", threadId }), or bind to the agent directly with useAgent({ agentId: "${runtimeAgentId}" }).`);
|
|
5127
6575
|
if (runtimeAgentId != null && agentId == null) throw new Error(`useAgent: \`runtimeAgentId\` requires an explicit \`agentId\`. The proxied agent is registered under \`agentId\`, and the usual fallbacks (chat configuration, then "${_copilotkit_shared.DEFAULT_AGENT_ID}") name agents that already exist — registering over one throws or shadows it. Pick a local id for this hook, e.g. useAgent({ agentId: "chat-1", runtimeAgentId: "${runtimeAgentId}", threadId }).`);
|
|
5128
|
-
const chatConfig = useCopilotChatConfiguration();
|
|
6576
|
+
const chatConfig = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
5129
6577
|
const providerAgentId = (0, _copilotkit_react_core_v2_context.useDefaultAgentId)();
|
|
5130
6578
|
const resolvedAgentId = agentId ?? chatConfig?.agentId ?? providerAgentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
5131
6579
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
@@ -5355,7 +6803,7 @@ function useAgentContext(context) {
|
|
|
5355
6803
|
//#region src/v2/hooks/use-suggestions.tsx
|
|
5356
6804
|
function useSuggestions({ agentId } = {}) {
|
|
5357
6805
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
5358
|
-
const config = useCopilotChatConfiguration();
|
|
6806
|
+
const config = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
5359
6807
|
const providerAgentId = (0, _copilotkit_react_core_v2_context.useDefaultAgentId)();
|
|
5360
6808
|
const resolvedAgentId = (0, react.useMemo)(() => agentId ?? config?.agentId ?? providerAgentId ?? _copilotkit_shared.DEFAULT_AGENT_ID, [
|
|
5361
6809
|
agentId,
|
|
@@ -5413,7 +6861,7 @@ function useSuggestions({ agentId } = {}) {
|
|
|
5413
6861
|
//#region src/v2/hooks/use-configure-suggestions.tsx
|
|
5414
6862
|
function useConfigureSuggestions(config, deps) {
|
|
5415
6863
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
5416
|
-
const chatConfig = useCopilotChatConfiguration();
|
|
6864
|
+
const chatConfig = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
5417
6865
|
const extraDeps = deps ?? [];
|
|
5418
6866
|
const resolvedConsumerAgentId = (0, react.useMemo)(() => chatConfig?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID, [chatConfig?.agentId]);
|
|
5419
6867
|
const rawConsumerAgentId = (0, react.useMemo)(() => config ? config.consumerAgentId : void 0, [config]);
|
|
@@ -6252,7 +7700,7 @@ function useLearnFromUserAction() {
|
|
|
6252
7700
|
* ```
|
|
6253
7701
|
*/
|
|
6254
7702
|
function useLearnFromUserActionInCurrentThread() {
|
|
6255
|
-
const config = useCopilotChatConfiguration();
|
|
7703
|
+
const config = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
6256
7704
|
const learnFromUserAction = useLearnFromUserAction();
|
|
6257
7705
|
return (0, react.useCallback)(async (input) => {
|
|
6258
7706
|
const threadId = config?.threadId;
|
|
@@ -6622,7 +8070,7 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
6622
8070
|
* Intelligence runtimes.
|
|
6623
8071
|
*/
|
|
6624
8072
|
function useLearningContainersInCurrentThread({ learningContainers }) {
|
|
6625
|
-
const threadId = useCopilotChatConfiguration()?.threadId;
|
|
8073
|
+
const threadId = require_MarkdownSurfaces.useCopilotChatConfiguration()?.threadId;
|
|
6626
8074
|
if (!threadId) throw new Error("useLearningContainersInCurrentThread must be used within a thread context (no active threadId). Wrap the component in <CopilotChat>, <CopilotSidebar>, or <CopilotChatConfigurationProvider>, or use `useLearningContainers()` and pass `threadId` explicitly.");
|
|
6627
8075
|
useLearningContainers({
|
|
6628
8076
|
threadId,
|
|
@@ -6974,7 +8422,7 @@ function InspectorKiteIcon({ className, ...props }) {
|
|
|
6974
8422
|
});
|
|
6975
8423
|
}
|
|
6976
8424
|
function CopilotChatInspectorButton({ title, className, onClick, onPointerDown, onPointerEnter, onPointerLeave, onKeyDown, disabled, ...props }) {
|
|
6977
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
8425
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
6978
8426
|
const { isInspectorEnabled } = useCopilotKitInspector();
|
|
6979
8427
|
const hidden = useInspectorShortcutsHidden();
|
|
6980
8428
|
const [open, setOpen] = (0, react.useState)(false);
|
|
@@ -7445,7 +8893,7 @@ function WorkText({ messageId, children }) {
|
|
|
7445
8893
|
* assistant message subscribe to chat configuration changes.
|
|
7446
8894
|
*/
|
|
7447
8895
|
function BoundInspectorButton({ inspectorButton, messageId, openInspector, ...props }) {
|
|
7448
|
-
const chatConfiguration = useCopilotChatConfiguration();
|
|
8896
|
+
const chatConfiguration = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
7449
8897
|
return renderSlot(inspectorButton, CopilotChatAssistantMessage.InspectorButton, {
|
|
7450
8898
|
...props,
|
|
7451
8899
|
onClick: () => openInspector({
|
|
@@ -7490,7 +8938,7 @@ function nextFocusable(element, skip) {
|
|
|
7490
8938
|
* control after the thumb, and Enter or Escape inside it returns to the thumb.
|
|
7491
8939
|
*/
|
|
7492
8940
|
function FeedbackCommentPopover({ feedbackComment, comment, savedComment, rating, anchor, messageId }) {
|
|
7493
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
8941
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7494
8942
|
const contentRef = (0, react.useRef)(null);
|
|
7495
8943
|
const focusInside = () => contentRef.current?.contains(document.activeElement) ?? false;
|
|
7496
8944
|
const { focusRequest, takeFocusRequest, inputRef } = comment;
|
|
@@ -7560,7 +9008,7 @@ function FeedbackCommentPopover({ feedbackComment, comment, savedComment, rating
|
|
|
7560
9008
|
});
|
|
7561
9009
|
}
|
|
7562
9010
|
function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, onThumbsUp, onThumbsDown, onReadAloud, onRegenerate, additionalToolbarItems, toolbarVisible = true, markdownRenderer, toolbar, copyButton, inspectorButton, thumbsUpButton, thumbsDownButton, readAloudButton, regenerateButton, feedbackComment: feedbackCommentSlot, toolCallsView, children, className, ...props }) {
|
|
7563
|
-
useKatexStyles();
|
|
9011
|
+
require_MarkdownSurfaces.useKatexStyles();
|
|
7564
9012
|
const { isInspectorEnabled, openInspector } = useCopilotKitInspector();
|
|
7565
9013
|
const shortcutsHidden = useInspectorShortcutsHidden();
|
|
7566
9014
|
const showInspectorShortcut = isInspectorEnabled && !shortcutsHidden;
|
|
@@ -7635,7 +9083,10 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7635
9083
|
}
|
|
7636
9084
|
};
|
|
7637
9085
|
};
|
|
7638
|
-
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, {
|
|
9086
|
+
const boundMarkdownRenderer = renderSlot(markdownRenderer, CopilotChatAssistantMessage.MarkdownRenderer, {
|
|
9087
|
+
content: message.content || "",
|
|
9088
|
+
messageId: message.id
|
|
9089
|
+
});
|
|
7639
9090
|
const boundCopyButton = renderSlot(copyButton, CopilotChatAssistantMessage.CopyButton, { onClick: async () => {
|
|
7640
9091
|
if (message.content) return await (0, _copilotkit_shared.copyToClipboard)(message.content);
|
|
7641
9092
|
return false;
|
|
@@ -7745,11 +9196,19 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7745
9196
|
});
|
|
7746
9197
|
}
|
|
7747
9198
|
(function(_CopilotChatAssistantMessage) {
|
|
7748
|
-
_CopilotChatAssistantMessage.MarkdownRenderer = ({ content, className, ...props }) =>
|
|
7749
|
-
|
|
7750
|
-
|
|
7751
|
-
|
|
7752
|
-
|
|
9199
|
+
_CopilotChatAssistantMessage.MarkdownRenderer = ({ content, className, messageId, ...props }) => {
|
|
9200
|
+
if (require_MarkdownSurfaces.useGenerativeUIRuntime()?.transport === "markdown" && messageId !== void 0) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.MarkdownSurfaces, {
|
|
9201
|
+
content: content ?? "",
|
|
9202
|
+
messageId,
|
|
9203
|
+
className,
|
|
9204
|
+
...props
|
|
9205
|
+
});
|
|
9206
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(streamdown.Streamdown, {
|
|
9207
|
+
className,
|
|
9208
|
+
...props,
|
|
9209
|
+
children: content ?? ""
|
|
9210
|
+
});
|
|
9211
|
+
};
|
|
7753
9212
|
_CopilotChatAssistantMessage.Toolbar = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7754
9213
|
"data-testid": "copilot-assistant-toolbar",
|
|
7755
9214
|
className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:bg-transparent cpk:flex cpk:items-center cpk:-ml-[5px] cpk:-mt-[0px]", className),
|
|
@@ -7779,7 +9238,7 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7779
9238
|
});
|
|
7780
9239
|
};
|
|
7781
9240
|
_CopilotChatAssistantMessage.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
7782
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9241
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7783
9242
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
7784
9243
|
const timerRef = (0, react.useRef)(null);
|
|
7785
9244
|
(0, react.useEffect)(() => {
|
|
@@ -7810,7 +9269,7 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7810
9269
|
};
|
|
7811
9270
|
_CopilotChatAssistantMessage.InspectorButton = CopilotChatInspectorButton;
|
|
7812
9271
|
_CopilotChatAssistantMessage.ThumbsUpButton = ({ title, ...props }) => {
|
|
7813
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9272
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7814
9273
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
7815
9274
|
"data-testid": "copilot-thumbs-up-button",
|
|
7816
9275
|
title: title || labels.assistantMessageToolbarThumbsUpLabel,
|
|
@@ -7822,7 +9281,7 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7822
9281
|
});
|
|
7823
9282
|
};
|
|
7824
9283
|
_CopilotChatAssistantMessage.ThumbsDownButton = ({ title, ...props }) => {
|
|
7825
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9284
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7826
9285
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
7827
9286
|
"data-testid": "copilot-thumbs-down-button",
|
|
7828
9287
|
title: title || labels.assistantMessageToolbarThumbsDownLabel,
|
|
@@ -7834,7 +9293,7 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7834
9293
|
});
|
|
7835
9294
|
};
|
|
7836
9295
|
_CopilotChatAssistantMessage.FeedbackComment = ({ value, savedComment, inputRef, onChange, onSubmit, onEditingChange, onLeave, className }) => {
|
|
7837
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9296
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7838
9297
|
const changed = value.trim() !== savedComment;
|
|
7839
9298
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("form", {
|
|
7840
9299
|
"data-testid": "copilot-feedback-comment",
|
|
@@ -7869,7 +9328,7 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7869
9328
|
});
|
|
7870
9329
|
};
|
|
7871
9330
|
_CopilotChatAssistantMessage.ReadAloudButton = ({ title, ...props }) => {
|
|
7872
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9331
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7873
9332
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
7874
9333
|
"data-testid": "copilot-read-aloud-button",
|
|
7875
9334
|
title: title || labels.assistantMessageToolbarReadAloudLabel,
|
|
@@ -7878,7 +9337,7 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, isLatest, o
|
|
|
7878
9337
|
});
|
|
7879
9338
|
};
|
|
7880
9339
|
_CopilotChatAssistantMessage.RegenerateButton = ({ title, ...props }) => {
|
|
7881
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9340
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7882
9341
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
7883
9342
|
"data-testid": "copilot-regenerate-button",
|
|
7884
9343
|
title: title || labels.assistantMessageToolbarRegenerateLabel,
|
|
@@ -7900,7 +9359,13 @@ var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
|
|
|
7900
9359
|
|
|
7901
9360
|
//#endregion
|
|
7902
9361
|
//#region src/v2/components/chat/Lightbox.tsx
|
|
9362
|
+
/**
|
|
9363
|
+
* A full-screen preview portalled to `document.body`. It closes on Escape, a
|
|
9364
|
+
* click on the backdrop, or its close button, which is named by
|
|
9365
|
+
* `labels.attachmentPreviewCloseButtonLabel`.
|
|
9366
|
+
*/
|
|
7903
9367
|
function Lightbox({ onClose, children }) {
|
|
9368
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
7904
9369
|
(0, react.useEffect)(() => {
|
|
7905
9370
|
const handleKey = (e) => {
|
|
7906
9371
|
if (e.key === "Escape") onClose();
|
|
@@ -7915,7 +9380,7 @@ function Lightbox({ onClose, children }) {
|
|
|
7915
9380
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
7916
9381
|
onClick: onClose,
|
|
7917
9382
|
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",
|
|
7918
|
-
"aria-label":
|
|
9383
|
+
"aria-label": labels.attachmentPreviewCloseButtonLabel,
|
|
7919
9384
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, { className: "cpk:w-5 cpk:h-5" })
|
|
7920
9385
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7921
9386
|
onClick: (e) => e.stopPropagation(),
|
|
@@ -8169,7 +9634,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
8169
9634
|
})] });
|
|
8170
9635
|
};
|
|
8171
9636
|
_CopilotChatUserMessage.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
8172
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9637
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
8173
9638
|
const [copied, setCopied] = (0, react.useState)(false);
|
|
8174
9639
|
const handleClick = async (event) => {
|
|
8175
9640
|
let success = false;
|
|
@@ -8189,7 +9654,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
8189
9654
|
});
|
|
8190
9655
|
};
|
|
8191
9656
|
_CopilotChatUserMessage.EditButton = ({ className, title, ...props }) => {
|
|
8192
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9657
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
8193
9658
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolbarButton, {
|
|
8194
9659
|
"data-testid": "copilot-edit-button",
|
|
8195
9660
|
title: title || labels.userMessageToolbarEditMessageLabel,
|
|
@@ -8199,7 +9664,7 @@ function CopilotChatUserMessage({ message, onEditMessage, branchIndex, numberOfB
|
|
|
8199
9664
|
});
|
|
8200
9665
|
};
|
|
8201
9666
|
_CopilotChatUserMessage.BranchNavigation = ({ className, currentBranch = 0, numberOfBranches = 1, onSwitchToBranch, message, ...props }) => {
|
|
8202
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
9667
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
8203
9668
|
if (!numberOfBranches || numberOfBranches <= 1 || !onSwitchToBranch) return null;
|
|
8204
9669
|
const canGoPrev = currentBranch > 0;
|
|
8205
9670
|
const canGoNext = currentBranch < numberOfBranches - 1;
|
|
@@ -8268,7 +9733,14 @@ function formatDuration$1(seconds) {
|
|
|
8268
9733
|
if (secs === 0) return `${mins} minute${mins > 1 ? "s" : ""}`;
|
|
8269
9734
|
return `${mins}m ${secs}s`;
|
|
8270
9735
|
}
|
|
9736
|
+
/**
|
|
9737
|
+
* A reasoning message as a collapsible block. While the model reasons it is
|
|
9738
|
+
* open and the header shows `labels.reasoningMessageThinkingLabel`; when
|
|
9739
|
+
* streaming ends it collapses and the header reads "Thought for …". The
|
|
9740
|
+
* `header` slot also receives `elapsedSeconds`.
|
|
9741
|
+
*/
|
|
8271
9742
|
function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: isLatestProp, header, contentView, toggle, children, className, ...props }) {
|
|
9743
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
8272
9744
|
const isLatest = isLatestProp ?? messages?.[messages.length - 1]?.id === message.id;
|
|
8273
9745
|
const isStreaming = !!(isRunning && isLatest);
|
|
8274
9746
|
const hasContent = !!(message.content && message.content.length > 0);
|
|
@@ -8298,12 +9770,13 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: i
|
|
|
8298
9770
|
userToggledRef.current = true;
|
|
8299
9771
|
setIsOpen((prev) => !prev);
|
|
8300
9772
|
} : void 0;
|
|
8301
|
-
const label = isStreaming ?
|
|
9773
|
+
const label = isStreaming ? labels.reasoningMessageThinkingLabel : `Thought for ${formatDuration$1(elapsed)}`;
|
|
8302
9774
|
const boundHeader = renderSlot(header, CopilotChatReasoningMessage.Header, {
|
|
8303
9775
|
isOpen,
|
|
8304
9776
|
label,
|
|
8305
9777
|
hasContent,
|
|
8306
9778
|
isStreaming,
|
|
9779
|
+
elapsedSeconds: elapsed,
|
|
8307
9780
|
onClick: handleToggle
|
|
8308
9781
|
});
|
|
8309
9782
|
const boundContent = renderSlot(contentView, CopilotChatReasoningMessage.Content, {
|
|
@@ -8335,7 +9808,7 @@ function CopilotChatReasoningMessage({ message, messages, isRunning, isLatest: i
|
|
|
8335
9808
|
});
|
|
8336
9809
|
}
|
|
8337
9810
|
(function(_CopilotChatReasoningMessage) {
|
|
8338
|
-
_CopilotChatReasoningMessage.Header = ({ isOpen, label = "Thoughts", hasContent, isStreaming, className, children: headerChildren, ...headerProps }) => {
|
|
9811
|
+
_CopilotChatReasoningMessage.Header = ({ isOpen, label = "Thoughts", hasContent, isStreaming, elapsedSeconds: _elapsedSeconds, className, children: headerChildren, ...headerProps }) => {
|
|
8339
9812
|
const isExpandable = !!hasContent;
|
|
8340
9813
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
8341
9814
|
type: "button",
|
|
@@ -8820,7 +10293,7 @@ const isToolCallLikeMessage = (m) => {
|
|
|
8820
10293
|
function IntelligenceIndicator(props) {
|
|
8821
10294
|
const { message, agentId, label = "CopilotKit Intelligence", intelligenceIndicator } = props;
|
|
8822
10295
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
8823
|
-
const config = useCopilotChatConfiguration();
|
|
10296
|
+
const config = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
8824
10297
|
const { agent } = useAgent({
|
|
8825
10298
|
agentId,
|
|
8826
10299
|
updates: [UseAgentUpdate.OnRunStatusChanged, UseAgentUpdate.OnMessagesChanged]
|
|
@@ -9076,7 +10549,7 @@ function CopilotChatMessageView({ messages = [], assistantMessage, userMessage,
|
|
|
9076
10549
|
const renderCustomMessage = useRenderCustomMessages();
|
|
9077
10550
|
const { renderActivityMessage } = useRenderActivityMessage();
|
|
9078
10551
|
const { copilotkit, showIntelligenceIndicator = true } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
9079
|
-
const config = useCopilotChatConfiguration();
|
|
10552
|
+
const config = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
9080
10553
|
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
9081
10554
|
(0, react.useEffect)(() => {
|
|
9082
10555
|
if (!config?.agentId) return;
|
|
@@ -9611,7 +11084,12 @@ CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
|
|
|
9611
11084
|
|
|
9612
11085
|
//#endregion
|
|
9613
11086
|
//#region src/v2/components/chat/CopilotChatAttachmentQueue.tsx
|
|
11087
|
+
/**
|
|
11088
|
+
* The attachments queued in the composer, each with a preview and a remove
|
|
11089
|
+
* button named by `labels.attachmentRemoveButtonLabel`.
|
|
11090
|
+
*/
|
|
9614
11091
|
const CopilotChatAttachmentQueue = ({ attachments, onRemoveAttachment, className }) => {
|
|
11092
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
9615
11093
|
if (attachments.length === 0) return null;
|
|
9616
11094
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9617
11095
|
"data-testid": "copilot-attachment-queue",
|
|
@@ -9626,7 +11104,7 @@ const CopilotChatAttachmentQueue = ({ attachments, onRemoveAttachment, className
|
|
|
9626
11104
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9627
11105
|
onClick: () => onRemoveAttachment(attachment.id),
|
|
9628
11106
|
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"),
|
|
9629
|
-
"aria-label":
|
|
11107
|
+
"aria-label": labels.attachmentRemoveButtonLabel,
|
|
9630
11108
|
children: "✕"
|
|
9631
11109
|
})
|
|
9632
11110
|
]
|
|
@@ -9682,7 +11160,13 @@ function AudioPreview({ attachment }) {
|
|
|
9682
11160
|
})]
|
|
9683
11161
|
});
|
|
9684
11162
|
}
|
|
11163
|
+
/**
|
|
11164
|
+
* A video thumbnail with a play button, named by
|
|
11165
|
+
* `labels.attachmentPlayVideoButtonLabel`, that opens the full player in a
|
|
11166
|
+
* lightbox.
|
|
11167
|
+
*/
|
|
9685
11168
|
function VideoPreview({ attachment }) {
|
|
11169
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
9686
11170
|
const src = (0, _copilotkit_shared.getSourceUrl)(attachment.source);
|
|
9687
11171
|
const { thumbnailRef, vtName, open, openLightbox, closeLightbox } = useLightbox();
|
|
9688
11172
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [
|
|
@@ -9703,7 +11187,7 @@ function VideoPreview({ attachment }) {
|
|
|
9703
11187
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
9704
11188
|
onClick: openLightbox,
|
|
9705
11189
|
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",
|
|
9706
|
-
"aria-label":
|
|
11190
|
+
"aria-label": labels.attachmentPlayVideoButtonLabel,
|
|
9707
11191
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9708
11192
|
className: "cpk:w-8 cpk:h-8 cpk:rounded-full cpk:bg-black/60 cpk:flex cpk:items-center cpk:justify-center",
|
|
9709
11193
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.Play, { className: "cpk:w-4 cpk:h-4 cpk:text-white cpk:ml-0.5" })
|
|
@@ -9983,7 +11467,7 @@ function DropOverlay() {
|
|
|
9983
11467
|
});
|
|
9984
11468
|
}
|
|
9985
11469
|
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, isConnecting = false, hasExplicitThreadId = false, disclaimer, intelligenceIndicator, children, className, ...props }) {
|
|
9986
|
-
const configuredThreadId = useCopilotChatConfiguration()?.threadId;
|
|
11470
|
+
const configuredThreadId = require_MarkdownSurfaces.useCopilotChatConfiguration()?.threadId;
|
|
9987
11471
|
const [fallbackThreadId, setFallbackThreadId] = (0, react.useState)(messages[0]?.id);
|
|
9988
11472
|
const previousMessageIds = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
9989
11473
|
(0, react.useEffect)(() => {
|
|
@@ -10419,7 +11903,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
10419
11903
|
});
|
|
10420
11904
|
};
|
|
10421
11905
|
_CopilotChatView.ScrollToBottomButton = ({ className, ...props }) => {
|
|
10422
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
11906
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
10423
11907
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Button, {
|
|
10424
11908
|
"data-testid": "copilot-scroll-to-bottom",
|
|
10425
11909
|
variant: "outline",
|
|
@@ -10435,7 +11919,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
10435
11919
|
...props
|
|
10436
11920
|
});
|
|
10437
11921
|
_CopilotChatView.WelcomeMessage = ({ className, ...props }) => {
|
|
10438
|
-
const labels = useCopilotChatConfiguration()?.labels ?? CopilotChatDefaultLabels;
|
|
11922
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
10439
11923
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("h1", {
|
|
10440
11924
|
className: cn("cpk:text-xl cpk:sm:text-2xl cpk:font-medium cpk:text-foreground cpk:text-center", className),
|
|
10441
11925
|
...props,
|
|
@@ -10685,8 +12169,8 @@ function useInspectorThreadOverride(args) {
|
|
|
10685
12169
|
|
|
10686
12170
|
//#endregion
|
|
10687
12171
|
//#region src/v2/components/chat/CopilotChat.tsx
|
|
10688
|
-
function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
10689
|
-
const existingConfig = useCopilotChatConfiguration();
|
|
12172
|
+
function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, generativeUISurface, ...props }) {
|
|
12173
|
+
const existingConfig = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
10690
12174
|
const inspector = useCopilotKitInspector();
|
|
10691
12175
|
const inspectorContextValue = (0, react.useMemo)(() => ({
|
|
10692
12176
|
...inspector,
|
|
@@ -10790,6 +12274,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
10790
12274
|
const pendingRunActivityReconnectRef = (0, react.useRef)(false);
|
|
10791
12275
|
const runActivityReconnectGenerationRef = (0, react.useRef)(0);
|
|
10792
12276
|
const activeLocalRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
12277
|
+
const observedLocalRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
10793
12278
|
const recentlyLocalRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
10794
12279
|
const activeWakeRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
10795
12280
|
const recentlyWakeRunIdsRef = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
@@ -10821,7 +12306,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
10821
12306
|
}, []);
|
|
10822
12307
|
const isLocalActiveRunActivity = (0, react.useCallback)((notification) => {
|
|
10823
12308
|
if (notification.agentId && notification.agentId !== resolvedAgentId) return false;
|
|
10824
|
-
if (!notification.runId || !activeLocalRunIdsRef.current.has(notification.runId) && !recentlyLocalRunIdsRef.current.has(notification.runId)) return false;
|
|
12309
|
+
if (!notification.runId || !activeLocalRunIdsRef.current.has(notification.runId) && !observedLocalRunIdsRef.current.has(notification.runId) && !recentlyLocalRunIdsRef.current.has(notification.runId)) return false;
|
|
10825
12310
|
const eventType = notification.eventType.toUpperCase();
|
|
10826
12311
|
return eventType === "RUN_STARTED" || eventType === "RUN_FINISHED" || eventType === "RUN_ERROR";
|
|
10827
12312
|
}, [resolvedAgentId]);
|
|
@@ -11020,6 +12505,16 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11020
12505
|
pendingWakeRunIdRef.current = notification.runId;
|
|
11021
12506
|
startRunActivityReconnectRef.current?.(generation);
|
|
11022
12507
|
});
|
|
12508
|
+
const observedLocalRunIds = observedLocalRunIdsRef.current;
|
|
12509
|
+
const localRunSubscription = agent.subscribe({
|
|
12510
|
+
onRunInitialized: ({ input }) => {
|
|
12511
|
+
observedLocalRunIds.add(input.runId);
|
|
12512
|
+
},
|
|
12513
|
+
onRunFinalized: ({ input }) => {
|
|
12514
|
+
observedLocalRunIds.delete(input.runId);
|
|
12515
|
+
rememberRecentlyLocalRunId(input.runId);
|
|
12516
|
+
}
|
|
12517
|
+
});
|
|
11023
12518
|
return () => {
|
|
11024
12519
|
detached = true;
|
|
11025
12520
|
pendingRunActivityReconnectRef.current = false;
|
|
@@ -11032,6 +12527,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11032
12527
|
if (wakeReconnectActive) agent.detachActiveRun().catch(() => {});
|
|
11033
12528
|
activeWakeRunIdsRef.current.clear();
|
|
11034
12529
|
subscription.unsubscribe();
|
|
12530
|
+
localRunSubscription.unsubscribe();
|
|
11035
12531
|
if (ownsStandaloneStore) {
|
|
11036
12532
|
threadStore.setContext(null);
|
|
11037
12533
|
threadStore.stop();
|
|
@@ -11050,6 +12546,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11050
12546
|
copilotkit.threadEndpoints?.realtimeMetadata,
|
|
11051
12547
|
standaloneRunActivityStore,
|
|
11052
12548
|
isLocalActiveRunActivity,
|
|
12549
|
+
rememberRecentlyLocalRunId,
|
|
11053
12550
|
rememberRecentlyWakeRunId
|
|
11054
12551
|
]);
|
|
11055
12552
|
const waitForActiveRunToSettle = (0, react.useCallback)(async () => {
|
|
@@ -11264,8 +12761,8 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11264
12761
|
return () => clearTimeout(timer);
|
|
11265
12762
|
}
|
|
11266
12763
|
}, [transcriptionError]);
|
|
11267
|
-
const stableMessageView = useShallowStableRef(typeof providedMessageView === "string" ? { className: providedMessageView } : providedMessageView);
|
|
11268
|
-
const stableSuggestionView = useShallowStableRef(providedSuggestionView);
|
|
12764
|
+
const stableMessageView = require_MarkdownSurfaces.useShallowStableRef(typeof providedMessageView === "string" ? { className: providedMessageView } : providedMessageView);
|
|
12765
|
+
const stableSuggestionView = require_MarkdownSurfaces.useShallowStableRef(providedSuggestionView);
|
|
11269
12766
|
const handleAddFile = (0, react.useCallback)(() => {
|
|
11270
12767
|
setTimeout(() => {
|
|
11271
12768
|
fileInputRef.current?.click();
|
|
@@ -11326,7 +12823,7 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11326
12823
|
isConnecting,
|
|
11327
12824
|
hasExplicitThreadId
|
|
11328
12825
|
});
|
|
11329
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
12826
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.CopilotChatConfigurationProvider, {
|
|
11330
12827
|
agentId: resolvedAgentId,
|
|
11331
12828
|
threadId: resolvedThreadId,
|
|
11332
12829
|
hasExplicitThreadId,
|
|
@@ -11364,7 +12861,10 @@ function CopilotChat({ agentId, threadId, labels, inspectorTools, chatView, isMo
|
|
|
11364
12861
|
value: lastUserMessageState,
|
|
11365
12862
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitInspectorContextProvider, {
|
|
11366
12863
|
value: inspectorContextValue,
|
|
11367
|
-
children:
|
|
12864
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.GenerativeUIChatSlotContext.Provider, {
|
|
12865
|
+
value: generativeUISurface,
|
|
12866
|
+
children: RenderedChatView
|
|
12867
|
+
})
|
|
11368
12868
|
})
|
|
11369
12869
|
})
|
|
11370
12870
|
]
|
|
@@ -11395,8 +12895,8 @@ const ICON_WRAPPER_BASE = "cpk:pointer-events-none cpk:absolute cpk:inset-0 cpk:
|
|
|
11395
12895
|
const BUTTON_BASE_CLASSES = cn("copilotKitButton", "cpk:fixed cpk:bottom-6 cpk:right-6 cpk:z-[1100] cpk:flex cpk:h-14 cpk:w-14 cpk:items-center cpk:justify-center", "cpk:rounded-full cpk:border cpk:border-primary cpk:bg-primary cpk:text-primary-foreground", "cpk:shadow-sm cpk:transition-all cpk:duration-200 cpk:ease-out", "cpk:hover:scale-[1.04] cpk:hover:shadow-md", "cpk:cursor-pointer", "cpk:active:scale-[0.96]", "cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-primary/50 cpk:focus-visible:ring-offset-2 cpk:focus-visible:ring-offset-background", "cpk:disabled:pointer-events-none cpk:disabled:opacity-60");
|
|
11396
12896
|
const CopilotChatToggleButton = react.default.forwardRef(function CopilotChatToggleButton({ openIcon, closeIcon, className, ...buttonProps }, ref) {
|
|
11397
12897
|
const { onClick, type, disabled, ...restProps } = buttonProps;
|
|
11398
|
-
const configuration = useCopilotChatConfiguration();
|
|
11399
|
-
const labels = configuration?.labels ?? CopilotChatDefaultLabels;
|
|
12898
|
+
const configuration = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
12899
|
+
const labels = configuration?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
11400
12900
|
const [fallbackOpen, setFallbackOpen] = (0, react.useState)(false);
|
|
11401
12901
|
const isOpen = configuration?.isModalOpen ?? fallbackOpen;
|
|
11402
12902
|
const setModalOpen = configuration?.setModalOpen ?? setFallbackOpen;
|
|
@@ -11512,8 +13012,8 @@ function useIsMobileViewport() {
|
|
|
11512
13012
|
return isMobile;
|
|
11513
13013
|
}
|
|
11514
13014
|
function CopilotModalHeader({ title, titleContent, closeButton, drawerLauncher, children, className, ...rest }) {
|
|
11515
|
-
const configuration = useCopilotChatConfiguration();
|
|
11516
|
-
const fallbackTitle = configuration?.labels.modalHeaderTitle ?? CopilotChatDefaultLabels.modalHeaderTitle;
|
|
13015
|
+
const configuration = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
13016
|
+
const fallbackTitle = configuration?.labels.modalHeaderTitle ?? require_MarkdownSurfaces.CopilotChatDefaultLabels.modalHeaderTitle;
|
|
11517
13017
|
const resolvedTitle = title ?? fallbackTitle;
|
|
11518
13018
|
const isMobile = useIsMobileViewport();
|
|
11519
13019
|
const drawerRegistered = (configuration?.drawerRegistered ?? false) && isMobile;
|
|
@@ -11568,28 +13068,34 @@ CopilotModalHeader.displayName = "CopilotModalHeader";
|
|
|
11568
13068
|
...props,
|
|
11569
13069
|
children
|
|
11570
13070
|
});
|
|
11571
|
-
_CopilotModalHeader.CloseButton = ({ className, ...props }) =>
|
|
11572
|
-
|
|
11573
|
-
|
|
11574
|
-
|
|
11575
|
-
|
|
11576
|
-
|
|
11577
|
-
|
|
11578
|
-
|
|
11579
|
-
|
|
11580
|
-
|
|
11581
|
-
|
|
11582
|
-
|
|
11583
|
-
|
|
11584
|
-
|
|
11585
|
-
|
|
11586
|
-
|
|
11587
|
-
|
|
11588
|
-
|
|
11589
|
-
|
|
11590
|
-
"
|
|
11591
|
-
|
|
11592
|
-
|
|
13071
|
+
_CopilotModalHeader.CloseButton = ({ className, ...props }) => {
|
|
13072
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
13073
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
13074
|
+
type: "button",
|
|
13075
|
+
"data-testid": "copilot-close-button",
|
|
13076
|
+
className: cn("cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer", "cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring", className),
|
|
13077
|
+
"aria-label": labels.modalHeaderCloseButtonLabel,
|
|
13078
|
+
...props,
|
|
13079
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.X, {
|
|
13080
|
+
className: "cpk:h-4 cpk:w-4",
|
|
13081
|
+
"aria-hidden": "true"
|
|
13082
|
+
})
|
|
13083
|
+
});
|
|
13084
|
+
};
|
|
13085
|
+
_CopilotModalHeader.DrawerLauncher = ({ className, ...props }) => {
|
|
13086
|
+
const labels = require_MarkdownSurfaces.useCopilotChatConfiguration()?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
13087
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
13088
|
+
type: "button",
|
|
13089
|
+
"data-testid": "copilot-threads-drawer-launcher",
|
|
13090
|
+
className: cn("cpk:inline-flex cpk:size-8 cpk:items-center cpk:justify-center cpk:rounded-full cpk:text-muted-foreground cpk:transition cpk:cursor-pointer", "cpk:hover:bg-muted cpk:hover:text-foreground cpk:focus-visible:outline-none cpk:focus-visible:ring-2 cpk:focus-visible:ring-ring", className),
|
|
13091
|
+
"aria-label": labels.modalHeaderThreadsButtonLabel,
|
|
13092
|
+
...props,
|
|
13093
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.PanelLeftOpen, {
|
|
13094
|
+
className: "cpk:h-4 cpk:w-4",
|
|
13095
|
+
"aria-hidden": "true"
|
|
13096
|
+
})
|
|
13097
|
+
});
|
|
13098
|
+
};
|
|
11593
13099
|
})(CopilotModalHeader || (CopilotModalHeader = {}));
|
|
11594
13100
|
CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
|
|
11595
13101
|
CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
|
|
@@ -11599,6 +13105,10 @@ CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLaunch
|
|
|
11599
13105
|
//#region src/v2/components/chat/CopilotSidebarView.tsx
|
|
11600
13106
|
const DEFAULT_SIDEBAR_WIDTH = 480;
|
|
11601
13107
|
const SIDEBAR_TRANSITION_MS = 260;
|
|
13108
|
+
/**
|
|
13109
|
+
* The chat in a side panel: a `complementary` region named by
|
|
13110
|
+
* `labels.sidebarLabel`, with a header, the chat view and a toggle button.
|
|
13111
|
+
*/
|
|
11602
13112
|
function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
|
|
11603
13113
|
const { open, onOpenChange } = useModalOpenControl();
|
|
11604
13114
|
const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
|
|
@@ -11609,9 +13119,9 @@ function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, p
|
|
|
11609
13119
|
position,
|
|
11610
13120
|
...props
|
|
11611
13121
|
});
|
|
11612
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
13122
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.CopilotChatConfigurationProvider, {
|
|
11613
13123
|
isModalDefaultOpen: open ?? defaultOpen,
|
|
11614
|
-
children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
|
|
13124
|
+
children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.ControlledModalOpenScope, {
|
|
11615
13125
|
open,
|
|
11616
13126
|
onOpenChange,
|
|
11617
13127
|
children: internal
|
|
@@ -11619,7 +13129,8 @@ function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, p
|
|
|
11619
13129
|
});
|
|
11620
13130
|
}
|
|
11621
13131
|
function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
|
|
11622
|
-
const
|
|
13132
|
+
const configuration = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
13133
|
+
const isSidebarOpen = configuration?.isModalOpen ?? false;
|
|
11623
13134
|
const sidebarRef = (0, react.useRef)(null);
|
|
11624
13135
|
const [sidebarWidth, setSidebarWidth] = (0, react.useState)(width ?? DEFAULT_SIDEBAR_WIDTH);
|
|
11625
13136
|
const widthToCss = (w) => {
|
|
@@ -11684,7 +13195,7 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "r
|
|
|
11684
13195
|
paddingBottom: "env(safe-area-inset-bottom)"
|
|
11685
13196
|
},
|
|
11686
13197
|
"aria-hidden": !isSidebarOpen,
|
|
11687
|
-
"aria-label":
|
|
13198
|
+
"aria-label": configuration?.labels.sidebarLabel ?? require_MarkdownSurfaces.CopilotChatDefaultLabels.sidebarLabel,
|
|
11688
13199
|
role: "complementary",
|
|
11689
13200
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
11690
13201
|
className: "cpk:flex cpk:h-full cpk:w-full cpk:flex-col cpk:overflow-hidden",
|
|
@@ -11752,9 +13263,9 @@ function CopilotPopupView({ header, toggleButton, width, height, clickOutsideToC
|
|
|
11752
13263
|
className,
|
|
11753
13264
|
...restProps
|
|
11754
13265
|
});
|
|
11755
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
13266
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.CopilotChatConfigurationProvider, {
|
|
11756
13267
|
isModalDefaultOpen: open ?? defaultOpen,
|
|
11757
|
-
children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
|
|
13268
|
+
children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.ControlledModalOpenScope, {
|
|
11758
13269
|
open,
|
|
11759
13270
|
onOpenChange,
|
|
11760
13271
|
children: internal
|
|
@@ -11762,10 +13273,10 @@ function CopilotPopupView({ header, toggleButton, width, height, clickOutsideToC
|
|
|
11762
13273
|
});
|
|
11763
13274
|
}
|
|
11764
13275
|
function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOutsideToClose, className, ...restProps }) {
|
|
11765
|
-
const configuration = useCopilotChatConfiguration();
|
|
13276
|
+
const configuration = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
11766
13277
|
const isPopupOpen = configuration?.isModalOpen ?? false;
|
|
11767
13278
|
const setModalOpen = configuration?.setModalOpen;
|
|
11768
|
-
const labels = configuration?.labels ?? CopilotChatDefaultLabels;
|
|
13279
|
+
const labels = configuration?.labels ?? require_MarkdownSurfaces.CopilotChatDefaultLabels;
|
|
11769
13280
|
const containerRef = (0, react.useRef)(null);
|
|
11770
13281
|
const [isRendered, setIsRendered] = (0, react.useState)(isPopupOpen);
|
|
11771
13282
|
const [isAnimatingOut, setIsAnimatingOut] = (0, react.useState)(false);
|
|
@@ -12068,7 +13579,7 @@ function findChatInput(origin) {
|
|
|
12068
13579
|
* ```
|
|
12069
13580
|
*/
|
|
12070
13581
|
function CopilotThreadsDrawer({ agentId, onThreadSelect, onNewThread, onLicensed, licenseUrl, renderRow, label, recentLabel, collapsible, onCollapseChange, limit, "data-testid": dataTestId = "copilot-threads-drawer" }) {
|
|
12071
|
-
const configuration = useCopilotChatConfiguration();
|
|
13582
|
+
const configuration = require_MarkdownSurfaces.useCopilotChatConfiguration();
|
|
12072
13583
|
const { status, checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
|
|
12073
13584
|
const licensePresent = status === "valid" || status === "expiring";
|
|
12074
13585
|
const featureLicensed = checkFeature("threads");
|
|
@@ -12327,7 +13838,7 @@ CopilotThreadsDrawer.displayName = "CopilotThreadsDrawer";
|
|
|
12327
13838
|
* Catch-all (`"*"`) tool-call renderer that shows CopilotKit's default
|
|
12328
13839
|
* tool-call card for any tool without a dedicated renderer.
|
|
12329
13840
|
*/
|
|
12330
|
-
const WildcardToolCallRender = defineToolCallRenderer({
|
|
13841
|
+
const WildcardToolCallRender = require_MarkdownSurfaces.defineToolCallRenderer({
|
|
12331
13842
|
name: "*",
|
|
12332
13843
|
group: true,
|
|
12333
13844
|
render: (props) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultToolCallRenderer, { ...adaptRendererProps(props) })
|
|
@@ -13944,7 +15455,7 @@ const usePredictStateSubscription = (agent) => {
|
|
|
13944
15455
|
};
|
|
13945
15456
|
function CopilotListenersAgentSubscription() {
|
|
13946
15457
|
const { copilotkit } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
13947
|
-
const configAgentId = useCopilotChatConfiguration()?.agentId;
|
|
15458
|
+
const configAgentId = require_MarkdownSurfaces.useCopilotChatConfiguration()?.agentId;
|
|
13948
15459
|
const { agent } = useAgent({ agentId: (0, react.useMemo)(() => {
|
|
13949
15460
|
const requested = configAgentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
13950
15461
|
const registered = copilotkit.agents ?? {};
|
|
@@ -14456,7 +15967,7 @@ function CopilotKitInternal(cpkProps) {
|
|
|
14456
15967
|
setInternalErrorHandler,
|
|
14457
15968
|
removeInternalErrorHandler
|
|
14458
15969
|
]);
|
|
14459
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
15970
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(require_MarkdownSurfaces.CopilotChatConfigurationProvider, {
|
|
14460
15971
|
agentId: props.agent ?? "default",
|
|
14461
15972
|
threadId,
|
|
14462
15973
|
hasExplicitThreadId: isThreadIdExplicit,
|
|
@@ -14567,12 +16078,6 @@ Object.defineProperty(exports, 'CopilotChatAudioRecorder', {
|
|
|
14567
16078
|
return CopilotChatAudioRecorder;
|
|
14568
16079
|
}
|
|
14569
16080
|
});
|
|
14570
|
-
Object.defineProperty(exports, 'CopilotChatConfigurationProvider', {
|
|
14571
|
-
enumerable: true,
|
|
14572
|
-
get: function () {
|
|
14573
|
-
return CopilotChatConfigurationProvider;
|
|
14574
|
-
}
|
|
14575
|
-
});
|
|
14576
16081
|
Object.defineProperty(exports, 'CopilotChatInput_default', {
|
|
14577
16082
|
enumerable: true,
|
|
14578
16083
|
get: function () {
|
|
@@ -14813,12 +16318,6 @@ Object.defineProperty(exports, 'WildcardToolCallRender', {
|
|
|
14813
16318
|
return WildcardToolCallRender;
|
|
14814
16319
|
}
|
|
14815
16320
|
});
|
|
14816
|
-
Object.defineProperty(exports, '__toESM', {
|
|
14817
|
-
enumerable: true,
|
|
14818
|
-
get: function () {
|
|
14819
|
-
return __toESM;
|
|
14820
|
-
}
|
|
14821
|
-
});
|
|
14822
16321
|
Object.defineProperty(exports, 'createA2UIMessageRenderer', {
|
|
14823
16322
|
enumerable: true,
|
|
14824
16323
|
get: function () {
|
|
@@ -14831,12 +16330,6 @@ Object.defineProperty(exports, 'defaultCopilotContextCategories', {
|
|
|
14831
16330
|
return defaultCopilotContextCategories;
|
|
14832
16331
|
}
|
|
14833
16332
|
});
|
|
14834
|
-
Object.defineProperty(exports, 'defineToolCallRenderer', {
|
|
14835
|
-
enumerable: true,
|
|
14836
|
-
get: function () {
|
|
14837
|
-
return defineToolCallRenderer;
|
|
14838
|
-
}
|
|
14839
|
-
});
|
|
14840
16333
|
Object.defineProperty(exports, 'getIntelligenceTurnAnchors', {
|
|
14841
16334
|
enumerable: true,
|
|
14842
16335
|
get: function () {
|
|
@@ -14909,12 +16402,6 @@ Object.defineProperty(exports, 'useConfigureSuggestions', {
|
|
|
14909
16402
|
return useConfigureSuggestions;
|
|
14910
16403
|
}
|
|
14911
16404
|
});
|
|
14912
|
-
Object.defineProperty(exports, 'useCopilotChatConfiguration', {
|
|
14913
|
-
enumerable: true,
|
|
14914
|
-
get: function () {
|
|
14915
|
-
return useCopilotChatConfiguration;
|
|
14916
|
-
}
|
|
14917
|
-
});
|
|
14918
16405
|
Object.defineProperty(exports, 'useCopilotContext', {
|
|
14919
16406
|
enumerable: true,
|
|
14920
16407
|
get: function () {
|
|
@@ -15041,4 +16528,4 @@ Object.defineProperty(exports, 'useToast', {
|
|
|
15041
16528
|
return useToast;
|
|
15042
16529
|
}
|
|
15043
16530
|
});
|
|
15044
|
-
//# sourceMappingURL=copilotkit-
|
|
16531
|
+
//# sourceMappingURL=copilotkit-CVvbU9lV.cjs.map
|