@copilotkit/react-core 1.56.2 → 1.56.4
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-Bd0m5HFp.mjs} +266 -81
- package/dist/copilotkit-Bd0m5HFp.mjs.map +1 -0
- package/dist/{copilotkit-CCbxm6JM.d.mts → copilotkit-DFaI4j2r.d.mts} +64 -18
- package/dist/copilotkit-DFaI4j2r.d.mts.map +1 -0
- package/dist/{copilotkit-BtP7w7cT.d.cts → copilotkit-Dg4r4Gi_.d.cts} +64 -18
- package/dist/copilotkit-Dg4r4Gi_.d.cts.map +1 -0
- package/dist/{copilotkit-CSJw5BG8.cjs → copilotkit-tb4zqaMK.cjs} +265 -80
- package/dist/copilotkit-tb4zqaMK.cjs.map +1 -0
- package/dist/index.cjs +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.mts +2 -1
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/index.umd.js +31 -44
- 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 +264 -83
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +6 -6
- package/src/components/copilot-provider/__tests__/v1-explicit-threadid-bridge.test.tsx +107 -0
- package/src/components/copilot-provider/copilotkit.tsx +6 -1
- package/src/context/__tests__/threads-context.test.tsx +116 -3
- package/src/context/threads-context.tsx +18 -1
- package/src/v2/components/chat/CopilotChat.tsx +91 -4
- package/src/v2/components/chat/CopilotChatAttachmentQueue.tsx +4 -1
- package/src/v2/components/chat/CopilotChatInput.tsx +22 -0
- package/src/v2/components/chat/CopilotChatView.tsx +207 -44
- package/src/v2/components/chat/__tests__/CopilotChat.absentThreadConnect.test.tsx +66 -0
- package/src/v2/components/chat/__tests__/CopilotChat.welcomeGate.test.tsx +186 -0
- package/src/v2/components/chat/__tests__/CopilotChatActivityRendering.e2e.test.tsx +438 -4
- package/src/v2/components/chat/__tests__/CopilotChatView.connectingGate.test.tsx +56 -0
- package/src/v2/components/chat/__tests__/CopilotChatView.inputOverlay.test.tsx +172 -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/CopilotChatConfigurationProvider.tsx +29 -1
- package/src/v2/providers/CopilotKitProvider.tsx +2 -11
- package/src/v2/providers/__tests__/CopilotChatConfigurationProvider.test.tsx +106 -0
- 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
|
|
@@ -145,7 +145,7 @@ const CopilotChatDefaultLabels = {
|
|
|
145
145
|
welcomeMessageText: "How can I help you today?"
|
|
146
146
|
};
|
|
147
147
|
const CopilotChatConfiguration = createContext(null);
|
|
148
|
-
const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, isModalDefaultOpen }) => {
|
|
148
|
+
const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, hasExplicitThreadId, isModalDefaultOpen }) => {
|
|
149
149
|
const parentConfig = useContext(CopilotChatConfiguration);
|
|
150
150
|
const stableLabels = useShallowStableRef(labels);
|
|
151
151
|
const mergedLabels = useMemo(() => ({
|
|
@@ -159,6 +159,7 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
|
|
|
159
159
|
if (parentConfig?.threadId) return parentConfig.threadId;
|
|
160
160
|
return randomUUID();
|
|
161
161
|
}, [threadId, parentConfig?.threadId]);
|
|
162
|
+
const resolvedHasExplicitThreadId = (hasExplicitThreadId !== void 0 ? hasExplicitThreadId : !!threadId) || !!parentConfig?.hasExplicitThreadId;
|
|
162
163
|
const [internalModalOpen, setInternalModalOpen] = useState(isModalDefaultOpen ?? true);
|
|
163
164
|
const hasExplicitDefault = isModalDefaultOpen !== void 0;
|
|
164
165
|
const setAndSync = useCallback((open) => {
|
|
@@ -181,12 +182,14 @@ const CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId,
|
|
|
181
182
|
labels: mergedLabels,
|
|
182
183
|
agentId: resolvedAgentId,
|
|
183
184
|
threadId: resolvedThreadId,
|
|
185
|
+
hasExplicitThreadId: resolvedHasExplicitThreadId,
|
|
184
186
|
isModalOpen: resolvedIsModalOpen,
|
|
185
187
|
setModalOpen: resolvedSetModalOpen
|
|
186
188
|
}), [
|
|
187
189
|
mergedLabels,
|
|
188
190
|
resolvedAgentId,
|
|
189
191
|
resolvedThreadId,
|
|
192
|
+
resolvedHasExplicitThreadId,
|
|
190
193
|
resolvedIsModalOpen,
|
|
191
194
|
resolvedSetModalOpen
|
|
192
195
|
]);
|
|
@@ -580,7 +583,7 @@ CopilotChatAudioRecorder.displayName = "CopilotChatAudioRecorder";
|
|
|
580
583
|
//#region src/v2/components/chat/CopilotChatInput.tsx
|
|
581
584
|
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
582
585
|
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 }) {
|
|
586
|
+
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
587
|
const isControlled = value !== void 0;
|
|
585
588
|
const [internalValue, setInternalValue] = useState(() => value ?? "");
|
|
586
589
|
useEffect(() => {
|
|
@@ -1104,7 +1107,8 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1104
1107
|
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
1108
|
style: {
|
|
1106
1109
|
transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0,
|
|
1107
|
-
transition: "transform 0.2s ease-out"
|
|
1110
|
+
transition: "transform 0.2s ease-out",
|
|
1111
|
+
...positioning === "absolute" || bottomAnchored ? { paddingBottom: "var(--copilotkit-license-banner-offset, 0px)" } : {}
|
|
1108
1112
|
},
|
|
1109
1113
|
...props,
|
|
1110
1114
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -1319,6 +1323,8 @@ CopilotKitInspector.displayName = "CopilotKitInspector";
|
|
|
1319
1323
|
|
|
1320
1324
|
//#endregion
|
|
1321
1325
|
//#region src/v2/components/license-warning-banner.tsx
|
|
1326
|
+
const LICENSE_BANNER_OFFSET_PX = 52;
|
|
1327
|
+
const LICENSE_BANNER_OFFSET_VAR = "--copilotkit-license-banner-offset";
|
|
1322
1328
|
const BANNER_STYLES = {
|
|
1323
1329
|
base: {
|
|
1324
1330
|
position: "fixed",
|
|
@@ -1360,6 +1366,14 @@ function getSeverityStyle(severity) {
|
|
|
1360
1366
|
}
|
|
1361
1367
|
}
|
|
1362
1368
|
function BannerShell({ severity, message, actionLabel, actionUrl, onDismiss }) {
|
|
1369
|
+
useEffect(() => {
|
|
1370
|
+
if (typeof document === "undefined") return;
|
|
1371
|
+
const root = document.documentElement;
|
|
1372
|
+
root.style.setProperty(LICENSE_BANNER_OFFSET_VAR, `${LICENSE_BANNER_OFFSET_PX}px`);
|
|
1373
|
+
return () => {
|
|
1374
|
+
root.style.removeProperty(LICENSE_BANNER_OFFSET_VAR);
|
|
1375
|
+
};
|
|
1376
|
+
}, []);
|
|
1363
1377
|
return /* @__PURE__ */ jsxs("div", {
|
|
1364
1378
|
style: {
|
|
1365
1379
|
...BANNER_STYLES.base,
|
|
@@ -3312,7 +3326,6 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
|
|
|
3312
3326
|
didMountRef.current = true;
|
|
3313
3327
|
}, []);
|
|
3314
3328
|
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
3329
|
copilotkit.setDefaultThrottleMs(defaultThrottleMs);
|
|
3317
3330
|
}, [copilotkit, defaultThrottleMs]);
|
|
3318
3331
|
const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
|
|
@@ -3529,15 +3542,6 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3529
3542
|
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
3530
3543
|
const chatConfig = useCopilotChatConfiguration();
|
|
3531
3544
|
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
3545
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
3542
3546
|
const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
|
|
3543
3547
|
const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
|
|
@@ -3600,9 +3604,8 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3600
3604
|
]);
|
|
3601
3605
|
useEffect(() => {
|
|
3602
3606
|
if (updateFlags.length === 0) return;
|
|
3603
|
-
const handlers = {};
|
|
3604
|
-
let timerId = null;
|
|
3605
3607
|
let active = true;
|
|
3608
|
+
const handlers = {};
|
|
3606
3609
|
let batchScheduled = false;
|
|
3607
3610
|
const batchedForceUpdate = () => {
|
|
3608
3611
|
if (!active) return;
|
|
@@ -3614,46 +3617,24 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3614
3617
|
});
|
|
3615
3618
|
}
|
|
3616
3619
|
};
|
|
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
|
-
}
|
|
3620
|
+
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
|
|
3641
3621
|
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
|
|
3642
3622
|
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
3643
3623
|
handlers.onRunInitialized = batchedForceUpdate;
|
|
3644
3624
|
handlers.onRunFinalized = batchedForceUpdate;
|
|
3645
3625
|
handlers.onRunFailed = batchedForceUpdate;
|
|
3626
|
+
handlers.onRunErrorEvent = batchedForceUpdate;
|
|
3646
3627
|
}
|
|
3647
|
-
const subscription =
|
|
3628
|
+
const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
|
|
3648
3629
|
return () => {
|
|
3649
3630
|
active = false;
|
|
3650
|
-
if (timerId !== null) clearTimeout(timerId);
|
|
3651
3631
|
subscription.unsubscribe();
|
|
3652
3632
|
};
|
|
3653
3633
|
}, [
|
|
3654
3634
|
agent,
|
|
3655
3635
|
forceUpdate,
|
|
3656
|
-
|
|
3636
|
+
throttleMs,
|
|
3637
|
+
providerThrottleMs,
|
|
3657
3638
|
updateFlags
|
|
3658
3639
|
]);
|
|
3659
3640
|
useEffect(() => {
|
|
@@ -4607,13 +4588,14 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4607
4588
|
const { copilotkit } = useCopilotKit();
|
|
4608
4589
|
const [store] = useState(() => ɵcreateThreadStore({ fetch: globalThis.fetch }));
|
|
4609
4590
|
const coreThreads = useThreadStoreSelector(store, ɵselectThreads);
|
|
4610
|
-
const threads = useMemo(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt }) => ({
|
|
4591
|
+
const threads = useMemo(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt, lastRunAt }) => ({
|
|
4611
4592
|
id,
|
|
4612
4593
|
agentId,
|
|
4613
4594
|
name,
|
|
4614
4595
|
archived,
|
|
4615
4596
|
createdAt,
|
|
4616
|
-
updatedAt
|
|
4597
|
+
updatedAt,
|
|
4598
|
+
...lastRunAt !== void 0 ? { lastRunAt } : {}
|
|
4617
4599
|
})), [coreThreads]);
|
|
4618
4600
|
const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);
|
|
4619
4601
|
const storeError = useThreadStoreSelector(store, ɵselectThreadsError);
|
|
@@ -4626,7 +4608,9 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4626
4608
|
if (copilotkit.runtimeUrl) return null;
|
|
4627
4609
|
return /* @__PURE__ */ new Error("Runtime URL is not configured");
|
|
4628
4610
|
}, [copilotkit.runtimeUrl]);
|
|
4629
|
-
const
|
|
4611
|
+
const [hasDispatchedContext, setHasDispatchedContext] = useState(false);
|
|
4612
|
+
const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
|
|
4613
|
+
const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
|
|
4630
4614
|
const error = runtimeError ?? storeError;
|
|
4631
4615
|
useEffect(() => {
|
|
4632
4616
|
store.start();
|
|
@@ -4634,19 +4618,27 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4634
4618
|
store.stop();
|
|
4635
4619
|
};
|
|
4636
4620
|
}, [store]);
|
|
4621
|
+
const runtimeStatus = copilotkit.runtimeConnectionStatus;
|
|
4637
4622
|
useEffect(() => {
|
|
4638
|
-
|
|
4623
|
+
if (!copilotkit.runtimeUrl) {
|
|
4624
|
+
store.setContext(null);
|
|
4625
|
+
return;
|
|
4626
|
+
}
|
|
4627
|
+
if (runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) return;
|
|
4628
|
+
const context = {
|
|
4639
4629
|
runtimeUrl: copilotkit.runtimeUrl,
|
|
4640
4630
|
headers: { ...copilotkit.headers },
|
|
4641
4631
|
wsUrl: copilotkit.intelligence?.wsUrl,
|
|
4642
4632
|
agentId,
|
|
4643
4633
|
includeArchived,
|
|
4644
4634
|
limit
|
|
4645
|
-
}
|
|
4635
|
+
};
|
|
4646
4636
|
store.setContext(context);
|
|
4637
|
+
setHasDispatchedContext(true);
|
|
4647
4638
|
}, [
|
|
4648
4639
|
store,
|
|
4649
4640
|
copilotkit.runtimeUrl,
|
|
4641
|
+
runtimeStatus,
|
|
4650
4642
|
headersKey,
|
|
4651
4643
|
copilotkit.intelligence?.wsUrl,
|
|
4652
4644
|
agentId,
|
|
@@ -5829,6 +5821,7 @@ CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
|
|
|
5829
5821
|
const CopilotChatAttachmentQueue = ({ attachments, onRemoveAttachment, className }) => {
|
|
5830
5822
|
if (attachments.length === 0) return null;
|
|
5831
5823
|
return /* @__PURE__ */ jsx("div", {
|
|
5824
|
+
"data-testid": "copilot-attachment-queue",
|
|
5832
5825
|
className: cn("cpk:flex cpk:flex-wrap cpk:gap-2 cpk:p-2", className),
|
|
5833
5826
|
children: attachments.map((attachment) => {
|
|
5834
5827
|
const isMedia = attachment.type === "image" || attachment.type === "video";
|
|
@@ -6171,9 +6164,91 @@ function useKeyboardHeight() {
|
|
|
6171
6164
|
return keyboardState;
|
|
6172
6165
|
}
|
|
6173
6166
|
|
|
6167
|
+
//#endregion
|
|
6168
|
+
//#region src/v2/components/chat/normalize-auto-scroll.ts
|
|
6169
|
+
const VALID = [
|
|
6170
|
+
"pin-to-bottom",
|
|
6171
|
+
"pin-to-send",
|
|
6172
|
+
"none"
|
|
6173
|
+
];
|
|
6174
|
+
function normalizeAutoScroll(value) {
|
|
6175
|
+
if (value === void 0) return "pin-to-bottom";
|
|
6176
|
+
if (value === true) return "pin-to-bottom";
|
|
6177
|
+
if (value === false) return "none";
|
|
6178
|
+
if (VALID.includes(value)) return value;
|
|
6179
|
+
return "pin-to-bottom";
|
|
6180
|
+
}
|
|
6181
|
+
|
|
6182
|
+
//#endregion
|
|
6183
|
+
//#region src/v2/components/chat/last-user-message-context.ts
|
|
6184
|
+
const LastUserMessageContext = React.createContext({
|
|
6185
|
+
id: null,
|
|
6186
|
+
sendNonce: 0
|
|
6187
|
+
});
|
|
6188
|
+
|
|
6189
|
+
//#endregion
|
|
6190
|
+
//#region src/v2/hooks/use-pin-to-send.ts
|
|
6191
|
+
function usePinToSend({ scrollRef, contentRef, spacerRef, topOffset = 16 }) {
|
|
6192
|
+
const { id, sendNonce } = useContext(LastUserMessageContext);
|
|
6193
|
+
const lastNonceRef = useRef(-1);
|
|
6194
|
+
const currentSpacerHeightRef = useRef(0);
|
|
6195
|
+
useEffect(() => {
|
|
6196
|
+
if (sendNonce === lastNonceRef.current) return;
|
|
6197
|
+
lastNonceRef.current = sendNonce;
|
|
6198
|
+
if (!id) return;
|
|
6199
|
+
const scrollEl = scrollRef.current;
|
|
6200
|
+
const contentEl = contentRef.current;
|
|
6201
|
+
const spacerEl = spacerRef.current;
|
|
6202
|
+
if (!scrollEl || !contentEl || !spacerEl) return;
|
|
6203
|
+
const escaped = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(id) : id.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
6204
|
+
const targetEl = contentEl.querySelector(`[data-message-id="${escaped}"]`);
|
|
6205
|
+
if (!targetEl) return;
|
|
6206
|
+
const viewportHeight = scrollEl.clientHeight;
|
|
6207
|
+
const userMessageHeight = targetEl.getBoundingClientRect().height;
|
|
6208
|
+
const paddingTop = parseFloat(getComputedStyle(targetEl).paddingTop) || 0;
|
|
6209
|
+
const bubbleHeight = Math.max(0, userMessageHeight - paddingTop);
|
|
6210
|
+
const spacerHeight = Math.max(0, viewportHeight - bubbleHeight - topOffset);
|
|
6211
|
+
spacerEl.style.height = `${spacerHeight}px`;
|
|
6212
|
+
currentSpacerHeightRef.current = spacerHeight;
|
|
6213
|
+
const raf = requestAnimationFrame(() => {
|
|
6214
|
+
const targetTop = computeOffsetTop(targetEl, scrollEl) + paddingTop - topOffset;
|
|
6215
|
+
scrollEl.scrollTo({
|
|
6216
|
+
top: Math.max(0, targetTop),
|
|
6217
|
+
behavior: "smooth"
|
|
6218
|
+
});
|
|
6219
|
+
});
|
|
6220
|
+
const ro = new ResizeObserver(() => {
|
|
6221
|
+
if (!contentEl || !spacerEl || !scrollEl) return;
|
|
6222
|
+
const consumedBelow = contentEl.getBoundingClientRect().height - computeOffsetTop(targetEl, contentEl) - userMessageHeight;
|
|
6223
|
+
const remaining = Math.max(0, spacerHeight - consumedBelow);
|
|
6224
|
+
if (remaining < currentSpacerHeightRef.current) {
|
|
6225
|
+
spacerEl.style.height = `${remaining}px`;
|
|
6226
|
+
currentSpacerHeightRef.current = remaining;
|
|
6227
|
+
}
|
|
6228
|
+
});
|
|
6229
|
+
ro.observe(contentEl);
|
|
6230
|
+
return () => {
|
|
6231
|
+
cancelAnimationFrame(raf);
|
|
6232
|
+
ro.disconnect();
|
|
6233
|
+
};
|
|
6234
|
+
}, [
|
|
6235
|
+
id,
|
|
6236
|
+
sendNonce,
|
|
6237
|
+
scrollRef,
|
|
6238
|
+
contentRef,
|
|
6239
|
+
spacerRef,
|
|
6240
|
+
topOffset
|
|
6241
|
+
]);
|
|
6242
|
+
}
|
|
6243
|
+
function computeOffsetTop(el, stopAt) {
|
|
6244
|
+
const elRect = el.getBoundingClientRect();
|
|
6245
|
+
const stopRect = stopAt.getBoundingClientRect();
|
|
6246
|
+
return elRect.top - stopRect.top + stopAt.scrollTop;
|
|
6247
|
+
}
|
|
6248
|
+
|
|
6174
6249
|
//#endregion
|
|
6175
6250
|
//#region src/v2/components/chat/CopilotChatView.tsx
|
|
6176
|
-
const
|
|
6251
|
+
const SCROLL_BUTTON_OFFSET = 16;
|
|
6177
6252
|
function DropOverlay() {
|
|
6178
6253
|
return /* @__PURE__ */ jsx("div", {
|
|
6179
6254
|
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 +6261,7 @@ function DropOverlay() {
|
|
|
6186
6261
|
})
|
|
6187
6262
|
});
|
|
6188
6263
|
}
|
|
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 }) {
|
|
6264
|
+
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
6265
|
const inputContainerRef = useRef(null);
|
|
6191
6266
|
const [inputContainerHeight, setInputContainerHeight] = useState(0);
|
|
6192
6267
|
const [isResizing, setIsResizing] = useState(false);
|
|
@@ -6236,11 +6311,11 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6236
6311
|
onAddFile,
|
|
6237
6312
|
positioning: "static",
|
|
6238
6313
|
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
6239
|
-
containerRef: inputContainerRef,
|
|
6240
6314
|
showDisclaimer: true,
|
|
6315
|
+
bottomAnchored: true,
|
|
6241
6316
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
6242
6317
|
});
|
|
6243
|
-
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
|
|
6318
|
+
const hasSuggestions = !isConnecting && !isRunning && Array.isArray(suggestions) && suggestions.length > 0;
|
|
6244
6319
|
const BoundSuggestionView = hasSuggestions ? renderSlot(suggestionView, CopilotChatSuggestionView, {
|
|
6245
6320
|
suggestions,
|
|
6246
6321
|
loadingIndexes: suggestionLoadingIndexes,
|
|
@@ -6252,7 +6327,8 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6252
6327
|
inputContainerHeight,
|
|
6253
6328
|
isResizing,
|
|
6254
6329
|
children: /* @__PURE__ */ jsx("div", {
|
|
6255
|
-
|
|
6330
|
+
"data-testid": "copilot-scroll-content",
|
|
6331
|
+
style: { paddingBottom: `${inputContainerHeight + (hasSuggestions ? 4 : 32)}px` },
|
|
6256
6332
|
children: /* @__PURE__ */ jsxs("div", {
|
|
6257
6333
|
className: "cpk:max-w-3xl cpk:mx-auto",
|
|
6258
6334
|
children: [BoundMessageView, hasSuggestions ? /* @__PURE__ */ jsx("div", {
|
|
@@ -6262,7 +6338,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6262
6338
|
})
|
|
6263
6339
|
})
|
|
6264
6340
|
});
|
|
6265
|
-
if (messages.length === 0 && !(welcomeScreen === false)) {
|
|
6341
|
+
if (messages.length === 0 && !(welcomeScreen === false) && !isConnecting && !hasExplicitThreadId) {
|
|
6266
6342
|
const BoundInputForWelcome = renderSlot(input, CopilotChatInput_default, {
|
|
6267
6343
|
onSubmitMessage,
|
|
6268
6344
|
onStop,
|
|
@@ -6326,15 +6402,19 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6326
6402
|
children: [
|
|
6327
6403
|
dragOver && /* @__PURE__ */ jsx(DropOverlay, {}),
|
|
6328
6404
|
BoundScrollView,
|
|
6329
|
-
/* @__PURE__ */
|
|
6330
|
-
|
|
6331
|
-
|
|
6332
|
-
|
|
6333
|
-
|
|
6334
|
-
className: "cpk:
|
|
6335
|
-
|
|
6336
|
-
|
|
6337
|
-
|
|
6405
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6406
|
+
ref: inputContainerRef,
|
|
6407
|
+
"data-testid": "copilot-input-overlay",
|
|
6408
|
+
className: "cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-0 cpk:z-20 cpk:pointer-events-none",
|
|
6409
|
+
children: [attachments && attachments.length > 0 && /* @__PURE__ */ jsx("div", {
|
|
6410
|
+
className: "cpk:max-w-3xl cpk:mx-auto cpk:w-full cpk:pointer-events-auto",
|
|
6411
|
+
children: /* @__PURE__ */ jsx(CopilotChatAttachmentQueue, {
|
|
6412
|
+
attachments,
|
|
6413
|
+
onRemoveAttachment: (id) => onRemoveAttachment?.(id),
|
|
6414
|
+
className: "cpk:px-4"
|
|
6415
|
+
})
|
|
6416
|
+
}), BoundInput]
|
|
6417
|
+
})
|
|
6338
6418
|
]
|
|
6339
6419
|
});
|
|
6340
6420
|
}
|
|
@@ -6363,15 +6443,66 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6363
6443
|
BoundFeather,
|
|
6364
6444
|
!isAtBottom && !isResizing && /* @__PURE__ */ jsx("div", {
|
|
6365
6445
|
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6366
|
-
style: { bottom: `${inputContainerHeight +
|
|
6446
|
+
style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
|
|
6367
6447
|
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
6368
6448
|
})
|
|
6369
6449
|
] })
|
|
6370
6450
|
});
|
|
6371
6451
|
};
|
|
6372
|
-
|
|
6452
|
+
const PinToSendScrollContainer = ({ children, scrollRef, contentRef, scrollToBottom, scrollToBottomButton, feather, inputContainerHeight, isResizing, nonAutoScrollEl, nonAutoScrollRefCallback, showScrollButton, className, ...props }) => {
|
|
6453
|
+
const spacerRef = useRef(null);
|
|
6454
|
+
usePinToSend({
|
|
6455
|
+
scrollRef,
|
|
6456
|
+
contentRef,
|
|
6457
|
+
spacerRef,
|
|
6458
|
+
topOffset: 16
|
|
6459
|
+
});
|
|
6460
|
+
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
6461
|
+
return /* @__PURE__ */ jsx(ScrollElementContext.Provider, {
|
|
6462
|
+
value: nonAutoScrollEl,
|
|
6463
|
+
children: /* @__PURE__ */ jsxs("div", {
|
|
6464
|
+
className: cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative", className),
|
|
6465
|
+
children: [
|
|
6466
|
+
/* @__PURE__ */ jsxs("div", {
|
|
6467
|
+
ref: nonAutoScrollRefCallback,
|
|
6468
|
+
className: "cpk:flex-1 cpk:min-h-0 cpk:overflow-y-auto cpk:overflow-x-hidden",
|
|
6469
|
+
...props,
|
|
6470
|
+
children: [/* @__PURE__ */ jsx("div", {
|
|
6471
|
+
ref: contentRef,
|
|
6472
|
+
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
6473
|
+
children
|
|
6474
|
+
}), /* @__PURE__ */ jsx("div", {
|
|
6475
|
+
ref: spacerRef,
|
|
6476
|
+
"data-pin-to-send-spacer": true,
|
|
6477
|
+
"aria-hidden": "true",
|
|
6478
|
+
style: {
|
|
6479
|
+
height: 0,
|
|
6480
|
+
flex: "0 0 auto"
|
|
6481
|
+
}
|
|
6482
|
+
})]
|
|
6483
|
+
}),
|
|
6484
|
+
BoundFeather,
|
|
6485
|
+
showScrollButton && !isResizing && /* @__PURE__ */ jsx("div", {
|
|
6486
|
+
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6487
|
+
style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
|
|
6488
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
6489
|
+
})
|
|
6490
|
+
]
|
|
6491
|
+
})
|
|
6492
|
+
});
|
|
6493
|
+
};
|
|
6494
|
+
_CopilotChatView.ScrollView = ({ children, autoScroll = "pin-to-bottom", scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
6495
|
+
const mode = normalizeAutoScroll(autoScroll);
|
|
6373
6496
|
const [hasMounted, setHasMounted] = useState(false);
|
|
6374
|
-
const
|
|
6497
|
+
const scrollRef = useRef(null);
|
|
6498
|
+
const contentRef = useRef(null);
|
|
6499
|
+
const scrollToBottom = useCallback(() => {
|
|
6500
|
+
const el = scrollRef.current;
|
|
6501
|
+
if (el) el.scrollTo({
|
|
6502
|
+
top: el.scrollHeight,
|
|
6503
|
+
behavior: "smooth"
|
|
6504
|
+
});
|
|
6505
|
+
}, []);
|
|
6375
6506
|
const [showScrollButton, setShowScrollButton] = useState(false);
|
|
6376
6507
|
const [nonAutoScrollEl, setNonAutoScrollEl] = useState(null);
|
|
6377
6508
|
const nonAutoScrollRefCallback = useCallback((el) => {
|
|
@@ -6382,7 +6513,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6382
6513
|
setHasMounted(true);
|
|
6383
6514
|
}, []);
|
|
6384
6515
|
useEffect(() => {
|
|
6385
|
-
if (
|
|
6516
|
+
if (mode === "pin-to-bottom") return;
|
|
6386
6517
|
const scrollElement = scrollRef.current;
|
|
6387
6518
|
if (!scrollElement) return;
|
|
6388
6519
|
const checkScroll = () => {
|
|
@@ -6396,7 +6527,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6396
6527
|
scrollElement.removeEventListener("scroll", checkScroll);
|
|
6397
6528
|
resizeObserver.disconnect();
|
|
6398
6529
|
};
|
|
6399
|
-
}, [scrollRef,
|
|
6530
|
+
}, [scrollRef, mode]);
|
|
6400
6531
|
if (!hasMounted) return /* @__PURE__ */ jsx("div", {
|
|
6401
6532
|
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
6533
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -6404,7 +6535,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6404
6535
|
children
|
|
6405
6536
|
})
|
|
6406
6537
|
});
|
|
6407
|
-
if (
|
|
6538
|
+
if (mode === "none") {
|
|
6408
6539
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
6409
6540
|
return /* @__PURE__ */ jsx(ScrollElementContext.Provider, {
|
|
6410
6541
|
value: nonAutoScrollEl,
|
|
@@ -6421,13 +6552,28 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6421
6552
|
BoundFeather,
|
|
6422
6553
|
showScrollButton && !isResizing && /* @__PURE__ */ jsx("div", {
|
|
6423
6554
|
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6424
|
-
style: { bottom: `${inputContainerHeight +
|
|
6555
|
+
style: { bottom: `${inputContainerHeight + SCROLL_BUTTON_OFFSET}px` },
|
|
6425
6556
|
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
6426
6557
|
})
|
|
6427
6558
|
]
|
|
6428
6559
|
})
|
|
6429
6560
|
});
|
|
6430
6561
|
}
|
|
6562
|
+
if (mode === "pin-to-send") return /* @__PURE__ */ jsx(PinToSendScrollContainer, {
|
|
6563
|
+
scrollRef,
|
|
6564
|
+
contentRef,
|
|
6565
|
+
scrollToBottom,
|
|
6566
|
+
scrollToBottomButton,
|
|
6567
|
+
feather,
|
|
6568
|
+
inputContainerHeight,
|
|
6569
|
+
isResizing,
|
|
6570
|
+
nonAutoScrollEl,
|
|
6571
|
+
nonAutoScrollRefCallback,
|
|
6572
|
+
showScrollButton,
|
|
6573
|
+
className,
|
|
6574
|
+
...props,
|
|
6575
|
+
children
|
|
6576
|
+
});
|
|
6431
6577
|
return /* @__PURE__ */ jsx(StickToBottom, {
|
|
6432
6578
|
className: cn("cpk:flex-1 cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0", className),
|
|
6433
6579
|
resize: "smooth",
|
|
@@ -6450,9 +6596,8 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6450
6596
|
...props,
|
|
6451
6597
|
children: /* @__PURE__ */ jsx(ChevronDown, { className: "cpk:w-4 cpk:h-4 cpk:text-gray-600 cpk:dark:text-white" })
|
|
6452
6598
|
});
|
|
6453
|
-
_CopilotChatView.Feather = ({ className,
|
|
6454
|
-
className
|
|
6455
|
-
style,
|
|
6599
|
+
_CopilotChatView.Feather = ({ className, ...props }) => /* @__PURE__ */ jsx("div", {
|
|
6600
|
+
className,
|
|
6456
6601
|
...props
|
|
6457
6602
|
});
|
|
6458
6603
|
_CopilotChatView.WelcomeMessage = ({ className, ...props }) => {
|
|
@@ -6620,7 +6765,9 @@ async function transcribeAudio(core, audioBlob, filename = "recording.webm") {
|
|
|
6620
6765
|
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
6621
6766
|
const existingConfig = useCopilotChatConfiguration();
|
|
6622
6767
|
const resolvedAgentId = agentId ?? existingConfig?.agentId ?? DEFAULT_AGENT_ID;
|
|
6623
|
-
const
|
|
6768
|
+
const providedThreadId = threadId ?? existingConfig?.threadId;
|
|
6769
|
+
const resolvedThreadId = useMemo(() => providedThreadId ?? randomUUID(), [providedThreadId]);
|
|
6770
|
+
const hasExplicitThreadId = !!threadId || !!existingConfig?.hasExplicitThreadId;
|
|
6624
6771
|
const { agent } = useAgent({
|
|
6625
6772
|
agentId: resolvedAgentId,
|
|
6626
6773
|
threadId: resolvedThreadId,
|
|
@@ -6658,7 +6805,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6658
6805
|
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
|
|
6659
6806
|
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
|
|
6660
6807
|
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
|
|
6808
|
+
const [lastConnectedThreadId, setLastConnectedThreadId] = useState(null);
|
|
6809
|
+
const isConnecting = hasExplicitThreadId && lastConnectedThreadId !== resolvedThreadId;
|
|
6661
6810
|
useEffect(() => {
|
|
6811
|
+
if (!hasExplicitThreadId) return;
|
|
6662
6812
|
let detached = false;
|
|
6663
6813
|
const connectAbortController = new AbortController();
|
|
6664
6814
|
if (agent instanceof HttpAgent) agent.abortController = connectAbortController;
|
|
@@ -6668,6 +6818,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6668
6818
|
} catch (error) {
|
|
6669
6819
|
if (detached) return;
|
|
6670
6820
|
console.error("CopilotChat: connectAgent failed", error);
|
|
6821
|
+
} finally {
|
|
6822
|
+
if (!detached) (typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 16))(() => {
|
|
6823
|
+
if (!detached) setLastConnectedThreadId(resolvedThreadId);
|
|
6824
|
+
});
|
|
6671
6825
|
}
|
|
6672
6826
|
};
|
|
6673
6827
|
connect(agent);
|
|
@@ -6679,7 +6833,8 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6679
6833
|
}, [
|
|
6680
6834
|
resolvedThreadId,
|
|
6681
6835
|
agent,
|
|
6682
|
-
resolvedAgentId
|
|
6836
|
+
resolvedAgentId,
|
|
6837
|
+
hasExplicitThreadId
|
|
6683
6838
|
]);
|
|
6684
6839
|
const onSubmitInput = useCallback(async (value) => {
|
|
6685
6840
|
if (selectedAttachments.some((a) => a.status === "uploading")) {
|
|
@@ -6832,6 +6987,22 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6832
6987
|
const toolCallsKey = "toolCalls" in m && Array.isArray(m.toolCalls) ? m.toolCalls.map((tc) => `${tc.id}:${tc.function?.arguments?.length ?? 0}`).join(";") : "";
|
|
6833
6988
|
return `${m.id}:${m.role}:${contentKey}:${toolCallsKey}`;
|
|
6834
6989
|
}).join(",")]);
|
|
6990
|
+
const lastUserMessageId = useMemo(() => {
|
|
6991
|
+
for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "user") return messages[i].id;
|
|
6992
|
+
return null;
|
|
6993
|
+
}, [messages]);
|
|
6994
|
+
const [sendNonce, setSendNonce] = useState(0);
|
|
6995
|
+
const prevLastUserMessageIdRef = useRef(lastUserMessageId);
|
|
6996
|
+
useEffect(() => {
|
|
6997
|
+
if (lastUserMessageId && lastUserMessageId !== prevLastUserMessageIdRef.current) {
|
|
6998
|
+
setSendNonce((n) => n + 1);
|
|
6999
|
+
prevLastUserMessageIdRef.current = lastUserMessageId;
|
|
7000
|
+
}
|
|
7001
|
+
}, [lastUserMessageId]);
|
|
7002
|
+
const lastUserMessageState = useMemo(() => ({
|
|
7003
|
+
id: lastUserMessageId,
|
|
7004
|
+
sendNonce
|
|
7005
|
+
}), [lastUserMessageId, sendNonce]);
|
|
6835
7006
|
const RenderedChatView = renderSlot(chatView, CopilotChatView, {
|
|
6836
7007
|
...mergedProps,
|
|
6837
7008
|
messages,
|
|
@@ -6850,11 +7021,14 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6850
7021
|
dragOver,
|
|
6851
7022
|
onDragOver: handleDragOver,
|
|
6852
7023
|
onDragLeave: handleDragLeave,
|
|
6853
|
-
onDrop: handleDrop
|
|
7024
|
+
onDrop: handleDrop,
|
|
7025
|
+
isConnecting,
|
|
7026
|
+
hasExplicitThreadId
|
|
6854
7027
|
});
|
|
6855
7028
|
return /* @__PURE__ */ jsx(CopilotChatConfigurationProvider, {
|
|
6856
7029
|
agentId: resolvedAgentId,
|
|
6857
7030
|
threadId: resolvedThreadId,
|
|
7031
|
+
hasExplicitThreadId,
|
|
6858
7032
|
labels,
|
|
6859
7033
|
isModalDefaultOpen,
|
|
6860
7034
|
children: /* @__PURE__ */ jsxs("div", {
|
|
@@ -6885,7 +7059,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6885
7059
|
},
|
|
6886
7060
|
children: transcriptionError
|
|
6887
7061
|
}),
|
|
6888
|
-
|
|
7062
|
+
/* @__PURE__ */ jsx(LastUserMessageContext.Provider, {
|
|
7063
|
+
value: lastUserMessageState,
|
|
7064
|
+
children: RenderedChatView
|
|
7065
|
+
})
|
|
6889
7066
|
]
|
|
6890
7067
|
})
|
|
6891
7068
|
});
|
|
@@ -8611,12 +8788,19 @@ function useCoAgentStateRenders() {
|
|
|
8611
8788
|
//#region src/context/threads-context.tsx
|
|
8612
8789
|
const ThreadsContext = createContext(void 0);
|
|
8613
8790
|
function ThreadsProvider({ children, threadId: explicitThreadId }) {
|
|
8614
|
-
const [internalThreadId,
|
|
8791
|
+
const [internalThreadId, setInternalThreadId] = useState(() => randomUUID());
|
|
8792
|
+
const [internalIsExplicit, setInternalIsExplicit] = useState(false);
|
|
8615
8793
|
const threadId = explicitThreadId ?? internalThreadId;
|
|
8794
|
+
const isThreadIdExplicit = explicitThreadId != null || internalIsExplicit;
|
|
8795
|
+
const setThreadId = useCallback((value) => {
|
|
8796
|
+
setInternalThreadId(value);
|
|
8797
|
+
setInternalIsExplicit(true);
|
|
8798
|
+
}, []);
|
|
8616
8799
|
return /* @__PURE__ */ jsx(ThreadsContext.Provider, {
|
|
8617
8800
|
value: {
|
|
8618
8801
|
threadId,
|
|
8619
|
-
setThreadId
|
|
8802
|
+
setThreadId,
|
|
8803
|
+
isThreadIdExplicit
|
|
8620
8804
|
},
|
|
8621
8805
|
children
|
|
8622
8806
|
});
|
|
@@ -9318,7 +9502,7 @@ function CopilotKitInternal(cpkProps) {
|
|
|
9318
9502
|
if (props.agent) setAgentSession({ agentName: props.agent });
|
|
9319
9503
|
else setAgentSession(null);
|
|
9320
9504
|
}, [props.agent]);
|
|
9321
|
-
const { threadId, setThreadId: setInternalThreadId } = useThreads();
|
|
9505
|
+
const { threadId, setThreadId: setInternalThreadId, isThreadIdExplicit } = useThreads();
|
|
9322
9506
|
const setThreadId = useCallback((value) => {
|
|
9323
9507
|
if (props.threadId) throw new Error("Cannot call setThreadId() when threadId is provided via props.");
|
|
9324
9508
|
setInternalThreadId(value);
|
|
@@ -9518,6 +9702,7 @@ function CopilotKitInternal(cpkProps) {
|
|
|
9518
9702
|
return /* @__PURE__ */ jsx(CopilotChatConfigurationProvider, {
|
|
9519
9703
|
agentId: props.agent ?? "default",
|
|
9520
9704
|
threadId,
|
|
9705
|
+
hasExplicitThreadId: isThreadIdExplicit,
|
|
9521
9706
|
children: /* @__PURE__ */ jsxs(CopilotContext.Provider, {
|
|
9522
9707
|
value: copilotContextValue,
|
|
9523
9708
|
children: [
|
|
@@ -9568,4 +9753,4 @@ function validateProps(props) {
|
|
|
9568
9753
|
|
|
9569
9754
|
//#endregion
|
|
9570
9755
|
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-
|
|
9756
|
+
//# sourceMappingURL=copilotkit-Bd0m5HFp.mjs.map
|