@copilotkit/react-core 1.61.1 → 1.62.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/{copilotkit-UY-H6Kx7.mjs → copilotkit-BtRkFsNR.mjs} +1227 -599
- package/dist/copilotkit-BtRkFsNR.mjs.map +1 -0
- package/dist/{copilotkit-BCJDP8qd.cjs → copilotkit-CdpDZi3i.cjs} +1219 -585
- package/dist/copilotkit-CdpDZi3i.cjs.map +1 -0
- package/dist/{copilotkit-CEdu_aie.d.cts → copilotkit-Cga6AHO0.d.cts} +497 -209
- package/dist/copilotkit-Cga6AHO0.d.cts.map +1 -0
- package/dist/{copilotkit-M1FiciGd.d.mts → copilotkit-DnLpJ2Cl.d.mts} +497 -209
- package/dist/copilotkit-DnLpJ2Cl.d.mts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.mjs.map +1 -1
- package/dist/index.umd.js +360 -270
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/context.d.cts +5 -1
- package/dist/v2/context.d.cts.map +1 -1
- package/dist/v2/context.d.mts +5 -1
- package/dist/v2/context.d.mts.map +1 -1
- package/dist/v2/headless.cjs +323 -104
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.d.cts +187 -69
- package/dist/v2/headless.d.cts.map +1 -1
- package/dist/v2/headless.d.mts +187 -69
- package/dist/v2/headless.d.mts.map +1 -1
- package/dist/v2/headless.mjs +325 -106
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +2 -1
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +2 -2
- package/dist/v2/index.d.mts +2 -2
- package/dist/v2/index.mjs +2 -2
- package/dist/v2/index.umd.js +1112 -484
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +8 -6
- package/dist/copilotkit-BCJDP8qd.cjs.map +0 -1
- package/dist/copilotkit-CEdu_aie.d.cts.map +0 -1
- package/dist/copilotkit-M1FiciGd.d.mts.map +0 -1
- package/dist/copilotkit-UY-H6Kx7.mjs.map +0 -1
package/dist/v2/index.umd.js
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
|
|
3
3
|
(function(global, factory) {
|
|
4
|
-
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('./index.css'), require('@copilotkit/core'), require('@ag-ui/client'), require('react'), require('tailwind-merge'), require('lucide-react'), require('@copilotkit/shared'), require('react/jsx-runtime'), require('@radix-ui/react-slot'), require('class-variance-authority'), require('clsx'), require('@radix-ui/react-tooltip'), require('@radix-ui/react-dropdown-menu'), require('streamdown'), require('zod'), require('@lit-labs/react'), require('@copilotkit/a2ui-renderer'), require('zod-to-json-schema'), require('react-dom'), require('@tanstack/react-virtual'), require('use-stick-to-bottom')) :
|
|
5
|
-
typeof define === 'function' && define.amd ? define(['exports', './index.css', '@copilotkit/core', '@ag-ui/client', 'react', 'tailwind-merge', 'lucide-react', '@copilotkit/shared', 'react/jsx-runtime', '@radix-ui/react-slot', 'class-variance-authority', 'clsx', '@radix-ui/react-tooltip', '@radix-ui/react-dropdown-menu', 'streamdown', 'zod', '@lit-labs/react', '@copilotkit/a2ui-renderer', 'zod-to-json-schema', 'react-dom', '@tanstack/react-virtual', 'use-stick-to-bottom'], factory) :
|
|
6
|
-
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitReactCoreV2 = {}), global.src_v2_index_css,global.CopilotKitCore,global.AgUIClient,global.React,global.tailwindMerge,global.lucideReact,global.CopilotKitShared,global.ReactJsxRuntime,global.RadixReactSlot,global.classVarianceAuthority,global.clsx,global.RadixReactTooltip,global.RadixReactDropdownMenu,global.streamdown,global.Zod,global.LitLabsReact,global.CopilotKitA2UIRenderer,global.zod_to_json_schema,global.ReactDOM,global._tanstack_react_virtual,global.useStickToBottom));
|
|
7
|
-
})(this, function(exports, src_v2_index_css, _copilotkit_core, _ag_ui_client, react, tailwind_merge, lucide_react, _copilotkit_shared, react_jsx_runtime, _radix_ui_react_slot, class_variance_authority, clsx, _radix_ui_react_tooltip, _radix_ui_react_dropdown_menu, streamdown, zod, _lit_labs_react, _copilotkit_a2ui_renderer, zod_to_json_schema, react_dom, _tanstack_react_virtual, use_stick_to_bottom) {
|
|
4
|
+
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('./index.css'), require('@copilotkit/core'), require('@ag-ui/client'), require('react'), require('tailwind-merge'), require('lucide-react'), require('@copilotkit/shared'), require('react/jsx-runtime'), require('@radix-ui/react-slot'), require('class-variance-authority'), require('clsx'), require('@radix-ui/react-tooltip'), require('@radix-ui/react-dropdown-menu'), require('streamdown'), require('zod'), require('@lit-labs/react'), require('@copilotkit/a2ui-renderer'), require('zod-to-json-schema'), require('react-dom'), require('@tanstack/react-virtual'), require('use-stick-to-bottom'), require('@copilotkit/web-components/threads-drawer')) :
|
|
5
|
+
typeof define === 'function' && define.amd ? define(['exports', './index.css', '@copilotkit/core', '@ag-ui/client', 'react', 'tailwind-merge', 'lucide-react', '@copilotkit/shared', 'react/jsx-runtime', '@radix-ui/react-slot', 'class-variance-authority', 'clsx', '@radix-ui/react-tooltip', '@radix-ui/react-dropdown-menu', 'streamdown', 'zod', '@lit-labs/react', '@copilotkit/a2ui-renderer', 'zod-to-json-schema', 'react-dom', '@tanstack/react-virtual', 'use-stick-to-bottom', '@copilotkit/web-components/threads-drawer'], factory) :
|
|
6
|
+
(global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory((global.CopilotKitReactCoreV2 = {}), global.src_v2_index_css,global.CopilotKitCore,global.AgUIClient,global.React,global.tailwindMerge,global.lucideReact,global.CopilotKitShared,global.ReactJsxRuntime,global.RadixReactSlot,global.classVarianceAuthority,global.clsx,global.RadixReactTooltip,global.RadixReactDropdownMenu,global.streamdown,global.Zod,global.LitLabsReact,global.CopilotKitA2UIRenderer,global.zod_to_json_schema,global.ReactDOM,global._tanstack_react_virtual,global.useStickToBottom,global._copilotkit_web_components_threads_drawer));
|
|
7
|
+
})(this, function(exports, src_v2_index_css, _copilotkit_core, _ag_ui_client, react, tailwind_merge, lucide_react, _copilotkit_shared, react_jsx_runtime, _radix_ui_react_slot, class_variance_authority, clsx, _radix_ui_react_tooltip, _radix_ui_react_dropdown_menu, streamdown, zod, _lit_labs_react, _copilotkit_a2ui_renderer, zod_to_json_schema, react_dom, _tanstack_react_virtual, use_stick_to_bottom, _copilotkit_web_components_threads_drawer) {
|
|
8
8
|
Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
|
|
9
9
|
//#region \0rolldown/runtime.js
|
|
10
10
|
var __create = Object.create;
|
|
@@ -160,6 +160,25 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
160
160
|
modalHeaderTitle: "CopilotKit Chat",
|
|
161
161
|
welcomeMessageText: "How can I help you today?"
|
|
162
162
|
};
|
|
163
|
+
/**
|
|
164
|
+
* Mobile breakpoint below which the chat modal and the thread-list drawer are
|
|
165
|
+
* mutually exclusive. At or above this width both surfaces may coexist. This
|
|
166
|
+
* mirrors the `(max-width: 767px)` / `(min-width: 768px)` split already used by
|
|
167
|
+
* CopilotChatInput and CopilotSidebarView.
|
|
168
|
+
*/
|
|
169
|
+
const MOBILE_MAX_WIDTH_PX = 767;
|
|
170
|
+
/**
|
|
171
|
+
* Reports whether the current viewport is in the mobile range (`<768px`), where
|
|
172
|
+
* the chat modal and drawer must not be open simultaneously. SSR-safe and
|
|
173
|
+
* defensive against environments without `matchMedia` (treated as desktop, so
|
|
174
|
+
* no mutual-exclusion constraint is applied).
|
|
175
|
+
*
|
|
176
|
+
* @returns `true` when the viewport is mobile-width, `false` otherwise.
|
|
177
|
+
*/
|
|
178
|
+
function isMobileViewport() {
|
|
179
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return false;
|
|
180
|
+
return window.matchMedia(`(max-width: ${MOBILE_MAX_WIDTH_PX}px)`).matches;
|
|
181
|
+
}
|
|
163
182
|
const CopilotChatConfiguration = (0, react.createContext)(null);
|
|
164
183
|
const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, hasExplicitThreadId, isModalDefaultOpen }) => {
|
|
165
184
|
const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
|
|
@@ -170,12 +189,22 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
170
189
|
...stableLabels
|
|
171
190
|
}), [stableLabels, parentConfig?.labels]);
|
|
172
191
|
const resolvedAgentId = agentId ?? parentConfig?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
192
|
+
const threadIdPropIsAuthoritative = threadId !== void 0 && hasExplicitThreadId !== false;
|
|
193
|
+
const isThreadIdControlled = threadIdPropIsAuthoritative;
|
|
194
|
+
const [activeThreadOverride, setActiveThreadOverride] = (0, react.useState)(null);
|
|
173
195
|
const resolvedThreadId = (0, react.useMemo)(() => {
|
|
174
|
-
if (
|
|
196
|
+
if (threadIdPropIsAuthoritative) return threadId;
|
|
197
|
+
if (activeThreadOverride) return activeThreadOverride.threadId;
|
|
175
198
|
if (parentConfig?.threadId) return parentConfig.threadId;
|
|
199
|
+
if (threadId) return threadId;
|
|
176
200
|
return (0, _copilotkit_shared.randomUUID)();
|
|
177
|
-
}, [
|
|
178
|
-
|
|
201
|
+
}, [
|
|
202
|
+
threadIdPropIsAuthoritative,
|
|
203
|
+
threadId,
|
|
204
|
+
parentConfig?.threadId,
|
|
205
|
+
activeThreadOverride
|
|
206
|
+
]);
|
|
207
|
+
const resolvedHasExplicitThreadId = (threadIdPropIsAuthoritative ? true : activeThreadOverride?.explicit ?? hasExplicitThreadId ?? false) || !!parentConfig?.hasExplicitThreadId;
|
|
179
208
|
const [internalModalOpen, setInternalModalOpen] = (0, react.useState)(isModalDefaultOpen ?? true);
|
|
180
209
|
const hasExplicitDefault = isModalDefaultOpen !== void 0;
|
|
181
210
|
const setAndSync = (0, react.useCallback)((open) => {
|
|
@@ -194,20 +223,113 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
194
223
|
}, [parentConfig?.isModalOpen, hasExplicitDefault]);
|
|
195
224
|
const resolvedIsModalOpen = hasExplicitDefault ? internalModalOpen : parentConfig?.isModalOpen ?? internalModalOpen;
|
|
196
225
|
const resolvedSetModalOpen = hasExplicitDefault ? setAndSync : parentConfig?.setModalOpen ?? setInternalModalOpen;
|
|
226
|
+
const [ownDrawerOpen, setOwnDrawerOpen] = (0, react.useState)(false);
|
|
227
|
+
const [ownDrawerCount, setOwnDrawerCount] = (0, react.useState)(0);
|
|
228
|
+
const modalCloseRef = (0, react.useRef)(() => {});
|
|
229
|
+
modalCloseRef.current = resolvedSetModalOpen;
|
|
230
|
+
const registeredModalClosersRef = (0, react.useRef)([]);
|
|
231
|
+
const ownRegisterModalCloser = (0, react.useCallback)((closeModal) => {
|
|
232
|
+
registeredModalClosersRef.current.push(closeModal);
|
|
233
|
+
return () => {
|
|
234
|
+
registeredModalClosersRef.current = registeredModalClosersRef.current.filter((entry) => entry !== closeModal);
|
|
235
|
+
};
|
|
236
|
+
}, []);
|
|
237
|
+
const ownSetDrawerOpen = (0, react.useCallback)((open) => {
|
|
238
|
+
setOwnDrawerOpen(open);
|
|
239
|
+
if (open && isMobileViewport()) {
|
|
240
|
+
const registered = registeredModalClosersRef.current;
|
|
241
|
+
(registered.length > 0 ? registered[registered.length - 1] : modalCloseRef.current)(false);
|
|
242
|
+
}
|
|
243
|
+
}, []);
|
|
244
|
+
const ownRegisterDrawer = (0, react.useCallback)(() => {
|
|
245
|
+
setOwnDrawerCount((count) => count + 1);
|
|
246
|
+
return () => {
|
|
247
|
+
setOwnDrawerCount((count) => Math.max(0, count - 1));
|
|
248
|
+
};
|
|
249
|
+
}, []);
|
|
250
|
+
const resolvedDrawerOpen = parentConfig ? parentConfig.drawerOpen : ownDrawerOpen;
|
|
251
|
+
const resolvedSetDrawerOpen = parentConfig ? parentConfig.setDrawerOpen : ownSetDrawerOpen;
|
|
252
|
+
const resolvedDrawerRegistered = parentConfig ? parentConfig.drawerRegistered : ownDrawerCount > 0;
|
|
253
|
+
const resolvedRegisterDrawer = parentConfig ? parentConfig.registerDrawer : ownRegisterDrawer;
|
|
254
|
+
const resolvedRegisterModalCloser = parentConfig ? parentConfig.ɵregisterModalCloser : ownRegisterModalCloser;
|
|
255
|
+
(0, react.useEffect)(() => {
|
|
256
|
+
if (!hasExplicitDefault) return;
|
|
257
|
+
return resolvedRegisterModalCloser(resolvedSetModalOpen);
|
|
258
|
+
}, [
|
|
259
|
+
hasExplicitDefault,
|
|
260
|
+
resolvedRegisterModalCloser,
|
|
261
|
+
resolvedSetModalOpen
|
|
262
|
+
]);
|
|
263
|
+
const isThreadIdControlledRef = (0, react.useRef)(isThreadIdControlled);
|
|
264
|
+
isThreadIdControlledRef.current = isThreadIdControlled;
|
|
265
|
+
const ownSetActiveThreadId = (0, react.useCallback)((id, options) => {
|
|
266
|
+
setActiveThreadOverride({
|
|
267
|
+
threadId: id,
|
|
268
|
+
explicit: options?.explicit ?? true
|
|
269
|
+
});
|
|
270
|
+
}, []);
|
|
271
|
+
const ownStartNewThread = (0, react.useCallback)(() => {
|
|
272
|
+
setActiveThreadOverride({
|
|
273
|
+
threadId: (0, _copilotkit_shared.randomUUID)(),
|
|
274
|
+
explicit: false
|
|
275
|
+
});
|
|
276
|
+
}, []);
|
|
277
|
+
const parentSetActiveThreadId = parentConfig?.setActiveThreadId;
|
|
278
|
+
const parentStartNewThread = parentConfig?.startNewThread;
|
|
279
|
+
const resolvedSetActiveThreadId = (0, react.useCallback)((id, options) => {
|
|
280
|
+
if (isThreadIdControlledRef.current) {
|
|
281
|
+
console.warn("[CopilotKit] Ignoring setActiveThreadId(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
284
|
+
if (parentSetActiveThreadId) {
|
|
285
|
+
parentSetActiveThreadId(id, options);
|
|
286
|
+
return;
|
|
287
|
+
}
|
|
288
|
+
ownSetActiveThreadId(id, options);
|
|
289
|
+
}, [parentSetActiveThreadId, ownSetActiveThreadId]);
|
|
290
|
+
const resolvedStartNewThread = (0, react.useCallback)(() => {
|
|
291
|
+
if (isThreadIdControlledRef.current) {
|
|
292
|
+
console.warn("[CopilotKit] Ignoring startNewThread(): threadId is controlled via the `threadId` prop on CopilotChatConfigurationProvider.");
|
|
293
|
+
return;
|
|
294
|
+
}
|
|
295
|
+
if (parentStartNewThread) {
|
|
296
|
+
parentStartNewThread();
|
|
297
|
+
return;
|
|
298
|
+
}
|
|
299
|
+
ownStartNewThread();
|
|
300
|
+
}, [parentStartNewThread, ownStartNewThread]);
|
|
301
|
+
const setModalOpenWithDrawerExclusion = (0, react.useCallback)((open) => {
|
|
302
|
+
if (open && isMobileViewport()) resolvedSetDrawerOpen(false);
|
|
303
|
+
resolvedSetModalOpen(open);
|
|
304
|
+
}, [resolvedSetModalOpen, resolvedSetDrawerOpen]);
|
|
197
305
|
const configurationValue = (0, react.useMemo)(() => ({
|
|
198
306
|
labels: mergedLabels,
|
|
199
307
|
agentId: resolvedAgentId,
|
|
200
308
|
threadId: resolvedThreadId,
|
|
201
309
|
hasExplicitThreadId: resolvedHasExplicitThreadId,
|
|
202
310
|
isModalOpen: resolvedIsModalOpen,
|
|
203
|
-
setModalOpen:
|
|
311
|
+
setModalOpen: setModalOpenWithDrawerExclusion,
|
|
312
|
+
drawerOpen: resolvedDrawerOpen,
|
|
313
|
+
setDrawerOpen: resolvedSetDrawerOpen,
|
|
314
|
+
drawerRegistered: resolvedDrawerRegistered,
|
|
315
|
+
registerDrawer: resolvedRegisterDrawer,
|
|
316
|
+
ɵregisterModalCloser: resolvedRegisterModalCloser,
|
|
317
|
+
setActiveThreadId: resolvedSetActiveThreadId,
|
|
318
|
+
startNewThread: resolvedStartNewThread
|
|
204
319
|
}), [
|
|
205
320
|
mergedLabels,
|
|
206
321
|
resolvedAgentId,
|
|
207
322
|
resolvedThreadId,
|
|
208
323
|
resolvedHasExplicitThreadId,
|
|
209
324
|
resolvedIsModalOpen,
|
|
210
|
-
|
|
325
|
+
setModalOpenWithDrawerExclusion,
|
|
326
|
+
resolvedDrawerOpen,
|
|
327
|
+
resolvedSetDrawerOpen,
|
|
328
|
+
resolvedDrawerRegistered,
|
|
329
|
+
resolvedRegisterDrawer,
|
|
330
|
+
resolvedRegisterModalCloser,
|
|
331
|
+
resolvedSetActiveThreadId,
|
|
332
|
+
resolvedStartNewThread
|
|
211
333
|
]);
|
|
212
334
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
|
|
213
335
|
value: configurationValue,
|
|
@@ -1128,7 +1250,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1128
1250
|
},
|
|
1129
1251
|
...props,
|
|
1130
1252
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1131
|
-
className: "cpk:max-w-3xl cpk:mx-auto cpk:py-0 cpk:px-4 cpk:
|
|
1253
|
+
className: "cpk:max-w-3xl cpk:mx-auto cpk:py-0 cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-4 cpk:pointer-events-auto",
|
|
1132
1254
|
children: inputPill
|
|
1133
1255
|
}), shouldShowDisclaimer && BoundDisclaimer]
|
|
1134
1256
|
});
|
|
@@ -1396,317 +1518,45 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1396
1518
|
* useAgentContext hook registers context via useLayoutEffect, which runs
|
|
1397
1519
|
* synchronously after React commits that batch.
|
|
1398
1520
|
*
|
|
1399
|
-
* Awaiting a zero-delay timeout yields to the macrotask queue. React's
|
|
1400
|
-
* MessageChannel task runs first, committing the pending state and running
|
|
1401
|
-
* useLayoutEffect (which updates the context store). The follow-up runAgent
|
|
1402
|
-
* call then reads fresh context.
|
|
1403
|
-
*/
|
|
1404
|
-
async waitForPendingFrameworkUpdates() {
|
|
1405
|
-
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1406
|
-
}
|
|
1407
|
-
};
|
|
1408
|
-
|
|
1409
|
-
//#endregion
|
|
1410
|
-
//#region src/v2/context.ts
|
|
1411
|
-
const CopilotKitContext = (0, react.createContext)(null);
|
|
1412
|
-
const useCopilotKit = () => {
|
|
1413
|
-
const context = (0, react.useContext)(CopilotKitContext);
|
|
1414
|
-
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
1415
|
-
if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
|
|
1416
|
-
(0, react.useEffect)(() => {
|
|
1417
|
-
const subscription = context.copilotkit.subscribe({
|
|
1418
|
-
onRuntimeConnectionStatusChanged: () => {
|
|
1419
|
-
forceUpdate();
|
|
1420
|
-
},
|
|
1421
|
-
onHeadersChanged: () => {
|
|
1422
|
-
forceUpdate();
|
|
1423
|
-
}
|
|
1424
|
-
});
|
|
1425
|
-
return () => {
|
|
1426
|
-
subscription.unsubscribe();
|
|
1427
|
-
};
|
|
1428
|
-
}, []);
|
|
1429
|
-
return context;
|
|
1430
|
-
};
|
|
1431
|
-
const LicenseContext = (0, react.createContext)({
|
|
1432
|
-
status: null,
|
|
1433
|
-
license: null,
|
|
1434
|
-
checkFeature: () => true,
|
|
1435
|
-
getLimit: () => null
|
|
1436
|
-
});
|
|
1437
|
-
const useLicenseContext = () => (0, react.useContext)(LicenseContext);
|
|
1438
|
-
|
|
1439
|
-
//#endregion
|
|
1440
|
-
//#region src/v2/types/defineToolCallRenderer.ts
|
|
1441
|
-
function defineToolCallRenderer(def) {
|
|
1442
|
-
const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
|
|
1443
|
-
return {
|
|
1444
|
-
name: def.name,
|
|
1445
|
-
args: argsSchema,
|
|
1446
|
-
render: def.render,
|
|
1447
|
-
...def.agentId ? { agentId: def.agentId } : {}
|
|
1448
|
-
};
|
|
1449
|
-
}
|
|
1450
|
-
|
|
1451
|
-
//#endregion
|
|
1452
|
-
//#region src/v2/hooks/use-render-tool.tsx
|
|
1453
|
-
const EMPTY_DEPS$1 = [];
|
|
1454
|
-
/**
|
|
1455
|
-
* Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
|
|
1456
|
-
*
|
|
1457
|
-
* Key behavior:
|
|
1458
|
-
* - deduplicates by `agentId:name` (latest registration wins),
|
|
1459
|
-
* - keeps renderer entries on cleanup so historical chat tool calls can still render,
|
|
1460
|
-
* - refreshes registration when `deps` change.
|
|
1461
|
-
*
|
|
1462
|
-
* @typeParam S - Schema type describing tool call parameters.
|
|
1463
|
-
* @param config - Renderer config for wildcard or named tools.
|
|
1464
|
-
* @param deps - Optional dependencies to refresh registration.
|
|
1465
|
-
*
|
|
1466
|
-
* @example
|
|
1467
|
-
* ```tsx
|
|
1468
|
-
* useRenderTool(
|
|
1469
|
-
* {
|
|
1470
|
-
* name: "searchDocs",
|
|
1471
|
-
* parameters: z.object({ query: z.string() }),
|
|
1472
|
-
* render: ({ status, parameters, result }) => {
|
|
1473
|
-
* if (status === "executing") return <div>Searching {parameters.query}</div>;
|
|
1474
|
-
* if (status === "complete") return <div>{result}</div>;
|
|
1475
|
-
* return <div>Preparing...</div>;
|
|
1476
|
-
* },
|
|
1477
|
-
* },
|
|
1478
|
-
* [],
|
|
1479
|
-
* );
|
|
1480
|
-
* ```
|
|
1481
|
-
*
|
|
1482
|
-
* @example
|
|
1483
|
-
* ```tsx
|
|
1484
|
-
* useRenderTool(
|
|
1485
|
-
* {
|
|
1486
|
-
* name: "summarize",
|
|
1487
|
-
* parameters: z.object({ text: z.string() }),
|
|
1488
|
-
* agentId: "research-agent",
|
|
1489
|
-
* render: ({ name, status }) => <div>{name}: {status}</div>,
|
|
1490
|
-
* },
|
|
1491
|
-
* [selectedAgentId],
|
|
1492
|
-
* );
|
|
1493
|
-
* ```
|
|
1494
|
-
*/
|
|
1495
|
-
function useRenderTool(config, deps) {
|
|
1496
|
-
const { copilotkit } = useCopilotKit();
|
|
1497
|
-
const extraDeps = deps ?? EMPTY_DEPS$1;
|
|
1498
|
-
(0, react.useEffect)(() => {
|
|
1499
|
-
const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
|
|
1500
|
-
name: "*",
|
|
1501
|
-
render: (props) => config.render({
|
|
1502
|
-
...props,
|
|
1503
|
-
parameters: props.args
|
|
1504
|
-
}),
|
|
1505
|
-
...config.agentId ? { agentId: config.agentId } : {}
|
|
1506
|
-
}) : defineToolCallRenderer({
|
|
1507
|
-
name: config.name,
|
|
1508
|
-
args: config.parameters,
|
|
1509
|
-
render: (props) => config.render({
|
|
1510
|
-
...props,
|
|
1511
|
-
parameters: props.args
|
|
1512
|
-
}),
|
|
1513
|
-
...config.agentId ? { agentId: config.agentId } : {}
|
|
1514
|
-
});
|
|
1515
|
-
copilotkit.addHookRenderToolCall(renderer);
|
|
1516
|
-
}, [
|
|
1517
|
-
config.name,
|
|
1518
|
-
copilotkit,
|
|
1519
|
-
JSON.stringify(extraDeps)
|
|
1520
|
-
]);
|
|
1521
|
-
}
|
|
1522
|
-
|
|
1523
|
-
//#endregion
|
|
1524
|
-
//#region src/v2/hooks/use-default-render-tool.tsx
|
|
1525
|
-
/**
|
|
1526
|
-
* Module-level dedup set so an unknown status value only emits a console
|
|
1527
|
-
* warning the FIRST time we encounter it. Otherwise a stuck/unmapped status
|
|
1528
|
-
* would log on every re-render (potentially many per second).
|
|
1529
|
-
*/
|
|
1530
|
-
const warnedUnknownStatuses = /* @__PURE__ */ new Set();
|
|
1531
|
-
/**
|
|
1532
|
-
* Map a {@link ToolCallStatus} enum value to the documented string-union
|
|
1533
|
-
* status the {@link DefaultRenderProps} contract exposes. Unknown / future
|
|
1534
|
-
* enum members log a warning (once per distinct value) and fall back to
|
|
1535
|
-
* `"inProgress"`.
|
|
1536
|
-
*/
|
|
1537
|
-
function mapToolCallStatus(status) {
|
|
1538
|
-
switch (status) {
|
|
1539
|
-
case _copilotkit_core.ToolCallStatus.Complete: return "complete";
|
|
1540
|
-
case _copilotkit_core.ToolCallStatus.Executing: return "executing";
|
|
1541
|
-
case _copilotkit_core.ToolCallStatus.InProgress: return "inProgress";
|
|
1542
|
-
default: {
|
|
1543
|
-
const key = String(status);
|
|
1544
|
-
if (!warnedUnknownStatuses.has(key)) {
|
|
1545
|
-
warnedUnknownStatuses.add(key);
|
|
1546
|
-
console.warn(`[CopilotKit] Unknown ToolCallStatus "${key}" in default tool-call renderer; falling back to "inProgress".`);
|
|
1547
|
-
}
|
|
1548
|
-
return "inProgress";
|
|
1549
|
-
}
|
|
1550
|
-
}
|
|
1551
|
-
}
|
|
1552
|
-
/**
|
|
1553
|
-
* Convert the framework-internal renderer props (`args`, enum status) into
|
|
1554
|
-
* the documented {@link DefaultRenderProps} shape (`parameters`, string-union
|
|
1555
|
-
* status) so a user `config.render` always sees the documented contract.
|
|
1556
|
-
*/
|
|
1557
|
-
function adaptRendererProps(props) {
|
|
1558
|
-
return {
|
|
1559
|
-
name: props.name,
|
|
1560
|
-
toolCallId: props.toolCallId,
|
|
1561
|
-
parameters: props.args,
|
|
1562
|
-
status: mapToolCallStatus(props.status),
|
|
1563
|
-
result: props.result
|
|
1564
|
-
};
|
|
1565
|
-
}
|
|
1566
|
-
/**
|
|
1567
|
-
* Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
|
|
1568
|
-
*
|
|
1569
|
-
* - Call with no config to use CopilotKit's built-in default tool-call card.
|
|
1570
|
-
* - Pass `config.render` to replace the default UI with your own fallback renderer.
|
|
1571
|
-
*
|
|
1572
|
-
* This is useful when you want a generic renderer for tools that do not have a
|
|
1573
|
-
* dedicated `useRenderTool({ name: "..." })` registration.
|
|
1574
|
-
*
|
|
1575
|
-
* @param config - Optional custom wildcard render function.
|
|
1576
|
-
* @param deps - Optional dependencies to refresh registration.
|
|
1577
|
-
*
|
|
1578
|
-
* @example
|
|
1579
|
-
* ```tsx
|
|
1580
|
-
* useDefaultRenderTool();
|
|
1581
|
-
* ```
|
|
1582
|
-
*
|
|
1583
|
-
* @example
|
|
1584
|
-
* ```tsx
|
|
1585
|
-
* useDefaultRenderTool({
|
|
1586
|
-
* render: ({ name, status }) => <div>{name}: {status}</div>,
|
|
1587
|
-
* });
|
|
1588
|
-
* ```
|
|
1589
|
-
*
|
|
1590
|
-
* @example
|
|
1591
|
-
* ```tsx
|
|
1592
|
-
* useDefaultRenderTool(
|
|
1593
|
-
* {
|
|
1594
|
-
* render: ({ name, result }) => (
|
|
1595
|
-
* <ToolEventRow title={name} payload={result} compact={compactMode} />
|
|
1596
|
-
* ),
|
|
1597
|
-
* },
|
|
1598
|
-
* [compactMode],
|
|
1599
|
-
* );
|
|
1600
|
-
* ```
|
|
1601
|
-
*/
|
|
1602
|
-
function useDefaultRenderTool(config, deps) {
|
|
1603
|
-
const userRender = config?.render;
|
|
1604
|
-
useRenderTool({
|
|
1605
|
-
name: "*",
|
|
1606
|
-
render: userRender ? (raw) => userRender(adaptRendererProps(raw)) : (raw) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultToolCallRenderer, { ...adaptRendererProps(raw) })
|
|
1607
|
-
}, deps);
|
|
1608
|
-
}
|
|
1609
|
-
/**
|
|
1610
|
-
* Guarded JSON.stringify used inside the expanded `<pre>` blocks. A circular
|
|
1611
|
-
* reference would otherwise crash the entire React tree on render.
|
|
1612
|
-
*/
|
|
1613
|
-
function safeStringifyForPre(value) {
|
|
1614
|
-
try {
|
|
1615
|
-
return JSON.stringify(value, null, 2);
|
|
1616
|
-
} catch (err) {
|
|
1617
|
-
console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for default renderer; falling back to String():", err);
|
|
1618
|
-
try {
|
|
1619
|
-
return String(value);
|
|
1620
|
-
} catch (innerErr) {
|
|
1621
|
-
console.warn("[CopilotKit] safeStringifyForPre: value could not be stringified:", innerErr);
|
|
1622
|
-
return "[unserializable]";
|
|
1623
|
-
}
|
|
1624
|
-
}
|
|
1625
|
-
}
|
|
1626
|
-
function DefaultToolCallRenderer({ name, toolCallId, parameters, status, result }) {
|
|
1627
|
-
const [isExpanded, setIsExpanded] = (0, react.useState)(false);
|
|
1628
|
-
const isActive = status === "inProgress" || status === "executing";
|
|
1629
|
-
const isComplete = status === "complete";
|
|
1630
|
-
const statusLabel = isActive ? "Running" : isComplete ? "Done" : status;
|
|
1631
|
-
const dotClassName = isActive ? "cpk:bg-amber-500" : isComplete ? "cpk:bg-emerald-500" : "cpk:bg-zinc-400";
|
|
1632
|
-
const badgeClassName = isActive ? "cpk:bg-amber-100 cpk:text-amber-800 cpk:dark:bg-amber-500/15 cpk:dark:text-amber-400" : isComplete ? "cpk:bg-emerald-100 cpk:text-emerald-800 cpk:dark:bg-emerald-500/15 cpk:dark:text-emerald-400" : "cpk:bg-zinc-100 cpk:text-zinc-800 cpk:dark:bg-zinc-700/40 cpk:dark:text-zinc-300";
|
|
1633
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1634
|
-
"data-testid": "copilot-tool-render",
|
|
1635
|
-
"data-tool-name": name,
|
|
1636
|
-
"data-tool-call-id": toolCallId,
|
|
1637
|
-
"data-status": status,
|
|
1638
|
-
"data-args": safeStringifyForAttr(parameters),
|
|
1639
|
-
"data-result": safeStringifyForAttr(result),
|
|
1640
|
-
className: "cpk:mt-2 cpk:pb-2",
|
|
1641
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1642
|
-
className: "cpk:rounded-xl cpk:border cpk:border-zinc-200/60 cpk:bg-white/70 cpk:p-4 cpk:shadow-sm cpk:backdrop-blur cpk:dark:border-zinc-800/60 cpk:dark:bg-zinc-900/50",
|
|
1643
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
1644
|
-
type: "button",
|
|
1645
|
-
"aria-expanded": isExpanded,
|
|
1646
|
-
onClick: () => setIsExpanded(!isExpanded),
|
|
1647
|
-
className: "cpk:flex cpk:w-full cpk:cursor-pointer cpk:select-none cpk:items-center cpk:justify-between cpk:gap-2.5 cpk:border-none cpk:bg-transparent cpk:p-0 cpk:m-0 cpk:text-left cpk:text-inherit",
|
|
1648
|
-
style: { font: "inherit" },
|
|
1649
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1650
|
-
className: "cpk:flex cpk:min-w-0 cpk:items-center cpk:gap-2",
|
|
1651
|
-
children: [
|
|
1652
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
1653
|
-
className: `cpk:h-3.5 cpk:w-3.5 cpk:flex-shrink-0 cpk:text-zinc-500 cpk:transition-transform cpk:dark:text-zinc-400 ${isExpanded ? "cpk:rotate-90" : ""}`,
|
|
1654
|
-
fill: "none",
|
|
1655
|
-
viewBox: "0 0 24 24",
|
|
1656
|
-
strokeWidth: 2,
|
|
1657
|
-
stroke: "currentColor",
|
|
1658
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
1659
|
-
strokeLinecap: "round",
|
|
1660
|
-
strokeLinejoin: "round",
|
|
1661
|
-
d: "M8.25 4.5l7.5 7.5-7.5 7.5"
|
|
1662
|
-
})
|
|
1663
|
-
}),
|
|
1664
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `cpk:inline-block cpk:h-2 cpk:w-2 cpk:flex-shrink-0 cpk:rounded-full ${dotClassName}` }),
|
|
1665
|
-
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1666
|
-
"data-testid": "copilot-tool-render-name",
|
|
1667
|
-
className: "cpk:truncate cpk:text-[13px] cpk:font-semibold cpk:text-zinc-900 cpk:dark:text-zinc-100",
|
|
1668
|
-
children: name
|
|
1669
|
-
})
|
|
1670
|
-
]
|
|
1671
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
1672
|
-
"data-testid": "copilot-tool-render-status",
|
|
1673
|
-
className: `cpk:inline-flex cpk:flex-shrink-0 cpk:items-center cpk:rounded-full cpk:px-2 cpk:py-0.5 cpk:text-[11px] cpk:font-medium ${badgeClassName}`,
|
|
1674
|
-
children: statusLabel
|
|
1675
|
-
})]
|
|
1676
|
-
}), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1677
|
-
className: "cpk:mt-3 cpk:grid cpk:gap-3",
|
|
1678
|
-
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1679
|
-
className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
|
|
1680
|
-
children: "Arguments"
|
|
1681
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
1682
|
-
className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
|
|
1683
|
-
children: safeStringifyForPre(parameters ?? {})
|
|
1684
|
-
})] }), result !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
1685
|
-
className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
|
|
1686
|
-
children: "Result"
|
|
1687
|
-
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
1688
|
-
className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
|
|
1689
|
-
children: typeof result === "string" ? result : safeStringifyForPre(result)
|
|
1690
|
-
})] })]
|
|
1691
|
-
})]
|
|
1692
|
-
})
|
|
1693
|
-
});
|
|
1694
|
-
}
|
|
1695
|
-
function safeStringifyForAttr(value) {
|
|
1696
|
-
if (value === void 0 || value === null) return "";
|
|
1697
|
-
if (typeof value === "string") return value;
|
|
1698
|
-
try {
|
|
1699
|
-
return JSON.stringify(value);
|
|
1700
|
-
} catch (err) {
|
|
1701
|
-
console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for data-* attribute; falling back to String():", err);
|
|
1702
|
-
try {
|
|
1703
|
-
return String(value);
|
|
1704
|
-
} catch (innerErr) {
|
|
1705
|
-
console.warn("[CopilotKit] safeStringifyForAttr: value could not be stringified:", innerErr);
|
|
1706
|
-
return "";
|
|
1707
|
-
}
|
|
1521
|
+
* Awaiting a zero-delay timeout yields to the macrotask queue. React's
|
|
1522
|
+
* MessageChannel task runs first, committing the pending state and running
|
|
1523
|
+
* useLayoutEffect (which updates the context store). The follow-up runAgent
|
|
1524
|
+
* call then reads fresh context.
|
|
1525
|
+
*/
|
|
1526
|
+
async waitForPendingFrameworkUpdates() {
|
|
1527
|
+
await new Promise((resolve) => setTimeout(resolve, 0));
|
|
1708
1528
|
}
|
|
1709
|
-
}
|
|
1529
|
+
};
|
|
1530
|
+
|
|
1531
|
+
//#endregion
|
|
1532
|
+
//#region src/v2/context.ts
|
|
1533
|
+
const CopilotKitContext = (0, react.createContext)(null);
|
|
1534
|
+
const useCopilotKit = () => {
|
|
1535
|
+
const context = (0, react.useContext)(CopilotKitContext);
|
|
1536
|
+
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
1537
|
+
if (!context) throw new Error("useCopilotKit must be used within CopilotKitProvider");
|
|
1538
|
+
(0, react.useEffect)(() => {
|
|
1539
|
+
const subscription = context.copilotkit.subscribe({
|
|
1540
|
+
onRuntimeConnectionStatusChanged: () => {
|
|
1541
|
+
forceUpdate();
|
|
1542
|
+
},
|
|
1543
|
+
onHeadersChanged: () => {
|
|
1544
|
+
forceUpdate();
|
|
1545
|
+
}
|
|
1546
|
+
});
|
|
1547
|
+
return () => {
|
|
1548
|
+
subscription.unsubscribe();
|
|
1549
|
+
};
|
|
1550
|
+
}, []);
|
|
1551
|
+
return context;
|
|
1552
|
+
};
|
|
1553
|
+
const LicenseContext = (0, react.createContext)({
|
|
1554
|
+
status: null,
|
|
1555
|
+
license: null,
|
|
1556
|
+
checkFeature: () => true,
|
|
1557
|
+
getLimit: () => null
|
|
1558
|
+
});
|
|
1559
|
+
const useLicenseContext = () => (0, react.useContext)(LicenseContext);
|
|
1710
1560
|
|
|
1711
1561
|
//#endregion
|
|
1712
1562
|
//#region src/v2/hooks/use-render-tool-call.tsx
|
|
@@ -1762,10 +1612,13 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1762
1612
|
}, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
|
|
1763
1613
|
return (0, react.useCallback)(({ toolCall, toolMessage }) => {
|
|
1764
1614
|
const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
|
|
1615
|
+
const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
|
|
1616
|
+
if (!renderConfig) return null;
|
|
1617
|
+
const RenderComponent = renderConfig.render;
|
|
1765
1618
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
|
|
1766
1619
|
toolCall,
|
|
1767
1620
|
toolMessage,
|
|
1768
|
-
RenderComponent
|
|
1621
|
+
RenderComponent,
|
|
1769
1622
|
isExecuting: executingToolCallIds.has(toolCall.id)
|
|
1770
1623
|
}, toolCall.id);
|
|
1771
1624
|
}, [
|
|
@@ -1774,15 +1627,6 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1774
1627
|
agentId
|
|
1775
1628
|
]);
|
|
1776
1629
|
}
|
|
1777
|
-
function defaultToolCallRenderAdapter(props) {
|
|
1778
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultToolCallRenderer, {
|
|
1779
|
-
name: props.name,
|
|
1780
|
-
toolCallId: props.toolCallId,
|
|
1781
|
-
parameters: props.args,
|
|
1782
|
-
status: mapToolCallStatus(props.status),
|
|
1783
|
-
result: props.result
|
|
1784
|
-
});
|
|
1785
|
-
}
|
|
1786
1630
|
|
|
1787
1631
|
//#endregion
|
|
1788
1632
|
//#region src/v2/components/CopilotKitInspector.tsx
|
|
@@ -3264,7 +3108,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3264
3108
|
...A2UILifecycleFields
|
|
3265
3109
|
}).passthrough();
|
|
3266
3110
|
function createA2UIMessageRenderer(options) {
|
|
3267
|
-
const { theme, catalog, loadingComponent, recovery } = options;
|
|
3111
|
+
const { theme, catalog, loadingComponent, recovery, onAction } = options;
|
|
3268
3112
|
const showAfterMs = recovery?.showAfterMs ?? 2e3;
|
|
3269
3113
|
const showAfterAttempts = recovery?.showAfterAttempts ?? 2;
|
|
3270
3114
|
const optionDebugExposure = recovery?.debugExposure ?? "collapsed";
|
|
@@ -3340,6 +3184,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3340
3184
|
agent,
|
|
3341
3185
|
copilotkit,
|
|
3342
3186
|
catalog,
|
|
3187
|
+
onAction,
|
|
3343
3188
|
onReady: markSurfaceReady
|
|
3344
3189
|
}, surfaceId))
|
|
3345
3190
|
});
|
|
@@ -3360,29 +3205,60 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3360
3205
|
};
|
|
3361
3206
|
}
|
|
3362
3207
|
/**
|
|
3208
|
+
* Orchestrates a single A2UI user action: runs the optional `onAction`
|
|
3209
|
+
* interceptor first, then forwards to the agent unless the interceptor
|
|
3210
|
+
* suppressed it (returned `null`). Exported for unit testing; the wiring lives
|
|
3211
|
+
* in {@link ReactSurfaceHost}.
|
|
3212
|
+
*/
|
|
3213
|
+
async function runA2UIAction({ message, agent, copilotkit, onAction }) {
|
|
3214
|
+
if (!agent) return;
|
|
3215
|
+
const action = message.userAction;
|
|
3216
|
+
const forward = async (forwardAction) => {
|
|
3217
|
+
const a2uiAction = forwardAction !== void 0 ? {
|
|
3218
|
+
...message,
|
|
3219
|
+
userAction: forwardAction
|
|
3220
|
+
} : message;
|
|
3221
|
+
try {
|
|
3222
|
+
copilotkit.setProperties({
|
|
3223
|
+
...copilotkit.properties,
|
|
3224
|
+
a2uiAction
|
|
3225
|
+
});
|
|
3226
|
+
await copilotkit.runAgent({ agent });
|
|
3227
|
+
} finally {
|
|
3228
|
+
if (copilotkit.properties) {
|
|
3229
|
+
const { a2uiAction: _omit, ...rest } = copilotkit.properties;
|
|
3230
|
+
copilotkit.setProperties(rest);
|
|
3231
|
+
}
|
|
3232
|
+
}
|
|
3233
|
+
};
|
|
3234
|
+
if (onAction && action) {
|
|
3235
|
+
const result = await onAction(action, forward);
|
|
3236
|
+
if (result === null) return;
|
|
3237
|
+
if (result) {
|
|
3238
|
+
await forward(result);
|
|
3239
|
+
return;
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
await forward();
|
|
3243
|
+
}
|
|
3244
|
+
/**
|
|
3363
3245
|
* Renders a single A2UI surface using the React renderer.
|
|
3364
3246
|
* Wraps A2UIProvider + A2UIRenderer and bridges actions back to CopilotKit.
|
|
3365
3247
|
*/
|
|
3366
|
-
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog, onReady }) {
|
|
3248
|
+
function ReactSurfaceHost({ surfaceId, operations, theme, agent, copilotkit, catalog, onAction, onReady }) {
|
|
3367
3249
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
3368
3250
|
className: "cpk:flex cpk:w-full cpk:flex-none cpk:flex-col cpk:gap-4",
|
|
3369
3251
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(_copilotkit_a2ui_renderer.A2UIProvider, {
|
|
3370
|
-
onAction: (0, react.useCallback)(
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
if (copilotkit.properties) {
|
|
3381
|
-
const { a2uiAction, ...rest } = copilotkit.properties;
|
|
3382
|
-
copilotkit.setProperties(rest);
|
|
3383
|
-
}
|
|
3384
|
-
}
|
|
3385
|
-
}, [agent, copilotkit]),
|
|
3252
|
+
onAction: (0, react.useCallback)((message) => runA2UIAction({
|
|
3253
|
+
message,
|
|
3254
|
+
agent,
|
|
3255
|
+
copilotkit,
|
|
3256
|
+
onAction
|
|
3257
|
+
}), [
|
|
3258
|
+
agent,
|
|
3259
|
+
copilotkit,
|
|
3260
|
+
onAction
|
|
3261
|
+
]),
|
|
3386
3262
|
theme,
|
|
3387
3263
|
catalog,
|
|
3388
3264
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)(SurfaceMessageProcessor, {
|
|
@@ -3453,6 +3329,18 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3453
3329
|
return operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId ?? null;
|
|
3454
3330
|
}
|
|
3455
3331
|
|
|
3332
|
+
//#endregion
|
|
3333
|
+
//#region src/v2/types/defineToolCallRenderer.ts
|
|
3334
|
+
function defineToolCallRenderer(def) {
|
|
3335
|
+
const argsSchema = def.name === "*" && !def.args ? zod.z.any() : def.args;
|
|
3336
|
+
return {
|
|
3337
|
+
name: def.name,
|
|
3338
|
+
args: argsSchema,
|
|
3339
|
+
render: def.render,
|
|
3340
|
+
...def.agentId ? { agentId: def.agentId } : {}
|
|
3341
|
+
};
|
|
3342
|
+
}
|
|
3343
|
+
|
|
3456
3344
|
//#endregion
|
|
3457
3345
|
//#region src/v2/a2ui/A2UIToolCallRenderer.tsx
|
|
3458
3346
|
/**
|
|
@@ -3547,6 +3435,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3547
3435
|
|
|
3548
3436
|
//#endregion
|
|
3549
3437
|
//#region src/v2/providers/CopilotKitProvider.tsx
|
|
3438
|
+
const zodToJsonSchemaAdapter = (schema, options) => {
|
|
3439
|
+
const refStrategy = options?.$refStrategy;
|
|
3440
|
+
return (0, zod_to_json_schema.zodToJsonSchema)(schema, refStrategy === "root" || refStrategy === "relative" || refStrategy === "none" || refStrategy === "seen" ? { $refStrategy: refStrategy } : {});
|
|
3441
|
+
};
|
|
3550
3442
|
const HEADER_NAME = "X-CopilotCloud-Public-Api-Key";
|
|
3551
3443
|
const COPILOT_CLOUD_CHAT_URL$1 = "https://api.cloud.copilotkit.ai/copilotkit/v1";
|
|
3552
3444
|
const EMPTY_HEADERS = Object.freeze({});
|
|
@@ -3577,6 +3469,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3577
3469
|
const [runtimeA2UIEnabled, setRuntimeA2UIEnabled] = (0, react.useState)(false);
|
|
3578
3470
|
const [runtimeOpenGenUIEnabled, setRuntimeOpenGenUIEnabled] = (0, react.useState)(false);
|
|
3579
3471
|
const openGenUIActive = runtimeOpenGenUIEnabled || !!openGenerativeUI;
|
|
3472
|
+
const a2uiCatalogProvided = !!a2ui?.catalog;
|
|
3473
|
+
const a2uiActive = runtimeA2UIEnabled || a2uiCatalogProvided;
|
|
3580
3474
|
const [runtimeLicenseStatus, setRuntimeLicenseStatus] = (0, react.useState)(void 0);
|
|
3581
3475
|
(0, react.useEffect)(() => {
|
|
3582
3476
|
if (typeof window === "undefined") return;
|
|
@@ -3607,7 +3501,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3607
3501
|
content: OpenGenerativeUIContentSchema,
|
|
3608
3502
|
render: OpenGenerativeUIActivityRenderer
|
|
3609
3503
|
});
|
|
3610
|
-
if (
|
|
3504
|
+
if (a2uiActive) renderers.unshift(createA2UIMessageRenderer({
|
|
3611
3505
|
theme: a2ui?.theme ?? _copilotkit_a2ui_renderer.viewerTheme,
|
|
3612
3506
|
catalog: a2ui?.catalog,
|
|
3613
3507
|
loadingComponent: a2ui?.loadingComponent,
|
|
@@ -3615,7 +3509,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3615
3509
|
}));
|
|
3616
3510
|
return renderers;
|
|
3617
3511
|
}, [
|
|
3618
|
-
|
|
3512
|
+
a2uiActive,
|
|
3619
3513
|
openGenUIActive,
|
|
3620
3514
|
a2ui
|
|
3621
3515
|
]);
|
|
@@ -3802,7 +3696,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3802
3696
|
copilotkit.setRuntimeTransport(useSingleEndpoint === true ? "single" : useSingleEndpoint === false ? "rest" : "auto");
|
|
3803
3697
|
copilotkit.setHeaders(mergedHeaders);
|
|
3804
3698
|
copilotkit.setCredentials(credentials);
|
|
3805
|
-
copilotkit.setProperties(
|
|
3699
|
+
copilotkit.setProperties(a2uiCatalogProvided ? {
|
|
3700
|
+
...properties,
|
|
3701
|
+
a2uiCatalogAvailable: true
|
|
3702
|
+
} : properties);
|
|
3806
3703
|
copilotkit.setAgents__unsafe_dev_only(mergedAgents);
|
|
3807
3704
|
copilotkit.setDebug(debug);
|
|
3808
3705
|
}, [
|
|
@@ -3811,6 +3708,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3811
3708
|
mergedHeaders,
|
|
3812
3709
|
credentials,
|
|
3813
3710
|
properties,
|
|
3711
|
+
a2uiCatalogProvided,
|
|
3814
3712
|
mergedAgents,
|
|
3815
3713
|
useSingleEndpoint,
|
|
3816
3714
|
debug
|
|
@@ -3858,7 +3756,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3858
3756
|
return JSON.stringify(sandboxFunctionsList.map((fn) => ({
|
|
3859
3757
|
name: fn.name,
|
|
3860
3758
|
description: fn.description,
|
|
3861
|
-
parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema:
|
|
3759
|
+
parameters: (0, _copilotkit_shared.schemaToJsonSchema)(fn.parameters, { zodToJsonSchema: zodToJsonSchemaAdapter })
|
|
3862
3760
|
})));
|
|
3863
3761
|
}, [sandboxFunctionsList]);
|
|
3864
3762
|
(0, react.useLayoutEffect)(() => {
|
|
@@ -3879,7 +3777,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3879
3777
|
copilotkit,
|
|
3880
3778
|
executingToolCallIds
|
|
3881
3779
|
}), [copilotkit, executingToolCallIds]);
|
|
3882
|
-
const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(
|
|
3780
|
+
const licenseContextValue = (0, react.useMemo)(() => (0, _copilotkit_shared.createLicenseContextValue)(runtimeLicenseStatus), [runtimeLicenseStatus]);
|
|
3883
3781
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(SandboxFunctionsContext.Provider, {
|
|
3884
3782
|
value: sandboxFunctionsList,
|
|
3885
3783
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitContext.Provider, {
|
|
@@ -3887,8 +3785,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3887
3785
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(LicenseContext.Provider, {
|
|
3888
3786
|
value: licenseContextValue,
|
|
3889
3787
|
children: [
|
|
3890
|
-
|
|
3891
|
-
|
|
3788
|
+
a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UIBuiltInToolCallRenderer, {}),
|
|
3789
|
+
a2uiActive && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(A2UICatalogContext, {
|
|
3892
3790
|
catalog: a2ui?.catalog,
|
|
3893
3791
|
includeSchema: a2ui?.includeSchema
|
|
3894
3792
|
}),
|
|
@@ -3966,16 +3864,20 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3966
3864
|
const renderActivityMessage = (0, react.useCallback)((message) => {
|
|
3967
3865
|
const renderer = findRenderer(message.activityType);
|
|
3968
3866
|
if (!renderer) return null;
|
|
3969
|
-
const parseResult = renderer.content.
|
|
3970
|
-
if (
|
|
3971
|
-
console.warn(`
|
|
3867
|
+
const parseResult = renderer.content["~standard"].validate(message.content);
|
|
3868
|
+
if (parseResult instanceof Promise) {
|
|
3869
|
+
console.warn(`Async content validation is not supported for activity message '${message.activityType}'`);
|
|
3870
|
+
return null;
|
|
3871
|
+
}
|
|
3872
|
+
if (parseResult.issues) {
|
|
3873
|
+
console.warn(`Failed to parse content for activity message '${message.activityType}':`, parseResult.issues);
|
|
3972
3874
|
return null;
|
|
3973
3875
|
}
|
|
3974
3876
|
const Component = renderer.render;
|
|
3975
3877
|
const agent = copilotkit.getAgent(agentId);
|
|
3976
3878
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, {
|
|
3977
3879
|
activityType: message.activityType,
|
|
3978
|
-
content: parseResult.
|
|
3880
|
+
content: parseResult.value,
|
|
3979
3881
|
message,
|
|
3980
3882
|
agent
|
|
3981
3883
|
}, message.id);
|
|
@@ -3992,10 +3894,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3992
3894
|
|
|
3993
3895
|
//#endregion
|
|
3994
3896
|
//#region src/v2/hooks/use-frontend-tool.tsx
|
|
3995
|
-
const EMPTY_DEPS = [];
|
|
3897
|
+
const EMPTY_DEPS$1 = [];
|
|
3996
3898
|
function useFrontendTool(tool, deps) {
|
|
3997
3899
|
const { copilotkit } = useCopilotKit();
|
|
3998
|
-
const extraDeps = deps ?? EMPTY_DEPS;
|
|
3900
|
+
const extraDeps = deps ?? EMPTY_DEPS$1;
|
|
3999
3901
|
(0, react.useEffect)(() => {
|
|
4000
3902
|
const name = tool.name;
|
|
4001
3903
|
if (copilotkit.getTool({
|
|
@@ -4075,21 +3977,291 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4075
3977
|
* );
|
|
4076
3978
|
* ```
|
|
4077
3979
|
*/
|
|
4078
|
-
function useComponent(config, deps) {
|
|
4079
|
-
const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
|
|
4080
|
-
const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
|
|
4081
|
-
useFrontendTool({
|
|
4082
|
-
name: config.name,
|
|
4083
|
-
description: fullDescription,
|
|
4084
|
-
parameters: config.parameters,
|
|
4085
|
-
render: ({ args }) => {
|
|
4086
|
-
const Component = config.render;
|
|
4087
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { ...args });
|
|
4088
|
-
},
|
|
4089
|
-
agentId: config.agentId,
|
|
4090
|
-
followUp: config.followUp
|
|
3980
|
+
function useComponent(config, deps) {
|
|
3981
|
+
const prefix = `Use this tool to display the "${config.name}" component in the chat. This tool renders a visual UI component for the user.`;
|
|
3982
|
+
const fullDescription = config.description ? `${prefix}\n\n${config.description}` : prefix;
|
|
3983
|
+
useFrontendTool({
|
|
3984
|
+
name: config.name,
|
|
3985
|
+
description: fullDescription,
|
|
3986
|
+
parameters: config.parameters,
|
|
3987
|
+
render: ({ args }) => {
|
|
3988
|
+
const Component = config.render;
|
|
3989
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(Component, { ...args });
|
|
3990
|
+
},
|
|
3991
|
+
agentId: config.agentId,
|
|
3992
|
+
followUp: config.followUp
|
|
3993
|
+
}, deps);
|
|
3994
|
+
}
|
|
3995
|
+
|
|
3996
|
+
//#endregion
|
|
3997
|
+
//#region src/v2/hooks/use-render-tool.tsx
|
|
3998
|
+
const EMPTY_DEPS = [];
|
|
3999
|
+
/**
|
|
4000
|
+
* Registers a renderer entry in CopilotKit's `renderToolCalls` registry.
|
|
4001
|
+
*
|
|
4002
|
+
* Key behavior:
|
|
4003
|
+
* - deduplicates by `agentId:name` (latest registration wins),
|
|
4004
|
+
* - keeps renderer entries on cleanup so historical chat tool calls can still render,
|
|
4005
|
+
* - refreshes registration when `deps` change.
|
|
4006
|
+
*
|
|
4007
|
+
* @typeParam S - Schema type describing tool call parameters.
|
|
4008
|
+
* @param config - Renderer config for wildcard or named tools.
|
|
4009
|
+
* @param deps - Optional dependencies to refresh registration.
|
|
4010
|
+
*
|
|
4011
|
+
* @example
|
|
4012
|
+
* ```tsx
|
|
4013
|
+
* useRenderTool(
|
|
4014
|
+
* {
|
|
4015
|
+
* name: "searchDocs",
|
|
4016
|
+
* parameters: z.object({ query: z.string() }),
|
|
4017
|
+
* render: ({ status, parameters, result }) => {
|
|
4018
|
+
* if (status === "executing") return <div>Searching {parameters.query}</div>;
|
|
4019
|
+
* if (status === "complete") return <div>{result}</div>;
|
|
4020
|
+
* return <div>Preparing...</div>;
|
|
4021
|
+
* },
|
|
4022
|
+
* },
|
|
4023
|
+
* [],
|
|
4024
|
+
* );
|
|
4025
|
+
* ```
|
|
4026
|
+
*
|
|
4027
|
+
* @example
|
|
4028
|
+
* ```tsx
|
|
4029
|
+
* useRenderTool(
|
|
4030
|
+
* {
|
|
4031
|
+
* name: "summarize",
|
|
4032
|
+
* parameters: z.object({ text: z.string() }),
|
|
4033
|
+
* agentId: "research-agent",
|
|
4034
|
+
* render: ({ name, status }) => <div>{name}: {status}</div>,
|
|
4035
|
+
* },
|
|
4036
|
+
* [selectedAgentId],
|
|
4037
|
+
* );
|
|
4038
|
+
* ```
|
|
4039
|
+
*/
|
|
4040
|
+
function useRenderTool(config, deps) {
|
|
4041
|
+
const { copilotkit } = useCopilotKit();
|
|
4042
|
+
const extraDeps = deps ?? EMPTY_DEPS;
|
|
4043
|
+
(0, react.useEffect)(() => {
|
|
4044
|
+
const renderer = config.name === "*" && !config.parameters ? defineToolCallRenderer({
|
|
4045
|
+
name: "*",
|
|
4046
|
+
render: (props) => config.render({
|
|
4047
|
+
...props,
|
|
4048
|
+
parameters: props.args
|
|
4049
|
+
}),
|
|
4050
|
+
...config.agentId ? { agentId: config.agentId } : {}
|
|
4051
|
+
}) : defineToolCallRenderer({
|
|
4052
|
+
name: config.name,
|
|
4053
|
+
args: config.parameters,
|
|
4054
|
+
render: (props) => {
|
|
4055
|
+
if (props.status === _copilotkit_core.ToolCallStatus.InProgress) return config.render({
|
|
4056
|
+
...props,
|
|
4057
|
+
parameters: props.args
|
|
4058
|
+
});
|
|
4059
|
+
if (props.status === _copilotkit_core.ToolCallStatus.Executing) return config.render({
|
|
4060
|
+
...props,
|
|
4061
|
+
parameters: props.args
|
|
4062
|
+
});
|
|
4063
|
+
return config.render({
|
|
4064
|
+
...props,
|
|
4065
|
+
parameters: props.args
|
|
4066
|
+
});
|
|
4067
|
+
},
|
|
4068
|
+
...config.agentId ? { agentId: config.agentId } : {}
|
|
4069
|
+
});
|
|
4070
|
+
copilotkit.addHookRenderToolCall(renderer);
|
|
4071
|
+
}, [
|
|
4072
|
+
config.name,
|
|
4073
|
+
copilotkit,
|
|
4074
|
+
JSON.stringify(extraDeps)
|
|
4075
|
+
]);
|
|
4076
|
+
}
|
|
4077
|
+
|
|
4078
|
+
//#endregion
|
|
4079
|
+
//#region src/v2/hooks/use-default-render-tool.tsx
|
|
4080
|
+
/**
|
|
4081
|
+
* Module-level dedup set so an unknown status value only emits a console
|
|
4082
|
+
* warning the FIRST time we encounter it. Otherwise a stuck/unmapped status
|
|
4083
|
+
* would log on every re-render (potentially many per second).
|
|
4084
|
+
*/
|
|
4085
|
+
const warnedUnknownStatuses = /* @__PURE__ */ new Set();
|
|
4086
|
+
/**
|
|
4087
|
+
* Map a {@link ToolCallStatus} enum value to the documented string-union
|
|
4088
|
+
* status the {@link DefaultRenderProps} contract exposes. Unknown / future
|
|
4089
|
+
* enum members log a warning (once per distinct value) and fall back to
|
|
4090
|
+
* `"inProgress"`.
|
|
4091
|
+
*/
|
|
4092
|
+
function mapToolCallStatus(status) {
|
|
4093
|
+
switch (status) {
|
|
4094
|
+
case _copilotkit_core.ToolCallStatus.Complete: return "complete";
|
|
4095
|
+
case _copilotkit_core.ToolCallStatus.Executing: return "executing";
|
|
4096
|
+
case _copilotkit_core.ToolCallStatus.InProgress: return "inProgress";
|
|
4097
|
+
default: {
|
|
4098
|
+
const key = String(status);
|
|
4099
|
+
if (!warnedUnknownStatuses.has(key)) {
|
|
4100
|
+
warnedUnknownStatuses.add(key);
|
|
4101
|
+
console.warn(`[CopilotKit] Unknown ToolCallStatus "${key}" in default tool-call renderer; falling back to "inProgress".`);
|
|
4102
|
+
}
|
|
4103
|
+
return "inProgress";
|
|
4104
|
+
}
|
|
4105
|
+
}
|
|
4106
|
+
}
|
|
4107
|
+
/**
|
|
4108
|
+
* Convert the framework-internal renderer props (`args`, enum status) into
|
|
4109
|
+
* the documented {@link DefaultRenderProps} shape (`parameters`, string-union
|
|
4110
|
+
* status) so a user `config.render` always sees the documented contract.
|
|
4111
|
+
*/
|
|
4112
|
+
function adaptRendererProps(props) {
|
|
4113
|
+
return {
|
|
4114
|
+
name: props.name,
|
|
4115
|
+
toolCallId: props.toolCallId,
|
|
4116
|
+
parameters: props.args,
|
|
4117
|
+
status: mapToolCallStatus(props.status),
|
|
4118
|
+
result: props.result
|
|
4119
|
+
};
|
|
4120
|
+
}
|
|
4121
|
+
/**
|
|
4122
|
+
* Registers a wildcard (`"*"`) tool-call renderer via `useRenderTool`.
|
|
4123
|
+
*
|
|
4124
|
+
* - Call with no config to use CopilotKit's built-in default tool-call card.
|
|
4125
|
+
* - Pass `config.render` to replace the default UI with your own fallback renderer.
|
|
4126
|
+
*
|
|
4127
|
+
* This is useful when you want a generic renderer for tools that do not have a
|
|
4128
|
+
* dedicated `useRenderTool({ name: "..." })` registration.
|
|
4129
|
+
*
|
|
4130
|
+
* @param config - Optional custom wildcard render function.
|
|
4131
|
+
* @param deps - Optional dependencies to refresh registration.
|
|
4132
|
+
*
|
|
4133
|
+
* @example
|
|
4134
|
+
* ```tsx
|
|
4135
|
+
* useDefaultRenderTool();
|
|
4136
|
+
* ```
|
|
4137
|
+
*
|
|
4138
|
+
* @example
|
|
4139
|
+
* ```tsx
|
|
4140
|
+
* useDefaultRenderTool({
|
|
4141
|
+
* render: ({ name, status }) => <div>{name}: {status}</div>,
|
|
4142
|
+
* });
|
|
4143
|
+
* ```
|
|
4144
|
+
*
|
|
4145
|
+
* @example
|
|
4146
|
+
* ```tsx
|
|
4147
|
+
* useDefaultRenderTool(
|
|
4148
|
+
* {
|
|
4149
|
+
* render: ({ name, result }) => (
|
|
4150
|
+
* <ToolEventRow title={name} payload={result} compact={compactMode} />
|
|
4151
|
+
* ),
|
|
4152
|
+
* },
|
|
4153
|
+
* [compactMode],
|
|
4154
|
+
* );
|
|
4155
|
+
* ```
|
|
4156
|
+
*/
|
|
4157
|
+
function useDefaultRenderTool(config, deps) {
|
|
4158
|
+
const userRender = config?.render;
|
|
4159
|
+
useRenderTool({
|
|
4160
|
+
name: "*",
|
|
4161
|
+
render: userRender ? (raw) => userRender(adaptRendererProps(raw)) : (raw) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DefaultToolCallRenderer, { ...adaptRendererProps(raw) })
|
|
4091
4162
|
}, deps);
|
|
4092
4163
|
}
|
|
4164
|
+
/**
|
|
4165
|
+
* Guarded JSON.stringify used inside the expanded `<pre>` blocks. A circular
|
|
4166
|
+
* reference would otherwise crash the entire React tree on render.
|
|
4167
|
+
*/
|
|
4168
|
+
function safeStringifyForPre(value) {
|
|
4169
|
+
try {
|
|
4170
|
+
return JSON.stringify(value, null, 2);
|
|
4171
|
+
} catch (err) {
|
|
4172
|
+
console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for default renderer; falling back to String():", err);
|
|
4173
|
+
try {
|
|
4174
|
+
return String(value);
|
|
4175
|
+
} catch (innerErr) {
|
|
4176
|
+
console.warn("[CopilotKit] safeStringifyForPre: value could not be stringified:", innerErr);
|
|
4177
|
+
return "[unserializable]";
|
|
4178
|
+
}
|
|
4179
|
+
}
|
|
4180
|
+
}
|
|
4181
|
+
function DefaultToolCallRenderer({ name, toolCallId, parameters, status, result }) {
|
|
4182
|
+
const [isExpanded, setIsExpanded] = (0, react.useState)(false);
|
|
4183
|
+
const isActive = status === "inProgress" || status === "executing";
|
|
4184
|
+
const isComplete = status === "complete";
|
|
4185
|
+
const statusLabel = isActive ? "Running" : isComplete ? "Done" : status;
|
|
4186
|
+
const dotClassName = isActive ? "cpk:bg-amber-500" : isComplete ? "cpk:bg-emerald-500" : "cpk:bg-zinc-400";
|
|
4187
|
+
const badgeClassName = isActive ? "cpk:bg-amber-100 cpk:text-amber-800 cpk:dark:bg-amber-500/15 cpk:dark:text-amber-400" : isComplete ? "cpk:bg-emerald-100 cpk:text-emerald-800 cpk:dark:bg-emerald-500/15 cpk:dark:text-emerald-400" : "cpk:bg-zinc-100 cpk:text-zinc-800 cpk:dark:bg-zinc-700/40 cpk:dark:text-zinc-300";
|
|
4188
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4189
|
+
"data-testid": "copilot-tool-render",
|
|
4190
|
+
"data-tool-name": name,
|
|
4191
|
+
"data-tool-call-id": toolCallId,
|
|
4192
|
+
"data-status": status,
|
|
4193
|
+
"data-args": safeStringifyForAttr(parameters),
|
|
4194
|
+
"data-result": safeStringifyForAttr(result),
|
|
4195
|
+
className: "cpk:mt-2 cpk:pb-2",
|
|
4196
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4197
|
+
className: "cpk:rounded-xl cpk:border cpk:border-zinc-200/60 cpk:bg-white/70 cpk:p-4 cpk:shadow-sm cpk:backdrop-blur cpk:dark:border-zinc-800/60 cpk:dark:bg-zinc-900/50",
|
|
4198
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("button", {
|
|
4199
|
+
type: "button",
|
|
4200
|
+
"aria-expanded": isExpanded,
|
|
4201
|
+
onClick: () => setIsExpanded(!isExpanded),
|
|
4202
|
+
className: "cpk:flex cpk:w-full cpk:cursor-pointer cpk:select-none cpk:items-center cpk:justify-between cpk:gap-2.5 cpk:border-none cpk:bg-transparent cpk:p-0 cpk:m-0 cpk:text-left cpk:text-inherit",
|
|
4203
|
+
style: { font: "inherit" },
|
|
4204
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4205
|
+
className: "cpk:flex cpk:min-w-0 cpk:items-center cpk:gap-2",
|
|
4206
|
+
children: [
|
|
4207
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("svg", {
|
|
4208
|
+
className: `cpk:h-3.5 cpk:w-3.5 cpk:flex-shrink-0 cpk:text-zinc-500 cpk:transition-transform cpk:dark:text-zinc-400 ${isExpanded ? "cpk:rotate-90" : ""}`,
|
|
4209
|
+
fill: "none",
|
|
4210
|
+
viewBox: "0 0 24 24",
|
|
4211
|
+
strokeWidth: 2,
|
|
4212
|
+
stroke: "currentColor",
|
|
4213
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("path", {
|
|
4214
|
+
strokeLinecap: "round",
|
|
4215
|
+
strokeLinejoin: "round",
|
|
4216
|
+
d: "M8.25 4.5l7.5 7.5-7.5 7.5"
|
|
4217
|
+
})
|
|
4218
|
+
}),
|
|
4219
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { className: `cpk:inline-block cpk:h-2 cpk:w-2 cpk:flex-shrink-0 cpk:rounded-full ${dotClassName}` }),
|
|
4220
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4221
|
+
"data-testid": "copilot-tool-render-name",
|
|
4222
|
+
className: "cpk:truncate cpk:text-[13px] cpk:font-semibold cpk:text-zinc-900 cpk:dark:text-zinc-100",
|
|
4223
|
+
children: name
|
|
4224
|
+
})
|
|
4225
|
+
]
|
|
4226
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", {
|
|
4227
|
+
"data-testid": "copilot-tool-render-status",
|
|
4228
|
+
className: `cpk:inline-flex cpk:flex-shrink-0 cpk:items-center cpk:rounded-full cpk:px-2 cpk:py-0.5 cpk:text-[11px] cpk:font-medium ${badgeClassName}`,
|
|
4229
|
+
children: statusLabel
|
|
4230
|
+
})]
|
|
4231
|
+
}), isExpanded && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4232
|
+
className: "cpk:mt-3 cpk:grid cpk:gap-3",
|
|
4233
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4234
|
+
className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
|
|
4235
|
+
children: "Arguments"
|
|
4236
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
4237
|
+
className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
|
|
4238
|
+
children: safeStringifyForPre(parameters ?? {})
|
|
4239
|
+
})] }), result !== void 0 && /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", { children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
4240
|
+
className: "cpk:text-[10px] cpk:uppercase cpk:text-zinc-500 cpk:dark:text-zinc-400",
|
|
4241
|
+
children: "Result"
|
|
4242
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("pre", {
|
|
4243
|
+
className: "cpk:mt-1.5 cpk:max-h-[200px] cpk:overflow-auto cpk:rounded-md cpk:bg-zinc-100 cpk:p-2.5 cpk:text-[11px] cpk:leading-relaxed cpk:text-zinc-800 cpk:whitespace-pre-wrap cpk:break-words cpk:dark:bg-zinc-800/60 cpk:dark:text-zinc-200",
|
|
4244
|
+
children: typeof result === "string" ? result : safeStringifyForPre(result)
|
|
4245
|
+
})] })]
|
|
4246
|
+
})]
|
|
4247
|
+
})
|
|
4248
|
+
});
|
|
4249
|
+
}
|
|
4250
|
+
function safeStringifyForAttr(value) {
|
|
4251
|
+
if (value === void 0 || value === null) return "";
|
|
4252
|
+
if (typeof value === "string") return value;
|
|
4253
|
+
try {
|
|
4254
|
+
return JSON.stringify(value);
|
|
4255
|
+
} catch (err) {
|
|
4256
|
+
console.warn("[CopilotKit] Failed to JSON.stringify tool-call payload for data-* attribute; falling back to String():", err);
|
|
4257
|
+
try {
|
|
4258
|
+
return String(value);
|
|
4259
|
+
} catch (innerErr) {
|
|
4260
|
+
console.warn("[CopilotKit] safeStringifyForAttr: value could not be stringified:", innerErr);
|
|
4261
|
+
return "";
|
|
4262
|
+
}
|
|
4263
|
+
}
|
|
4264
|
+
}
|
|
4093
4265
|
|
|
4094
4266
|
//#endregion
|
|
4095
4267
|
//#region src/v2/hooks/use-human-in-the-loop.tsx
|
|
@@ -4211,7 +4383,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4211
4383
|
if (isRuntimeConfigured && (status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Disconnected || status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connecting)) {
|
|
4212
4384
|
const cached = provisionalAgentCache.current.get(agentId);
|
|
4213
4385
|
if (cached) {
|
|
4214
|
-
|
|
4386
|
+
copilotkit.applyHeadersToAgent(cached);
|
|
4215
4387
|
return cached;
|
|
4216
4388
|
}
|
|
4217
4389
|
const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
|
|
@@ -4220,14 +4392,14 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4220
4392
|
transport: copilotkit.runtimeTransport,
|
|
4221
4393
|
runtimeMode: "pending"
|
|
4222
4394
|
});
|
|
4223
|
-
|
|
4395
|
+
copilotkit.applyHeadersToAgent(provisional);
|
|
4224
4396
|
provisionalAgentCache.current.set(agentId, provisional);
|
|
4225
4397
|
return provisional;
|
|
4226
4398
|
}
|
|
4227
4399
|
if (isRuntimeConfigured && status === _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Error) {
|
|
4228
4400
|
const cached = provisionalAgentCache.current.get(agentId);
|
|
4229
4401
|
if (cached) {
|
|
4230
|
-
|
|
4402
|
+
copilotkit.applyHeadersToAgent(cached);
|
|
4231
4403
|
return cached;
|
|
4232
4404
|
}
|
|
4233
4405
|
const provisional = new _copilotkit_core.ProxiedCopilotRuntimeAgent({
|
|
@@ -4236,7 +4408,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4236
4408
|
transport: copilotkit.runtimeTransport,
|
|
4237
4409
|
runtimeMode: "pending"
|
|
4238
4410
|
});
|
|
4239
|
-
|
|
4411
|
+
copilotkit.applyHeadersToAgent(provisional);
|
|
4240
4412
|
provisionalAgentCache.current.set(agentId, provisional);
|
|
4241
4413
|
return provisional;
|
|
4242
4414
|
}
|
|
@@ -4287,7 +4459,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4287
4459
|
updateFlags
|
|
4288
4460
|
]);
|
|
4289
4461
|
(0, react.useEffect)(() => {
|
|
4290
|
-
if (agent instanceof _ag_ui_client.HttpAgent)
|
|
4462
|
+
if (agent instanceof _ag_ui_client.HttpAgent) copilotkit.applyHeadersToAgent(agent);
|
|
4291
4463
|
}, [agent, JSON.stringify(copilotkit.headers)]);
|
|
4292
4464
|
const chatConfig = useCopilotChatConfiguration();
|
|
4293
4465
|
const configThreadId = chatConfig?.threadId;
|
|
@@ -4564,114 +4736,165 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4564
4736
|
function isPromiseLike(value) {
|
|
4565
4737
|
return (typeof value === "object" || typeof value === "function") && value !== null && typeof Reflect.get(value, "then") === "function";
|
|
4566
4738
|
}
|
|
4739
|
+
/** Derive the legacy-compatible `event` for any pending interrupt. */
|
|
4740
|
+
function toLegacyEvent(pending) {
|
|
4741
|
+
if (pending.kind === "legacy") return pending.event;
|
|
4742
|
+
return {
|
|
4743
|
+
name: INTERRUPT_EVENT_NAME,
|
|
4744
|
+
value: pending.interrupts[0]
|
|
4745
|
+
};
|
|
4746
|
+
}
|
|
4567
4747
|
/**
|
|
4568
|
-
* Handles agent interrupts
|
|
4569
|
-
*
|
|
4570
|
-
* The hook listens to custom events on the active agent, stores interrupt payloads per run,
|
|
4571
|
-
* and surfaces a render callback once the run finalizes. Call `resolve` from your UI to resume
|
|
4572
|
-
* execution with user-provided data.
|
|
4573
|
-
*
|
|
4574
|
-
* - `renderInChat: true` (default): the element is published into `<CopilotChat>` and this hook returns `void`.
|
|
4575
|
-
* - `renderInChat: false`: the hook returns the interrupt element so you can place it anywhere in your component tree.
|
|
4576
|
-
*
|
|
4577
|
-
* `event.value` is typed as `any` since the interrupt payload shape depends on your agent.
|
|
4578
|
-
* Type-narrow it in your callbacks (e.g. `handler`, `enabled`, `render`) as needed.
|
|
4579
|
-
*
|
|
4580
|
-
* @typeParam TResult - Inferred from `handler` return type. Exposed as `result` in `render`.
|
|
4581
|
-
* @param config - Interrupt configuration (renderer, optional handler/filter, and render mode).
|
|
4582
|
-
* @returns When `renderInChat` is `false`, returns the interrupt element (or `null` when idle).
|
|
4583
|
-
* Otherwise returns `void` and publishes the element into chat. In `render`, `result` is always
|
|
4584
|
-
* either the handler's resolved return value or `null` (including when no handler is provided,
|
|
4585
|
-
* when filtering skips the interrupt, or when handler execution fails).
|
|
4586
|
-
*
|
|
4587
|
-
* @example
|
|
4588
|
-
* ```tsx
|
|
4589
|
-
* import { useInterrupt } from "@copilotkit/react-core/v2";
|
|
4748
|
+
* Handles agent interrupts with optional filtering, preprocessing, and resume behavior.
|
|
4590
4749
|
*
|
|
4591
|
-
*
|
|
4592
|
-
*
|
|
4593
|
-
*
|
|
4594
|
-
*
|
|
4595
|
-
*
|
|
4596
|
-
*
|
|
4597
|
-
*
|
|
4598
|
-
* </div>
|
|
4599
|
-
* ),
|
|
4600
|
-
* });
|
|
4750
|
+
* Supports both the AG-UI standard interrupt flow (`RUN_FINISHED` with
|
|
4751
|
+
* `outcome.type === "interrupt"`) and the legacy custom-event flow
|
|
4752
|
+
* (`on_interrupt`). For standard interrupts, `render` receives `interrupt`
|
|
4753
|
+
* (the primary one) and `interrupts` (the full open set); call `resolve(payload)`
|
|
4754
|
+
* to resume or `cancel()` to cancel. Resuming addresses the targeted interrupt
|
|
4755
|
+
* and, once every open interrupt is addressed, submits a single spec `resume`
|
|
4756
|
+
* array via `copilotkit.runAgent`.
|
|
4601
4757
|
*
|
|
4602
|
-
*
|
|
4603
|
-
*
|
|
4604
|
-
* ```
|
|
4758
|
+
* - `renderInChat: true` (default): the element is published into `<CopilotChat>`; returns `void`.
|
|
4759
|
+
* - `renderInChat: false`: the hook returns the interrupt element for manual placement.
|
|
4605
4760
|
*
|
|
4606
4761
|
* @example
|
|
4607
4762
|
* ```tsx
|
|
4608
|
-
*
|
|
4609
|
-
*
|
|
4610
|
-
*
|
|
4611
|
-
*
|
|
4612
|
-
*
|
|
4613
|
-
*
|
|
4614
|
-
*
|
|
4615
|
-
*
|
|
4616
|
-
*
|
|
4617
|
-
* <strong>{result?.label ?? ""}</strong>
|
|
4618
|
-
* <button onClick={() => resolve({ value: event.value })}>Continue</button>
|
|
4619
|
-
* </aside>
|
|
4620
|
-
* ),
|
|
4621
|
-
* });
|
|
4622
|
-
*
|
|
4623
|
-
* return <>{interruptElement}</>;
|
|
4624
|
-
* }
|
|
4763
|
+
* useInterrupt({
|
|
4764
|
+
* render: ({ interrupt, resolve, cancel }) => (
|
|
4765
|
+
* <div>
|
|
4766
|
+
* <p>{interrupt?.message}</p>
|
|
4767
|
+
* <button onClick={() => resolve({ approved: true })}>Approve</button>
|
|
4768
|
+
* <button onClick={() => cancel()}>Cancel</button>
|
|
4769
|
+
* </div>
|
|
4770
|
+
* ),
|
|
4771
|
+
* });
|
|
4625
4772
|
* ```
|
|
4626
4773
|
*/
|
|
4627
4774
|
function useInterrupt(config) {
|
|
4628
4775
|
const { copilotkit } = useCopilotKit();
|
|
4629
4776
|
const { agent } = useAgent({ agentId: config.agentId });
|
|
4630
|
-
const [
|
|
4631
|
-
const
|
|
4632
|
-
|
|
4777
|
+
const [pending, setPending] = (0, react.useState)(null);
|
|
4778
|
+
const pendingRef = (0, react.useRef)(pending);
|
|
4779
|
+
pendingRef.current = pending;
|
|
4633
4780
|
const [handlerResult, setHandlerResult] = (0, react.useState)(null);
|
|
4781
|
+
const responsesRef = (0, react.useRef)({});
|
|
4634
4782
|
(0, react.useEffect)(() => {
|
|
4635
|
-
let
|
|
4783
|
+
let localLegacy = null;
|
|
4784
|
+
let localStandard = null;
|
|
4636
4785
|
const subscription = agent.subscribe({
|
|
4637
4786
|
onCustomEvent: ({ event }) => {
|
|
4638
|
-
if (event.name === INTERRUPT_EVENT_NAME)
|
|
4787
|
+
if (event.name === INTERRUPT_EVENT_NAME) localLegacy = {
|
|
4639
4788
|
name: event.name,
|
|
4640
4789
|
value: event.value
|
|
4641
4790
|
};
|
|
4642
4791
|
},
|
|
4792
|
+
onRunFinishedEvent: (params) => {
|
|
4793
|
+
if (params.outcome === "interrupt") localStandard = params.interrupts;
|
|
4794
|
+
},
|
|
4643
4795
|
onRunStartedEvent: () => {
|
|
4644
|
-
|
|
4645
|
-
|
|
4796
|
+
localLegacy = null;
|
|
4797
|
+
localStandard = null;
|
|
4798
|
+
responsesRef.current = {};
|
|
4799
|
+
setPending(null);
|
|
4646
4800
|
},
|
|
4647
4801
|
onRunFinalized: () => {
|
|
4648
|
-
if (
|
|
4649
|
-
|
|
4650
|
-
|
|
4651
|
-
}
|
|
4802
|
+
if (localStandard && localStandard.length > 0) setPending({
|
|
4803
|
+
kind: "standard",
|
|
4804
|
+
interrupts: localStandard
|
|
4805
|
+
});
|
|
4806
|
+
else if (localLegacy) setPending({
|
|
4807
|
+
kind: "legacy",
|
|
4808
|
+
event: localLegacy
|
|
4809
|
+
});
|
|
4810
|
+
localLegacy = null;
|
|
4811
|
+
localStandard = null;
|
|
4652
4812
|
},
|
|
4653
4813
|
onRunFailed: () => {
|
|
4654
|
-
|
|
4655
|
-
|
|
4814
|
+
localLegacy = null;
|
|
4815
|
+
localStandard = null;
|
|
4816
|
+
responsesRef.current = {};
|
|
4817
|
+
setPending(null);
|
|
4656
4818
|
}
|
|
4657
4819
|
});
|
|
4658
4820
|
return () => subscription.unsubscribe();
|
|
4659
4821
|
}, [agent]);
|
|
4660
|
-
const
|
|
4822
|
+
const submitStandardIfComplete = (0, react.useCallback)(async (interrupts) => {
|
|
4823
|
+
if (!interrupts.every((i) => responsesRef.current[i.id])) return;
|
|
4824
|
+
const expired = interrupts.find((i) => (0, _ag_ui_client.isInterruptExpired)(i));
|
|
4825
|
+
if (expired) {
|
|
4826
|
+
console.error(`[CopilotKit] useInterrupt: interrupt ${expired.id} expired at ${expired.expiresAt}; not resuming.`);
|
|
4827
|
+
responsesRef.current = {};
|
|
4828
|
+
setPending(null);
|
|
4829
|
+
return;
|
|
4830
|
+
}
|
|
4831
|
+
const resume = (0, _ag_ui_client.buildResumeArray)(interrupts, responsesRef.current);
|
|
4832
|
+
for (const i of interrupts) {
|
|
4833
|
+
if (!i.toolCallId) continue;
|
|
4834
|
+
const response = responsesRef.current[i.id];
|
|
4835
|
+
const content = response.status === "cancelled" ? { status: "cancelled" } : response.payload ?? { status: "resolved" };
|
|
4836
|
+
agent.addMessage({
|
|
4837
|
+
id: (0, _ag_ui_client.randomUUID)(),
|
|
4838
|
+
role: "tool",
|
|
4839
|
+
toolCallId: i.toolCallId,
|
|
4840
|
+
content: JSON.stringify(content)
|
|
4841
|
+
});
|
|
4842
|
+
}
|
|
4843
|
+
responsesRef.current = {};
|
|
4661
4844
|
try {
|
|
4845
|
+
return await copilotkit.runAgent({
|
|
4846
|
+
agent,
|
|
4847
|
+
resume
|
|
4848
|
+
});
|
|
4849
|
+
} catch (err) {
|
|
4850
|
+
console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
|
|
4851
|
+
setPending(null);
|
|
4852
|
+
throw err;
|
|
4853
|
+
}
|
|
4854
|
+
}, [agent, copilotkit]);
|
|
4855
|
+
const resolve = (0, react.useCallback)(async (payload, interruptId) => {
|
|
4856
|
+
const current = pendingRef.current;
|
|
4857
|
+
if (!current) return;
|
|
4858
|
+
if (current.kind === "legacy") try {
|
|
4662
4859
|
return await copilotkit.runAgent({
|
|
4663
4860
|
agent,
|
|
4664
4861
|
forwardedProps: { command: {
|
|
4665
|
-
resume:
|
|
4666
|
-
interruptEvent:
|
|
4862
|
+
resume: payload,
|
|
4863
|
+
interruptEvent: current.event.value
|
|
4667
4864
|
} }
|
|
4668
4865
|
});
|
|
4669
4866
|
} catch (err) {
|
|
4670
4867
|
console.error("[CopilotKit] useInterrupt resolve: runAgent rejected; clearing pending + rethrowing", err);
|
|
4671
|
-
|
|
4868
|
+
setPending(null);
|
|
4672
4869
|
throw err;
|
|
4673
4870
|
}
|
|
4674
|
-
|
|
4871
|
+
if (current.interrupts.length > 1 && interruptId === void 0) console.warn(`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`);
|
|
4872
|
+
const id = interruptId ?? current.interrupts[0]?.id;
|
|
4873
|
+
if (!id) return;
|
|
4874
|
+
responsesRef.current[id] = {
|
|
4875
|
+
status: "resolved",
|
|
4876
|
+
payload
|
|
4877
|
+
};
|
|
4878
|
+
return submitStandardIfComplete(current.interrupts);
|
|
4879
|
+
}, [
|
|
4880
|
+
agent,
|
|
4881
|
+
copilotkit,
|
|
4882
|
+
submitStandardIfComplete
|
|
4883
|
+
]);
|
|
4884
|
+
const cancel = (0, react.useCallback)(async (interruptId) => {
|
|
4885
|
+
const current = pendingRef.current;
|
|
4886
|
+
if (!current) return;
|
|
4887
|
+
if (current.kind === "legacy") {
|
|
4888
|
+
console.warn("[CopilotKit] useInterrupt: cancel() is not supported for legacy on_interrupt interrupts; dismissing.");
|
|
4889
|
+
setPending(null);
|
|
4890
|
+
return;
|
|
4891
|
+
}
|
|
4892
|
+
if (current.interrupts.length > 1 && interruptId === void 0) console.warn(`[CopilotKit] useInterrupt: resolve()/cancel() called without an interruptId while ${current.interrupts.length} interrupts are open; defaulting to the first. Pass an interruptId to address a specific interrupt.`);
|
|
4893
|
+
const id = interruptId ?? current.interrupts[0]?.id;
|
|
4894
|
+
if (!id) return;
|
|
4895
|
+
responsesRef.current[id] = { status: "cancelled" };
|
|
4896
|
+
return submitStandardIfComplete(current.interrupts);
|
|
4897
|
+
}, [submitStandardIfComplete]);
|
|
4675
4898
|
const renderRef = (0, react.useRef)(config.render);
|
|
4676
4899
|
renderRef.current = config.render;
|
|
4677
4900
|
const enabledRef = (0, react.useRef)(config.enabled);
|
|
@@ -4680,6 +4903,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4680
4903
|
handlerRef.current = config.handler;
|
|
4681
4904
|
const resolveRef = (0, react.useRef)(resolve);
|
|
4682
4905
|
resolveRef.current = resolve;
|
|
4906
|
+
const cancelRef = (0, react.useRef)(cancel);
|
|
4907
|
+
cancelRef.current = cancel;
|
|
4683
4908
|
const isEnabled = (event) => {
|
|
4684
4909
|
const predicate = enabledRef.current;
|
|
4685
4910
|
if (!predicate) return true;
|
|
@@ -4691,11 +4916,12 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4691
4916
|
}
|
|
4692
4917
|
};
|
|
4693
4918
|
(0, react.useEffect)(() => {
|
|
4694
|
-
if (!
|
|
4919
|
+
if (!pending) {
|
|
4695
4920
|
setHandlerResult(null);
|
|
4696
4921
|
return;
|
|
4697
4922
|
}
|
|
4698
|
-
|
|
4923
|
+
const legacyEvent = toLegacyEvent(pending);
|
|
4924
|
+
if (!isEnabled(legacyEvent)) {
|
|
4699
4925
|
setHandlerResult(null);
|
|
4700
4926
|
return;
|
|
4701
4927
|
}
|
|
@@ -4708,8 +4934,11 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4708
4934
|
let maybePromise;
|
|
4709
4935
|
try {
|
|
4710
4936
|
maybePromise = handler({
|
|
4711
|
-
event:
|
|
4712
|
-
|
|
4937
|
+
event: legacyEvent,
|
|
4938
|
+
interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
|
|
4939
|
+
interrupts: pending.kind === "standard" ? pending.interrupts : [],
|
|
4940
|
+
resolve: resolveRef.current,
|
|
4941
|
+
cancel: cancelRef.current
|
|
4713
4942
|
});
|
|
4714
4943
|
} catch (err) {
|
|
4715
4944
|
console.error("[CopilotKit] useInterrupt handler threw; result will be null:", err);
|
|
@@ -4728,19 +4957,24 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4728
4957
|
return () => {
|
|
4729
4958
|
cancelled = true;
|
|
4730
4959
|
};
|
|
4731
|
-
}, [
|
|
4960
|
+
}, [pending]);
|
|
4732
4961
|
const element = (0, react.useMemo)(() => {
|
|
4733
|
-
if (!
|
|
4734
|
-
|
|
4962
|
+
if (!pending) return null;
|
|
4963
|
+
const legacyEvent = toLegacyEvent(pending);
|
|
4964
|
+
if (!isEnabled(legacyEvent)) return null;
|
|
4735
4965
|
return renderRef.current({
|
|
4736
|
-
event:
|
|
4966
|
+
event: legacyEvent,
|
|
4967
|
+
interrupt: pending.kind === "standard" ? pending.interrupts[0] : null,
|
|
4968
|
+
interrupts: pending.kind === "standard" ? pending.interrupts : [],
|
|
4737
4969
|
result: handlerResult,
|
|
4738
|
-
resolve
|
|
4970
|
+
resolve,
|
|
4971
|
+
cancel
|
|
4739
4972
|
});
|
|
4740
4973
|
}, [
|
|
4741
|
-
|
|
4974
|
+
pending,
|
|
4742
4975
|
handlerResult,
|
|
4743
|
-
resolve
|
|
4976
|
+
resolve,
|
|
4977
|
+
cancel
|
|
4744
4978
|
]);
|
|
4745
4979
|
(0, react.useEffect)(() => {
|
|
4746
4980
|
if (config.renderInChat === false) return;
|
|
@@ -4765,7 +4999,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4765
4999
|
return (0, react.useSyncExternalStore)((0, react.useCallback)((onStoreChange) => {
|
|
4766
5000
|
const subscription = store.select(selector).subscribe(onStoreChange);
|
|
4767
5001
|
return () => subscription.unsubscribe();
|
|
4768
|
-
}, [store, selector]), () => selector(store.getState()));
|
|
5002
|
+
}, [store, selector]), () => selector(store.getState()), () => selector(store.getServerState()));
|
|
4769
5003
|
}
|
|
4770
5004
|
/**
|
|
4771
5005
|
* React hook for listing and managing Intelligence platform threads.
|
|
@@ -4776,9 +5010,9 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4776
5010
|
* current without polling — thread creates, renames, archives, and deletes
|
|
4777
5011
|
* from any client are reflected immediately.
|
|
4778
5012
|
*
|
|
4779
|
-
* Mutation methods (`renameThread`, `archiveThread`, `
|
|
4780
|
-
* promises that resolve once the platform confirms the
|
|
4781
|
-
* with an `Error` on failure.
|
|
5013
|
+
* Mutation methods (`renameThread`, `archiveThread`, `unarchiveThread`,
|
|
5014
|
+
* `deleteThread`) return promises that resolve once the platform confirms the
|
|
5015
|
+
* operation and reject with an `Error` on failure.
|
|
4782
5016
|
*
|
|
4783
5017
|
* @param input - Agent identifier and optional list controls.
|
|
4784
5018
|
* @returns Thread list state and stable mutation callbacks.
|
|
@@ -4808,7 +5042,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4808
5042
|
* }
|
|
4809
5043
|
* ```
|
|
4810
5044
|
*/
|
|
4811
|
-
function useThreads({ agentId, includeArchived, limit }) {
|
|
5045
|
+
function useThreads({ agentId, includeArchived, limit, enabled = true }) {
|
|
4812
5046
|
const { copilotkit } = useCopilotKit();
|
|
4813
5047
|
const [store] = (0, react.useState)(() => (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: globalThis.fetch }));
|
|
4814
5048
|
const coreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreads);
|
|
@@ -4825,6 +5059,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4825
5059
|
const storeError = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsError);
|
|
4826
5060
|
const hasMoreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectHasNextPage);
|
|
4827
5061
|
const isFetchingMoreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectIsFetchingNextPage);
|
|
5062
|
+
const isMutating = useThreadStoreSelector(store, _copilotkit_core.ɵselectIsMutating);
|
|
4828
5063
|
const headersKey = (0, react.useMemo)(() => {
|
|
4829
5064
|
return JSON.stringify(Object.entries(copilotkit.headers ?? {}).sort(([left], [right]) => left.localeCompare(right)));
|
|
4830
5065
|
}, [copilotkit.headers]);
|
|
@@ -4845,9 +5080,16 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4845
5080
|
return /* @__PURE__ */ new Error("Thread mutations are not available on this CopilotKit runtime");
|
|
4846
5081
|
}, [threadMutationsSupported]);
|
|
4847
5082
|
const [hasDispatchedContext, setHasDispatchedContext] = (0, react.useState)(false);
|
|
4848
|
-
const preConnectLoading = !!copilotkit.runtimeUrl && !threadEndpointsUnavailable && !hasDispatchedContext;
|
|
4849
|
-
const
|
|
4850
|
-
|
|
5083
|
+
const preConnectLoading = enabled && !!copilotkit.runtimeUrl && !threadEndpointsUnavailable && !hasDispatchedContext;
|
|
5084
|
+
const [configErrorDismissed, setConfigErrorDismissed] = (0, react.useState)(false);
|
|
5085
|
+
(0, react.useEffect)(() => {
|
|
5086
|
+
setConfigErrorDismissed(false);
|
|
5087
|
+
}, [runtimeError, threadEndpointsError]);
|
|
5088
|
+
const activeRuntimeError = configErrorDismissed ? null : runtimeError;
|
|
5089
|
+
const activeThreadEndpointsError = configErrorDismissed ? null : threadEndpointsError;
|
|
5090
|
+
const isLoading = activeRuntimeError || activeThreadEndpointsError ? false : preConnectLoading || storeIsLoading;
|
|
5091
|
+
const error = activeRuntimeError ?? activeThreadEndpointsError ?? storeError;
|
|
5092
|
+
const listError = storeError;
|
|
4851
5093
|
(0, react.useEffect)(() => {
|
|
4852
5094
|
store.start();
|
|
4853
5095
|
return () => {
|
|
@@ -4855,6 +5097,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4855
5097
|
};
|
|
4856
5098
|
}, [store]);
|
|
4857
5099
|
(0, react.useEffect)(() => {
|
|
5100
|
+
if (!enabled) return;
|
|
4858
5101
|
copilotkit.registerThreadStore(agentId, store);
|
|
4859
5102
|
return () => {
|
|
4860
5103
|
copilotkit.unregisterThreadStore(agentId);
|
|
@@ -4862,9 +5105,15 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4862
5105
|
}, [
|
|
4863
5106
|
copilotkit,
|
|
4864
5107
|
agentId,
|
|
4865
|
-
store
|
|
5108
|
+
store,
|
|
5109
|
+
enabled
|
|
4866
5110
|
]);
|
|
4867
5111
|
(0, react.useEffect)(() => {
|
|
5112
|
+
if (!enabled) {
|
|
5113
|
+
store.setContext(null);
|
|
5114
|
+
setHasDispatchedContext(false);
|
|
5115
|
+
return;
|
|
5116
|
+
}
|
|
4868
5117
|
if (!copilotkit.runtimeUrl) {
|
|
4869
5118
|
store.setContext(null);
|
|
4870
5119
|
setHasDispatchedContext(false);
|
|
@@ -4888,6 +5137,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4888
5137
|
setHasDispatchedContext(true);
|
|
4889
5138
|
}, [
|
|
4890
5139
|
store,
|
|
5140
|
+
enabled,
|
|
4891
5141
|
copilotkit.runtimeUrl,
|
|
4892
5142
|
runtimeStatus,
|
|
4893
5143
|
headersKey,
|
|
@@ -4905,16 +5155,25 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4905
5155
|
}, [threadMutationsError]);
|
|
4906
5156
|
const renameThread = (0, react.useMemo)(() => guardMutation((threadId, name) => store.renameThread(threadId, name)), [store, guardMutation]);
|
|
4907
5157
|
const archiveThread = (0, react.useMemo)(() => guardMutation((threadId) => store.archiveThread(threadId)), [store, guardMutation]);
|
|
5158
|
+
const unarchiveThread = (0, react.useMemo)(() => guardMutation((threadId) => store.unarchiveThread(threadId)), [store, guardMutation]);
|
|
4908
5159
|
const deleteThread = (0, react.useMemo)(() => guardMutation((threadId) => store.deleteThread(threadId)), [store, guardMutation]);
|
|
4909
5160
|
return {
|
|
4910
5161
|
threads,
|
|
4911
5162
|
isLoading,
|
|
4912
5163
|
error,
|
|
5164
|
+
listError,
|
|
4913
5165
|
hasMoreThreads,
|
|
4914
5166
|
isFetchingMoreThreads,
|
|
5167
|
+
isMutating,
|
|
4915
5168
|
fetchMoreThreads: (0, react.useCallback)(() => store.fetchNextPage(), [store]),
|
|
5169
|
+
refetchThreads: (0, react.useCallback)(() => store.refetchThreads(), [store]),
|
|
5170
|
+
startNewThread: (0, react.useCallback)(() => {
|
|
5171
|
+
setConfigErrorDismissed(true);
|
|
5172
|
+
store.startNewThread();
|
|
5173
|
+
}, [store]),
|
|
4916
5174
|
renameThread,
|
|
4917
5175
|
archiveThread,
|
|
5176
|
+
unarchiveThread,
|
|
4918
5177
|
deleteThread
|
|
4919
5178
|
};
|
|
4920
5179
|
}
|
|
@@ -6098,7 +6357,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6098
6357
|
ref,
|
|
6099
6358
|
"data-copilotkit": true,
|
|
6100
6359
|
"data-testid": "copilot-suggestions",
|
|
6101
|
-
className: cn("cpk:flex cpk:flex-wrap cpk:items-center cpk:gap-1.5 cpk:sm:gap-2 cpk:pl-0 cpk:pr-4 cpk:
|
|
6360
|
+
className: cn("cpk:flex cpk:flex-wrap cpk:items-center cpk:gap-1.5 cpk:sm:gap-2 cpk:pl-0 cpk:pr-4 cpk:@3xl:px-0 cpk:pointer-events-none", className),
|
|
6102
6361
|
...props
|
|
6103
6362
|
});
|
|
6104
6363
|
});
|
|
@@ -7203,7 +7462,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7203
7462
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
7204
7463
|
className: "cpk:max-w-3xl cpk:mx-auto",
|
|
7205
7464
|
children: [BoundMessageView, hasSuggestions ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7206
|
-
className: "cpk:pl-0 cpk:pr-4 cpk:
|
|
7465
|
+
className: "cpk:pl-0 cpk:pr-4 cpk:@3xl:px-0 cpk:mt-4",
|
|
7207
7466
|
children: BoundSuggestionView
|
|
7208
7467
|
}) : null]
|
|
7209
7468
|
})
|
|
@@ -7246,7 +7505,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7246
7505
|
onDragOver,
|
|
7247
7506
|
onDragLeave,
|
|
7248
7507
|
onDrop,
|
|
7249
|
-
className: cn("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
7508
|
+
className: cn("copilotKitChat cpk:@container cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
7250
7509
|
...props,
|
|
7251
7510
|
children: [dragOver && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropOverlay, {}), BoundWelcomeScreen]
|
|
7252
7511
|
});
|
|
@@ -7268,7 +7527,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7268
7527
|
onDragOver,
|
|
7269
7528
|
onDragLeave,
|
|
7270
7529
|
onDrop,
|
|
7271
|
-
className: cn("copilotKitChat cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
7530
|
+
className: cn("copilotKitChat cpk:@container cpk:relative cpk:h-full cpk:flex cpk:flex-col", className),
|
|
7272
7531
|
...props,
|
|
7273
7532
|
children: [
|
|
7274
7533
|
dragOver && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(DropOverlay, {}),
|
|
@@ -7307,7 +7566,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7307
7566
|
minHeight: 0
|
|
7308
7567
|
},
|
|
7309
7568
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7310
|
-
className: "cpk:px-4 cpk:
|
|
7569
|
+
className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
7311
7570
|
children
|
|
7312
7571
|
})
|
|
7313
7572
|
}),
|
|
@@ -7340,7 +7599,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7340
7599
|
...props,
|
|
7341
7600
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7342
7601
|
ref: contentRef,
|
|
7343
|
-
className: "cpk:px-4 cpk:
|
|
7602
|
+
className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
7344
7603
|
children
|
|
7345
7604
|
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7346
7605
|
ref: spacerRef,
|
|
@@ -7402,7 +7661,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7402
7661
|
if (!hasMounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7403
7662
|
className: "cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:overflow-y-auto cpk:overflow-x-hidden",
|
|
7404
7663
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7405
|
-
className: "cpk:px-4 cpk:
|
|
7664
|
+
className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
7406
7665
|
children
|
|
7407
7666
|
})
|
|
7408
7667
|
});
|
|
@@ -7417,7 +7676,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7417
7676
|
children: [
|
|
7418
7677
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
7419
7678
|
ref: contentRef,
|
|
7420
|
-
className: "cpk:px-4 cpk:
|
|
7679
|
+
className: "cpk:px-4 cpk:@3xl:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
7421
7680
|
children
|
|
7422
7681
|
}),
|
|
7423
7682
|
BoundFeather,
|
|
@@ -7681,9 +7940,17 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7681
7940
|
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
|
|
7682
7941
|
const [lastConnectedThreadId, setLastConnectedThreadId] = (0, react.useState)(null);
|
|
7683
7942
|
const isConnecting = hasExplicitThreadId && lastConnectedThreadId !== resolvedThreadId;
|
|
7943
|
+
const previousThreadIdRef = (0, react.useRef)(null);
|
|
7944
|
+
const hasExplicitThreadIdRef = (0, react.useRef)(hasExplicitThreadId);
|
|
7945
|
+
hasExplicitThreadIdRef.current = hasExplicitThreadId;
|
|
7684
7946
|
(0, react.useEffect)(() => {
|
|
7947
|
+
const threadChanged = previousThreadIdRef.current !== resolvedThreadId;
|
|
7948
|
+
previousThreadIdRef.current = resolvedThreadId;
|
|
7685
7949
|
agent.threadId = resolvedThreadId;
|
|
7686
|
-
if (!hasExplicitThreadId)
|
|
7950
|
+
if (!hasExplicitThreadId) {
|
|
7951
|
+
if (threadChanged && agent.messages.length > 0) agent.setMessages([]);
|
|
7952
|
+
return;
|
|
7953
|
+
}
|
|
7687
7954
|
let detached = false;
|
|
7688
7955
|
const connectAbortController = new AbortController();
|
|
7689
7956
|
if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
|
|
@@ -7697,6 +7964,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7697
7964
|
if (!detached) (typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 16))(() => {
|
|
7698
7965
|
if (!detached) setLastConnectedThreadId(resolvedThreadId);
|
|
7699
7966
|
});
|
|
7967
|
+
else if (!hasExplicitThreadIdRef.current) agentToConnect.setMessages([]);
|
|
7700
7968
|
}
|
|
7701
7969
|
};
|
|
7702
7970
|
connect(agent);
|
|
@@ -7712,8 +7980,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7712
7980
|
hasExplicitThreadId
|
|
7713
7981
|
]);
|
|
7714
7982
|
const waitForActiveRunToSettle = (0, react.useCallback)(async () => {
|
|
7715
|
-
|
|
7716
|
-
|
|
7983
|
+
const maybeAware = agent;
|
|
7984
|
+
const activeRunCompletionPromise = (0, _copilotkit_core.isRunCompletionAware)(maybeAware) ? maybeAware.activeRunCompletionPromise : void 0;
|
|
7985
|
+
if (agent.isRunning && activeRunCompletionPromise) try {
|
|
7986
|
+
await activeRunCompletionPromise;
|
|
7717
7987
|
} catch (error) {
|
|
7718
7988
|
console.error("CopilotChat: in-flight run rejected while queuing send", error);
|
|
7719
7989
|
}
|
|
@@ -8045,18 +8315,46 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
8045
8315
|
|
|
8046
8316
|
//#endregion
|
|
8047
8317
|
//#region src/v2/components/chat/CopilotModalHeader.tsx
|
|
8048
|
-
|
|
8318
|
+
/**
|
|
8319
|
+
* Reactively tracks whether the viewport is in the mobile range (≤767px) — the
|
|
8320
|
+
* same breakpoint the drawer + chat coordination use. SSR-safe: starts `false`
|
|
8321
|
+
* (desktop) so the server render and first client render agree, then syncs on
|
|
8322
|
+
* mount and on resize.
|
|
8323
|
+
*/
|
|
8324
|
+
function useIsMobileViewport() {
|
|
8325
|
+
const [isMobile, setIsMobile] = (0, react.useState)(false);
|
|
8326
|
+
(0, react.useEffect)(() => {
|
|
8327
|
+
if (typeof window === "undefined" || typeof window.matchMedia !== "function") return;
|
|
8328
|
+
const mql = window.matchMedia("(max-width: 767px)");
|
|
8329
|
+
const update = () => setIsMobile(mql.matches);
|
|
8330
|
+
update();
|
|
8331
|
+
mql.addEventListener("change", update);
|
|
8332
|
+
return () => mql.removeEventListener("change", update);
|
|
8333
|
+
}, []);
|
|
8334
|
+
return isMobile;
|
|
8335
|
+
}
|
|
8336
|
+
function CopilotModalHeader({ title, titleContent, closeButton, drawerLauncher, children, className, ...rest }) {
|
|
8049
8337
|
const configuration = useCopilotChatConfiguration();
|
|
8050
8338
|
const fallbackTitle = configuration?.labels.modalHeaderTitle ?? CopilotChatDefaultLabels.modalHeaderTitle;
|
|
8051
8339
|
const resolvedTitle = title ?? fallbackTitle;
|
|
8340
|
+
const isMobile = useIsMobileViewport();
|
|
8341
|
+
const drawerRegistered = (configuration?.drawerRegistered ?? false) && isMobile;
|
|
8052
8342
|
const handleClose = (0, react.useCallback)(() => {
|
|
8053
8343
|
configuration?.setModalOpen?.(false);
|
|
8054
8344
|
}, [configuration]);
|
|
8345
|
+
const handleToggleDrawer = (0, react.useCallback)(() => {
|
|
8346
|
+
configuration?.setDrawerOpen?.(!configuration.drawerOpen);
|
|
8347
|
+
}, [configuration]);
|
|
8055
8348
|
const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, { children: resolvedTitle });
|
|
8056
8349
|
const BoundCloseButton = renderSlot(closeButton, CopilotModalHeader.CloseButton, { onClick: handleClose });
|
|
8350
|
+
const BoundDrawerLauncher = drawerRegistered ? renderSlot(drawerLauncher, CopilotModalHeader.DrawerLauncher, {
|
|
8351
|
+
onClick: handleToggleDrawer,
|
|
8352
|
+
"aria-expanded": configuration?.drawerOpen ?? false
|
|
8353
|
+
}) : null;
|
|
8057
8354
|
if (children) return children({
|
|
8058
8355
|
titleContent: BoundTitle,
|
|
8059
8356
|
closeButton: BoundCloseButton,
|
|
8357
|
+
drawerLauncher: BoundDrawerLauncher,
|
|
8060
8358
|
title: resolvedTitle,
|
|
8061
8359
|
...rest
|
|
8062
8360
|
});
|
|
@@ -8069,8 +8367,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
8069
8367
|
className: "cpk:flex cpk:w-full cpk:items-center cpk:gap-2",
|
|
8070
8368
|
children: [
|
|
8071
8369
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8072
|
-
className: "cpk:flex-1",
|
|
8073
|
-
"aria-hidden": "true"
|
|
8370
|
+
className: "cpk:flex cpk:flex-1 cpk:justify-start",
|
|
8371
|
+
children: BoundDrawerLauncher ?? /* @__PURE__ */ (0, react_jsx_runtime.jsx)("span", { "aria-hidden": "true" })
|
|
8074
8372
|
}),
|
|
8075
8373
|
/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
8076
8374
|
className: "cpk:flex cpk:flex-1 cpk:justify-center cpk:text-center",
|
|
@@ -8103,9 +8401,21 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
8103
8401
|
"aria-hidden": "true"
|
|
8104
8402
|
})
|
|
8105
8403
|
});
|
|
8404
|
+
_CopilotModalHeader.DrawerLauncher = ({ className, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("button", {
|
|
8405
|
+
type: "button",
|
|
8406
|
+
"data-testid": "copilot-threads-drawer-launcher",
|
|
8407
|
+
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),
|
|
8408
|
+
"aria-label": "Open threads",
|
|
8409
|
+
...props,
|
|
8410
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(lucide_react.PanelLeftOpen, {
|
|
8411
|
+
className: "cpk:h-4 cpk:w-4",
|
|
8412
|
+
"aria-hidden": "true"
|
|
8413
|
+
})
|
|
8414
|
+
});
|
|
8106
8415
|
})(CopilotModalHeader || (CopilotModalHeader = {}));
|
|
8107
8416
|
CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
|
|
8108
8417
|
CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
|
|
8418
|
+
CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLauncher";
|
|
8109
8419
|
|
|
8110
8420
|
//#endregion
|
|
8111
8421
|
//#region src/v2/components/chat/CopilotSidebarView.tsx
|
|
@@ -8463,6 +8773,322 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
8463
8773
|
}
|
|
8464
8774
|
CopilotPopup.displayName = "CopilotPopup";
|
|
8465
8775
|
|
|
8776
|
+
//#endregion
|
|
8777
|
+
//#region src/v2/components/chat/CopilotThreadsDrawer.tsx
|
|
8778
|
+
/**
|
|
8779
|
+
* Maps a {@link Thread} from {@link useThreads} to the element's
|
|
8780
|
+
* {@link DrawerThread} view shape. The shapes are structurally compatible; this
|
|
8781
|
+
* narrows to exactly the fields the element renders so the element never sees
|
|
8782
|
+
* platform-internal fields.
|
|
8783
|
+
*/
|
|
8784
|
+
function toDrawerThread(thread) {
|
|
8785
|
+
return {
|
|
8786
|
+
id: thread.id,
|
|
8787
|
+
name: thread.name,
|
|
8788
|
+
archived: thread.archived,
|
|
8789
|
+
createdAt: thread.createdAt,
|
|
8790
|
+
updatedAt: thread.updatedAt,
|
|
8791
|
+
...thread.lastRunAt !== void 0 ? { lastRunAt: thread.lastRunAt } : {}
|
|
8792
|
+
};
|
|
8793
|
+
}
|
|
8794
|
+
/** The chat input textarea's documented `data-testid`. */
|
|
8795
|
+
const CHAT_INPUT_TESTID = "copilot-chat-textarea";
|
|
8796
|
+
/** The chat view container's documented `data-testid`. */
|
|
8797
|
+
const CHAT_CONTAINER_TESTID = "copilot-chat";
|
|
8798
|
+
/**
|
|
8799
|
+
* Returns the chat input element for focus-return after a thread is selected.
|
|
8800
|
+
*
|
|
8801
|
+
* Best-effort and SCOPED: walks up from the drawer element looking for an
|
|
8802
|
+
* ancestor that contains a chat-view container (`data-testid="copilot-chat"`),
|
|
8803
|
+
* then returns the chat input within that subtree. This avoids focusing the
|
|
8804
|
+
* wrong composer on a page hosting more than one chat (multi-chat dashboards),
|
|
8805
|
+
* where a document-global lookup would grab whichever input appears first in
|
|
8806
|
+
* DOM order rather than the one this drawer drives.
|
|
8807
|
+
*
|
|
8808
|
+
* Falls back to a document-global lookup when no scoping ancestor is found
|
|
8809
|
+
* (e.g. the drawer and chat share no common container, or headless usage),
|
|
8810
|
+
* and returns `null` when there is no chat input at all.
|
|
8811
|
+
*
|
|
8812
|
+
* @param origin - The drawer element to scope the search from.
|
|
8813
|
+
*/
|
|
8814
|
+
function findChatInput(origin) {
|
|
8815
|
+
if (typeof document === "undefined") return null;
|
|
8816
|
+
const container = origin?.closest?.(`[data-testid="${CHAT_CONTAINER_TESTID}"]`);
|
|
8817
|
+
if (container) {
|
|
8818
|
+
const scoped = container.querySelector(`[data-testid="${CHAT_INPUT_TESTID}"]`);
|
|
8819
|
+
if (scoped) return scoped;
|
|
8820
|
+
}
|
|
8821
|
+
return document.querySelector(`[data-testid="${CHAT_INPUT_TESTID}"]`);
|
|
8822
|
+
}
|
|
8823
|
+
/**
|
|
8824
|
+
* React wrapper for the shadow-DOM `<copilotkit-threads-drawer>` threads drawer.
|
|
8825
|
+
*
|
|
8826
|
+
* Responsibilities:
|
|
8827
|
+
* - Registers the custom element on the client (SSR-safe; nothing renders
|
|
8828
|
+
* during prerender to avoid hydration mismatch).
|
|
8829
|
+
* - Feeds the element domain data: `threads`, `loading`, `error`,
|
|
8830
|
+
* `activeThreadId`, `licensed`, fetch-more state.
|
|
8831
|
+
* - Routes the element's nine outbound events to core thread operations
|
|
8832
|
+
* ({@link useThreads}) and chat-configuration changes.
|
|
8833
|
+
* - Registers with the surrounding chat configuration so the header
|
|
8834
|
+
* thread-list launcher appears, and binds the element `open` state to the
|
|
8835
|
+
* configuration's `drawerOpen`.
|
|
8836
|
+
*
|
|
8837
|
+
* License gating is two-pronged: the locked view shows when no license is configured
|
|
8838
|
+
* (the runtime reported no license status) OR the `threads` feature is
|
|
8839
|
+
* explicitly unlicensed. While unlicensed, the thread fetch is skipped entirely
|
|
8840
|
+
* so an unlicensed drawer issues no network requests.
|
|
8841
|
+
*
|
|
8842
|
+
* Thread switching needs no host wiring: when `onThreadSelect`/`onNewThread`
|
|
8843
|
+
* are omitted, the wrapper drives the surrounding chat configuration directly
|
|
8844
|
+
* ({@link CopilotChatConfigurationValue.setActiveThreadId} /
|
|
8845
|
+
* {@link CopilotChatConfigurationValue.startNewThread}), so a bare drawer
|
|
8846
|
+
* connects to the picked thread and shows the welcome screen on "+ New". Pass
|
|
8847
|
+
* the callbacks only to take control yourself.
|
|
8848
|
+
*
|
|
8849
|
+
* @example
|
|
8850
|
+
* ```tsx
|
|
8851
|
+
* // Callback-free: the drawer drives the chat configuration itself.
|
|
8852
|
+
* <CopilotKitProvider runtimeUrl="/api/copilotkit" publicLicenseKey="ck_pub_...">
|
|
8853
|
+
* <CopilotChat />
|
|
8854
|
+
* <CopilotThreadsDrawer />
|
|
8855
|
+
* </CopilotKitProvider>
|
|
8856
|
+
* ```
|
|
8857
|
+
*/
|
|
8858
|
+
function CopilotThreadsDrawer({ agentId, onThreadSelect, onNewThread, onLicensed, licenseUrl, renderRow, label, limit, "data-testid": dataTestId = "copilot-threads-drawer" }) {
|
|
8859
|
+
const configuration = useCopilotChatConfiguration();
|
|
8860
|
+
const { status, checkFeature } = useLicenseContext();
|
|
8861
|
+
const licensePresent = status === "valid" || status === "expiring";
|
|
8862
|
+
const featureLicensed = checkFeature("threads");
|
|
8863
|
+
const licensed = licensePresent && featureLicensed;
|
|
8864
|
+
const licensePending = status === null;
|
|
8865
|
+
const resolvedAgentId = agentId ?? configuration?.agentId ?? "default";
|
|
8866
|
+
const activeThreadId = configuration?.threadId ?? null;
|
|
8867
|
+
const { threads, isLoading, listError, hasMoreThreads, isFetchingMoreThreads, archiveThread, unarchiveThread, deleteThread, fetchMoreThreads, refetchThreads, startNewThread } = useThreads({
|
|
8868
|
+
agentId: resolvedAgentId,
|
|
8869
|
+
includeArchived: true,
|
|
8870
|
+
enabled: licensed,
|
|
8871
|
+
...limit !== void 0 ? { limit } : {}
|
|
8872
|
+
});
|
|
8873
|
+
const drawerThreads = (0, react.useMemo)(() => threads.map(toDrawerThread), [threads]);
|
|
8874
|
+
const elementRef = (0, react.useRef)(null);
|
|
8875
|
+
const [mounted, setMounted] = (0, react.useState)(false);
|
|
8876
|
+
(0, react.useEffect)(() => {
|
|
8877
|
+
(0, _copilotkit_web_components_threads_drawer.defineCopilotKitThreadsDrawer)();
|
|
8878
|
+
setMounted(true);
|
|
8879
|
+
}, []);
|
|
8880
|
+
const registerDrawer = configuration?.registerDrawer;
|
|
8881
|
+
(0, react.useEffect)(() => {
|
|
8882
|
+
if (!registerDrawer) return;
|
|
8883
|
+
return registerDrawer();
|
|
8884
|
+
}, [registerDrawer]);
|
|
8885
|
+
const [localDrawerOpen, setLocalDrawerOpen] = (0, react.useState)(false);
|
|
8886
|
+
const drawerOpen = configuration ? configuration.drawerOpen : localDrawerOpen;
|
|
8887
|
+
const setDrawerOpen = configuration ? configuration.setDrawerOpen : setLocalDrawerOpen;
|
|
8888
|
+
const setActiveThreadId = configuration?.setActiveThreadId;
|
|
8889
|
+
const startNewThreadConfig = configuration?.startNewThread;
|
|
8890
|
+
const handleThreadSelected = (0, react.useCallback)((threadId) => {
|
|
8891
|
+
if (onThreadSelect) onThreadSelect(threadId);
|
|
8892
|
+
else setActiveThreadId?.(threadId, { explicit: true });
|
|
8893
|
+
findChatInput(elementRef.current)?.focus();
|
|
8894
|
+
}, [onThreadSelect, setActiveThreadId]);
|
|
8895
|
+
const handleNewThread = (0, react.useCallback)(() => {
|
|
8896
|
+
startNewThread();
|
|
8897
|
+
if (onNewThread) onNewThread();
|
|
8898
|
+
else startNewThreadConfig?.();
|
|
8899
|
+
}, [
|
|
8900
|
+
startNewThread,
|
|
8901
|
+
onNewThread,
|
|
8902
|
+
startNewThreadConfig
|
|
8903
|
+
]);
|
|
8904
|
+
const handleArchive = (0, react.useCallback)((threadId) => {
|
|
8905
|
+
archiveThread(threadId).catch((err) => {
|
|
8906
|
+
console.error("CopilotThreadsDrawer: archiveThread failed", err);
|
|
8907
|
+
});
|
|
8908
|
+
}, [archiveThread]);
|
|
8909
|
+
const handleUnarchive = (0, react.useCallback)((threadId) => {
|
|
8910
|
+
unarchiveThread(threadId).catch((err) => {
|
|
8911
|
+
console.error("CopilotThreadsDrawer: unarchiveThread failed", err);
|
|
8912
|
+
});
|
|
8913
|
+
}, [unarchiveThread]);
|
|
8914
|
+
const handleDelete = (0, react.useCallback)((threadId) => {
|
|
8915
|
+
const isActive = threadId === activeThreadId;
|
|
8916
|
+
deleteThread(threadId).then(() => {
|
|
8917
|
+
if (isActive) {
|
|
8918
|
+
startNewThread();
|
|
8919
|
+
if (onNewThread) onNewThread();
|
|
8920
|
+
else startNewThreadConfig?.();
|
|
8921
|
+
}
|
|
8922
|
+
}).catch((err) => {
|
|
8923
|
+
console.error("CopilotThreadsDrawer: deleteThread failed", err);
|
|
8924
|
+
});
|
|
8925
|
+
}, [
|
|
8926
|
+
deleteThread,
|
|
8927
|
+
activeThreadId,
|
|
8928
|
+
startNewThread,
|
|
8929
|
+
onNewThread,
|
|
8930
|
+
startNewThreadConfig
|
|
8931
|
+
]);
|
|
8932
|
+
const handleFilterChange = (0, react.useCallback)(() => {
|
|
8933
|
+
refetchThreads();
|
|
8934
|
+
}, [refetchThreads]);
|
|
8935
|
+
const handleRetry = (0, react.useCallback)((scope) => {
|
|
8936
|
+
if (scope === "fetch-more") fetchMoreThreads();
|
|
8937
|
+
else refetchThreads();
|
|
8938
|
+
}, [fetchMoreThreads, refetchThreads]);
|
|
8939
|
+
const handleOpenChange = (0, react.useCallback)((open) => {
|
|
8940
|
+
setDrawerOpen(open);
|
|
8941
|
+
}, [setDrawerOpen]);
|
|
8942
|
+
const handleLicensed = (0, react.useCallback)(() => {
|
|
8943
|
+
onLicensed?.();
|
|
8944
|
+
}, [onLicensed]);
|
|
8945
|
+
const handleLoadMore = (0, react.useCallback)(() => {
|
|
8946
|
+
fetchMoreThreads();
|
|
8947
|
+
}, [fetchMoreThreads]);
|
|
8948
|
+
const handlersRef = (0, react.useRef)({
|
|
8949
|
+
handleThreadSelected,
|
|
8950
|
+
handleNewThread,
|
|
8951
|
+
handleArchive,
|
|
8952
|
+
handleUnarchive,
|
|
8953
|
+
handleDelete,
|
|
8954
|
+
handleFilterChange,
|
|
8955
|
+
handleRetry,
|
|
8956
|
+
handleOpenChange,
|
|
8957
|
+
handleLicensed,
|
|
8958
|
+
handleLoadMore
|
|
8959
|
+
});
|
|
8960
|
+
handlersRef.current = {
|
|
8961
|
+
handleThreadSelected,
|
|
8962
|
+
handleNewThread,
|
|
8963
|
+
handleArchive,
|
|
8964
|
+
handleUnarchive,
|
|
8965
|
+
handleDelete,
|
|
8966
|
+
handleFilterChange,
|
|
8967
|
+
handleRetry,
|
|
8968
|
+
handleOpenChange,
|
|
8969
|
+
handleLicensed,
|
|
8970
|
+
handleLoadMore
|
|
8971
|
+
};
|
|
8972
|
+
(0, react.useEffect)(() => {
|
|
8973
|
+
const el = elementRef.current;
|
|
8974
|
+
if (!el) return;
|
|
8975
|
+
const onThreadSelected = (event) => {
|
|
8976
|
+
const detail = event.detail;
|
|
8977
|
+
handlersRef.current.handleThreadSelected(detail.threadId);
|
|
8978
|
+
};
|
|
8979
|
+
const onNewThreadEvent = () => handlersRef.current.handleNewThread();
|
|
8980
|
+
const onArchive = (event) => {
|
|
8981
|
+
const detail = event.detail;
|
|
8982
|
+
handlersRef.current.handleArchive(detail.threadId);
|
|
8983
|
+
};
|
|
8984
|
+
const onUnarchive = (event) => {
|
|
8985
|
+
const detail = event.detail;
|
|
8986
|
+
handlersRef.current.handleUnarchive(detail.threadId);
|
|
8987
|
+
};
|
|
8988
|
+
const onDelete = (event) => {
|
|
8989
|
+
const detail = event.detail;
|
|
8990
|
+
handlersRef.current.handleDelete(detail.threadId);
|
|
8991
|
+
};
|
|
8992
|
+
const onFilterChange = (_event) => {
|
|
8993
|
+
handlersRef.current.handleFilterChange();
|
|
8994
|
+
};
|
|
8995
|
+
const onOpenChangeEvent = (event) => {
|
|
8996
|
+
const detail = event.detail;
|
|
8997
|
+
handlersRef.current.handleOpenChange(detail.open);
|
|
8998
|
+
};
|
|
8999
|
+
const onRetry = (event) => {
|
|
9000
|
+
const detail = event.detail;
|
|
9001
|
+
handlersRef.current.handleRetry(detail.scope);
|
|
9002
|
+
};
|
|
9003
|
+
const onLicensedEvent = () => handlersRef.current.handleLicensed();
|
|
9004
|
+
const onLoadMore = () => handlersRef.current.handleLoadMore();
|
|
9005
|
+
el.addEventListener("thread-selected", onThreadSelected);
|
|
9006
|
+
el.addEventListener("new-thread", onNewThreadEvent);
|
|
9007
|
+
el.addEventListener("archive", onArchive);
|
|
9008
|
+
el.addEventListener("unarchive", onUnarchive);
|
|
9009
|
+
el.addEventListener("delete", onDelete);
|
|
9010
|
+
el.addEventListener("filter-change", onFilterChange);
|
|
9011
|
+
el.addEventListener("open-change", onOpenChangeEvent);
|
|
9012
|
+
el.addEventListener("retry", onRetry);
|
|
9013
|
+
el.addEventListener("licensed", onLicensedEvent);
|
|
9014
|
+
el.addEventListener("load-more", onLoadMore);
|
|
9015
|
+
return () => {
|
|
9016
|
+
el.removeEventListener("thread-selected", onThreadSelected);
|
|
9017
|
+
el.removeEventListener("new-thread", onNewThreadEvent);
|
|
9018
|
+
el.removeEventListener("archive", onArchive);
|
|
9019
|
+
el.removeEventListener("unarchive", onUnarchive);
|
|
9020
|
+
el.removeEventListener("delete", onDelete);
|
|
9021
|
+
el.removeEventListener("filter-change", onFilterChange);
|
|
9022
|
+
el.removeEventListener("open-change", onOpenChangeEvent);
|
|
9023
|
+
el.removeEventListener("retry", onRetry);
|
|
9024
|
+
el.removeEventListener("licensed", onLicensedEvent);
|
|
9025
|
+
el.removeEventListener("load-more", onLoadMore);
|
|
9026
|
+
};
|
|
9027
|
+
}, [mounted]);
|
|
9028
|
+
(0, react.useEffect)(() => {
|
|
9029
|
+
const el = elementRef.current;
|
|
9030
|
+
if (!el) return;
|
|
9031
|
+
el.threads = drawerThreads;
|
|
9032
|
+
}, [drawerThreads, mounted]);
|
|
9033
|
+
(0, react.useEffect)(() => {
|
|
9034
|
+
const el = elementRef.current;
|
|
9035
|
+
if (!el) return;
|
|
9036
|
+
el.loading = isLoading || licensePending;
|
|
9037
|
+
el.error = listError ? listError.message : null;
|
|
9038
|
+
el.activeThreadId = activeThreadId;
|
|
9039
|
+
el.licensed = licensed || licensePending;
|
|
9040
|
+
el.hasMore = hasMoreThreads;
|
|
9041
|
+
el.fetchingMore = isFetchingMoreThreads;
|
|
9042
|
+
}, [
|
|
9043
|
+
isLoading,
|
|
9044
|
+
listError,
|
|
9045
|
+
activeThreadId,
|
|
9046
|
+
licensed,
|
|
9047
|
+
licensePending,
|
|
9048
|
+
hasMoreThreads,
|
|
9049
|
+
isFetchingMoreThreads,
|
|
9050
|
+
mounted
|
|
9051
|
+
]);
|
|
9052
|
+
(0, react.useEffect)(() => {
|
|
9053
|
+
const el = elementRef.current;
|
|
9054
|
+
if (!el) return;
|
|
9055
|
+
el.open = drawerOpen;
|
|
9056
|
+
}, [drawerOpen, mounted]);
|
|
9057
|
+
(0, react.useEffect)(() => {
|
|
9058
|
+
const el = elementRef.current;
|
|
9059
|
+
if (!el) return;
|
|
9060
|
+
if (label !== void 0) el.label = label;
|
|
9061
|
+
}, [label, mounted]);
|
|
9062
|
+
(0, react.useEffect)(() => {
|
|
9063
|
+
const el = elementRef.current;
|
|
9064
|
+
if (!el) return;
|
|
9065
|
+
if (licenseUrl !== void 0) el.licenseUrl = licenseUrl;
|
|
9066
|
+
}, [licenseUrl, mounted]);
|
|
9067
|
+
const rowChildren = (0, react.useMemo)(() => {
|
|
9068
|
+
if (!renderRow) return null;
|
|
9069
|
+
return drawerThreads.map((drawerThread) => {
|
|
9070
|
+
const fullThread = threads.find((t) => t.id === drawerThread.id);
|
|
9071
|
+
if (!fullThread) return null;
|
|
9072
|
+
const content = renderRow(fullThread);
|
|
9073
|
+
if (content === null || content === void 0) return null;
|
|
9074
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
9075
|
+
slot: `row:${drawerThread.id}`,
|
|
9076
|
+
children: content
|
|
9077
|
+
}, drawerThread.id);
|
|
9078
|
+
});
|
|
9079
|
+
}, [
|
|
9080
|
+
renderRow,
|
|
9081
|
+
drawerThreads,
|
|
9082
|
+
threads
|
|
9083
|
+
]);
|
|
9084
|
+
if (!mounted) return null;
|
|
9085
|
+
return react.default.createElement(_copilotkit_web_components_threads_drawer.COPILOTKIT_THREADS_DRAWER_TAG, {
|
|
9086
|
+
ref: elementRef,
|
|
9087
|
+
"data-testid": dataTestId
|
|
9088
|
+
}, rowChildren);
|
|
9089
|
+
}
|
|
9090
|
+
CopilotThreadsDrawer.displayName = "CopilotThreadsDrawer";
|
|
9091
|
+
|
|
8466
9092
|
//#endregion
|
|
8467
9093
|
//#region src/v2/components/WildcardToolCallRender.tsx
|
|
8468
9094
|
const WildcardToolCallRender = defineToolCallRenderer({
|
|
@@ -10038,6 +10664,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
10038
10664
|
const showInspector = shouldShowDevConsole(props.enableInspector);
|
|
10039
10665
|
const publicApiKey = props.publicApiKey || props.publicLicenseKey;
|
|
10040
10666
|
const renderArr = (0, react.useMemo)(() => [{ render: CoAgentStateRenderBridge }], []);
|
|
10667
|
+
const { onError: _onError, ...v2Props } = props;
|
|
10041
10668
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToastProvider, {
|
|
10042
10669
|
enabled,
|
|
10043
10670
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotErrorBoundary, {
|
|
@@ -10046,7 +10673,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
10046
10673
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ThreadsProvider, {
|
|
10047
10674
|
threadId: props.threadId,
|
|
10048
10675
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotKitProvider, {
|
|
10049
|
-
...
|
|
10676
|
+
...v2Props,
|
|
10050
10677
|
showDevConsole: showInspector,
|
|
10051
10678
|
renderCustomMessages: renderArr,
|
|
10052
10679
|
useSingleEndpoint: props.useSingleEndpoint ?? true,
|
|
@@ -10577,6 +11204,7 @@ Object.defineProperty(exports, 'CopilotSidebarView', {
|
|
|
10577
11204
|
return CopilotSidebarView;
|
|
10578
11205
|
}
|
|
10579
11206
|
});
|
|
11207
|
+
exports.CopilotThreadsDrawer = CopilotThreadsDrawer;
|
|
10580
11208
|
exports.INTELLIGENCE_TURN_HEAD = INTELLIGENCE_TURN_HEAD;
|
|
10581
11209
|
exports.IntelligenceIndicator = IntelligenceIndicator;
|
|
10582
11210
|
exports.IntelligenceIndicatorView = IntelligenceIndicatorView;
|