@gendive/chatllm 0.2.0 → 0.3.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.
@@ -37,15 +37,18 @@ __export(index_exports, {
37
37
  EmptyState: () => EmptyState,
38
38
  Icon: () => Icon,
39
39
  IconSvg: () => IconSvg,
40
+ LinkChip: () => LinkChip,
41
+ MarkdownRenderer: () => MarkdownRenderer,
40
42
  MemoryPanel: () => MemoryPanel,
41
43
  MessageBubble: () => MessageBubble,
42
44
  MessageList: () => MessageList,
45
+ SettingsModal: () => SettingsModal,
43
46
  useChatUI: () => useChatUI
44
47
  });
45
48
  module.exports = __toCommonJS(index_exports);
46
49
 
47
50
  // src/react/ChatUI.tsx
48
- var import_react7 = __toESM(require("react"));
51
+ var import_react10 = __toESM(require("react"));
49
52
 
50
53
  // src/react/hooks/useChatUI.ts
51
54
  var import_react = require("react");
@@ -609,6 +612,7 @@ var IconSvg = ({
609
612
  size = 20,
610
613
  color = "currentColor",
611
614
  className = "",
615
+ style,
612
616
  onClick,
613
617
  "aria-label": ariaLabel
614
618
  }) => {
@@ -640,7 +644,11 @@ var IconSvg = ({
640
644
  "user-3-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M20 22h-2v-2a3 3 0 0 0-3-3H9a3 3 0 0 0-3 3v2H4v-2a5 5 0 0 1 5-5h6a5 5 0 0 1 5 5v2zm-8-9a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8z" }),
641
645
  "sun-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 18a6 6 0 1 1 0-12 6 6 0 0 1 0 12zm0-2a4 4 0 1 0 0-8 4 4 0 0 0 0 8zM11 1h2v3h-2V1zm0 19h2v3h-2v-3zM3.515 4.929l1.414-1.414L7.05 5.636 5.636 7.05 3.515 4.93zM16.95 18.364l1.414-1.414 2.121 2.121-1.414 1.414-2.121-2.121zm2.121-14.85l1.414 1.415-2.121 2.121-1.414-1.414 2.121-2.121zM5.636 16.95l1.414 1.414-2.121 2.121-1.414-1.414 2.121-2.121zM23 11v2h-3v-2h3zM4 11v2H1v-2h3z" }),
642
646
  "moon-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M10 7a7 7 0 0 0 12 4.9v.1c0 5.523-4.477 10-10 10S2 17.523 2 12 6.477 2 12 2h.1A6.979 6.979 0 0 0 10 7zm-6 5a8 8 0 0 0 15.062 3.762A9 9 0 0 1 8.238 4.938 7.999 7.999 0 0 0 4 12z" }),
643
- "key-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12.917 13A6.002 6.002 0 0 1 1 12a6 6 0 0 1 11.917-1H23v6h-2v-4h-2v4h-2v-4h-4.083zM7 10a2 2 0 1 0 0 4 2 2 0 0 0 0-4z" })
647
+ "key-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12.917 13A6.002 6.002 0 0 1 1 12a6 6 0 0 1 11.917-1H23v6h-2v-4h-2v4h-2v-4h-4.083zM7 10a2 2 0 1 0 0 4 2 2 0 0 0 0-4z" }),
648
+ "links-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M17.657 14.828l-1.414-1.414L17.657 12A4 4 0 1 0 12 6.343l-1.414 1.414-1.414-1.414 1.414-1.414a6 6 0 0 1 8.485 8.485l-1.414 1.414zm-2.829 2.829l-1.414 1.414a6 6 0 1 1-8.485-8.485l1.414-1.414 1.414 1.414L6.343 12A4 4 0 1 0 12 17.657l1.414-1.414 1.414 1.414zm0-9.9l1.415 1.415-7.071 7.07-1.415-1.414 7.071-7.07z" }),
649
+ "external-link-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M10 6v2H5v11h11v-5h2v6a1 1 0 0 1-1 1H4a1 1 0 0 1-1-1V7a1 1 0 0 1 1-1h6zm11-3v8h-2V6.413l-7.793 7.794-1.414-1.414L17.585 5H13V3h8z" }),
650
+ "arrow-left-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M7.828 11H20v2H7.828l5.364 5.364-1.414 1.414L4 12l7.778-7.778 1.414 1.414z" }),
651
+ "arrow-right-line": /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M16.172 11l-5.364-5.364 1.414-1.414L20 12l-7.778 7.778-1.414-1.414L16.172 13H4v-2z" })
644
652
  };
645
653
  const iconPath = icons[name];
