@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
|
@@ -299,8 +299,9 @@ const buttonVariants = (0, class_variance_authority.cva)("cpk:inline-flex cpk:it
|
|
|
299
299
|
size: "default"
|
|
300
300
|
}
|
|
301
301
|
});
|
|
302
|
-
function Button({ className, variant, size, asChild = false, ...props }) {
|
|
302
|
+
const Button = react.forwardRef(function Button({ className, variant, size, asChild = false, ...props }, ref) {
|
|
303
303
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(asChild ? _radix_ui_react_slot.Slot : "button", {
|
|
304
|
+
ref,
|
|
304
305
|
"data-slot": "button",
|
|
305
306
|
className: cn(buttonVariants({
|
|
306
307
|
variant,
|
|
@@ -309,7 +310,7 @@ function Button({ className, variant, size, asChild = false, ...props }) {
|
|
|
309
310
|
})),
|
|
310
311
|
...props
|
|
311
312
|
});
|
|
312
|
-
}
|
|
313
|
+
});
|
|
313
314
|
|
|
314
315
|
//#endregion
|
|
315
316
|
//#region src/v2/components/ui/tooltip.tsx
|
|
@@ -609,7 +610,7 @@ CopilotChatAudioRecorder.displayName = "CopilotChatAudioRecorder";
|
|
|
609
610
|
//#region src/v2/components/chat/CopilotChatInput.tsx
|
|
610
611
|
const SLASH_MENU_MAX_VISIBLE_ITEMS = 5;
|
|
611
612
|
const SLASH_MENU_ITEM_HEIGHT_PX = 40;
|
|
612
|
-
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 }) {
|
|
613
|
+
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 }) {
|
|
613
614
|
const isControlled = value !== void 0;
|
|
614
615
|
const [internalValue, setInternalValue] = (0, react.useState)(() => value ?? "");
|
|
615
616
|
(0, react.useEffect)(() => {
|
|
@@ -751,6 +752,7 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
751
752
|
});
|
|
752
753
|
}, [clearInputValue]);
|
|
753
754
|
const handleKeyDown = (e) => {
|
|
755
|
+
if (e.nativeEvent.isComposing || e.keyCode === 229) return;
|
|
754
756
|
if (commandQuery !== null && mode === "input") {
|
|
755
757
|
if (e.key === "ArrowDown") {
|
|
756
758
|
if (filteredCommands.length > 0) {
|
|
@@ -798,10 +800,8 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
798
800
|
const trimmed = resolvedValue.trim();
|
|
799
801
|
if (!trimmed) return;
|
|
800
802
|
onSubmitMessage(trimmed);
|
|
801
|
-
if (!isControlled)
|
|
802
|
-
|
|
803
|
-
onChange?.("");
|
|
804
|
-
}
|
|
803
|
+
if (!isControlled) setInternalValue("");
|
|
804
|
+
onChange?.("");
|
|
805
805
|
if (inputRef.current) inputRef.current.focus();
|
|
806
806
|
};
|
|
807
807
|
const BoundTextArea = renderSlot(textArea, CopilotChatInput.TextArea, {
|
|
@@ -809,6 +809,12 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
809
809
|
value: resolvedValue,
|
|
810
810
|
onChange: handleChange,
|
|
811
811
|
onKeyDown: handleKeyDown,
|
|
812
|
+
onCompositionStart: () => {
|
|
813
|
+
isComposingRef.current = true;
|
|
814
|
+
},
|
|
815
|
+
onCompositionEnd: () => {
|
|
816
|
+
isComposingRef.current = false;
|
|
817
|
+
},
|
|
812
818
|
autoFocus,
|
|
813
819
|
className: (0, tailwind_merge.twMerge)("cpk:w-full cpk:py-3", isExpanded ? "cpk:px-5" : "cpk:pr-5")
|
|
814
820
|
});
|
|
@@ -883,9 +889,10 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
883
889
|
const target = e.target;
|
|
884
890
|
if (target.tagName !== "BUTTON" && !target.closest("button") && inputRef.current && mode === "input") inputRef.current.focus();
|
|
885
891
|
};
|
|
892
|
+
const isComposingRef = (0, react.useRef)(false);
|
|
886
893
|
const ensureMeasurements = (0, react.useCallback)(() => {
|
|
887
894
|
const textarea = inputRef.current;
|
|
888
|
-
if (!textarea) return;
|
|
895
|
+
if (!textarea || isComposingRef.current) return;
|
|
889
896
|
const previousValue = textarea.value;
|
|
890
897
|
const previousHeight = textarea.style.height;
|
|
891
898
|
textarea.style.height = "auto";
|
|
@@ -1127,7 +1134,8 @@ function CopilotChatInput({ mode = "input", onSubmitMessage, onStop, isRunning =
|
|
|
1127
1134
|
className: cn("cpk:pointer-events-none cpk:relative cpk:z-20", positioning === "absolute" && "cpk:absolute cpk:bottom-0 cpk:left-0 cpk:right-0", className),
|
|
1128
1135
|
style: {
|
|
1129
1136
|
transform: keyboardHeight > 0 ? `translateY(-${keyboardHeight}px)` : void 0,
|
|
1130
|
-
transition: "transform 0.2s ease-out"
|
|
1137
|
+
transition: "transform 0.2s ease-out",
|
|
1138
|
+
...positioning === "absolute" || bottomAnchored ? { paddingBottom: "var(--copilotkit-license-banner-offset, 0px)" } : {}
|
|
1131
1139
|
},
|
|
1132
1140
|
...props,
|
|
1133
1141
|
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -1342,6 +1350,8 @@ CopilotKitInspector.displayName = "CopilotKitInspector";
|
|
|
1342
1350
|
|
|
1343
1351
|
//#endregion
|
|
1344
1352
|
//#region src/v2/components/license-warning-banner.tsx
|
|
1353
|
+
const LICENSE_BANNER_OFFSET_PX = 52;
|
|
1354
|
+
const LICENSE_BANNER_OFFSET_VAR = "--copilotkit-license-banner-offset";
|
|
1345
1355
|
const BANNER_STYLES = {
|
|
1346
1356
|
base: {
|
|
1347
1357
|
position: "fixed",
|
|
@@ -1383,6 +1393,14 @@ function getSeverityStyle(severity) {
|
|
|
1383
1393
|
}
|
|
1384
1394
|
}
|
|
1385
1395
|
function BannerShell({ severity, message, actionLabel, actionUrl, onDismiss }) {
|
|
1396
|
+
(0, react.useEffect)(() => {
|
|
1397
|
+
if (typeof document === "undefined") return;
|
|
1398
|
+
const root = document.documentElement;
|
|
1399
|
+
root.style.setProperty(LICENSE_BANNER_OFFSET_VAR, `${LICENSE_BANNER_OFFSET_PX}px`);
|
|
1400
|
+
return () => {
|
|
1401
|
+
root.style.removeProperty(LICENSE_BANNER_OFFSET_VAR);
|
|
1402
|
+
};
|
|
1403
|
+
}, []);
|
|
1386
1404
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
1387
1405
|
style: {
|
|
1388
1406
|
...BANNER_STYLES.base,
|
|
@@ -3335,7 +3353,6 @@ const CopilotKitProvider = ({ children, runtimeUrl, headers: headersProp = {}, c
|
|
|
3335
3353
|
didMountRef.current = true;
|
|
3336
3354
|
}, []);
|
|
3337
3355
|
(0, react.useEffect)(() => {
|
|
3338
|
-
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.`);
|
|
3339
3356
|
copilotkit.setDefaultThrottleMs(defaultThrottleMs);
|
|
3340
3357
|
}, [copilotkit, defaultThrottleMs]);
|
|
3341
3358
|
const designSkill = openGenerativeUI?.designSkill ?? DEFAULT_DESIGN_SKILL;
|
|
@@ -3433,18 +3450,21 @@ const ToolCallRenderer = react.default.memo(function ToolCallRenderer({ toolCall
|
|
|
3433
3450
|
const toolName = toolCall.function.name;
|
|
3434
3451
|
if (toolMessage) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
|
|
3435
3452
|
name: toolName,
|
|
3453
|
+
toolCallId: toolCall.id,
|
|
3436
3454
|
args,
|
|
3437
3455
|
status: _copilotkit_core.ToolCallStatus.Complete,
|
|
3438
3456
|
result: toolMessage.content
|
|
3439
3457
|
});
|
|
3440
3458
|
else if (isExecuting) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
|
|
3441
3459
|
name: toolName,
|
|
3460
|
+
toolCallId: toolCall.id,
|
|
3442
3461
|
args,
|
|
3443
3462
|
status: _copilotkit_core.ToolCallStatus.Executing,
|
|
3444
3463
|
result: void 0
|
|
3445
3464
|
});
|
|
3446
3465
|
else return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(RenderComponent, {
|
|
3447
3466
|
name: toolName,
|
|
3467
|
+
toolCallId: toolCall.id,
|
|
3448
3468
|
args,
|
|
3449
3469
|
status: _copilotkit_core.ToolCallStatus.InProgress,
|
|
3450
3470
|
result: void 0
|
|
@@ -3549,15 +3569,6 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3549
3569
|
const providerThrottleMs = copilotkit.defaultThrottleMs;
|
|
3550
3570
|
const chatConfig = useCopilotChatConfiguration();
|
|
3551
3571
|
threadId ??= chatConfig?.threadId;
|
|
3552
|
-
const effectiveThrottleMs = (0, react.useMemo)(() => {
|
|
3553
|
-
const resolved = throttleMs ?? providerThrottleMs ?? 0;
|
|
3554
|
-
if (!Number.isFinite(resolved) || resolved < 0) {
|
|
3555
|
-
const source = throttleMs !== void 0 ? "hook-level throttleMs" : "provider-level defaultThrottleMs";
|
|
3556
|
-
console.error(`useAgent: ${source} must be a non-negative finite number, got ${resolved}. Falling back to unthrottled.`);
|
|
3557
|
-
return 0;
|
|
3558
|
-
}
|
|
3559
|
-
return resolved;
|
|
3560
|
-
}, [throttleMs, providerThrottleMs]);
|
|
3561
3572
|
const [, forceUpdate] = (0, react.useReducer)((x) => x + 1, 0);
|
|
3562
3573
|
const updateFlags = (0, react.useMemo)(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
|
|
3563
3574
|
const provisionalAgentCache = (0, react.useRef)(/* @__PURE__ */ new Map());
|
|
@@ -3620,9 +3631,8 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3620
3631
|
]);
|
|
3621
3632
|
(0, react.useEffect)(() => {
|
|
3622
3633
|
if (updateFlags.length === 0) return;
|
|
3623
|
-
const handlers = {};
|
|
3624
|
-
let timerId = null;
|
|
3625
3634
|
let active = true;
|
|
3635
|
+
const handlers = {};
|
|
3626
3636
|
let batchScheduled = false;
|
|
3627
3637
|
const batchedForceUpdate = () => {
|
|
3628
3638
|
if (!active) return;
|
|
@@ -3634,46 +3644,24 @@ function useAgent({ agentId, threadId, updates, throttleMs } = {}) {
|
|
|
3634
3644
|
});
|
|
3635
3645
|
}
|
|
3636
3646
|
};
|
|
3637
|
-
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged))
|
|
3638
|
-
const ms = effectiveThrottleMs;
|
|
3639
|
-
if (ms > 0) {
|
|
3640
|
-
let throttleActive = false;
|
|
3641
|
-
let pending = false;
|
|
3642
|
-
const throttledNotify = () => {
|
|
3643
|
-
if (!active) return;
|
|
3644
|
-
if (!throttleActive) {
|
|
3645
|
-
throttleActive = true;
|
|
3646
|
-
pending = false;
|
|
3647
|
-
forceUpdate();
|
|
3648
|
-
timerId = setTimeout(function trailingEdge() {
|
|
3649
|
-
timerId = null;
|
|
3650
|
-
if (active && pending) {
|
|
3651
|
-
pending = false;
|
|
3652
|
-
forceUpdate();
|
|
3653
|
-
timerId = setTimeout(trailingEdge, ms);
|
|
3654
|
-
} else throttleActive = false;
|
|
3655
|
-
}, ms);
|
|
3656
|
-
} else pending = true;
|
|
3657
|
-
};
|
|
3658
|
-
handlers.onMessagesChanged = throttledNotify;
|
|
3659
|
-
} else handlers.onMessagesChanged = forceUpdate;
|
|
3660
|
-
}
|
|
3647
|
+
if (updateFlags.includes(UseAgentUpdate.OnMessagesChanged)) handlers.onMessagesChanged = forceUpdate;
|
|
3661
3648
|
if (updateFlags.includes(UseAgentUpdate.OnStateChanged)) handlers.onStateChanged = batchedForceUpdate;
|
|
3662
3649
|
if (updateFlags.includes(UseAgentUpdate.OnRunStatusChanged)) {
|
|
3663
3650
|
handlers.onRunInitialized = batchedForceUpdate;
|
|
3664
3651
|
handlers.onRunFinalized = batchedForceUpdate;
|
|
3665
3652
|
handlers.onRunFailed = batchedForceUpdate;
|
|
3653
|
+
handlers.onRunErrorEvent = batchedForceUpdate;
|
|
3666
3654
|
}
|
|
3667
|
-
const subscription =
|
|
3655
|
+
const subscription = copilotkit.subscribeToAgentWithOptions(agent, handlers, { throttleMs });
|
|
3668
3656
|
return () => {
|
|
3669
3657
|
active = false;
|
|
3670
|
-
if (timerId !== null) clearTimeout(timerId);
|
|
3671
3658
|
subscription.unsubscribe();
|
|
3672
3659
|
};
|
|
3673
3660
|
}, [
|
|
3674
3661
|
agent,
|
|
3675
3662
|
forceUpdate,
|
|
3676
|
-
|
|
3663
|
+
throttleMs,
|
|
3664
|
+
providerThrottleMs,
|
|
3677
3665
|
updateFlags
|
|
3678
3666
|
]);
|
|
3679
3667
|
(0, react.useEffect)(() => {
|
|
@@ -3701,7 +3689,7 @@ function useRenderCustomMessages() {
|
|
|
3701
3689
|
const runId = resolvedRunId ?? `missing-run-id:${message.id}`;
|
|
3702
3690
|
const registryAgent = copilotkit.getAgent(agentId);
|
|
3703
3691
|
const agent = getThreadClone(registryAgent, threadId) ?? registryAgent;
|
|
3704
|
-
if (!agent)
|
|
3692
|
+
if (!agent) return null;
|
|
3705
3693
|
const messagesIdsInRun = resolvedRunId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === resolvedRunId).map((msg) => msg.id) : [message.id];
|
|
3706
3694
|
const rawMessageIndex = agent.messages.findIndex((msg) => msg.id === message.id);
|
|
3707
3695
|
const messageIndex = rawMessageIndex >= 0 ? rawMessageIndex : 0;
|
|
@@ -4627,13 +4615,14 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4627
4615
|
const { copilotkit } = useCopilotKit();
|
|
4628
4616
|
const [store] = (0, react.useState)(() => (0, _copilotkit_core.ɵcreateThreadStore)({ fetch: globalThis.fetch }));
|
|
4629
4617
|
const coreThreads = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreads);
|
|
4630
|
-
const threads = (0, react.useMemo)(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt }) => ({
|
|
4618
|
+
const threads = (0, react.useMemo)(() => coreThreads.map(({ id, agentId, name, archived, createdAt, updatedAt, lastRunAt }) => ({
|
|
4631
4619
|
id,
|
|
4632
4620
|
agentId,
|
|
4633
4621
|
name,
|
|
4634
4622
|
archived,
|
|
4635
4623
|
createdAt,
|
|
4636
|
-
updatedAt
|
|
4624
|
+
updatedAt,
|
|
4625
|
+
...lastRunAt !== void 0 ? { lastRunAt } : {}
|
|
4637
4626
|
})), [coreThreads]);
|
|
4638
4627
|
const storeIsLoading = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsIsLoading);
|
|
4639
4628
|
const storeError = useThreadStoreSelector(store, _copilotkit_core.ɵselectThreadsError);
|
|
@@ -4646,7 +4635,9 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4646
4635
|
if (copilotkit.runtimeUrl) return null;
|
|
4647
4636
|
return /* @__PURE__ */ new Error("Runtime URL is not configured");
|
|
4648
4637
|
}, [copilotkit.runtimeUrl]);
|
|
4649
|
-
const
|
|
4638
|
+
const [hasDispatchedContext, setHasDispatchedContext] = (0, react.useState)(false);
|
|
4639
|
+
const preConnectLoading = !!copilotkit.runtimeUrl && !hasDispatchedContext;
|
|
4640
|
+
const isLoading = runtimeError ? false : preConnectLoading || storeIsLoading;
|
|
4650
4641
|
const error = runtimeError ?? storeError;
|
|
4651
4642
|
(0, react.useEffect)(() => {
|
|
4652
4643
|
store.start();
|
|
@@ -4654,19 +4645,27 @@ function useThreads$1({ agentId, includeArchived, limit }) {
|
|
|
4654
4645
|
store.stop();
|
|
4655
4646
|
};
|
|
4656
4647
|
}, [store]);
|
|
4648
|
+
const runtimeStatus = copilotkit.runtimeConnectionStatus;
|
|
4657
4649
|
(0, react.useEffect)(() => {
|
|
4658
|
-
|
|
4650
|
+
if (!copilotkit.runtimeUrl) {
|
|
4651
|
+
store.setContext(null);
|
|
4652
|
+
return;
|
|
4653
|
+
}
|
|
4654
|
+
if (runtimeStatus !== _copilotkit_core.CopilotKitCoreRuntimeConnectionStatus.Connected) return;
|
|
4655
|
+
const context = {
|
|
4659
4656
|
runtimeUrl: copilotkit.runtimeUrl,
|
|
4660
4657
|
headers: { ...copilotkit.headers },
|
|
4661
4658
|
wsUrl: copilotkit.intelligence?.wsUrl,
|
|
4662
4659
|
agentId,
|
|
4663
4660
|
includeArchived,
|
|
4664
4661
|
limit
|
|
4665
|
-
}
|
|
4662
|
+
};
|
|
4666
4663
|
store.setContext(context);
|
|
4664
|
+
setHasDispatchedContext(true);
|
|
4667
4665
|
}, [
|
|
4668
4666
|
store,
|
|
4669
4667
|
copilotkit.runtimeUrl,
|
|
4668
|
+
runtimeStatus,
|
|
4670
4669
|
headersKey,
|
|
4671
4670
|
copilotkit.intelligence?.wsUrl,
|
|
4672
4671
|
agentId,
|
|
@@ -4871,10 +4870,10 @@ function CopilotChatAssistantMessage({ message, messages, isRunning, onThumbsUp,
|
|
|
4871
4870
|
if (message.content) return await (0, _copilotkit_shared.copyToClipboard)(message.content);
|
|
4872
4871
|
return false;
|
|
4873
4872
|
} });
|
|
4874
|
-
const boundThumbsUpButton = renderSlot(thumbsUpButton, CopilotChatAssistantMessage.ThumbsUpButton, { onClick: onThumbsUp });
|
|
4875
|
-
const boundThumbsDownButton = renderSlot(thumbsDownButton, CopilotChatAssistantMessage.ThumbsDownButton, { onClick: onThumbsDown });
|
|
4876
|
-
const boundReadAloudButton = renderSlot(readAloudButton, CopilotChatAssistantMessage.ReadAloudButton, { onClick: onReadAloud });
|
|
4877
|
-
const boundRegenerateButton = renderSlot(regenerateButton, CopilotChatAssistantMessage.RegenerateButton, { onClick: onRegenerate });
|
|
4873
|
+
const boundThumbsUpButton = renderSlot(thumbsUpButton, CopilotChatAssistantMessage.ThumbsUpButton, { onClick: onThumbsUp ? () => onThumbsUp(message) : void 0 });
|
|
4874
|
+
const boundThumbsDownButton = renderSlot(thumbsDownButton, CopilotChatAssistantMessage.ThumbsDownButton, { onClick: onThumbsDown ? () => onThumbsDown(message) : void 0 });
|
|
4875
|
+
const boundReadAloudButton = renderSlot(readAloudButton, CopilotChatAssistantMessage.ReadAloudButton, { onClick: onReadAloud ? () => onReadAloud(message) : void 0 });
|
|
4876
|
+
const boundRegenerateButton = renderSlot(regenerateButton, CopilotChatAssistantMessage.RegenerateButton, { onClick: onRegenerate ? () => onRegenerate(message) : void 0 });
|
|
4878
4877
|
const boundToolbar = renderSlot(toolbar, CopilotChatAssistantMessage.Toolbar, { children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
4879
4878
|
className: "cpk:flex cpk:items-center cpk:gap-1",
|
|
4880
4879
|
children: [
|
|
@@ -6191,9 +6190,97 @@ function useKeyboardHeight() {
|
|
|
6191
6190
|
return keyboardState;
|
|
6192
6191
|
}
|
|
6193
6192
|
|
|
6193
|
+
//#endregion
|
|
6194
|
+
//#region src/v2/components/chat/normalize-auto-scroll.ts
|
|
6195
|
+
const VALID = [
|
|
6196
|
+
"pin-to-bottom",
|
|
6197
|
+
"pin-to-send",
|
|
6198
|
+
"none"
|
|
6199
|
+
];
|
|
6200
|
+
function normalizeAutoScroll(value) {
|
|
6201
|
+
if (value === void 0) return "pin-to-bottom";
|
|
6202
|
+
if (value === true) return "pin-to-bottom";
|
|
6203
|
+
if (value === false) return "none";
|
|
6204
|
+
if (VALID.includes(value)) return value;
|
|
6205
|
+
return "pin-to-bottom";
|
|
6206
|
+
}
|
|
6207
|
+
|
|
6208
|
+
//#endregion
|
|
6209
|
+
//#region src/v2/components/chat/last-user-message-context.ts
|
|
6210
|
+
const LastUserMessageContext = react.default.createContext({
|
|
6211
|
+
id: null,
|
|
6212
|
+
sendNonce: 0
|
|
6213
|
+
});
|
|
6214
|
+
|
|
6215
|
+
//#endregion
|
|
6216
|
+
//#region src/v2/hooks/use-pin-to-send.ts
|
|
6217
|
+
function usePinToSend({ scrollRef, contentRef, spacerRef, topOffset = 16 }) {
|
|
6218
|
+
const { id, sendNonce } = (0, react.useContext)(LastUserMessageContext);
|
|
6219
|
+
const lastNonceRef = (0, react.useRef)(-1);
|
|
6220
|
+
const currentSpacerHeightRef = (0, react.useRef)(0);
|
|
6221
|
+
(0, react.useEffect)(() => {
|
|
6222
|
+
if (sendNonce === lastNonceRef.current) return;
|
|
6223
|
+
lastNonceRef.current = sendNonce;
|
|
6224
|
+
if (!id) return;
|
|
6225
|
+
const scrollEl = scrollRef.current;
|
|
6226
|
+
const contentEl = contentRef.current;
|
|
6227
|
+
const spacerEl = spacerRef.current;
|
|
6228
|
+
if (!scrollEl || !contentEl || !spacerEl) return;
|
|
6229
|
+
const escaped = typeof CSS !== "undefined" && CSS.escape ? CSS.escape(id) : id.replace(/[!"#$%&'()*+,./:;<=>?@[\\\]^`{|}~]/g, "\\$&");
|
|
6230
|
+
const targetEl = contentEl.querySelector(`[data-message-id="${escaped}"]`);
|
|
6231
|
+
if (!targetEl) return;
|
|
6232
|
+
const viewportHeight = scrollEl.clientHeight;
|
|
6233
|
+
const userMessageHeight = targetEl.getBoundingClientRect().height;
|
|
6234
|
+
const paddingTop = parseFloat(getComputedStyle(targetEl).paddingTop) || 0;
|
|
6235
|
+
const bubbleHeight = Math.max(0, userMessageHeight - paddingTop);
|
|
6236
|
+
const spacerHeight = Math.max(0, viewportHeight - bubbleHeight - topOffset);
|
|
6237
|
+
spacerEl.style.height = `${spacerHeight}px`;
|
|
6238
|
+
currentSpacerHeightRef.current = spacerHeight;
|
|
6239
|
+
const raf = requestAnimationFrame(() => {
|
|
6240
|
+
const targetTop = computeOffsetTop(targetEl, scrollEl) + paddingTop - topOffset;
|
|
6241
|
+
scrollEl.scrollTo({
|
|
6242
|
+
top: Math.max(0, targetTop),
|
|
6243
|
+
behavior: "smooth"
|
|
6244
|
+
});
|
|
6245
|
+
});
|
|
6246
|
+
const ro = new ResizeObserver(() => {
|
|
6247
|
+
if (!contentEl || !spacerEl || !scrollEl) return;
|
|
6248
|
+
const consumedBelow = contentEl.getBoundingClientRect().height - computeOffsetTop(targetEl, contentEl) - userMessageHeight;
|
|
6249
|
+
const remaining = Math.max(0, spacerHeight - consumedBelow);
|
|
6250
|
+
if (remaining < currentSpacerHeightRef.current) {
|
|
6251
|
+
spacerEl.style.height = `${remaining}px`;
|
|
6252
|
+
currentSpacerHeightRef.current = remaining;
|
|
6253
|
+
}
|
|
6254
|
+
});
|
|
6255
|
+
ro.observe(contentEl);
|
|
6256
|
+
return () => {
|
|
6257
|
+
cancelAnimationFrame(raf);
|
|
6258
|
+
ro.disconnect();
|
|
6259
|
+
};
|
|
6260
|
+
}, [
|
|
6261
|
+
id,
|
|
6262
|
+
sendNonce,
|
|
6263
|
+
scrollRef,
|
|
6264
|
+
contentRef,
|
|
6265
|
+
spacerRef,
|
|
6266
|
+
topOffset
|
|
6267
|
+
]);
|
|
6268
|
+
}
|
|
6269
|
+
function computeOffsetTop(el, stopAt) {
|
|
6270
|
+
const elRect = el.getBoundingClientRect();
|
|
6271
|
+
const stopRect = stopAt.getBoundingClientRect();
|
|
6272
|
+
return elRect.top - stopRect.top + stopAt.scrollTop;
|
|
6273
|
+
}
|
|
6274
|
+
|
|
6194
6275
|
//#endregion
|
|
6195
6276
|
//#region src/v2/components/chat/CopilotChatView.tsx
|
|
6196
6277
|
const FEATHER_HEIGHT = 96;
|
|
6278
|
+
const PIN_TO_SEND_FEATHER_HEIGHT = 48;
|
|
6279
|
+
const PinToSendSoftFeather = ({ className, style, ...props }) => /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6280
|
+
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),
|
|
6281
|
+
style,
|
|
6282
|
+
...props
|
|
6283
|
+
});
|
|
6197
6284
|
function DropOverlay() {
|
|
6198
6285
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6199
6286
|
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"),
|
|
@@ -6206,7 +6293,7 @@ function DropOverlay() {
|
|
|
6206
6293
|
})
|
|
6207
6294
|
});
|
|
6208
6295
|
}
|
|
6209
|
-
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 }) {
|
|
6296
|
+
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 }) {
|
|
6210
6297
|
const inputContainerRef = (0, react.useRef)(null);
|
|
6211
6298
|
const [inputContainerHeight, setInputContainerHeight] = (0, react.useState)(0);
|
|
6212
6299
|
const [isResizing, setIsResizing] = (0, react.useState)(false);
|
|
@@ -6258,9 +6345,10 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6258
6345
|
keyboardHeight: isKeyboardOpen ? keyboardHeight : 0,
|
|
6259
6346
|
containerRef: inputContainerRef,
|
|
6260
6347
|
showDisclaimer: true,
|
|
6348
|
+
bottomAnchored: true,
|
|
6261
6349
|
...disclaimer !== void 0 ? { disclaimer } : {}
|
|
6262
6350
|
});
|
|
6263
|
-
const hasSuggestions = Array.isArray(suggestions) && suggestions.length > 0;
|
|
6351
|
+
const hasSuggestions = !isConnecting && !isRunning && Array.isArray(suggestions) && suggestions.length > 0;
|
|
6264
6352
|
const BoundSuggestionView = hasSuggestions ? renderSlot(suggestionView, CopilotChatSuggestionView, {
|
|
6265
6353
|
suggestions,
|
|
6266
6354
|
loadingIndexes: suggestionLoadingIndexes,
|
|
@@ -6282,7 +6370,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6282
6370
|
})
|
|
6283
6371
|
})
|
|
6284
6372
|
});
|
|
6285
|
-
if (messages.length === 0 && !(welcomeScreen === false)) {
|
|
6373
|
+
if (messages.length === 0 && !(welcomeScreen === false) && !isConnecting && !hasExplicitThreadId) {
|
|
6286
6374
|
const BoundInputForWelcome = renderSlot(input, CopilotChatInput_default, {
|
|
6287
6375
|
onSubmitMessage,
|
|
6288
6376
|
onStop,
|
|
@@ -6389,9 +6477,60 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6389
6477
|
] })
|
|
6390
6478
|
});
|
|
6391
6479
|
};
|
|
6392
|
-
|
|
6480
|
+
const PinToSendScrollContainer = ({ children, scrollRef, contentRef, scrollToBottom, scrollToBottomButton, feather, inputContainerHeight, isResizing, nonAutoScrollEl, nonAutoScrollRefCallback, showScrollButton, className, ...props }) => {
|
|
6481
|
+
const spacerRef = (0, react.useRef)(null);
|
|
6482
|
+
usePinToSend({
|
|
6483
|
+
scrollRef,
|
|
6484
|
+
contentRef,
|
|
6485
|
+
spacerRef,
|
|
6486
|
+
topOffset: 16
|
|
6487
|
+
});
|
|
6488
|
+
const BoundFeather = renderSlot(feather, PinToSendSoftFeather, {});
|
|
6489
|
+
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
|
|
6490
|
+
value: nonAutoScrollEl,
|
|
6491
|
+
children: /* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6492
|
+
className: cn("cpk:h-full cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0 cpk:relative", className),
|
|
6493
|
+
children: [
|
|
6494
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsxs)("div", {
|
|
6495
|
+
ref: nonAutoScrollRefCallback,
|
|
6496
|
+
className: "cpk:flex-1 cpk:min-h-0 cpk:overflow-y-auto cpk:overflow-x-hidden",
|
|
6497
|
+
...props,
|
|
6498
|
+
children: [/* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6499
|
+
ref: contentRef,
|
|
6500
|
+
className: "cpk:px-4 cpk:sm:px-0 cpk:[div[data-sidebar-chat]_&]:px-8 cpk:[div[data-popup-chat]_&]:px-6",
|
|
6501
|
+
children
|
|
6502
|
+
}), /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6503
|
+
ref: spacerRef,
|
|
6504
|
+
"data-pin-to-send-spacer": true,
|
|
6505
|
+
"aria-hidden": "true",
|
|
6506
|
+
style: {
|
|
6507
|
+
height: 0,
|
|
6508
|
+
flex: "0 0 auto"
|
|
6509
|
+
}
|
|
6510
|
+
})]
|
|
6511
|
+
}),
|
|
6512
|
+
BoundFeather,
|
|
6513
|
+
showScrollButton && !isResizing && /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6514
|
+
className: "cpk:absolute cpk:inset-x-0 cpk:flex cpk:justify-center cpk:z-30 cpk:pointer-events-none",
|
|
6515
|
+
style: { bottom: `${inputContainerHeight + PIN_TO_SEND_FEATHER_HEIGHT + 16}px` },
|
|
6516
|
+
children: renderSlot(scrollToBottomButton, CopilotChatView.ScrollToBottomButton, { onClick: () => scrollToBottom() })
|
|
6517
|
+
})
|
|
6518
|
+
]
|
|
6519
|
+
})
|
|
6520
|
+
});
|
|
6521
|
+
};
|
|
6522
|
+
_CopilotChatView.ScrollView = ({ children, autoScroll = "pin-to-bottom", scrollToBottomButton, feather, inputContainerHeight = 0, isResizing = false, className, ...props }) => {
|
|
6523
|
+
const mode = normalizeAutoScroll(autoScroll);
|
|
6393
6524
|
const [hasMounted, setHasMounted] = (0, react.useState)(false);
|
|
6394
|
-
const
|
|
6525
|
+
const scrollRef = (0, react.useRef)(null);
|
|
6526
|
+
const contentRef = (0, react.useRef)(null);
|
|
6527
|
+
const scrollToBottom = (0, react.useCallback)(() => {
|
|
6528
|
+
const el = scrollRef.current;
|
|
6529
|
+
if (el) el.scrollTo({
|
|
6530
|
+
top: el.scrollHeight,
|
|
6531
|
+
behavior: "smooth"
|
|
6532
|
+
});
|
|
6533
|
+
}, []);
|
|
6395
6534
|
const [showScrollButton, setShowScrollButton] = (0, react.useState)(false);
|
|
6396
6535
|
const [nonAutoScrollEl, setNonAutoScrollEl] = (0, react.useState)(null);
|
|
6397
6536
|
const nonAutoScrollRefCallback = (0, react.useCallback)((el) => {
|
|
@@ -6402,7 +6541,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6402
6541
|
setHasMounted(true);
|
|
6403
6542
|
}, []);
|
|
6404
6543
|
(0, react.useEffect)(() => {
|
|
6405
|
-
if (
|
|
6544
|
+
if (mode === "pin-to-bottom") return;
|
|
6406
6545
|
const scrollElement = scrollRef.current;
|
|
6407
6546
|
if (!scrollElement) return;
|
|
6408
6547
|
const checkScroll = () => {
|
|
@@ -6416,7 +6555,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6416
6555
|
scrollElement.removeEventListener("scroll", checkScroll);
|
|
6417
6556
|
resizeObserver.disconnect();
|
|
6418
6557
|
};
|
|
6419
|
-
}, [scrollRef,
|
|
6558
|
+
}, [scrollRef, mode]);
|
|
6420
6559
|
if (!hasMounted) return /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
6421
6560
|
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",
|
|
6422
6561
|
children: /* @__PURE__ */ (0, react_jsx_runtime.jsx)("div", {
|
|
@@ -6424,7 +6563,7 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6424
6563
|
children
|
|
6425
6564
|
})
|
|
6426
6565
|
});
|
|
6427
|
-
if (
|
|
6566
|
+
if (mode === "none") {
|
|
6428
6567
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
6429
6568
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(ScrollElementContext.Provider, {
|
|
6430
6569
|
value: nonAutoScrollEl,
|
|
@@ -6448,6 +6587,21 @@ function CopilotChatView({ messageView, input, scrollView, suggestionView, welco
|
|
|
6448
6587
|
})
|
|
6449
6588
|
});
|
|
6450
6589
|
}
|
|
6590
|
+
if (mode === "pin-to-send") return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(PinToSendScrollContainer, {
|
|
6591
|
+
scrollRef,
|
|
6592
|
+
contentRef,
|
|
6593
|
+
scrollToBottom,
|
|
6594
|
+
scrollToBottomButton,
|
|
6595
|
+
feather,
|
|
6596
|
+
inputContainerHeight,
|
|
6597
|
+
isResizing,
|
|
6598
|
+
nonAutoScrollEl,
|
|
6599
|
+
nonAutoScrollRefCallback,
|
|
6600
|
+
showScrollButton,
|
|
6601
|
+
className,
|
|
6602
|
+
...props,
|
|
6603
|
+
children
|
|
6604
|
+
});
|
|
6451
6605
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(use_stick_to_bottom.StickToBottom, {
|
|
6452
6606
|
className: cn("cpk:flex-1 cpk:max-h-full cpk:flex cpk:flex-col cpk:min-h-0", className),
|
|
6453
6607
|
resize: "smooth",
|
|
@@ -6640,7 +6794,8 @@ async function transcribeAudio(core, audioBlob, filename = "recording.webm") {
|
|
|
6640
6794
|
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, attachments: attachmentsConfig, onError, throttleMs, ...props }) {
|
|
6641
6795
|
const existingConfig = useCopilotChatConfiguration();
|
|
6642
6796
|
const resolvedAgentId = agentId ?? existingConfig?.agentId ?? _copilotkit_shared.DEFAULT_AGENT_ID;
|
|
6643
|
-
const
|
|
6797
|
+
const providedThreadId = threadId ?? existingConfig?.threadId;
|
|
6798
|
+
const resolvedThreadId = (0, react.useMemo)(() => providedThreadId ?? (0, _copilotkit_shared.randomUUID)(), [providedThreadId]);
|
|
6644
6799
|
const { agent } = useAgent({
|
|
6645
6800
|
agentId: resolvedAgentId,
|
|
6646
6801
|
threadId: resolvedThreadId,
|
|
@@ -6678,7 +6833,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6678
6833
|
const isTranscriptionEnabled = copilotkit.audioFileTranscriptionEnabled;
|
|
6679
6834
|
const isMediaRecorderSupported = typeof window !== "undefined" && typeof MediaRecorder !== "undefined";
|
|
6680
6835
|
const { messageView: providedMessageView, suggestionView: providedSuggestionView, onStop: providedStopHandler, ...restProps } = props;
|
|
6836
|
+
const [lastConnectedThreadId, setLastConnectedThreadId] = (0, react.useState)(null);
|
|
6837
|
+
const isConnecting = !!providedThreadId && lastConnectedThreadId !== resolvedThreadId;
|
|
6681
6838
|
(0, react.useEffect)(() => {
|
|
6839
|
+
if (!providedThreadId) return;
|
|
6682
6840
|
let detached = false;
|
|
6683
6841
|
const connectAbortController = new AbortController();
|
|
6684
6842
|
if (agent instanceof _ag_ui_client.HttpAgent) agent.abortController = connectAbortController;
|
|
@@ -6688,6 +6846,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6688
6846
|
} catch (error) {
|
|
6689
6847
|
if (detached) return;
|
|
6690
6848
|
console.error("CopilotChat: connectAgent failed", error);
|
|
6849
|
+
} finally {
|
|
6850
|
+
if (!detached) (typeof requestAnimationFrame === "function" ? requestAnimationFrame : (cb) => setTimeout(cb, 16))(() => {
|
|
6851
|
+
if (!detached) setLastConnectedThreadId(resolvedThreadId);
|
|
6852
|
+
});
|
|
6691
6853
|
}
|
|
6692
6854
|
};
|
|
6693
6855
|
connect(agent);
|
|
@@ -6699,7 +6861,8 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6699
6861
|
}, [
|
|
6700
6862
|
resolvedThreadId,
|
|
6701
6863
|
agent,
|
|
6702
|
-
resolvedAgentId
|
|
6864
|
+
resolvedAgentId,
|
|
6865
|
+
providedThreadId
|
|
6703
6866
|
]);
|
|
6704
6867
|
const onSubmitInput = (0, react.useCallback)(async (value) => {
|
|
6705
6868
|
if (selectedAttachments.some((a) => a.status === "uploading")) {
|
|
@@ -6852,6 +7015,22 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6852
7015
|
const toolCallsKey = "toolCalls" in m && Array.isArray(m.toolCalls) ? m.toolCalls.map((tc) => `${tc.id}:${tc.function?.arguments?.length ?? 0}`).join(";") : "";
|
|
6853
7016
|
return `${m.id}:${m.role}:${contentKey}:${toolCallsKey}`;
|
|
6854
7017
|
}).join(",")]);
|
|
7018
|
+
const lastUserMessageId = (0, react.useMemo)(() => {
|
|
7019
|
+
for (let i = messages.length - 1; i >= 0; i--) if (messages[i].role === "user") return messages[i].id;
|
|
7020
|
+
return null;
|
|
7021
|
+
}, [messages]);
|
|
7022
|
+
const [sendNonce, setSendNonce] = (0, react.useState)(0);
|
|
7023
|
+
const prevLastUserMessageIdRef = (0, react.useRef)(lastUserMessageId);
|
|
7024
|
+
(0, react.useEffect)(() => {
|
|
7025
|
+
if (lastUserMessageId && lastUserMessageId !== prevLastUserMessageIdRef.current) {
|
|
7026
|
+
setSendNonce((n) => n + 1);
|
|
7027
|
+
prevLastUserMessageIdRef.current = lastUserMessageId;
|
|
7028
|
+
}
|
|
7029
|
+
}, [lastUserMessageId]);
|
|
7030
|
+
const lastUserMessageState = (0, react.useMemo)(() => ({
|
|
7031
|
+
id: lastUserMessageId,
|
|
7032
|
+
sendNonce
|
|
7033
|
+
}), [lastUserMessageId, sendNonce]);
|
|
6855
7034
|
const RenderedChatView = renderSlot(chatView, CopilotChatView, {
|
|
6856
7035
|
...mergedProps,
|
|
6857
7036
|
messages,
|
|
@@ -6870,7 +7049,9 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6870
7049
|
dragOver,
|
|
6871
7050
|
onDragOver: handleDragOver,
|
|
6872
7051
|
onDragLeave: handleDragLeave,
|
|
6873
|
-
onDrop: handleDrop
|
|
7052
|
+
onDrop: handleDrop,
|
|
7053
|
+
isConnecting,
|
|
7054
|
+
hasExplicitThreadId: !!providedThreadId
|
|
6874
7055
|
});
|
|
6875
7056
|
return /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotChatConfigurationProvider, {
|
|
6876
7057
|
agentId: resolvedAgentId,
|
|
@@ -6905,7 +7086,10 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
6905
7086
|
},
|
|
6906
7087
|
children: transcriptionError
|
|
6907
7088
|
}),
|
|
6908
|
-
|
|
7089
|
+
/* @__PURE__ */ (0, react_jsx_runtime.jsx)(LastUserMessageContext.Provider, {
|
|
7090
|
+
value: lastUserMessageState,
|
|
7091
|
+
children: RenderedChatView
|
|
7092
|
+
})
|
|
6909
7093
|
]
|
|
6910
7094
|
})
|
|
6911
7095
|
});
|
|
@@ -9043,12 +9227,17 @@ const usePredictStateSubscription = (agent) => {
|
|
|
9043
9227
|
};
|
|
9044
9228
|
}, [agent, getSubscriber]);
|
|
9045
9229
|
};
|
|
9046
|
-
function
|
|
9047
|
-
const { copilotkit } = useCopilotKit();
|
|
9230
|
+
function CopilotListenersAgentSubscription() {
|
|
9048
9231
|
const resolvedAgentId = useCopilotChatConfiguration()?.agentId;
|
|
9049
|
-
const { setBannerError } = useToast();
|
|
9050
9232
|
const { agent } = useAgent({ agentId: resolvedAgentId });
|
|
9051
9233
|
usePredictStateSubscription(agent);
|
|
9234
|
+
return null;
|
|
9235
|
+
}
|
|
9236
|
+
function CopilotListeners() {
|
|
9237
|
+
const { copilotkit } = useCopilotKit();
|
|
9238
|
+
const { setBannerError } = useToast();
|
|
9239
|
+
const hasAgents = Object.keys(copilotkit.agents ?? {}).length > 0;
|
|
9240
|
+
const hasRuntime = copilotkit.runtimeUrl !== void 0;
|
|
9052
9241
|
(0, react.useEffect)(() => {
|
|
9053
9242
|
const subscription = copilotkit.subscribe({ onError: ({ error, code, context }) => {
|
|
9054
9243
|
if (error.name === "AbortError" || error.message === "Fetch is aborted" || error.message === "signal is aborted without reason" || error.message === "component unmounted" || !error.message) return;
|
|
@@ -9070,7 +9259,7 @@ function CopilotListeners() {
|
|
|
9070
9259
|
subscription.unsubscribe();
|
|
9071
9260
|
};
|
|
9072
9261
|
}, [copilotkit?.subscribe]);
|
|
9073
|
-
return null;
|
|
9262
|
+
return hasAgents || hasRuntime ? /* @__PURE__ */ (0, react_jsx_runtime.jsx)(CopilotListenersAgentSubscription, {}) : null;
|
|
9074
9263
|
}
|
|
9075
9264
|
|
|
9076
9265
|
//#endregion
|
|
@@ -10002,4 +10191,4 @@ Object.defineProperty(exports, 'useToast', {
|
|
|
10002
10191
|
return useToast;
|
|
10003
10192
|
}
|
|
10004
10193
|
});
|
|
10005
|
-
//# sourceMappingURL=copilotkit-
|
|
10194
|
+
//# sourceMappingURL=copilotkit-D5JT2Pu3.cjs.map
|