@copilotkit/react-core 1.70.1 → 1.70.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{copilotkit-DiUK2Bhq.mjs → copilotkit-Ap_yisA5.mjs} +470 -98
- package/dist/copilotkit-Ap_yisA5.mjs.map +1 -0
- package/dist/{copilotkit-CxLT6zFx.cjs → copilotkit-BU3OvveB.cjs} +468 -96
- package/dist/copilotkit-BU3OvveB.cjs.map +1 -0
- package/dist/{copilotkit-DsWuxPUQ.d.mts → copilotkit-Bs98akp9.d.mts} +32 -2
- package/dist/{copilotkit-DsWuxPUQ.d.mts.map → copilotkit-Bs98akp9.d.mts.map} +1 -1
- package/dist/{copilotkit-CtF2clxZ.d.cts → copilotkit-X2eGbOwf.d.cts} +32 -2
- package/dist/{copilotkit-CtF2clxZ.d.cts.map → copilotkit-X2eGbOwf.d.cts.map} +1 -1
- 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 +273 -15
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/headless.cjs +97 -2
- package/dist/v2/headless.cjs.map +1 -1
- package/dist/v2/headless.d.cts.map +1 -1
- package/dist/v2/headless.d.mts.map +1 -1
- package/dist/v2/headless.mjs +98 -3
- package/dist/v2/headless.mjs.map +1 -1
- package/dist/v2/index.cjs +1 -1
- package/dist/v2/index.css +1 -1
- package/dist/v2/index.d.cts +1 -1
- package/dist/v2/index.d.mts +1 -1
- package/dist/v2/index.mjs +1 -1
- package/dist/v2/index.umd.js +468 -96
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +7 -7
- package/skills/react-core/SKILL.md +1 -1
- package/skills/react-core/references/attachments.md +20 -0
- package/dist/copilotkit-CxLT6zFx.cjs.map +0 -1
- package/dist/copilotkit-DiUK2Bhq.mjs.map +0 -1
|
@@ -298,6 +298,62 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
|
|
|
298
298
|
const useCopilotChatConfiguration = () => {
|
|
299
299
|
return (0, react.useContext)(CopilotChatConfiguration);
|
|
300
300
|
};
|
|
301
|
+
/**
|
|
302
|
+
* Reports modal open/close requests to the host, and — when `open` is
|
|
303
|
+
* supplied — makes the modal state of an already-established chat
|
|
304
|
+
* configuration **controlled** for the subtree it wraps.
|
|
305
|
+
*
|
|
306
|
+
* This is deliberately a scope component rather than another mode inside
|
|
307
|
+
* {@link CopilotChatConfigurationProvider}. The provider resolves modal state
|
|
308
|
+
* across a nested chain (own state, parent sync, drawer mutual-exclusion, the
|
|
309
|
+
* modal-closer registry); a controlled branch inside that resolution would add
|
|
310
|
+
* a fourth interacting mode. Overriding the context for the subtree instead
|
|
311
|
+
* leaves every one of those paths untouched:
|
|
312
|
+
*
|
|
313
|
+
* - `isModalOpen` is replaced with the host's `open`, so the rendered surface
|
|
314
|
+
* follows the prop from the very first frame (no open-then-close flash).
|
|
315
|
+
* - `setModalOpen` still calls the underlying setter, so the existing
|
|
316
|
+
* parent-sync and drawer mutual-exclusion side effects continue to run, and
|
|
317
|
+
* *then* reports the request through `onOpenChange`.
|
|
318
|
+
* - The wrapped setter is registered as the modal closer, so the drawer's
|
|
319
|
+
* mobile mutual-exclusion reaches the host instead of silently flipping
|
|
320
|
+
* state that nothing displays.
|
|
321
|
+
*
|
|
322
|
+
* A host that supplies `open` and ignores `onOpenChange` gets a modal pinned
|
|
323
|
+
* to `open`, which is the standard controlled-component contract. A host that
|
|
324
|
+
* supplies only `onOpenChange` is notified while the modal keeps managing
|
|
325
|
+
* itself.
|
|
326
|
+
*
|
|
327
|
+
* Renders `children` unchanged when no chat configuration is in scope.
|
|
328
|
+
*/
|
|
329
|
+
const ControlledModalOpenScope = ({ children, open, onOpenChange }) => {
|
|
330
|
+
const parentConfig = (0, react.useContext)(CopilotChatConfiguration);
|
|
331
|
+
const parentSetModalOpen = parentConfig?.setModalOpen;
|
|
332
|
+
const registerModalCloser = parentConfig?.ɵregisterModalCloser;
|
|
333
|
+
const setModalOpen = (0, react.useCallback)((next) => {
|
|
334
|
+
parentSetModalOpen?.(next);
|
|
335
|
+
onOpenChange?.(next);
|
|
336
|
+
}, [parentSetModalOpen, onOpenChange]);
|
|
337
|
+
(0, react.useEffect)(() => {
|
|
338
|
+
if (!registerModalCloser) return;
|
|
339
|
+
return registerModalCloser(setModalOpen);
|
|
340
|
+
}, [registerModalCloser, setModalOpen]);
|
|
341
|
+
const configurationValue = (0, react.useMemo)(() => parentConfig ? {
|
|
342
|
+
...parentConfig,
|
|
343
|
+
isModalOpen: open ?? parentConfig.isModalOpen,
|
|
344
|
+
setModalOpen
|
|
345
|
+
} : null, [
|
|
346
|
+
parentConfig,
|
|
347
|
+
open,
|
|
348
|
+
setModalOpen
|
|
349
|
+
]);
|
|
350
|
+
if (!configurationValue) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(react_jsx_runtime.Fragment, { children });
|
|
351
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfiguration.Provider, {
|
|
352
|
+
value: configurationValue,
|
|
353
|
+
children
|
|
354
|
+
});
|
|
355
|
+
};
|
|
356
|
+
ControlledModalOpenScope.displayName = "ControlledModalOpenScope";
|
|
301
357
|
|
|
302
358
|
//#endregion
|
|
303
359
|
//#region src/v2/lib/utils.ts
|
|
@@ -1493,6 +1549,29 @@ const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall
|
|
|
1493
1549
|
if (prevProps.RenderComponent !== nextProps.RenderComponent) return false;
|
|
1494
1550
|
return true;
|
|
1495
1551
|
});
|
|
1552
|
+
const IS_DEVELOPMENT$1 = process.env.NODE_ENV !== "production";
|
|
1553
|
+
/**
|
|
1554
|
+
* Reports tool calls that resolved to no renderer.
|
|
1555
|
+
*
|
|
1556
|
+
* A tool call with no renderer paints an empty message container and says
|
|
1557
|
+
* nothing else, so the only signal a developer gets today is a blank space in
|
|
1558
|
+
* the chat. This names the call and the renderers that *are* registered, which
|
|
1559
|
+
* is the whole diagnosis when the cause is a name that does not match.
|
|
1560
|
+
*
|
|
1561
|
+
* @param toolNames - The unmatched tool names collected during render.
|
|
1562
|
+
* @param registered - The registry as it stands now, re-read at report time.
|
|
1563
|
+
* @param alreadyWarned - Names already reported, mutated to keep this once per name.
|
|
1564
|
+
*/
|
|
1565
|
+
function warnAboutUnrenderedToolCalls(toolNames, registered, alreadyWarned) {
|
|
1566
|
+
const registeredNames = Array.from(new Set(registered.map((rc) => rc.name)));
|
|
1567
|
+
const hasWildcard = registeredNames.includes("*");
|
|
1568
|
+
for (const toolName of toolNames) {
|
|
1569
|
+
if (hasWildcard || registeredNames.includes(toolName)) continue;
|
|
1570
|
+
if (alreadyWarned.has(toolName)) continue;
|
|
1571
|
+
alreadyWarned.add(toolName);
|
|
1572
|
+
console.warn(`[CopilotKit] The agent called the tool "${toolName}", and no renderer is registered for it, so that message rendered nothing. ` + (registeredNames.length === 0 ? "No tool-call renderers are registered. " : `Registered renderers: ${registeredNames.map((name) => `"${name}"`).join(", ")}. `) + `Register one with useRenderTool({ name: "${toolName}", ... }), or call useDefaultRenderTool() for a built-in card that covers every tool the agent calls. This warning is development-only.`);
|
|
1573
|
+
}
|
|
1574
|
+
}
|
|
1496
1575
|
/**
|
|
1497
1576
|
* Hook that returns a function to render tool calls based on the render functions
|
|
1498
1577
|
* defined in CopilotKitProvider.
|
|
@@ -1502,13 +1581,18 @@ const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall
|
|
|
1502
1581
|
function useRenderToolCall() {
|
|
1503
1582
|
const { copilotkit, executingToolCallIds } = (0, _copilotkit_react_core_v2_context.useCopilotKit)();
|
|
1504
1583
|
const agentId = useCopilotChatConfiguration()?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
1584
|
+
const unrenderedToolNames = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
1585
|
+
const warnedToolNames = (0, react.useRef)(/* @__PURE__ */ new Set());
|
|
1505
1586
|
const renderToolCalls = (0, react.useSyncExternalStore)((callback) => {
|
|
1506
1587
|
return copilotkit.subscribe({ onRenderToolCallsChanged: callback }).unsubscribe;
|
|
1507
1588
|
}, () => copilotkit.renderToolCalls, () => copilotkit.renderToolCalls);
|
|
1508
|
-
|
|
1589
|
+
const renderToolCall = (0, react.useCallback)(({ toolCall, toolMessage }) => {
|
|
1509
1590
|
const exactMatches = renderToolCalls.filter((rc) => rc.name === toolCall.function.name);
|
|
1510
1591
|
const renderConfig = exactMatches.find((rc) => rc.agentId === agentId) || exactMatches.find((rc) => !rc.agentId) || exactMatches[0] || renderToolCalls.find((rc) => rc.name === "*");
|
|
1511
|
-
if (!renderConfig)
|
|
1592
|
+
if (!renderConfig) {
|
|
1593
|
+
if (IS_DEVELOPMENT$1) unrenderedToolNames.current.add(toolCall.function.name);
|
|
1594
|
+
return null;
|
|
1595
|
+
}
|
|
1512
1596
|
const RenderComponent = renderConfig.render;
|
|
1513
1597
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ToolCallRenderer, {
|
|
1514
1598
|
toolCall,
|
|
@@ -1521,6 +1605,17 @@ function useRenderToolCall() {
|
|
|
1521
1605
|
executingToolCallIds,
|
|
1522
1606
|
agentId
|
|
1523
1607
|
]);
|
|
1608
|
+
(0, react.useEffect)(() => {
|
|
1609
|
+
if (!IS_DEVELOPMENT$1) return;
|
|
1610
|
+
if (unrenderedToolNames.current.size === 0) return;
|
|
1611
|
+
const timer = setTimeout(() => {
|
|
1612
|
+
const pending = Array.from(unrenderedToolNames.current);
|
|
1613
|
+
unrenderedToolNames.current.clear();
|
|
1614
|
+
warnAboutUnrenderedToolCalls(pending, copilotkit.renderToolCalls, warnedToolNames.current);
|
|
1615
|
+
}, 0);
|
|
1616
|
+
return () => clearTimeout(timer);
|
|
1617
|
+
});
|
|
1618
|
+
return renderToolCall;
|
|
1524
1619
|
}
|
|
1525
1620
|
|
|
1526
1621
|
//#endregion
|
|
@@ -2999,6 +3094,95 @@ const A2UISurfaceContentSchema = zod.z.object({
|
|
|
2999
3094
|
a2ui_operations: zod.z.array(zod.z.any()).optional(),
|
|
3000
3095
|
...A2UILifecycleFields
|
|
3001
3096
|
}).passthrough();
|
|
3097
|
+
const IS_DEVELOPMENT = process.env.NODE_ENV !== "production";
|
|
3098
|
+
/**
|
|
3099
|
+
* How long to wait for a surface to report its first paint before giving up on
|
|
3100
|
+
* the loader cross-over. Reaching it also means `onReady` never fired, which is
|
|
3101
|
+
* the signal the warning below reports.
|
|
3102
|
+
*/
|
|
3103
|
+
const PAINT_FALLBACK_MS = 8e3;
|
|
3104
|
+
/**
|
|
3105
|
+
* Names the operation kinds a surface received, for a warning that has to say
|
|
3106
|
+
* what did arrive as well as what did not.
|
|
3107
|
+
*
|
|
3108
|
+
* @param operations - The operations grouped under one surface.
|
|
3109
|
+
* @returns A comma-separated list of operation keys, or "none".
|
|
3110
|
+
*/
|
|
3111
|
+
function describeOperationKinds(operations) {
|
|
3112
|
+
const kinds = /* @__PURE__ */ new Set();
|
|
3113
|
+
for (const operation of operations) {
|
|
3114
|
+
if (!operation || typeof operation !== "object") continue;
|
|
3115
|
+
for (const key of Object.keys(operation)) if (key !== "version") kinds.add(key);
|
|
3116
|
+
}
|
|
3117
|
+
return kinds.size === 0 ? "none" : Array.from(kinds).join(", ");
|
|
3118
|
+
}
|
|
3119
|
+
/**
|
|
3120
|
+
* Reports surfaces that received operations and never painted.
|
|
3121
|
+
*
|
|
3122
|
+
* Reaching {@link PAINT_FALLBACK_MS} with no `onReady` means the operations were
|
|
3123
|
+
* accepted, were not malformed enough to raise the provider's error state, and
|
|
3124
|
+
* still put nothing on screen. Left alone that is invisible: the loader drops,
|
|
3125
|
+
* the turn finishes, and the only trace is an empty placeholder above the reply.
|
|
3126
|
+
*
|
|
3127
|
+
* `surfaceHasRenderableContent` already knows which half is missing, so the
|
|
3128
|
+
* warning says which rather than making the reader re-derive it.
|
|
3129
|
+
*
|
|
3130
|
+
* @param grouped - Operations grouped by surface id.
|
|
3131
|
+
*/
|
|
3132
|
+
function warnAboutUnpaintedSurfaces(grouped) {
|
|
3133
|
+
for (const [surfaceId, operations] of grouped) {
|
|
3134
|
+
if (surfaceHasRenderableContent(operations)) continue;
|
|
3135
|
+
const cause = operations.filter((o) => o?.updateComponents).length === 0 ? "no updateComponents operation arrived, so the surface was never given anything to draw" : "its components address their values by \"path\" and no updateDataModel carried a non-empty value, so every bound component drew empty";
|
|
3136
|
+
console.warn(`[CopilotKit] A2UI surface "${surfaceId}" received operations and never painted after ${String(PAINT_FALLBACK_MS)}ms: ${cause}. Operations received: ${describeOperationKinds(operations)}. The payload was accepted, so check what the agent sent rather than the client wiring. This warning is development-only.`);
|
|
3137
|
+
}
|
|
3138
|
+
}
|
|
3139
|
+
/**
|
|
3140
|
+
* Names the component ids a surface was sent, for a warning about the one id
|
|
3141
|
+
* that is missing.
|
|
3142
|
+
*
|
|
3143
|
+
* @param operations - The operations grouped under one surface.
|
|
3144
|
+
* @returns A quoted, comma-separated list of ids, or "none".
|
|
3145
|
+
*/
|
|
3146
|
+
function describeComponentIds(operations) {
|
|
3147
|
+
const ids = [];
|
|
3148
|
+
for (const operation of operations) {
|
|
3149
|
+
const components = operation?.updateComponents?.components;
|
|
3150
|
+
if (!Array.isArray(components)) continue;
|
|
3151
|
+
for (const component of components) {
|
|
3152
|
+
const id = component?.id;
|
|
3153
|
+
if (typeof id === "string" && !ids.includes(id)) ids.push(id);
|
|
3154
|
+
}
|
|
3155
|
+
}
|
|
3156
|
+
return ids.length === 0 ? "none" : ids.map((id) => `"${id}"`).join(", ");
|
|
3157
|
+
}
|
|
3158
|
+
/**
|
|
3159
|
+
* Reports a surface that is still waiting for its {@link ROOT_COMPONENT_ID}
|
|
3160
|
+
* component once its operations have stopped arriving.
|
|
3161
|
+
*
|
|
3162
|
+
* Both renderers begin walking a surface at that one id, and treat an id they
|
|
3163
|
+
* cannot find as not arrived yet — an animated placeholder. That is right while
|
|
3164
|
+
* operations stream. Once they have stopped it is not waiting, it is stuck, and
|
|
3165
|
+
* every other check calls it healthy: the surface exists, `processMessages` did
|
|
3166
|
+
* not throw, the component types were never reached, and
|
|
3167
|
+
* `surfaceHasRenderableContent` says yes on the strength of components plus a
|
|
3168
|
+
* data model, so `onReady` fires and the never-painted report is suppressed.
|
|
3169
|
+
* A complete, accepted payload therefore animates a grey box forever in silence.
|
|
3170
|
+
*
|
|
3171
|
+
* Reads the live components model rather than scanning the operations for the
|
|
3172
|
+
* id, so it covers every way the root can fail to resolve — not only a payload
|
|
3173
|
+
* that never named one.
|
|
3174
|
+
*
|
|
3175
|
+
* @param surfaceId - The surface the operations were addressed to.
|
|
3176
|
+
* @param operations - The operations processed for that surface.
|
|
3177
|
+
* @param surface - The live surface model, already known to exist.
|
|
3178
|
+
*/
|
|
3179
|
+
function warnAboutUnresolvedRoot(surfaceId, operations, surface) {
|
|
3180
|
+
if (surface?.componentsModel?.get?.(_copilotkit_a2ui_renderer.ROOT_COMPONENT_ID)) return;
|
|
3181
|
+
const componentOps = operations.filter((o) => o?.updateComponents);
|
|
3182
|
+
if (componentOps.length === 0) return;
|
|
3183
|
+
const cause = componentOps.some((o) => o.updateComponents?.components?.some?.((c) => c?.id === _copilotkit_a2ui_renderer.ROOT_COMPONENT_ID)) ? `a component with id "${_copilotkit_a2ui_renderer.ROOT_COMPONENT_ID}" WAS sent, so the components did not reach the surface's model — check for an A2UI render error above, or a catalog that took none of them` : `the components it received are named ${describeComponentIds(operations)}, and none of them is "${_copilotkit_a2ui_renderer.ROOT_COMPONENT_ID}" — rename the entry-point component to "${_copilotkit_a2ui_renderer.ROOT_COMPONENT_ID}", and make every other component reachable from it through child/children`;
|
|
3184
|
+
console.warn(`[CopilotKit] A2UI surface "${surfaceId}" has no "${_copilotkit_a2ui_renderer.ROOT_COMPONENT_ID}" component ${String(PAINT_FALLBACK_MS)}ms after its last operations were processed, so it is showing the placeholder for a component that has not arrived yet and will keep showing it: ${cause}. Operations received: ${describeOperationKinds(operations)}. This warning is development-only.`);
|
|
3185
|
+
}
|
|
3002
3186
|
function createA2UIMessageRenderer(options) {
|
|
3003
3187
|
const { theme, catalog, loadingComponent, recovery, onAction } = options;
|
|
3004
3188
|
const showAfterMs = recovery?.showAfterMs ?? 2e3;
|
|
@@ -3032,6 +3216,8 @@ function createA2UIMessageRenderer(options) {
|
|
|
3032
3216
|
return groups;
|
|
3033
3217
|
}, [operations]);
|
|
3034
3218
|
const hasOps = groupedOperations.size > 0;
|
|
3219
|
+
const groupedOperationsRef = (0, react.useRef)(groupedOperations);
|
|
3220
|
+
groupedOperationsRef.current = groupedOperations;
|
|
3035
3221
|
const renderLifecycle = (c) => {
|
|
3036
3222
|
const status = c?.status;
|
|
3037
3223
|
const debugExposure = resolveDebugExposure(c, optionDebugExposure);
|
|
@@ -3063,7 +3249,10 @@ function createA2UIMessageRenderer(options) {
|
|
|
3063
3249
|
readyRef.current = false;
|
|
3064
3250
|
return;
|
|
3065
3251
|
}
|
|
3066
|
-
const t = setTimeout(() =>
|
|
3252
|
+
const t = setTimeout(() => {
|
|
3253
|
+
setSurfaceReady(true);
|
|
3254
|
+
if (IS_DEVELOPMENT && !readyRef.current) warnAboutUnpaintedSurfaces(groupedOperationsRef.current);
|
|
3255
|
+
}, PAINT_FALLBACK_MS);
|
|
3067
3256
|
return () => clearTimeout(t);
|
|
3068
3257
|
}, [hasOps]);
|
|
3069
3258
|
if (!hasOps) return renderLifecycle(content);
|
|
@@ -3187,8 +3376,21 @@ function SurfaceMessageProcessor({ surfaceId, operations, onReady }) {
|
|
|
3187
3376
|
const hash = JSON.stringify(operations);
|
|
3188
3377
|
if (hash === lastHashRef.current) return;
|
|
3189
3378
|
lastHashRef.current = hash;
|
|
3190
|
-
|
|
3379
|
+
const ops = getSurface(surfaceId) ? operations.filter((op) => !op?.createSurface) : operations;
|
|
3380
|
+
processMessages(ops);
|
|
3191
3381
|
if (onReady && surfaceHasRenderableContent(operations)) onReady();
|
|
3382
|
+
if (!IS_DEVELOPMENT) return;
|
|
3383
|
+
if (!getSurface(surfaceId)) {
|
|
3384
|
+
const missingSurfaceCheck = setTimeout(() => {
|
|
3385
|
+
if (getSurface(surfaceId)) return;
|
|
3386
|
+
console.warn(`[CopilotKit] A2UI processed ${String(ops.length)} operation(s) addressed to surface "${surfaceId}" and no surface by that id exists, so this card rendered nothing. Operations received: ${describeOperationKinds(ops)}. A createSurface for "${surfaceId}" has to arrive before, or with, the operations that target it. This warning is development-only.`);
|
|
3387
|
+
}, 0);
|
|
3388
|
+
return () => clearTimeout(missingSurfaceCheck);
|
|
3389
|
+
}
|
|
3390
|
+
const unresolvedRootCheck = setTimeout(() => {
|
|
3391
|
+
warnAboutUnresolvedRoot(surfaceId, operations, getSurface(surfaceId));
|
|
3392
|
+
}, PAINT_FALLBACK_MS);
|
|
3393
|
+
return () => clearTimeout(unresolvedRootCheck);
|
|
3192
3394
|
}, [
|
|
3193
3395
|
processMessages,
|
|
3194
3396
|
getSurface,
|
|
@@ -3215,10 +3417,26 @@ function surfaceHasRenderableContent(operations) {
|
|
|
3215
3417
|
return Object.values(v).some((x) => Array.isArray(x) ? x.length > 0 : x !== null && x !== void 0 && x !== "");
|
|
3216
3418
|
});
|
|
3217
3419
|
}
|
|
3420
|
+
/**
|
|
3421
|
+
* Resolves the surface an operation addresses.
|
|
3422
|
+
*
|
|
3423
|
+
* The nested v0.9 `surfaceId` wins, because that is the id `MessageProcessor`
|
|
3424
|
+
* creates the surface under. Grouping by a top-level `surfaceId` instead files
|
|
3425
|
+
* the operations against a surface that never exists, which paints nothing —
|
|
3426
|
+
* the silence the missing-surface report above now names. A top-level
|
|
3427
|
+
* `surfaceId` is not the v0.9 shape, so it is honoured only when no nested id is
|
|
3428
|
+
* present. `getSurfaceId` in `@copilotkit/a2ui-renderer`'s web-components path
|
|
3429
|
+
* resolves it in the same order; the two disagreeing is what OSS-1048 recorded.
|
|
3430
|
+
*
|
|
3431
|
+
* @param operation - One A2UI operation, of any shape.
|
|
3432
|
+
* @returns The surface id, or null when the operation names none.
|
|
3433
|
+
*/
|
|
3218
3434
|
function getOperationSurfaceId(operation) {
|
|
3219
3435
|
if (!operation || typeof operation !== "object") return null;
|
|
3436
|
+
const nested = operation?.createSurface?.surfaceId ?? operation?.updateComponents?.surfaceId ?? operation?.updateDataModel?.surfaceId ?? operation?.deleteSurface?.surfaceId;
|
|
3437
|
+
if (typeof nested === "string") return nested;
|
|
3220
3438
|
if (typeof operation.surfaceId === "string") return operation.surfaceId;
|
|
3221
|
-
return
|
|
3439
|
+
return null;
|
|
3222
3440
|
}
|
|
3223
3441
|
|
|
3224
3442
|
//#endregion
|
|
@@ -3432,6 +3650,9 @@ const COPILOT_CLOUD_CHAT_URL$1 = "https://api.cloud.copilotkit.ai/copilotkit/v1"
|
|
|
3432
3650
|
const EMPTY_HEADERS = Object.freeze({});
|
|
3433
3651
|
const EMPTY_PROPERTIES = Object.freeze({});
|
|
3434
3652
|
const EMPTY_AGENTS = Object.freeze({});
|
|
3653
|
+
/** Registration name of a catch-all tool: handles any otherwise-unhandled call. */
|
|
3654
|
+
const WILDCARD_TOOL_NAME$1 = "*";
|
|
3655
|
+
const HUMAN_IN_THE_LOOP_ABORTED_MESSAGE = "Human-in-the-loop interaction aborted";
|
|
3435
3656
|
const DEFAULT_DESIGN_SKILL = `When generating UI with generateSandboxedUi, follow these design principles inspired by shadcn/ui:
|
|
3436
3657
|
|
|
3437
3658
|
- Use a minimal, flat aesthetic. Avoid drop shadows and gradients — rely on subtle borders (1px solid, light gray like #e5e7eb) to define surfaces.
|
|
@@ -3550,6 +3771,11 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3550
3771
|
}
|
|
3551
3772
|
const chatApiEndpoint = runtimeUrl ?? (resolvedPublicKey ? COPILOT_CLOUD_CHAT_URL$1 : void 0);
|
|
3552
3773
|
const frontendToolsList = useStableArrayProp(frontendTools, "frontendTools must be a stable array. If you want to dynamically add or remove tools, use `useFrontendTool` instead.");
|
|
3774
|
+
/**
|
|
3775
|
+
* A `humanInTheLoop` prop tool call that is parked, waiting on the user.
|
|
3776
|
+
* Keyed by tool call id, so parallel calls of one tool stay independent.
|
|
3777
|
+
*/
|
|
3778
|
+
const pendingHumanInTheLoopRef = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
3553
3779
|
const humanInTheLoopList = useStableArrayProp(humanInTheLoop, "humanInTheLoop must be a stable array. If you want to dynamically add or remove human-in-the-loop tools, use `useHumanInTheLoop` instead.");
|
|
3554
3780
|
const sandboxFunctionsList = useStableArrayProp(openGenerativeUI?.sandboxFunctions, "openGenerativeUI.sandboxFunctions must be a stable array.");
|
|
3555
3781
|
const processedHumanInTheLoopTools = (0, react.useMemo)(() => {
|
|
@@ -3562,20 +3788,52 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = EMPTY
|
|
|
3562
3788
|
parameters: tool.parameters,
|
|
3563
3789
|
followUp: tool.followUp,
|
|
3564
3790
|
...tool.agentId && { agentId: tool.agentId },
|
|
3565
|
-
handler: async () => {
|
|
3566
|
-
|
|
3567
|
-
|
|
3568
|
-
|
|
3791
|
+
handler: async (_args, context) => {
|
|
3792
|
+
const signal = context?.signal;
|
|
3793
|
+
const key = context?.toolCall?.id ?? tool.name;
|
|
3794
|
+
return new Promise((resolve, reject) => {
|
|
3795
|
+
if (signal?.aborted) {
|
|
3796
|
+
reject(new Error(HUMAN_IN_THE_LOOP_ABORTED_MESSAGE));
|
|
3797
|
+
return;
|
|
3798
|
+
}
|
|
3799
|
+
const pending = { resolve };
|
|
3800
|
+
pendingHumanInTheLoopRef.current.set(key, pending);
|
|
3801
|
+
if (signal) {
|
|
3802
|
+
const onAbort = () => {
|
|
3803
|
+
pendingHumanInTheLoopRef.current.delete(key);
|
|
3804
|
+
reject(new Error(HUMAN_IN_THE_LOOP_ABORTED_MESSAGE));
|
|
3805
|
+
};
|
|
3806
|
+
signal.addEventListener("abort", onAbort, { once: true });
|
|
3807
|
+
pending.detachAbort = () => {
|
|
3808
|
+
signal.removeEventListener("abort", onAbort);
|
|
3809
|
+
};
|
|
3810
|
+
}
|
|
3569
3811
|
});
|
|
3570
3812
|
}
|
|
3571
3813
|
};
|
|
3572
3814
|
processedTools.push(frontendTool);
|
|
3573
|
-
if (tool.render)
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
3577
|
-
|
|
3578
|
-
|
|
3815
|
+
if (tool.render) {
|
|
3816
|
+
const ToolComponent = tool.render;
|
|
3817
|
+
const RenderComponent = (props) => (0, react.createElement)(ToolComponent, {
|
|
3818
|
+
...props,
|
|
3819
|
+
name: tool.name === WILDCARD_TOOL_NAME$1 ? props.name : tool.name,
|
|
3820
|
+
description: tool.description || "",
|
|
3821
|
+
agentId: tool.agentId,
|
|
3822
|
+
respond: props.status === _copilotkit_core.ToolCallStatus.Executing ? async (result) => {
|
|
3823
|
+
const pending = pendingHumanInTheLoopRef.current.get(props.toolCallId);
|
|
3824
|
+
if (!pending) return;
|
|
3825
|
+
pending.detachAbort?.();
|
|
3826
|
+
pendingHumanInTheLoopRef.current.delete(props.toolCallId);
|
|
3827
|
+
pending.resolve(result);
|
|
3828
|
+
} : void 0
|
|
3829
|
+
});
|
|
3830
|
+
processedRenderToolCalls.push({
|
|
3831
|
+
name: tool.name,
|
|
3832
|
+
args: tool.parameters,
|
|
3833
|
+
render: RenderComponent,
|
|
3834
|
+
...tool.agentId && { agentId: tool.agentId }
|
|
3835
|
+
});
|
|
3836
|
+
}
|
|
3579
3837
|
});
|
|
3580
3838
|
return {
|
|
3581
3839
|
tools: processedTools,
|
|
@@ -5424,7 +5682,7 @@ function useMemories() {
|
|
|
5424
5682
|
* at the call site.
|
|
5425
5683
|
*/
|
|
5426
5684
|
async function recordAnnotation(args) {
|
|
5427
|
-
const { runtimeUrl, headers, type, payload, threadId, occurredAt } = args;
|
|
5685
|
+
const { runtimeUrl, headers, type, payload, threadId, occurredAt, fetch: fetchImplementation = globalThis.fetch } = args;
|
|
5428
5686
|
const body = {
|
|
5429
5687
|
type,
|
|
5430
5688
|
threadId,
|
|
@@ -5432,7 +5690,7 @@ async function recordAnnotation(args) {
|
|
|
5432
5690
|
...payload !== void 0 ? { payload } : {},
|
|
5433
5691
|
...occurredAt !== void 0 ? { occurredAt } : {}
|
|
5434
5692
|
};
|
|
5435
|
-
const response = await
|
|
5693
|
+
const response = await fetchImplementation(`${runtimeUrl}/annotate`, {
|
|
5436
5694
|
method: "POST",
|
|
5437
5695
|
headers: {
|
|
5438
5696
|
"Content-Type": "application/json",
|
|
@@ -5501,6 +5759,7 @@ function useLearnFromUserAction() {
|
|
|
5501
5759
|
...input.data !== void 0 ? { data: input.data } : {}
|
|
5502
5760
|
};
|
|
5503
5761
|
return recordAnnotation({
|
|
5762
|
+
fetch: copilotkit.ɵruntimeFetch,
|
|
5504
5763
|
runtimeUrl,
|
|
5505
5764
|
headers: copilotkit.headers ?? {},
|
|
5506
5765
|
type: "user_action",
|
|
@@ -5570,6 +5829,21 @@ function useLearnFromUserActionInCurrentThread() {
|
|
|
5570
5829
|
|
|
5571
5830
|
//#endregion
|
|
5572
5831
|
//#region src/v2/hooks/use-attachments.tsx
|
|
5832
|
+
const DEFAULT_MAX_SIZE = 20 * 1024 * 1024;
|
|
5833
|
+
/**
|
|
5834
|
+
* How many uploads run at once when `maxConcurrentUploads` is unset. One, because
|
|
5835
|
+
* `onUpload` is a public callback an app may have written expecting the previous
|
|
5836
|
+
* file to have finished — concurrency is something the app asks for.
|
|
5837
|
+
*/
|
|
5838
|
+
const DEFAULT_MAX_CONCURRENT_UPLOADS = 1;
|
|
5839
|
+
/**
|
|
5840
|
+
* At least one upload at a time, whole files only; `NaN` or a non-number falls back to the
|
|
5841
|
+
* default, and `Infinity` means "no limit" — bounded in practice by how many files are queued.
|
|
5842
|
+
*/
|
|
5843
|
+
function resolveMaxConcurrentUploads(configured) {
|
|
5844
|
+
if (typeof configured !== "number" || Number.isNaN(configured)) return DEFAULT_MAX_CONCURRENT_UPLOADS;
|
|
5845
|
+
return Math.max(1, Math.floor(configured));
|
|
5846
|
+
}
|
|
5573
5847
|
/**
|
|
5574
5848
|
* Hook that manages file attachment state — uploads, drag-and-drop, paste,
|
|
5575
5849
|
* and lifecycle. All returned callbacks are referentially stable across
|
|
@@ -5585,10 +5859,62 @@ function useAttachments({ config }) {
|
|
|
5585
5859
|
configRef.current = config;
|
|
5586
5860
|
const attachmentsRef = (0, react.useRef)([]);
|
|
5587
5861
|
attachmentsRef.current = attachments;
|
|
5862
|
+
const uploadQueueRef = (0, react.useRef)([]);
|
|
5863
|
+
const activeWorkersRef = (0, react.useRef)(0);
|
|
5864
|
+
const uploadFile = (0, react.useCallback)(async (file, placeholder, cfg) => {
|
|
5865
|
+
try {
|
|
5866
|
+
let source;
|
|
5867
|
+
let uploadMetadata;
|
|
5868
|
+
if (cfg?.onUpload) {
|
|
5869
|
+
const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
|
|
5870
|
+
source = uploadSource;
|
|
5871
|
+
uploadMetadata = meta;
|
|
5872
|
+
} else source = {
|
|
5873
|
+
type: "data",
|
|
5874
|
+
value: await (0, _copilotkit_shared.readFileAsBase64)(file),
|
|
5875
|
+
mimeType: file.type
|
|
5876
|
+
};
|
|
5877
|
+
let thumbnail;
|
|
5878
|
+
if (placeholder.type === "video") thumbnail = await (0, _copilotkit_shared.generateVideoThumbnail)(file);
|
|
5879
|
+
setAttachments((prev) => prev.map((att) => att.id === placeholder.id ? {
|
|
5880
|
+
...att,
|
|
5881
|
+
source,
|
|
5882
|
+
status: "ready",
|
|
5883
|
+
thumbnail,
|
|
5884
|
+
metadata: uploadMetadata
|
|
5885
|
+
} : att));
|
|
5886
|
+
} catch (error) {
|
|
5887
|
+
setAttachments((prev) => prev.filter((att) => att.id !== placeholder.id));
|
|
5888
|
+
console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
|
|
5889
|
+
cfg?.onUploadFailed?.({
|
|
5890
|
+
reason: "upload-failed",
|
|
5891
|
+
file,
|
|
5892
|
+
message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
|
|
5893
|
+
});
|
|
5894
|
+
}
|
|
5895
|
+
}, []);
|
|
5896
|
+
const drainUploadQueue = (0, react.useCallback)(async () => {
|
|
5897
|
+
activeWorkersRef.current++;
|
|
5898
|
+
try {
|
|
5899
|
+
for (;;) {
|
|
5900
|
+
const item = uploadQueueRef.current.shift();
|
|
5901
|
+
if (!item) return;
|
|
5902
|
+
try {
|
|
5903
|
+
await uploadFile(item.file, item.placeholder, item.cfg);
|
|
5904
|
+
} catch (error) {
|
|
5905
|
+
console.error("[CopilotKit] Upload worker error:", error);
|
|
5906
|
+
} finally {
|
|
5907
|
+
item.settle();
|
|
5908
|
+
}
|
|
5909
|
+
}
|
|
5910
|
+
} finally {
|
|
5911
|
+
activeWorkersRef.current--;
|
|
5912
|
+
}
|
|
5913
|
+
}, [uploadFile]);
|
|
5588
5914
|
const processFiles = (0, react.useCallback)(async (files) => {
|
|
5589
5915
|
const cfg = configRef.current;
|
|
5590
5916
|
const accept = cfg?.accept ?? "*/*";
|
|
5591
|
-
const maxSize = cfg?.maxSize ??
|
|
5917
|
+
const maxSize = cfg?.maxSize ?? DEFAULT_MAX_SIZE;
|
|
5592
5918
|
const rejectedFiles = files.filter((file) => !(0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
|
|
5593
5919
|
for (const file of rejectedFiles) cfg?.onUploadFailed?.({
|
|
5594
5920
|
reason: "invalid-type",
|
|
@@ -5596,6 +5922,7 @@ function useAttachments({ config }) {
|
|
|
5596
5922
|
message: `File "${file.name}" is not accepted. Supported types: ${accept}`
|
|
5597
5923
|
});
|
|
5598
5924
|
const validFiles = files.filter((file) => (0, _copilotkit_shared.matchesAcceptFilter)(file, accept));
|
|
5925
|
+
const queued = [];
|
|
5599
5926
|
for (const file of validFiles) {
|
|
5600
5927
|
if ((0, _copilotkit_shared.exceedsMaxSize)(file, maxSize)) {
|
|
5601
5928
|
cfg?.onUploadFailed?.({
|
|
@@ -5605,53 +5932,37 @@ function useAttachments({ config }) {
|
|
|
5605
5932
|
});
|
|
5606
5933
|
continue;
|
|
5607
5934
|
}
|
|
5608
|
-
|
|
5609
|
-
|
|
5610
|
-
|
|
5611
|
-
|
|
5612
|
-
|
|
5613
|
-
|
|
5614
|
-
|
|
5615
|
-
|
|
5616
|
-
|
|
5617
|
-
|
|
5618
|
-
|
|
5619
|
-
|
|
5620
|
-
|
|
5621
|
-
|
|
5622
|
-
|
|
5623
|
-
try {
|
|
5624
|
-
let source;
|
|
5625
|
-
let uploadMetadata;
|
|
5626
|
-
if (cfg?.onUpload) {
|
|
5627
|
-
const { metadata: meta, ...uploadSource } = await cfg.onUpload(file);
|
|
5628
|
-
source = uploadSource;
|
|
5629
|
-
uploadMetadata = meta;
|
|
5630
|
-
} else source = {
|
|
5631
|
-
type: "data",
|
|
5632
|
-
value: await (0, _copilotkit_shared.readFileAsBase64)(file),
|
|
5633
|
-
mimeType: file.type
|
|
5634
|
-
};
|
|
5635
|
-
let thumbnail;
|
|
5636
|
-
if (modality === "video") thumbnail = await (0, _copilotkit_shared.generateVideoThumbnail)(file);
|
|
5637
|
-
setAttachments((prev) => prev.map((att) => att.id === placeholderId ? {
|
|
5638
|
-
...att,
|
|
5639
|
-
source,
|
|
5640
|
-
status: "ready",
|
|
5641
|
-
thumbnail,
|
|
5642
|
-
metadata: uploadMetadata
|
|
5643
|
-
} : att));
|
|
5644
|
-
} catch (error) {
|
|
5645
|
-
setAttachments((prev) => prev.filter((att) => att.id !== placeholderId));
|
|
5646
|
-
console.error(`[CopilotKit] Failed to upload "${file.name}":`, error);
|
|
5647
|
-
cfg?.onUploadFailed?.({
|
|
5648
|
-
reason: "upload-failed",
|
|
5649
|
-
file,
|
|
5650
|
-
message: error instanceof Error ? error.message : `Failed to upload "${file.name}"`
|
|
5651
|
-
});
|
|
5652
|
-
}
|
|
5935
|
+
queued.push({
|
|
5936
|
+
file,
|
|
5937
|
+
placeholder: {
|
|
5938
|
+
id: (0, _copilotkit_shared.randomUUID)(),
|
|
5939
|
+
type: (0, _copilotkit_shared.getModalityFromMimeType)(file.type),
|
|
5940
|
+
source: {
|
|
5941
|
+
type: "data",
|
|
5942
|
+
value: "",
|
|
5943
|
+
mimeType: file.type
|
|
5944
|
+
},
|
|
5945
|
+
filename: file.name,
|
|
5946
|
+
size: file.size,
|
|
5947
|
+
status: "uploading"
|
|
5948
|
+
}
|
|
5949
|
+
});
|
|
5653
5950
|
}
|
|
5654
|
-
|
|
5951
|
+
if (queued.length === 0) return;
|
|
5952
|
+
setAttachments((prev) => [...prev, ...queued.map((q) => q.placeholder)]);
|
|
5953
|
+
const settled = queued.map(({ file, placeholder }) => new Promise((resolve) => {
|
|
5954
|
+
uploadQueueRef.current.push({
|
|
5955
|
+
file,
|
|
5956
|
+
placeholder,
|
|
5957
|
+
cfg,
|
|
5958
|
+
settle: resolve
|
|
5959
|
+
});
|
|
5960
|
+
}));
|
|
5961
|
+
const limit = resolveMaxConcurrentUploads(cfg?.maxConcurrentUploads);
|
|
5962
|
+
const toSpawn = Math.min(uploadQueueRef.current.length, Math.max(0, limit - activeWorkersRef.current));
|
|
5963
|
+
for (let i = 0; i < toSpawn; i++) drainUploadQueue();
|
|
5964
|
+
await Promise.all(settled);
|
|
5965
|
+
}, [drainUploadQueue]);
|
|
5655
5966
|
const handleFileUpload = (0, react.useCallback)(async (e) => {
|
|
5656
5967
|
if (!e.target.files?.length) return;
|
|
5657
5968
|
try {
|
|
@@ -5779,8 +6090,10 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
5779
6090
|
const warnedMissingUrlRef = (0, react.useRef)(false);
|
|
5780
6091
|
const runtimeUrlRef = (0, react.useRef)(copilotkit.runtimeUrl);
|
|
5781
6092
|
const headersRef = (0, react.useRef)(copilotkit.headers ?? {});
|
|
6093
|
+
const runtimeFetchRef = (0, react.useRef)(copilotkit.ɵruntimeFetch);
|
|
5782
6094
|
runtimeUrlRef.current = copilotkit.runtimeUrl;
|
|
5783
6095
|
headersRef.current = copilotkit.headers ?? {};
|
|
6096
|
+
runtimeFetchRef.current = copilotkit.ɵruntimeFetch;
|
|
5784
6097
|
const key = JSON.stringify(learningContainers);
|
|
5785
6098
|
const defaultKey = JSON.stringify(DEFAULT_CONTAINERS);
|
|
5786
6099
|
(0, react.useEffect)(() => {
|
|
@@ -5800,6 +6113,7 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
5800
6113
|
return;
|
|
5801
6114
|
}
|
|
5802
6115
|
recordAnnotation({
|
|
6116
|
+
fetch: copilotkit.ɵruntimeFetch,
|
|
5803
6117
|
runtimeUrl,
|
|
5804
6118
|
headers,
|
|
5805
6119
|
type: "set_learning_containers",
|
|
@@ -5827,6 +6141,7 @@ function useLearningContainers({ threadId, learningContainers }) {
|
|
|
5827
6141
|
const capturedRuntimeUrl = runtimeUrlRef.current;
|
|
5828
6142
|
const capturedHeaders = headersRef.current;
|
|
5829
6143
|
if (capturedRuntimeUrl) recordAnnotation({
|
|
6144
|
+
fetch: runtimeFetchRef.current,
|
|
5830
6145
|
runtimeUrl: capturedRuntimeUrl,
|
|
5831
6146
|
headers: capturedHeaders,
|
|
5832
6147
|
type: "set_learning_containers",
|
|
@@ -9089,6 +9404,41 @@ const CopilotChatToggleButton = react.default.forwardRef(function CopilotChatTog
|
|
|
9089
9404
|
});
|
|
9090
9405
|
CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
|
|
9091
9406
|
|
|
9407
|
+
//#endregion
|
|
9408
|
+
//#region src/v2/components/chat/modal-open-control.tsx
|
|
9409
|
+
const ModalOpenControlContext = (0, react.createContext)({});
|
|
9410
|
+
/**
|
|
9411
|
+
* Carries `open` / `onOpenChange` from a prebuilt surface down to the view that
|
|
9412
|
+
* owns the modal state.
|
|
9413
|
+
*
|
|
9414
|
+
* A context is required rather than plain props because `<CopilotSidebar>`
|
|
9415
|
+
* hands its view to `<CopilotChat>` as a `chatView` **component**. Threading a
|
|
9416
|
+
* value that changes (like `open`) through that component's identity would mint
|
|
9417
|
+
* a new element type on every toggle, and React unmounts and remounts the whole
|
|
9418
|
+
* chat subtree when the element type changes. That is the remount class of bug
|
|
9419
|
+
* already fixed for `<CopilotPopup>` on resize. Context keeps the override
|
|
9420
|
+
* identity stable while still re-rendering the view when `open` changes.
|
|
9421
|
+
*/
|
|
9422
|
+
function ModalOpenControlProvider({ open, onOpenChange, children }) {
|
|
9423
|
+
const value = (0, react.useMemo)(() => ({
|
|
9424
|
+
open,
|
|
9425
|
+
onOpenChange
|
|
9426
|
+
}), [open, onOpenChange]);
|
|
9427
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlContext.Provider, {
|
|
9428
|
+
value,
|
|
9429
|
+
children
|
|
9430
|
+
});
|
|
9431
|
+
}
|
|
9432
|
+
/**
|
|
9433
|
+
* Reads the controlled open state supplied by the surrounding prebuilt
|
|
9434
|
+
* surface. Returns an empty control (uncontrolled) when there is none.
|
|
9435
|
+
*
|
|
9436
|
+
* @returns The host's `open` / `onOpenChange` pair.
|
|
9437
|
+
*/
|
|
9438
|
+
function useModalOpenControl() {
|
|
9439
|
+
return (0, react.useContext)(ModalOpenControlContext);
|
|
9440
|
+
}
|
|
9441
|
+
|
|
9092
9442
|
//#endregion
|
|
9093
9443
|
//#region src/v2/components/chat/CopilotModalHeader.tsx
|
|
9094
9444
|
/**
|
|
@@ -9198,15 +9548,22 @@ CopilotModalHeader.DrawerLauncher.displayName = "CopilotModalHeader.DrawerLaunch
|
|
|
9198
9548
|
const DEFAULT_SIDEBAR_WIDTH = 480;
|
|
9199
9549
|
const SIDEBAR_TRANSITION_MS = 260;
|
|
9200
9550
|
function CopilotSidebarView({ header, toggleButton, width, defaultOpen = true, position = "right", ...props }) {
|
|
9551
|
+
const { open, onOpenChange } = useModalOpenControl();
|
|
9552
|
+
const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
|
|
9553
|
+
const internal = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotSidebarViewInternal, {
|
|
9554
|
+
header,
|
|
9555
|
+
toggleButton,
|
|
9556
|
+
width,
|
|
9557
|
+
position,
|
|
9558
|
+
...props
|
|
9559
|
+
});
|
|
9201
9560
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
9202
|
-
isModalDefaultOpen: defaultOpen,
|
|
9203
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
...props
|
|
9209
|
-
})
|
|
9561
|
+
isModalDefaultOpen: open ?? defaultOpen,
|
|
9562
|
+
children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
|
|
9563
|
+
open,
|
|
9564
|
+
onOpenChange,
|
|
9565
|
+
children: internal
|
|
9566
|
+
}) : internal
|
|
9210
9567
|
});
|
|
9211
9568
|
}
|
|
9212
9569
|
function CopilotSidebarViewInternal({ header, toggleButton, width, position = "right", ...props }) {
|
|
@@ -9270,7 +9627,7 @@ function CopilotSidebarViewInternal({ header, toggleButton, width, position = "r
|
|
|
9270
9627
|
"data-position": position,
|
|
9271
9628
|
className: cn("copilotKitSidebar copilotKitWindow", "cpk:fixed cpk:top-0 cpk:z-[1200] cpk:flex", position === "left" ? "cpk:left-0" : "cpk:right-0", "cpk:h-[100vh] cpk:h-[100dvh] cpk:max-h-screen", "cpk:w-full", position === "left" ? "cpk:border-r" : "cpk:border-l", "cpk:border-border cpk:bg-background cpk:text-foreground cpk:shadow-xl", "cpk:transition-transform cpk:duration-300 cpk:ease-out", isSidebarOpen ? "cpk:translate-x-0" : position === "left" ? "cpk:-translate-x-full cpk:pointer-events-none" : "cpk:translate-x-full cpk:pointer-events-none"),
|
|
9272
9629
|
style: {
|
|
9273
|
-
|
|
9630
|
+
"--sidebar-width": widthToCss(sidebarWidth),
|
|
9274
9631
|
paddingTop: "env(safe-area-inset-top)",
|
|
9275
9632
|
paddingBottom: "env(safe-area-inset-bottom)"
|
|
9276
9633
|
},
|
|
@@ -9332,17 +9689,24 @@ const dimensionToCss = (value, fallback) => {
|
|
|
9332
9689
|
return `${fallback}px`;
|
|
9333
9690
|
};
|
|
9334
9691
|
function CopilotPopupView({ header, toggleButton, width, height, clickOutsideToClose, defaultOpen = true, className, ...restProps }) {
|
|
9692
|
+
const { open, onOpenChange } = useModalOpenControl();
|
|
9693
|
+
const hasOpenControl = open !== void 0 || onOpenChange !== void 0;
|
|
9694
|
+
const internal = /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotPopupViewInternal, {
|
|
9695
|
+
header,
|
|
9696
|
+
toggleButton,
|
|
9697
|
+
width,
|
|
9698
|
+
height,
|
|
9699
|
+
clickOutsideToClose,
|
|
9700
|
+
className,
|
|
9701
|
+
...restProps
|
|
9702
|
+
});
|
|
9335
9703
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
9336
|
-
isModalDefaultOpen: defaultOpen,
|
|
9337
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
9338
|
-
|
|
9339
|
-
|
|
9340
|
-
|
|
9341
|
-
|
|
9342
|
-
clickOutsideToClose,
|
|
9343
|
-
className,
|
|
9344
|
-
...restProps
|
|
9345
|
-
})
|
|
9704
|
+
isModalDefaultOpen: open ?? defaultOpen,
|
|
9705
|
+
children: hasOpenControl ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ControlledModalOpenScope, {
|
|
9706
|
+
open,
|
|
9707
|
+
onOpenChange,
|
|
9708
|
+
children: internal
|
|
9709
|
+
}) : internal
|
|
9346
9710
|
});
|
|
9347
9711
|
}
|
|
9348
9712
|
function CopilotPopupViewInternal({ header, toggleButton, width, height, clickOutsideToClose, className, ...restProps }) {
|
|
@@ -9475,7 +9839,7 @@ var CopilotPopupView_default = CopilotPopupView;
|
|
|
9475
9839
|
|
|
9476
9840
|
//#endregion
|
|
9477
9841
|
//#region src/v2/components/chat/CopilotSidebar.tsx
|
|
9478
|
-
function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ...chatProps }) {
|
|
9842
|
+
function CopilotSidebar({ header, toggleButton, defaultOpen, open, onOpenChange, width, position, ...chatProps }) {
|
|
9479
9843
|
const { checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
|
|
9480
9844
|
const isSidebarLicensed = checkFeature("sidebar");
|
|
9481
9845
|
(0, react.useEffect)(() => {
|
|
@@ -9501,11 +9865,15 @@ function CopilotSidebar({ header, toggleButton, defaultOpen, width, position, ..
|
|
|
9501
9865
|
defaultOpen,
|
|
9502
9866
|
position
|
|
9503
9867
|
]);
|
|
9504
|
-
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isSidebarLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
9505
|
-
|
|
9506
|
-
|
|
9507
|
-
|
|
9508
|
-
|
|
9868
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isSidebarLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Sidebar" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlProvider, {
|
|
9869
|
+
open,
|
|
9870
|
+
onOpenChange,
|
|
9871
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
|
|
9872
|
+
welcomeScreen: CopilotSidebarView.WelcomeScreen,
|
|
9873
|
+
...chatProps,
|
|
9874
|
+
isModalDefaultOpen: defaultOpen,
|
|
9875
|
+
chatView: SidebarViewOverride
|
|
9876
|
+
})
|
|
9509
9877
|
})] });
|
|
9510
9878
|
}
|
|
9511
9879
|
CopilotSidebar.displayName = "CopilotSidebar";
|
|
@@ -9527,7 +9895,7 @@ const PopupViewOverride = (viewProps) => {
|
|
|
9527
9895
|
});
|
|
9528
9896
|
};
|
|
9529
9897
|
const PopupViewOverrideWithStatics = Object.assign(PopupViewOverride, CopilotChatView_default);
|
|
9530
|
-
function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickOutsideToClose, ...chatProps }) {
|
|
9898
|
+
function CopilotPopup({ header, toggleButton, defaultOpen, open, onOpenChange, width, height, clickOutsideToClose, ...chatProps }) {
|
|
9531
9899
|
const { checkFeature } = (0, _copilotkit_react_core_v2_context.useLicenseContext)();
|
|
9532
9900
|
const isPopupLicensed = checkFeature("popup");
|
|
9533
9901
|
(0, react.useEffect)(() => {
|
|
@@ -9550,11 +9918,15 @@ function CopilotPopup({ header, toggleButton, defaultOpen, width, height, clickO
|
|
|
9550
9918
|
]);
|
|
9551
9919
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)(react_jsx_runtime.Fragment, { children: [!isPopupLicensed && /* @__PURE__ */ (0, react_jsx_runtime.jsx)(InlineFeatureWarning, { featureName: "Popup" }), /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PopupShellPropsContext.Provider, {
|
|
9552
9920
|
value: shellProps,
|
|
9553
|
-
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(
|
|
9554
|
-
|
|
9555
|
-
|
|
9556
|
-
|
|
9557
|
-
|
|
9921
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ModalOpenControlProvider, {
|
|
9922
|
+
open,
|
|
9923
|
+
onOpenChange,
|
|
9924
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChat, {
|
|
9925
|
+
welcomeScreen: CopilotPopupView_default.WelcomeScreen,
|
|
9926
|
+
...chatProps,
|
|
9927
|
+
isModalDefaultOpen: defaultOpen,
|
|
9928
|
+
chatView: PopupViewOverrideWithStatics
|
|
9929
|
+
})
|
|
9558
9930
|
})
|
|
9559
9931
|
})] });
|
|
9560
9932
|
}
|
|
@@ -12623,4 +12995,4 @@ Object.defineProperty(exports, 'ɵrunMcpFollowUp', {
|
|
|
12623
12995
|
return ɵrunMcpFollowUp;
|
|
12624
12996
|
}
|
|
12625
12997
|
});
|
|
12626
|
-
//# sourceMappingURL=copilotkit-
|
|
12998
|
+
//# sourceMappingURL=copilotkit-BU3OvveB.cjs.map
|