646
654
  return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(
@@ -655,7 +663,7 @@ var IconSvg = ({
655
663
  "aria-label": ariaLabel,
656
664
  role: onClick ? "button" : "img",
657
665
  tabIndex: onClick ? 0 : void 0,
658
- style: { display: "inline-block", verticalAlign: "middle" },
666
+ style: { display: "inline-block", verticalAlign: "middle", ...style },
659
667
  children: iconPath || /* @__PURE__ */ (0, import_jsx_runtime.jsx)("path", { d: "M12 2C6.48 2 2 6.48 2 12s4.48 10 10 10 10-4.48 10-10S17.52 2 12 2z" })
660
668
  }
661
669
  );
@@ -1454,11 +1462,568 @@ var ChatInput = ({
1454
1462
  };
1455
1463
 
1456
1464
  // src/react/components/MessageList.tsx
1457
- var import_react5 = require("react");
1465
+ var import_react7 = require("react");
1458
1466
 
1459
1467
  // src/react/components/MessageBubble.tsx
1468
+ var import_react6 = require("react");
1469
+
1470
+ // src/react/components/MarkdownRenderer.tsx
1471
+ var import_react5 = __toESM(require("react"));
1472
+
1473
+ // src/react/components/LinkChip.tsx
1460
1474
  var import_react4 = require("react");
1461
1475
  var import_jsx_runtime5 = require("react/jsx-runtime");
1476
+ var getDomain = (url) => {
1477
+ try {
1478
+ const urlObj = new URL(url);
1479
+ return urlObj.hostname.replace("www.", "");
1480
+ } catch {
1481
+ return url;
1482
+ }
1483
+ };
1484
+ var getShortName = (domain) => {
1485
+ const parts = domain.split(".");
1486
+ if (parts.length >= 2) {
1487
+ return parts[parts.length - 2];
1488
+ }
1489
+ return domain;
1490
+ };
1491
+ var getDomainColor = (domain) => {
1492
+ const lowerDomain = domain.toLowerCase();
1493
+ const colorMap = {
1494
+ "google": "#4285f4",
1495
+ "wikipedia": "#000000",
1496
+ "github": "#24292e",
1497
+ "stackoverflow": "#f48024",
1498
+ "medium": "#00ab6c",
1499
+ "youtube": "#ff0000",
1500
+ "twitter": "#1da1f2",
1501
+ "naver": "#03c75a",
1502
+ "namu": "#00a495",
1503
+ "tistory": "#eb531f",
1504
+ "velog": "#20c997",
1505
+ "brave": "#fb542b",
1506
+ "mk": "#0066cc",
1507
+ "ko": "#3366cc"
1508
+ };
1509
+ for (const [key, color] of Object.entries(colorMap)) {
1510
+ if (lowerDomain.includes(key)) {
1511
+ return color;
1512
+ }
1513
+ }
1514
+ let hash = 0;
1515
+ for (let i = 0; i < domain.length; i++) {
1516
+ hash = domain.charCodeAt(i) + ((hash << 5) - hash);
1517
+ }
1518
+ const hue = hash % 360;
1519
+ return `hsl(${hue}, 60%, 45%)`;
1520
+ };
1521
+ var LinkChip = ({
1522
+ text,
1523
+ url,
1524
+ showFavicon = true,
1525
+ index,
1526
+ style
1527
+ }) => {
1528
+ const [isHovered, setIsHovered] = (0, import_react4.useState)(false);
1529
+ const domain = getDomain(url);
1530
+ const shortName = getShortName(domain);
1531
+ const domainColor = getDomainColor(domain);
1532
+ const parseText = (t) => {
1533
+ const match = t.match(/^(\d+)\.\s*(.+)$/);
1534
+ if (match) {
1535
+ return { number: match[1], label: match[2] };
1536
+ }
1537
+ return { label: t };
1538
+ };
1539
+ const parsed = parseText(text);
1540
+ const displayNumber = index !== void 0 ? String(index + 1) : parsed.number;
1541
+ const displayLabel = parsed.label;
1542
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
1543
+ "a",
1544
+ {
1545
+ href: url,
1546
+ target: "_blank",
1547
+ rel: "noopener noreferrer",
1548
+ onMouseEnter: () => setIsHovered(true),
1549
+ onMouseLeave: () => setIsHovered(false),
1550
+ style: {
1551
+ display: "inline-flex",
1552
+ alignItems: "center",
1553
+ gap: "6px",
1554
+ padding: "4px 10px",
1555
+ backgroundColor: isHovered ? "var(--chatllm-chip-bg-hover, #e2e8f0)" : "var(--chatllm-chip-bg, #f1f5f9)",
1556
+ border: "1px solid var(--chatllm-chip-border, #e2e8f0)",
1557
+ borderRadius: "16px",
1558
+ textDecoration: "none",
1559
+ fontSize: "13px",
1560
+ fontWeight: 500,
1561
+ color: "var(--chatllm-chip-text, #475569)",
1562
+ transition: "all 0.15s ease",
1563
+ cursor: "pointer",
1564
+ maxWidth: "180px",
1565
+ ...style
1566
+ },
1567
+ title: `${displayLabel} - ${domain}`,
1568
+ children: [
1569
+ displayNumber && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1570
+ "span",
1571
+ {
1572
+ style: {
1573
+ display: "flex",
1574
+ alignItems: "center",
1575
+ justifyContent: "center",
1576
+ width: "18px",
1577
+ height: "18px",
1578
+ borderRadius: "50%",
1579
+ backgroundColor: domainColor,
1580
+ color: "#ffffff",
1581
+ fontSize: "11px",
1582
+ fontWeight: 600,
1583
+ flexShrink: 0
1584
+ },
1585
+ children: displayNumber
1586
+ }
1587
+ ),
1588
+ showFavicon && !displayNumber && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1589
+ "span",
1590
+ {
1591
+ style: {
1592
+ width: "16px",
1593
+ height: "16px",
1594
+ display: "flex",
1595
+ alignItems: "center",
1596
+ justifyContent: "center",
1597
+ flexShrink: 0
1598
+ },
1599
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1600
+ IconSvg,
1601
+ {
1602
+ name: "links-line",
1603
+ size: 14,
1604
+ color: domainColor
1605
+ }
1606
+ )
1607
+ }
1608
+ ),
1609
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1610
+ "span",
1611
+ {
1612
+ style: {
1613
+ overflow: "hidden",
1614
+ textOverflow: "ellipsis",
1615
+ whiteSpace: "nowrap"
1616
+ },
1617
+ children: displayLabel
1618
+ }
1619
+ ),
1620
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
1621
+ IconSvg,
1622
+ {
1623
+ name: "external-link-line",
1624
+ size: 12,
1625
+ color: "var(--chatllm-text-muted, #94a3b8)",
1626
+ style: {
1627
+ opacity: isHovered ? 1 : 0.6,
1628
+ flexShrink: 0
1629
+ }
1630
+ }
1631
+ )
1632
+ ]
1633
+ }
1634
+ );
1635
+ };
1636
+
1637
+ // src/react/components/MarkdownRenderer.tsx
1638
+ var import_jsx_runtime6 = require("react/jsx-runtime");
1639
+ var LINK_REGEX = /\[([^\]]+)\]\(([^)]+)\)/g;
1640
+ var SOURCE_LINKS_REGEX = /(\*{0,2}출처:?\*{0,2}\s*)?((?:\[`?[^\]]+`?\]\([^)]+\)\s*)+)/gi;
1641
+ var CODE_BLOCK_REGEX = /```(\w*)\n?([\s\S]*?)```/g;
1642
+ var INLINE_CODE_REGEX = /`([^`]+)`/g;
1643
+ var BOLD_REGEX = /\*\*([^*]+)\*\*/g;
1644
+ var ITALIC_REGEX = /(?<!\*)\*([^*]+)\*(?!\*)/g;
1645
+ var HR_REGEX = /^---+$/gm;
1646
+ var parseSourceLinks = (text) => {
1647
+ const links = [];
1648
+ let match;
1649
+ const linkRegex = /\[`?([^\]`]+)`?\]\(([^)]+)\)/g;
1650
+ while ((match = linkRegex.exec(text)) !== null) {
1651
+ links.push({
1652
+ text: match[1],
1653
+ url: match[2]
1654
+ });
1655
+ }
1656
+ return links;
1657
+ };
1658
+ var parseInlineElements = (text, key) => {
1659
+ const elements = [];
1660
+ let lastIndex = 0;
1661
+ let currentText = text;
1662
+ currentText = currentText.replace(INLINE_CODE_REGEX, "\xA7CODE\xA7$1\xA7/CODE\xA7");
1663
+ currentText = currentText.replace(BOLD_REGEX, "\xA7BOLD\xA7$1\xA7/BOLD\xA7");
1664
+ currentText = currentText.replace(ITALIC_REGEX, "\xA7ITALIC\xA7$1\xA7/ITALIC\xA7");
1665
+ currentText = currentText.replace(LINK_REGEX, "\xA7LINK\xA7$1\xA7URL\xA7$2\xA7/LINK\xA7");
1666
+ const parts = currentText.split(/(§CODE§.*?§\/CODE§|§BOLD§.*?§\/BOLD§|§ITALIC§.*?§\/ITALIC§|§LINK§.*?§\/LINK§)/);
1667
+ parts.forEach((part, index) => {
1668
+ if (part.startsWith("\xA7CODE\xA7")) {
1669
+ const content = part.replace("\xA7CODE\xA7", "").replace("\xA7/CODE\xA7", "");
1670
+ elements.push(
1671
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1672
+ "code",
1673
+ {
1674
+ style: {
1675
+ backgroundColor: "var(--chatllm-code-bg, #f3f4f6)",
1676
+ padding: "2px 6px",
1677
+ borderRadius: "4px",
1678
+ fontSize: "0.9em",
1679
+ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
1680
+ color: "var(--chatllm-code-text, #e11d48)"
1681
+ },
1682
+ children: content
1683
+ },
1684
+ `${key}-code-${index}`
1685
+ )
1686
+ );
1687
+ } else if (part.startsWith("\xA7BOLD\xA7")) {
1688
+ const content = part.replace("\xA7BOLD\xA7", "").replace("\xA7/BOLD\xA7", "");
1689
+ elements.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("strong", { children: content }, `${key}-bold-${index}`));
1690
+ } else if (part.startsWith("\xA7ITALIC\xA7")) {
1691
+ const content = part.replace("\xA7ITALIC\xA7", "").replace("\xA7/ITALIC\xA7", "");
1692
+ elements.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("em", { children: content }, `${key}-italic-${index}`));
1693
+ } else if (part.startsWith("\xA7LINK\xA7")) {
1694
+ const match = part.match(/§LINK§(.+?)§URL§(.+?)§\/LINK§/);
1695
+ if (match) {
1696
+ elements.push(
1697
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1698
+ "a",
1699
+ {
1700
+ href: match[2],
1701
+ target: "_blank",
1702
+ rel: "noopener noreferrer",
1703
+ style: {
1704
+ color: "var(--chatllm-link, #3b82f6)",
1705
+ textDecoration: "none"
1706
+ },
1707
+ children: match[1]
1708
+ },
1709
+ `${key}-link-${index}`
1710
+ )
1711
+ );
1712
+ }
1713
+ } else if (part) {
1714
+ elements.push(part);
1715
+ }
1716
+ });
1717
+ return elements;
1718
+ };
1719
+ var CodeBlock = ({ language, code }) => {
1720
+ const [copied, setCopied] = import_react5.default.useState(false);
1721
+ const handleCopy = async () => {
1722
+ try {
1723
+ await navigator.clipboard.writeText(code);
1724
+ setCopied(true);
1725
+ setTimeout(() => setCopied(false), 2e3);
1726
+ } catch (e) {
1727
+ console.error("Failed to copy");
1728
+ }
1729
+ };
1730
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1731
+ "div",
1732
+ {
1733
+ style: {
1734
+ position: "relative",
1735
+ margin: "12px 0",
1736
+ borderRadius: "8px",
1737
+ overflow: "hidden",
1738
+ backgroundColor: "var(--chatllm-code-block-bg, #1f2937)"
1739
+ },
1740
+ children: [
1741
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1742
+ "div",
1743
+ {
1744
+ style: {
1745
+ display: "flex",
1746
+ justifyContent: "space-between",
1747
+ alignItems: "center",
1748
+ padding: "8px 12px",
1749
+ backgroundColor: "var(--chatllm-code-block-header, #374151)",
1750
+ borderBottom: "1px solid var(--chatllm-code-block-border, #4b5563)"
1751
+ },
1752
+ children: [
1753
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1754
+ "span",
1755
+ {
1756
+ style: {
1757
+ fontSize: "12px",
1758
+ color: "var(--chatllm-code-block-lang, #9ca3af)",
1759
+ textTransform: "lowercase"
1760
+ },
1761
+ children: language || "code"
1762
+ }
1763
+ ),
1764
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1765
+ "button",
1766
+ {
1767
+ onClick: handleCopy,
1768
+ style: {
1769
+ padding: "4px 8px",
1770
+ fontSize: "12px",
1771
+ backgroundColor: "transparent",
1772
+ border: "1px solid var(--chatllm-code-block-border, #4b5563)",
1773
+ borderRadius: "4px",
1774
+ color: "var(--chatllm-code-block-text, #e5e7eb)",
1775
+ cursor: "pointer"
1776
+ },
1777
+ children: copied ? "\uBCF5\uC0AC\uB428!" : "\uBCF5\uC0AC"
1778
+ }
1779
+ )
1780
+ ]
1781
+ }
1782
+ ),
1783
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1784
+ "pre",
1785
+ {
1786
+ style: {
1787
+ margin: 0,
1788
+ padding: "16px",
1789
+ overflow: "auto",
1790
+ fontSize: "13px",
1791
+ lineHeight: "1.6",
1792
+ fontFamily: 'ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace',
1793
+ color: "var(--chatllm-code-block-text, #e5e7eb)"
1794
+ },
1795
+ children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("code", { children: code.trim() })
1796
+ }
1797
+ )
1798
+ ]
1799
+ }
1800
+ );
1801
+ };
1802
+ var SourceLinksSection = ({ links, label }) => {
1803
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
1804
+ "div",
1805
+ {
1806
+ style: {
1807
+ display: "flex",
1808
+ flexWrap: "wrap",
1809
+ alignItems: "center",
1810
+ gap: "8px",
1811
+ margin: "12px 0",
1812
+ padding: "12px",
1813
+ backgroundColor: "var(--chatllm-source-bg, #f8fafc)",
1814
+ borderRadius: "8px",
1815
+ border: "1px solid var(--chatllm-border-light, #e2e8f0)"
1816
+ },
1817
+ children: [
1818
+ label && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1819
+ "span",
1820
+ {
1821
+ style: {
1822
+ fontSize: "13px",
1823
+ fontWeight: 500,
1824
+ color: "var(--chatllm-text-muted, #64748b)",
1825
+ marginRight: "4px"
1826
+ },
1827
+ children: label
1828
+ }
1829
+ ),
1830
+ links.map((link, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(LinkChip, { text: link.text, url: link.url }, index))
1831
+ ]
1832
+ }
1833
+ );
1834
+ };
1835
+ var MarkdownRenderer = ({ content, className }) => {
1836
+ const rendered = (0, import_react5.useMemo)(() => {
1837
+ const elements = [];
1838
+ let processedContent = content;
1839
+ const codeBlocks = [];
1840
+ processedContent = processedContent.replace(CODE_BLOCK_REGEX, (_, lang, code) => {
1841
+ codeBlocks.push({ language: lang || "", code });
1842
+ return `\xA7CODEBLOCK\xA7${codeBlocks.length - 1}\xA7/CODEBLOCK\xA7`;
1843
+ });
1844
+ const sourceSections = [];
1845
+ processedContent = processedContent.replace(SOURCE_LINKS_REGEX, (match, label, linksText) => {
1846
+ const links = parseSourceLinks(linksText);
1847
+ if (links.length > 0) {
1848
+ sourceSections.push({ label: label?.replace(/\*+/g, "").trim() || "\uCD9C\uCC98", links });
1849
+ return `\xA7SOURCES\xA7${sourceSections.length - 1}\xA7/SOURCES\xA7`;
1850
+ }
1851
+ return match;
1852
+ });
1853
+ const lines = processedContent.split("\n");
1854
+ let currentList = null;
1855
+ let blockquoteLines = [];
1856
+ const flushList = () => {
1857
+ if (currentList) {
1858
+ if (currentList.type === "ul") {
1859
+ elements.push(
1860
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ul", { style: { margin: "8px 0", paddingLeft: "24px" }, children: currentList.items }, `ul-${elements.length}`)
1861
+ );
1862
+ } else {
1863
+ elements.push(
1864
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("ol", { style: { margin: "8px 0", paddingLeft: "24px" }, children: currentList.items }, `ol-${elements.length}`)
1865
+ );
1866
+ }
1867
+ currentList = null;
1868
+ }
1869
+ };
1870
+ const flushBlockquote = () => {
1871
+ if (blockquoteLines.length > 0) {
1872
+ elements.push(
1873
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1874
+ "blockquote",
1875
+ {
1876
+ style: {
1877
+ margin: "12px 0",
1878
+ padding: "12px 16px",
1879
+ borderLeft: "4px solid var(--chatllm-primary, #3b82f6)",
1880
+ backgroundColor: "var(--chatllm-bg-secondary, #f9fafb)",
1881
+ borderRadius: "0 8px 8px 0",
1882
+ color: "var(--chatllm-text, #374151)"
1883
+ },
1884
+ children: blockquoteLines.map((line, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_react5.default.Fragment, { children: [
1885
+ parseInlineElements(line, `bq-line-${i}`),
1886
+ i < blockquoteLines.length - 1 && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("br", {})
1887
+ ] }, i))
1888
+ },
1889
+ `bq-${elements.length}`
1890
+ )
1891
+ );
1892
+ blockquoteLines = [];
1893
+ }
1894
+ };
1895
+ lines.forEach((line, lineIndex) => {
1896
+ const codeBlockMatch = line.match(/§CODEBLOCK§(\d+)§\/CODEBLOCK§/);
1897
+ if (codeBlockMatch) {
1898
+ flushList();
1899
+ flushBlockquote();
1900
+ const index = parseInt(codeBlockMatch[1]);
1901
+ elements.push(
1902
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(CodeBlock, { ...codeBlocks[index] }, `codeblock-${lineIndex}`)
1903
+ );
1904
+ return;
1905
+ }
1906
+ const sourcesMatch = line.match(/§SOURCES§(\d+)§\/SOURCES§/);
1907
+ if (sourcesMatch) {
1908
+ flushList();
1909
+ flushBlockquote();
1910
+ const index = parseInt(sourcesMatch[1]);
1911
+ elements.push(
1912
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(SourceLinksSection, { ...sourceSections[index] }, `sources-${lineIndex}`)
1913
+ );
1914
+ return;
1915
+ }
1916
+ if (HR_REGEX.test(line)) {
1917
+ flushList();
1918
+ flushBlockquote();
1919
+ elements.push(
1920
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1921
+ "hr",
1922
+ {
1923
+ style: {
1924
+ margin: "16px 0",
1925
+ border: "none",
1926
+ borderTop: "1px solid var(--chatllm-border, #e5e7eb)"
1927
+ }
1928
+ },
1929
+ `hr-${lineIndex}`
1930
+ )
1931
+ );
1932
+ return;
1933
+ }
1934
+ const headingMatch = line.match(/^(#{1,6})\s+(.+)$/);
1935
+ if (headingMatch) {
1936
+ flushList();
1937
+ flushBlockquote();
1938
+ const level = headingMatch[1].length;
1939
+ const text = headingMatch[2];
1940
+ const HeadingTag = `h${level}`;
1941
+ const sizes = {
1942
+ 1: "1.5em",
1943
+ 2: "1.3em",
1944
+ 3: "1.15em",
1945
+ 4: "1.05em",
1946
+ 5: "1em",
1947
+ 6: "0.95em"
1948
+ };
1949
+ elements.push(
1950
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
1951
+ HeadingTag,
1952
+ {
1953
+ style: {
1954
+ fontSize: sizes[level],
1955
+ fontWeight: level <= 2 ? 600 : 500,
1956
+ margin: "16px 0 8px",
1957
+ color: "var(--chatllm-text, #1f2937)"
1958
+ },
1959
+ children: parseInlineElements(text, `heading-${lineIndex}`)
1960
+ },
1961
+ `heading-${lineIndex}`
1962
+ )
1963
+ );
1964
+ return;
1965
+ }
1966
+ const blockquoteMatch = line.match(/^>\s*(.*)$/);
1967
+ if (blockquoteMatch) {
1968
+ flushList();
1969
+ blockquoteLines.push(blockquoteMatch[1]);
1970
+ return;
1971
+ } else {
1972
+ flushBlockquote();
1973
+ }
1974
+ const ulMatch = line.match(/^[\-\*]\s+(.+)$/);
1975
+ if (ulMatch) {
1976
+ flushBlockquote();
1977
+ if (!currentList || currentList.type !== "ul") {
1978
+ flushList();
1979
+ currentList = { type: "ul", items: [] };
1980
+ }
1981
+ currentList.items.push(
1982
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { style: { margin: "4px 0" }, children: parseInlineElements(ulMatch[1], `li-${lineIndex}`) }, `li-${lineIndex}`)
1983
+ );
1984
+ return;
1985
+ }
1986
+ const olMatch = line.match(/^(\d+)\.\s+(.+)$/);
1987
+ if (olMatch) {
1988
+ flushBlockquote();
1989
+ if (!currentList || currentList.type !== "ol") {
1990
+ flushList();
1991
+ currentList = { type: "ol", items: [] };
1992
+ }
1993
+ currentList.items.push(
1994
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("li", { style: { margin: "4px 0" }, children: parseInlineElements(olMatch[2], `li-${lineIndex}`) }, `li-${lineIndex}`)
1995
+ );
1996
+ return;
1997
+ }
1998
+ flushList();
1999
+ if (!line.trim()) {
2000
+ elements.push(/* @__PURE__ */ (0, import_jsx_runtime6.jsx)("br", {}, `br-${lineIndex}`));
2001
+ return;
2002
+ }
2003
+ elements.push(
2004
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { style: { margin: "4px 0" }, children: parseInlineElements(line, `p-${lineIndex}`) }, `p-${lineIndex}`)
2005
+ );
2006
+ });
2007
+ flushList();
2008
+ flushBlockquote();
2009
+ return elements;
2010
+ }, [content]);
2011
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2012
+ "div",
2013
+ {
2014
+ className: `chatllm-markdown ${className || ""}`,
2015
+ style: {
2016
+ fontSize: "15px",
2017
+ lineHeight: "1.7",
2018
+ color: "var(--chatllm-text, #374151)"
2019
+ },
2020
+ children: rendered
2021
+ }
2022
+ );
2023
+ };
2024
+
2025
+ // src/react/components/MessageBubble.tsx
2026
+ var import_jsx_runtime7 = require("react/jsx-runtime");
1462
2027
  var MessageBubble = ({
1463
2028
  message,
1464
2029
  isLoading,
@@ -1472,7 +2037,7 @@ var MessageBubble = ({
1472
2037
  activeAlternativeIndex = 0,
1473
2038
  onAlternativeChange
1474
2039
  }) => {
1475
- const [showActions, setShowActions] = (0, import_react4.useState)(false);
2040
+ const [showActions, setShowActions] = (0, import_react6.useState)(false);
1476
2041
  const isUser = message.role === "user";
1477
2042
  const isAssistant = message.role === "assistant";
1478
2043
  const displayContent = alternatives && alternatives.length > 0 && activeAlternativeIndex > 0 ? alternatives[activeAlternativeIndex - 1]?.content || message.content : message.content;
@@ -1484,7 +2049,7 @@ var MessageBubble = ({
1484
2049
  if (text && text.length > 0) {
1485
2050
  }
1486
2051
  };
1487
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2052
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1488
2053
  "div",
1489
2054
  {
1490
2055
  className: `chatllm-message chatllm-message--${message.role}`,
@@ -1498,7 +2063,7 @@ var MessageBubble = ({
1498
2063
  onMouseLeave: () => setShowActions(false),
1499
2064
  onMouseUp: handleMouseUp,
1500
2065
  children: [
1501
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2066
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1502
2067
  "div",
1503
2068
  {
1504
2069
  style: {
@@ -1511,7 +2076,7 @@ var MessageBubble = ({
1511
2076
  justifyContent: "center",
1512
2077
  flexShrink: 0
1513
2078
  },
1514
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2079
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1515
2080
  IconSvg,
1516
2081
  {
1517
2082
  name: isUser ? "user-3-line" : "robot-line",
@@ -1521,8 +2086,8 @@ var MessageBubble = ({
1521
2086
  )
1522
2087
  }
1523
2088
  ),
1524
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
1525
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2089
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2090
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1526
2091
  "div",
1527
2092
  {
1528
2093
  style: {
@@ -1532,7 +2097,7 @@ var MessageBubble = ({
1532
2097
  marginBottom: "8px"
1533
2098
  },
1534
2099
  children: [
1535
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2100
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1536
2101
  "span",
1537
2102
  {
1538
2103
  style: {
@@ -1543,7 +2108,7 @@ var MessageBubble = ({
1543
2108
  children: isUser ? "\uB098" : "AI"
1544
2109
  }
1545
2110
  ),
1546
- displayModel && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2111
+ displayModel && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1547
2112
  "span",
1548
2113
  {
1549
2114
  style: {
@@ -1559,19 +2124,32 @@ var MessageBubble = ({
1559
2124
  ]
1560
2125
  }
1561
2126
  ),
1562
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2127
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1563
2128
  "div",
1564
2129
  {
1565
2130
  style: {
1566
- fontSize: "15px",
1567
- lineHeight: "1.7",
1568
- color: "var(--chatllm-text, #374151)",
1569
- whiteSpace: "pre-wrap",
1570
2131
  wordBreak: "break-word"
1571
2132
  },
1572
2133
  children: [
1573
- displayContent,
1574
- isLoading && isAssistant && !displayContent && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2134
+ isAssistant ? (
2135
+ // AI 메시지는 마크다운 렌더링
2136
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MarkdownRenderer, { content: displayContent })
2137
+ ) : (
2138
+ // 사용자 메시지는 일반 텍스트
2139
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2140
+ "div",
2141
+ {
2142
+ style: {
2143
+ fontSize: "15px",
2144
+ lineHeight: "1.7",
2145
+ color: "var(--chatllm-text, #374151)",
2146
+ whiteSpace: "pre-wrap"
2147
+ },
2148
+ children: displayContent
2149
+ }
2150
+ )
2151
+ ),
2152
+ isLoading && isAssistant && !displayContent && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1575
2153
  "span",
1576
2154
  {
1577
2155
  style: {
@@ -1579,16 +2157,16 @@ var MessageBubble = ({
1579
2157
  gap: "4px"
1580
2158
  },
1581
2159
  children: [
1582
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "chatllm-typing-dot", style: dotStyle }),
1583
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "chatllm-typing-dot", style: { ...dotStyle, animationDelay: "0.2s" } }),
1584
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "chatllm-typing-dot", style: { ...dotStyle, animationDelay: "0.4s" } })
2160
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "chatllm-typing-dot", style: dotStyle }),
2161
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "chatllm-typing-dot", style: { ...dotStyle, animationDelay: "0.2s" } }),
2162
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "chatllm-typing-dot", style: { ...dotStyle, animationDelay: "0.4s" } })
1585
2163
  ]
1586
2164
  }
1587
2165
  )
1588
2166
  ]
1589
2167
  }
1590
2168
  ),
1591
- alternatives && alternatives.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2169
+ alternatives && alternatives.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1592
2170
  "div",
1593
2171
  {
1594
2172
  style: {
@@ -1600,7 +2178,7 @@ var MessageBubble = ({
1600
2178
  borderTop: "1px solid var(--chatllm-border-light, #f3f4f6)"
1601
2179
  },
1602
2180
  children: [
1603
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2181
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1604
2182
  "button",
1605
2183
  {
1606
2184
  onClick: () => onAlternativeChange?.(Math.max(0, activeAlternativeIndex - 1)),
@@ -1610,15 +2188,15 @@ var MessageBubble = ({
1610
2188
  opacity: activeAlternativeIndex === 0 ? 0.5 : 1,
1611
2189
  cursor: activeAlternativeIndex === 0 ? "not-allowed" : "pointer"
1612
2190
  },
1613
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconSvg, { name: "arrow-left-line", size: 14 })
2191
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSvg, { name: "arrow-left-line", size: 14 })
1614
2192
  }
1615
2193
  ),
1616
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { style: { fontSize: "12px", color: "var(--chatllm-text-muted, #9ca3af)" }, children: [
2194
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { fontSize: "12px", color: "var(--chatllm-text-muted, #9ca3af)" }, children: [
1617
2195
  activeAlternativeIndex + 1,
1618
2196
  " / ",
1619
2197
  alternatives.length + 1
1620
2198
  ] }),
1621
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2199
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1622
2200
  "button",
1623
2201
  {
1624
2202
  onClick: () => onAlternativeChange?.(Math.min(alternatives.length, activeAlternativeIndex + 1)),
@@ -1628,13 +2206,13 @@ var MessageBubble = ({
1628
2206
  opacity: activeAlternativeIndex === alternatives.length ? 0.5 : 1,
1629
2207
  cursor: activeAlternativeIndex === alternatives.length ? "not-allowed" : "pointer"
1630
2208
  },
1631
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconSvg, { name: "arrow-right-line", size: 14 })
2209
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSvg, { name: "arrow-right-line", size: 14 })
1632
2210
  }
1633
2211
  )
1634
2212
  ]
1635
2213
  }
1636
2214
  ),
1637
- showActions && !isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
2215
+ showActions && !isLoading && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1638
2216
  "div",
1639
2217
  {
1640
2218
  style: {
@@ -1643,7 +2221,7 @@ var MessageBubble = ({
1643
2221
  marginTop: "12px"
1644
2222
  },
1645
2223
  children: [
1646
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: onCopy, style: actionButtonStyle, title: "\uBCF5\uC0AC", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
2224
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { onClick: onCopy, style: actionButtonStyle, title: "\uBCF5\uC0AC", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1647
2225
  IconSvg,
1648
2226
  {
1649
2227
  name: isCopied ? "check-line" : "file-copy-line",
@@ -1651,8 +2229,8 @@ var MessageBubble = ({
1651
2229
  color: isCopied ? "var(--chatllm-success, #22c55e)" : "var(--chatllm-text-muted, #9ca3af)"
1652
2230
  }
1653
2231
  ) }),
1654
- isUser && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: onEdit, style: actionButtonStyle, title: "\uC218\uC815", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconSvg, { name: "edit-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" }) }),
1655
- isAssistant && onRegenerate && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("button", { onClick: onRegenerate, style: actionButtonStyle, title: "\uB2E4\uC2DC \uC0DD\uC131", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(IconSvg, { name: "refresh-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" }) })
2232
+ isUser && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { onClick: onEdit, style: actionButtonStyle, title: "\uC218\uC815", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSvg, { name: "edit-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" }) }),
2233
+ isAssistant && onRegenerate && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { onClick: onRegenerate, style: actionButtonStyle, title: "\uB2E4\uC2DC \uC0DD\uC131", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSvg, { name: "refresh-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" }) })
1656
2234
  ]
