@gendive/chatllm 0.7.0 → 0.8.1
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/react/index.d.mts +18 -0
- package/dist/react/index.d.ts +18 -0
- package/dist/react/index.js +196 -68
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +194 -66
- package/dist/react/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/react/index.d.mts
CHANGED
|
@@ -246,6 +246,13 @@ interface ChatUIProps {
|
|
|
246
246
|
onSessionChange?: (session: ChatSession | null) => void;
|
|
247
247
|
/** 에러 핸들러 */
|
|
248
248
|
onError?: (error: Error) => void;
|
|
249
|
+
/** @Todo vibecode - 세션 제목 변경 핸들러 */
|
|
250
|
+
onTitleChange?: (sessionId: string, newTitle: string) => void;
|
|
251
|
+
/**
|
|
252
|
+
* @description 첫 메시지 전송 시 LLM으로 제목 생성 콜백
|
|
253
|
+
* @Todo vibecode - 자동 제목 생성 기능
|
|
254
|
+
*/
|
|
255
|
+
generateTitle?: (firstMessage: string) => Promise<string> | string;
|
|
249
256
|
/** 재압축 임계값 - 새 메시지 수 (기본: 10) */
|
|
250
257
|
recompressionThreshold?: number;
|
|
251
258
|
/** 토큰 한도 (기본: 8000) */
|
|
@@ -300,6 +307,8 @@ interface SidebarProps {
|
|
|
300
307
|
onSelectSession: (id: string) => void;
|
|
301
308
|
onNewSession: () => void;
|
|
302
309
|
onDeleteSession: (id: string) => void;
|
|
310
|
+
/** @Todo vibecode - 세션 제목 변경 핸들러 */
|
|
311
|
+
onRenameSession?: (id: string, newTitle: string) => void;
|
|
303
312
|
isOpen: boolean;
|
|
304
313
|
onToggle: () => void;
|
|
305
314
|
}
|
|
@@ -404,6 +413,8 @@ interface UseChatUIReturn {
|
|
|
404
413
|
newSession: () => void;
|
|
405
414
|
selectSession: (id: string) => void;
|
|
406
415
|
deleteSession: (id: string) => void;
|
|
416
|
+
/** @Todo vibecode - 세션 제목 변경 함수 */
|
|
417
|
+
renameSession: (id: string, newTitle: string) => void;
|
|
407
418
|
setModel: (model: string) => void;
|
|
408
419
|
toggleSidebar: () => void;
|
|
409
420
|
openSettings: () => void;
|
|
@@ -465,6 +476,13 @@ interface UseChatUIOptions {
|
|
|
465
476
|
onSessionChange?: (session: ChatSession | null) => void;
|
|
466
477
|
/** 에러 핸들러 */
|
|
467
478
|
onError?: (error: Error) => void;
|
|
479
|
+
/** @Todo vibecode - 세션 제목 변경 핸들러 */
|
|
480
|
+
onTitleChange?: (sessionId: string, newTitle: string) => void;
|
|
481
|
+
/**
|
|
482
|
+
* @description 첫 메시지 전송 시 LLM으로 제목 생성 콜백
|
|
483
|
+
* @Todo vibecode - 자동 제목 생성 기능
|
|
484
|
+
*/
|
|
485
|
+
generateTitle?: (firstMessage: string) => Promise<string> | string;
|
|
468
486
|
/** 글로벌 메모리 사용 여부 (기본: true) */
|
|
469
487
|
useGlobalMemoryEnabled?: boolean;
|
|
470
488
|
/** 글로벌 메모리 설정 */
|
package/dist/react/index.d.ts
CHANGED
|
@@ -246,6 +246,13 @@ interface ChatUIProps {
|
|
|
246
246
|
onSessionChange?: (session: ChatSession | null) => void;
|
|
247
247
|
/** 에러 핸들러 */
|
|
248
248
|
onError?: (error: Error) => void;
|
|
249
|
+
/** @Todo vibecode - 세션 제목 변경 핸들러 */
|
|
250
|
+
onTitleChange?: (sessionId: string, newTitle: string) => void;
|
|
251
|
+
/**
|
|
252
|
+
* @description 첫 메시지 전송 시 LLM으로 제목 생성 콜백
|
|
253
|
+
* @Todo vibecode - 자동 제목 생성 기능
|
|
254
|
+
*/
|
|
255
|
+
generateTitle?: (firstMessage: string) => Promise<string> | string;
|
|
249
256
|
/** 재압축 임계값 - 새 메시지 수 (기본: 10) */
|
|
250
257
|
recompressionThreshold?: number;
|
|
251
258
|
/** 토큰 한도 (기본: 8000) */
|
|
@@ -300,6 +307,8 @@ interface SidebarProps {
|
|
|
300
307
|
onSelectSession: (id: string) => void;
|
|
301
308
|
onNewSession: () => void;
|
|
302
309
|
onDeleteSession: (id: string) => void;
|
|
310
|
+
/** @Todo vibecode - 세션 제목 변경 핸들러 */
|
|
311
|
+
onRenameSession?: (id: string, newTitle: string) => void;
|
|
303
312
|
isOpen: boolean;
|
|
304
313
|
onToggle: () => void;
|
|
305
314
|
}
|
|
@@ -404,6 +413,8 @@ interface UseChatUIReturn {
|
|
|
404
413
|
newSession: () => void;
|
|
405
414
|
selectSession: (id: string) => void;
|
|
406
415
|
deleteSession: (id: string) => void;
|
|
416
|
+
/** @Todo vibecode - 세션 제목 변경 함수 */
|
|
417
|
+
renameSession: (id: string, newTitle: string) => void;
|
|
407
418
|
setModel: (model: string) => void;
|
|
408
419
|
toggleSidebar: () => void;
|
|
409
420
|
openSettings: () => void;
|
|
@@ -465,6 +476,13 @@ interface UseChatUIOptions {
|
|
|
465
476
|
onSessionChange?: (session: ChatSession | null) => void;
|
|
466
477
|
/** 에러 핸들러 */
|
|
467
478
|
onError?: (error: Error) => void;
|
|
479
|
+
/** @Todo vibecode - 세션 제목 변경 핸들러 */
|
|
480
|
+
onTitleChange?: (sessionId: string, newTitle: string) => void;
|
|
481
|
+
/**
|
|
482
|
+
* @description 첫 메시지 전송 시 LLM으로 제목 생성 콜백
|
|
483
|
+
* @Todo vibecode - 자동 제목 생성 기능
|
|
484
|
+
*/
|
|
485
|
+
generateTitle?: (firstMessage: string) => Promise<string> | string;
|
|
468
486
|
/** 글로벌 메모리 사용 여부 (기본: true) */
|
|
469
487
|
useGlobalMemoryEnabled?: boolean;
|
|
470
488
|
/** 글로벌 메모리 설정 */
|
package/dist/react/index.js
CHANGED
|
@@ -48,7 +48,7 @@ __export(index_exports, {
|
|
|
48
48
|
module.exports = __toCommonJS(index_exports);
|
|
49
49
|
|
|
50
50
|
// src/react/ChatUI.tsx
|
|
51
|
-
var
|
|
51
|
+
var import_react13 = __toESM(require("react"));
|
|
52
52
|
|
|
53
53
|
// src/react/hooks/useChatUI.ts
|
|
54
54
|
var import_react3 = require("react");
|
|
@@ -563,6 +563,8 @@ var useChatUI = (options) => {
|
|
|
563
563
|
onSendMessage,
|
|
564
564
|
onSessionChange,
|
|
565
565
|
onError,
|
|
566
|
+
onTitleChange,
|
|
567
|
+
generateTitle: generateTitleCallback,
|
|
566
568
|
// Memory options
|
|
567
569
|
useGlobalMemoryEnabled = true,
|
|
568
570
|
globalMemoryConfig,
|
|
@@ -817,6 +819,15 @@ ${newConversation}
|
|
|
817
819
|
return filtered;
|
|
818
820
|
});
|
|
819
821
|
}, [currentSessionId, storageKey]);
|
|
822
|
+
const renameSession = (0, import_react3.useCallback)((id, newTitle) => {
|
|
823
|
+
if (!newTitle.trim()) return;
|
|
824
|
+
setSessions(
|
|
825
|
+
(prev) => prev.map(
|
|
826
|
+
(s) => s.id === id ? { ...s, title: newTitle.trim(), updatedAt: Date.now() } : s
|
|
827
|
+
)
|
|
828
|
+
);
|
|
829
|
+
onTitleChange?.(id, newTitle.trim());
|
|
830
|
+
}, [onTitleChange]);
|
|
820
831
|
const setModel = (0, import_react3.useCallback)((model) => {
|
|
821
832
|
setSelectedModel(model);
|
|
822
833
|
if (currentSessionId) {
|
|
@@ -896,6 +907,7 @@ ${finalContent}`;
|
|
|
896
907
|
setQuotedText(null);
|
|
897
908
|
setSelectedAction(null);
|
|
898
909
|
const capturedSessionId = sessionId;
|
|
910
|
+
const isFirstMessage = !sessions.find((s) => s.id === capturedSessionId)?.messages.length;
|
|
899
911
|
setSessions(
|
|
900
912
|
(prev) => prev.map((s) => {
|
|
901
913
|
if (s.id === capturedSessionId) {
|
|
@@ -910,6 +922,19 @@ ${finalContent}`;
|
|
|
910
922
|
return s;
|
|
911
923
|
})
|
|
912
924
|
);
|
|
925
|
+
if (isFirstMessage && generateTitleCallback) {
|
|
926
|
+
Promise.resolve(generateTitleCallback(finalContent)).then((generatedTitle) => {
|
|
927
|
+
if (generatedTitle && generatedTitle.trim()) {
|
|
928
|
+
setSessions(
|
|
929
|
+
(prev) => prev.map(
|
|
930
|
+
(s) => s.id === capturedSessionId ? { ...s, title: generatedTitle.trim(), updatedAt: Date.now() } : s
|
|
931
|
+
)
|
|
932
|
+
);
|
|
933
|
+
onTitleChange?.(capturedSessionId, generatedTitle.trim());
|
|
934
|
+
}
|
|
935
|
+
}).catch(() => {
|
|
936
|
+
});
|
|
937
|
+
}
|
|
913
938
|
setIsLoading(true);
|
|
914
939
|
abortControllerRef.current = new AbortController();
|
|
915
940
|
try {
|
|
@@ -1109,7 +1134,9 @@ ${contextSummary}` },
|
|
|
1109
1134
|
buildSystemPrompt,
|
|
1110
1135
|
compressContext,
|
|
1111
1136
|
onSendMessage,
|
|
1112
|
-
onError
|
|
1137
|
+
onError,
|
|
1138
|
+
generateTitleCallback,
|
|
1139
|
+
onTitleChange
|
|
1113
1140
|
]);
|
|
1114
1141
|
const saveEdit = (0, import_react3.useCallback)(async (content) => {
|
|
1115
1142
|
if (!editingMessageId || !currentSession || !currentSessionId) return;
|
|
@@ -1335,6 +1362,7 @@ ${currentSession.contextSummary}` },
|
|
|
1335
1362
|
newSession,
|
|
1336
1363
|
selectSession,
|
|
1337
1364
|
deleteSession,
|
|
1365
|
+
renameSession,
|
|
1338
1366
|
setModel,
|
|
1339
1367
|
toggleSidebar,
|
|
1340
1368
|
openSettings,
|
|
@@ -1365,6 +1393,9 @@ ${currentSession.contextSummary}` },
|
|
|
1365
1393
|
};
|
|
1366
1394
|
};
|
|
1367
1395
|
|
|
1396
|
+
// src/react/components/ChatSidebar.tsx
|
|
1397
|
+
var import_react4 = require("react");
|
|
1398
|
+
|
|
1368
1399
|
// src/react/components/Icon.tsx
|
|
1369
1400
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
1370
1401
|
var Icon = ({
|
|
@@ -1475,9 +1506,44 @@ var ChatSidebar = ({
|
|
|
1475
1506
|
onSelectSession,
|
|
1476
1507
|
onNewSession,
|
|
1477
1508
|
onDeleteSession,
|
|
1509
|
+
onRenameSession,
|
|
1478
1510
|
isOpen,
|
|
1479
1511
|
onToggle
|
|
1480
1512
|
}) => {
|
|
1513
|
+
const [editingId, setEditingId] = (0, import_react4.useState)(null);
|
|
1514
|
+
const [editingTitle, setEditingTitle] = (0, import_react4.useState)("");
|
|
1515
|
+
const inputRef = (0, import_react4.useRef)(null);
|
|
1516
|
+
(0, import_react4.useEffect)(() => {
|
|
1517
|
+
if (editingId && inputRef.current) {
|
|
1518
|
+
inputRef.current.focus();
|
|
1519
|
+
inputRef.current.select();
|
|
1520
|
+
}
|
|
1521
|
+
}, [editingId]);
|
|
1522
|
+
const handleStartEdit = (session, e) => {
|
|
1523
|
+
e.stopPropagation();
|
|
1524
|
+
setEditingId(session.id);
|
|
1525
|
+
setEditingTitle(session.title);
|
|
1526
|
+
};
|
|
1527
|
+
const handleSaveEdit = () => {
|
|
1528
|
+
if (editingId && editingTitle.trim() && onRenameSession) {
|
|
1529
|
+
onRenameSession(editingId, editingTitle.trim());
|
|
1530
|
+
}
|
|
1531
|
+
setEditingId(null);
|
|
1532
|
+
setEditingTitle("");
|
|
1533
|
+
};
|
|
1534
|
+
const handleCancelEdit = () => {
|
|
1535
|
+
setEditingId(null);
|
|
1536
|
+
setEditingTitle("");
|
|
1537
|
+
};
|
|
1538
|
+
const handleKeyDown = (e) => {
|
|
1539
|
+
if (e.key === "Enter") {
|
|
1540
|
+
e.preventDefault();
|
|
1541
|
+
handleSaveEdit();
|
|
1542
|
+
} else if (e.key === "Escape") {
|
|
1543
|
+
e.preventDefault();
|
|
1544
|
+
handleCancelEdit();
|
|
1545
|
+
}
|
|
1546
|
+
};
|
|
1481
1547
|
return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1482
1548
|
"aside",
|
|
1483
1549
|
{
|
|
@@ -1587,7 +1653,30 @@ var ChatSidebar = ({
|
|
|
1587
1653
|
},
|
|
1588
1654
|
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: [
|
|
1589
1655
|
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
|
|
1590
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1656
|
+
editingId === session.id ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1657
|
+
"input",
|
|
1658
|
+
{
|
|
1659
|
+
ref: inputRef,
|
|
1660
|
+
type: "text",
|
|
1661
|
+
value: editingTitle,
|
|
1662
|
+
onChange: (e) => setEditingTitle(e.target.value),
|
|
1663
|
+
onKeyDown: handleKeyDown,
|
|
1664
|
+
onBlur: handleSaveEdit,
|
|
1665
|
+
onClick: (e) => e.stopPropagation(),
|
|
1666
|
+
"aria-label": "\uC138\uC158 \uC81C\uBAA9 \uD3B8\uC9D1",
|
|
1667
|
+
style: {
|
|
1668
|
+
width: "100%",
|
|
1669
|
+
padding: "4px 8px",
|
|
1670
|
+
fontSize: "14px",
|
|
1671
|
+
fontWeight: session.id === currentSessionId ? 500 : 400,
|
|
1672
|
+
color: "var(--chatllm-text, #1f2937)",
|
|
1673
|
+
backgroundColor: "var(--chatllm-bg, #ffffff)",
|
|
1674
|
+
border: "1px solid var(--chatllm-primary, #3b82f6)",
|
|
1675
|
+
borderRadius: "4px",
|
|
1676
|
+
outline: "none"
|
|
1677
|
+
}
|
|
1678
|
+
}
|
|
1679
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1591
1680
|
"div",
|
|
1592
1681
|
{
|
|
1593
1682
|
style: {
|
|
@@ -1613,31 +1702,57 @@ var ChatSidebar = ({
|
|
|
1613
1702
|
}
|
|
1614
1703
|
)
|
|
1615
1704
|
] }),
|
|
1616
|
-
/* @__PURE__ */ (0, import_jsx_runtime2.
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
e
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1705
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "2px" }, children: [
|
|
1706
|
+
onRenameSession && editingId !== session.id && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1707
|
+
"button",
|
|
1708
|
+
{
|
|
1709
|
+
onClick: (e) => handleStartEdit(session, e),
|
|
1710
|
+
"aria-label": "\uC81C\uBAA9 \uD3B8\uC9D1",
|
|
1711
|
+
style: {
|
|
1712
|
+
padding: "4px",
|
|
1713
|
+
backgroundColor: "transparent",
|
|
1714
|
+
border: "none",
|
|
1715
|
+
borderRadius: "4px",
|
|
1716
|
+
cursor: "pointer",
|
|
1717
|
+
opacity: 0.5,
|
|
1718
|
+
transition: "opacity 0.2s"
|
|
1719
|
+
},
|
|
1720
|
+
onMouseOver: (e) => {
|
|
1721
|
+
e.currentTarget.style.opacity = "1";
|
|
1722
|
+
},
|
|
1723
|
+
onMouseOut: (e) => {
|
|
1724
|
+
e.currentTarget.style.opacity = "0.5";
|
|
1725
|
+
},
|
|
1726
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconSvg, { name: "pencil-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" })
|
|
1727
|
+
}
|
|
1728
|
+
),
|
|
1729
|
+
/* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
|
|
1730
|
+
"button",
|
|
1731
|
+
{
|
|
1732
|
+
onClick: (e) => {
|
|
1733
|
+
e.stopPropagation();
|
|
1734
|
+
onDeleteSession(session.id);
|
|
1735
|
+
},
|
|
1736
|
+
"aria-label": "\uC138\uC158 \uC0AD\uC81C",
|
|
1737
|
+
style: {
|
|
1738
|
+
padding: "4px",
|
|
1739
|
+
backgroundColor: "transparent",
|
|
1740
|
+
border: "none",
|
|
1741
|
+
borderRadius: "4px",
|
|
1742
|
+
cursor: "pointer",
|
|
1743
|
+
opacity: 0.5,
|
|
1744
|
+
transition: "opacity 0.2s"
|
|
1745
|
+
},
|
|
1746
|
+
onMouseOver: (e) => {
|
|
1747
|
+
e.currentTarget.style.opacity = "1";
|
|
1748
|
+
},
|
|
1749
|
+
onMouseOut: (e) => {
|
|
1750
|
+
e.currentTarget.style.opacity = "0.5";
|
|
1751
|
+
},
|
|
1752
|
+
children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconSvg, { name: "delete-bin-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" })
|
|
1753
|
+
}
|
|
1754
|
+
)
|
|
1755
|
+
] })
|
|
1641
1756
|
] })
|
|
1642
1757
|
},
|
|
1643
1758
|
session.id
|
|
@@ -1669,7 +1784,7 @@ var ChatSidebar = ({
|
|
|
1669
1784
|
};
|
|
1670
1785
|
|
|
1671
1786
|
// src/react/components/ChatHeader.tsx
|
|
1672
|
-
var
|
|
1787
|
+
var import_react5 = require("react");
|
|
1673
1788
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
1674
1789
|
var ChatHeader = ({
|
|
1675
1790
|
title,
|
|
@@ -1682,7 +1797,7 @@ var ChatHeader = ({
|
|
|
1682
1797
|
showModelSelector = true,
|
|
1683
1798
|
showSettings = true
|
|
1684
1799
|
}) => {
|
|
1685
|
-
const [modelDropdownOpen, setModelDropdownOpen] = (0,
|
|
1800
|
+
const [modelDropdownOpen, setModelDropdownOpen] = (0, import_react5.useState)(false);
|
|
1686
1801
|
const currentModel = models.find((m) => m.id === model);
|
|
1687
1802
|
return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
|
|
1688
1803
|
"header",
|
|
@@ -1936,7 +2051,7 @@ var ChatHeader = ({
|
|
|
1936
2051
|
};
|
|
1937
2052
|
|
|
1938
2053
|
// src/react/components/ChatInput.tsx
|
|
1939
|
-
var
|
|
2054
|
+
var import_react6 = require("react");
|
|
1940
2055
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1941
2056
|
var ChatInput = ({
|
|
1942
2057
|
value,
|
|
@@ -1952,9 +2067,9 @@ var ChatInput = ({
|
|
|
1952
2067
|
onActionSelect,
|
|
1953
2068
|
actions = []
|
|
1954
2069
|
}) => {
|
|
1955
|
-
const textareaRef = (0,
|
|
1956
|
-
const [actionMenuOpen, setActionMenuOpen] = (0,
|
|
1957
|
-
(0,
|
|
2070
|
+
const textareaRef = (0, import_react6.useRef)(null);
|
|
2071
|
+
const [actionMenuOpen, setActionMenuOpen] = (0, import_react6.useState)(false);
|
|
2072
|
+
(0, import_react6.useEffect)(() => {
|
|
1958
2073
|
if (textareaRef.current) {
|
|
1959
2074
|
textareaRef.current.style.height = "auto";
|
|
1960
2075
|
textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`;
|
|
@@ -2252,16 +2367,16 @@ var ChatInput = ({
|
|
|
2252
2367
|
};
|
|
2253
2368
|
|
|
2254
2369
|
// src/react/components/MessageList.tsx
|
|
2255
|
-
var
|
|
2370
|
+
var import_react10 = require("react");
|
|
2256
2371
|
|
|
2257
2372
|
// src/react/components/MessageBubble.tsx
|
|
2258
|
-
var
|
|
2373
|
+
var import_react9 = require("react");
|
|
2259
2374
|
|
|
2260
2375
|
// src/react/components/MarkdownRenderer.tsx
|
|
2261
|
-
var
|
|
2376
|
+
var import_react8 = __toESM(require("react"));
|
|
2262
2377
|
|
|
2263
2378
|
// src/react/components/LinkChip.tsx
|
|
2264
|
-
var
|
|
2379
|
+
var import_react7 = require("react");
|
|
2265
2380
|
var import_jsx_runtime5 = require("react/jsx-runtime");
|
|
2266
2381
|
var getDomain = (url) => {
|
|
2267
2382
|
try {
|
|
@@ -2315,7 +2430,7 @@ var LinkChip = ({
|
|
|
2315
2430
|
index,
|
|
2316
2431
|
style
|
|
2317
2432
|
}) => {
|
|
2318
|
-
const [isHovered, setIsHovered] = (0,
|
|
2433
|
+
const [isHovered, setIsHovered] = (0, import_react7.useState)(false);
|
|
2319
2434
|
const domain = getDomain(url);
|
|
2320
2435
|
const shortName = getShortName(domain);
|
|
2321
2436
|
const domainColor = getDomainColor(domain);
|
|
@@ -2610,7 +2725,7 @@ var MarkdownTable = ({ data }) => {
|
|
|
2610
2725
|
);
|
|
2611
2726
|
};
|
|
2612
2727
|
var CodeBlock = ({ language, code }) => {
|
|
2613
|
-
const [copied, setCopied] =
|
|
2728
|
+
const [copied, setCopied] = import_react8.default.useState(false);
|
|
2614
2729
|
const handleCopy = async () => {
|
|
2615
2730
|
try {
|
|
2616
2731
|
await navigator.clipboard.writeText(code);
|
|
@@ -2693,9 +2808,9 @@ var CodeBlock = ({ language, code }) => {
|
|
|
2693
2808
|
);
|
|
2694
2809
|
};
|
|
2695
2810
|
var ImageWithCopyButton = ({ src, alt, imageKey }) => {
|
|
2696
|
-
const [isHovered, setIsHovered] =
|
|
2697
|
-
const [copyState, setCopyState] =
|
|
2698
|
-
const imgRef =
|
|
2811
|
+
const [isHovered, setIsHovered] = import_react8.default.useState(false);
|
|
2812
|
+
const [copyState, setCopyState] = import_react8.default.useState("idle");
|
|
2813
|
+
const imgRef = import_react8.default.useRef(null);
|
|
2699
2814
|
const getImageBlob = async () => {
|
|
2700
2815
|
const img = imgRef.current;
|
|
2701
2816
|
if (img && img.complete && img.naturalWidth > 0) {
|
|
@@ -2911,7 +3026,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
|
|
|
2911
3026
|
);
|
|
2912
3027
|
};
|
|
2913
3028
|
var ChoiceButtons = ({ choices, title, onChoiceClick }) => {
|
|
2914
|
-
const [hoveredIndex, setHoveredIndex] =
|
|
3029
|
+
const [hoveredIndex, setHoveredIndex] = import_react8.default.useState(null);
|
|
2915
3030
|
return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
2916
3031
|
"div",
|
|
2917
3032
|
{
|
|
@@ -3034,7 +3149,7 @@ var SourceLinksSection = ({ links, label }) => {
|
|
|
3034
3149
|
);
|
|
3035
3150
|
};
|
|
3036
3151
|
var MarkdownRenderer = ({ content, className, onChoiceClick }) => {
|
|
3037
|
-
const rendered = (0,
|
|
3152
|
+
const rendered = (0, import_react8.useMemo)(() => {
|
|
3038
3153
|
const elements = [];
|
|
3039
3154
|
let processedContent = content;
|
|
3040
3155
|
const codeBlocks = [];
|
|
@@ -3132,7 +3247,7 @@ var MarkdownRenderer = ({ content, className, onChoiceClick }) => {
|
|
|
3132
3247
|
borderRadius: "0 8px 8px 0",
|
|
3133
3248
|
color: "var(--chatllm-text, #374151)"
|
|
3134
3249
|
},
|
|
3135
|
-
children: blockquoteLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
|
|
3250
|
+
children: blockquoteLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react8.default.Fragment, { children: [
|
|
3136
3251
|
parseInlineElements(line, `bq-line-${i}`),
|
|
3137
3252
|
i < blockquoteLines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("br", {})
|
|
3138
3253
|
] }, i))
|
|
@@ -3285,9 +3400,16 @@ var MarkdownRenderer = ({ content, className, onChoiceClick }) => {
|
|
|
3285
3400
|
return;
|
|
3286
3401
|
}
|
|
3287
3402
|
}
|
|
3288
|
-
|
|
3289
|
-
|
|
3290
|
-
|
|
3403
|
+
const hasImage = IMAGE_REGEX.test(line);
|
|
3404
|
+
if (hasImage) {
|
|
3405
|
+
elements.push(
|
|
3406
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { margin: "4px 0" }, children: parseInlineElements(line, `p-${lineIndex}`) }, `p-${lineIndex}`)
|
|
3407
|
+
);
|
|
3408
|
+
} else {
|
|
3409
|
+
elements.push(
|
|
3410
|
+
/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { margin: "4px 0" }, children: parseInlineElements(line, `p-${lineIndex}`) }, `p-${lineIndex}`)
|
|
3411
|
+
);
|
|
3412
|
+
}
|
|
3291
3413
|
});
|
|
3292
3414
|
flushList();
|
|
3293
3415
|
flushBlockquote();
|
|
@@ -3327,8 +3449,8 @@ var MessageBubble = ({
|
|
|
3327
3449
|
nextAssistantMessage,
|
|
3328
3450
|
onChoiceClick
|
|
3329
3451
|
}) => {
|
|
3330
|
-
const [showActions, setShowActions] = (0,
|
|
3331
|
-
const [showModelMenu, setShowModelMenu] = (0,
|
|
3452
|
+
const [showActions, setShowActions] = (0, import_react9.useState)(false);
|
|
3453
|
+
const [showModelMenu, setShowModelMenu] = (0, import_react9.useState)(false);
|
|
3332
3454
|
const isUser = message.role === "user";
|
|
3333
3455
|
const isAssistant = message.role === "assistant";
|
|
3334
3456
|
const relevantAlternatives = isUser ? alternatives : message.alternatives;
|
|
@@ -3721,14 +3843,14 @@ var MessageList = ({
|
|
|
3721
3843
|
editingId,
|
|
3722
3844
|
onChoiceClick
|
|
3723
3845
|
}) => {
|
|
3724
|
-
const messagesEndRef = (0,
|
|
3725
|
-
const containerRef = (0,
|
|
3726
|
-
const [selectedText, setSelectedText] = (0,
|
|
3727
|
-
const [selectionPosition, setSelectionPosition] = (0,
|
|
3728
|
-
(0,
|
|
3846
|
+
const messagesEndRef = (0, import_react10.useRef)(null);
|
|
3847
|
+
const containerRef = (0, import_react10.useRef)(null);
|
|
3848
|
+
const [selectedText, setSelectedText] = (0, import_react10.useState)("");
|
|
3849
|
+
const [selectionPosition, setSelectionPosition] = (0, import_react10.useState)(null);
|
|
3850
|
+
(0, import_react10.useEffect)(() => {
|
|
3729
3851
|
messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
|
|
3730
3852
|
}, [messages]);
|
|
3731
|
-
const handleMouseUp = (0,
|
|
3853
|
+
const handleMouseUp = (0, import_react10.useCallback)(() => {
|
|
3732
3854
|
const selection = window.getSelection();
|
|
3733
3855
|
const text = selection?.toString().trim();
|
|
3734
3856
|
if (text && text.length > 0) {
|
|
@@ -4105,7 +4227,7 @@ var EmptyState = ({
|
|
|
4105
4227
|
};
|
|
4106
4228
|
|
|
4107
4229
|
// src/react/components/MemoryPanel.tsx
|
|
4108
|
-
var
|
|
4230
|
+
var import_react11 = require("react");
|
|
4109
4231
|
var import_jsx_runtime10 = require("react/jsx-runtime");
|
|
4110
4232
|
var categoryLabels = {
|
|
4111
4233
|
context: "\uB300\uD654 \uCEE8\uD14D\uC2A4\uD2B8",
|
|
@@ -4127,8 +4249,8 @@ var MemoryPanel = ({
|
|
|
4127
4249
|
isOpen,
|
|
4128
4250
|
onToggle
|
|
4129
4251
|
}) => {
|
|
4130
|
-
const [expandedId, setExpandedId] = (0,
|
|
4131
|
-
const [activeTab, setActiveTab] = (0,
|
|
4252
|
+
const [expandedId, setExpandedId] = (0, import_react11.useState)(null);
|
|
4253
|
+
const [activeTab, setActiveTab] = (0, import_react11.useState)("all");
|
|
4132
4254
|
const filteredItems = activeTab === "all" ? items : items.filter((item) => item.category === activeTab);
|
|
4133
4255
|
const formatDate2 = (timestamp) => {
|
|
4134
4256
|
const date = new Date(timestamp);
|
|
@@ -4446,7 +4568,7 @@ var MemoryPanel = ({
|
|
|
4446
4568
|
};
|
|
4447
4569
|
|
|
4448
4570
|
// src/react/components/SettingsModal.tsx
|
|
4449
|
-
var
|
|
4571
|
+
var import_react12 = require("react");
|
|
4450
4572
|
var import_jsx_runtime11 = require("react/jsx-runtime");
|
|
4451
4573
|
var DEFAULT_PERSONALIZATION2 = {
|
|
4452
4574
|
responseStyle: {
|
|
@@ -4471,8 +4593,8 @@ var SettingsModal = ({
|
|
|
4471
4593
|
apiKeyLabel = "API Key",
|
|
4472
4594
|
apiKeyDescription = "Cloud \uBAA8\uB378 \uC0AC\uC6A9\uC5D0 \uD544\uC694\uD569\uB2C8\uB2E4"
|
|
4473
4595
|
}) => {
|
|
4474
|
-
const [activeTab, setActiveTab] = (0,
|
|
4475
|
-
const [localApiKey, setLocalApiKey] = (0,
|
|
4596
|
+
const [activeTab, setActiveTab] = (0, import_react12.useState)("general");
|
|
4597
|
+
const [localApiKey, setLocalApiKey] = (0, import_react12.useState)(apiKey);
|
|
4476
4598
|
if (!isOpen) return null;
|
|
4477
4599
|
const updateResponseStyle = (key, value) => {
|
|
4478
4600
|
onPersonalizationChange({
|
|
@@ -5078,9 +5200,11 @@ var ChatUI = ({
|
|
|
5078
5200
|
className = "",
|
|
5079
5201
|
onSendMessage,
|
|
5080
5202
|
onSessionChange,
|
|
5081
|
-
onError
|
|
5203
|
+
onError,
|
|
5204
|
+
onTitleChange,
|
|
5205
|
+
generateTitle: generateTitle2
|
|
5082
5206
|
}) => {
|
|
5083
|
-
|
|
5207
|
+
import_react13.default.useEffect(() => {
|
|
5084
5208
|
injectStyles();
|
|
5085
5209
|
}, []);
|
|
5086
5210
|
const hookOptions = {
|
|
@@ -5095,7 +5219,9 @@ var ChatUI = ({
|
|
|
5095
5219
|
keepRecentMessages,
|
|
5096
5220
|
onSendMessage,
|
|
5097
5221
|
onSessionChange,
|
|
5098
|
-
onError
|
|
5222
|
+
onError,
|
|
5223
|
+
onTitleChange,
|
|
5224
|
+
generateTitle: generateTitle2
|
|
5099
5225
|
};
|
|
5100
5226
|
const {
|
|
5101
5227
|
sessions,
|
|
@@ -5118,6 +5244,7 @@ var ChatUI = ({
|
|
|
5118
5244
|
newSession,
|
|
5119
5245
|
selectSession,
|
|
5120
5246
|
deleteSession,
|
|
5247
|
+
renameSession,
|
|
5121
5248
|
setModel,
|
|
5122
5249
|
toggleSidebar,
|
|
5123
5250
|
openSettings,
|
|
@@ -5148,8 +5275,8 @@ var ChatUI = ({
|
|
|
5148
5275
|
const handleChoiceClick = (choice) => {
|
|
5149
5276
|
setInput(choice.text);
|
|
5150
5277
|
};
|
|
5151
|
-
const [memoryPanelOpen, setMemoryPanelOpen] = (0,
|
|
5152
|
-
const memoryItems =
|
|
5278
|
+
const [memoryPanelOpen, setMemoryPanelOpen] = (0, import_react13.useState)(false);
|
|
5279
|
+
const memoryItems = import_react13.default.useMemo(() => {
|
|
5153
5280
|
const items = [];
|
|
5154
5281
|
if (currentSession?.contextSummary) {
|
|
5155
5282
|
items.push({
|
|
@@ -5209,6 +5336,7 @@ var ChatUI = ({
|
|
|
5209
5336
|
onSelectSession: selectSession,
|
|
5210
5337
|
onNewSession: newSession,
|
|
5211
5338
|
onDeleteSession: deleteSession,
|
|
5339
|
+
onRenameSession: renameSession,
|
|
5212
5340
|
isOpen: sidebarOpen,
|
|
5213
5341
|
onToggle: toggleSidebar
|
|
5214
5342
|
}
|