@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
|
@@ -18,7 +18,7 @@ import { A2UIProvider, A2UIRenderer, A2UI_SCHEMA_CONTEXT_DESCRIPTION, DEFAULT_SU
|
|
|
18
18
|
import { zodToJsonSchema } from "zod-to-json-schema";
|
|
19
19
|
import { useVirtualizer } from "@tanstack/react-virtual";
|
|
20
20
|
import { createPortal, flushSync } from "react-dom";
|
|
21
|
-
import { StickToBottom,
|
|
21
|
+
import { StickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
22
22
|
import ReactMarkdown from "react-markdown";
|
|
23
23
|
|
|
24
24
|
//#region src/v2/lib/slots.tsx
|
|
@@ -580,7 +580,7 @@ CopilotChatAudioRecorder.displayName = "CopilotChatAudioRecorder";
|
|
|
580
580
|
//#region src/v2/components/chat/CopilotChatInput.tsx
|
|
581
581
|
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
582
582
|
const SLASH_MENU_ITEM_HEIGHT_PX = 40;
|
|
583
|
-
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 }) {
|
|
583
|
+
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 }) {
|
|
584
584
|
const isControlled = value !== void 0;
|
|
585
585
|
const [internalValue, setInternalValue] = useState(() => value ?? "");
|
|
586
586
|
useEffect(() => {
|
|
@@ -1104,7 +1104,8 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1104
1104
|
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),
|
|
1105
1105
|
style: {
|
|
1106
1106
|
transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0,
|
|
1107
|
-
transition: "transform 0.2s ease-out"
|
|
1107
|
+
transition: "transform 0.2s ease-out",
|
|
1108
|
+
...positioning === "absolute" || bottomAnchored ? { paddingBottom: "var(--copilotkit-license-banner-offset, 0px)" } : {}
|
|
1108
1109
|
},
|
|
1109
1110
|
...props,
|
|
1110
1111
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -1319,6 +1320,8 @@ CopilotKitInspector.displayName = "CopilotKitInspector";
|
|
|
1319
1320
|
|
|
1320
1321
|
//#endregion
|
|
1321
1322
|
//#region src/v2/components/license-warning-banner.tsx
|
|
1323
|
+
const LICENSE_BANNER_OFFSET_PX = 52;
|
|
1324
|
+
const LICENSE_BANNER_OFFSET_VAR = "--copilotkit-license-banner-offset";
|
|
1322
1325
|
const BANNER_STYLES = {
|
|
1323
1326
|
base: {
|
|
1324
1327
|
position: "fixed",
|
|
@@ -1360,6 +1363,14 @@ function getSeverityStyle(severity) {
|
|
|
1360
1363
|
}
|
|
1361
1364
|
}
|
|
1362
1365
|
function BannerShell({ severity, message, actionLabel, actionUrl, onDismiss }) {
|
|
1366
|
+
useEffect(() => {
|
|
1367
|
+
if (typeof document === "undefined") return;
|
|
1368
|
+
const root = document.documentElement;
|
|
1369
|
+
root.style.setProperty(LICENSE_BANNER_OFFSET_VAR, `${LICENSE_BANNER_OFFSET_PX}px`);
|
|
1370
|
+
return () => {
|
|
1371
|
+
root.style.removeProperty(LICENSE_BANNER_OFFSET_VAR);
|
|
1372
|
+
};
|
|
1373
|
+
}, []);
|
|
1363
1374
|
return /* @__PURE__ */ jsxs("div", {
|
|
1364
1375
|
style: {
|
|
1365
1376
|
...BANNER_STYLES.base,
|
|
@@ -3312,7 +3323,6 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
|
|
|
3312
3323
|
didMountRef.current = true;
|
|
3313
3324
|
}, []);
|
|
3314
3325
|
useEffect(() => {
|
|
3315
|
-
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.`);
|
|
3316
3326
|
copilotkit.setDefaultThrottleMs(defaultThrottleMs);
|
|
3317
3327
|
}, [copilotkit, defaultThrottleMs]);
|
|
3318
3328
|
const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
|
|
@@ -3529,15 +3539,6 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3529
3539
|
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
3530
3540
|
const chatConfig = useCopilotChatConfiguration();
|
|
3531
3541
|
threadId ??= chatConfig?.threadId;
|
|
3532
|
-
const effectiveThrottleMs = useMemo(() => {
|
|
3533
|
-
const resolved = throttleMs ?? providerThrottleMs ?? 0;
|
|
3534
|
-
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
3535
|
-
const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
|
|
3536
|
-
console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
|
|
3537
|
-
return 0;
|
|
3538
|
-
}
|
|
3539
|
-
return resolved;
|
|
3540
|
-
}, [throttleMs, providerThrottleMs]);
|
|
3541
3542
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
3542
3543
|
const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
|
|
3543
3544
|
const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
|
|
@@ -3600,9 +3601,8 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3600
3601
|
]);
|
|
3601
3602
|
useEffect(() => {
|
|
3602
3603
|
if (updateFlags.length === 0) return;
|
|
3603
|
-
const handlers = {};
|
|
3604
|
-
let timerId = null;
|
|
3605
3604
|
let active = true;
|
|
3605
|
+
const handlers = {};
|
|
3606
3606
|
let batchScheduled = false;
|
|
3607
3607
|
const batchedForceUpdate = () => {
|
|
3608
3608
|
if (!active) return;
|
|
@@ -3614,46 +3614,24 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3614
3614
|
});
|
|
3615
3615
|
}
|
|
3616
3616
|
};
|
|
3617
|
-
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged))
|
|
3618
|
-
const ms = effectiveThrottleMs;
|
|
3619
|
-
if (ms > 0) {
|
|
3620
|
-
let throttleActive = false;
|
|
3621
|
-
let pending = false;
|
|
3622
|
-
const throttledNotify = () => {
|
|
3623
|
-
if (!active) return;
|
|
3624
|
-
if (!throttleActive) {
|
|
3625
|
-
throttleActive = true;
|
|
3626
|
-
pending = false;
|
|
3627
|
-
forceUpdate();
|
|
3628
|
-
timerId = setTimeout(function trailingEdge() {
|
|
3629
|
-
timerId = null;
|
|
3630
|
-
if (active && pending) {
|
|
3631
|
-
pending = false;
|
|
3632
|
-
forceUpdate();
|
|
3633
|
-
timerId = setTimeout(trailingEdge, ms);
|
|
3634
|
-
} else throttleActive = false;
|
|
3635
|
-
}, ms);
|
|
3636
|
-
} else pending = true;
|
|
3637
|
-
};
|
|
3638
|
-
handlers.onMessagesChanged = throttledNotify;
|
|
3639
|
-
} else handlers.onMessagesChanged = forceUpdate;
|
|
3640
|
-
}
|
|
3617
|
+
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
|
|
3641
3618
|
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
|
|
3642
3619
|
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
3643
3620
|
handlers.onRunInitialized = batchedForceUpdate;
|
|
3644
3621
|
handlers.onRunFinalized = batchedForceUpdate;
|
|
3645
3622
|
handlers.onRunFailed = batchedForceUpdate;
|
|
3623
|
+
handlers.onRunErrorEvent = batchedForceUpdate;
|
|
3646
3624
|
}
|
|
3647
|
-
const subscription =
|
|
3625
|
+
const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
|
|
3648
3626
|
return () => {
|
|
3649
3627
|
active = false;
|
|
3650
|
-
if (timerId !== null) clearTimeout(timerId);
|
|
3651
3628
|
subscription.unsubscribe();
|
|
3652
3629
|
};
|
|
3653
3630
|
}, [
|
|
3654
3631
|
agent,
|
|
3655
3632
|
forceUpdate,
|
|
3656
|
-
|
|
3633
|
+
throttleMs,
|
|
3634
|
+
providerThrottleMs,
|
|
3657
3635
|
updateFlags
|
|
3658
3636
|
]);
|
|
3659
3637
|
useEffect(() => {
|
|
@@ -4607,13 +4585,14 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4607
4585
|
const { copilotkit } = useCopilotKit();
|
|
4608
4586
|
const [store] = useState(() => ɵcreateThreadStore({ fetch: globalThis.fetch }));
|
|
4609
4587
|
const coreThreads = useThreadStoreSelector(store, ɵselectThreads);
|
|
4610
|
-
const threads = useMemo(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt }) => ({
|
|
4588
|
+
const threads = useMemo(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt, lastRunAt }) => ({
|
|
4611
4589
|
id,
|
|
4612
4590
|
agentId,
|
|
4613
4591
|
name,
|
|
4614
4592
|
archived,
|
|
4615
4593
|
createdAt,
|
|
4616
|
-
updatedAt
|
|
4594
|
+
updatedAt,
|
|
4595
|
+
...lastRunAt !== void 0 ? { lastRunAt } : {}
|
|
4617
4596
|
})), [coreThreads]);
|
|
4618
4597
|
const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);
|
|
4619
4598
|
const storeError = useThreadStoreSelector(store, ɵselectThreadsError);
|
|
@@ -4626,7 +4605,9 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4626
4605
|
if (copilotkit.runtimeUrl) return null;
|
|
4627
4606
|
return /* @__PURE__ */ new Error("Runtime URL is not configured");
|
|
4628
4607
|
}, [copilotkit.runtimeUrl]);
|
|
4629
|
-
const
|
|
4608
|
+
const [hasDispatchedContext, setHasDispatchedContext] = useState(false);
|
|
4609
|
+
const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
|
|
4610
|
+
const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
|
|
4630
4611
|
const error = runtimeError ?? storeError;
|
|
4631
4612
|
useEffect(() => {
|
|
4632
4613
|
store.start();
|
|
@@ -4634,19 +4615,27 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4634
4615
|
store.stop();
|
|
4635
4616
|
};
|
|
4636
4617
|
}, [store]);
|
|
4618
|
+
const runtimeStatus = copilotkit.runtimeConnectionStatus;
|
|
4637
4619
|
useEffect(() => {
|
|
4638
|
-
|
|
4620
|
+
if (!copilotkit.runtimeUrl) {
|
|
4621
|
+
store.setContext(null);
|
|
4622
|
+
return;
|
|
4623
|
+
}
|
|
4624
|
+
if (runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) return;
|
|
4625
|
+
const context = {
|
|
4639
4626
|
runtimeUrl: copilotkit.runtimeUrl,
|
|
4640
4627
|
headers: { ...copilotkit.headers },
|
|
4641
4628
|
wsUrl: copilotkit.intelligence?.wsUrl,
|
|
4642
4629
|
agentId,
|
|
4643
4630
|
includeArchived,
|
|
4644
4631
|
limit
|
|
4645
|
-
}
|
|
4632
|
+
};
|
|
4646
4633
|
store.setContext(context);
|
|
4634
|
+
setHasDispatchedContext(true);
|
|
4647
4635
|
}, [
|
|
4648
4636
|
store,
|
|
4649
4637
|
copilotkit.runtimeUrl,
|
|
4638
|
+
runtimeStatus,
|
|
4650
4639
|
headersKey,
|
|
4651
4640
|
copilotkit.intelligence?.wsUrl,
|
|
4652
4641
|
agentId,
|
|
@@ -6171,9 +6160,97 @@ function useKeyboardHeight() {
|
|
|
6171
6160
|
return keyboardState;
|
|
6172
6161
|
}
|
|
6173
6162
|
|
|
6163
|
+
//#endregion
|
|
6164
|
+
//#region src/v2/components/chat/normalize-auto-scroll.ts
|
|
6165
|
+
const VALID = [
|
|
6166
|
+
"pin-to-bottom",
|
|
6167
|
+
"pin-to-send",
|
|
6168
|
+
"none"
|
|
6169
|
+
];
|
|
6170
|
+
function normalizeAutoScroll(value) {
|
|
6171
|
+
if (value === void 0) return "pin-to-bottom";
|
|
6172
|
+
if (value === true) return "pin-to-bottom";
|
|
6173
|
+
if (value === false) return "none";
|
|
6174
|
+
if (VALID.includes(value)) return value;
|
|
6175
|
+
return "pin-to-bottom";
|
|
6176
|
+
}
|
|
6177
|
+
|
|
6178
|
+
//#endregion
|
|
6179
|
+
//#region src/v2/components/chat/last-user-message-context.ts
|
|
6180
|
+
const LastUserMessageContext = React.createContext({
|
|
6181
|
+
id: null,
|
|
6182
|
+
sendNonce: 0
|
|
6183
|
+
});
|
|
6184
|
+
|
|
6185
|
+
//#endregion
|
|
6186
|
+
//#region src/v2/hooks/use-pin-to-send.ts
|
|
6187
|
+
function usePinToSend({ scrollRef, contentRef, spacerRef, topOffset = 16 }) {
|
|
6188
|
+
const { id, sendNonce } = useContext(LastUserMessageContext);
|
|
6189
|
+
const lastNonceRef = useRef(-1);
|
|
6190
|
+
const currentSpacerHeightRef = useRef(0);
|
|
6191
|
+
useEffect(() => {
|
|
6192
|
+
if (sendNonce === lastNonceRef.current) return;
|
|
6193
|
+
lastNonceRef.current = sendNonce;
|
|
6194
|
+
if (!id) return;
|
|
6195
|
+
const scrollEl = scrollRef.current;
|
|
6196
|
+
const contentEl = contentRef.current;
|
|
6197
|
+
const spacerEl = spacerRef.current;
|
|
6198
|
+
if (!scrollEl || !contentEl || !spacerEl) return;
|
|
6199
|
+
const escaped = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(id) : id.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
6200
|
+
const targetEl = contentEl.querySelector(`[data-message-id="${escaped}"]`);
|
|
6201
|
+
if (!targetEl) return;
|
|
6202
|
+
const viewportHeight = scrollEl.clientHeight;
|
|
6203
|
+
const userMessageHeight = targetEl.getBoundingClientRect().height;
|
|
6204
|
+
const paddingTop = parseFloat(getComputedStyle(targetEl).paddingTop) || 0;
|
|
6205
|
+
const bubbleHeight = Math.max(0, userMessageHeight - paddingTop);
|
|
6206
|
+
const spacerHeight = Math.max(0, viewportHeight - bubbleHeight - topOffset);
|
|
6207
|
+
spacerEl.style.height = `${spacerHeight}px`;
|
|
6208
|
+
currentSpacerHeightRef.current = spacerHeight;
|
|
6209
|
+
const raf = requestAnimationFrame(() => {
|
|
6210
|
+
const targetTop = computeOffsetTop(targetEl, scrollEl) + paddingTop - topOffset;
|
|
6211
|
+
scrollEl.scrollTo({
|
|
6212
|
+
top: Math.max(0, targetTop),
|
|
6213
|
+
behavior: "smooth"
|
|
6214
|
+
});
|
|
6215
|
+
});
|
|
6216
|
+
const ro = new ResizeObserver(() => {
|
|
6217
|
+
if (!contentEl || !spacerEl || !scrollEl) return;
|
|
6218
|
+
const consumedBelow = contentEl.getBoundingClientRect().height - computeOffsetTop(targetEl, contentEl) - userMessageHeight;
|
|
6219
|
+
const remaining = Math.max(0, spacerHeight - consumedBelow);
|
|
6220
|
+
if (remaining < currentSpacerHeightRef.current) {
|
|
6221
|
+
spacerEl.style.height = `${remaining}px`;
|
|
6222
|
+
currentSpacerHeightRef.current = remaining;
|
|
6223
|
+
}
|
|
6224
|
+
});
|
|
6225
|
+
ro.observe(contentEl);
|
|
6226
|
+
return () => {
|
|
6227
|
+
cancelAnimationFrame(raf);
|
|
6228
|
+
ro.disconnect();
|
|
6229
|
+
};
|
|
6230
|
+
}, [
|
|
6231
|
+
id,
|
|
6232
|
+
sendNonce,
|
|
6233
|
+
scrollRef,
|
|
6234
|
+
contentRef,
|
|
6235
|
+
spacerRef,
|
|
6236
|
+
topOffset
|
|
6237
|
+
]);
|
|
6238
|
+
}
|
|
6239
|
+
function computeOffsetTop(el, stopAt) {
|
|
6240
|
+
const elRect = el.getBoundingClientRect();
|
|
6241
|
+
const stopRect = stopAt.getBoundingClientRect();
|
|
6242
|
+
return elRect.top - stopRect.top + stopAt.scrollTop;
|
|
6243
|
+
}
|
|
6244
|
+
|
|
6174
6245
|
//#endregion
|
|
6175
6246
|
//#region src/v2/components/chat/CopilotChatView.tsx
|
|
6176
6247
|
const FEATHER_HEIGHT = 96;
|
|
6248
|
+
const PIN_TO_SEND_FEATHER_HEIGHT = 48;
|
|
6249
|
+
const PinToSendSoftFeather = ({ className, style, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
6250
|
+
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),
|
|
6251
|
+
style,
|
|
6252
|
+
...props
|
|
6253
|
+
});
|
|
6177
6254
|
function DropOverlay() {
|
|
6178
6255
|
return /* @__PURE__ */ jsx("div", {
|
|
6179
6256
|
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"),
|
|
@@ -6186,7 +6263,7 @@ function DropOverlay() {
|
|
|
6186
6263
|
})
|
|
6187
6264
|
});
|
|
6188
6265
|
}
|
|
6189
|
-
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 }) {
|
|
6266
|
+
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 }) {
|
|
6190
6267
|
const inputContainerRef = useRef(null);
|
|
6191
6268
|
const [inputContainerHeight, setInputContainerHeight] = useState(0);
|
|
6192
6269
|
const [isResizing, setIsResizing] = useState(false);
|
|
@@ -6238,9 +6315,10 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6238
6315
|
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
6239
6316
|
containerRef: inputContainerRef,
|
|
6240
6317
|
showDisclaimer: true,
|
|
6318
|
+
bottomAnchored: true,
|
|
6241
6319
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
6242
6320
|
});
|
|
6243
|
-
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
|
|
6321
|
+
const hasSuggestions = !isConnecting && !isRunning && Array.isArray(suggestions) && suggestions.length > 0;
|
|
6244
6322
|
const BoundSuggestionView = hasSuggestions ? renderSlot(suggestionView, CopilotChatSuggestionView, {
|
|
6245
6323
|
suggestions,
|
|
6246
6324
|
loadingIndexes: suggestionLoadingIndexes,
|
|
@@ -6262,7 +6340,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6262
6340
|
})
|
|
6263
6341
|
})
|
|
6264
6342
|
});
|
|
6265
|
-
if (messages.length === 0 && !(welcomeScreen === false)) {
|
|
6343
|
+
if (messages.length === 0 && !(welcomeScreen === false) && !isConnecting && !hasExplicitThreadId) {
|
|
6266
6344
|
const BoundInputForWelcome = renderSlot(input, CopilotChatInput_default, {
|
|
6267
6345
|
onSubmitMessage,
|
|
6268
6346
|
onStop,
|
|
@@ -6369,9 +6447,60 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6369
6447
|
] })
|
|
6370
6448
|
});
|
|
6371
6449
|
};
|
|
6372
|
-
|
|
6450
|
+
const PinToSendScrollContainer = ({ children, scrollRef, contentRef, scrollToBottom, scrollToBottomButton, feather, inputContainerHeight, isResizing, nonAutoScrollEl, nonAutoScrollRefCallback, showScrollButton, className, ...props }) => {
|
|
6451
|
+
const spacerRef = useRef(null);
|
|
6452
|
+
usePinToSend({
|
|
6453
|
+
scrollRef,
|
|
6454
|
+
contentRef,
|
|
6455
|
+
spacerRef,
|
|
6456
|
+
topOffset: 16
|
|
6457
|
+
});
|
|
6458
|
+
const BoundFeather = renderSlot(feather, PinToSendSoftFeather, {});
|
|
6459
|
+
return /* @__PURE__ */ jsx(ScrollElementContext.Provider, {
|
|
6460
|
+
value: nonAutoScrollEl,
|
|
6461
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
6462
|
+
className: cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative", className),
|
|
6463
|
+
children: [
|
|
6464
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6465
|
+
ref: nonAutoScrollRefCallback,
|
|
6466
|
+
className: "cpk:flex-1 cpk:min-h-0 cpk:overflow-y-auto cpk:overflow-x-hidden",
|
|
6467
|
+
...props,
|
|
6468
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
6469
|
+
ref: contentRef,
|
|
6470
|
+
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
6471
|
+
children
|
|
6472
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
6473
|
+
ref: spacerRef,
|
|
6474
|
+
"data-pin-to-send-spacer": true,
|
|
6475
|
+
"aria-hidden": "true",
|
|
6476
|
+
style: {
|
|
6477
|
+
height: 0,
|
|
6478
|
+
flex: "0 0 auto"
|
|
6479
|
+
}
|
|
6480
|
+
})]
|
|
6481
|
+
}),
|
|
6482
|
+
BoundFeather,
|
|
6483
|
+
showScrollButton && !isResizing && /* @__PURE__ */ jsx("div", {
|
|
6484
|
+
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6485
|
+
style: { bottom: `${inputContainerHeight + PIN_TO_SEND_FEATHER_HEIGHT + 16}px` },
|
|
6486
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
6487
|
+
})
|
|
6488
|
+
]
|
|
6489
|
+
})
|
|
6490
|
+
});
|
|
6491
|
+
};
|
|
6492
|
+
_CopilotChatView.ScrollView = ({ children, autoScroll = "pin-to-bottom", scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
6493
|
+
const mode = normalizeAutoScroll(autoScroll);
|
|
6373
6494
|
const [hasMounted, setHasMounted] = useState(false);
|
|
6374
|
-
const
|
|
6495
|
+
const scrollRef = useRef(null);
|
|
6496
|
+
const contentRef = useRef(null);
|
|
6497
|
+
const scrollToBottom = useCallback(() => {
|
|
6498
|
+
const el = scrollRef.current;
|
|
6499
|
+
if (el) el.scrollTo({
|
|
6500
|
+
top: el.scrollHeight,
|
|
6501
|
+
behavior: "smooth"
|
|
6502
|
+
});
|
|
6503
|
+
}, []);
|
|
6375
6504
|
const [showScrollButton, setShowScrollButton] = useState(false);
|
|
6376
6505
|
const [nonAutoScrollEl, setNonAutoScrollEl] = useState(null);
|
|
6377
6506
|
const nonAutoScrollRefCallback = useCallback((el) => {
|
|
@@ -6382,7 +6511,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6382
6511
|
setHasMounted(true);
|
|
6383
6512
|
}, []);
|
|
6384
6513
|
useEffect(() => {
|
|
6385
|
-
if (
|
|
6514
|
+
if (mode === "pin-to-bottom") return;
|
|
6386
6515
|
const scrollElement = scrollRef.current;
|
|
6387
6516
|
if (!scrollElement) return;
|
|
6388
6517
|
const checkScroll = () => {
|
|
@@ -6396,7 +6525,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6396
6525
|
scrollElement.removeEventListener("scroll", checkScroll);
|
|
6397
6526
|
resizeObserver.disconnect();
|
|
6398
6527
|
};
|
|
6399
|
-
}, [scrollRef,
|
|
6528
|
+
}, [scrollRef, mode]);
|
|
6400
6529
|
if (!hasMounted) return /* @__PURE__ */ jsx("div", {
|
|
6401
6530
|
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",
|
|
6402
6531
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -6404,7 +6533,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6404
6533
|
children
|
|
6405
6534
|
})
|
|
6406
6535
|
});
|
|
6407
|
-
if (
|
|
6536
|
+
if (mode === "none") {
|
|
6408
6537
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
6409
6538
|
return /* @__PURE__ */ jsx(ScrollElementContext.Provider, {
|
|
6410
6539
|
value: nonAutoScrollEl,
|
|
@@ -6428,6 +6557,21 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6428
6557
|
})
|
|
6429
6558
|
});
|
|
6430
6559
|
}
|
|
6560
|
+
if (mode === "pin-to-send") return /* @__PURE__ */ jsx(PinToSendScrollContainer, {
|
|
6561
|
+
scrollRef,
|
|
6562
|
+
contentRef,
|
|
6563
|
+
scrollToBottom,
|
|
6564
|
+
scrollToBottomButton,
|
|
6565
|
+
feather,
|
|
6566
|
+
inputContainerHeight,
|
|
6567
|
+
isResizing,
|
|
6568
|
+
nonAutoScrollEl,
|
|
6569
|
+
nonAutoScrollRefCallback,
|
|
6570
|
+
showScrollButton,
|
|
6571
|
+
className,
|
|
6572
|
+
...props,
|
|
6573
|
+
children
|
|
6574
|
+
});
|
|
6431
6575
|
return /* @__PURE__ */ jsx(StickToBottom, {
|
|
6432
6576
|
className: cn("cpk:flex-1 cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0", className),
|
|
6433
6577
|
resize: "smooth",
|
|
@@ -6620,7 +6764,8 @@ async function transcribeAudio(core, audioBlob, filename = "recording.webm") {
|
|
|
6620
6764
|
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
6621
6765
|
const existingConfig = useCopilotChatConfiguration();
|
|
6622
6766
|
const resolvedAgentId = agentId ?? existingConfig?.agentId ?? DEFAULT_AGENT_ID;
|
|
6623
|
-
const
|
|
6767
|
+
const providedThreadId = threadId ?? existingConfig?.threadId;
|
|
6768
|
+
const resolvedThreadId = useMemo(() => providedThreadId ?? randomUUID(), [providedThreadId]);
|
|
6624
6769
|
const { agent } = useAgent({
|
|
6625
6770
|
agentId: resolvedAgentId,
|
|
6626
6771
|
threadId: resolvedThreadId,
|
|
@@ -6658,7 +6803,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6658
6803
|
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
|
|
6659
6804
|
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
|
|
6660
6805
|
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
|
|
6806
|
+
const [lastConnectedThreadId, setLastConnectedThreadId] = useState(null);
|
|
6807
|
+
const isConnecting = !!providedThreadId && lastConnectedThreadId !== resolvedThreadId;
|
|
6661
6808
|
useEffect(() => {
|
|
6809
|
+
if (!providedThreadId) return;
|
|
6662
6810
|
let detached = false;
|
|
6663
6811
|
const connectAbortController = new AbortController();
|
|
6664
6812
|
if (agent instanceof HttpAgent) agent.abortController = connectAbortController;
|
|
@@ -6668,6 +6816,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6668
6816
|
} catch (error) {
|
|
6669
6817
|
if (detached) return;
|
|
6670
6818
|
console.error("CopilotChat: connectAgent failed", error);
|
|
6819
|
+
} finally {
|
|
6820
|
+
if (!detached) (typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 16))(() => {
|
|
6821
|
+
if (!detached) setLastConnectedThreadId(resolvedThreadId);
|
|
6822
|
+
});
|
|
6671
6823
|
}
|
|
6672
6824
|
};
|
|
6673
6825
|
connect(agent);
|
|
@@ -6679,7 +6831,8 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6679
6831
|
}, [
|
|
6680
6832
|
resolvedThreadId,
|
|
6681
6833
|
agent,
|
|
6682
|
-
resolvedAgentId
|
|
6834
|
+
resolvedAgentId,
|
|
6835
|
+
providedThreadId
|
|
6683
6836
|
]);
|
|
6684
6837
|
const onSubmitInput = useCallback(async (value) => {
|
|
6685
6838
|
if (selectedAttachments.some((a) => a.status === "uploading")) {
|
|
@@ -6832,6 +6985,22 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6832
6985
|
const toolCallsKey = "toolCalls" in m && Array.isArray(m.toolCalls) ? m.toolCalls.map((tc) => `${tc.id}:${tc.function?.arguments?.length ?? 0}`).join(";") : "";
|
|
6833
6986
|
return `${m.id}:${m.role}:${contentKey}:${toolCallsKey}`;
|
|
6834
6987
|
}).join(",")]);
|
|
6988
|
+
const lastUserMessageId = useMemo(() => {
|
|
6989
|
+
for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "user") return messages[i].id;
|
|
6990
|
+
return null;
|
|
6991
|
+
}, [messages]);
|
|
6992
|
+
const [sendNonce, setSendNonce] = useState(0);
|
|
6993
|
+
const prevLastUserMessageIdRef = useRef(lastUserMessageId);
|
|
6994
|
+
useEffect(() => {
|
|
6995
|
+
if (lastUserMessageId && lastUserMessageId !== prevLastUserMessageIdRef.current) {
|
|
6996
|
+
setSendNonce((n) => n + 1);
|
|
6997
|
+
prevLastUserMessageIdRef.current = lastUserMessageId;
|
|
6998
|
+
}
|
|
6999
|
+
}, [lastUserMessageId]);
|
|
7000
|
+
const lastUserMessageState = useMemo(() => ({
|
|
7001
|
+
id: lastUserMessageId,
|
|
7002
|
+
sendNonce
|
|
7003
|
+
}), [lastUserMessageId, sendNonce]);
|
|
6835
7004
|
const RenderedChatView = renderSlot(chatView, CopilotChatView, {
|
|
6836
7005
|
...mergedProps,
|
|
6837
7006
|
messages,
|
|
@@ -6850,7 +7019,9 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6850
7019
|
dragOver,
|
|
6851
7020
|
onDragOver: handleDragOver,
|
|
6852
7021
|
onDragLeave: handleDragLeave,
|
|
6853
|
-
onDrop: handleDrop
|
|
7022
|
+
onDrop: handleDrop,
|
|
7023
|
+
isConnecting,
|
|
7024
|
+
hasExplicitThreadId: !!providedThreadId
|
|
6854
7025
|
});
|
|
6855
7026
|
return /* @__PURE__ */ jsx(CopilotChatConfigurationProvider, {
|
|
6856
7027
|
agentId: resolvedAgentId,
|
|
@@ -6885,7 +7056,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6885
7056
|
},
|
|
6886
7057
|
children: transcriptionError
|
|
6887
7058
|
}),
|
|
6888
|
-
|
|
7059
|
+
/* @__PURE__ */ jsx(LastUserMessageContext.Provider, {
|
|
7060
|
+
value: lastUserMessageState,
|
|
7061
|
+
children: RenderedChatView
|
|
7062
|
+
})
|
|
6889
7063
|
]
|
|
6890
7064
|
})
|
|
6891
7065
|
});
|
|
@@ -9568,4 +9742,4 @@ function validateProps(props) {
|
|
|
9568
9742
|
|
|
9569
9743
|
//#endregion
|
|
9570
9744
|
export { CopilotKitProvider as $, CopilotChatSuggestionView as A, useConfigureSuggestions as B, CopilotChatToggleButton as C, CopilotChatView_default as D, CopilotChat as E, CopilotChatAssistantMessage_default as F, useRenderTool as G, useCapabilities as H, CopilotChatToolCallsView as I, useRenderActivityMessage as J, useComponent as K, useAttachments as L, CopilotChatReasoningMessage_default as M, CopilotChatUserMessage_default as N, CopilotChatAttachmentQueue as O, CopilotChatAttachmentRenderer as P, useRenderToolCall as Q, useThreads$1 as R, CopilotModalHeader as S, DefaultOpenIcon as T, useHumanInTheLoop as U, useSuggestions as V, useDefaultRenderTool as W, UseAgentUpdate as X, useRenderCustomMessages as Y, useAgent as Z, WildcardToolCallRender as _, ThreadsProvider as a, SandboxFunctionsContext as at, CopilotPopupView as b, CoAgentStateRendersProvider as c, MCPAppsActivityRenderer as ct, shouldShowDevConsole as d, CopilotChatInput_default as dt, useCopilotKit as et, useToast as f, AudioRecorderError as ft, useCopilotContext as g, CopilotContext as h, useCopilotChatConfiguration as ht, ThreadsContext as i, createA2UIMessageRenderer as it, CopilotChatSuggestionPill as j, CopilotChatMessageView as k, useCoAgentStateRenders as l, MCPAppsActivityType as lt, useCopilotMessagesContext as m, CopilotChatConfigurationProvider as mt, defaultCopilotContextCategories as n, useAgentContext as nt, useThreads as o, useSandboxFunctions as ot, CopilotMessagesContext as p, CopilotChatAudioRecorder as pt, useFrontendTool as q, CoAgentStateRenderBridge as r, defineToolCallRenderer as rt, CoAgentStateRendersContext as s, MCPAppsActivityContentSchema as st, CopilotKit as t, CopilotKitCoreReact as tt, useAsyncCallback as u, CopilotKitInspector as ut, CopilotPopup as v, DefaultCloseIcon as w, CopilotSidebarView as x, CopilotSidebar as y, useInterrupt as z };
|
|
9571
|
-
//# sourceMappingURL=copilotkit-
|
|
9745
|
+
//# sourceMappingURL=copilotkit-BBYbekCa.mjs.map
|