1657
2235
  }
1658
2236
  )
@@ -1691,7 +2269,7 @@ var navButtonStyle = {
1691
2269
  };
1692
2270
 
1693
2271
  // src/react/components/MessageList.tsx
1694
- var import_jsx_runtime6 = require("react/jsx-runtime");
2272
+ var import_jsx_runtime8 = require("react/jsx-runtime");
1695
2273
  var MessageList = ({
1696
2274
  messages,
1697
2275
  isLoading,
@@ -1702,14 +2280,14 @@ var MessageList = ({
1702
2280
  copiedId,
1703
2281
  editingId
1704
2282
  }) => {
1705
- const messagesEndRef = (0, import_react5.useRef)(null);
1706
- const containerRef = (0, import_react5.useRef)(null);
1707
- const [selectedText, setSelectedText] = (0, import_react5.useState)("");
1708
- const [selectionPosition, setSelectionPosition] = (0, import_react5.useState)(null);
1709
- (0, import_react5.useEffect)(() => {
2283
+ const messagesEndRef = (0, import_react7.useRef)(null);
2284
+ const containerRef = (0, import_react7.useRef)(null);
2285
+ const [selectedText, setSelectedText] = (0, import_react7.useState)("");
2286
+ const [selectionPosition, setSelectionPosition] = (0, import_react7.useState)(null);
2287
+ (0, import_react7.useEffect)(() => {
1710
2288
  messagesEndRef.current?.scrollIntoView({ behavior: "smooth" });
1711
2289
  }, [messages]);
1712
- const handleMouseUp = (0, import_react5.useCallback)(() => {
2290
+ const handleMouseUp = (0, import_react7.useCallback)(() => {
1713
2291
  const selection = window.getSelection();
1714
2292
  const text = selection?.toString().trim();
1715
2293
  if (text && text.length > 0) {
@@ -1740,7 +2318,7 @@ var MessageList = ({
1740
2318
  window.getSelection()?.removeAllRanges();
1741
2319
  }
1742
2320
  };
1743
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2321
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1744
2322
  "div",
1745
2323
  {
1746
2324
  ref: containerRef,
@@ -1752,7 +2330,7 @@ var MessageList = ({
1752
2330
  },
1753
2331
  onMouseUp: handleMouseUp,
1754
2332
  children: [
1755
- messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2333
+ messages.map((message, index) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1756
2334
  MessageBubble,
1757
2335
  {
1758
2336
  message,
@@ -1767,7 +2345,7 @@ var MessageList = ({
1767
2345
  },
1768
2346
  message.id
1769
2347
  )),
1770
- selectionPosition && /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2348
+ selectionPosition && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1771
2349
  "div",
1772
2350
  {
1773
2351
  style: {
@@ -1778,7 +2356,7 @@ var MessageList = ({
1778
2356
  zIndex: 50
1779
2357
  },
1780
2358
  children: [
1781
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
2359
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1782
2360
  "button",
1783
2361
  {
1784
2362
  onClick: handleQuote,
@@ -1797,12 +2375,12 @@ var MessageList = ({
1797
2375
  boxShadow: "0 4px 12px rgba(0, 0, 0, 0.15)"
1798
2376
  },
1799
2377
  children: [
1800
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(IconSvg, { name: "double-quotes-l", size: 14, color: "#ffffff" }),
2378
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "double-quotes-l", size: 14, color: "#ffffff" }),
1801
2379
  "\uC778\uC6A9\uD558\uAE30"
1802
2380
  ]
1803
2381
  }
1804
2382
  ),
1805
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
2383
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1806
2384
  "div",
1807
2385
  {
1808
2386
  style: {
@@ -1821,14 +2399,14 @@ var MessageList = ({
1821
2399
  ]
1822
2400
  }
1823
2401
  ),
1824
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: messagesEndRef })
2402
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { ref: messagesEndRef })
1825
2403
  ]
1826
2404
  }
1827
2405
  );
1828
2406
  };
1829
2407
 
1830
2408
  // src/react/components/EmptyState.tsx
1831
- var import_jsx_runtime7 = require("react/jsx-runtime");
2409
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1832
2410
  var EmptyState = ({
1833
2411
  greeting,
1834
2412
  templates = [],
@@ -1845,7 +2423,7 @@ var EmptyState = ({
1845
2423
  };
1846
2424
  return iconMap[icon] || "sparkling-line";
1847
2425
  };
1848
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2426
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1849
2427
  "div",
1850
2428
  {
1851
2429
  className: "chatllm-empty-state",
@@ -1859,7 +2437,7 @@ var EmptyState = ({
1859
2437
  textAlign: "center"
1860
2438
  },
1861
2439
  children: [
1862
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2440
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1863
2441
  "div",
1864
2442
  {
1865
2443
  style: {
@@ -1873,10 +2451,10 @@ var EmptyState = ({
1873
2451
  marginBottom: "24px",
1874
2452
  boxShadow: "0 8px 32px rgba(59, 130, 246, 0.25)"
1875
2453
  },
1876
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSvg, { name: "sparkling-line", size: 32, color: "#ffffff" })
2454
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconSvg, { name: "sparkling-line", size: 32, color: "#ffffff" })
1877
2455
  }
1878
2456
  ),
1879
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2457
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1880
2458
  "h1",
1881
2459
  {
1882
2460
  style: {
@@ -1888,7 +2466,7 @@ var EmptyState = ({
1888
2466
  children: greeting
1889
2467
  }
1890
2468
  ),
1891
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2469
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1892
2470
  "p",
1893
2471
  {
1894
2472
  style: {
@@ -1899,7 +2477,7 @@ var EmptyState = ({
1899
2477
  children: "\uBB34\uC5C7\uC744 \uB3C4\uC640\uB4DC\uB9B4\uAE4C\uC694?"
1900
2478
  }
1901
2479
  ),
1902
- actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2480
+ actions.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1903
2481
  "div",
1904
2482
  {
1905
2483
  style: {
@@ -1910,7 +2488,7 @@ var EmptyState = ({
1910
2488
  maxWidth: "600px",
1911
2489
  marginBottom: "32px"
1912
2490
  },
1913
- children: actions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2491
+ children: actions.map((action) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
1914
2492
  "button",
1915
2493
  {
1916
2494
  onClick: () => onActionSelect?.(action),
@@ -1935,7 +2513,7 @@ var EmptyState = ({
1935
2513
  e.currentTarget.style.boxShadow = "none";
1936
2514
  },
1937
2515
  children: [
1938
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2516
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1939
2517
  "div",
1940
2518
  {
1941
2519
  style: {
@@ -1947,7 +2525,7 @@ var EmptyState = ({
1947
2525
  alignItems: "center",
1948
2526
  justifyContent: "center"
1949
2527
  },
1950
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2528
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1951
2529
  IconSvg,
1952
2530
  {
1953
2531
  name: getActionIcon(action.icon),
@@ -1957,7 +2535,7 @@ var EmptyState = ({
1957
2535
  )
1958
2536
  }
1959
2537
  ),
1960
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2538
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1961
2539
  "div",
1962
2540
  {
1963
2541
  style: {
@@ -1974,8 +2552,8 @@ var EmptyState = ({
1974
2552
  ))
1975
2553
  }
1976
2554
  ),
1977
- templates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { width: "100%", maxWidth: "600px" }, children: [
1978
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2555
+ templates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { width: "100%", maxWidth: "600px" }, children: [
2556
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1979
2557
  "h3",
1980
2558
  {
1981
2559
  style: {
@@ -1988,7 +2566,7 @@ var EmptyState = ({
1988
2566
  children: "\uCD94\uCC9C \uD504\uB86C\uD504\uD2B8"
1989
2567
  }
1990
2568
  ),
1991
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2569
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1992
2570
  "div",
1993
2571
  {
1994
2572
  style: {
@@ -1996,7 +2574,7 @@ var EmptyState = ({
1996
2574
  flexDirection: "column",
1997
2575
  gap: "8px"
1998
2576
  },
1999
- children: templates.map((template) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2577
+ children: templates.map((template) => /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
2000
2578
  "button",
2001
2579
  {
2002
2580
  onClick: () => onTemplateClick(template),
@@ -2019,7 +2597,7 @@ var EmptyState = ({
2019
2597
  e.currentTarget.style.backgroundColor = "var(--chatllm-bg, #ffffff)";
2020
2598
  },
2021
2599
  children: [
2022
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2600
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2023
2601
  "div",
2024
2602
  {
2025
2603
  style: {
@@ -2032,11 +2610,11 @@ var EmptyState = ({
2032
2610
  justifyContent: "center",
2033
2611
  flexShrink: 0
2034
2612
  },
2035
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSvg, { name: "file-text-line", size: 18, color: "var(--chatllm-text-muted, #6b7280)" })
2613
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconSvg, { name: "file-text-line", size: 18, color: "var(--chatllm-text-muted, #6b7280)" })
2036
2614
  }
2037
2615
  ),
2038
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2039
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2616
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2617
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2040
2618
  "div",
2041
2619
  {
2042
2620
  style: {
@@ -2047,7 +2625,7 @@ var EmptyState = ({
2047
2625
  children: template.title
2048
2626
  }
2049
2627
  ),
2050
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2628
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
2051
2629
  "div",
2052
2630
  {
2053
2631
  style: {
@@ -2061,7 +2639,7 @@ var EmptyState = ({
2061
2639
  }
2062
2640
  )
2063
2641
  ] }),
2064
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(IconSvg, { name: "arrow-right-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" })
2642
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(IconSvg, { name: "arrow-right-line", size: 16, color: "var(--chatllm-text-muted, #9ca3af)" })
2065
2643
  ]
2066
2644
  },
2067
2645
  template.id
@@ -2075,8 +2653,8 @@ var EmptyState = ({
2075
2653
  };
2076
2654
 
2077
2655
  // src/react/components/MemoryPanel.tsx
2078
- var import_react6 = require("react");
2079
- var import_jsx_runtime8 = require("react/jsx-runtime");
2656
+ var import_react8 = require("react");
2657
+ var import_jsx_runtime10 = require("react/jsx-runtime");
2080
2658
  var categoryLabels = {
2081
2659
  context: "\uB300\uD654 \uCEE8\uD14D\uC2A4\uD2B8",
2082
2660
  preference: "\uC0AC\uC6A9\uC790 \uC120\uD638",
@@ -2097,8 +2675,8 @@ var MemoryPanel = ({
2097
2675
  isOpen,
2098
2676
  onToggle
2099
2677
  }) => {
2100
- const [expandedId, setExpandedId] = (0, import_react6.useState)(null);
2101
- const [activeTab, setActiveTab] = (0, import_react6.useState)("all");
2678
+ const [expandedId, setExpandedId] = (0, import_react8.useState)(null);
2679
+ const [activeTab, setActiveTab] = (0, import_react8.useState)("all");
2102
2680
  const filteredItems = activeTab === "all" ? items : items.filter((item) => item.category === activeTab);
2103
2681
  const formatDate2 = (timestamp) => {
2104
2682
  const date = new Date(timestamp);
@@ -2110,7 +2688,7 @@ var MemoryPanel = ({
2110
2688
  });
2111
2689
  };
2112
2690
  if (!isOpen) {
2113
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2691
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2114
2692
  "button",
2115
2693
  {
2116
2694
  onClick: onToggle,
@@ -2130,11 +2708,11 @@ var MemoryPanel = ({
2130
2708
  justifyContent: "center",
2131
2709
  zIndex: 100
2132
2710
  },
2133
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "robot-line", size: 24, color: "#ffffff" })
2711
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "robot-line", size: 24, color: "#ffffff" })
2134
2712
  }
2135
2713
  );
2136
2714
  }
2137
- return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2715
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2138
2716
  "div",
2139
2717
  {
2140
2718
  className: "chatllm-memory-panel",
@@ -2154,7 +2732,7 @@ var MemoryPanel = ({
2154
2732
  zIndex: 100
2155
2733
  },
2156
2734
  children: [
2157
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2735
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2158
2736
  "div",
2159
2737
  {
2160
2738
  style: {
@@ -2165,8 +2743,8 @@ var MemoryPanel = ({
2165
2743
  borderBottom: "1px solid var(--chatllm-border, #e5e7eb)"
2166
2744
  },
2167
2745
  children: [
2168
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
2169
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2746
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "10px" }, children: [
2747
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2170
2748
  "div",
2171
2749
  {
2172
2750
  style: {
@@ -2178,19 +2756,19 @@ var MemoryPanel = ({
2178
2756
  alignItems: "center",
2179
2757
  justifyContent: "center"
2180
2758
  },
2181
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "robot-line", size: 18, color: "var(--chatllm-primary, #3b82f6)" })
2759
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "robot-line", size: 18, color: "var(--chatllm-primary, #3b82f6)" })
2182
2760
  }
2183
2761
  ),
2184
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
2185
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { fontSize: "15px", fontWeight: 600, color: "var(--chatllm-text, #1f2937)" }, children: "AI \uBA54\uBAA8\uB9AC" }),
2186
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { fontSize: "12px", color: "var(--chatllm-text-muted, #9ca3af)" }, children: [
2762
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { children: [
2763
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { fontSize: "15px", fontWeight: 600, color: "var(--chatllm-text, #1f2937)" }, children: "AI \uBA54\uBAA8\uB9AC" }),
2764
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { fontSize: "12px", color: "var(--chatllm-text-muted, #9ca3af)" }, children: [
2187
2765
  items.length,
2188
2766
  "\uAC1C \uD56D\uBAA9"
2189
2767
  ] })
2190
2768
  ] })
2191
2769
  ] }),
2192
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", gap: "4px" }, children: [
2193
- onClearAll && items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2770
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", gap: "4px" }, children: [
2771
+ onClearAll && items.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2194
2772
  "button",
2195
2773
  {
2196
2774
  onClick: onClearAll,
@@ -2202,10 +2780,10 @@ var MemoryPanel = ({
2202
2780
  cursor: "pointer"
2203
2781
  },
2204
2782
  title: "\uC804\uCCB4 \uC0AD\uC81C",
2205
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "delete-bin-line", size: 18, color: "var(--chatllm-text-muted, #9ca3af)" })
2783
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "delete-bin-line", size: 18, color: "var(--chatllm-text-muted, #9ca3af)" })
2206
2784
  }
2207
2785
  ),
2208
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2786
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2209
2787
  "button",
2210
2788
  {
2211
2789
  onClick: onToggle,
@@ -2216,14 +2794,14 @@ var MemoryPanel = ({
2216
2794
  borderRadius: "8px",
2217
2795
  cursor: "pointer"
2218
2796
  },
2219
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "close-line", size: 18, color: "var(--chatllm-text-muted, #9ca3af)" })
2797
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "close-line", size: 18, color: "var(--chatllm-text-muted, #9ca3af)" })
2220
2798
  }
2221
2799
  )
2222
2800
  ] })
2223
2801
  ]
2224
2802
  }
2225
2803
  ),
2226
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2804
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2227
2805
  "div",
2228
2806
  {
2229
2807
  style: {
@@ -2233,7 +2811,7 @@ var MemoryPanel = ({
2233
2811
  borderBottom: "1px solid var(--chatllm-border-light, #f3f4f6)",
2234
2812
  overflowX: "auto"
2235
2813
  },
2236
- children: ["all", "context", "preference", "skill", "fact"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2814
+ children: ["all", "context", "preference", "skill", "fact"].map((tab) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2237
2815
  "button",
2238
2816
  {
2239
2817
  onClick: () => setActiveTab(tab),
@@ -2254,8 +2832,8 @@ var MemoryPanel = ({
2254
2832
  ))
2255
2833
  }
2256
2834
  ),
2257
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { flex: 1, overflow: "auto", padding: "12px" }, children: [
2258
- contextSummary && activeTab === "all" && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2835
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1, overflow: "auto", padding: "12px" }, children: [
2836
+ contextSummary && activeTab === "all" && /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2259
2837
  "div",
2260
2838
  {
2261
2839
  style: {
@@ -2266,7 +2844,7 @@ var MemoryPanel = ({
2266
2844
  borderLeft: "3px solid var(--chatllm-primary, #3b82f6)"
2267
2845
  },
2268
2846
  children: [
2269
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2847
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2270
2848
  "div",
2271
2849
  {
2272
2850
  style: {
@@ -2276,12 +2854,12 @@ var MemoryPanel = ({
2276
2854
  marginBottom: "8px"
2277
2855
  },
2278
2856
  children: [
2279
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "file-text-line", size: 14, color: "var(--chatllm-primary, #3b82f6)" }),
2280
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "12px", fontWeight: 500, color: "var(--chatllm-primary, #3b82f6)" }, children: "\uB300\uD654 \uC694\uC57D" })
2857
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "file-text-line", size: 14, color: "var(--chatllm-primary, #3b82f6)" }),
2858
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { fontSize: "12px", fontWeight: 500, color: "var(--chatllm-primary, #3b82f6)" }, children: "\uB300\uD654 \uC694\uC57D" })
2281
2859
  ]
2282
2860
  }
2283
2861
  ),
2284
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2862
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2285
2863
  "p",
2286
2864
  {
2287
2865
  style: {
@@ -2296,7 +2874,7 @@ var MemoryPanel = ({
2296
2874
  ]
2297
2875
  }
2298
2876
  ),
2299
- filteredItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2877
+ filteredItems.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2300
2878
  "div",
2301
2879
  {
2302
2880
  style: {
@@ -2305,11 +2883,11 @@ var MemoryPanel = ({
2305
2883
  color: "var(--chatllm-text-muted, #9ca3af)"
2306
2884
  },
2307
2885
  children: [
2308
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "robot-line", size: 32, color: "var(--chatllm-text-muted, #d1d5db)" }),
2309
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { style: { fontSize: "14px", marginTop: "12px" }, children: "\uC800\uC7A5\uB41C \uBA54\uBAA8\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" })
2886
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "robot-line", size: 32, color: "var(--chatllm-text-muted, #d1d5db)" }),
2887
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { style: { fontSize: "14px", marginTop: "12px" }, children: "\uC800\uC7A5\uB41C \uBA54\uBAA8\uB9AC\uAC00 \uC5C6\uC2B5\uB2C8\uB2E4" })
2310
2888
  ]
2311
2889
  }
2312
- ) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: filteredItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
2890
+ ) : /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { style: { display: "flex", flexDirection: "column", gap: "8px" }, children: filteredItems.map((item) => /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)(
2313
2891
  "div",
2314
2892
  {
2315
2893
  style: {
@@ -2322,10 +2900,10 @@ var MemoryPanel = ({
2322
2900
  },
2323
2901
  onClick: () => setExpandedId(expandedId === item.id ? null : item.id),
2324
2902
  children: [
2325
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between" }, children: [
2326
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2327
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "4px" }, children: [
2328
- item.category && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2903
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "flex-start", justifyContent: "space-between" }, children: [
2904
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { flex: 1, minWidth: 0 }, children: [
2905
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "8px", marginBottom: "4px" }, children: [
2906
+ item.category && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2329
2907
  "span",
2330
2908
  {
2331
2909
  style: {
@@ -2339,9 +2917,9 @@ var MemoryPanel = ({
2339
2917
  children: categoryLabels[item.category]
2340
2918
  }
2341
2919
  ),
2342
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { style: { fontSize: "11px", color: "var(--chatllm-text-muted, #9ca3af)" }, children: formatDate2(item.timestamp) })
2920
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("span", { style: { fontSize: "11px", color: "var(--chatllm-text-muted, #9ca3af)" }, children: formatDate2(item.timestamp) })
2343
2921
  ] }),
2344
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2922
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2345
2923
  "div",
2346
2924
  {
2347
2925
  style: {
@@ -2353,8 +2931,8 @@ var MemoryPanel = ({
2353
2931
  }
2354
2932
  )
2355
2933
  ] }),
2356
- /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2357
- onDelete && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2934
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { style: { display: "flex", alignItems: "center", gap: "4px" }, children: [
2935
+ onDelete && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2358
2936
  "button",
2359
2937
  {
2360
2938
  onClick: (e) => {
@@ -2369,10 +2947,10 @@ var MemoryPanel = ({
2369
2947
  cursor: "pointer",
2370
2948
  opacity: 0.5
2371
2949
  },
2372
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(IconSvg, { name: "delete-bin-line", size: 14, color: "var(--chatllm-text-muted, #9ca3af)" })
2950
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(IconSvg, { name: "delete-bin-line", size: 14, color: "var(--chatllm-text-muted, #9ca3af)" })
2373
2951
  }
2374
2952
  ),
2375
- /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2953
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2376
2954
  IconSvg,
2377
2955
  {
2378
2956
  name: expandedId === item.id ? "arrow-up-s-line" : "arrow-down-s-line",
@@ -2382,7 +2960,7 @@ var MemoryPanel = ({
2382
2960
  )
2383
2961
  ] })
2384
2962
  ] }),
2385
- expandedId === item.id && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2963
+ expandedId === item.id && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2386
2964
  "div",
2387
2965
  {
2388
2966
  style: {
@@ -2390,7 +2968,7 @@ var MemoryPanel = ({
2390
2968
  paddingTop: "12px",
2391
2969
  borderTop: "1px solid var(--chatllm-border-light, #f3f4f6)"
2392
2970
  },
2393
- children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
2971
+ children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
2394
2972
  "p",
2395
2973
  {
2396
2974
  style: {
@@ -2415,8 +2993,439 @@ var MemoryPanel = ({
2415
2993
  );
2416
2994
  };
2417
2995
 
2996
+ // src/react/components/SettingsModal.tsx
2997
+ var import_react9 = require("react");
2998
+ var import_jsx_runtime11 = require("react/jsx-runtime");
2999
+ var DEFAULT_PERSONALIZATION2 = {
3000
+ responseStyle: {
3001
+ warmth: "medium",
3002
+ enthusiasm: "medium",
3003
+ emojiUsage: "low",
3004
+ formatting: "default",
3005
+ verbosity: "balanced"
3006
+ },
3007
+ userProfile: {},
3008
+ useMemory: true,
3009
+ language: "auto"
3010
+ };
3011
+ var SettingsModal = ({
3012
+ isOpen,
3013
+ onClose,
3014
+ personalization,
3015
+ onPersonalizationChange,
3016
+ apiKey = "",
3017
+ onApiKeyChange,
3018
+ onClearAllData,
3019
+ apiKeyLabel = "API Key",
3020
+ apiKeyDescription = "Cloud \uBAA8\uB378 \uC0AC\uC6A9\uC5D0 \uD544\uC694\uD569\uB2C8\uB2E4"
3021
+ }) => {
3022
+ const [activeTab, setActiveTab] = (0, import_react9.useState)("general");
3023
+ const [localApiKey, setLocalApiKey] = (0, import_react9.useState)(apiKey);
3024
+ if (!isOpen) return null;
3025
+ const updateResponseStyle = (key, value) => {
3026
+ onPersonalizationChange({
3027
+ ...personalization,
3028
+ responseStyle: {
3029
+ ...personalization.responseStyle,
3030
+ [key]: value
3031
+ }
3032
+ });
3033
+ };
3034
+ const updateUserProfile = (key, value) => {
3035
+ onPersonalizationChange({
3036
+ ...personalization,
3037
+ userProfile: {
3038
+ ...personalization.userProfile,
3039
+ [key]: value
3040
+ }
3041
+ });
3042
+ };
3043
+ const handleApiKeyChange = (value) => {
3044
+ setLocalApiKey(value);
3045
+ onApiKeyChange?.(value);
3046
+ };
3047
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3048
+ "div",
3049
+ {
3050
+ className: "chatllm-settings-overlay",
3051
+ style: {
3052
+ position: "fixed",
3053
+ inset: 0,
3054
+ backgroundColor: "rgba(0, 0, 0, 0.3)",
3055
+ display: "flex",
3056
+ alignItems: "center",
3057
+ justifyContent: "center",
3058
+ zIndex: 1e3
3059
+ },
3060
+ onClick: onClose,
3061
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3062
+ "div",
3063
+ {
3064
+ className: "chatllm-settings-modal",
3065
+ style: {
3066
+ backgroundColor: "var(--chatllm-bg, #ffffff)",
3067
+ borderRadius: "16px",
3068
+ width: "100%",
3069
+ maxWidth: "800px",
3070
+ height: "80vh",
3071
+ maxHeight: "600px",
3072
+ margin: "16px",
3073
+ boxShadow: "0 20px 60px rgba(0, 0, 0, 0.15)",
3074
+ display: "flex",
3075
+ overflow: "hidden"
3076
+ },
3077
+ onClick: (e) => e.stopPropagation(),
3078
+ children: [
3079
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3080
+ "div",
3081
+ {
3082
+ style: {
3083
+ width: "200px",
3084
+ backgroundColor: "var(--chatllm-bg-secondary, #f9fafb)",
3085
+ borderRight: "1px solid var(--chatllm-border, #e5e7eb)",
3086
+ display: "flex",
3087
+ flexDirection: "column"
3088
+ },
3089
+ children: [
3090
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { style: { padding: "16px", borderBottom: "1px solid var(--chatllm-border, #e5e7eb)" }, children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3091
+ "button",
3092
+ {
3093
+ onClick: onClose,
3094
+ style: {
3095
+ padding: "8px",
3096
+ backgroundColor: "transparent",
3097
+ border: "none",
3098
+ borderRadius: "8px",
3099
+ cursor: "pointer",
3100
+ display: "flex",
3101
+ alignItems: "center",
3102
+ justifyContent: "center"
3103
+ },
3104
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconSvg, { name: "close-line", size: 20, color: "var(--chatllm-text-muted, #6b7280)" })
3105
+ }
3106
+ ) }),
3107
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("nav", { style: { flex: 1, padding: "8px" }, children: [
3108
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3109
+ TabButton,
3110
+ {
3111
+ active: activeTab === "general",
3112
+ onClick: () => setActiveTab("general"),
3113
+ icon: "settings-3-line",
3114
+ label: "\uC77C\uBC18"
3115
+ }
3116
+ ),
3117
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3118
+ TabButton,
3119
+ {
3120
+ active: activeTab === "personalization",
3121
+ onClick: () => setActiveTab("personalization"),
3122
+ icon: "user-3-line",
3123
+ label: "\uAC1C\uC778 \uB9DE\uCDA4 \uC124\uC815"
3124
+ }
3125
+ ),
3126
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3127
+ TabButton,
3128
+ {
3129
+ active: activeTab === "data",
3130
+ onClick: () => setActiveTab("data"),
3131
+ icon: "delete-bin-line",
3132
+ label: "\uB370\uC774\uD130 \uC81C\uC5B4"
3133
+ }
3134
+ )
3135
+ ] })
3136
+ ]
3137
+ }
3138
+ ),
3139
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { flex: 1, overflow: "auto", padding: "24px" }, children: [
3140
+ activeTab === "general" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3141
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { style: { fontSize: "20px", fontWeight: 600, marginBottom: "24px", color: "var(--chatllm-text, #1f2937)" }, children: "\uC77C\uBC18" }),
3142
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uC5B8\uC5B4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3143
+ "select",
3144
+ {
3145
+ value: personalization.language,
3146
+ onChange: (e) => onPersonalizationChange({ ...personalization, language: e.target.value }),
3147
+ style: selectStyle,
3148
+ children: [
3149
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "auto", children: "\uC790\uB3D9 \uD0D0\uC9C0" }),
3150
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "ko", children: "\uD55C\uAD6D\uC5B4" }),
3151
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "en", children: "English" }),
3152
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "ja", children: "\u65E5\u672C\u8A9E" })
3153
+ ]
3154
+ }
3155
+ ) }),
3156
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uAE30\uBCF8\uAC12\uC73C\uB85C \uCD08\uAE30\uD654", description: "\uBAA8\uB4E0 \uC124\uC815\uC744 \uCD08\uAE30 \uC0C1\uD0DC\uB85C \uB418\uB3CC\uB9BD\uB2C8\uB2E4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3157
+ "button",
3158
+ {
3159
+ onClick: () => onPersonalizationChange(DEFAULT_PERSONALIZATION2),
3160
+ style: buttonSecondaryStyle,
3161
+ children: "\uCD08\uAE30\uD654"
3162
+ }
3163
+ ) }),
3164
+ onApiKeyChange && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { marginTop: "32px", paddingTop: "24px", borderTop: "1px solid var(--chatllm-border, #e5e7eb)" }, children: [
3165
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { style: { fontSize: "16px", fontWeight: 500, marginBottom: "16px", color: "var(--chatllm-text, #1f2937)" }, children: "API \uC124\uC815" }),
3166
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3167
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { style: { display: "block", fontSize: "14px", marginBottom: "8px", color: "var(--chatllm-text, #374151)" }, children: apiKeyLabel }),
3168
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3169
+ "input",
3170
+ {
3171
+ type: "password",
3172
+ value: localApiKey,
3173
+ onChange: (e) => handleApiKeyChange(e.target.value),
3174
+ placeholder: "API \uD0A4\uB97C \uC785\uB825\uD558\uC138\uC694",
3175
+ style: inputStyle
3176
+ }
3177
+ ),
3178
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { fontSize: "12px", color: "var(--chatllm-text-muted, #9ca3af)", marginTop: "4px" }, children: apiKeyDescription })
3179
+ ] })
3180
+ ] })
3181
+ ] }),
3182
+ activeTab === "personalization" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3183
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { style: { fontSize: "20px", fontWeight: 600, marginBottom: "24px", color: "var(--chatllm-text, #1f2937)" }, children: "\uAC1C\uC778 \uB9DE\uCDA4 \uC124\uC815" }),
3184
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { style: { marginBottom: "32px" }, children: [
3185
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { style: { fontSize: "14px", fontWeight: 500, color: "var(--chatllm-text-muted, #6b7280)", marginBottom: "16px" }, children: "\uC0AC\uC6A9\uC790 \uD504\uB85C\uD544" }),
3186
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "12px" }, children: [
3187
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3188
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { style: labelStyle, children: "\uB2C9\uB124\uC784" }),
3189
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3190
+ "input",
3191
+ {
3192
+ type: "text",
3193
+ value: personalization.userProfile.nickname || "",
3194
+ onChange: (e) => updateUserProfile("nickname", e.target.value),
3195
+ placeholder: "\uC5B4\uB5BB\uAC8C \uBD88\uB7EC\uB4DC\uB9B4\uAE4C\uC694?",
3196
+ style: inputStyle
3197
+ }
3198
+ )
3199
+ ] }),
3200
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3201
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { style: labelStyle, children: "\uC9C1\uC5C5" }),
3202
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3203
+ "input",
3204
+ {
3205
+ type: "text",
3206
+ value: personalization.userProfile.occupation || "",
3207
+ onChange: (e) => updateUserProfile("occupation", e.target.value),
3208
+ placeholder: "\uC608: \uC18C\uD504\uD2B8\uC6E8\uC5B4 \uAC1C\uBC1C\uC790",
3209
+ style: inputStyle
3210
+ }
3211
+ )
3212
+ ] }),
3213
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3214
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("label", { style: labelStyle, children: "\uCD94\uAC00 \uC815\uBCF4" }),
3215
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3216
+ "textarea",
3217
+ {
3218
+ value: personalization.userProfile.additionalInfo || "",
3219
+ onChange: (e) => updateUserProfile("additionalInfo", e.target.value),
3220
+ placeholder: "\uAD00\uC2EC\uC0AC, \uC120\uD638 \uC0AC\uD56D \uB4F1",
3221
+ rows: 3,
3222
+ style: { ...inputStyle, resize: "none" }
3223
+ }
3224
+ )
3225
+ ] })
3226
+ ] })
3227
+ ] }),
3228
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("section", { children: [
3229
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h3", { style: { fontSize: "14px", fontWeight: 500, color: "var(--chatllm-text-muted, #6b7280)", marginBottom: "16px" }, children: "\uC751\uB2F5 \uC2A4\uD0C0\uC77C" }),
3230
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uB530\uB73B\uD568", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3231
+ "select",
3232
+ {
3233
+ value: personalization.responseStyle.warmth,
3234
+ onChange: (e) => updateResponseStyle("warmth", e.target.value),
3235
+ style: selectStyle,
3236
+ children: [
3237
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "high", children: "\uB192\uC74C - \uCE5C\uADFC\uD558\uACE0 \uB530\uB73B\uD558\uAC8C" }),
3238
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "medium", children: "\uAE30\uBCF8\uAC12" }),
3239
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "low", children: "\uB0AE\uC74C - \uAC04\uACB0\uD558\uACE0 \uC0AC\uBB34\uC801\uC73C\uB85C" })
3240
+ ]
3241
+ }
3242
+ ) }),
3243
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uC5F4\uC815\uC801", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3244
+ "select",
3245
+ {
3246
+ value: personalization.responseStyle.enthusiasm,
3247
+ onChange: (e) => updateResponseStyle("enthusiasm", e.target.value),
3248
+ style: selectStyle,
3249
+ children: [
3250
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "high", children: "\uB192\uC74C - \uC801\uADF9\uC801\uC774\uACE0 \uD65C\uBC1C\uD558\uAC8C" }),
3251
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "medium", children: "\uAE30\uBCF8\uAC12" }),
3252
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "low", children: "\uB0AE\uC74C - \uCC28\uBD84\uD558\uACE0 \uC808\uC81C\uC788\uAC8C" })
3253
+ ]
3254
+ }
3255
+ ) }),
3256
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uC774\uBAA8\uC9C0 \uC0AC\uC6A9", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3257
+ "select",
3258
+ {
3259
+ value: personalization.responseStyle.emojiUsage,
3260
+ onChange: (e) => updateResponseStyle("emojiUsage", e.target.value),
3261
+ style: selectStyle,
3262
+ children: [
3263
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "high", children: "\uB192\uC74C - \uC790\uC8FC \uC0AC\uC6A9" }),
3264
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "medium", children: "\uAE30\uBCF8\uAC12" }),
3265
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "low", children: "\uB0AE\uC74C - \uAC70\uC758 \uC0AC\uC6A9 \uC548 \uD568" })
3266
+ ]
3267
+ }
3268
+ ) }),
3269
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uC751\uB2F5 \uAE38\uC774", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3270
+ "select",
3271
+ {
3272
+ value: personalization.responseStyle.verbosity,
3273
+ onChange: (e) => updateResponseStyle("verbosity", e.target.value),
3274
+ style: selectStyle,
3275
+ children: [
3276
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "detailed", children: "\uC0C1\uC138 - \uC790\uC138\uD558\uAC8C \uC124\uBA85" }),
3277
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "balanced", children: "\uAE30\uBCF8\uAC12" }),
3278
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("option", { value: "concise", children: "\uAC04\uACB0 - \uD575\uC2EC\uB9CC \uC694\uC57D" })
3279
+ ]
3280
+ }
3281
+ ) })
3282
+ ] })
3283
+ ] }),
3284
+ activeTab === "data" && /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3285
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("h2", { style: { fontSize: "20px", fontWeight: 600, marginBottom: "24px", color: "var(--chatllm-text, #1f2937)" }, children: "\uB370\uC774\uD130 \uC81C\uC5B4" }),
3286
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uBA54\uBAA8\uB9AC \uC0AC\uC6A9", description: "\uB300\uD654 \uCEE8\uD14D\uC2A4\uD2B8\uB97C \uAE30\uC5B5\uD569\uB2C8\uB2E4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3287
+ "button",
3288
+ {
3289
+ onClick: () => onPersonalizationChange({ ...personalization, useMemory: !personalization.useMemory }),
3290
+ style: {
3291
+ width: "48px",
3292
+ height: "28px",
3293
+ borderRadius: "14px",
3294
+ backgroundColor: personalization.useMemory ? "var(--chatllm-primary, #3b82f6)" : "var(--chatllm-text-muted, #d1d5db)",
3295
+ border: "none",
3296
+ cursor: "pointer",
3297
+ position: "relative",
3298
+ transition: "background-color 0.2s"
3299
+ },
3300
+ children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3301
+ "div",
3302
+ {
3303
+ style: {
3304
+ width: "22px",
3305
+ height: "22px",
3306
+ borderRadius: "50%",
3307
+ backgroundColor: "#ffffff",
3308
+ boxShadow: "0 2px 4px rgba(0, 0, 0, 0.1)",
3309
+ position: "absolute",
3310
+ top: "3px",
3311
+ left: personalization.useMemory ? "23px" : "3px",
3312
+ transition: "left 0.2s"
3313
+ }
3314
+ }
3315
+ )
3316
+ }
3317
+ ) }),
3318
+ onClearAllData && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(SettingRow, { label: "\uB300\uD654 \uAE30\uB85D \uC0AD\uC81C", description: "\uBAA8\uB4E0 \uB300\uD654 \uAE30\uB85D\uC744 \uC0AD\uC81C\uD569\uB2C8\uB2E4", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
3319
+ "button",
3320
+ {
3321
+ onClick: () => {
3322
+ if (window.confirm("\uBAA8\uB4E0 \uB300\uD654 \uAE30\uB85D\uC744 \uC0AD\uC81C\uD558\uC2DC\uACA0\uC2B5\uB2C8\uAE4C?")) {
3323
+ onClearAllData();
3324
+ }
3325
+ },
3326
+ style: buttonDangerStyle,
3327
+ children: "\uC0AD\uC81C"
3328
+ }
3329
+ ) })
3330
+ ] })
3331
+ ] })
3332
+ ]
3333
+ }
3334
+ )
3335
+ }
3336
+ );
3337
+ };
3338
+ var TabButton = ({ active, onClick, icon, label }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3339
+ "button",
3340
+ {
3341
+ onClick,
3342
+ style: {
3343
+ width: "100%",
3344
+ display: "flex",
3345
+ alignItems: "center",
3346
+ gap: "12px",
3347
+ padding: "10px 12px",
3348
+ borderRadius: "10px",
3349
+ border: "none",
3350
+ backgroundColor: active ? "var(--chatllm-bg, #ffffff)" : "transparent",
3351
+ boxShadow: active ? "0 1px 3px rgba(0, 0, 0, 0.08)" : "none",
3352
+ color: active ? "var(--chatllm-primary, #3b82f6)" : "var(--chatllm-text-muted, #6b7280)",
3353
+ fontSize: "14px",
3354
+ cursor: "pointer",
3355
+ textAlign: "left",
3356
+ marginBottom: "4px"
3357
+ },
3358
+ children: [
3359
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(IconSvg, { name: icon, size: 20 }),
3360
+ label
3361
+ ]
3362
+ }
3363
+ );
3364
+ var SettingRow = ({ label, description, children }) => /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)(
3365
+ "div",
3366
+ {
3367
+ style: {
3368
+ display: "flex",
3369
+ alignItems: "center",
3370
+ justifyContent: "space-between",
3371
+ padding: "12px 0",
3372
+ borderBottom: "1px solid var(--chatllm-border-light, #f3f4f6)"
3373
+ },
3374
+ children: [
3375
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { children: [
3376
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("span", { style: { fontSize: "14px", color: "var(--chatllm-text, #374151)" }, children: label }),
3377
+ description && /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { style: { fontSize: "12px", color: "var(--chatllm-text-muted, #9ca3af)", marginTop: "2px" }, children: description })
3378
+ ] }),
3379
+ children
3380
+ ]
3381
+ }
3382
+ );
3383
+ var selectStyle = {
3384
+ padding: "8px 12px",
3385
+ backgroundColor: "var(--chatllm-bg-secondary, #f9fafb)",
3386
+ border: "1px solid var(--chatllm-border, #e5e7eb)",
3387
+ borderRadius: "8px",
3388
+ fontSize: "14px",
3389
+ color: "var(--chatllm-text, #374151)",
3390
+ minWidth: "200px",
3391
+ cursor: "pointer"
3392
+ };
3393
+ var inputStyle = {
3394
+ width: "100%",
3395
+ padding: "10px 12px",
3396
+ backgroundColor: "var(--chatllm-bg-secondary, #f9fafb)",
3397
+ border: "1px solid var(--chatllm-border, #e5e7eb)",
3398
+ borderRadius: "8px",
3399
+ fontSize: "14px",
3400
+ color: "var(--chatllm-text, #374151)"
3401
+ };
3402
+ var labelStyle = {
3403
+ display: "block",
3404
+ fontSize: "12px",
3405
+ color: "var(--chatllm-text-muted, #6b7280)",
3406
+ marginBottom: "6px"
3407
+ };
3408
+ var buttonSecondaryStyle = {
3409
+ padding: "8px 16px",
3410
+ backgroundColor: "var(--chatllm-bg-secondary, #f3f4f6)",
3411
+ border: "none",
3412
+ borderRadius: "8px",
3413
+ fontSize: "14px",
3414
+ color: "var(--chatllm-text, #374151)",
3415
+ cursor: "pointer"
3416
+ };
3417
+ var buttonDangerStyle = {
3418
+ padding: "8px 16px",
3419
+ backgroundColor: "var(--chatllm-danger-bg, #fef2f2)",
3420
+ border: "none",
3421
+ borderRadius: "8px",
3422
+ fontSize: "14px",
3423
+ color: "var(--chatllm-danger, #dc2626)",
3424
+ cursor: "pointer"
3425
+ };
3426
+
2418
3427
  // src/react/ChatUI.tsx
