@copilotkit/react-core 1.56.0 → 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-BebqQrYT.mjs → copilotkit-BBYbekCa.mjs} +265 -76
- package/dist/copilotkit-BBYbekCa.mjs.map +1 -0
- package/dist/{copilotkit-Cvb6WpAX.cjs → copilotkit-D5JT2Pu3.cjs} +264 -75
- package/dist/copilotkit-D5JT2Pu3.cjs.map +1 -0
- package/dist/{copilotkit-f2Uq0RwG.d.mts → copilotkit-DArT2Iuw.d.mts} +71 -18
- package/dist/copilotkit-DArT2Iuw.d.mts.map +1 -0
- package/dist/{copilotkit-Dv8zU8_U.d.cts → copilotkit-KEc28l8G.d.cts} +71 -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 +30 -46
- 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 -79
- package/dist/v2/index.umd.js.map +1 -1
- package/package.json +6 -6
- package/src/components/CopilotListeners.tsx +15 -4
- package/src/components/__tests__/CopilotListeners.test.tsx +38 -0
- package/src/v2/components/chat/CopilotChat.tsx +80 -4
- package/src/v2/components/chat/CopilotChatAssistantMessage.tsx +4 -4
- package/src/v2/components/chat/CopilotChatInput.tsx +43 -2
- 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__/CopilotChatAssistantMessage.thumbs.test.tsx +72 -0
- package/src/v2/components/chat/__tests__/CopilotChatInput.test.tsx +38 -0
- 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/components/ui/button.tsx +12 -11
- 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-render-custom-messages.test.tsx +55 -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-render-custom-messages.tsx +1 -1
- package/src/v2/hooks/use-render-tool-call.tsx +3 -0
- package/src/v2/hooks/use-render-tool.tsx +3 -0
- package/src/v2/hooks/use-threads.tsx +55 -12
- package/src/v2/providers/CopilotKitProvider.tsx +2 -11
- package/src/v2/types/defineToolCallRenderer.ts +3 -0
- package/src/v2/types/react-tool-call-renderer.ts +3 -0
- package/dist/copilotkit-BebqQrYT.mjs.map +0 -1
- package/dist/copilotkit-Cvb6WpAX.cjs.map +0 -1
- package/dist/copilotkit-Dv8zU8_U.d.cts.map +0 -1
- package/dist/copilotkit-f2Uq0RwG.d.mts.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
|
|
@@ -269,8 +269,9 @@ const buttonVariants = cva("cpk:inline-flex cpk:items-center cpk:justify-center
|
|
|
269
269
|
size: "default"
|
|
270
270
|
}
|
|
271
271
|
});
|
|
272
|
-
function Button({ className, variant, size, asChild = false, ...props }) {
|
|
272
|
+
const Button = React$1.forwardRef(function Button({ className, variant, size, asChild = false, ...props }, ref) {
|
|
273
273
|
return /* @__PURE__ */ jsx(asChild ? Slot : "button", {
|
|
274
|
+
ref,
|
|
274
275
|
"data-slot": "button",
|
|
275
276
|
className: cn(buttonVariants({
|
|
276
277
|
variant,
|
|
@@ -279,7 +280,7 @@ function Button({ className, variant, size, asChild = false, ...props }) {
|
|
|
279
280
|
})),
|
|
280
281
|
...props
|
|
281
282
|
});
|
|
282
|
-
}
|
|
283
|
+
});
|
|
283
284
|
|
|
284
285
|
//#endregion
|
|
285
286
|
//#region src/v2/components/ui/tooltip.tsx
|
|
@@ -579,7 +580,7 @@ CopilotChatAudioRecorder.displayName = "CopilotChatAudioRecorder";
|
|
|
579
580
|
//#region src/v2/components/chat/CopilotChatInput.tsx
|
|
580
581
|
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
581
582
|
const SLASH_MENU_ITEM_HEIGHT_PX = 40;
|
|
582
|
-
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 }) {
|
|
583
584
|
const isControlled = value !== void 0;
|
|
584
585
|
const [internalValue, setInternalValue] = useState(() => value ?? "");
|
|
585
586
|
useEffect(() => {
|
|
@@ -721,6 +722,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
721
722
|
});
|
|
722
723
|
}, [clearInputValue]);
|
|
723
724
|
const handleKeyDown = (e) => {
|
|
725
|
+
if (e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
724
726
|
if (commandQuery !== null && mode === "input") {
|
|
725
727
|
if (e.key === "ArrowDown") {
|
|
726
728
|
if (filteredCommands.length > 0) {
|
|
@@ -768,10 +770,8 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
768
770
|
const trimmed = resolvedValue.trim();
|
|
769
771
|
if (!trimmed) return;
|
|
770
772
|
onSubmitMessage(trimmed);
|
|
771
|
-
if (!isControlled)
|
|
772
|
-
|
|
773
|
-
onChange?.("");
|
|
774
|
-
}
|
|
773
|
+
if (!isControlled) setInternalValue("");
|
|
774
|
+
onChange?.("");
|
|
775
775
|
if (inputRef.current) inputRef.current.focus();
|
|
776
776
|
};
|
|
777
777
|
const BoundTextArea = renderSlot(textArea, CopilotChatInput.TextArea, {
|
|
@@ -779,6 +779,12 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
779
779
|
value: resolvedValue,
|
|
780
780
|
onChange: handleChange,
|
|
781
781
|
onKeyDown: handleKeyDown,
|
|
782
|
+
onCompositionStart: () => {
|
|
783
|
+
isComposingRef.current = true;
|
|
784
|
+
},
|
|
785
|
+
onCompositionEnd: () => {
|
|
786
|
+
isComposingRef.current = false;
|
|
787
|
+
},
|
|
782
788
|
autoFocus,
|
|
783
789
|
className: twMerge("cpk:w-full cpk:py-3", isExpanded ? "cpk:px-5" : "cpk:pr-5")
|
|
784
790
|
});
|
|
@@ -853,9 +859,10 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
853
859
|
const target = e.target;
|
|
854
860
|
if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") inputRef.current.focus();
|
|
855
861
|
};
|
|
862
|
+
const isComposingRef = useRef(false);
|
|
856
863
|
const ensureMeasurements = useCallback(() => {
|
|
857
864
|
const textarea = inputRef.current;
|
|
858
|
-
if (!textarea) return;
|
|
865
|
+
if (!textarea || isComposingRef.current) return;
|
|
859
866
|
const previousValue = textarea.value;
|
|
860
867
|
const previousHeight = textarea.style.height;
|
|
861
868
|
textarea.style.height = "auto";
|
|
@@ -1097,7 +1104,8 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1097
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),
|
|
1098
1105
|
style: {
|
|
1099
1106
|
transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0,
|
|
1100
|
-
transition: "transform 0.2s ease-out"
|
|
1107
|
+
transition: "transform 0.2s ease-out",
|
|
1108
|
+
...positioning === "absolute" || bottomAnchored ? { paddingBottom: "var(--copilotkit-license-banner-offset, 0px)" } : {}
|
|
1101
1109
|
},
|
|
1102
1110
|
...props,
|
|
1103
1111
|
children: [/* @__PURE__ */ jsx("div", {
|
|
@@ -1312,6 +1320,8 @@ CopilotKitInspector.displayName = "CopilotKitInspector";
|
|
|
1312
1320
|
|
|
1313
1321
|
//#endregion
|
|
1314
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";
|
|
1315
1325
|
const BANNER_STYLES = {
|
|
1316
1326
|
base: {
|
|
1317
1327
|
position: "fixed",
|
|
@@ -1353,6 +1363,14 @@ function getSeverityStyle(severity) {
|
|
|
1353
1363
|
}
|
|
1354
1364
|
}
|
|
1355
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
|
+
}, []);
|
|
1356
1374
|
return /* @__PURE__ */ jsxs("div", {
|
|
1357
1375
|
style: {
|
|
1358
1376
|
...BANNER_STYLES.base,
|
|
@@ -3305,7 +3323,6 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
|
|
|
3305
3323
|
didMountRef.current = true;
|
|
3306
3324
|
}, []);
|
|
3307
3325
|
useEffect(() => {
|
|
3308
|
-
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.`);
|
|
3309
3326
|
copilotkit.setDefaultThrottleMs(defaultThrottleMs);
|
|
3310
3327
|
}, [copilotkit, defaultThrottleMs]);
|
|
3311
3328
|
const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
|
|
@@ -3403,18 +3420,21 @@ const ToolCallRenderer = React.memo(function ToolCallRenderer({ toolCall, toolMe
|
|
|
3403
3420
|
const toolName = toolCall.function.name;
|
|
3404
3421
|
if (toolMessage) return /* @__PURE__ */ jsx(RenderComponent, {
|
|
3405
3422
|
name: toolName,
|
|
3423
|
+
toolCallId: toolCall.id,
|
|
3406
3424
|
args,
|
|
3407
3425
|
status: ToolCallStatus.Complete,
|
|
3408
3426
|
result: toolMessage.content
|
|
3409
3427
|
});
|
|
3410
3428
|
else if (isExecuting) return /* @__PURE__ */ jsx(RenderComponent, {
|
|
3411
3429
|
name: toolName,
|
|
3430
|
+
toolCallId: toolCall.id,
|
|
3412
3431
|
args,
|
|
3413
3432
|
status: ToolCallStatus.Executing,
|
|
3414
3433
|
result: void 0
|
|
3415
3434
|
});
|
|
3416
3435
|
else return /* @__PURE__ */ jsx(RenderComponent, {
|
|
3417
3436
|
name: toolName,
|
|
3437
|
+
toolCallId: toolCall.id,
|
|
3418
3438
|
args,
|
|
3419
3439
|
status: ToolCallStatus.InProgress,
|
|
3420
3440
|
result: void 0
|
|
@@ -3519,15 +3539,6 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3519
3539
|
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
3520
3540
|
const chatConfig = useCopilotChatConfiguration();
|
|
3521
3541
|
threadId ??= chatConfig?.threadId;
|
|
3522
|
-
const effectiveThrottleMs = useMemo(() => {
|
|
3523
|
-
const resolved = throttleMs ?? providerThrottleMs ?? 0;
|
|
3524
|
-
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
3525
|
-
const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
|
|
3526
|
-
console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
|
|
3527
|
-
return 0;
|
|
3528
|
-
}
|
|
3529
|
-
return resolved;
|
|
3530
|
-
}, [throttleMs, providerThrottleMs]);
|
|
3531
3542
|
const [, forceUpdate] = useReducer((x) => x + 1, 0);
|
|
3532
3543
|
const updateFlags = useMemo(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
|
|
3533
3544
|
const provisionalAgentCache = useRef(/* @__PURE__ */ new Map());
|
|
@@ -3590,9 +3601,8 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3590
3601
|
]);
|
|
3591
3602
|
useEffect(() => {
|
|
3592
3603
|
if (updateFlags.length === 0) return;
|
|
3593
|
-
const handlers = {};
|
|
3594
|
-
let timerId = null;
|
|
3595
3604
|
let active = true;
|
|
3605
|
+
const handlers = {};
|
|
3596
3606
|
let batchScheduled = false;
|
|
3597
3607
|
const batchedForceUpdate = () => {
|
|
3598
3608
|
if (!active) return;
|
|
@@ -3604,46 +3614,24 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3604
3614
|
});
|
|
3605
3615
|
}
|
|
3606
3616
|
};
|
|
3607
|
-
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged))
|
|
3608
|
-
const ms = effectiveThrottleMs;
|
|
3609
|
-
if (ms > 0) {
|
|
3610
|
-
let throttleActive = false;
|
|
3611
|
-
let pending = false;
|
|
3612
|
-
const throttledNotify = () => {
|
|
3613
|
-
if (!active) return;
|
|
3614
|
-
if (!throttleActive) {
|
|
3615
|
-
throttleActive = true;
|
|
3616
|
-
pending = false;
|
|
3617
|
-
forceUpdate();
|
|
3618
|
-
timerId = setTimeout(function trailingEdge() {
|
|
3619
|
-
timerId = null;
|
|
3620
|
-
if (active && pending) {
|
|
3621
|
-
pending = false;
|
|
3622
|
-
forceUpdate();
|
|
3623
|
-
timerId = setTimeout(trailingEdge, ms);
|
|
3624
|
-
} else throttleActive = false;
|
|
3625
|
-
}, ms);
|
|
3626
|
-
} else pending = true;
|
|
3627
|
-
};
|
|
3628
|
-
handlers.onMessagesChanged = throttledNotify;
|
|
3629
|
-
} else handlers.onMessagesChanged = forceUpdate;
|
|
3630
|
-
}
|
|
3617
|
+
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
|
|
3631
3618
|
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
|
|
3632
3619
|
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
3633
3620
|
handlers.onRunInitialized = batchedForceUpdate;
|
|
3634
3621
|
handlers.onRunFinalized = batchedForceUpdate;
|
|
3635
3622
|
handlers.onRunFailed = batchedForceUpdate;
|
|
3623
|
+
handlers.onRunErrorEvent = batchedForceUpdate;
|
|
3636
3624
|
}
|
|
3637
|
-
const subscription =
|
|
3625
|
+
const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
|
|
3638
3626
|
return () => {
|
|
3639
3627
|
active = false;
|
|
3640
|
-
if (timerId !== null) clearTimeout(timerId);
|
|
3641
3628
|
subscription.unsubscribe();
|
|
3642
3629
|
};
|
|
3643
3630
|
}, [
|
|
3644
3631
|
agent,
|
|
3645
3632
|
forceUpdate,
|
|
3646
|
-
|
|
3633
|
+
throttleMs,
|
|
3634
|
+
providerThrottleMs,
|
|
3647
3635
|
updateFlags
|
|
3648
3636
|
]);
|
|
3649
3637
|
useEffect(() => {
|
|
@@ -3671,7 +3659,7 @@ function useRenderCustomMessages() {
|
|
|
3671
3659
|
const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
|
|
3672
3660
|
const registryAgent = copilotkit.getAgent(agentId);
|
|
3673
3661
|
const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
|
|
3674
|
-
if (!agent)
|
|
3662
|
+
if (!agent) return null;
|
|
3675
3663
|
const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
|
|
3676
3664
|
const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
|
|
3677
3665
|
const messageIndex = rawMessageIndex >= 0 ? rawMessageIndex : 0;
|
|
@@ -4597,13 +4585,14 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4597
4585
|
const { copilotkit } = useCopilotKit();
|
|
4598
4586
|
const [store] = useState(() => ɵcreateThreadStore({ fetch: globalThis.fetch }));
|
|
4599
4587
|
const coreThreads = useThreadStoreSelector(store, ɵselectThreads);
|
|
4600
|
-
const threads = useMemo(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt }) => ({
|
|
4588
|
+
const threads = useMemo(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt, lastRunAt }) => ({
|
|
4601
4589
|
id,
|
|
4602
4590
|
agentId,
|
|
4603
4591
|
name,
|
|
4604
4592
|
archived,
|
|
4605
4593
|
createdAt,
|
|
4606
|
-
updatedAt
|
|
4594
|
+
updatedAt,
|
|
4595
|
+
...lastRunAt !== void 0 ? { lastRunAt } : {}
|
|
4607
4596
|
})), [coreThreads]);
|
|
4608
4597
|
const storeIsLoading = useThreadStoreSelector(store, ɵselectThreadsIsLoading);
|
|
4609
4598
|
const storeError = useThreadStoreSelector(store, ɵselectThreadsError);
|
|
@@ -4616,7 +4605,9 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4616
4605
|
if (copilotkit.runtimeUrl) return null;
|
|
4617
4606
|
return /* @__PURE__ */ new Error("Runtime URL is not configured");
|
|
4618
4607
|
}, [copilotkit.runtimeUrl]);
|
|
4619
|
-
const
|
|
4608
|
+
const [hasDispatchedContext, setHasDispatchedContext] = useState(false);
|
|
4609
|
+
const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
|
|
4610
|
+
const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
|
|
4620
4611
|
const error = runtimeError ?? storeError;
|
|
4621
4612
|
useEffect(() => {
|
|
4622
4613
|
store.start();
|
|
@@ -4624,19 +4615,27 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4624
4615
|
store.stop();
|
|
4625
4616
|
};
|
|
4626
4617
|
}, [store]);
|
|
4618
|
+
const runtimeStatus = copilotkit.runtimeConnectionStatus;
|
|
4627
4619
|
useEffect(() => {
|
|
4628
|
-
|
|
4620
|
+
if (!copilotkit.runtimeUrl) {
|
|
4621
|
+
store.setContext(null);
|
|
4622
|
+
return;
|
|
4623
|
+
}
|
|
4624
|
+
if (runtimeStatus !== CopilotKitCoreRuntimeConnectionStatus.Connected) return;
|
|
4625
|
+
const context = {
|
|
4629
4626
|
runtimeUrl: copilotkit.runtimeUrl,
|
|
4630
4627
|
headers: { ...copilotkit.headers },
|
|
4631
4628
|
wsUrl: copilotkit.intelligence?.wsUrl,
|
|
4632
4629
|
agentId,
|
|
4633
4630
|
includeArchived,
|
|
4634
4631
|
limit
|
|
4635
|
-
}
|
|
4632
|
+
};
|
|
4636
4633
|
store.setContext(context);
|
|
4634
|
+
setHasDispatchedContext(true);
|
|
4637
4635
|
}, [
|
|
4638
4636
|
store,
|
|
4639
4637
|
copilotkit.runtimeUrl,
|
|
4638
|
+
runtimeStatus,
|
|
4640
4639
|
headersKey,
|
|
4641
4640
|
copilotkit.intelligence?.wsUrl,
|
|
4642
4641
|
agentId,
|
|
@@ -4841,10 +4840,10 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp,
|
|
|
4841
4840
|
if (message.content) return await copyToClipboard(message.content);
|
|
4842
4841
|
return false;
|
|
4843
4842
|
} });
|
|
4844
|
-
const boundThumbsUpButton = renderSlot(thumbsUpButton, CopilotChatAssistantMessage.ThumbsUpButton, { onClick: onThumbsUp });
|
|
4845
|
-
const boundThumbsDownButton = renderSlot(thumbsDownButton, CopilotChatAssistantMessage.ThumbsDownButton, { onClick: onThumbsDown });
|
|
4846
|
-
const boundReadAloudButton = renderSlot(readAloudButton, CopilotChatAssistantMessage.ReadAloudButton, { onClick: onReadAloud });
|
|
4847
|
-
const boundRegenerateButton = renderSlot(regenerateButton, CopilotChatAssistantMessage.RegenerateButton, { onClick: onRegenerate });
|
|
4843
|
+
const boundThumbsUpButton = renderSlot(thumbsUpButton, CopilotChatAssistantMessage.ThumbsUpButton, { onClick: onThumbsUp ? () => onThumbsUp(message) : void 0 });
|
|
4844
|
+
const boundThumbsDownButton = renderSlot(thumbsDownButton, CopilotChatAssistantMessage.ThumbsDownButton, { onClick: onThumbsDown ? () => onThumbsDown(message) : void 0 });
|
|
4845
|
+
const boundReadAloudButton = renderSlot(readAloudButton, CopilotChatAssistantMessage.ReadAloudButton, { onClick: onReadAloud ? () => onReadAloud(message) : void 0 });
|
|
4846
|
+
const boundRegenerateButton = renderSlot(regenerateButton, CopilotChatAssistantMessage.RegenerateButton, { onClick: onRegenerate ? () => onRegenerate(message) : void 0 });
|
|
4848
4847
|
const boundToolbar = renderSlot(toolbar, CopilotChatAssistantMessage.Toolbar, { children: /* @__PURE__ */ jsxs("div", {
|
|
4849
4848
|
className: "cpk:flex cpk:items-center cpk:gap-1",
|
|
4850
4849
|
children: [
|
|
@@ -6161,9 +6160,97 @@ function useKeyboardHeight() {
|
|
|
6161
6160
|
return keyboardState;
|
|
6162
6161
|
}
|
|
6163
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
|
+
|
|
6164
6245
|
//#endregion
|
|
6165
6246
|
//#region src/v2/components/chat/CopilotChatView.tsx
|
|
6166
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
|
+
});
|
|
6167
6254
|
function DropOverlay() {
|
|
6168
6255
|
return /* @__PURE__ */ jsx("div", {
|
|
6169
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"),
|
|
@@ -6176,7 +6263,7 @@ function DropOverlay() {
|
|
|
6176
6263
|
})
|
|
6177
6264
|
});
|
|
6178
6265
|
}
|
|
6179
|
-
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 }) {
|
|
6180
6267
|
const inputContainerRef = useRef(null);
|
|
6181
6268
|
const [inputContainerHeight, setInputContainerHeight] = useState(0);
|
|
6182
6269
|
const [isResizing, setIsResizing] = useState(false);
|
|
@@ -6228,9 +6315,10 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6228
6315
|
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
6229
6316
|
containerRef: inputContainerRef,
|
|
6230
6317
|
showDisclaimer: true,
|
|
6318
|
+
bottomAnchored: true,
|
|
6231
6319
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
6232
6320
|
});
|
|
6233
|
-
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
|
|
6321
|
+
const hasSuggestions = !isConnecting && !isRunning && Array.isArray(suggestions) && suggestions.length > 0;
|
|
6234
6322
|
const BoundSuggestionView = hasSuggestions ? renderSlot(suggestionView, CopilotChatSuggestionView, {
|
|
6235
6323
|
suggestions,
|
|
6236
6324
|
loadingIndexes: suggestionLoadingIndexes,
|
|
@@ -6252,7 +6340,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6252
6340
|
})
|
|
6253
6341
|
})
|
|
6254
6342
|
});
|
|
6255
|
-
if (messages.length === 0 && !(welcomeScreen === false)) {
|
|
6343
|
+
if (messages.length === 0 && !(welcomeScreen === false) && !isConnecting && !hasExplicitThreadId) {
|
|
6256
6344
|
const BoundInputForWelcome = renderSlot(input, CopilotChatInput_default, {
|
|
6257
6345
|
onSubmitMessage,
|
|
6258
6346
|
onStop,
|
|
@@ -6359,9 +6447,60 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6359
6447
|
] })
|
|
6360
6448
|
});
|
|
6361
6449
|
};
|
|
6362
|
-
|
|
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);
|
|
6363
6494
|
const [hasMounted, setHasMounted] = useState(false);
|
|
6364
|
-
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
|
+
}, []);
|
|
6365
6504
|
const [showScrollButton, setShowScrollButton] = useState(false);
|
|
6366
6505
|
const [nonAutoScrollEl, setNonAutoScrollEl] = useState(null);
|
|
6367
6506
|
const nonAutoScrollRefCallback = useCallback((el) => {
|
|
@@ -6372,7 +6511,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6372
6511
|
setHasMounted(true);
|
|
6373
6512
|
}, []);
|
|
6374
6513
|
useEffect(() => {
|
|
6375
|
-
if (
|
|
6514
|
+
if (mode === "pin-to-bottom") return;
|
|
6376
6515
|
const scrollElement = scrollRef.current;
|
|
6377
6516
|
if (!scrollElement) return;
|
|
6378
6517
|
const checkScroll = () => {
|
|
@@ -6386,7 +6525,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6386
6525
|
scrollElement.removeEventListener("scroll", checkScroll);
|
|
6387
6526
|
resizeObserver.disconnect();
|
|
6388
6527
|
};
|
|
6389
|
-
}, [scrollRef,
|
|
6528
|
+
}, [scrollRef, mode]);
|
|
6390
6529
|
if (!hasMounted) return /* @__PURE__ */ jsx("div", {
|
|
6391
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",
|
|
6392
6531
|
children: /* @__PURE__ */ jsx("div", {
|
|
@@ -6394,7 +6533,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6394
6533
|
children
|
|
6395
6534
|
})
|
|
6396
6535
|
});
|
|
6397
|
-
if (
|
|
6536
|
+
if (mode === "none") {
|
|
6398
6537
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
6399
6538
|
return /* @__PURE__ */ jsx(ScrollElementContext.Provider, {
|
|
6400
6539
|
value: nonAutoScrollEl,
|
|
@@ -6418,6 +6557,21 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6418
6557
|
})
|
|
6419
6558
|
});
|
|
6420
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
|
+
});
|
|
6421
6575
|
return /* @__PURE__ */ jsx(StickToBottom, {
|
|
6422
6576
|
className: cn("cpk:flex-1 cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0", className),
|
|
6423
6577
|
resize: "smooth",
|
|
@@ -6610,7 +6764,8 @@ async function transcribeAudio(core, audioBlob, filename = "recording.webm") {
|
|
|
6610
6764
|
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
6611
6765
|
const existingConfig = useCopilotChatConfiguration();
|
|
6612
6766
|
const resolvedAgentId = agentId ?? existingConfig?.agentId ?? DEFAULT_AGENT_ID;
|
|
6613
|
-
const
|
|
6767
|
+
const providedThreadId = threadId ?? existingConfig?.threadId;
|
|
6768
|
+
const resolvedThreadId = useMemo(() => providedThreadId ?? randomUUID(), [providedThreadId]);
|
|
6614
6769
|
const { agent } = useAgent({
|
|
6615
6770
|
agentId: resolvedAgentId,
|
|
6616
6771
|
threadId: resolvedThreadId,
|
|
@@ -6648,7 +6803,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6648
6803
|
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
|
|
6649
6804
|
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
|
|
6650
6805
|
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
|
|
6806
|
+
const [lastConnectedThreadId, setLastConnectedThreadId] = useState(null);
|
|
6807
|
+
const isConnecting = !!providedThreadId && lastConnectedThreadId !== resolvedThreadId;
|
|
6651
6808
|
useEffect(() => {
|
|
6809
|
+
if (!providedThreadId) return;
|
|
6652
6810
|
let detached = false;
|
|
6653
6811
|
const connectAbortController = new AbortController();
|
|
6654
6812
|
if (agent instanceof HttpAgent) agent.abortController = connectAbortController;
|
|
@@ -6658,6 +6816,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6658
6816
|
} catch (error) {
|
|
6659
6817
|
if (detached) return;
|
|
6660
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
|
+
});
|
|
6661
6823
|
}
|
|
6662
6824
|
};
|
|
6663
6825
|
connect(agent);
|
|
@@ -6669,7 +6831,8 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6669
6831
|
}, [
|
|
6670
6832
|
resolvedThreadId,
|
|
6671
6833
|
agent,
|
|
6672
|
-
resolvedAgentId
|
|
6834
|
+
resolvedAgentId,
|
|
6835
|
+
providedThreadId
|
|
6673
6836
|
]);
|
|
6674
6837
|
const onSubmitInput = useCallback(async (value) => {
|
|
6675
6838
|
if (selectedAttachments.some((a) => a.status === "uploading")) {
|
|
@@ -6822,6 +6985,22 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6822
6985
|
const toolCallsKey = "toolCalls" in m && Array.isArray(m.toolCalls) ? m.toolCalls.map((tc) => `${tc.id}:${tc.function?.arguments?.length ?? 0}`).join(";") : "";
|
|
6823
6986
|
return `${m.id}:${m.role}:${contentKey}:${toolCallsKey}`;
|
|
6824
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]);
|
|
6825
7004
|
const RenderedChatView = renderSlot(chatView, CopilotChatView, {
|
|
6826
7005
|
...mergedProps,
|
|
6827
7006
|
messages,
|
|
@@ -6840,7 +7019,9 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6840
7019
|
dragOver,
|
|
6841
7020
|
onDragOver: handleDragOver,
|
|
6842
7021
|
onDragLeave: handleDragLeave,
|
|
6843
|
-
onDrop: handleDrop
|
|
7022
|
+
onDrop: handleDrop,
|
|
7023
|
+
isConnecting,
|
|
7024
|
+
hasExplicitThreadId: !!providedThreadId
|
|
6844
7025
|
});
|
|
6845
7026
|
return /* @__PURE__ */ jsx(CopilotChatConfigurationProvider, {
|
|
6846
7027
|
agentId: resolvedAgentId,
|
|
@@ -6875,7 +7056,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6875
7056
|
},
|
|
6876
7057
|
children: transcriptionError
|
|
6877
7058
|
}),
|
|
6878
|
-
|
|
7059
|
+
/* @__PURE__ */ jsx(LastUserMessageContext.Provider, {
|
|
7060
|
+
value: lastUserMessageState,
|
|
7061
|
+
children: RenderedChatView
|
|
7062
|
+
})
|
|
6879
7063
|
]
|
|
6880
7064
|
})
|
|
6881
7065
|
});
|
|
@@ -9013,12 +9197,17 @@ const usePredictStateSubscription = (agent) => {
|
|
|
9013
9197
|
};
|
|
9014
9198
|
}, [agent, getSubscriber]);
|
|
9015
9199
|
};
|
|
9016
|
-
function
|
|
9017
|
-
const { copilotkit } = useCopilotKit();
|
|
9200
|
+
function CopilotListenersAgentSubscription() {
|
|
9018
9201
|
const resolvedAgentId = useCopilotChatConfiguration()?.agentId;
|
|
9019
|
-
const { setBannerError } = useToast();
|
|
9020
9202
|
const { agent } = useAgent({ agentId: resolvedAgentId });
|
|
9021
9203
|
usePredictStateSubscription(agent);
|
|
9204
|
+
return null;
|
|
9205
|
+
}
|
|
9206
|
+
function CopilotListeners() {
|
|
9207
|
+
const { copilotkit } = useCopilotKit();
|
|
9208
|
+
const { setBannerError } = useToast();
|
|
9209
|
+
const hasAgents = Object.keys(copilotkit.agents ?? {}).length > 0;
|
|
9210
|
+
const hasRuntime = copilotkit.runtimeUrl !== void 0;
|
|
9022
9211
|
useEffect(() => {
|
|
9023
9212
|
const subscription = copilotkit.subscribe({ onError: ({ error, code, context }) => {
|
|
9024
9213
|
if (error.name === "AbortError" || error.message === "Fetch is aborted" || error.message === "signal is aborted without reason" || error.message === "component unmounted" || !error.message) return;
|
|
@@ -9040,7 +9229,7 @@ function CopilotListeners() {
|
|
|
9040
9229
|
subscription.unsubscribe();
|
|
9041
9230
|
};
|
|
9042
9231
|
}, [copilotkit?.subscribe]);
|
|
9043
|
-
return null;
|
|
9232
|
+
return hasAgents || hasRuntime ? /* @__PURE__ */ jsx(CopilotListenersAgentSubscription, {}) : null;
|
|
9044
9233
|
}
|
|
9045
9234
|
|
|
9046
9235
|
//#endregion
|
|
@@ -9553,4 +9742,4 @@ function validateProps(props) {
|
|
|
9553
9742
|
|
|
9554
9743
|
//#endregion
|
|
9555
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 };
|
|
9556
|
-
//# sourceMappingURL=copilotkit-
|
|
9745
|
+
//# sourceMappingURL=copilotkit-BBYbekCa.mjs.map
|