@gendive/chatllm 0.7.0 → 0.8.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.
@@ -246,6 +246,8 @@ 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;
249
251
  /** 재압축 임계값 - 새 메시지 수 (기본: 10) */
250
252
  recompressionThreshold?: number;
251
253
  /** 토큰 한도 (기본: 8000) */
@@ -300,6 +302,8 @@ interface SidebarProps {
300
302
  onSelectSession: (id: string) => void;
301
303
  onNewSession: () => void;
302
304
  onDeleteSession: (id: string) => void;
305
+ /** @Todo vibecode - 세션 제목 변경 핸들러 */
306
+ onRenameSession?: (id: string, newTitle: string) => void;
303
307
  isOpen: boolean;
304
308
  onToggle: () => void;
305
309
  }
@@ -404,6 +408,8 @@ interface UseChatUIReturn {
404
408
  newSession: () => void;
405
409
  selectSession: (id: string) => void;
406
410
  deleteSession: (id: string) => void;
411
+ /** @Todo vibecode - 세션 제목 변경 함수 */
412
+ renameSession: (id: string, newTitle: string) => void;
407
413
  setModel: (model: string) => void;
408
414
  toggleSidebar: () => void;
409
415
  openSettings: () => void;
@@ -465,6 +471,8 @@ interface UseChatUIOptions {
465
471
  onSessionChange?: (session: ChatSession | null) => void;
466
472
  /** 에러 핸들러 */
467
473
  onError?: (error: Error) => void;
474
+ /** @Todo vibecode - 세션 제목 변경 핸들러 */
475
+ onTitleChange?: (sessionId: string, newTitle: string) => void;
468
476
  /** 글로벌 메모리 사용 여부 (기본: true) */
469
477
  useGlobalMemoryEnabled?: boolean;
470
478
  /** 글로벌 메모리 설정 */
@@ -246,6 +246,8 @@ 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;
249
251
  /** 재압축 임계값 - 새 메시지 수 (기본: 10) */
250
252
  recompressionThreshold?: number;
251
253
  /** 토큰 한도 (기본: 8000) */
@@ -300,6 +302,8 @@ interface SidebarProps {
300
302
  onSelectSession: (id: string) => void;
301
303
  onNewSession: () => void;
302
304
  onDeleteSession: (id: string) => void;
305
+ /** @Todo vibecode - 세션 제목 변경 핸들러 */
306
+ onRenameSession?: (id: string, newTitle: string) => void;
303
307
  isOpen: boolean;
304
308
  onToggle: () => void;
305
309
  }
@@ -404,6 +408,8 @@ interface UseChatUIReturn {
404
408
  newSession: () => void;
405
409
  selectSession: (id: string) => void;
406
410
  deleteSession: (id: string) => void;
411
+ /** @Todo vibecode - 세션 제목 변경 함수 */
412
+ renameSession: (id: string, newTitle: string) => void;
407
413
  setModel: (model: string) => void;
408
414
  toggleSidebar: () => void;
409
415
  openSettings: () => void;
@@ -465,6 +471,8 @@ interface UseChatUIOptions {
465
471
  onSessionChange?: (session: ChatSession | null) => void;
466
472
  /** 에러 핸들러 */
467
473
  onError?: (error: Error) => void;
474
+ /** @Todo vibecode - 세션 제목 변경 핸들러 */
475
+ onTitleChange?: (sessionId: string, newTitle: string) => void;
468
476
  /** 글로벌 메모리 사용 여부 (기본: true) */
469
477
  useGlobalMemoryEnabled?: boolean;
470
478
  /** 글로벌 메모리 설정 */
@@ -48,7 +48,7 @@ __export(index_exports, {
48
48
  module.exports = __toCommonJS(index_exports);
49
49
 
50
50
  // src/react/ChatUI.tsx
51
- var import_react12 = __toESM(require("react"));
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,7 @@ var useChatUI = (options) => {
563
563
  onSendMessage,
564
564
  onSessionChange,
565
565
  onError,
566
+ onTitleChange,
566
567
  // Memory options
567
568
  useGlobalMemoryEnabled = true,
568
569
  globalMemoryConfig,
@@ -817,6 +818,15 @@ ${newConversation}
817
818
  return filtered;
818
819
  });
819
820
  }, [currentSessionId, storageKey]);
821
+ const renameSession = (0, import_react3.useCallback)((id, newTitle) => {
822
+ if (!newTitle.trim()) return;
823
+ setSessions(
824
+ (prev) => prev.map(
825
+ (s) => s.id === id ? { ...s, title: newTitle.trim(), updatedAt: Date.now() } : s
826
+ )
827
+ );
828
+ onTitleChange?.(id, newTitle.trim());
829
+ }, [onTitleChange]);
820
830
  const setModel = (0, import_react3.useCallback)((model) => {
821
831
  setSelectedModel(model);
822
832
  if (currentSessionId) {
@@ -1335,6 +1345,7 @@ ${currentSession.contextSummary}` },
1335
1345
  newSession,
1336
1346
  selectSession,
1337
1347
  deleteSession,
1348
+ renameSession,
1338
1349
  setModel,
1339
1350
  toggleSidebar,
1340
1351
  openSettings,
@@ -1365,6 +1376,9 @@ ${currentSession.contextSummary}` },
1365
1376
  };
1366
1377
  };
1367
1378
 
1379
+ // src/react/components/ChatSidebar.tsx
1380
+ var import_react4 = require("react");
1381
+
1368
1382
  // src/react/components/Icon.tsx
1369
1383
  var import_jsx_runtime = require("react/jsx-runtime");
1370
1384
  var Icon = ({
@@ -1475,9 +1489,44 @@ var ChatSidebar = ({
1475
1489
  onSelectSession,
1476
1490
  onNewSession,
1477
1491
  onDeleteSession,
1492
+ onRenameSession,
1478
1493
  isOpen,
1479
1494
  onToggle
1480
1495
  }) => {
1496
+ const [editingId, setEditingId] = (0, import_react4.useState)(null);
1497
+ const [editingTitle, setEditingTitle] = (0, import_react4.useState)("");
1498
+ const inputRef = (0, import_react4.useRef)(null);
1499
+ (0, import_react4.useEffect)(() => {
1500
+ if (editingId && inputRef.current) {
1501
+ inputRef.current.focus();
1502
+ inputRef.current.select();
1503
+ }
1504
+ }, [editingId]);
1505
+ const handleStartEdit = (session, e) => {
1506
+ e.stopPropagation();
1507
+ setEditingId(session.id);
1508
+ setEditingTitle(session.title);
1509
+ };
1510
+ const handleSaveEdit = () => {
1511
+ if (editingId && editingTitle.trim() && onRenameSession) {
1512
+ onRenameSession(editingId, editingTitle.trim());
1513
+ }
1514
+ setEditingId(null);
1515
+ setEditingTitle("");
1516
+ };
1517
+ const handleCancelEdit = () => {
1518
+ setEditingId(null);
1519
+ setEditingTitle("");
1520
+ };
1521
+ const handleKeyDown = (e) => {
1522
+ if (e.key === "Enter") {
1523
+ e.preventDefault();
1524
+ handleSaveEdit();
1525
+ } else if (e.key === "Escape") {
1526
+ e.preventDefault();
1527
+ handleCancelEdit();
1528
+ }
1529
+ };
1481
1530
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1482
1531
  "aside",
1483
1532
  {
@@ -1587,7 +1636,30 @@ var ChatSidebar = ({
1587
1636
  },
1588
1637
  children: /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", justifyContent: "space-between", alignItems: "flex-start" }, children: [
1589
1638
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
1590
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1639
+ editingId === session.id ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1640
+ "input",
1641
+ {
1642
+ ref: inputRef,
1643
+ type: "text",
1644
+ value: editingTitle,
1645
+ onChange: (e) => setEditingTitle(e.target.value),
1646
+ onKeyDown: handleKeyDown,
1647
+ onBlur: handleSaveEdit,
1648
+ onClick: (e) => e.stopPropagation(),
1649
+ "aria-label": "\uC138\uC158 \uC81C\uBAA9 \uD3B8\uC9D1",
1650
+ style: {
1651
+ width: "100%",
1652
+ padding: "4px 8px",
1653
+ fontSize: "14px",
1654
+ fontWeight: session.id === currentSessionId ? 500 : 400,
1655
+ color: "var(--chatllm-text, #1f2937)",
1656
+ backgroundColor: "var(--chatllm-bg, #ffffff)",
1657
+ border: "1px solid var(--chatllm-primary, #3b82f6)",
1658
+ borderRadius: "4px",
1659
+ outline: "none"
1660
+ }
1661
+ }
1662
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1591
1663
  "div",
1592
1664
  {
1593
1665
  style: {
@@ -1613,31 +1685,57 @@ var ChatSidebar = ({
1613
1685
  }
1614
1686
  )
1615
1687
  ] }),
1616
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1617
- "button",
1618
- {
1619
- onClick: (e) => {
1620
- e.stopPropagation();
1621
- onDeleteSession(session.id);
1622
- },
1623
- style: {
1624
- padding: "4px",
1625
- backgroundColor: "transparent",
1626
- border: "none",
1627
- borderRadius: "4px",
1628
- cursor: "pointer",
1629
- opacity: 0.5,
1630
- transition: "opacity 0.2s"
1631
- },
1632
- onMouseOver: (e) => {
1633
- e.currentTarget.style.opacity = "1";
1634
- },
1635
- onMouseOut: (e) => {
1636
- e.currentTarget.style.opacity = "0.5";
1637
- },
1638
- children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconSvg, { name: "delete-bin-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" })
1639
- }
1640
- )
1688
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { display: "flex", gap: "2px" }, children: [
1689
+ onRenameSession && editingId !== session.id && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1690
+ "button",
1691
+ {
1692
+ onClick: (e) => handleStartEdit(session, e),
1693
+ "aria-label": "\uC81C\uBAA9 \uD3B8\uC9D1",
1694
+ style: {
1695
+ padding: "4px",
1696
+ backgroundColor: "transparent",
1697
+ border: "none",
1698
+ borderRadius: "4px",
1699
+ cursor: "pointer",
1700
+ opacity: 0.5,
1701
+ transition: "opacity 0.2s"
1702
+ },
1703
+ onMouseOver: (e) => {
1704
+ e.currentTarget.style.opacity = "1";
1705
+ },
1706
+ onMouseOut: (e) => {
1707
+ e.currentTarget.style.opacity = "0.5";
1708
+ },
1709
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconSvg, { name: "pencil-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" })
1710
+ }
1711
+ ),
1712
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
1713
+ "button",
1714
+ {
1715
+ onClick: (e) => {
1716
+ e.stopPropagation();
1717
+ onDeleteSession(session.id);
1718
+ },
1719
+ "aria-label": "\uC138\uC158 \uC0AD\uC81C",
1720
+ style: {
1721
+ padding: "4px",
1722
+ backgroundColor: "transparent",
1723
+ border: "none",
1724
+ borderRadius: "4px",
1725
+ cursor: "pointer",
1726
+ opacity: 0.5,
1727
+ transition: "opacity 0.2s"
1728
+ },
1729
+ onMouseOver: (e) => {
1730
+ e.currentTarget.style.opacity = "1";
1731
+ },
1732
+ onMouseOut: (e) => {
1733
+ e.currentTarget.style.opacity = "0.5";
1734
+ },
1735
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(IconSvg, { name: "delete-bin-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" })
1736
+ }
1737
+ )
1738
+ ] })
1641
1739
  ] })
