@copilotkitnext/react 0.0.18 → 0.0.19-threads-and-attachements.0
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/index.d.mts +196 -19
- package/dist/index.d.ts +196 -19
- package/dist/index.js +868 -220
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +874 -228
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +1 -1
- package/package.json +4 -4
package/dist/index.mjs
CHANGED
|
@@ -8,14 +8,14 @@ import {
|
|
|
8
8
|
useLayoutEffect,
|
|
9
9
|
forwardRef as forwardRef2,
|
|
10
10
|
useImperativeHandle as useImperativeHandle2,
|
|
11
|
-
useCallback,
|
|
11
|
+
useCallback as useCallback2,
|
|
12
12
|
useMemo as useMemo2
|
|
13
13
|
} from "react";
|
|
14
14
|
import { twMerge as twMerge3 } from "tailwind-merge";
|
|
15
15
|
import { Plus, Mic, ArrowUp, X, Check, Square } from "lucide-react";
|
|
16
16
|
|
|
17
17
|
// src/providers/CopilotChatConfigurationProvider.tsx
|
|
18
|
-
import { createContext, useContext, useMemo, useState } from "react";
|
|
18
|
+
import { createContext, useContext, useMemo, useState, useCallback } from "react";
|
|
19
19
|
import { DEFAULT_AGENT_ID, randomUUID } from "@copilotkitnext/shared";
|
|
20
20
|
import { jsx } from "react/jsx-runtime";
|
|
21
21
|
var CopilotChatDefaultLabels = {
|
|
@@ -51,15 +51,21 @@ var CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, i
|
|
|
51
51
|
[labels, parentConfig?.labels]
|
|
52
52
|
);
|
|
53
53
|
const resolvedAgentId = agentId ?? parentConfig?.agentId ?? DEFAULT_AGENT_ID;
|
|
54
|
-
const
|
|
55
|
-
if (threadId)
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
if (parentConfig?.threadId) {
|
|
59
|
-
return parentConfig.threadId;
|
|
60
|
-
}
|
|
54
|
+
const [internalThreadId, setInternalThreadId] = useState(() => {
|
|
55
|
+
if (threadId) return threadId;
|
|
56
|
+
if (parentConfig?.threadId) return parentConfig.threadId;
|
|
61
57
|
return randomUUID();
|
|
62
|
-
}
|
|
58
|
+
});
|
|
59
|
+
const resolvedThreadId = threadId ?? internalThreadId;
|
|
60
|
+
const handleSetThreadId = useCallback(
|
|
61
|
+
(newThreadId) => {
|
|
62
|
+
if (threadId === void 0) {
|
|
63
|
+
setInternalThreadId(newThreadId);
|
|
64
|
+
}
|
|
65
|
+
},
|
|
66
|
+
[threadId]
|
|
67
|
+
);
|
|
68
|
+
const resolvedSetThreadId = parentConfig?.setThreadId ?? handleSetThreadId;
|
|
63
69
|
const resolvedDefaultOpen = isModalDefaultOpen ?? parentConfig?.isModalDefaultOpen ?? true;
|
|
64
70
|
const [internalModalOpen, setInternalModalOpen] = useState(
|
|
65
71
|
parentConfig?.isModalOpen ?? resolvedDefaultOpen
|
|
@@ -71,6 +77,7 @@ var CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, i
|
|
|
71
77
|
labels: mergedLabels,
|
|
72
78
|
agentId: resolvedAgentId,
|
|
73
79
|
threadId: resolvedThreadId,
|
|
80
|
+
setThreadId: resolvedSetThreadId,
|
|
74
81
|
isModalOpen: resolvedIsModalOpen,
|
|
75
82
|
setModalOpen: resolvedSetModalOpen,
|
|
76
83
|
isModalDefaultOpen: resolvedDefaultOpen
|
|
@@ -79,6 +86,7 @@ var CopilotChatConfigurationProvider = ({ children, labels, agentId, threadId, i
|
|
|
79
86
|
mergedLabels,
|
|
80
87
|
resolvedAgentId,
|
|
81
88
|
resolvedThreadId,
|
|
89
|
+
resolvedSetThreadId,
|
|
82
90
|
resolvedIsModalOpen,
|
|
83
91
|
resolvedSetModalOpen,
|
|
84
92
|
resolvedDefaultOpen
|
|
@@ -664,7 +672,7 @@ function CopilotChatInput({
|
|
|
664
672
|
setCommandQuery(null);
|
|
665
673
|
}
|
|
666
674
|
}, [mode]);
|
|
667
|
-
const updateSlashState =
|
|
675
|
+
const updateSlashState = useCallback2(
|
|
668
676
|
(value2) => {
|
|
669
677
|
if (commandItems.length === 0) {
|
|
670
678
|
setCommandQuery((prev) => prev === null ? prev : null);
|
|
@@ -691,7 +699,7 @@ function CopilotChatInput({
|
|
|
691
699
|
onChange?.(nextValue);
|
|
692
700
|
updateSlashState(nextValue);
|
|
693
701
|
};
|
|
694
|
-
const clearInputValue =
|
|
702
|
+
const clearInputValue = useCallback2(() => {
|
|
695
703
|
if (!isControlled) {
|
|
696
704
|
setInternalValue("");
|
|
697
705
|
}
|
|
@@ -699,7 +707,7 @@ function CopilotChatInput({
|
|
|
699
707
|
onChange("");
|
|
700
708
|
}
|
|
701
709
|
}, [isControlled, onChange]);
|
|
702
|
-
const runCommand =
|
|
710
|
+
const runCommand = useCallback2(
|
|
703
711
|
(item) => {
|
|
704
712
|
clearInputValue();
|
|
705
713
|
item.action?.();
|
|
@@ -787,10 +795,7 @@ function CopilotChatInput({
|
|
|
787
795
|
onChange: handleChange,
|
|
788
796
|
onKeyDown: handleKeyDown,
|
|
789
797
|
autoFocus,
|
|
790
|
-
className: twMerge3(
|
|
791
|
-
"w-full py-3",
|
|
792
|
-
isExpanded ? "px-5" : "pr-5"
|
|
793
|
-
)
|
|
798
|
+
className: twMerge3("w-full py-3", isExpanded ? "px-5" : "pr-5")
|
|
794
799
|
});
|
|
795
800
|
const isProcessing = mode !== "transcribe" && isRunning;
|
|
796
801
|
const canSend = resolvedValue.trim().length > 0 && !!onSubmitMessage;
|
|
@@ -852,7 +857,7 @@ function CopilotChatInput({
|
|
|
852
857
|
inputRef.current.focus();
|
|
853
858
|
}
|
|
854
859
|
};
|
|
855
|
-
const ensureMeasurements =
|
|
860
|
+
const ensureMeasurements = useCallback2(() => {
|
|
856
861
|
const textarea = inputRef.current;
|
|
857
862
|
if (!textarea) {
|
|
858
863
|
return;
|
|
@@ -879,7 +884,7 @@ function CopilotChatInput({
|
|
|
879
884
|
textarea.style.height = previousHeight;
|
|
880
885
|
textarea.style.maxHeight = `${maxHeight}px`;
|
|
881
886
|
}, []);
|
|
882
|
-
const adjustTextareaHeight =
|
|
887
|
+
const adjustTextareaHeight = useCallback2(() => {
|
|
883
888
|
const textarea = inputRef.current;
|
|
884
889
|
if (!textarea) {
|
|
885
890
|
return 0;
|
|
@@ -900,7 +905,7 @@ function CopilotChatInput({
|
|
|
900
905
|
}
|
|
901
906
|
return scrollHeight;
|
|
902
907
|
}, [ensureMeasurements]);
|
|
903
|
-
const updateLayout =
|
|
908
|
+
const updateLayout = useCallback2((nextLayout) => {
|
|
904
909
|
setLayout((prev) => {
|
|
905
910
|
if (prev === nextLayout) {
|
|
906
911
|
return prev;
|
|
@@ -909,7 +914,7 @@ function CopilotChatInput({
|
|
|
909
914
|
return nextLayout;
|
|
910
915
|
});
|
|
911
916
|
}, []);
|
|
912
|
-
const evaluateLayout =
|
|
917
|
+
const evaluateLayout = useCallback2(() => {
|
|
913
918
|
if (mode !== "input") {
|
|
914
919
|
updateLayout("compact");
|
|
915
920
|
return;
|
|
@@ -1031,10 +1036,10 @@ function CopilotChatInput({
|
|
|
1031
1036
|
if (!slashMenuVisible || slashHighlightIndex < 0) {
|
|
1032
1037
|
return;
|
|
1033
1038
|
}
|
|
1034
|
-
const active = slashMenuRef.current?.querySelector(
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
|
|
1039
|
+
const active = slashMenuRef.current?.querySelector(`[data-slash-index="${slashHighlightIndex}"]`);
|
|
1040
|
+
if (active && typeof active.scrollIntoView === "function") {
|
|
1041
|
+
active.scrollIntoView({ block: "nearest" });
|
|
1042
|
+
}
|
|
1038
1043
|
}, [slashMenuVisible, slashHighlightIndex]);
|
|
1039
1044
|
const slashMenu = slashMenuVisible ? /* @__PURE__ */ jsx6(
|
|
1040
1045
|
"div",
|
|
@@ -1105,11 +1110,7 @@ function CopilotChatInput({
|
|
|
1105
1110
|
"div",
|
|
1106
1111
|
{
|
|
1107
1112
|
ref: addButtonContainerRef,
|
|
1108
|
-
className: twMerge3(
|
|
1109
|
-
"flex items-center",
|
|
1110
|
-
isExpanded ? "row-start-2" : "row-start-1",
|
|
1111
|
-
"col-start-1"
|
|
1112
|
-
),
|
|
1113
|
+
className: twMerge3("flex items-center", isExpanded ? "row-start-2" : "row-start-1", "col-start-1"),
|
|
1113
1114
|
children: BoundAddMenuButton
|
|
1114
1115
|
}
|
|
1115
1116
|
),
|
|
@@ -1237,7 +1238,7 @@ function CopilotChatInput({
|
|
|
1237
1238
|
}
|
|
1238
1239
|
return items;
|
|
1239
1240
|
}, [onAddFile, toolsMenu, labels.chatInputToolbarAddButtonLabel]);
|
|
1240
|
-
const renderMenuItems =
|
|
1241
|
+
const renderMenuItems = useCallback2(
|
|
1241
1242
|
(items) => items.map((item, index) => {
|
|
1242
1243
|
if (item === "-") {
|
|
1243
1244
|
return /* @__PURE__ */ jsx6(DropdownMenuSeparator, {}, `separator-${index}`);
|
|
@@ -1286,7 +1287,9 @@ function CopilotChatInput({
|
|
|
1286
1287
|
if (!textarea) return;
|
|
1287
1288
|
const handleFocus = () => {
|
|
1288
1289
|
setTimeout(() => {
|
|
1289
|
-
textarea.scrollIntoView
|
|
1290
|
+
if (typeof textarea.scrollIntoView === "function") {
|
|
1291
|
+
textarea.scrollIntoView({ behavior: "smooth", block: "nearest" });
|
|
1292
|
+
}
|
|
1290
1293
|
}, 300);
|
|
1291
1294
|
};
|
|
1292
1295
|
textarea.addEventListener("focus", handleFocus);
|
|
@@ -1328,7 +1331,7 @@ CopilotChatInput.AddMenuButton.displayName = "CopilotChatInput.AddMenuButton";
|
|
|
1328
1331
|
var CopilotChatInput_default = CopilotChatInput;
|
|
1329
1332
|
|
|
1330
1333
|
// src/components/chat/CopilotChatAssistantMessage.tsx
|
|
1331
|
-
import { useState as
|
|
1334
|
+
import { useState as useState8 } from "react";
|
|
1332
1335
|
import {
|
|
1333
1336
|
Copy,
|
|
1334
1337
|
Check as Check2,
|
|
@@ -1342,7 +1345,7 @@ import "katex/dist/katex.min.css";
|
|
|
1342
1345
|
import { Streamdown } from "streamdown";
|
|
1343
1346
|
|
|
1344
1347
|
// src/hooks/use-render-tool-call.tsx
|
|
1345
|
-
import { useCallback as
|
|
1348
|
+
import { useCallback as useCallback4, useEffect as useEffect5, useState as useState4, useSyncExternalStore } from "react";
|
|
1346
1349
|
import { ToolCallStatus } from "@copilotkitnext/core";
|
|
1347
1350
|
|
|
1348
1351
|
// src/providers/CopilotKitProvider.tsx
|
|
@@ -1353,7 +1356,8 @@ import {
|
|
|
1353
1356
|
useEffect as useEffect4,
|
|
1354
1357
|
useReducer,
|
|
1355
1358
|
useRef as useRef4,
|
|
1356
|
-
useState as useState3
|
|
1359
|
+
useState as useState3,
|
|
1360
|
+
useCallback as useCallback3
|
|
1357
1361
|
} from "react";
|
|
1358
1362
|
import { z } from "zod";
|
|
1359
1363
|
|
|
@@ -1400,16 +1404,15 @@ var CopilotKitCoreReact = class extends CopilotKitCore {
|
|
|
1400
1404
|
// src/components/CopilotKitInspector.tsx
|
|
1401
1405
|
import * as React4 from "react";
|
|
1402
1406
|
import { createComponent } from "@lit-labs/react";
|
|
1403
|
-
import
|
|
1404
|
-
WEB_INSPECTOR_TAG,
|
|
1405
|
-
WebInspectorElement,
|
|
1406
|
-
defineWebInspector
|
|
1407
|
-
} from "@copilotkitnext/web-inspector";
|
|
1407
|
+
import * as WebInspectorModule from "@copilotkitnext/web-inspector";
|
|
1408
1408
|
import { jsx as jsx7 } from "react/jsx-runtime";
|
|
1409
|
-
|
|
1409
|
+
var WEB_INSPECTOR_TAG2 = WebInspectorModule.WEB_INSPECTOR_TAG;
|
|
1410
|
+
var defineWebInspector2 = WebInspectorModule.defineWebInspector;
|
|
1411
|
+
var WebInspectorElementClass = WebInspectorModule.WebInspectorElement;
|
|
1412
|
+
defineWebInspector2();
|
|
1410
1413
|
var CopilotKitInspectorBase = createComponent({
|
|
1411
|
-
tagName:
|
|
1412
|
-
elementClass:
|
|
1414
|
+
tagName: WEB_INSPECTOR_TAG2,
|
|
1415
|
+
elementClass: WebInspectorElementClass,
|
|
1413
1416
|
react: React4
|
|
1414
1417
|
});
|
|
1415
1418
|
var CopilotKitInspector = React4.forwardRef(
|
|
@@ -1435,7 +1438,10 @@ CopilotKitInspector.displayName = "CopilotKitInspector";
|
|
|
1435
1438
|
// src/providers/CopilotKitProvider.tsx
|
|
1436
1439
|
import { jsx as jsx8, jsxs as jsxs4 } from "react/jsx-runtime";
|
|
1437
1440
|
var CopilotKitContext = createContext2({
|
|
1438
|
-
copilotkit: null
|
|
1441
|
+
copilotkit: null,
|
|
1442
|
+
setResourceId: () => {
|
|
1443
|
+
throw new Error("useCopilotKit must be used within CopilotKitProvider");
|
|
1444
|
+
}
|
|
1439
1445
|
});
|
|
1440
1446
|
function useStableArrayProp(prop, warningMessage, isMeaningfulChange) {
|
|
1441
1447
|
const empty = useMemo3(() => [], []);
|
|
@@ -1453,6 +1459,7 @@ var CopilotKitProvider = ({
|
|
|
1453
1459
|
runtimeUrl,
|
|
1454
1460
|
headers = {},
|
|
1455
1461
|
properties = {},
|
|
1462
|
+
resourceId,
|
|
1456
1463
|
agents__unsafe_dev_only: agents = {},
|
|
1457
1464
|
renderToolCalls,
|
|
1458
1465
|
renderCustomMessages,
|
|
@@ -1560,6 +1567,7 @@ var CopilotKitProvider = ({
|
|
|
1560
1567
|
runtimeUrl,
|
|
1561
1568
|
headers,
|
|
1562
1569
|
properties,
|
|
1570
|
+
resourceId,
|
|
1563
1571
|
agents__unsafe_dev_only: agents,
|
|
1564
1572
|
tools: allTools,
|
|
1565
1573
|
renderToolCalls: allRenderToolCalls,
|
|
@@ -1582,13 +1590,36 @@ var CopilotKitProvider = ({
|
|
|
1582
1590
|
copilotkit.setRuntimeUrl(runtimeUrl);
|
|
1583
1591
|
copilotkit.setHeaders(headers);
|
|
1584
1592
|
copilotkit.setProperties(properties);
|
|
1593
|
+
copilotkit.setResourceId(resourceId);
|
|
1585
1594
|
copilotkit.setAgents__unsafe_dev_only(agents);
|
|
1586
|
-
}, [runtimeUrl, headers, properties, agents]);
|
|
1595
|
+
}, [runtimeUrl, headers, properties, resourceId, agents]);
|
|
1596
|
+
useEffect4(() => {
|
|
1597
|
+
if (typeof window === "undefined") {
|
|
1598
|
+
return;
|
|
1599
|
+
}
|
|
1600
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
1601
|
+
if (isProduction && !resourceId) {
|
|
1602
|
+
console.error(
|
|
1603
|
+
"CopilotKit Security Warning: No resourceId set in production.\nAll threads will be globally accessible. Set the resourceId prop:\n<CopilotKitProvider resourceId={userId}>\nLearn more: https://docs.copilotkit.ai/security/resource-scoping"
|
|
1604
|
+
);
|
|
1605
|
+
} else if (!isProduction && !resourceId) {
|
|
1606
|
+
console.warn(
|
|
1607
|
+
"CopilotKit: No resourceId set. All threads are globally accessible.\nThis is fine for development, but add resourceId for production:\n<CopilotKitProvider resourceId={userId}>"
|
|
1608
|
+
);
|
|
1609
|
+
}
|
|
1610
|
+
}, [resourceId]);
|
|
1611
|
+
const setResourceId = useCallback3(
|
|
1612
|
+
(newResourceId) => {
|
|
1613
|
+
copilotkit.setResourceId(newResourceId);
|
|
1614
|
+
},
|
|
1615
|
+
[copilotkit]
|
|
1616
|
+
);
|
|
1587
1617
|
return /* @__PURE__ */ jsxs4(
|
|
1588
1618
|
CopilotKitContext.Provider,
|
|
1589
1619
|
{
|
|
1590
1620
|
value: {
|
|
1591
|
-
copilotkit
|
|
1621
|
+
copilotkit,
|
|
1622
|
+
setResourceId
|
|
1592
1623
|
},
|
|
1593
1624
|
children: [
|
|
1594
1625
|
children,
|
|
@@ -1607,6 +1638,9 @@ var useCopilotKit = () => {
|
|
|
1607
1638
|
const unsubscribe = context.copilotkit.subscribe({
|
|
1608
1639
|
onRuntimeConnectionStatusChanged: () => {
|
|
1609
1640
|
forceUpdate();
|
|
1641
|
+
},
|
|
1642
|
+
onResourceIdChanged: () => {
|
|
1643
|
+
forceUpdate();
|
|
1610
1644
|
}
|
|
1611
1645
|
});
|
|
1612
1646
|
return () => {
|
|
@@ -1655,7 +1689,7 @@ function useRenderToolCall() {
|
|
|
1655
1689
|
});
|
|
1656
1690
|
return () => unsubscribe();
|
|
1657
1691
|
}, [copilotkit]);
|
|
1658
|
-
const renderToolCall =
|
|
1692
|
+
const renderToolCall = useCallback4(
|
|
1659
1693
|
({
|
|
1660
1694
|
toolCall,
|
|
1661
1695
|
toolMessage
|
|
@@ -1735,33 +1769,38 @@ function useRenderCustomMessages() {
|
|
|
1735
1769
|
if (!agent) {
|
|
1736
1770
|
throw new Error("Agent not found");
|
|
1737
1771
|
}
|
|
1738
|
-
const messagesIdsInRun = agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === runId).map((msg) => msg.id);
|
|
1772
|
+
const messagesIdsInRun = runId ? agent.messages.filter((msg) => copilotkit.getRunIdForMessage(agentId, threadId, msg.id) === runId).map((msg) => msg.id) : [];
|
|
1739
1773
|
const messageIndex = agent.messages.findIndex((msg) => msg.id === message.id) ?? 0;
|
|
1740
|
-
const messageIndexInRun = Math.
|
|
1774
|
+
const messageIndexInRun = Math.max(messagesIdsInRun.indexOf(message.id), 0);
|
|
1741
1775
|
const numberOfMessagesInRun = messagesIdsInRun.length;
|
|
1742
|
-
const stateSnapshot = copilotkit.getStateByRun(agentId, threadId, runId);
|
|
1776
|
+
const stateSnapshot = runId ? copilotkit.getStateByRun(agentId, threadId, runId) : void 0;
|
|
1743
1777
|
let result = null;
|
|
1744
1778
|
for (const renderer of customMessageRenderers) {
|
|
1745
1779
|
if (!renderer.render) {
|
|
1746
1780
|
continue;
|
|
1747
1781
|
}
|
|
1748
|
-
|
|
1749
|
-
|
|
1750
|
-
|
|
1751
|
-
|
|
1752
|
-
|
|
1753
|
-
|
|
1754
|
-
|
|
1755
|
-
|
|
1756
|
-
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
|
|
1760
|
-
|
|
1761
|
-
|
|
1762
|
-
|
|
1763
|
-
|
|
1764
|
-
|
|
1782
|
+
try {
|
|
1783
|
+
const Component = renderer.render;
|
|
1784
|
+
result = /* @__PURE__ */ jsx10(
|
|
1785
|
+
Component,
|
|
1786
|
+
{
|
|
1787
|
+
message,
|
|
1788
|
+
position,
|
|
1789
|
+
runId: runId ?? "",
|
|
1790
|
+
messageIndex,
|
|
1791
|
+
messageIndexInRun,
|
|
1792
|
+
numberOfMessagesInRun,
|
|
1793
|
+
agentId,
|
|
1794
|
+
stateSnapshot
|
|
1795
|
+
},
|
|
1796
|
+
`${runId ?? "no-run"}-${message.id}-${position}`
|
|
1797
|
+
);
|
|
1798
|
+
if (result) {
|
|
1799
|
+
break;
|
|
1800
|
+
}
|
|
1801
|
+
} catch (error) {
|
|
1802
|
+
console.error("Error rendering custom message:", error);
|
|
1803
|
+
continue;
|
|
1765
1804
|
}
|
|
1766
1805
|
}
|
|
1767
1806
|
return result;
|
|
@@ -1804,7 +1843,7 @@ function useFrontendTool(tool) {
|
|
|
1804
1843
|
}
|
|
1805
1844
|
|
|
1806
1845
|
// src/hooks/use-human-in-the-loop.tsx
|
|
1807
|
-
import { useState as useState5, useCallback as
|
|
1846
|
+
import { useState as useState5, useCallback as useCallback5, useRef as useRef5, useEffect as useEffect7 } from "react";
|
|
1808
1847
|
import React7 from "react";
|
|
1809
1848
|
function useHumanInTheLoop(tool) {
|
|
1810
1849
|
const { copilotkit } = useCopilotKit();
|
|
@@ -1814,20 +1853,20 @@ function useHumanInTheLoop(tool) {
|
|
|
1814
1853
|
const statusRef = useRef5(status);
|
|
1815
1854
|
const resolvePromiseRef = useRef5(null);
|
|
1816
1855
|
statusRef.current = status;
|
|
1817
|
-
const respond =
|
|
1856
|
+
const respond = useCallback5(async (result) => {
|
|
1818
1857
|
if (resolvePromiseRef.current) {
|
|
1819
1858
|
resolvePromiseRef.current(result);
|
|
1820
1859
|
setStatus("complete");
|
|
1821
1860
|
resolvePromiseRef.current = null;
|
|
1822
1861
|
}
|
|
1823
1862
|
}, []);
|
|
1824
|
-
const handler =
|
|
1863
|
+
const handler = useCallback5(async () => {
|
|
1825
1864
|
return new Promise((resolve) => {
|
|
1826
1865
|
setStatus("executing");
|
|
1827
1866
|
resolvePromiseRef.current = resolve;
|
|
1828
1867
|
});
|
|
1829
1868
|
}, []);
|
|
1830
|
-
const RenderComponent =
|
|
1869
|
+
const RenderComponent = useCallback5(
|
|
1831
1870
|
(props) => {
|
|
1832
1871
|
const ToolComponent = tool.render;
|
|
1833
1872
|
const currentStatus = statusRef.current;
|
|
@@ -1890,18 +1929,10 @@ function useAgent({ agentId, updates } = {}) {
|
|
|
1890
1929
|
agentId ??= DEFAULT_AGENT_ID3;
|
|
1891
1930
|
const { copilotkit } = useCopilotKit();
|
|
1892
1931
|
const [, forceUpdate] = useReducer2((x) => x + 1, 0);
|
|
1893
|
-
const updateFlags = useMemo4(
|
|
1894
|
-
() => updates ?? ALL_UPDATES,
|
|
1895
|
-
[JSON.stringify(updates)]
|
|
1896
|
-
);
|
|
1932
|
+
const updateFlags = useMemo4(() => updates ?? ALL_UPDATES, [JSON.stringify(updates)]);
|
|
1897
1933
|
const agent = useMemo4(() => {
|
|
1898
1934
|
return copilotkit.getAgent(agentId);
|
|
1899
|
-
}, [
|
|
1900
|
-
agentId,
|
|
1901
|
-
copilotkit.agents,
|
|
1902
|
-
copilotkit.runtimeConnectionStatus,
|
|
1903
|
-
copilotkit
|
|
1904
|
-
]);
|
|
1935
|
+
}, [agentId, copilotkit.agents, copilotkit.runtimeConnectionStatus, copilotkit]);
|
|
1905
1936
|
useEffect8(() => {
|
|
1906
1937
|
if (!agent) {
|
|
1907
1938
|
return;
|
|
@@ -1954,7 +1985,7 @@ function useAgentContext(context) {
|
|
|
1954
1985
|
}
|
|
1955
1986
|
|
|
1956
1987
|
// src/hooks/use-suggestions.tsx
|
|
1957
|
-
import { useCallback as
|
|
1988
|
+
import { useCallback as useCallback6, useEffect as useEffect10, useMemo as useMemo5, useState as useState6 } from "react";
|
|
1958
1989
|
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID4 } from "@copilotkitnext/shared";
|
|
1959
1990
|
function useSuggestions({ agentId } = {}) {
|
|
1960
1991
|
const { copilotkit } = useCopilotKit();
|
|
@@ -2003,10 +2034,10 @@ function useSuggestions({ agentId } = {}) {
|
|
|
2003
2034
|
unsubscribe();
|
|
2004
2035
|
};
|
|
2005
2036
|
}, [copilotkit, resolvedAgentId]);
|
|
2006
|
-
const reloadSuggestions =
|
|
2037
|
+
const reloadSuggestions = useCallback6(() => {
|
|
2007
2038
|
copilotkit.reloadSuggestions(resolvedAgentId);
|
|
2008
2039
|
}, [copilotkit, resolvedAgentId]);
|
|
2009
|
-
const clearSuggestions =
|
|
2040
|
+
const clearSuggestions = useCallback6(() => {
|
|
2010
2041
|
copilotkit.clearSuggestions(resolvedAgentId);
|
|
2011
2042
|
}, [copilotkit, resolvedAgentId]);
|
|
2012
2043
|
return {
|
|
@@ -2018,7 +2049,7 @@ function useSuggestions({ agentId } = {}) {
|
|
|
2018
2049
|
}
|
|
2019
2050
|
|
|
2020
2051
|
// src/hooks/use-configure-suggestions.tsx
|
|
2021
|
-
import { useCallback as
|
|
2052
|
+
import { useCallback as useCallback7, useEffect as useEffect11, useMemo as useMemo6, useRef as useRef6 } from "react";
|
|
2022
2053
|
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID5 } from "@copilotkitnext/shared";
|
|
2023
2054
|
var EMPTY_DEPS = [];
|
|
2024
2055
|
function useConfigureSuggestions(config, options) {
|
|
@@ -2075,7 +2106,7 @@ function useConfigureSuggestions(config, options) {
|
|
|
2075
2106
|
return consumer;
|
|
2076
2107
|
}, [normalizedConfig, resolvedConsumerAgentId]);
|
|
2077
2108
|
const isGlobalConfig = rawConsumerAgentId === void 0 || rawConsumerAgentId === "*";
|
|
2078
|
-
const requestReload =
|
|
2109
|
+
const requestReload = useCallback7(() => {
|
|
2079
2110
|
if (!normalizedConfig) {
|
|
2080
2111
|
return;
|
|
2081
2112
|
}
|
|
@@ -2137,6 +2168,135 @@ function normalizeStaticSuggestions(suggestions) {
|
|
|
2137
2168
|
}));
|
|
2138
2169
|
}
|
|
2139
2170
|
|
|
2171
|
+
// src/hooks/use-threads.tsx
|
|
2172
|
+
import { useCallback as useCallback8, useEffect as useEffect12, useState as useState7 } from "react";
|
|
2173
|
+
function useThreads(options = {}) {
|
|
2174
|
+
const { limit = 50, autoFetch = true } = options;
|
|
2175
|
+
const { copilotkit: core } = useCopilotKit();
|
|
2176
|
+
const chatConfig = useCopilotChatConfiguration();
|
|
2177
|
+
const [threads, setThreads] = useState7([]);
|
|
2178
|
+
const [total, setTotal] = useState7(0);
|
|
2179
|
+
const [isLoading, setIsLoading] = useState7(false);
|
|
2180
|
+
const [error, setError] = useState7(null);
|
|
2181
|
+
const fetchThreads = useCallback8(
|
|
2182
|
+
async (offset = 0) => {
|
|
2183
|
+
if (!core) {
|
|
2184
|
+
return;
|
|
2185
|
+
}
|
|
2186
|
+
setIsLoading(true);
|
|
2187
|
+
setError(null);
|
|
2188
|
+
try {
|
|
2189
|
+
const result = await core.listThreads({ limit, offset });
|
|
2190
|
+
setThreads(result.threads);
|
|
2191
|
+
setTotal(result.total);
|
|
2192
|
+
} catch (err) {
|
|
2193
|
+
const error2 = err instanceof Error ? err : new Error("Failed to fetch threads");
|
|
2194
|
+
setError(error2);
|
|
2195
|
+
console.error("Error fetching threads:", error2);
|
|
2196
|
+
} finally {
|
|
2197
|
+
setIsLoading(false);
|
|
2198
|
+
}
|
|
2199
|
+
},
|
|
2200
|
+
[core, limit]
|
|
2201
|
+
);
|
|
2202
|
+
const getThreadMetadata = useCallback8(
|
|
2203
|
+
async (threadId) => {
|
|
2204
|
+
if (!core) {
|
|
2205
|
+
throw new Error("CopilotKit core not initialized");
|
|
2206
|
+
}
|
|
2207
|
+
try {
|
|
2208
|
+
return await core.getThreadMetadata(threadId);
|
|
2209
|
+
} catch (err) {
|
|
2210
|
+
const error2 = err instanceof Error ? err : new Error("Failed to get thread metadata");
|
|
2211
|
+
console.error("Error getting thread metadata:", error2);
|
|
2212
|
+
throw error2;
|
|
2213
|
+
}
|
|
2214
|
+
},
|
|
2215
|
+
[core]
|
|
2216
|
+
);
|
|
2217
|
+
const refresh = useCallback8(() => fetchThreads(0), [fetchThreads]);
|
|
2218
|
+
const addOptimisticThread = useCallback8((threadId) => {
|
|
2219
|
+
const newThread = {
|
|
2220
|
+
threadId,
|
|
2221
|
+
createdAt: Date.now(),
|
|
2222
|
+
lastActivityAt: Date.now(),
|
|
2223
|
+
isRunning: false,
|
|
2224
|
+
messageCount: 0,
|
|
2225
|
+
firstMessage: void 0
|
|
2226
|
+
};
|
|
2227
|
+
setThreads((prev) => [newThread, ...prev]);
|
|
2228
|
+
setTotal((prev) => prev + 1);
|
|
2229
|
+
}, []);
|
|
2230
|
+
const deleteThread = useCallback8(
|
|
2231
|
+
async (threadId) => {
|
|
2232
|
+
if (!core) {
|
|
2233
|
+
throw new Error("CopilotKit core not initialized");
|
|
2234
|
+
}
|
|
2235
|
+
const originalThreads = threads;
|
|
2236
|
+
const originalTotal = total;
|
|
2237
|
+
const threadIndex = threads.findIndex((t) => t.threadId === threadId);
|
|
2238
|
+
const deletedThread = threadIndex >= 0 ? threads[threadIndex] : null;
|
|
2239
|
+
if (threadIndex >= 0) {
|
|
2240
|
+
setThreads((prev) => prev.filter((t) => t.threadId !== threadId));
|
|
2241
|
+
setTotal((prev) => prev - 1);
|
|
2242
|
+
}
|
|
2243
|
+
try {
|
|
2244
|
+
await core.deleteThread(threadId);
|
|
2245
|
+
await fetchThreads();
|
|
2246
|
+
} catch (err) {
|
|
2247
|
+
if (deletedThread && threadIndex >= 0) {
|
|
2248
|
+
setThreads((prev) => {
|
|
2249
|
+
const newThreads = [...prev];
|
|
2250
|
+
newThreads.splice(threadIndex, 0, deletedThread);
|
|
2251
|
+
return newThreads;
|
|
2252
|
+
});
|
|
2253
|
+
setTotal(originalTotal);
|
|
2254
|
+
} else {
|
|
2255
|
+
setThreads(originalThreads);
|
|
2256
|
+
setTotal(originalTotal);
|
|
2257
|
+
}
|
|
2258
|
+
const error2 = err instanceof Error ? err : new Error("Failed to delete thread");
|
|
2259
|
+
console.error("Error deleting thread:", error2);
|
|
2260
|
+
throw error2;
|
|
2261
|
+
}
|
|
2262
|
+
},
|
|
2263
|
+
[core, fetchThreads, threads, total]
|
|
2264
|
+
);
|
|
2265
|
+
useEffect12(() => {
|
|
2266
|
+
if (autoFetch && core) {
|
|
2267
|
+
void fetchThreads();
|
|
2268
|
+
}
|
|
2269
|
+
}, [autoFetch, core, fetchThreads]);
|
|
2270
|
+
return {
|
|
2271
|
+
threads,
|
|
2272
|
+
total,
|
|
2273
|
+
isLoading,
|
|
2274
|
+
error,
|
|
2275
|
+
fetchThreads,
|
|
2276
|
+
getThreadMetadata,
|
|
2277
|
+
refresh,
|
|
2278
|
+
addOptimisticThread,
|
|
2279
|
+
deleteThread,
|
|
2280
|
+
currentThreadId: chatConfig?.threadId
|
|
2281
|
+
};
|
|
2282
|
+
}
|
|
2283
|
+
|
|
2284
|
+
// src/hooks/use-thread-switcher.tsx
|
|
2285
|
+
import { useCallback as useCallback9 } from "react";
|
|
2286
|
+
function useThreadSwitch() {
|
|
2287
|
+
const config = useCopilotChatConfiguration();
|
|
2288
|
+
const switchThread = useCallback9(
|
|
2289
|
+
(threadId) => {
|
|
2290
|
+
config?.setThreadId?.(threadId);
|
|
2291
|
+
},
|
|
2292
|
+
[config]
|
|
2293
|
+
);
|
|
2294
|
+
return {
|
|
2295
|
+
switchThread,
|
|
2296
|
+
currentThreadId: config?.threadId
|
|
2297
|
+
};
|
|
2298
|
+
}
|
|
2299
|
+
|
|
2140
2300
|
// src/components/chat/CopilotChatToolCallsView.tsx
|
|
2141
2301
|
import React8 from "react";
|
|
2142
2302
|
import { Fragment as Fragment2, jsx as jsx11 } from "react/jsx-runtime";
|
|
@@ -2148,14 +2308,14 @@ function CopilotChatToolCallsView({
|
|
|
2148
2308
|
if (!message.toolCalls || message.toolCalls.length === 0) {
|
|
2149
2309
|
return null;
|
|
2150
2310
|
}
|
|
2151
|
-
return /* @__PURE__ */ jsx11(Fragment2, { children: message.toolCalls.map((toolCall) => {
|
|
2311
|
+
return /* @__PURE__ */ jsx11(Fragment2, { children: message.toolCalls.map((toolCall, index) => {
|
|
2152
2312
|
const toolMessage = messages.find(
|
|
2153
2313
|
(m) => m.role === "tool" && m.toolCallId === toolCall.id
|
|
2154
2314
|
);
|
|
2155
2315
|
return /* @__PURE__ */ jsx11(React8.Fragment, { children: renderToolCall({
|
|
2156
2316
|
toolCall,
|
|
2157
2317
|
toolMessage
|
|
2158
|
-
}) }, toolCall.id);
|
|
2318
|
+
}) }, `${message.id}-${toolCall.id ?? index}-${index}`);
|
|
2159
2319
|
}) });
|
|
2160
2320
|
}
|
|
2161
2321
|
var CopilotChatToolCallsView_default = CopilotChatToolCallsView;
|
|
@@ -2330,7 +2490,7 @@ function CopilotChatAssistantMessage({
|
|
|
2330
2490
|
CopilotChatAssistantMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
2331
2491
|
const config = useCopilotChatConfiguration();
|
|
2332
2492
|
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
2333
|
-
const [copied, setCopied] =
|
|
2493
|
+
const [copied, setCopied] = useState8(false);
|
|
2334
2494
|
const handleClick = (event) => {
|
|
2335
2495
|
setCopied(true);
|
|
2336
2496
|
setTimeout(() => setCopied(false), 2e3);
|
|
@@ -2408,9 +2568,14 @@ CopilotChatAssistantMessage.RegenerateButton.displayName = "CopilotChatAssistant
|
|
|
2408
2568
|
var CopilotChatAssistantMessage_default = CopilotChatAssistantMessage;
|
|
2409
2569
|
|
|
2410
2570
|
// src/components/chat/CopilotChatUserMessage.tsx
|
|
2411
|
-
import { useState as
|
|
2571
|
+
import { useState as useState9 } from "react";
|
|
2412
2572
|
import { Copy as Copy2, Check as Check3, Edit, ChevronLeft, ChevronRight } from "lucide-react";
|
|
2413
2573
|
import { twMerge as twMerge5 } from "tailwind-merge";
|
|
2574
|
+
import {
|
|
2575
|
+
getUserMessageBinaryContents,
|
|
2576
|
+
getUserMessageTextContent,
|
|
2577
|
+
normalizeUserMessageContents
|
|
2578
|
+
} from "@copilotkitnext/shared";
|
|
2414
2579
|
import { Fragment as Fragment4, jsx as jsx13, jsxs as jsxs6 } from "react/jsx-runtime";
|
|
2415
2580
|
function CopilotChatUserMessage({
|
|
2416
2581
|
message,
|
|
@@ -2432,7 +2597,8 @@ function CopilotChatUserMessage({
|
|
|
2432
2597
|
messageRenderer,
|
|
2433
2598
|
CopilotChatUserMessage.MessageRenderer,
|
|
2434
2599
|
{
|
|
2435
|
-
content: message.content
|
|
2600
|
+
content: getUserMessageTextContent(message.content),
|
|
2601
|
+
contents: normalizeUserMessageContents(message.content)
|
|
2436
2602
|
}
|
|
2437
2603
|
);
|
|
2438
2604
|
const BoundCopyButton = renderSlot(
|
|
@@ -2440,9 +2606,10 @@ function CopilotChatUserMessage({
|
|
|
2440
2606
|
CopilotChatUserMessage.CopyButton,
|
|
2441
2607
|
{
|
|
2442
2608
|
onClick: async () => {
|
|
2443
|
-
|
|
2609
|
+
const textContent = getUserMessageTextContent(message.content);
|
|
2610
|
+
if (textContent.trim().length > 0) {
|
|
2444
2611
|
try {
|
|
2445
|
-
await navigator.clipboard.writeText(
|
|
2612
|
+
await navigator.clipboard.writeText(textContent);
|
|
2446
2613
|
} catch (err) {
|
|
2447
2614
|
console.error("Failed to copy message:", err);
|
|
2448
2615
|
}
|
|
@@ -2511,16 +2678,33 @@ function CopilotChatUserMessage({
|
|
|
2511
2678
|
children
|
|
2512
2679
|
}
|
|
2513
2680
|
);
|
|
2514
|
-
CopilotChatUserMessage2.MessageRenderer = ({
|
|
2515
|
-
|
|
2516
|
-
|
|
2517
|
-
|
|
2518
|
-
|
|
2519
|
-
|
|
2520
|
-
|
|
2521
|
-
|
|
2522
|
-
|
|
2523
|
-
|
|
2681
|
+
CopilotChatUserMessage2.MessageRenderer = ({
|
|
2682
|
+
content,
|
|
2683
|
+
contents = [],
|
|
2684
|
+
className
|
|
2685
|
+
}) => {
|
|
2686
|
+
const attachments = getUserMessageBinaryContents(contents);
|
|
2687
|
+
const hasText = content.trim().length > 0;
|
|
2688
|
+
return /* @__PURE__ */ jsxs6(
|
|
2689
|
+
"div",
|
|
2690
|
+
{
|
|
2691
|
+
className: twMerge5(
|
|
2692
|
+
"prose dark:prose-invert bg-muted relative max-w-[80%] rounded-[18px] px-4 py-1.5 data-[multiline]:py-3 inline-block whitespace-pre-wrap",
|
|
2693
|
+
className
|
|
2694
|
+
),
|
|
2695
|
+
children: [
|
|
2696
|
+
hasText && /* @__PURE__ */ jsx13("span", { children: content }),
|
|
2697
|
+
attachments.length > 0 && /* @__PURE__ */ jsx13("div", { className: twMerge5(hasText ? "mt-3 flex flex-col gap-2" : "flex flex-col gap-2"), children: attachments.map((attachment, index) => /* @__PURE__ */ jsx13(
|
|
2698
|
+
AttachmentPreview,
|
|
2699
|
+
{
|
|
2700
|
+
attachment
|
|
2701
|
+
},
|
|
2702
|
+
attachment.id ?? attachment.url ?? attachment.filename ?? index
|
|
2703
|
+
)) })
|
|
2704
|
+
]
|
|
2705
|
+
}
|
|
2706
|
+
);
|
|
2707
|
+
};
|
|
2524
2708
|
CopilotChatUserMessage2.Toolbar = ({
|
|
2525
2709
|
className,
|
|
2526
2710
|
...props
|
|
@@ -2553,7 +2737,7 @@ function CopilotChatUserMessage({
|
|
|
2553
2737
|
CopilotChatUserMessage2.CopyButton = ({ className, title, onClick, ...props }) => {
|
|
2554
2738
|
const config = useCopilotChatConfiguration();
|
|
2555
2739
|
const labels = config?.labels ?? CopilotChatDefaultLabels;
|
|
2556
|
-
const [copied, setCopied] =
|
|
2740
|
+
const [copied, setCopied] = useState9(false);
|
|
2557
2741
|
const handleClick = (event) => {
|
|
2558
2742
|
setCopied(true);
|
|
2559
2743
|
setTimeout(() => setCopied(false), 2e3);
|
|
@@ -2637,6 +2821,47 @@ function CopilotChatUserMessage({
|
|
|
2637
2821
|
] });
|
|
2638
2822
|
};
|
|
2639
2823
|
})(CopilotChatUserMessage || (CopilotChatUserMessage = {}));
|
|
2824
|
+
var AttachmentPreview = ({ attachment }) => {
|
|
2825
|
+
const source = resolveAttachmentSource(attachment);
|
|
2826
|
+
const isImage = attachment.mimeType.startsWith("image/");
|
|
2827
|
+
const label = attachment.filename ?? attachment.id ?? attachment.mimeType;
|
|
2828
|
+
if (isImage && source) {
|
|
2829
|
+
return /* @__PURE__ */ jsxs6("figure", { className: "flex flex-col gap-1", children: [
|
|
2830
|
+
/* @__PURE__ */ jsx13(
|
|
2831
|
+
"img",
|
|
2832
|
+
{
|
|
2833
|
+
src: source,
|
|
2834
|
+
alt: label ?? "User provided image",
|
|
2835
|
+
className: "max-h-64 rounded-lg border border-border object-contain"
|
|
2836
|
+
}
|
|
2837
|
+
),
|
|
2838
|
+
/* @__PURE__ */ jsx13("figcaption", { className: "text-xs text-muted-foreground", children: label ?? "Image attachment" })
|
|
2839
|
+
] });
|
|
2840
|
+
}
|
|
2841
|
+
return /* @__PURE__ */ jsxs6("div", { className: "rounded-md border border-dashed border-border bg-muted/70 px-3 py-2 text-xs text-muted-foreground", children: [
|
|
2842
|
+
label ?? "Attachment",
|
|
2843
|
+
/* @__PURE__ */ jsx13("span", { className: "block text-[10px] uppercase tracking-wide text-muted-foreground/70", children: attachment.mimeType }),
|
|
2844
|
+
source && !isImage ? /* @__PURE__ */ jsx13(
|
|
2845
|
+
"a",
|
|
2846
|
+
{
|
|
2847
|
+
href: source,
|
|
2848
|
+
target: "_blank",
|
|
2849
|
+
rel: "noreferrer",
|
|
2850
|
+
className: "mt-1 block text-xs text-primary underline",
|
|
2851
|
+
children: "Open"
|
|
2852
|
+
}
|
|
2853
|
+
) : null
|
|
2854
|
+
] });
|
|
2855
|
+
};
|
|
2856
|
+
function resolveAttachmentSource(attachment) {
|
|
2857
|
+
if (attachment.url) {
|
|
2858
|
+
return attachment.url;
|
|
2859
|
+
}
|
|
2860
|
+
if (attachment.data) {
|
|
2861
|
+
return `data:${attachment.mimeType};base64,${attachment.data}`;
|
|
2862
|
+
}
|
|
2863
|
+
return null;
|
|
2864
|
+
}
|
|
2640
2865
|
CopilotChatUserMessage.Container.displayName = "CopilotChatUserMessage.Container";
|
|
2641
2866
|
CopilotChatUserMessage.MessageRenderer.displayName = "CopilotChatUserMessage.MessageRenderer";
|
|
2642
2867
|
CopilotChatUserMessage.Toolbar.displayName = "CopilotChatUserMessage.Toolbar";
|
|
@@ -2826,21 +3051,21 @@ CopilotChatMessageView.Cursor = function Cursor({ className, ...props }) {
|
|
|
2826
3051
|
var CopilotChatMessageView_default = CopilotChatMessageView;
|
|
2827
3052
|
|
|
2828
3053
|
// src/components/chat/CopilotChatView.tsx
|
|
2829
|
-
import React11, { useRef as useRef7, useState as
|
|
3054
|
+
import React11, { useRef as useRef7, useState as useState11, useEffect as useEffect14 } from "react";
|
|
2830
3055
|
import { twMerge as twMerge7 } from "tailwind-merge";
|
|
2831
3056
|
import { StickToBottom, useStickToBottom, useStickToBottomContext } from "use-stick-to-bottom";
|
|
2832
3057
|
import { ChevronDown } from "lucide-react";
|
|
2833
3058
|
|
|
2834
3059
|
// src/hooks/use-keyboard-height.tsx
|
|
2835
|
-
import { useState as
|
|
3060
|
+
import { useState as useState10, useEffect as useEffect13 } from "react";
|
|
2836
3061
|
function useKeyboardHeight() {
|
|
2837
|
-
const [keyboardState, setKeyboardState] =
|
|
3062
|
+
const [keyboardState, setKeyboardState] = useState10({
|
|
2838
3063
|
isKeyboardOpen: false,
|
|
2839
3064
|
keyboardHeight: 0,
|
|
2840
3065
|
availableHeight: typeof window !== "undefined" ? window.innerHeight : 0,
|
|
2841
3066
|
viewportHeight: typeof window !== "undefined" ? window.innerHeight : 0
|
|
2842
3067
|
});
|
|
2843
|
-
|
|
3068
|
+
useEffect13(() => {
|
|
2844
3069
|
if (typeof window === "undefined") {
|
|
2845
3070
|
return;
|
|
2846
3071
|
}
|
|
@@ -2884,8 +3109,10 @@ function CopilotChatView({
|
|
|
2884
3109
|
suggestionView,
|
|
2885
3110
|
messages = [],
|
|
2886
3111
|
autoScroll = true,
|
|
3112
|
+
scrollBehavior = "auto",
|
|
2887
3113
|
inputProps,
|
|
2888
3114
|
isRunning = false,
|
|
3115
|
+
isSwitchingThread = false,
|
|
2889
3116
|
suggestions,
|
|
2890
3117
|
suggestionLoadingIndexes,
|
|
2891
3118
|
onSelectSuggestion,
|
|
@@ -2894,11 +3121,11 @@ function CopilotChatView({
|
|
|
2894
3121
|
...props
|
|
2895
3122
|
}) {
|
|
2896
3123
|
const inputContainerRef = useRef7(null);
|
|
2897
|
-
const [inputContainerHeight, setInputContainerHeight] =
|
|
2898
|
-
const [isResizing, setIsResizing] =
|
|
3124
|
+
const [inputContainerHeight, setInputContainerHeight] = useState11(0);
|
|
3125
|
+
const [isResizing, setIsResizing] = useState11(false);
|
|
2899
3126
|
const resizeTimeoutRef = useRef7(null);
|
|
2900
3127
|
const { isKeyboardOpen, keyboardHeight, availableHeight } = useKeyboardHeight();
|
|
2901
|
-
|
|
3128
|
+
useEffect14(() => {
|
|
2902
3129
|
const element = inputContainerRef.current;
|
|
2903
3130
|
if (!element) return;
|
|
2904
3131
|
const resizeObserver = new ResizeObserver((entries) => {
|
|
@@ -2947,6 +3174,8 @@ function CopilotChatView({
|
|
|
2947
3174
|
const BoundFeather = renderSlot(feather, CopilotChatView.Feather, {});
|
|
2948
3175
|
const BoundScrollView = renderSlot(scrollView, CopilotChatView.ScrollView, {
|
|
2949
3176
|
autoScroll,
|
|
3177
|
+
scrollBehavior,
|
|
3178
|
+
isSwitchingThread,
|
|
2950
3179
|
scrollToBottomButton,
|
|
2951
3180
|
inputContainerHeight,
|
|
2952
3181
|
isResizing,
|
|
@@ -3005,19 +3234,21 @@ function CopilotChatView({
|
|
|
3005
3234
|
CopilotChatView2.ScrollView = ({
|
|
3006
3235
|
children,
|
|
3007
3236
|
autoScroll = true,
|
|
3237
|
+
scrollBehavior = "auto",
|
|
3238
|
+
isSwitchingThread = false,
|
|
3008
3239
|
scrollToBottomButton,
|
|
3009
3240
|
inputContainerHeight = 0,
|
|
3010
3241
|
isResizing = false,
|
|
3011
3242
|
className,
|
|
3012
3243
|
...props
|
|
3013
3244
|
}) => {
|
|
3014
|
-
const [hasMounted, setHasMounted] =
|
|
3245
|
+
const [hasMounted, setHasMounted] = useState11(false);
|
|
3015
3246
|
const { scrollRef, contentRef, scrollToBottom } = useStickToBottom();
|
|
3016
|
-
const [showScrollButton, setShowScrollButton] =
|
|
3017
|
-
|
|
3247
|
+
const [showScrollButton, setShowScrollButton] = useState11(false);
|
|
3248
|
+
useEffect14(() => {
|
|
3018
3249
|
setHasMounted(true);
|
|
3019
3250
|
}, []);
|
|
3020
|
-
|
|
3251
|
+
useEffect14(() => {
|
|
3021
3252
|
if (autoScroll) return;
|
|
3022
3253
|
const scrollElement = scrollRef.current;
|
|
3023
3254
|
if (!scrollElement) return;
|
|
@@ -3065,12 +3296,14 @@ function CopilotChatView({
|
|
|
3065
3296
|
}
|
|
3066
3297
|
);
|
|
3067
3298
|
}
|
|
3299
|
+
const initial = scrollBehavior === "auto" ? "instant" : scrollBehavior;
|
|
3300
|
+
const resize = scrollBehavior === "instant" ? "instant" : scrollBehavior === "auto" && isSwitchingThread ? "instant" : "smooth";
|
|
3068
3301
|
return /* @__PURE__ */ jsx17(
|
|
3069
3302
|
StickToBottom,
|
|
3070
3303
|
{
|
|
3071
3304
|
className: cn("h-full max-h-full flex flex-col min-h-0 relative", className),
|
|
3072
|
-
resize
|
|
3073
|
-
initial
|
|
3305
|
+
resize,
|
|
3306
|
+
initial,
|
|
3074
3307
|
...props,
|
|
3075
3308
|
children: /* @__PURE__ */ jsx17(
|
|
3076
3309
|
ScrollContent,
|
|
@@ -3149,19 +3382,94 @@ var CopilotChatView_default = CopilotChatView;
|
|
|
3149
3382
|
|
|
3150
3383
|
// src/components/chat/CopilotChat.tsx
|
|
3151
3384
|
import { DEFAULT_AGENT_ID as DEFAULT_AGENT_ID6, randomUUID as randomUUID2 } from "@copilotkitnext/shared";
|
|
3152
|
-
import { useCallback as
|
|
3385
|
+
import { useCallback as useCallback10, useEffect as useEffect15, useRef as useRef8, useState as useState12 } from "react";
|
|
3153
3386
|
import { merge } from "ts-deepmerge";
|
|
3154
|
-
import { AGUIConnectNotImplementedError } from "@ag-ui/client";
|
|
3155
3387
|
import { jsx as jsx18 } from "react/jsx-runtime";
|
|
3156
3388
|
function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen, ...props }) {
|
|
3157
3389
|
const existingConfig = useCopilotChatConfiguration();
|
|
3390
|
+
const hasOverrideProps = agentId !== void 0 || threadId !== void 0 || labels !== void 0 || isModalDefaultOpen !== void 0;
|
|
3391
|
+
if (!existingConfig || hasOverrideProps) {
|
|
3392
|
+
return /* @__PURE__ */ jsx18(
|
|
3393
|
+
CopilotChatConfigurationProvider,
|
|
3394
|
+
{
|
|
3395
|
+
agentId,
|
|
3396
|
+
threadId,
|
|
3397
|
+
labels,
|
|
3398
|
+
isModalDefaultOpen,
|
|
3399
|
+
children: /* @__PURE__ */ jsx18(CopilotChat, { chatView, ...props })
|
|
3400
|
+
}
|
|
3401
|
+
);
|
|
3402
|
+
}
|
|
3158
3403
|
const resolvedAgentId = agentId ?? existingConfig?.agentId ?? DEFAULT_AGENT_ID6;
|
|
3159
|
-
const resolvedThreadId =
|
|
3160
|
-
() => threadId ?? existingConfig?.threadId ?? randomUUID2(),
|
|
3161
|
-
[threadId, existingConfig?.threadId]
|
|
3162
|
-
);
|
|
3404
|
+
const resolvedThreadId = threadId ?? existingConfig?.threadId;
|
|
3163
3405
|
const { agent } = useAgent({ agentId: resolvedAgentId });
|
|
3164
3406
|
const { copilotkit } = useCopilotKit();
|
|
3407
|
+
const [isSwitchingThread, setIsSwitchingThread] = useState12(false);
|
|
3408
|
+
const [threadSwitchError, setThreadSwitchError] = useState12(null);
|
|
3409
|
+
const previousThreadIdRef = useRef8(void 0);
|
|
3410
|
+
const abortControllerRef = useRef8(null);
|
|
3411
|
+
useEffect15(() => {
|
|
3412
|
+
if (!agent || !resolvedThreadId) return;
|
|
3413
|
+
if (previousThreadIdRef.current === resolvedThreadId) return;
|
|
3414
|
+
if (abortControllerRef.current) {
|
|
3415
|
+
abortControllerRef.current.abort();
|
|
3416
|
+
}
|
|
3417
|
+
const abortController = new AbortController();
|
|
3418
|
+
abortControllerRef.current = abortController;
|
|
3419
|
+
const switchThread = async () => {
|
|
3420
|
+
setIsSwitchingThread(true);
|
|
3421
|
+
setThreadSwitchError(null);
|
|
3422
|
+
try {
|
|
3423
|
+
if (abortController.signal.aborted) return;
|
|
3424
|
+
if (previousThreadIdRef.current) {
|
|
3425
|
+
try {
|
|
3426
|
+
await copilotkit.disconnectAgent({ agent });
|
|
3427
|
+
} catch (disconnectErr) {
|
|
3428
|
+
console.warn("Error during disconnect, continuing with thread switch:", disconnectErr);
|
|
3429
|
+
}
|
|
3430
|
+
}
|
|
3431
|
+
if (abortController.signal.aborted) {
|
|
3432
|
+
previousThreadIdRef.current = void 0;
|
|
3433
|
+
return;
|
|
3434
|
+
}
|
|
3435
|
+
agent.messages = [];
|
|
3436
|
+
const subscribers = agent.subscribers || [];
|
|
3437
|
+
subscribers.forEach((subscriber) => {
|
|
3438
|
+
if (subscriber.onMessagesChanged) {
|
|
3439
|
+
subscriber.onMessagesChanged({
|
|
3440
|
+
messages: agent.messages,
|
|
3441
|
+
state: agent.state,
|
|
3442
|
+
agent
|
|
3443
|
+
});
|
|
3444
|
+
}
|
|
3445
|
+
});
|
|
3446
|
+
if (abortController.signal.aborted) {
|
|
3447
|
+
previousThreadIdRef.current = void 0;
|
|
3448
|
+
return;
|
|
3449
|
+
}
|
|
3450
|
+
await copilotkit.connectAgent({ agent, threadId: resolvedThreadId });
|
|
3451
|
+
if (!abortController.signal.aborted) {
|
|
3452
|
+
previousThreadIdRef.current = resolvedThreadId;
|
|
3453
|
+
}
|
|
3454
|
+
} catch (err) {
|
|
3455
|
+
if (abortController.signal.aborted) {
|
|
3456
|
+
previousThreadIdRef.current = void 0;
|
|
3457
|
+
return;
|
|
3458
|
+
}
|
|
3459
|
+
const error = err instanceof Error ? err : new Error(String(err));
|
|
3460
|
+
setThreadSwitchError(error);
|
|
3461
|
+
console.error("Failed to switch thread:", error);
|
|
3462
|
+
} finally {
|
|
3463
|
+
if (!abortController.signal.aborted) {
|
|
3464
|
+
setIsSwitchingThread(false);
|
|
3465
|
+
}
|
|
3466
|
+
}
|
|
3467
|
+
};
|
|
3468
|
+
void switchThread();
|
|
3469
|
+
return () => {
|
|
3470
|
+
abortController.abort();
|
|
3471
|
+
};
|
|
3472
|
+
}, [agent, resolvedThreadId, copilotkit]);
|
|
3165
3473
|
const { suggestions: autoSuggestions } = useSuggestions({ agentId: resolvedAgentId });
|
|
3166
3474
|
const {
|
|
3167
3475
|
inputProps: providedInputProps,
|
|
@@ -3169,25 +3477,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
3169
3477
|
suggestionView: providedSuggestionView,
|
|
3170
3478
|
...restProps
|
|
3171
3479
|
} = props;
|
|
3172
|
-
|
|
3173
|
-
const connect = async (agent2) => {
|
|
3174
|
-
try {
|
|
3175
|
-
await copilotkit.connectAgent({ agent: agent2 });
|
|
3176
|
-
} catch (error) {
|
|
3177
|
-
if (error instanceof AGUIConnectNotImplementedError) {
|
|
3178
|
-
} else {
|
|
3179
|
-
throw error;
|
|
3180
|
-
}
|
|
3181
|
-
}
|
|
3182
|
-
};
|
|
3183
|
-
if (agent) {
|
|
3184
|
-
agent.threadId = resolvedThreadId;
|
|
3185
|
-
connect(agent);
|
|
3186
|
-
}
|
|
3187
|
-
return () => {
|
|
3188
|
-
};
|
|
3189
|
-
}, [resolvedThreadId, agent, copilotkit, resolvedAgentId]);
|
|
3190
|
-
const onSubmitInput = useCallback6(
|
|
3480
|
+
const onSubmitInput = useCallback10(
|
|
3191
3481
|
async (value) => {
|
|
3192
3482
|
agent?.addMessage({
|
|
3193
3483
|
id: randomUUID2(),
|
|
@@ -3204,7 +3494,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
3204
3494
|
},
|
|
3205
3495
|
[agent, copilotkit]
|
|
3206
3496
|
);
|
|
3207
|
-
const handleSelectSuggestion =
|
|
3497
|
+
const handleSelectSuggestion = useCallback10(
|
|
3208
3498
|
async (suggestion) => {
|
|
3209
3499
|
if (!agent) {
|
|
3210
3500
|
return;
|
|
@@ -3222,7 +3512,7 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
3222
3512
|
},
|
|
3223
3513
|
[agent, copilotkit]
|
|
3224
3514
|
);
|
|
3225
|
-
const stopCurrentRun =
|
|
3515
|
+
const stopCurrentRun = useCallback10(() => {
|
|
3226
3516
|
if (!agent) {
|
|
3227
3517
|
return;
|
|
3228
3518
|
}
|
|
@@ -3264,24 +3554,27 @@ function CopilotChat({ agentId, threadId, labels, chatView, isModalDefaultOpen,
|
|
|
3264
3554
|
messages: agent?.messages ?? [],
|
|
3265
3555
|
inputProps: finalInputProps
|
|
3266
3556
|
});
|
|
3267
|
-
const
|
|
3268
|
-
|
|
3269
|
-
|
|
3270
|
-
|
|
3271
|
-
|
|
3272
|
-
|
|
3273
|
-
|
|
3274
|
-
|
|
3275
|
-
|
|
3276
|
-
|
|
3277
|
-
|
|
3557
|
+
const inputPropsWithThreadState = {
|
|
3558
|
+
...finalProps.inputProps ?? {},
|
|
3559
|
+
mode: isSwitchingThread ? "processing" : finalProps.inputProps?.mode
|
|
3560
|
+
};
|
|
3561
|
+
const finalPropsWithThreadState = {
|
|
3562
|
+
...finalProps,
|
|
3563
|
+
isRunning: (finalProps.isRunning ?? false) || isSwitchingThread,
|
|
3564
|
+
inputProps: inputPropsWithThreadState,
|
|
3565
|
+
// Pass thread switching state to control scroll behavior
|
|
3566
|
+
isSwitchingThread,
|
|
3567
|
+
"data-thread-switching": isSwitchingThread ? "true" : void 0,
|
|
3568
|
+
"data-thread-switch-error": threadSwitchError ? threadSwitchError.message : void 0
|
|
3569
|
+
};
|
|
3570
|
+
return renderSlot(chatView, CopilotChatView, finalPropsWithThreadState);
|
|
3278
3571
|
}
|
|
3279
3572
|
((CopilotChat2) => {
|
|
3280
3573
|
CopilotChat2.View = CopilotChatView;
|
|
3281
3574
|
})(CopilotChat || (CopilotChat = {}));
|
|
3282
3575
|
|
|
3283
3576
|
// src/components/chat/CopilotChatToggleButton.tsx
|
|
3284
|
-
import React12, { useState as
|
|
3577
|
+
import React12, { useState as useState13 } from "react";
|
|
3285
3578
|
import { MessageCircle, X as X2 } from "lucide-react";
|
|
3286
3579
|
import { jsx as jsx19, jsxs as jsxs11 } from "react/jsx-runtime";
|
|
3287
3580
|
var DefaultOpenIcon = ({
|
|
@@ -3312,7 +3605,7 @@ var CopilotChatToggleButton = React12.forwardRef(function CopilotChatToggleButto
|
|
|
3312
3605
|
const { onClick, type, disabled, ...restProps } = buttonProps;
|
|
3313
3606
|
const configuration = useCopilotChatConfiguration();
|
|
3314
3607
|
const labels = configuration?.labels ?? CopilotChatDefaultLabels;
|
|
3315
|
-
const [fallbackOpen, setFallbackOpen] =
|
|
3608
|
+
const [fallbackOpen, setFallbackOpen] = useState13(false);
|
|
3316
3609
|
const isOpen = configuration?.isModalOpen ?? fallbackOpen;
|
|
3317
3610
|
const setModalOpen = configuration?.setModalOpen ?? setFallbackOpen;
|
|
3318
3611
|
const handleClick = (event) => {
|
|
@@ -3398,16 +3691,21 @@ CopilotChatToggleButton.displayName = "CopilotChatToggleButton";
|
|
|
3398
3691
|
var CopilotChatToggleButton_default = CopilotChatToggleButton;
|
|
3399
3692
|
|
|
3400
3693
|
// src/components/chat/CopilotSidebarView.tsx
|
|
3401
|
-
import { useEffect as
|
|
3694
|
+
import { useEffect as useEffect17, useRef as useRef10, useState as useState15, useCallback as useCallback13 } from "react";
|
|
3402
3695
|
|
|
3403
3696
|
// src/components/chat/CopilotModalHeader.tsx
|
|
3404
|
-
import { useCallback as
|
|
3405
|
-
import { X as X3 } from "lucide-react";
|
|
3697
|
+
import { useCallback as useCallback11 } from "react";
|
|
3698
|
+
import { X as X3, List, SquarePen } from "lucide-react";
|
|
3406
3699
|
import { jsx as jsx20, jsxs as jsxs12 } from "react/jsx-runtime";
|
|
3407
3700
|
function CopilotModalHeader({
|
|
3408
3701
|
title,
|
|
3409
3702
|
titleContent,
|
|
3410
3703
|
closeButton,
|
|
3704
|
+
leftContent,
|
|
3705
|
+
onThreadListClick,
|
|
3706
|
+
showThreadListButton = false,
|
|
3707
|
+
onNewThreadClick,
|
|
3708
|
+
showNewThreadButton = false,
|
|
3411
3709
|
children,
|
|
3412
3710
|
className,
|
|
3413
3711
|
...rest
|
|
@@ -3415,7 +3713,7 @@ function CopilotModalHeader({
|
|
|
3415
3713
|
const configuration = useCopilotChatConfiguration();
|
|
3416
3714
|
const fallbackTitle = configuration?.labels.modalHeaderTitle ?? CopilotChatDefaultLabels.modalHeaderTitle;
|
|
3417
3715
|
const resolvedTitle = title ?? fallbackTitle;
|
|
3418
|
-
const handleClose =
|
|
3716
|
+
const handleClose = useCallback11(() => {
|
|
3419
3717
|
configuration?.setModalOpen(false);
|
|
3420
3718
|
}, [configuration]);
|
|
3421
3719
|
const BoundTitle = renderSlot(titleContent, CopilotModalHeader.Title, {
|
|
@@ -3424,10 +3722,17 @@ function CopilotModalHeader({
|
|
|
3424
3722
|
const BoundCloseButton = renderSlot(closeButton, CopilotModalHeader.CloseButton, {
|
|
3425
3723
|
onClick: handleClose
|
|
3426
3724
|
});
|
|
3725
|
+
const BoundLeftContent = renderSlot(leftContent, CopilotModalHeader.LeftContent, {
|
|
3726
|
+
onThreadListClick,
|
|
3727
|
+
showThreadListButton,
|
|
3728
|
+
onNewThreadClick,
|
|
3729
|
+
showNewThreadButton
|
|
3730
|
+
});
|
|
3427
3731
|
if (children) {
|
|
3428
3732
|
return children({
|
|
3429
3733
|
titleContent: BoundTitle,
|
|
3430
3734
|
closeButton: BoundCloseButton,
|
|
3735
|
+
leftContent: BoundLeftContent,
|
|
3431
3736
|
title: resolvedTitle,
|
|
3432
3737
|
...rest
|
|
3433
3738
|
});
|
|
@@ -3443,7 +3748,7 @@ function CopilotModalHeader({
|
|
|
3443
3748
|
),
|
|
3444
3749
|
...rest,
|
|
3445
3750
|
children: /* @__PURE__ */ jsxs12("div", { className: "flex w-full items-center gap-2", children: [
|
|
3446
|
-
/* @__PURE__ */ jsx20("div", { className: "flex-1",
|
|
3751
|
+
/* @__PURE__ */ jsx20("div", { className: "flex flex-1 justify-start", children: BoundLeftContent }),
|
|
3447
3752
|
/* @__PURE__ */ jsx20("div", { className: "flex flex-1 justify-center text-center", children: BoundTitle }),
|
|
3448
3753
|
/* @__PURE__ */ jsx20("div", { className: "flex flex-1 justify-end", children: BoundCloseButton })
|
|
3449
3754
|
] })
|
|
@@ -3480,19 +3785,281 @@ CopilotModalHeader.displayName = "CopilotModalHeader";
|
|
|
3480
3785
|
children: /* @__PURE__ */ jsx20(X3, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
3481
3786
|
}
|
|
3482
3787
|
);
|
|
3788
|
+
CopilotModalHeader2.LeftContent = ({
|
|
3789
|
+
onThreadListClick,
|
|
3790
|
+
showThreadListButton,
|
|
3791
|
+
onNewThreadClick,
|
|
3792
|
+
showNewThreadButton,
|
|
3793
|
+
className,
|
|
3794
|
+
children
|
|
3795
|
+
}) => {
|
|
3796
|
+
if (children) {
|
|
3797
|
+
return /* @__PURE__ */ jsx20("div", { className, children });
|
|
3798
|
+
}
|
|
3799
|
+
const hasAnyButton = showNewThreadButton && onNewThreadClick || showThreadListButton && onThreadListClick;
|
|
3800
|
+
if (!hasAnyButton) {
|
|
3801
|
+
return null;
|
|
3802
|
+
}
|
|
3803
|
+
return /* @__PURE__ */ jsxs12("div", { className: cn("flex items-center gap-1", className), children: [
|
|
3804
|
+
showNewThreadButton && onNewThreadClick && /* @__PURE__ */ jsx20(
|
|
3805
|
+
"button",
|
|
3806
|
+
{
|
|
3807
|
+
type: "button",
|
|
3808
|
+
onClick: onNewThreadClick,
|
|
3809
|
+
className: cn(
|
|
3810
|
+
"inline-flex size-8 items-center justify-center rounded-full text-muted-foreground transition cursor-pointer",
|
|
3811
|
+
"hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
3812
|
+
),
|
|
3813
|
+
"aria-label": "New thread",
|
|
3814
|
+
title: "New thread",
|
|
3815
|
+
children: /* @__PURE__ */ jsx20(SquarePen, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
3816
|
+
}
|
|
3817
|
+
),
|
|
3818
|
+
showThreadListButton && onThreadListClick && /* @__PURE__ */ jsx20(
|
|
3819
|
+
"button",
|
|
3820
|
+
{
|
|
3821
|
+
type: "button",
|
|
3822
|
+
onClick: onThreadListClick,
|
|
3823
|
+
className: cn(
|
|
3824
|
+
"inline-flex size-8 items-center justify-center rounded-full text-muted-foreground transition cursor-pointer",
|
|
3825
|
+
"hover:bg-muted hover:text-foreground focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring"
|
|
3826
|
+
),
|
|
3827
|
+
"aria-label": "Show threads",
|
|
3828
|
+
title: "Show threads",
|
|
3829
|
+
children: /* @__PURE__ */ jsx20(List, { className: "h-4 w-4", "aria-hidden": "true" })
|
|
3830
|
+
}
|
|
3831
|
+
)
|
|
3832
|
+
] });
|
|
3833
|
+
};
|
|
3483
3834
|
})(CopilotModalHeader || (CopilotModalHeader = {}));
|
|
3484
3835
|
CopilotModalHeader.Title.displayName = "CopilotModalHeader.Title";
|
|
3485
3836
|
CopilotModalHeader.CloseButton.displayName = "CopilotModalHeader.CloseButton";
|
|
3837
|
+
CopilotModalHeader.LeftContent.displayName = "CopilotModalHeader.LeftContent";
|
|
3486
3838
|
|
|
3487
|
-
// src/components/
|
|
3839
|
+
// src/components/threads/CopilotThreadList.tsx
|
|
3840
|
+
import { useCallback as useCallback12, useEffect as useEffect16, useRef as useRef9, useState as useState14 } from "react";
|
|
3841
|
+
import { MessageSquare, Plus as Plus2, Trash2 } from "lucide-react";
|
|
3842
|
+
import { randomUUID as randomUUID3 } from "@copilotkitnext/shared";
|
|
3488
3843
|
import { Fragment as Fragment7, jsx as jsx21, jsxs as jsxs13 } from "react/jsx-runtime";
|
|
3844
|
+
function CopilotThreadListInner({
|
|
3845
|
+
limit = 50,
|
|
3846
|
+
onThreadSelect,
|
|
3847
|
+
className,
|
|
3848
|
+
threadItem,
|
|
3849
|
+
newThreadButton,
|
|
3850
|
+
container,
|
|
3851
|
+
refreshInterval = 2e3,
|
|
3852
|
+
disableAutoRefresh = false
|
|
3853
|
+
}) {
|
|
3854
|
+
const config = useCopilotChatConfiguration();
|
|
3855
|
+
const { threads, isLoading, error, fetchThreads, addOptimisticThread, refresh, currentThreadId, deleteThread } = useThreads({
|
|
3856
|
+
limit
|
|
3857
|
+
});
|
|
3858
|
+
const attemptedFetchRef = useRef9(/* @__PURE__ */ new Set());
|
|
3859
|
+
const handleNewThread = useCallback12(() => {
|
|
3860
|
+
const newThreadId = randomUUID3();
|
|
3861
|
+
addOptimisticThread(newThreadId);
|
|
3862
|
+
config?.setThreadId?.(newThreadId);
|
|
3863
|
+
onThreadSelect?.(newThreadId);
|
|
3864
|
+
}, [addOptimisticThread, config, onThreadSelect]);
|
|
3865
|
+
const handleThreadSelect = useCallback12(
|
|
3866
|
+
(threadId) => {
|
|
3867
|
+
config?.setThreadId?.(threadId);
|
|
3868
|
+
onThreadSelect?.(threadId);
|
|
3869
|
+
},
|
|
3870
|
+
[config, onThreadSelect]
|
|
3871
|
+
);
|
|
3872
|
+
const handleDeleteThread = useCallback12(
|
|
3873
|
+
async (threadId) => {
|
|
3874
|
+
try {
|
|
3875
|
+
await deleteThread(threadId);
|
|
3876
|
+
if (threadId === (currentThreadId ?? config?.threadId)) {
|
|
3877
|
+
const newThreadId = randomUUID3();
|
|
3878
|
+
addOptimisticThread(newThreadId);
|
|
3879
|
+
config?.setThreadId?.(newThreadId);
|
|
3880
|
+
}
|
|
3881
|
+
} catch (err) {
|
|
3882
|
+
console.error("Failed to delete thread:", err);
|
|
3883
|
+
}
|
|
3884
|
+
},
|
|
3885
|
+
[deleteThread, currentThreadId, config, addOptimisticThread]
|
|
3886
|
+
);
|
|
3887
|
+
useEffect16(() => {
|
|
3888
|
+
const activeId = currentThreadId ?? config?.threadId;
|
|
3889
|
+
if (!activeId) return;
|
|
3890
|
+
const isCurrentThreadInList = threads.some((t) => t.threadId === activeId);
|
|
3891
|
+
if (isCurrentThreadInList) {
|
|
3892
|
+
attemptedFetchRef.current.delete(activeId);
|
|
3893
|
+
return;
|
|
3894
|
+
}
|
|
3895
|
+
if (!isLoading && !attemptedFetchRef.current.has(activeId)) {
|
|
3896
|
+
attemptedFetchRef.current.add(activeId);
|
|
3897
|
+
refresh();
|
|
3898
|
+
}
|
|
3899
|
+
}, [currentThreadId, config?.threadId, threads, refresh, isLoading]);
|
|
3900
|
+
useEffect16(() => {
|
|
3901
|
+
if (disableAutoRefresh) return;
|
|
3902
|
+
const hasRunningThread = threads.some((t) => t.isRunning);
|
|
3903
|
+
const hasUnnamedThread = threads.some((t) => !t.firstMessage);
|
|
3904
|
+
if (!hasRunningThread && !hasUnnamedThread) return;
|
|
3905
|
+
const interval = setInterval(() => {
|
|
3906
|
+
refresh();
|
|
3907
|
+
}, refreshInterval);
|
|
3908
|
+
return () => clearInterval(interval);
|
|
3909
|
+
}, [threads, refresh, refreshInterval, disableAutoRefresh]);
|
|
3910
|
+
const BoundNewThreadButton = renderSlot(newThreadButton, NewThreadButton, {
|
|
3911
|
+
onClick: handleNewThread
|
|
3912
|
+
});
|
|
3913
|
+
const activeThreadId = currentThreadId ?? config?.threadId;
|
|
3914
|
+
const threadItems = threads.map((thread) => {
|
|
3915
|
+
const isActive = thread.threadId === activeThreadId;
|
|
3916
|
+
return renderSlot(threadItem, ThreadListItem, {
|
|
3917
|
+
key: thread.threadId,
|
|
3918
|
+
thread,
|
|
3919
|
+
isActive,
|
|
3920
|
+
onClick: () => handleThreadSelect(thread.threadId),
|
|
3921
|
+
onDelete: () => handleDeleteThread(thread.threadId)
|
|
3922
|
+
});
|
|
3923
|
+
});
|
|
3924
|
+
const content = /* @__PURE__ */ jsxs13(Fragment7, { children: [
|
|
3925
|
+
BoundNewThreadButton,
|
|
3926
|
+
/* @__PURE__ */ jsx21("div", { className: "space-y-1", children: error ? /* @__PURE__ */ jsxs13("div", { className: "copilotkit-thread-list-error mx-4 my-3 rounded-md border border-destructive/30 bg-destructive/5 p-4 text-sm text-destructive", children: [
|
|
3927
|
+
/* @__PURE__ */ jsxs13("p", { className: "mb-3 font-medium", children: [
|
|
3928
|
+
"Failed to load threads: ",
|
|
3929
|
+
error.message
|
|
3930
|
+
] }),
|
|
3931
|
+
/* @__PURE__ */ jsx21(
|
|
3932
|
+
"button",
|
|
3933
|
+
{
|
|
3934
|
+
type: "button",
|
|
3935
|
+
className: "rounded bg-destructive px-3 py-1.5 text-xs font-medium text-destructive-foreground transition hover:bg-destructive/90",
|
|
3936
|
+
onClick: () => fetchThreads(),
|
|
3937
|
+
children: "Retry"
|
|
3938
|
+
}
|
|
3939
|
+
)
|
|
3940
|
+
] }) : isLoading && threads.length === 0 ? /* @__PURE__ */ jsx21("div", { className: "p-4 text-center text-sm text-muted-foreground", children: "Loading threads..." }) : threads.length === 0 ? /* @__PURE__ */ jsx21("div", { className: "p-4 text-center text-sm text-muted-foreground", children: "No threads yet" }) : threadItems })
|
|
3941
|
+
] });
|
|
3942
|
+
return renderSlot(container, Container, {
|
|
3943
|
+
className,
|
|
3944
|
+
children: content
|
|
3945
|
+
});
|
|
3946
|
+
}
|
|
3947
|
+
var Container = ({ className, children, ...props }) => /* @__PURE__ */ jsx21("div", { className: cn("flex flex-col h-full", className), ...props, children });
|
|
3948
|
+
var NewThreadButton = ({ className, ...props }) => /* @__PURE__ */ jsxs13(
|
|
3949
|
+
"button",
|
|
3950
|
+
{
|
|
3951
|
+
className: cn(
|
|
3952
|
+
"w-full flex items-center gap-3 px-4 py-3 text-sm font-medium",
|
|
3953
|
+
"border-b border-border",
|
|
3954
|
+
"hover:bg-accent/50 transition-colors",
|
|
3955
|
+
"text-foreground",
|
|
3956
|
+
className
|
|
3957
|
+
),
|
|
3958
|
+
...props,
|
|
3959
|
+
children: [
|
|
3960
|
+
/* @__PURE__ */ jsx21(Plus2, { className: "w-4 h-4" }),
|
|
3961
|
+
/* @__PURE__ */ jsx21("span", { children: "New Conversation" })
|
|
3962
|
+
]
|
|
3963
|
+
}
|
|
3964
|
+
);
|
|
3965
|
+
var ThreadListItem = ({ thread, isActive, onClick, onDelete }) => {
|
|
3966
|
+
const displayText = thread.firstMessage?.substring(0, 60) || "New conversation";
|
|
3967
|
+
const hasEllipsis = thread.firstMessage && thread.firstMessage.length > 60;
|
|
3968
|
+
const messageCount = thread.messageCount || 0;
|
|
3969
|
+
const [isDeleting, setIsDeleting] = useState14(false);
|
|
3970
|
+
const handleDelete = useCallback12(
|
|
3971
|
+
async (e) => {
|
|
3972
|
+
e.stopPropagation();
|
|
3973
|
+
if (!onDelete) return;
|
|
3974
|
+
setIsDeleting(true);
|
|
3975
|
+
try {
|
|
3976
|
+
await onDelete();
|
|
3977
|
+
} catch (err) {
|
|
3978
|
+
console.error("Delete failed:", err);
|
|
3979
|
+
setIsDeleting(false);
|
|
3980
|
+
}
|
|
3981
|
+
},
|
|
3982
|
+
[onDelete]
|
|
3983
|
+
);
|
|
3984
|
+
return /* @__PURE__ */ jsxs13(
|
|
3985
|
+
"div",
|
|
3986
|
+
{
|
|
3987
|
+
className: cn(
|
|
3988
|
+
"w-full flex items-start gap-3 px-4 py-3 group relative",
|
|
3989
|
+
"hover:bg-accent/50 transition-colors",
|
|
3990
|
+
"border-b border-border",
|
|
3991
|
+
isActive && "bg-accent border-l-2 border-l-primary",
|
|
3992
|
+
isDeleting && "opacity-50 pointer-events-none"
|
|
3993
|
+
),
|
|
3994
|
+
children: [
|
|
3995
|
+
/* @__PURE__ */ jsxs13("button", { onClick, className: "flex items-start gap-3 flex-1 min-w-0 text-left", children: [
|
|
3996
|
+
/* @__PURE__ */ jsx21(MessageSquare, { className: "w-4 h-4 mt-0.5 flex-shrink-0 text-muted-foreground" }),
|
|
3997
|
+
/* @__PURE__ */ jsxs13("div", { className: "flex-1 min-w-0", children: [
|
|
3998
|
+
/* @__PURE__ */ jsxs13("p", { className: "text-sm text-foreground truncate", children: [
|
|
3999
|
+
displayText,
|
|
4000
|
+
hasEllipsis && "..."
|
|
4001
|
+
] }),
|
|
4002
|
+
messageCount > 0 && /* @__PURE__ */ jsxs13("p", { className: "text-xs text-muted-foreground mt-1", children: [
|
|
4003
|
+
messageCount,
|
|
4004
|
+
" messages"
|
|
4005
|
+
] })
|
|
4006
|
+
] })
|
|
4007
|
+
] }),
|
|
4008
|
+
onDelete && /* @__PURE__ */ jsx21(
|
|
4009
|
+
"button",
|
|
4010
|
+
{
|
|
4011
|
+
type: "button",
|
|
4012
|
+
onClick: handleDelete,
|
|
4013
|
+
disabled: isDeleting,
|
|
4014
|
+
className: cn(
|
|
4015
|
+
"p-1.5 rounded transition-all",
|
|
4016
|
+
"text-muted-foreground hover:text-destructive hover:bg-destructive/10",
|
|
4017
|
+
"opacity-0 group-hover:opacity-100",
|
|
4018
|
+
"focus:opacity-100 focus:outline-none focus:ring-2 focus:ring-destructive/20",
|
|
4019
|
+
isDeleting && "animate-pulse"
|
|
4020
|
+
),
|
|
4021
|
+
"aria-label": "Delete thread",
|
|
4022
|
+
title: "Delete thread",
|
|
4023
|
+
children: /* @__PURE__ */ jsx21(Trash2, { className: "w-4 h-4" })
|
|
4024
|
+
}
|
|
4025
|
+
)
|
|
4026
|
+
]
|
|
4027
|
+
}
|
|
4028
|
+
);
|
|
4029
|
+
};
|
|
4030
|
+
function CopilotThreadList(props) {
|
|
4031
|
+
const existingConfig = useCopilotChatConfiguration();
|
|
4032
|
+
if (!existingConfig) {
|
|
4033
|
+
return /* @__PURE__ */ jsx21(CopilotChatConfigurationProvider, { children: /* @__PURE__ */ jsx21(CopilotThreadListInner, { ...props }) });
|
|
4034
|
+
}
|
|
4035
|
+
return /* @__PURE__ */ jsx21(CopilotThreadListInner, { ...props });
|
|
4036
|
+
}
|
|
4037
|
+
CopilotThreadList.displayName = "CopilotThreadList";
|
|
4038
|
+
CopilotThreadList.ThreadItem = ThreadListItem;
|
|
4039
|
+
CopilotThreadList.NewThreadButton = NewThreadButton;
|
|
4040
|
+
CopilotThreadList.Container = Container;
|
|
4041
|
+
|
|
4042
|
+
// src/components/chat/CopilotSidebarView.tsx
|
|
4043
|
+
import { randomUUID as randomUUID4 } from "@copilotkitnext/shared";
|
|
4044
|
+
import { Fragment as Fragment8, jsx as jsx22, jsxs as jsxs14 } from "react/jsx-runtime";
|
|
3489
4045
|
var DEFAULT_SIDEBAR_WIDTH = 480;
|
|
3490
4046
|
var SIDEBAR_TRANSITION_MS = 260;
|
|
3491
|
-
function CopilotSidebarView({ header, width, ...props }) {
|
|
4047
|
+
function CopilotSidebarView({ header, width, showThreadListButton = false, showNewThreadButton = false, ...props }) {
|
|
3492
4048
|
const configuration = useCopilotChatConfiguration();
|
|
3493
4049
|
const isSidebarOpen = configuration?.isModalOpen ?? false;
|
|
3494
|
-
const
|
|
3495
|
-
const
|
|
4050
|
+
const [isThreadListOpen, setIsThreadListOpen] = useState15(false);
|
|
4051
|
+
const sidebarRef = useRef10(null);
|
|
4052
|
+
const [sidebarWidth, setSidebarWidth] = useState15(width ?? DEFAULT_SIDEBAR_WIDTH);
|
|
4053
|
+
const handleThreadListToggle = useCallback13(() => {
|
|
4054
|
+
setIsThreadListOpen((prev) => !prev);
|
|
4055
|
+
}, []);
|
|
4056
|
+
const handleThreadSelect = useCallback13(() => {
|
|
4057
|
+
setIsThreadListOpen(false);
|
|
4058
|
+
}, []);
|
|
4059
|
+
const handleNewThread = useCallback13(() => {
|
|
4060
|
+
const newThreadId = randomUUID4();
|
|
4061
|
+
configuration?.setThreadId?.(newThreadId);
|
|
4062
|
+
}, [configuration]);
|
|
3496
4063
|
const widthToCss = (w) => {
|
|
3497
4064
|
return typeof w === "number" ? `${w}px` : w;
|
|
3498
4065
|
};
|
|
@@ -3502,7 +4069,7 @@ function CopilotSidebarView({ header, width, ...props }) {
|
|
|
3502
4069
|
}
|
|
3503
4070
|
return w;
|
|
3504
4071
|
};
|
|
3505
|
-
|
|
4072
|
+
useEffect17(() => {
|
|
3506
4073
|
if (width !== void 0) {
|
|
3507
4074
|
return;
|
|
3508
4075
|
}
|
|
@@ -3528,9 +4095,14 @@ function CopilotSidebarView({ header, width, ...props }) {
|
|
|
3528
4095
|
window.addEventListener("resize", updateWidth);
|
|
3529
4096
|
return () => window.removeEventListener("resize", updateWidth);
|
|
3530
4097
|
}, [width]);
|
|
3531
|
-
const headerElement = renderSlot(header, CopilotModalHeader, {
|
|
3532
|
-
|
|
3533
|
-
|
|
4098
|
+
const headerElement = renderSlot(header, CopilotModalHeader, {
|
|
4099
|
+
onThreadListClick: handleThreadListToggle,
|
|
4100
|
+
showThreadListButton,
|
|
4101
|
+
onNewThreadClick: handleNewThread,
|
|
4102
|
+
showNewThreadButton
|
|
4103
|
+
});
|
|
4104
|
+
return /* @__PURE__ */ jsxs14(Fragment8, { children: [
|
|
4105
|
+
isSidebarOpen && /* @__PURE__ */ jsx22(
|
|
3534
4106
|
"style",
|
|
3535
4107
|
{
|
|
3536
4108
|
dangerouslySetInnerHTML: {
|
|
@@ -3544,8 +4116,8 @@ function CopilotSidebarView({ header, width, ...props }) {
|
|
|
3544
4116
|
}
|
|
3545
4117
|
}
|
|
3546
4118
|
),
|
|
3547
|
-
/* @__PURE__ */
|
|
3548
|
-
/* @__PURE__ */
|
|
4119
|
+
/* @__PURE__ */ jsx22(CopilotChatToggleButton_default, {}),
|
|
4120
|
+
/* @__PURE__ */ jsxs14(
|
|
3549
4121
|
"aside",
|
|
3550
4122
|
{
|
|
3551
4123
|
ref: sidebarRef,
|
|
@@ -3558,6 +4130,8 @@ function CopilotSidebarView({ header, width, ...props }) {
|
|
|
3558
4130
|
"w-full",
|
|
3559
4131
|
"border-l border-border bg-background text-foreground shadow-xl",
|
|
3560
4132
|
"transition-transform duration-300 ease-out",
|
|
4133
|
+
"overflow-hidden",
|
|
4134
|
+
// Clip the sliding panel
|
|
3561
4135
|
isSidebarOpen ? "translate-x-0" : "translate-x-full pointer-events-none"
|
|
3562
4136
|
),
|
|
3563
4137
|
style: {
|
|
@@ -3570,10 +4144,31 @@ function CopilotSidebarView({ header, width, ...props }) {
|
|
|
3570
4144
|
"aria-hidden": !isSidebarOpen,
|
|
3571
4145
|
"aria-label": "Copilot chat sidebar",
|
|
3572
4146
|
role: "complementary",
|
|
3573
|
-
children:
|
|
3574
|
-
|
|
3575
|
-
|
|
3576
|
-
|
|
4147
|
+
children: [
|
|
4148
|
+
isThreadListOpen && /* @__PURE__ */ jsx22(
|
|
4149
|
+
"div",
|
|
4150
|
+
{
|
|
4151
|
+
className: "absolute inset-0 z-50",
|
|
4152
|
+
onClick: handleThreadListToggle,
|
|
4153
|
+
"aria-hidden": "true"
|
|
4154
|
+
}
|
|
4155
|
+
),
|
|
4156
|
+
/* @__PURE__ */ jsx22(
|
|
4157
|
+
"div",
|
|
4158
|
+
{
|
|
4159
|
+
className: cn(
|
|
4160
|
+
"absolute left-0 top-0 h-full w-80 bg-background border-r border-border z-[60]",
|
|
4161
|
+
"transition-transform duration-300 ease-out",
|
|
4162
|
+
isThreadListOpen ? "translate-x-0" : "-translate-x-full"
|
|
4163
|
+
),
|
|
4164
|
+
children: /* @__PURE__ */ jsx22(CopilotThreadList, { onThreadSelect: handleThreadSelect })
|
|
4165
|
+
}
|
|
4166
|
+
),
|
|
4167
|
+
/* @__PURE__ */ jsxs14("div", { className: "flex h-full w-full flex-col overflow-hidden", children: [
|
|
4168
|
+
headerElement,
|
|
4169
|
+
/* @__PURE__ */ jsx22("div", { className: "flex-1 overflow-hidden", "data-sidebar-chat": true, children: /* @__PURE__ */ jsx22(CopilotChatView_default, { ...props }) })
|
|
4170
|
+
] })
|
|
4171
|
+
]
|
|
3577
4172
|
}
|
|
3578
4173
|
)
|
|
3579
4174
|
] });
|
|
@@ -3581,8 +4176,9 @@ function CopilotSidebarView({ header, width, ...props }) {
|
|
|
3581
4176
|
CopilotSidebarView.displayName = "CopilotSidebarView";
|
|
3582
4177
|
|
|
3583
4178
|
// src/components/chat/CopilotPopupView.tsx
|
|
3584
|
-
import { useEffect as
|
|
3585
|
-
import {
|
|
4179
|
+
import { useCallback as useCallback14, useEffect as useEffect18, useMemo as useMemo7, useRef as useRef11, useState as useState16 } from "react";
|
|
4180
|
+
import { randomUUID as randomUUID5 } from "@copilotkitnext/shared";
|
|
4181
|
+
import { Fragment as Fragment9, jsx as jsx23, jsxs as jsxs15 } from "react/jsx-runtime";
|
|
3586
4182
|
var DEFAULT_POPUP_WIDTH = 420;
|
|
3587
4183
|
var DEFAULT_POPUP_HEIGHT = 560;
|
|
3588
4184
|
var dimensionToCss = (value, fallback) => {
|
|
@@ -3599,6 +4195,8 @@ function CopilotPopupView({
|
|
|
3599
4195
|
width,
|
|
3600
4196
|
height,
|
|
3601
4197
|
clickOutsideToClose,
|
|
4198
|
+
showThreadListButton = false,
|
|
4199
|
+
showNewThreadButton = false,
|
|
3602
4200
|
className,
|
|
3603
4201
|
...restProps
|
|
3604
4202
|
}) {
|
|
@@ -3606,10 +4204,21 @@ function CopilotPopupView({
|
|
|
3606
4204
|
const isPopupOpen = configuration?.isModalOpen ?? false;
|
|
3607
4205
|
const setModalOpen = configuration?.setModalOpen;
|
|
3608
4206
|
const labels = configuration?.labels ?? CopilotChatDefaultLabels;
|
|
3609
|
-
const containerRef =
|
|
3610
|
-
const [isRendered, setIsRendered] =
|
|
3611
|
-
const [isAnimatingOut, setIsAnimatingOut] =
|
|
3612
|
-
|
|
4207
|
+
const containerRef = useRef11(null);
|
|
4208
|
+
const [isRendered, setIsRendered] = useState16(isPopupOpen);
|
|
4209
|
+
const [isAnimatingOut, setIsAnimatingOut] = useState16(false);
|
|
4210
|
+
const [isThreadListOpen, setIsThreadListOpen] = useState16(false);
|
|
4211
|
+
const handleThreadListToggle = useCallback14(() => {
|
|
4212
|
+
setIsThreadListOpen((prev) => !prev);
|
|
4213
|
+
}, []);
|
|
4214
|
+
const handleThreadSelect = useCallback14(() => {
|
|
4215
|
+
setIsThreadListOpen(false);
|
|
4216
|
+
}, []);
|
|
4217
|
+
const handleNewThread = useCallback14(() => {
|
|
4218
|
+
const newThreadId = randomUUID5();
|
|
4219
|
+
configuration?.setThreadId?.(newThreadId);
|
|
4220
|
+
}, [configuration]);
|
|
4221
|
+
useEffect18(() => {
|
|
3613
4222
|
if (isPopupOpen) {
|
|
3614
4223
|
setIsRendered(true);
|
|
3615
4224
|
setIsAnimatingOut(false);
|
|
@@ -3625,7 +4234,7 @@ function CopilotPopupView({
|
|
|
3625
4234
|
}, 200);
|
|
3626
4235
|
return () => clearTimeout(timeout);
|
|
3627
4236
|
}, [isPopupOpen, isRendered]);
|
|
3628
|
-
|
|
4237
|
+
useEffect18(() => {
|
|
3629
4238
|
if (!isPopupOpen) {
|
|
3630
4239
|
return;
|
|
3631
4240
|
}
|
|
@@ -3641,7 +4250,7 @@ function CopilotPopupView({
|
|
|
3641
4250
|
window.addEventListener("keydown", handleKeyDown);
|
|
3642
4251
|
return () => window.removeEventListener("keydown", handleKeyDown);
|
|
3643
4252
|
}, [isPopupOpen, setModalOpen]);
|
|
3644
|
-
|
|
4253
|
+
useEffect18(() => {
|
|
3645
4254
|
if (!isPopupOpen) {
|
|
3646
4255
|
return;
|
|
3647
4256
|
}
|
|
@@ -3650,7 +4259,7 @@ function CopilotPopupView({
|
|
|
3650
4259
|
}, 200);
|
|
3651
4260
|
return () => clearTimeout(focusTimer);
|
|
3652
4261
|
}, [isPopupOpen]);
|
|
3653
|
-
|
|
4262
|
+
useEffect18(() => {
|
|
3654
4263
|
if (!isPopupOpen || !clickOutsideToClose) {
|
|
3655
4264
|
return;
|
|
3656
4265
|
}
|
|
@@ -3675,10 +4284,15 @@ function CopilotPopupView({
|
|
|
3675
4284
|
document.addEventListener("pointerdown", handlePointerDown);
|
|
3676
4285
|
return () => document.removeEventListener("pointerdown", handlePointerDown);
|
|
3677
4286
|
}, [isPopupOpen, clickOutsideToClose, setModalOpen]);
|
|
3678
|
-
const headerElement =
|
|
4287
|
+
const headerElement = useMemo7(() => renderSlot(header, CopilotModalHeader, {
|
|
4288
|
+
onThreadListClick: handleThreadListToggle,
|
|
4289
|
+
showThreadListButton,
|
|
4290
|
+
onNewThreadClick: handleNewThread,
|
|
4291
|
+
showNewThreadButton
|
|
4292
|
+
}), [header, handleThreadListToggle, showThreadListButton, handleNewThread, showNewThreadButton]);
|
|
3679
4293
|
const resolvedWidth = dimensionToCss(width, DEFAULT_POPUP_WIDTH);
|
|
3680
4294
|
const resolvedHeight = dimensionToCss(height, DEFAULT_POPUP_HEIGHT);
|
|
3681
|
-
const popupStyle =
|
|
4295
|
+
const popupStyle = useMemo7(
|
|
3682
4296
|
() => ({
|
|
3683
4297
|
"--copilot-popup-width": resolvedWidth,
|
|
3684
4298
|
"--copilot-popup-height": resolvedHeight,
|
|
@@ -3692,14 +4306,14 @@ function CopilotPopupView({
|
|
|
3692
4306
|
[resolvedHeight, resolvedWidth]
|
|
3693
4307
|
);
|
|
3694
4308
|
const popupAnimationClass = isPopupOpen && !isAnimatingOut ? "pointer-events-auto translate-y-0 opacity-100 md:scale-100" : "pointer-events-none translate-y-4 opacity-0 md:translate-y-5 md:scale-[0.95]";
|
|
3695
|
-
const popupContent = isRendered ? /* @__PURE__ */
|
|
4309
|
+
const popupContent = isRendered ? /* @__PURE__ */ jsx23(
|
|
3696
4310
|
"div",
|
|
3697
4311
|
{
|
|
3698
4312
|
className: cn(
|
|
3699
4313
|
"fixed inset-0 z-[1200] flex max-w-full flex-col items-stretch",
|
|
3700
4314
|
"md:inset-auto md:bottom-24 md:right-6 md:items-end md:gap-4"
|
|
3701
4315
|
),
|
|
3702
|
-
children: /* @__PURE__ */
|
|
4316
|
+
children: /* @__PURE__ */ jsxs15(
|
|
3703
4317
|
"div",
|
|
3704
4318
|
{
|
|
3705
4319
|
ref: containerRef,
|
|
@@ -3708,19 +4322,40 @@ function CopilotPopupView({
|
|
|
3708
4322
|
"aria-label": labels.modalHeaderTitle,
|
|
3709
4323
|
"data-copilot-popup": true,
|
|
3710
4324
|
className: cn(
|
|
3711
|
-
"relative flex h-full w-full flex-col
|
|
4325
|
+
"relative flex h-full w-full flex-col bg-background text-foreground",
|
|
3712
4326
|
"origin-bottom focus:outline-none transform-gpu transition-transform transition-opacity duration-200 ease-out",
|
|
3713
4327
|
"md:transition-transform md:transition-opacity",
|
|
3714
4328
|
"rounded-none border border-border/0 shadow-none ring-0",
|
|
3715
4329
|
"md:h-[var(--copilot-popup-height)] md:w-[var(--copilot-popup-width)]",
|
|
3716
4330
|
"md:max-h-[var(--copilot-popup-max-height)] md:max-w-[var(--copilot-popup-max-width)]",
|
|
3717
4331
|
"md:origin-bottom-right md:rounded-2xl md:border-border md:shadow-xl md:ring-1 md:ring-border/40",
|
|
4332
|
+
"overflow-hidden",
|
|
4333
|
+
// Clip the sliding panel
|
|
3718
4334
|
popupAnimationClass
|
|
3719
4335
|
),
|
|
3720
4336
|
style: popupStyle,
|
|
3721
4337
|
children: [
|
|
4338
|
+
isThreadListOpen && /* @__PURE__ */ jsx23(
|
|
4339
|
+
"div",
|
|
4340
|
+
{
|
|
4341
|
+
className: "absolute inset-0 z-50",
|
|
4342
|
+
onClick: handleThreadListToggle,
|
|
4343
|
+
"aria-hidden": "true"
|
|
4344
|
+
}
|
|
4345
|
+
),
|
|
4346
|
+
/* @__PURE__ */ jsx23(
|
|
4347
|
+
"div",
|
|
4348
|
+
{
|
|
4349
|
+
className: cn(
|
|
4350
|
+
"absolute left-0 top-0 h-full w-80 bg-background border-r border-border z-[60]",
|
|
4351
|
+
"transition-transform duration-300 ease-out",
|
|
4352
|
+
isThreadListOpen ? "translate-x-0" : "-translate-x-full"
|
|
4353
|
+
),
|
|
4354
|
+
children: /* @__PURE__ */ jsx23(CopilotThreadList, { onThreadSelect: handleThreadSelect })
|
|
4355
|
+
}
|
|
4356
|
+
),
|
|
3722
4357
|
headerElement,
|
|
3723
|
-
/* @__PURE__ */
|
|
4358
|
+
/* @__PURE__ */ jsx23("div", { className: "flex-1 overflow-hidden", "data-popup-chat": true, children: /* @__PURE__ */ jsx23(
|
|
3724
4359
|
CopilotChatView_default,
|
|
3725
4360
|
{
|
|
3726
4361
|
...restProps,
|
|
@@ -3732,32 +4367,34 @@ function CopilotPopupView({
|
|
|
3732
4367
|
)
|
|
3733
4368
|
}
|
|
3734
4369
|
) : null;
|
|
3735
|
-
return /* @__PURE__ */
|
|
3736
|
-
/* @__PURE__ */
|
|
4370
|
+
return /* @__PURE__ */ jsxs15(Fragment9, { children: [
|
|
4371
|
+
/* @__PURE__ */ jsx23(CopilotChatToggleButton_default, {}),
|
|
3737
4372
|
popupContent
|
|
3738
4373
|
] });
|
|
3739
4374
|
}
|
|
3740
4375
|
CopilotPopupView.displayName = "CopilotPopupView";
|
|
3741
4376
|
|
|
3742
4377
|
// src/components/chat/CopilotSidebar.tsx
|
|
3743
|
-
import { useMemo as
|
|
3744
|
-
import { jsx as
|
|
3745
|
-
function CopilotSidebar({ header, defaultOpen, width, ...chatProps }) {
|
|
3746
|
-
const SidebarViewOverride =
|
|
4378
|
+
import { useMemo as useMemo8 } from "react";
|
|
4379
|
+
import { jsx as jsx24 } from "react/jsx-runtime";
|
|
4380
|
+
function CopilotSidebar({ header, defaultOpen, width, showThreadListButton, showNewThreadButton, ...chatProps }) {
|
|
4381
|
+
const SidebarViewOverride = useMemo8(() => {
|
|
3747
4382
|
const Component = (viewProps) => {
|
|
3748
|
-
const { header: viewHeader, width: viewWidth, ...restProps } = viewProps;
|
|
3749
|
-
return /* @__PURE__ */
|
|
4383
|
+
const { header: viewHeader, width: viewWidth, showThreadListButton: viewShowThreadList, showNewThreadButton: viewShowNewThread, ...restProps } = viewProps;
|
|
4384
|
+
return /* @__PURE__ */ jsx24(
|
|
3750
4385
|
CopilotSidebarView,
|
|
3751
4386
|
{
|
|
3752
4387
|
...restProps,
|
|
3753
4388
|
header: header ?? viewHeader,
|
|
3754
|
-
width: width ?? viewWidth
|
|
4389
|
+
width: width ?? viewWidth,
|
|
4390
|
+
showThreadListButton: showThreadListButton ?? viewShowThreadList,
|
|
4391
|
+
showNewThreadButton: showNewThreadButton ?? viewShowNewThread
|
|
3755
4392
|
}
|
|
3756
4393
|
);
|
|
3757
4394
|
};
|
|
3758
4395
|
return Object.assign(Component, CopilotChatView_default);
|
|
3759
|
-
}, [header, width]);
|
|
3760
|
-
return /* @__PURE__ */
|
|
4396
|
+
}, [header, width, showThreadListButton, showNewThreadButton]);
|
|
4397
|
+
return /* @__PURE__ */ jsx24(
|
|
3761
4398
|
CopilotChat,
|
|
3762
4399
|
{
|
|
3763
4400
|
...chatProps,
|
|
@@ -3769,39 +4406,45 @@ function CopilotSidebar({ header, defaultOpen, width, ...chatProps }) {
|
|
|
3769
4406
|
CopilotSidebar.displayName = "CopilotSidebar";
|
|
3770
4407
|
|
|
3771
4408
|
// src/components/chat/CopilotPopup.tsx
|
|
3772
|
-
import { useMemo as
|
|
3773
|
-
import { jsx as
|
|
4409
|
+
import { useMemo as useMemo9 } from "react";
|
|
4410
|
+
import { jsx as jsx25 } from "react/jsx-runtime";
|
|
3774
4411
|
function CopilotPopup({
|
|
3775
4412
|
header,
|
|
3776
4413
|
defaultOpen,
|
|
3777
4414
|
width,
|
|
3778
4415
|
height,
|
|
3779
4416
|
clickOutsideToClose,
|
|
4417
|
+
showThreadListButton,
|
|
4418
|
+
showNewThreadButton,
|
|
3780
4419
|
...chatProps
|
|
3781
4420
|
}) {
|
|
3782
|
-
const PopupViewOverride =
|
|
4421
|
+
const PopupViewOverride = useMemo9(() => {
|
|
3783
4422
|
const Component = (viewProps) => {
|
|
3784
4423
|
const {
|
|
3785
4424
|
header: viewHeader,
|
|
3786
4425
|
width: viewWidth,
|
|
3787
4426
|
height: viewHeight,
|
|
3788
4427
|
clickOutsideToClose: viewClickOutsideToClose,
|
|
4428
|
+
showThreadListButton: viewShowThreadList,
|
|
4429
|
+
showNewThreadButton: viewShowNewThread,
|
|
3789
4430
|
...restProps
|
|
3790
4431
|
} = viewProps;
|
|
3791
|
-
return /* @__PURE__ */
|
|
4432
|
+
return /* @__PURE__ */ jsx25(
|
|
3792
4433
|
CopilotPopupView,
|
|
3793
4434
|
{
|
|
3794
4435
|
...restProps,
|
|
3795
4436
|
header: header ?? viewHeader,
|
|
3796
4437
|
width: width ?? viewWidth,
|
|
3797
4438
|
height: height ?? viewHeight,
|
|
3798
|
-
clickOutsideToClose: clickOutsideToClose ?? viewClickOutsideToClose
|
|
4439
|
+
clickOutsideToClose: clickOutsideToClose ?? viewClickOutsideToClose,
|
|
4440
|
+
showThreadListButton: showThreadListButton ?? viewShowThreadList,
|
|
4441
|
+
showNewThreadButton: showNewThreadButton ?? viewShowNewThread
|
|
3799
4442
|
}
|
|
3800
4443
|
);
|
|
3801
4444
|
};
|
|
3802
4445
|
return Object.assign(Component, CopilotChatView_default);
|
|
3803
|
-
}, [clickOutsideToClose, header, height, width]);
|
|
3804
|
-
return /* @__PURE__ */
|
|
4446
|
+
}, [clickOutsideToClose, header, height, width, showThreadListButton, showNewThreadButton]);
|
|
4447
|
+
return /* @__PURE__ */ jsx25(
|
|
3805
4448
|
CopilotChat,
|
|
3806
4449
|
{
|
|
3807
4450
|
...chatProps,
|
|
@@ -3825,25 +4468,25 @@ function defineToolCallRenderer(def) {
|
|
|
3825
4468
|
}
|
|
3826
4469
|
|
|
3827
4470
|
// src/components/WildcardToolCallRender.tsx
|
|
3828
|
-
import { useState as
|
|
3829
|
-
import { jsx as
|
|
4471
|
+
import { useState as useState17 } from "react";
|
|
4472
|
+
import { jsx as jsx26, jsxs as jsxs16 } from "react/jsx-runtime";
|
|
3830
4473
|
var WildcardToolCallRender = defineToolCallRenderer({
|
|
3831
4474
|
name: "*",
|
|
3832
4475
|
render: ({ args, result, name, status }) => {
|
|
3833
|
-
const [isExpanded, setIsExpanded] =
|
|
4476
|
+
const [isExpanded, setIsExpanded] = useState17(false);
|
|
3834
4477
|
const statusString = String(status);
|
|
3835
4478
|
const isActive = statusString === "inProgress" || statusString === "executing";
|
|
3836
4479
|
const isComplete = statusString === "complete";
|
|
3837
4480
|
const statusStyles = isActive ? "bg-amber-100 text-amber-800 dark:bg-amber-500/15 dark:text-amber-400" : isComplete ? "bg-emerald-100 text-emerald-800 dark:bg-emerald-500/15 dark:text-emerald-400" : "bg-zinc-100 text-zinc-800 dark:bg-zinc-700/40 dark:text-zinc-300";
|
|
3838
|
-
return /* @__PURE__ */
|
|
3839
|
-
/* @__PURE__ */
|
|
4481
|
+
return /* @__PURE__ */ jsx26("div", { className: "mt-2 pb-2", children: /* @__PURE__ */ jsxs16("div", { className: "rounded-xl border border-zinc-200/60 dark:border-zinc-800/60 bg-white/70 dark:bg-zinc-900/50 shadow-sm backdrop-blur p-4", children: [
|
|
4482
|
+
/* @__PURE__ */ jsxs16(
|
|
3840
4483
|
"div",
|
|
3841
4484
|
{
|
|
3842
4485
|
className: "flex items-center justify-between gap-3 cursor-pointer",
|
|
3843
4486
|
onClick: () => setIsExpanded(!isExpanded),
|
|
3844
4487
|
children: [
|
|
3845
|
-
/* @__PURE__ */
|
|
3846
|
-
/* @__PURE__ */
|
|
4488
|
+
/* @__PURE__ */ jsxs16("div", { className: "flex items-center gap-2 min-w-0", children: [
|
|
4489
|
+
/* @__PURE__ */ jsx26(
|
|
3847
4490
|
"svg",
|
|
3848
4491
|
{
|
|
3849
4492
|
className: `h-4 w-4 text-zinc-500 dark:text-zinc-400 transition-transform ${isExpanded ? "rotate-90" : ""}`,
|
|
@@ -3851,7 +4494,7 @@ var WildcardToolCallRender = defineToolCallRenderer({
|
|
|
3851
4494
|
viewBox: "0 0 24 24",
|
|
3852
4495
|
strokeWidth: 2,
|
|
3853
4496
|
stroke: "currentColor",
|
|
3854
|
-
children: /* @__PURE__ */
|
|
4497
|
+
children: /* @__PURE__ */ jsx26(
|
|
3855
4498
|
"path",
|
|
3856
4499
|
{
|
|
3857
4500
|
strokeLinecap: "round",
|
|
@@ -3861,10 +4504,10 @@ var WildcardToolCallRender = defineToolCallRenderer({
|
|
|
3861
4504
|
)
|
|
3862
4505
|
}
|
|
3863
4506
|
),
|
|
3864
|
-
/* @__PURE__ */
|
|
3865
|
-
/* @__PURE__ */
|
|
4507
|
+
/* @__PURE__ */ jsx26("span", { className: "inline-block h-2 w-2 rounded-full bg-blue-500" }),
|
|
4508
|
+
/* @__PURE__ */ jsx26("span", { className: "truncate text-sm font-medium text-zinc-900 dark:text-zinc-100", children: name })
|
|
3866
4509
|
] }),
|
|
3867
|
-
/* @__PURE__ */
|
|
4510
|
+
/* @__PURE__ */ jsx26(
|
|
3868
4511
|
"span",
|
|
3869
4512
|
{
|
|
3870
4513
|
className: `inline-flex items-center rounded-full px-2 py-1 text-xs font-medium ${statusStyles}`,
|
|
@@ -3874,14 +4517,14 @@ var WildcardToolCallRender = defineToolCallRenderer({
|
|
|
3874
4517
|
]
|
|
3875
4518
|
}
|
|
3876
4519
|
),
|
|
3877
|
-
isExpanded && /* @__PURE__ */
|
|
3878
|
-
/* @__PURE__ */
|
|
3879
|
-
/* @__PURE__ */
|
|
3880
|
-
/* @__PURE__ */
|
|
4520
|
+
isExpanded && /* @__PURE__ */ jsxs16("div", { className: "mt-3 grid gap-4", children: [
|
|
4521
|
+
/* @__PURE__ */ jsxs16("div", { children: [
|
|
4522
|
+
/* @__PURE__ */ jsx26("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Arguments" }),
|
|
4523
|
+
/* @__PURE__ */ jsx26("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: JSON.stringify(args ?? {}, null, 2) })
|
|
3881
4524
|
] }),
|
|
3882
|
-
result !== void 0 && /* @__PURE__ */
|
|
3883
|
-
/* @__PURE__ */
|
|
3884
|
-
/* @__PURE__ */
|
|
4525
|
+
result !== void 0 && /* @__PURE__ */ jsxs16("div", { children: [
|
|
4526
|
+
/* @__PURE__ */ jsx26("div", { className: "text-xs uppercase tracking-wide text-zinc-500 dark:text-zinc-400", children: "Result" }),
|
|
4527
|
+
/* @__PURE__ */ jsx26("pre", { className: "mt-2 max-h-64 overflow-auto rounded-md bg-zinc-50 dark:bg-zinc-800/60 p-3 text-xs leading-relaxed text-zinc-800 dark:text-zinc-200 whitespace-pre-wrap break-words", children: typeof result === "string" ? result : JSON.stringify(result, null, 2) })
|
|
3885
4528
|
] })
|
|
3886
4529
|
] })
|
|
3887
4530
|
] }) });
|
|
@@ -3911,6 +4554,7 @@ export {
|
|
|
3911
4554
|
CopilotPopupView,
|
|
3912
4555
|
CopilotSidebar,
|
|
3913
4556
|
CopilotSidebarView,
|
|
4557
|
+
CopilotThreadList,
|
|
3914
4558
|
WildcardToolCallRender,
|
|
3915
4559
|
defineToolCallRenderer,
|
|
3916
4560
|
useAgent,
|
|
@@ -3922,6 +4566,8 @@ export {
|
|
|
3922
4566
|
useHumanInTheLoop,
|
|
3923
4567
|
useRenderCustomMessages,
|
|
3924
4568
|
useRenderToolCall,
|
|
3925
|
-
useSuggestions
|
|
4569
|
+
useSuggestions,
|
|
4570
|
+
useThreadSwitch,
|
|
4571
|
+
useThreads
|
|
3926
4572
|
};
|
|
3927
4573
|
//# sourceMappingURL=index.mjs.map
|