2419
- var import_jsx_runtime9 = require("react/jsx-runtime");
3428
+ var import_jsx_runtime12 = require("react/jsx-runtime");
2420
3429
  var DEFAULT_ACTIONS = [
2421
3430
  {
2422
3431
  id: "webSearch",
@@ -2571,6 +3580,7 @@ var ChatUI = ({
2571
3580
  templates = DEFAULT_TEMPLATES,
2572
3581
  personalization,
2573
3582
  apiKey,
3583
+ onApiKeyChange,
2574
3584
  apiEndpoint = "/api/chat",
2575
3585
  theme,
2576
3586
  showSidebar = true,
@@ -2585,7 +3595,7 @@ var ChatUI = ({
2585
3595
  onSessionChange,
2586
3596
  onError
2587
3597
  }) => {
2588
- import_react7.default.useEffect(() => {
3598
+ import_react10.default.useEffect(() => {
2589
3599
  injectStyles();
2590
3600
  }, []);
2591
3601
  const hookOptions = {
@@ -2646,8 +3656,8 @@ var ChatUI = ({
2646
3656
  const handleSubmit = () => {
2647
3657
  sendMessage();
2648
3658
  };
2649
- const [memoryPanelOpen, setMemoryPanelOpen] = (0, import_react7.useState)(false);
2650
- const memoryItems = import_react7.default.useMemo(() => {
3659
+ const [memoryPanelOpen, setMemoryPanelOpen] = (0, import_react10.useState)(false);
3660
+ const memoryItems = import_react10.default.useMemo(() => {
2651
3661
  const items = [];
2652
3662
  if (currentSession?.contextSummary) {
2653
3663
  items.push({
@@ -2688,7 +3698,7 @@ var ChatUI = ({
2688
3698
  return items;
2689
3699
  }, [currentSession, currentPersonalization]);
2690
3700
  const themeClass = theme?.mode === "dark" ? "chatllm-dark" : "";
2691
- return /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3701
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2692
3702
  "div",
2693
3703
  {
2694
3704
  className: `chatllm-root ${themeClass} ${className}`,
@@ -2699,7 +3709,7 @@ var ChatUI = ({
2699
3709
  fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif'
2700
3710
  },
2701
3711
  children: [
2702
- showSidebar && /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3712
+ showSidebar && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2703
3713
  ChatSidebar,
2704
3714
  {
2705
3715
  sessions,
@@ -2711,7 +3721,7 @@ var ChatUI = ({
2711
3721
  onToggle: toggleSidebar
2712
3722
  }
2713
3723
  ),
2714
- /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)(
3724
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2715
3725
  "main",
2716
3726
  {
2717
3727
  style: {
@@ -2722,7 +3732,7 @@ var ChatUI = ({
2722
3732
  minWidth: 0
2723
3733
  },
2724
3734
  children: [
2725
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3735
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2726
3736
  ChatHeader,
2727
3737
  {
2728
3738
  title: currentSession?.title || "\uC0C8 \uB300\uD654",
@@ -2734,7 +3744,7 @@ var ChatUI = ({
2734
3744
  sidebarOpen
2735
3745
  }
2736
3746
  ),
2737
- messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3747
+ messages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2738
3748
  EmptyState,
2739
3749
  {
2740
3750
  greeting,
@@ -2743,7 +3753,7 @@ var ChatUI = ({
2743
3753
  actions,
2744
3754
  onActionSelect: handleActionSelect
2745
3755
  }
2746
- ) : /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3756
+ ) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2747
3757
  MessageList,
2748
3758
  {
2749
3759
  messages,
@@ -2756,7 +3766,7 @@ var ChatUI = ({
2756
3766
  editingId: editingMessageId
2757
3767
  }
2758
3768
  ),
2759
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3769
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2760
3770
  ChatInput,
2761
3771
  {
2762
3772
  value: input,
@@ -2776,7 +3786,7 @@ var ChatUI = ({
2776
3786
  ]
2777
3787
  }
2778
3788
  ),
2779
- /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
3789
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2780
3790
  MemoryPanel,
2781
3791
  {
2782
3792
  items: memoryItems,
@@ -2784,6 +3794,22 @@ var ChatUI = ({
2784
3794
  isOpen: memoryPanelOpen,
2785
3795
  onToggle: () => setMemoryPanelOpen(!memoryPanelOpen)
2786
3796
  }
3797
+ ),
3798
+ showSettings && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
3799
+ SettingsModal,
3800
+ {
3801
+ isOpen: settingsOpen,
3802
+ onClose: closeSettings,
3803
+ personalization: currentPersonalization,
3804
+ onPersonalizationChange: updatePersonalization,
3805
+ apiKey,
3806
+ onApiKeyChange,
3807
+ onClearAllData: () => {
3808
+ sessions.forEach((s) => deleteSession(s.id));
3809
+ },
3810
+ apiKeyLabel: "API Key",
3811
+ apiKeyDescription: "Cloud \uBAA8\uB378 \uC0AC\uC6A9\uC5D0 \uD544\uC694\uD569\uB2C8\uB2E4"
3812
+ }
2787
3813
  )
2788
3814
  ]
2789
3815
  }
@@ -2798,9 +3824,12 @@ var ChatUI = ({
2798
3824
  EmptyState,
2799
3825
  Icon,
2800
3826
  IconSvg,
3827
+ LinkChip,
3828
+ MarkdownRenderer,
2801
3829
  MemoryPanel,
2802
3830
  MessageBubble,
2803
3831
  MessageList,
3832
+ SettingsModal,
2804
3833
  useChatUI
2805
3834
  });
2806
3835
  //# sourceMappingURL=index.js.map