1642
1740
  },
1643
1741
  session.id
@@ -1669,7 +1767,7 @@ var ChatSidebar = ({
1669
1767
  };
1670
1768
 
1671
1769
  // src/react/components/ChatHeader.tsx
1672
- var import_react4 = require("react");
1770
+ var import_react5 = require("react");
1673
1771
  var import_jsx_runtime3 = require("react/jsx-runtime");
1674
1772
  var ChatHeader = ({
1675
1773
  title,
@@ -1682,7 +1780,7 @@ var ChatHeader = ({
1682
1780
  showModelSelector = true,
1683
1781
  showSettings = true
1684
1782
  }) => {
1685
- const [modelDropdownOpen, setModelDropdownOpen] = (0, import_react4.useState)(false);
1783
+ const [modelDropdownOpen, setModelDropdownOpen] = (0, import_react5.useState)(false);
1686
1784
  const currentModel = models.find((m) => m.id === model);
1687
1785
  return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
1688
1786
  "header",
@@ -1936,7 +2034,7 @@ var ChatHeader = ({
1936
2034
  };
1937
2035
 
1938
2036
  // src/react/components/ChatInput.tsx
1939
- var import_react5 = require("react");
2037
+ var import_react6 = require("react");
1940
2038
  var import_jsx_runtime4 = require("react/jsx-runtime");
1941
2039
  var ChatInput = ({
1942
2040
  value,
@@ -1952,9 +2050,9 @@ var ChatInput = ({
1952
2050
  onActionSelect,
1953
2051
  actions = []
1954
2052
  }) => {
1955
- const textareaRef = (0, import_react5.useRef)(null);
1956
- const [actionMenuOpen, setActionMenuOpen] = (0, import_react5.useState)(false);
1957
- (0, import_react5.useEffect)(() => {
2053
+ const textareaRef = (0, import_react6.useRef)(null);
2054
+ const [actionMenuOpen, setActionMenuOpen] = (0, import_react6.useState)(false);
2055
+ (0, import_react6.useEffect)(() => {
1958
2056
  if (textareaRef.current) {
1959
2057
  textareaRef.current.style.height = "auto";
1960
2058
  textareaRef.current.style.height = `${Math.min(textareaRef.current.scrollHeight, 200)}px`;
@@ -2252,16 +2350,16 @@ var ChatInput = ({
2252
2350
  };
2253
2351
 
2254
2352
  // src/react/components/MessageList.tsx
2255
- var import_react9 = require("react");
2353
+ var import_react10 = require("react");
2256
2354
 
2257
2355
  // src/react/components/MessageBubble.tsx
2258
- var import_react8 = require("react");
2356
+ var import_react9 = require("react");
2259
2357
 
2260
2358
  // src/react/components/MarkdownRenderer.tsx
2261
- var import_react7 = __toESM(require("react"));
2359
+ var import_react8 = __toESM(require("react"));
2262
2360
 
2263
2361
  // src/react/components/LinkChip.tsx
2264
- var import_react6 = require("react");
2362
+ var import_react7 = require("react");
2265
2363
  var import_jsx_runtime5 = require("react/jsx-runtime");
2266
2364
  var getDomain = (url) => {
2267
2365
  try {
@@ -2315,7 +2413,7 @@ var LinkChip = ({
2315
2413
  index,
2316
2414
  style
2317
2415
  }) => {
2318
- const [isHovered, setIsHovered] = (0, import_react6.useState)(false);
2416
+ const [isHovered, setIsHovered] = (0, import_react7.useState)(false);
2319
2417
  const domain = getDomain(url);
2320
2418
  const shortName = getShortName(domain);
2321
2419
  const domainColor = getDomainColor(domain);
@@ -2610,7 +2708,7 @@ var MarkdownTable = ({ data }) => {
2610
2708
  );
2611
2709
  };
2612
2710
  var CodeBlock = ({ language, code }) => {
2613
- const [copied, setCopied] = import_react7.default.useState(false);
2711
+ const [copied, setCopied] = import_react8.default.useState(false);
2614
2712
  const handleCopy = async () => {
2615
2713
  try {
2616
2714
  await navigator.clipboard.writeText(code);
@@ -2693,9 +2791,9 @@ var CodeBlock = ({ language, code }) => {
2693
2791
  );
2694
2792
  };
2695
2793
  var ImageWithCopyButton = ({ src, alt, imageKey }) => {
2696
- const [isHovered, setIsHovered] = import_react7.default.useState(false);
2697
- const [copyState, setCopyState] = import_react7.default.useState("idle");
2698
- const imgRef = import_react7.default.useRef(null);
2794
+ const [isHovered, setIsHovered] = import_react8.default.useState(false);
2795
+ const [copyState, setCopyState] = import_react8.default.useState("idle");
2796
+ const imgRef = import_react8.default.useRef(null);
2699
2797
  const getImageBlob = async () => {
2700
2798
  const img = imgRef.current;
2701
2799
  if (img && img.complete && img.naturalWidth > 0) {
@@ -2911,7 +3009,7 @@ var ImageWithCopyButton = ({ src, alt, imageKey }) => {
2911
3009
  );
2912
3010
  };
2913
3011
  var ChoiceButtons = ({ choices, title, onChoiceClick }) => {
2914
- const [hoveredIndex, setHoveredIndex] = import_react7.default.useState(null);
3012
+ const [hoveredIndex, setHoveredIndex] = import_react8.default.useState(null);
2915
3013
  return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2916
3014
  "div",
2917
3015
  {
@@ -3034,7 +3132,7 @@ var SourceLinksSection = ({ links, label }) => {
3034
3132
  );
3035
3133
  };
3036
3134
  var MarkdownRenderer = ({ content, className, onChoiceClick }) => {
3037
- const rendered = (0, import_react7.useMemo)(() => {
3135
+ const rendered = (0, import_react8.useMemo)(() => {
3038
3136
  const elements = [];
3039
3137
  let processedContent = content;
3040
3138
  const codeBlocks = [];
@@ -3132,7 +3230,7 @@ var MarkdownRenderer = ({ content, className, onChoiceClick }) => {
3132
3230
  borderRadius: "0 8px 8px 0",
3133
3231
  color: "var(--chatllm-text, #374151)"
3134
3232
  },
3135
- children: blockquoteLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react7.default.Fragment, { children: [
3233
+ children: blockquoteLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react8.default.Fragment, { children: [
3136
3234
  parseInlineElements(line, `bq-line-${i}`),
3137
3235
  i < blockquoteLines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("br", {})
3138
3236
  ] }, i))
@@ -3285,9 +3383,16 @@ var MarkdownRenderer = ({ content, className, onChoiceClick }) => {
3285
3383
  return;
3286
3384
  }
3287
3385
  }
3288
- elements.push(
3289
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { margin: "4px 0" }, children: parseInlineElements(line, `p-${lineIndex}`) }, `p-${lineIndex}`)
3290
- );
3386
+ const hasImage = IMAGE_REGEX.test(line);
3387
+ if (hasImage) {
3388
+ elements.push(
3389
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { style: { margin: "4px 0" }, children: parseInlineElements(line, `p-${lineIndex}`) }, `p-${lineIndex}`)
3390
+ );
3391
+ } else {
3392
+ elements.push(
3393
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { margin: "4px 0" }, children: parseInlineElements(line, `p-${lineIndex}`) }, `p-${lineIndex}`)
3394
+ );
3395
+ }
3291
3396
  });
3292
3397
  flushList();
3293
3398
  flushBlockquote();
@@ -3327,8 +3432,8 @@ var MessageBubble = ({
3327
3432
  nextAssistantMessage,
3328
3433
  onChoiceClick
3329
3434
  }) => {
3330
- const [showActions, setShowActions] = (0, import_react8.useState)(false);
3331
- const [showModelMenu, setShowModelMenu] = (0, import_react8.useState)(false);
3435
+ const [showActions, setShowActions] = (0, import_react9.useState)(false);
3436
+ const [showModelMenu, setShowModelMenu] = (0, import_react9.useState)(false);
3332
3437
  const isUser = message.role === "user";
3333
3438
  const isAssistant = message.role === "assistant";
3334
3439
  const relevantAlternatives = isUser ? alternatives : message.alternatives;
@@ -3721,14 +3826,14 @@ var MessageList = ({
3721
3826
  editingId,
3722
3827
  onChoiceClick
3723
3828
  }) => {
3724
- const messagesEndRef = (0, import_react9.useRef)(null);
3725
- const containerRef = (0, import_react9.useRef)(null);
3726
- const [selectedText, setSelectedText] = (0, import_react9.useState)("");
3727
- const [selectionPosition, setSelectionPosition] = (0, import_react9.useState)(null);
3728
- (0, import_react9.useEffect)(() => {
3829
+ const messagesEndRef = (0, import_react10.useRef)(null);
3830
+ const containerRef = (0, import_react10.useRef)(null);
3831
+ const [selectedText, setSelectedText] = (0, import_react10.useState)("");
3832
+ const [selectionPosition, setSelectionPosition] = (0, import_react10.useState)(null);
3833
+ (0, import_react10.useEffect)(() => {
3729
3834
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
3730
3835
  }, [messages]);
3731
- const handleMouseUp = (0, import_react9.useCallback)(() => {
3836
+ const handleMouseUp = (0, import_react10.useCallback)(() => {
3732
3837
  const selection = window.getSelection();
3733
3838
  const text = selection?.toString().trim();
3734
3839
  if (text && text.length > 0) {
@@ -4105,7 +4210,7 @@ var EmptyState = ({
4105
4210
  };
4106
4211
 
4107
4212
  // src/react/components/MemoryPanel.tsx
4108
- var import_react10 = require("react");
4213
+ var import_react11 = require("react");
4109
4214
  var import_jsx_runtime10 = require("react/jsx-runtime");
4110
4215
  var categoryLabels = {
4111
4216
  context: "\uB300\uD654 \uCEE8\uD14D\uC2A4\uD2B8",
@@ -4127,8 +4232,8 @@ var MemoryPanel = ({
4127
4232
  isOpen,
4128
4233
  onToggle
4129
4234
  }) => {
4130
- const [expandedId, setExpandedId] = (0, import_react10.useState)(null);
4131
- const [activeTab, setActiveTab] = (0, import_react10.useState)("all");
4235
+ const [expandedId, setExpandedId] = (0, import_react11.useState)(null);
4236
+ const [activeTab, setActiveTab] = (0, import_react11.useState)("all");
4132
4237
  const filteredItems = activeTab === "all" ? items : items.filter((item) => item.category === activeTab);
4133
4238
  const formatDate2 = (timestamp) => {
4134
4239
  const date = new Date(timestamp);
@@ -4446,7 +4551,7 @@ var MemoryPanel = ({
4446
4551
  };
4447
4552
 
4448
4553
  // src/react/components/SettingsModal.tsx
4449
- var import_react11 = require("react");
4554
+ var import_react12 = require("react");
4450
4555
  var import_jsx_runtime11 = require("react/jsx-runtime");
4451
4556
  var DEFAULT_PERSONALIZATION2 = {
4452
4557
  responseStyle: {
@@ -4471,8 +4576,8 @@ var SettingsModal = ({
4471
4576
  apiKeyLabel = "API Key",
4472
4577
  apiKeyDescription = "Cloud \uBAA8\uB378 \uC0AC\uC6A9\uC5D0 \uD544\uC694\uD569\uB2C8\uB2E4"
4473
4578
  }) => {
4474
- const [activeTab, setActiveTab] = (0, import_react11.useState)("general");
4475
- const [localApiKey, setLocalApiKey] = (0, import_react11.useState)(apiKey);
4579
+ const [activeTab, setActiveTab] = (0, import_react12.useState)("general");
4580
+ const [localApiKey, setLocalApiKey] = (0, import_react12.useState)(apiKey);
4476
4581
  if (!isOpen) return null;
4477
4582
  const updateResponseStyle = (key, value) => {
4478
4583
  onPersonalizationChange({
@@ -5078,9 +5183,10 @@ var ChatUI = ({
5078
5183
  className = "",
5079
5184
  onSendMessage,
5080
5185
  onSessionChange,
5081
- onError
5186
+ onError,
5187
+ onTitleChange
5082
5188
  }) => {
5083
- import_react12.default.useEffect(() => {
5189
+ import_react13.default.useEffect(() => {
5084
5190
  injectStyles();
5085
5191
  }, []);
5086
5192
  const hookOptions = {
@@ -5095,7 +5201,8 @@ var ChatUI = ({
5095
5201
  keepRecentMessages,
5096
5202
  onSendMessage,
5097
5203
  onSessionChange,
5098
- onError
5204
+ onError,
5205
+ onTitleChange
5099
5206
  };
5100
5207
  const {
5101
5208
  sessions,
@@ -5118,6 +5225,7 @@ var ChatUI = ({
5118
5225
  newSession,
5119
5226
  selectSession,
5120
5227
  deleteSession,
5228
+ renameSession,
5121
5229
  setModel,
5122
5230
  toggleSidebar,
5123
5231
  openSettings,
@@ -5148,8 +5256,8 @@ var ChatUI = ({
5148
5256
  const handleChoiceClick = (choice) => {
5149
5257
  setInput(choice.text);
5150
5258
  };
5151
- const [memoryPanelOpen, setMemoryPanelOpen] = (0, import_react12.useState)(false);
5152
- const memoryItems = import_react12.default.useMemo(() => {
5259
+ const [memoryPanelOpen, setMemoryPanelOpen] = (0, import_react13.useState)(false);
5260
+ const memoryItems = import_react13.default.useMemo(() => {
5153
5261
  const items = [];
5154
5262
  if (currentSession?.contextSummary) {
5155
5263
  items.push({
@@ -5209,6 +5317,7 @@ var ChatUI = ({
5209
5317
  onSelectSession: selectSession,
5210
5318
  onNewSession: newSession,
5211
5319
  onDeleteSession: deleteSession,
5320
+ onRenameSession: renameSession,
5212
5321
  isOpen: sidebarOpen,
5213
5322
  onToggle: toggleSidebar
5214
5323
  }