@copilotkit/react-core 1.56.1 → 1.56.2-canary.pin-to-send
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-Cj2ZIxVr.mjs → copilotkit-BBYbekCa.mjs} +234 -60
- package/dist/copilotkit-BBYbekCa.mjs.map +1 -0
- package/dist/{copilotkit-CSJw5BG8.cjs → copilotkit-D5JT2Pu3.cjs} +233 -59
- package/dist/copilotkit-D5JT2Pu3.cjs.map +1 -0
- package/dist/{copilotkit-CCbxm6JM.d.mts → copilotkit-DArT2Iuw.d.mts} +62 -18
- package/dist/copilotkit-DArT2Iuw.d.mts.map +1 -0
- package/dist/{copilotkit-BtP7w7cT.d.cts → copilotkit-KEc28l8G.d.cts} +62 -18
- package/dist/copilotkit-KEc28l8G.d.cts.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +1 -1
- package/dist/index.d.mts +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +16 -40
- package/dist/index.umd.js.map +1 -1
- package/dist/v2/index.cjs +1 -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 +1 -1
- package/dist/v2/index.umd.js +232 -62
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +6 -6
- package/src/v2/components/chat/CopilotChat.tsx +80 -4
- package/src/v2/components/chat/CopilotChatInput.tsx +22 -0
- package/src/v2/components/chat/CopilotChatView.tsx +206 -11
- package/src/v2/components/chat/__tests__/CopilotChat.absentThreadConnect.test.tsx +66 -0
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +300 -2
- package/src/v2/components/chat/__tests__/CopilotChatView.connectingGate.test.tsx +56 -0
- package/src/v2/components/chat/__tests__/CopilotChatView.pinToSend.test.tsx +94 -0
- package/src/v2/components/chat/__tests__/copilot-chat-throttle.test.tsx +0 -1
- package/src/v2/components/chat/__tests__/normalize-auto-scroll.test.ts +37 -0
- package/src/v2/components/chat/index.ts +2 -0
- package/src/v2/components/chat/last-user-message-context.ts +21 -0
- package/src/v2/components/chat/normalize-auto-scroll.ts +17 -0
- package/src/v2/components/license-warning-banner.tsx +20 -1
- package/src/v2/hooks/__tests__/use-agent-stability.test.tsx +6 -0
- package/src/v2/hooks/__tests__/use-agent-thread-isolation.test.tsx +6 -0
- package/src/v2/hooks/__tests__/use-agent-throttle.test.tsx +76 -50
- package/src/v2/hooks/__tests__/use-pin-to-send.test.tsx +219 -0
- package/src/v2/hooks/__tests__/use-threads.test.tsx +68 -0
- package/src/v2/hooks/use-agent.tsx +34 -77
- package/src/v2/hooks/use-pin-to-send.ts +94 -0
- package/src/v2/hooks/use-threads.tsx +55 -12
- package/src/v2/providers/CopilotKitProvider.tsx +2 -11
- package/dist/copilotkit-BtP7w7cT.d.cts.map +0 -1
- package/dist/copilotkit-CCbxm6JM.d.mts.map +0 -1
- package/dist/copilotkit-CSJw5BG8.cjs.map +0 -1
- package/dist/copilotkit-Cj2ZIxVr.mjs.map +0 -1
package/dist/v2/index.umd.js
CHANGED
|
@@ -599,7 +599,7 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
599
599
|
//#region src/v2/components/chat/CopilotChatInput.tsx
|
|
600
600
|
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
601
601
|
const SLASH_MENU_ITEM_HEIGHT_PX = 40;
|
|
602
|
-
function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning = false, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, onAddFile, onChange, value, toolsMenu, autoFocus = false, positioning = "static", keyboardHeight = 0, containerRef, showDisclaimer, textArea, sendButton, startTranscribeButton, cancelTranscribeButton, finishTranscribeButton, addMenuButton, audioRecorder, disclaimer, children, className, ...props }) {
|
|
602
|
+
function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning = false, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, onAddFile, onChange, value, toolsMenu, autoFocus = false, positioning = "static", keyboardHeight = 0, containerRef, showDisclaimer, bottomAnchored = false, textArea, sendButton, startTranscribeButton, cancelTranscribeButton, finishTranscribeButton, addMenuButton, audioRecorder, disclaimer, children, className, ...props }) {
|
|
603
603
|
var _config$labels;
|
|
604
604
|
const isControlled = value !== void 0;
|
|
605
605
|
const [internalValue, setInternalValue] = (0, react.useState)(() => value !== null && value !== void 0 ? value : "");
|
|
@@ -1134,7 +1134,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1134
1134
|
className: cn("cpk:pointer-events-none cpk:relative cpk:z-20", positioning === "absolute" && "cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-0", className),
|
|
1135
1135
|
style: {
|
|
1136
1136
|
transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0,
|
|
1137
|
-
transition: "transform 0.2s ease-out"
|
|
1137
|
+
transition: "transform 0.2s ease-out",
|
|
1138
|
+
...positioning === "absolute" || bottomAnchored ? { paddingBottom: "var(--copilotkit-license-banner-offset, 0px)" } : {}
|
|
1138
1139
|
},
|
|
1139
1140
|
...props,
|
|
1140
1141
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1361,6 +1362,8 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1361
1362
|
|
|
1362
1363
|
//#endregion
|
|
1363
1364
|
//#region src/v2/components/license-warning-banner.tsx
|
|
1365
|
+
const LICENSE_BANNER_OFFSET_PX = 52;
|
|
1366
|
+
const LICENSE_BANNER_OFFSET_VAR = "--copilotkit-license-banner-offset";
|
|
1364
1367
|
const BANNER_STYLES = {
|
|
1365
1368
|
base: {
|
|
1366
1369
|
position: "fixed",
|
|
@@ -1402,6 +1405,14 @@ _radix_ui_react_dropdown_menu = __toESM(_radix_ui_react_dropdown_menu);
|
|
|
1402
1405
|
}
|
|
1403
1406
|
}
|
|
1404
1407
|
function BannerShell({ severity, message, actionLabel, actionUrl, onDismiss }) {
|
|
1408
|
+
(0, react.useEffect)(() => {
|
|
1409
|
+
if (typeof document === "undefined") return;
|
|
1410
|
+
const root = document.documentElement;
|
|
1411
|
+
root.style.setProperty(LICENSE_BANNER_OFFSET_VAR, `${LICENSE_BANNER_OFFSET_PX}px`);
|
|
1412
|
+
return () => {
|
|
1413
|
+
root.style.removeProperty(LICENSE_BANNER_OFFSET_VAR);
|
|
1414
|
+
};
|
|
1415
|
+
}, []);
|
|
1405
1416
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1406
1417
|
style: {
|
|
1407
1418
|
...BANNER_STYLES.base,
|
|
@@ -3386,7 +3397,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3386
3397
|
didMountRef.current = true;
|
|
3387
3398
|
}, []);
|
|
3388
3399
|
(0, react.useEffect)(() => {
|
|
3389
|
-
if (defaultThrottleMs !== void 0 && (!Number.isFinite(defaultThrottleMs) || defaultThrottleMs < 0)) console.error(`CopilotKitProvider: defaultThrottleMs must be a non-negative finite number, got ${defaultThrottleMs}. useAgent hooks without an explicit throttleMs will fall back to unthrottled.`);
|
|
3390
3400
|
copilotkit.setDefaultThrottleMs(defaultThrottleMs);
|
|
3391
3401
|
}, [copilotkit, defaultThrottleMs]);
|
|
3392
3402
|
const designSkill = (_openGenerativeUI$des = openGenerativeUI === null || openGenerativeUI === void 0 ? void 0 : openGenerativeUI.designSkill) !== null && _openGenerativeUI$des !== void 0 ? _openGenerativeUI$des : DEFAULT_DESIGN_SKILL;
|
|
@@ -3608,16 +3618,6 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3608
3618
|
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
3609
3619
|
const chatConfig = useCopilotChatConfiguration();
|
|
3610
3620
|
(_threadId = threadId) !== null && _threadId !== void 0 || (threadId = chatConfig === null || chatConfig === void 0 ? void 0 : chatConfig.threadId);
|
|
3611
|
-
const effectiveThrottleMs = (0, react.useMemo)(() => {
|
|
3612
|
-
var _ref;
|
|
3613
|
-
const resolved = (_ref = throttleMs !== null && throttleMs !== void 0 ? throttleMs : providerThrottleMs) !== null && _ref !== void 0 ? _ref : 0;
|
|
3614
|
-
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
3615
|
-
const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
|
|
3616
|
-
console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
|
|
3617
|
-
return 0;
|
|
3618
|
-
}
|
|
3619
|
-
return resolved;
|
|
3620
|
-
}, [throttleMs, providerThrottleMs]);
|
|
3621
3621
|
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
3622
3622
|
const updateFlags = (0, react.useMemo)(() => updates !== null && updates !== void 0 ? updates : ALL_UPDATES, [JSON.stringify(updates)]);
|
|
3623
3623
|
const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
@@ -3681,9 +3681,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3681
3681
|
]);
|
|
3682
3682
|
(0, react.useEffect)(() => {
|
|
3683
3683
|
if (updateFlags.length === 0) return;
|
|
3684
|
-
const handlers = {};
|
|
3685
|
-
let timerId = null;
|
|
3686
3684
|
let active = true;
|
|
3685
|
+
const handlers = {};
|
|
3687
3686
|
let batchScheduled = false;
|
|
3688
3687
|
const batchedForceUpdate = () => {
|
|
3689
3688
|
if (!active) return;
|
|
@@ -3695,46 +3694,24 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
3695
3694
|
});
|
|
3696
3695
|
}
|
|
3697
3696
|
};
|
|
3698
|
-
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged))
|
|
3699
|
-
const ms = effectiveThrottleMs;
|
|
3700
|
-
if (ms > 0) {
|
|
3701
|
-
let throttleActive = false;
|
|
3702
|
-
let pending = false;
|
|
3703
|
-
const throttledNotify = () => {
|
|
3704
|
-
if (!active) return;
|
|
3705
|
-
if (!throttleActive) {
|
|
3706
|
-
throttleActive = true;
|
|
3707
|
-
pending = false;
|
|
3708
|
-
forceUpdate();
|
|
3709
|
-
timerId = setTimeout(function trailingEdge() {
|
|
3710
|
-
timerId = null;
|
|
3711
|
-
if (active && pending) {
|
|
3712
|
-
pending = false;
|
|
3713
|
-
forceUpdate();
|
|
3714
|
-
timerId = setTimeout(trailingEdge, ms);
|
|
3715
|
-
} else throttleActive = false;
|
|
3716
|
-
}, ms);
|
|
3717
|
-
} else pending = true;
|
|
3718
|
-
};
|
|
3719
|
-
handlers.onMessagesChanged = throttledNotify;
|
|
3720
|
-
} else handlers.onMessagesChanged = forceUpdate;
|
|
3721
|
-
}
|
|
3697
|
+
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
|
|
3722
3698
|
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
|
|
3723
3699
|
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
3724
3700
|
handlers.onRunInitialized = batchedForceUpdate;
|
|
3725
3701
|
handlers.onRunFinalized = batchedForceUpdate;
|
|
3726
3702
|
handlers.onRunFailed = batchedForceUpdate;
|
|
3703
|
+
handlers.onRunErrorEvent = batchedForceUpdate;
|
|
3727
3704
|
}
|
|
3728
|
-
const subscription =
|
|
3705
|
+
const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
|
|
3729
3706
|
return () => {
|
|
3730
3707
|
active = false;
|
|
3731
|
-
if (timerId !== null) clearTimeout(timerId);
|
|
3732
3708
|
subscription.unsubscribe();
|
|
3733
3709
|
};
|
|
3734
3710
|
}, [
|
|
3735
3711
|
agent,
|
|
3736
3712
|
forceUpdate,
|
|
3737
|
-
|
|
3713
|
+
throttleMs,
|
|
3714
|
+
providerThrottleMs,
|
|
3738
3715
|
updateFlags
|
|
3739
3716
|
]);
|
|
3740
3717
|
(0, react.useEffect)(() => {
|
|
@@ -4705,13 +4682,14 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4705
4682
|
const { copilotkit } = useCopilotKit();
|
|
4706
4683
|
const [store] = (0, react.useState)(() => (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: globalThis.fetch }));
|
|
4707
4684
|
const coreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreads);
|
|
4708
|
-
const threads = (0, react.useMemo)(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt }) => ({
|
|
4685
|
+
const threads = (0, react.useMemo)(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt, lastRunAt }) => ({
|
|
4709
4686
|
id,
|
|
4710
4687
|
agentId,
|
|
4711
4688
|
name,
|
|
4712
4689
|
archived,
|
|
4713
4690
|
createdAt,
|
|
4714
|
-
updatedAt
|
|
4691
|
+
updatedAt,
|
|
4692
|
+
...lastRunAt !== void 0 ? { lastRunAt } : {}
|
|
4715
4693
|
})), [coreThreads]);
|
|
4716
4694
|
const storeIsLoading = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsIsLoading);
|
|
4717
4695
|
const storeError = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsError);
|
|
@@ -4725,7 +4703,9 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4725
4703
|
if (copilotkit.runtimeUrl) return null;
|
|
4726
4704
|
return /* @__PURE__ */ new Error("Runtime URL is not configured");
|
|
4727
4705
|
}, [copilotkit.runtimeUrl]);
|
|
4728
|
-
const
|
|
4706
|
+
const [hasDispatchedContext, setHasDispatchedContext] = (0, react.useState)(false);
|
|
4707
|
+
const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
|
|
4708
|
+
const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
|
|
4729
4709
|
const error = runtimeError !== null && runtimeError !== void 0 ? runtimeError : storeError;
|
|
4730
4710
|
(0, react.useEffect)(() => {
|
|
4731
4711
|
store.start();
|
|
@@ -4733,20 +4713,28 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
4733
4713
|
store.stop();
|
|
4734
4714
|
};
|
|
4735
4715
|
}, [store]);
|
|
4716
|
+
const runtimeStatus = copilotkit.runtimeConnectionStatus;
|
|
4736
4717
|
(0, react.useEffect)(() => {
|
|
4737
4718
|
var _copilotkit$intellige;
|
|
4738
|
-
|
|
4719
|
+
if (!copilotkit.runtimeUrl) {
|
|
4720
|
+
store.setContext(null);
|
|
4721
|
+
return;
|
|
4722
|
+
}
|
|
4723
|
+
if (runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return;
|
|
4724
|
+
const context = {
|
|
4739
4725
|
runtimeUrl: copilotkit.runtimeUrl,
|
|
4740
4726
|
headers: { ...copilotkit.headers },
|
|
4741
4727
|
wsUrl: (_copilotkit$intellige = copilotkit.intelligence) === null || _copilotkit$intellige === void 0 ? void 0 : _copilotkit$intellige.wsUrl,
|
|
4742
4728
|
agentId,
|
|
4743
4729
|
includeArchived,
|
|
4744
4730
|
limit
|
|
4745
|
-
}
|
|
4731
|
+
};
|
|
4746
4732
|
store.setContext(context);
|
|
4733
|
+
setHasDispatchedContext(true);
|
|
4747
4734
|
}, [
|
|
4748
4735
|
store,
|
|
4749
4736
|
copilotkit.runtimeUrl,
|
|
4737
|
+
runtimeStatus,
|
|
4750
4738
|
headersKey,
|
|
4751
4739
|
(_copilotkit$intellige2 = copilotkit.intelligence) === null || _copilotkit$intellige2 === void 0 ? void 0 : _copilotkit$intellige2.wsUrl,
|
|
4752
4740
|
agentId,
|
|
@@ -6308,9 +6296,97 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6308
6296
|
return keyboardState;
|
|
6309
6297
|
}
|
|
6310
6298
|
|
|
6299
|
+
//#endregion
|
|
6300
|
+
//#region src/v2/components/chat/normalize-auto-scroll.ts
|
|
6301
|
+
const VALID = [
|
|
6302
|
+
"pin-to-bottom",
|
|
6303
|
+
"pin-to-send",
|
|
6304
|
+
"none"
|
|
6305
|
+
];
|
|
6306
|
+
function normalizeAutoScroll(value) {
|
|
6307
|
+
if (value === void 0) return "pin-to-bottom";
|
|
6308
|
+
if (value === true) return "pin-to-bottom";
|
|
6309
|
+
if (value === false) return "none";
|
|
6310
|
+
if (VALID.includes(value)) return value;
|
|
6311
|
+
return "pin-to-bottom";
|
|
6312
|
+
}
|
|
6313
|
+
|
|
6314
|
+
//#endregion
|
|
6315
|
+
//#region src/v2/components/chat/last-user-message-context.ts
|
|
6316
|
+
const LastUserMessageContext = react.default.createContext({
|
|
6317
|
+
id: null,
|
|
6318
|
+
sendNonce: 0
|
|
6319
|
+
});
|
|
6320
|
+
|
|
6321
|
+
//#endregion
|
|
6322
|
+
//#region src/v2/hooks/use-pin-to-send.ts
|
|
6323
|
+
function usePinToSend({ scrollRef, contentRef, spacerRef, topOffset = 16 }) {
|
|
6324
|
+
const { id, sendNonce } = (0, react.useContext)(LastUserMessageContext);
|
|
6325
|
+
const lastNonceRef = (0, react.useRef)(-1);
|
|
6326
|
+
const currentSpacerHeightRef = (0, react.useRef)(0);
|
|
6327
|
+
(0, react.useEffect)(() => {
|
|
6328
|
+
if (sendNonce === lastNonceRef.current) return;
|
|
6329
|
+
lastNonceRef.current = sendNonce;
|
|
6330
|
+
if (!id) return;
|
|
6331
|
+
const scrollEl = scrollRef.current;
|
|
6332
|
+
const contentEl = contentRef.current;
|
|
6333
|
+
const spacerEl = spacerRef.current;
|
|
6334
|
+
if (!scrollEl || !contentEl || !spacerEl) return;
|
|
6335
|
+
const escaped = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(id) : id.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
6336
|
+
const targetEl = contentEl.querySelector(`[data-message-id="${escaped}"]`);
|
|
6337
|
+
if (!targetEl) return;
|
|
6338
|
+
const viewportHeight = scrollEl.clientHeight;
|
|
6339
|
+
const userMessageHeight = targetEl.getBoundingClientRect().height;
|
|
6340
|
+
const paddingTop = parseFloat(getComputedStyle(targetEl).paddingTop) || 0;
|
|
6341
|
+
const bubbleHeight = Math.max(0, userMessageHeight - paddingTop);
|
|
6342
|
+
const spacerHeight = Math.max(0, viewportHeight - bubbleHeight - topOffset);
|
|
6343
|
+
spacerEl.style.height = `${spacerHeight}px`;
|
|
6344
|
+
currentSpacerHeightRef.current = spacerHeight;
|
|
6345
|
+
const raf = requestAnimationFrame(() => {
|
|
6346
|
+
const targetTop = computeOffsetTop(targetEl, scrollEl) + paddingTop - topOffset;
|
|
6347
|
+
scrollEl.scrollTo({
|
|
6348
|
+
top: Math.max(0, targetTop),
|
|
6349
|
+
behavior: "smooth"
|
|
6350
|
+
});
|
|
6351
|
+
});
|
|
6352
|
+
const ro = new ResizeObserver(() => {
|
|
6353
|
+
if (!contentEl || !spacerEl || !scrollEl) return;
|
|
6354
|
+
const consumedBelow = contentEl.getBoundingClientRect().height - computeOffsetTop(targetEl, contentEl) - userMessageHeight;
|
|
6355
|
+
const remaining = Math.max(0, spacerHeight - consumedBelow);
|
|
6356
|
+
if (remaining < currentSpacerHeightRef.current) {
|
|
6357
|
+
spacerEl.style.height = `${remaining}px`;
|
|
6358
|
+
currentSpacerHeightRef.current = remaining;
|
|
6359
|
+
}
|
|
6360
|
+
});
|
|
6361
|
+
ro.observe(contentEl);
|
|
6362
|
+
return () => {
|
|
6363
|
+
cancelAnimationFrame(raf);
|
|
6364
|
+
ro.disconnect();
|
|
6365
|
+
};
|
|
6366
|
+
}, [
|
|
6367
|
+
id,
|
|
6368
|
+
sendNonce,
|
|
6369
|
+
scrollRef,
|
|
6370
|
+
contentRef,
|
|
6371
|
+
spacerRef,
|
|
6372
|
+
topOffset
|
|
6373
|
+
]);
|
|
6374
|
+
}
|
|
6375
|
+
function computeOffsetTop(el, stopAt) {
|
|
6376
|
+
const elRect = el.getBoundingClientRect();
|
|
6377
|
+
const stopRect = stopAt.getBoundingClientRect();
|
|
6378
|
+
return elRect.top - stopRect.top + stopAt.scrollTop;
|
|
6379
|
+
}
|
|
6380
|
+
|
|
6311
6381
|
//#endregion
|
|
6312
6382
|
//#region src/v2/components/chat/CopilotChatView.tsx
|
|
6313
6383
|
const FEATHER_HEIGHT = 96;
|
|
6384
|
+
const PIN_TO_SEND_FEATHER_HEIGHT = 48;
|
|
6385
|
+
const PinToSendSoftFeather = ({ className, style, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6386
|
+
className: cn("cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-4 cpk:h-12 cpk:pointer-events-none cpk:z-10 cpk:bg-gradient-to-t", "cpk:from-white cpk:to-transparent", "cpk:dark:from-[rgb(33,33,33)]", className),
|
|
6387
|
+
style,
|
|
6388
|
+
...props
|
|
6389
|
+
});
|
|
6314
6390
|
function DropOverlay() {
|
|
6315
6391
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6316
6392
|
className: cn("cpk:absolute cpk:inset-0 cpk:z-50 cpk:pointer-events-none", "cpk:flex cpk:items-center cpk:justify-center", "cpk:bg-primary/5 cpk:backdrop-blur-[2px]", "cpk:border-2 cpk:border-dashed cpk:border-primary/40 cpk:rounded-lg cpk:m-2"),
|
|
@@ -6323,7 +6399,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6323
6399
|
})
|
|
6324
6400
|
});
|
|
6325
6401
|
}
|
|
6326
|
-
function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, attachments, onRemoveAttachment, onAddFile, dragOver, onDragOver, onDragLeave, onDrop, disclaimer, children, className, ...props }) {
|
|
6402
|
+
function CopilotChatView({ messageView, input, scrollView, suggestionView, welcomeScreen, messages = [], autoScroll = true, isRunning = false, suggestions, suggestionLoadingIndexes, onSelectSuggestion, onSubmitMessage, onStop, inputMode, inputValue, onInputChange, onStartTranscribe, onCancelTranscribe, onFinishTranscribe, onFinishTranscribeWithAudio, attachments, onRemoveAttachment, onAddFile, dragOver, onDragOver, onDragLeave, onDrop, isConnecting = false, hasExplicitThreadId = false, disclaimer, children, className, ...props }) {
|
|
6327
6403
|
const inputContainerRef = (0, react.useRef)(null);
|
|
6328
6404
|
const [inputContainerHeight, setInputContainerHeight] = (0, react.useState)(0);
|
|
6329
6405
|
const [isResizing, setIsResizing] = (0, react.useState)(false);
|
|
@@ -6375,9 +6451,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6375
6451
|
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
6376
6452
|
containerRef: inputContainerRef,
|
|
6377
6453
|
showDisclaimer: true,
|
|
6454
|
+
bottomAnchored: true,
|
|
6378
6455
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
6379
6456
|
});
|
|
6380
|
-
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
|
|
6457
|
+
const hasSuggestions = !isConnecting && !isRunning && Array.isArray(suggestions) && suggestions.length > 0;
|
|
6381
6458
|
const BoundSuggestionView = hasSuggestions ? renderSlot(suggestionView, CopilotChatSuggestionView, {
|
|
6382
6459
|
suggestions,
|
|
6383
6460
|
loadingIndexes: suggestionLoadingIndexes,
|
|
@@ -6399,7 +6476,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6399
6476
|
})
|
|
6400
6477
|
})
|
|
6401
6478
|
});
|
|
6402
|
-
if (messages.length === 0 && !(welcomeScreen === false)) {
|
|
6479
|
+
if (messages.length === 0 && !(welcomeScreen === false) && !isConnecting && !hasExplicitThreadId) {
|
|
6403
6480
|
const BoundInputForWelcome = renderSlot(input, CopilotChatInput_default, {
|
|
6404
6481
|
onSubmitMessage,
|
|
6405
6482
|
onStop,
|
|
@@ -6507,9 +6584,60 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6507
6584
|
] })
|
|
6508
6585
|
});
|
|
6509
6586
|
};
|
|
6510
|
-
|
|
6587
|
+
const PinToSendScrollContainer = ({ children, scrollRef, contentRef, scrollToBottom, scrollToBottomButton, feather, inputContainerHeight, isResizing, nonAutoScrollEl, nonAutoScrollRefCallback, showScrollButton, className, ...props }) => {
|
|
6588
|
+
const spacerRef = (0, react.useRef)(null);
|
|
6589
|
+
usePinToSend({
|
|
6590
|
+
scrollRef,
|
|
6591
|
+
contentRef,
|
|
6592
|
+
spacerRef,
|
|
6593
|
+
topOffset: 16
|
|
6594
|
+
});
|
|
6595
|
+
const BoundFeather = renderSlot(feather, PinToSendSoftFeather, {});
|
|
6596
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
|
|
6597
|
+
value: nonAutoScrollEl,
|
|
6598
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6599
|
+
className: cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative", className),
|
|
6600
|
+
children: [
|
|
6601
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6602
|
+
ref: nonAutoScrollRefCallback,
|
|
6603
|
+
className: "cpk:flex-1 cpk:min-h-0 cpk:overflow-y-auto cpk:overflow-x-hidden",
|
|
6604
|
+
...props,
|
|
6605
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6606
|
+
ref: contentRef,
|
|
6607
|
+
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
6608
|
+
children
|
|
6609
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6610
|
+
ref: spacerRef,
|
|
6611
|
+
"data-pin-to-send-spacer": true,
|
|
6612
|
+
"aria-hidden": "true",
|
|
6613
|
+
style: {
|
|
6614
|
+
height: 0,
|
|
6615
|
+
flex: "0 0 auto"
|
|
6616
|
+
}
|
|
6617
|
+
})]
|
|
6618
|
+
}),
|
|
6619
|
+
BoundFeather,
|
|
6620
|
+
showScrollButton && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6621
|
+
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6622
|
+
style: { bottom: `${inputContainerHeight + PIN_TO_SEND_FEATHER_HEIGHT + 16}px` },
|
|
6623
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
6624
|
+
})
|
|
6625
|
+
]
|
|
6626
|
+
})
|
|
6627
|
+
});
|
|
6628
|
+
};
|
|
6629
|
+
_CopilotChatView.ScrollView = ({ children, autoScroll = "pin-to-bottom", scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
6630
|
+
const mode = normalizeAutoScroll(autoScroll);
|
|
6511
6631
|
const [hasMounted, setHasMounted] = (0, react.useState)(false);
|
|
6512
|
-
const
|
|
6632
|
+
const scrollRef = (0, react.useRef)(null);
|
|
6633
|
+
const contentRef = (0, react.useRef)(null);
|
|
6634
|
+
const scrollToBottom = (0, react.useCallback)(() => {
|
|
6635
|
+
const el = scrollRef.current;
|
|
6636
|
+
if (el) el.scrollTo({
|
|
6637
|
+
top: el.scrollHeight,
|
|
6638
|
+
behavior: "smooth"
|
|
6639
|
+
});
|
|
6640
|
+
}, []);
|
|
6513
6641
|
const [showScrollButton, setShowScrollButton] = (0, react.useState)(false);
|
|
6514
6642
|
const [nonAutoScrollEl, setNonAutoScrollEl] = (0, react.useState)(null);
|
|
6515
6643
|
const nonAutoScrollRefCallback = (0, react.useCallback)((el) => {
|
|
@@ -6520,7 +6648,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6520
6648
|
setHasMounted(true);
|
|
6521
6649
|
}, []);
|
|
6522
6650
|
(0, react.useEffect)(() => {
|
|
6523
|
-
if (
|
|
6651
|
+
if (mode === "pin-to-bottom") return;
|
|
6524
6652
|
const scrollElement = scrollRef.current;
|
|
6525
6653
|
if (!scrollElement) return;
|
|
6526
6654
|
const checkScroll = () => {
|
|
@@ -6534,7 +6662,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6534
6662
|
scrollElement.removeEventListener("scroll", checkScroll);
|
|
6535
6663
|
resizeObserver.disconnect();
|
|
6536
6664
|
};
|
|
6537
|
-
}, [scrollRef,
|
|
6665
|
+
}, [scrollRef, mode]);
|
|
6538
6666
|
if (!hasMounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6539
6667
|
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",
|
|
6540
6668
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -6542,7 +6670,7 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6542
6670
|
children
|
|
6543
6671
|
})
|
|
6544
6672
|
});
|
|
6545
|
-
if (
|
|
6673
|
+
if (mode === "none") {
|
|
6546
6674
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
6547
6675
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
|
|
6548
6676
|
value: nonAutoScrollEl,
|
|
@@ -6566,6 +6694,21 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6566
6694
|
})
|
|
6567
6695
|
});
|
|
6568
6696
|
}
|
|
6697
|
+
if (mode === "pin-to-send") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinToSendScrollContainer, {
|
|
6698
|
+
scrollRef,
|
|
6699
|
+
contentRef,
|
|
6700
|
+
scrollToBottom,
|
|
6701
|
+
scrollToBottomButton,
|
|
6702
|
+
feather,
|
|
6703
|
+
inputContainerHeight,
|
|
6704
|
+
isResizing,
|
|
6705
|
+
nonAutoScrollEl,
|
|
6706
|
+
nonAutoScrollRefCallback,
|
|
6707
|
+
showScrollButton,
|
|
6708
|
+
className,
|
|
6709
|
+
...props,
|
|
6710
|
+
children
|
|
6711
|
+
});
|
|
6569
6712
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom, {
|
|
6570
6713
|
className: cn("cpk:flex-1 cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0", className),
|
|
6571
6714
|
resize: "smooth",
|
|
@@ -6762,10 +6905,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6762
6905
|
var _ref, _attachmentsConfig$ac;
|
|
6763
6906
|
const existingConfig = useCopilotChatConfiguration();
|
|
6764
6907
|
const resolvedAgentId = (_ref = agentId !== null && agentId !== void 0 ? agentId : existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.agentId) !== null && _ref !== void 0 ? _ref : _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
6765
|
-
const
|
|
6766
|
-
|
|
6767
|
-
return (_ref2 = threadId !== null && threadId !== void 0 ? threadId : existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId) !== null && _ref2 !== void 0 ? _ref2 : (0, _copilotkit_shared.randomUUID)();
|
|
6768
|
-
}, [threadId, existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId]);
|
|
6908
|
+
const providedThreadId = threadId !== null && threadId !== void 0 ? threadId : existingConfig === null || existingConfig === void 0 ? void 0 : existingConfig.threadId;
|
|
6909
|
+
const resolvedThreadId = (0, react.useMemo)(() => providedThreadId !== null && providedThreadId !== void 0 ? providedThreadId : (0, _copilotkit_shared.randomUUID)(), [providedThreadId]);
|
|
6769
6910
|
const { agent } = useAgent({
|
|
6770
6911
|
agentId: resolvedAgentId,
|
|
6771
6912
|
threadId: resolvedThreadId,
|
|
@@ -6807,7 +6948,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6807
6948
|
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
|
|
6808
6949
|
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
|
|
6809
6950
|
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
|
|
6951
|
+
const [lastConnectedThreadId, setLastConnectedThreadId] = (0, react.useState)(null);
|
|
6952
|
+
const isConnecting = !!providedThreadId && lastConnectedThreadId !== resolvedThreadId;
|
|
6810
6953
|
(0, react.useEffect)(() => {
|
|
6954
|
+
if (!providedThreadId) return;
|
|
6811
6955
|
let detached = false;
|
|
6812
6956
|
const connectAbortController = new AbortController();
|
|
6813
6957
|
if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
|
|
@@ -6817,6 +6961,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6817
6961
|
} catch (error) {
|
|
6818
6962
|
if (detached) return;
|
|
6819
6963
|
console.error("CopilotChat: connectAgent failed", error);
|
|
6964
|
+
} finally {
|
|
6965
|
+
if (!detached) (typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 16))(() => {
|
|
6966
|
+
if (!detached) setLastConnectedThreadId(resolvedThreadId);
|
|
6967
|
+
});
|
|
6820
6968
|
}
|
|
6821
6969
|
};
|
|
6822
6970
|
connect(agent);
|
|
@@ -6828,7 +6976,8 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6828
6976
|
}, [
|
|
6829
6977
|
resolvedThreadId,
|
|
6830
6978
|
agent,
|
|
6831
|
-
resolvedAgentId
|
|
6979
|
+
resolvedAgentId,
|
|
6980
|
+
providedThreadId
|
|
6832
6981
|
]);
|
|
6833
6982
|
const onSubmitInput = (0, react.useCallback)(async (value) => {
|
|
6834
6983
|
if (selectedAttachments.some((a) => a.status === "uploading")) {
|
|
@@ -6985,6 +7134,22 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
6985
7134
|
}).join(";") : "";
|
|
6986
7135
|
return `${m.id}:${m.role}:${contentKey}:${toolCallsKey}`;
|
|
6987
7136
|
}).join(",")]);
|
|
7137
|
+
const lastUserMessageId = (0, react.useMemo)(() => {
|
|
7138
|
+
for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "user") return messages[i].id;
|
|
7139
|
+
return null;
|
|
7140
|
+
}, [messages]);
|
|
7141
|
+
const [sendNonce, setSendNonce] = (0, react.useState)(0);
|
|
7142
|
+
const prevLastUserMessageIdRef = (0, react.useRef)(lastUserMessageId);
|
|
7143
|
+
(0, react.useEffect)(() => {
|
|
7144
|
+
if (lastUserMessageId && lastUserMessageId !== prevLastUserMessageIdRef.current) {
|
|
7145
|
+
setSendNonce((n) => n + 1);
|
|
7146
|
+
prevLastUserMessageIdRef.current = lastUserMessageId;
|
|
7147
|
+
}
|
|
7148
|
+
}, [lastUserMessageId]);
|
|
7149
|
+
const lastUserMessageState = (0, react.useMemo)(() => ({
|
|
7150
|
+
id: lastUserMessageId,
|
|
7151
|
+
sendNonce
|
|
7152
|
+
}), [lastUserMessageId, sendNonce]);
|
|
6988
7153
|
const RenderedChatView = renderSlot(chatView, CopilotChatView, {
|
|
6989
7154
|
...mergedProps,
|
|
6990
7155
|
messages,
|
|
@@ -7003,7 +7168,9 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7003
7168
|
dragOver,
|
|
7004
7169
|
onDragOver: handleDragOver,
|
|
7005
7170
|
onDragLeave: handleDragLeave,
|
|
7006
|
-
onDrop: handleDrop
|
|
7171
|
+
onDrop: handleDrop,
|
|
7172
|
+
isConnecting,
|
|
7173
|
+
hasExplicitThreadId: !!providedThreadId
|
|
7007
7174
|
});
|
|
7008
7175
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
7009
7176
|
agentId: resolvedAgentId,
|
|
@@ -7038,7 +7205,10 @@ window.parent.postMessage({jsonrpc:"2.0",method:"ui/notifications/sandbox-proxy-
|
|
|
7038
7205
|
},
|
|
7039
7206
|
children: transcriptionError
|
|
7040
7207
|
}),
|
|
7041
|
-
|
|
7208
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(LastUserMessageContext.Provider, {
|
|
7209
|
+
value: lastUserMessageState,
|
|
7210
|
+
children: RenderedChatView
|
|
7211
|
+
})
|
|
7042
7212
|
]
|
|
7043
7213
|
})
|
|
7044
7214
|
});
|