@akropolys/kiku 1.6.7 → 1.6.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -89,7 +89,7 @@ function SearchBar({
89
89
  }, []);
90
90
  const handleSelect = (r) => {
91
91
  if (query.trim()) {
92
- client.api.searchVector(query, 1).catch(() => {
92
+ client.api.searchVector(query, 1, void 0, true).catch(() => {
93
93
  });
94
94
  }
95
95
  ignoreNextQueryChange.current = true;
@@ -99,7 +99,7 @@ function SearchBar({
99
99
  };
100
100
  const handleCommitSearch = () => {
101
101
  if (!query.trim()) return;
102
- client.api.searchVector(query, 1).catch(() => {
102
+ client.api.searchVector(query, 1, void 0, true).catch(() => {
103
103
  });
104
104
  if (results.length > 0) {
105
105
  handleSelect(results[0]);
@@ -1189,6 +1189,7 @@ var ArrowUpIcon2 = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", {
1189
1189
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "m5 12 7-7 7 7" }),
1190
1190
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 19V5" })
1191
1191
  ] });
1192
+ var StopIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "currentColor", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("rect", { x: "5", y: "5", width: "14", height: "14", rx: "2" }) });
1192
1193
  var CloseIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2.5", strokeLinecap: "round", strokeLinejoin: "round", children: [
1193
1194
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "18", y1: "6", x2: "6", y2: "18" }),
1194
1195
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("line", { x1: "6", y1: "6", x2: "18", y2: "18" })
@@ -1199,7 +1200,6 @@ var HistoryIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { w
1199
1200
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3 3v5h5" }),
1200
1201
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 7v5l4 2" })
1201
1202
  ] });
1202
- var NewChatIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "14", height: "14", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M12 5v14M5 12h14" }) });
1203
1203
  var BookmarkIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M19 21 12 16l-7 5V5a2 2 0 0 1 2-2h10a2 2 0 0 1 2 2z" }) });
1204
1204
  var TrashIcon = () => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1205
1205
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("path", { d: "M3 6h18" }),
@@ -1225,8 +1225,6 @@ var DEFAULT_CHIPS = [
1225
1225
  "Noise-cancelling headphones",
1226
1226
  "Best laptop for students"
1227
1227
  ];
1228
- var SESSIONS_KEY = "akropolys_chat_sessions";
1229
- var MAX_SESSIONS = 20;
1230
1228
  function parseAtKiku(raw) {
1231
1229
  const trimmed = raw.trim();
1232
1230
  if (!/^@kiku\b/i.test(trimmed)) return null;
@@ -1379,33 +1377,7 @@ function AtPickerMenu({ onSelect, onDismiss }) {
1379
1377
  }
1380
1378
  );
1381
1379
  }
1382
- function loadSessions() {
1383
- try {
1384
- if (typeof window === "undefined") return [];
1385
- const raw = localStorage.getItem(SESSIONS_KEY);
1386
- return raw ? JSON.parse(raw) : [];
1387
- } catch {
1388
- return [];
1389
- }
1390
- }
1391
- function saveSessions(sessions) {
1392
- try {
1393
- if (typeof window === "undefined") return;
1394
- localStorage.setItem(SESSIONS_KEY, JSON.stringify(sessions.slice(0, MAX_SESSIONS)));
1395
- } catch {
1396
- }
1397
- }
1398
- function relativeTime(ts) {
1399
- const diff = Date.now() - ts;
1400
- const mins = Math.floor(diff / 6e4);
1401
- if (mins < 1) return "just now";
1402
- if (mins < 60) return `${mins}m ago`;
1403
- const hrs = Math.floor(mins / 60);
1404
- if (hrs < 24) return `${hrs}h ago`;
1405
- const days = Math.floor(hrs / 24);
1406
- return `${days}d ago`;
1407
- }
1408
- function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedIds = [] }) {
1380
+ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, onImageClick, referencedIds = [] }) {
1409
1381
  const client = (0, import_sdk6.useAkropolysContext)();
1410
1382
  const isProperty = client?.vertical === "property";
1411
1383
  const railRef = (0, import_react5.useRef)(null);
@@ -1444,7 +1416,18 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedI
1444
1416
  onClick: () => onSelectSource?.(src),
1445
1417
  children: [
1446
1418
  src.image ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-src-imgwrap", style: { position: "relative" }, children: [
1447
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: src.image, alt: src.name, loading: "lazy" }),
1419
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
1420
+ "img",
1421
+ {
1422
+ src: src.image,
1423
+ alt: src.name,
1424
+ loading: "lazy",
1425
+ onClick: onImageClick ? (e) => {
1426
+ e.stopPropagation();
1427
+ onImageClick(src.image);
1428
+ } : void 0
1429
+ }
1430
+ ),
1448
1431
  isReferenced && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, { size: 10 }) }),
1449
1432
  isProperty && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: {
1450
1433
  position: "absolute",
@@ -1717,7 +1700,7 @@ function ChatModal({
1717
1700
  visionCategoryHint
1718
1701
  }) {
1719
1702
  const client = (0, import_sdk6.useAkropolysContext)();
1720
- const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset, referencedIds } = (0, import_sdk5.useKiku)();
1703
+ const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, stop, reset, referencedIds } = (0, import_sdk5.useKiku)();
1721
1704
  const [input, setInput] = (0, import_react5.useState)("");
1722
1705
  const [attachments, setAttachments] = (0, import_react5.useState)([]);
1723
1706
  const imageInputRef = (0, import_react5.useRef)(null);
@@ -1792,6 +1775,7 @@ function ChatModal({
1792
1775
  const activeTitle = title === "Shopping Assistant" && isProperty ? "Property Assistant" : title;
1793
1776
  const activePlaceholder = placeholder === "Ask me anything \u2014 gifts, budget, use case\u2026" && isProperty ? "Ask me anything \u2014 location, budget, bedrooms\u2026" : placeholder;
1794
1777
  const [selectedProduct, setSelectedProduct] = (0, import_react5.useState)(null);
1778
+ const [lightboxSrc, setLightboxSrc] = (0, import_react5.useState)(null);
1795
1779
  const bottomRef = (0, import_react5.useRef)(null);
1796
1780
  const textareaRef = (0, import_react5.useRef)(null);
1797
1781
  const [keyInput, setKeyInput] = (0, import_react5.useState)("");
@@ -1801,9 +1785,6 @@ function ChatModal({
1801
1785
  const [minting, setMinting] = (0, import_react5.useState)(false);
1802
1786
  const [showKikuPicker, setShowKikuPicker] = (0, import_react5.useState)(false);
1803
1787
  const [showAtPicker, setShowAtPicker] = (0, import_react5.useState)(false);
1804
- const [sessions, setSessions] = (0, import_react5.useState)(() => loadSessions());
1805
- const [sidebarOpen, setSidebarOpen] = (0, import_react5.useState)(false);
1806
- const [replayMessages, setReplayMessages] = (0, import_react5.useState)(null);
1807
1788
  (0, import_react5.useEffect)(() => {
1808
1789
  if (!lastAction) return;
1809
1790
  if (lastAction.type === "request_kiku_key") {
@@ -1860,9 +1841,15 @@ function ChatModal({
1860
1841
  }
1861
1842
  };
1862
1843
  const msgsContainerRef = (0, import_react5.useRef)(null);
1844
+ const messageRefs = (0, import_react5.useRef)([]);
1863
1845
  (0, import_react5.useEffect)(() => {
1864
1846
  const container = msgsContainerRef.current;
1865
1847
  if (!container) return;
1848
+ const lastMsg = messages[messages.length - 1];
1849
+ if (lastMsg?.role === "user") {
1850
+ messageRefs.current[messages.length - 1]?.scrollIntoView({ behavior: "smooth", block: "start" });
1851
+ return;
1852
+ }
1866
1853
  const distanceFromBottom = container.scrollHeight - container.scrollTop - container.clientHeight;
1867
1854
  if (distanceFromBottom < 120) {
1868
1855
  bottomRef.current?.scrollIntoView({ behavior: "smooth" });
@@ -1870,30 +1857,20 @@ function ChatModal({
1870
1857
  }, [messages, loading, selectedProduct]);
1871
1858
  (0, import_react5.useEffect)(() => {
1872
1859
  const h = (e) => {
1873
- if (e.key === "Escape") onClose();
1860
+ if (e.key !== "Escape") return;
1861
+ if (lightboxSrc) {
1862
+ setLightboxSrc(null);
1863
+ return;
1864
+ }
1865
+ onClose();
1874
1866
  };
1875
1867
  document.addEventListener("keydown", h);
1876
1868
  return () => document.removeEventListener("keydown", h);
1877
- }, []);
1878
- const saveCurrentSession = (0, import_react5.useCallback)(() => {
1879
- if (messages.length < 2) return;
1880
- const firstUser = messages.find((m) => m.role === "user");
1881
- const session = {
1882
- id: `session_${Date.now()}`,
1883
- title: firstUser ? firstUser.content.slice(0, 60) : "Chat session",
1884
- messages,
1885
- ts: Date.now()
1886
- };
1887
- const updated = [session, ...sessions].slice(0, MAX_SESSIONS);
1888
- setSessions(updated);
1889
- saveSessions(updated);
1890
- }, [messages, sessions]);
1869
+ }, [lightboxSrc, onClose]);
1891
1870
  const handleReset = (0, import_react5.useCallback)(() => {
1892
- saveCurrentSession();
1893
1871
  reset();
1894
- setReplayMessages(null);
1895
1872
  setKeyPhase("idle");
1896
- }, [reset, saveCurrentSession]);
1873
+ }, [reset]);
1897
1874
  const handleSourceClick = (src) => {
1898
1875
  setSelectedProduct(src);
1899
1876
  onSelectSource?.(src);
@@ -1906,7 +1883,6 @@ function ChatModal({
1906
1883
  const kiku = parseAtKiku(raw);
1907
1884
  const q = kiku ? kiku.cleanQuery : raw;
1908
1885
  const resolvedForcedIntent = forcedIntent ?? kiku?.intent;
1909
- setReplayMessages(null);
1910
1886
  setSelectedProduct(null);
1911
1887
  setShowKikuPicker(false);
1912
1888
  setShowAtPicker(false);
@@ -1931,7 +1907,6 @@ function ChatModal({
1931
1907
  const display = `@kiku capture${name ? " " + name : ""}`;
1932
1908
  const q = name || "capture current page";
1933
1909
  setInput("");
1934
- setReplayMessages(null);
1935
1910
  setSelectedProduct(null);
1936
1911
  const toSend = attachments;
1937
1912
  setAttachments([]);
@@ -1948,7 +1923,6 @@ function ChatModal({
1948
1923
  const names = products.map((p) => p.name).filter(Boolean).join(", ");
1949
1924
  const display = `@kiku capture all (${products.length} items)`;
1950
1925
  setInput("");
1951
- setReplayMessages(null);
1952
1926
  setSelectedProduct(null);
1953
1927
  setAttachments([]);
1954
1928
  send(names || "capture all", display, void 0, "capture_all", targets);
@@ -1956,7 +1930,6 @@ function ChatModal({
1956
1930
  const handleKikuViewHistory = (0, import_react5.useCallback)(() => {
1957
1931
  const display = "@kiku what have you saved?";
1958
1932
  setInput("");
1959
- setReplayMessages(null);
1960
1933
  setSelectedProduct(null);
1961
1934
  setAttachments([]);
1962
1935
  send("show my saved items", display, void 0, "view_history");
@@ -1964,7 +1937,6 @@ function ChatModal({
1964
1937
  const handleKikuDelete = (0, import_react5.useCallback)(() => {
1965
1938
  const display = "@kiku delete this";
1966
1939
  setInput("");
1967
- setReplayMessages(null);
1968
1940
  setSelectedProduct(null);
1969
1941
  setAttachments([]);
1970
1942
  send("delete this", display, void 0, "delete");
@@ -2010,17 +1982,7 @@ function ChatModal({
2010
1982
  return () => clearTimeout(timer);
2011
1983
  }, [voiceState]);
2012
1984
  const blurVal = typeof backdropBlur === "number" ? `${backdropBlur}px` : backdropBlur ?? "20px";
2013
- const displayMessages = replayMessages ?? messages;
2014
- const loadSession = (session) => {
2015
- setReplayMessages(session.messages);
2016
- setSidebarOpen(false);
2017
- };
2018
- const deleteSession = (id, e) => {
2019
- e.stopPropagation();
2020
- const updated = sessions.filter((s) => s.id !== id);
2021
- setSessions(updated);
2022
- saveSessions(updated);
2023
- };
1985
+ const displayMessages = messages;
2024
1986
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2025
1987
  "div",
2026
1988
  {
@@ -2033,326 +1995,298 @@ function ChatModal({
2033
1995
  ...backdropColor ? { background: backdropColor } : {},
2034
1996
  ...customStyles
2035
1997
  },
2036
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("hsk-cb-panel hsk-cb-panel--with-sidebar", classNames.panel), onClick: (e) => e.stopPropagation(), children: [
2037
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: cn("hsk-cb-sidebar", sidebarOpen && "hsk-cb-sidebar--open"), children: [
2038
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-sidebar-header", children: [
2039
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-sidebar-title", children: "History" }),
2040
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2041
- "button",
2042
- {
2043
- className: "hsk-cb-sidebar-new",
2044
- onClick: handleReset,
2045
- title: "New chat",
2046
- children: [
2047
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(NewChatIcon, {}),
2048
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "New chat" })
2049
- ]
2050
- }
2051
- )
2052
- ] }),
2053
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sidebar-list", children: sessions.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-sidebar-empty", children: [
2054
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryIcon, {}),
2055
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "No history yet" })
2056
- ] }) : sessions.map((session) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2057
- "div",
2058
- {
2059
- className: cn(
2060
- "hsk-cb-sidebar-session",
2061
- replayMessages === session.messages && "hsk-cb-sidebar-session--active"
2062
- ),
2063
- onClick: () => loadSession(session),
2064
- children: [
2065
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sidebar-session-title", children: session.title }),
2066
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sidebar-session-meta", children: relativeTime(session.ts) }),
2067
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2068
- "button",
2069
- {
2070
- className: "hsk-cb-sidebar-session-del",
2071
- onClick: (e) => deleteSession(session.id, e),
2072
- title: "Delete",
2073
- children: "\xD7"
2074
- }
2075
- )
2076
- ]
2077
- },
2078
- session.id
2079
- )) })
2080
- ] }),
2081
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-main", children: [
2082
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar", children: [
2083
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar-left", children: [
2084
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2085
- "button",
2086
- {
2087
- className: cn("hsk-cb-sidebar-toggle", sidebarOpen && "hsk-cb-sidebar-toggle--active"),
2088
- onClick: (e) => {
2089
- e.stopPropagation();
2090
- setSidebarOpen((v) => !v);
2091
- },
2092
- "aria-label": "Toggle history",
2093
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryIcon, {})
2094
- }
2095
- ),
2096
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-topbar-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2097
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-topbar-title", children: activeTitle }) })
1998
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1999
+ "div",
2000
+ {
2001
+ className: cn("hsk-cb-panel", classNames.panel),
2002
+ onClick: (e) => {
2003
+ e.stopPropagation();
2004
+ const target = e.target;
2005
+ if (target.tagName === "IMG" && (target.classList.contains("hsk-markdown-img") || target.classList.contains("hsk-cb-user-img-thumb"))) {
2006
+ const src = target.src;
2007
+ if (src) setLightboxSrc(src);
2008
+ }
2009
+ },
2010
+ children: [
2011
+ lightboxSrc && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-lightbox", onClick: () => setLightboxSrc(null), children: [
2012
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-lightbox-close", onClick: () => setLightboxSrc(null), "aria-label": "Close image", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) }),
2013
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: lightboxSrc, alt: "", className: "hsk-lightbox-img", onClick: (e) => e.stopPropagation() })
2098
2014
  ] }),
2099
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar-actions", children: [
2100
- replayMessages ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-topbar-btn", onClick: () => {
2101
- setReplayMessages(null);
2102
- }, children: "\u2190 Live chat" }) : messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-topbar-btn", onClick: handleReset, children: "Clear chat" }),
2103
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) })
2104
- ] })
2105
- ] }),
2106
- replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-replay-banner", children: [
2107
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(HistoryIcon, {}),
2108
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { children: "You're viewing a past conversation." }),
2109
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { onClick: () => setReplayMessages(null), children: "Back to chat \u2192" })
2110
- ] }),
2111
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-msgs", ref: msgsContainerRef, children: [
2112
- displayMessages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-empty", children: [
2113
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2114
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-title", children: "Find exactly what you need" }),
2115
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2116
- "button",
2117
- {
2118
- className: "hsk-cb-chip",
2119
- onClick: () => handleSend(chip),
2120
- children: chip
2121
- },
2122
- chip
2123
- )) })
2124
- ] }) : displayMessages.map((msg, idx) => {
2125
- const isLast = idx === displayMessages.length - 1 && !replayMessages;
2126
- const isUser = msg.role === "user";
2127
- const displayContent = !isUser && isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages ? stripMarkdownTables(msg.content) : msg.content;
2128
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-user-msg", children: [
2129
- msg.images && msg.images.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-user-imgs", children: msg.images.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: img, alt: `attachment ${i + 1}`, className: "hsk-cb-user-img-thumb" }, i)) }),
2130
- msg.content && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-user-bubble", children: [
2131
- /^@kiku\b/i.test(msg.content) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-kiku-badge", children: "@kiku" }),
2132
- msg.content
2015
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-main", children: [
2016
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar", children: [
2017
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar-left", children: [
2018
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-topbar-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2019
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-topbar-title", children: activeTitle }) })
2020
+ ] }),
2021
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-topbar-actions", children: [
2022
+ messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-topbar-btn", onClick: handleReset, children: "Clear chat" }),
2023
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-close", onClick: onClose, "aria-label": "Close", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CloseIcon, {}) })
2133
2024
  ] })
2134
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2135
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2136
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-body", children: [
2137
- (() => {
2138
- const { thinking, content, isComplete } = parseThinking(displayContent);
2139
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2140
- thinking && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThinkingBlock, { text: thinking, isComplete }),
2141
- content && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-text", children: [
2142
- renderMarkdown(content),
2143
- isLast && streaming && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { display: "inline-block", width: "0.5em", height: "1.05em", marginLeft: "2px", verticalAlign: "text-bottom", background: "currentColor", opacity: 0.55, borderRadius: "1px" } })
2144
- ] })
2145
- ] });
2146
- })(),
2147
- isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ComparisonMatrix, { sources, defaultCurrency }),
2148
- isLast && referencedIds.length > 0 && lastIntent !== "compare" && lastAction?.type !== "request_kiku_key" && lastAction?.type !== "capture" && lastAction?.type !== "delete" && lastAction?.type !== "view_history" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2149
- SourcesCarousel,
2150
- {
2151
- sources,
2152
- defaultCurrency,
2153
- onSelectSource: handleSourceClick,
2154
- referencedIds
2155
- }
2156
- ),
2157
- isLast && !loading && lastAction?.url && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-action-pills", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { className: "hsk-action-pill", href: lastAction.url, children: [
2158
- String(lastAction.type || "continue").replace(/_/g, " "),
2159
- " \u2192"
2160
- ] }) }),
2161
- isLast && !loading && !replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2162
- SmartContextPills,
2025
+ ] }),
2026
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-msgs", ref: msgsContainerRef, children: [
2027
+ displayMessages.length === 0 ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-empty", children: [
2028
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2029
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-empty-title", children: "Find exactly what you need" }),
2030
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-chips", children: activeChips.map((chip) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2031
+ "button",
2163
2032
  {
2164
- intent: lastIntent,
2165
- sources: sources.filter((s) => s.id && referencedIds.includes(s.id)),
2166
- onSend: handleSend,
2167
- loading
2168
- }
2169
- )
2170
- ] })
2171
- ] }) }, idx);
2172
- }),
2173
- selectedProduct && loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2174
- "div",
2175
- {
2176
- className: "hsk-cb-selected-product",
2177
- onClick: () => selectedProduct.url && window.open(selectedProduct.url, "_blank"),
2178
- children: [
2179
- selectedProduct.image && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { className: "hsk-cb-selected-img", src: selectedProduct.image, alt: selectedProduct.name }),
2180
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-selected-info", children: [
2181
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-selected-name", children: selectedProduct.name }),
2182
- selectedProduct.price && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-selected-price", children: [
2183
- selectedProduct.currency ?? defaultCurrency,
2184
- " ",
2185
- parseFloat(String(selectedProduct.price ?? "").replace(/[^0-9.]/g, "") || "0").toLocaleString()
2033
+ className: "hsk-cb-chip",
2034
+ onClick: () => handleSend(chip),
2035
+ children: chip
2036
+ },
2037
+ chip
2038
+ )) })
2039
+ ] }) : displayMessages.map((msg, idx) => {
2040
+ const isLast = idx === displayMessages.length - 1;
2041
+ const isUser = msg.role === "user";
2042
+ const displayContent = !isUser && isLast && lastIntent === "compare" && sources.length >= 2 ? stripMarkdownTables(msg.content) : msg.content;
2043
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-msg-group", ref: (el) => {
2044
+ messageRefs.current[idx] = el;
2045
+ }, children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-user-msg", children: [
2046
+ msg.images && msg.images.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-user-imgs", children: msg.images.map((img, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: img, alt: `attachment ${i + 1}`, className: "hsk-cb-user-img-thumb" }, i)) }),
2047
+ msg.content && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-user-bubble", children: [
2048
+ /^@kiku\b/i.test(msg.content) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-kiku-badge", children: "@kiku" }),
2049
+ msg.content
2186
2050
  ] })
2187
- ] })
2188
- ]
2189
- }
2190
- ),
2191
- loading && !streaming && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-typing-row", style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
2192
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center", marginTop: "4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2193
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
2194
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
2051
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2052
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2053
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-body", children: [
2054
+ (() => {
2055
+ const { thinking, content, isComplete } = parseThinking(displayContent);
2056
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
2057
+ thinking && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ThinkingBlock, { text: thinking, isComplete }),
2058
+ content && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-text", children: [
2059
+ renderMarkdown(content),
2060
+ isLast && streaming && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { display: "inline-block", width: "0.5em", height: "1.05em", marginLeft: "2px", verticalAlign: "text-bottom", background: "currentColor", opacity: 0.55, borderRadius: "1px" } })
2061
+ ] })
2062
+ ] });
2063
+ })(),
2064
+ isLast && lastIntent === "compare" && sources.length >= 2 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ComparisonMatrix, { sources, defaultCurrency }),
2065
+ (() => {
2066
+ const msgReferencedIds = isLast ? referencedIds : msg.referencedIds ?? [];
2067
+ const msgSources = isLast ? sources : msg.sources ?? [];
2068
+ const showCarousel = msgReferencedIds.length > 0 && (isLast ? lastIntent !== "compare" : msg.intent !== "compare") && lastAction?.type !== "request_kiku_key" && lastAction?.type !== "capture" && lastAction?.type !== "delete" && lastAction?.type !== "view_history";
2069
+ return showCarousel && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2070
+ SourcesCarousel,
2071
+ {
2072
+ sources: msgSources,
2073
+ defaultCurrency,
2074
+ onSelectSource: handleSourceClick,
2075
+ onImageClick: setLightboxSrc,
2076
+ referencedIds: msgReferencedIds
2077
+ }
2078
+ );
2079
+ })(),
2080
+ isLast && !loading && lastAction?.url && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-action-pills", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("a", { className: "hsk-action-pill", href: lastAction.url, children: [
2081
+ String(lastAction.type || "continue").replace(/_/g, " "),
2082
+ " \u2192"
2083
+ ] }) }),
2084
+ isLast && !loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2085
+ SmartContextPills,
2086
+ {
2087
+ intent: lastIntent,
2088
+ sources: sources.filter((s) => s.id && referencedIds.includes(s.id)),
2089
+ onSend: handleSend,
2090
+ loading
2091
+ }
2092
+ )
2093
+ ] })
2094
+ ] }) }, idx);
2095
+ }),
2096
+ selectedProduct && loading && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2097
+ "div",
2098
+ {
2099
+ className: "hsk-cb-selected-product",
2100
+ onClick: () => selectedProduct.url && window.open(selectedProduct.url, "_blank"),
2101
+ children: [
2102
+ selectedProduct.image && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { className: "hsk-cb-selected-img", src: selectedProduct.image, alt: selectedProduct.name }),
2103
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-selected-info", children: [
2104
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-selected-name", children: selectedProduct.name }),
2105
+ selectedProduct.price && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-selected-price", children: [
2106
+ selectedProduct.currency ?? defaultCurrency,
2107
+ " ",
2108
+ parseFloat(String(selectedProduct.price ?? "").replace(/[^0-9.]/g, "") || "0").toLocaleString()
2109
+ ] })
2110
+ ] })
2111
+ ]
2112
+ }
2113
+ ),
2114
+ loading && !streaming && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-typing-row", style: { display: "flex", alignItems: "flex-start", gap: "10px" }, children: [
2115
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center", marginTop: "4px" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2116
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", flexDirection: "column", gap: "6px" }, children: [
2117
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("style", { children: `
2195
2118
  @keyframes hsk-pulse {
2196
2119
  0%, 100% { opacity: 0.6; }
2197
2120
  50% { opacity: 1; }
2198
2121
  }
2199
2122
  ` }),
2200
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: "0.85rem", color: "#6b7280", fontStyle: "italic", animation: "hsk-pulse 1.5s infinite ease-in-out" }, children: "Thinking\u2026" }),
2201
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-typing", style: { margin: 0, alignSelf: "flex-start" }, children: [
2202
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" }),
2203
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" }),
2204
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" })
2205
- ] })
2206
- ] })
2207
- ] }),
2208
- error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError(error) }),
2209
- !replayMessages && keyPhase === "prompt_key" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2210
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2211
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-phone-form", children: [
2212
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "hsk-cb-phone-label", children: "Paste your kiku key \u2014 or create one" }),
2213
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2214
- "input",
2123
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: "0.85rem", color: "#6b7280", fontStyle: "italic", animation: "hsk-pulse 1.5s infinite ease-in-out" }, children: "Thinking\u2026" }),
2124
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-typing", style: { margin: 0, alignSelf: "flex-start" }, children: [
2125
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" }),
2126
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" }),
2127
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-dot" })
2128
+ ] })
2129
+ ] })
2130
+ ] }),
2131
+ error && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-error", children: getFriendlyError(error) }),
2132
+ keyPhase === "prompt_key" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2133
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2134
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-phone-form", children: [
2135
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "hsk-cb-phone-label", children: "Paste your kiku key \u2014 or create one" }),
2136
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2137
+ "input",
2138
+ {
2139
+ type: "text",
2140
+ className: "hsk-cb-phone-input",
2141
+ placeholder: "kiku_\u2026",
2142
+ value: keyInput,
2143
+ onChange: (e) => setKeyInput(e.target.value),
2144
+ onKeyDown: (e) => e.key === "Enter" && handleUseExistingKey(),
2145
+ autoFocus: true
2146
+ }
2147
+ ),
2148
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
2149
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleUseExistingKey, disabled: !keyInput.trim(), children: "Use my key" }),
2150
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleCreateKey, disabled: minting, children: minting ? "Creating\u2026" : "I'm new \u2014 create my key" })
2151
+ ] })
2152
+ ] }) }) })
2153
+ ] }),
2154
+ mintedKey && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2155
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2156
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "10px 12px", border: "1px solid var(--hsk-border, #e5e5e5)", borderRadius: 8 }, children: [
2157
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "\u{1F511} Your kiku key \u2014 shown only once" }),
2158
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: mintedKey }),
2159
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2160
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2161
+ try {
2162
+ navigator.clipboard?.writeText(mintedKey);
2163
+ } catch {
2164
+ }
2165
+ }, children: "Copy" }),
2166
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { fontSize: 11, opacity: 0.7 }, children: [
2167
+ "Disappears in ",
2168
+ keyCountdown,
2169
+ "s. Save it like a password \u2014 if lost, the memory it opens is lost with it."
2170
+ ] })
2171
+ ] })
2172
+ ] }) }) })
2173
+ ] }),
2174
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: bottomRef, style: { height: 1 } })
2175
+ ] }),
2176
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-input-wrap", children: [
2177
+ showAtPicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2178
+ AtPickerMenu,
2215
2179
  {
2216
- type: "text",
2217
- className: "hsk-cb-phone-input",
2218
- placeholder: "kiku_\u2026",
2219
- value: keyInput,
2220
- onChange: (e) => setKeyInput(e.target.value),
2221
- onKeyDown: (e) => e.key === "Enter" && handleUseExistingKey(),
2222
- autoFocus: true
2180
+ onSelect: handleSelectExtension,
2181
+ onDismiss: () => setShowAtPicker(false)
2223
2182
  }
2224
2183
  ),
2225
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8 }, children: [
2226
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleUseExistingKey, disabled: !keyInput.trim(), children: "Use my key" }),
2227
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handleCreateKey, disabled: minting, children: minting ? "Creating\u2026" : "I'm new \u2014 create my key" })
2228
- ] })
2229
- ] }) }) })
2230
- ] }),
2231
- !replayMessages && mintedKey && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2232
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(SparkleIcon2, {}) }),
2233
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-body", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-ai-text", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { padding: "10px 12px", border: "1px solid var(--hsk-border, #e5e5e5)", borderRadius: 8 }, children: [
2234
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "\u{1F511} Your kiku key \u2014 shown only once" }),
2235
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: mintedKey }),
2236
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2237
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2238
- try {
2239
- navigator.clipboard?.writeText(mintedKey);
2240
- } catch {
2184
+ showKikuPicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2185
+ KikuPickerMenu,
2186
+ {
2187
+ sources,
2188
+ referencedIds,
2189
+ defaultCurrency,
2190
+ onCapture: handleKikuCapture,
2191
+ onCaptureAll: handleKikuCaptureAll,
2192
+ onViewHistory: handleKikuViewHistory,
2193
+ onDelete: handleKikuDelete,
2194
+ onDismiss: () => setShowKikuPicker(false)
2195
+ }
2196
+ ),
2197
+ attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-img-strip", children: attachments.map((att, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-img-thumb-wrap", children: [
2198
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: att.data, alt: `attachment ${i + 1}`, className: "hsk-cb-img-thumb" }),
2199
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2200
+ "button",
2201
+ {
2202
+ className: "hsk-cb-img-thumb-remove",
2203
+ onClick: () => removeAttachment(i),
2204
+ "aria-label": "Remove image",
2205
+ children: "\xD7"
2206
+ }
2207
+ )
2208
+ ] }, i)) }),
2209
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-input-box", children: [
2210
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2211
+ "input",
2212
+ {
2213
+ ref: imageInputRef,
2214
+ type: "file",
2215
+ accept: "image/*",
2216
+ multiple: true,
2217
+ style: { display: "none" },
2218
+ onChange: (e) => handleImageFiles(e.target.files)
2241
2219
  }
2242
- }, children: "Copy" }),
2243
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { style: { fontSize: 11, opacity: 0.7 }, children: [
2244
- "Disappears in ",
2245
- keyCountdown,
2246
- "s. Save it like a password \u2014 if lost, the memory it opens is lost with it."
2247
- ] })
2248
- ] })
2249
- ] }) }) })
2250
- ] }),
2251
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { ref: bottomRef, style: { height: 1 } })
2252
- ] }),
2253
- !replayMessages && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-input-wrap", children: [
2254
- showAtPicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2255
- AtPickerMenu,
2256
- {
2257
- onSelect: handleSelectExtension,
2258
- onDismiss: () => setShowAtPicker(false)
2259
- }
2260
- ),
2261
- showKikuPicker && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2262
- KikuPickerMenu,
2263
- {
2264
- sources,
2265
- referencedIds,
2266
- defaultCurrency,
2267
- onCapture: handleKikuCapture,
2268
- onCaptureAll: handleKikuCaptureAll,
2269
- onViewHistory: handleKikuViewHistory,
2270
- onDelete: handleKikuDelete,
2271
- onDismiss: () => setShowKikuPicker(false)
2272
- }
2273
- ),
2274
- attachments.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-img-strip", children: attachments.map((att, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-img-thumb-wrap", children: [
2275
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("img", { src: att.data, alt: `attachment ${i + 1}`, className: "hsk-cb-img-thumb" }),
2276
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2277
- "button",
2278
- {
2279
- className: "hsk-cb-img-thumb-remove",
2280
- onClick: () => removeAttachment(i),
2281
- "aria-label": "Remove image",
2282
- children: "\xD7"
2283
- }
2284
- )
2285
- ] }, i)) }),
2286
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-input-box", children: [
2287
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2288
- "input",
2289
- {
2290
- ref: imageInputRef,
2291
- type: "file",
2292
- accept: "image/*",
2293
- multiple: true,
2294
- style: { display: "none" },
2295
- onChange: (e) => handleImageFiles(e.target.files)
2296
- }
2297
- ),
2298
- enableVision && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2299
- "button",
2300
- {
2301
- className: "hsk-cb-attach-btn",
2302
- onClick: () => imageInputRef.current?.click(),
2303
- disabled: loading,
2304
- "aria-label": "Attach image",
2305
- title: "Attach image",
2306
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PaperclipIcon, {})
2307
- }
2308
- ),
2309
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2310
- "textarea",
2311
- {
2312
- ref: textareaRef,
2313
- className: cn("hsk-cb-textarea", classNames.input),
2314
- value: input,
2315
- onChange: handleInput,
2316
- onKeyDown: handleKeyDown,
2317
- placeholder: voiceState === "listening" ? "\u{1F399}\uFE0F Listening\u2026 tap the mic to stop" : voiceState === "processing" ? "Got it \u2014 sending\u2026" : activePlaceholder,
2318
- rows: 1,
2319
- disabled: loading,
2320
- autoFocus: true
2321
- }
2322
- ),
2323
- hasSpeechAPI && enableVoice && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2324
- "button",
2325
- {
2326
- className: cn(
2327
- "hsk-cb-mic-btn",
2328
- voiceState === "listening" && "hsk-cb-mic-btn--listening",
2329
- voiceState === "processing" && "hsk-cb-mic-btn--processing"
2330
2220
  ),
2331
- onClick: voiceState === "idle" ? startVoice : stopVoice,
2332
- disabled: loading,
2333
- "aria-label": voiceState === "idle" ? "Start voice input" : "Stop recording",
2334
- title: voiceState === "idle" ? "Voice input" : "Stop",
2335
- children: [
2336
- voiceState === "listening" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MicOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MicIcon2, {}),
2337
- voiceState === "listening" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-mic-pulse" })
2338
- ]
2339
- }
2340
- ),
2341
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2342
- "button",
2343
- {
2344
- className: cn("hsk-cb-send", classNames.sendButton),
2345
- onClick: () => handleSend(),
2346
- disabled: !input.trim() && attachments.length === 0 || loading,
2347
- "aria-label": "Send message",
2348
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArrowUpIcon2, {})
2349
- }
2350
- )
2351
- ] }),
2352
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-hint", children: "Akropolys AI \xB7 searches the whole catalogue in real time" })
2353
- ] })
2354
- ] })
2355
- ] })
2221
+ enableVision && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2222
+ "button",
2223
+ {
2224
+ className: "hsk-cb-attach-btn",
2225
+ onClick: () => imageInputRef.current?.click(),
2226
+ disabled: loading,
2227
+ "aria-label": "Attach image",
2228
+ title: "Attach image",
2229
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PaperclipIcon, {})
2230
+ }
2231
+ ),
2232
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2233
+ "textarea",
2234
+ {
2235
+ ref: textareaRef,
2236
+ className: cn("hsk-cb-textarea", classNames.input),
2237
+ value: input,
2238
+ onChange: handleInput,
2239
+ onKeyDown: handleKeyDown,
2240
+ placeholder: voiceState === "listening" ? "\u{1F399}\uFE0F Listening\u2026 tap the mic to stop" : voiceState === "processing" ? "Got it \u2014 sending\u2026" : activePlaceholder,
2241
+ rows: 1,
2242
+ disabled: loading,
2243
+ autoFocus: true
2244
+ }
2245
+ ),
2246
+ hasSpeechAPI && enableVoice && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
2247
+ "button",
2248
+ {
2249
+ className: cn(
2250
+ "hsk-cb-mic-btn",
2251
+ voiceState === "listening" && "hsk-cb-mic-btn--listening",
2252
+ voiceState === "processing" && "hsk-cb-mic-btn--processing"
2253
+ ),
2254
+ onClick: voiceState === "idle" ? startVoice : stopVoice,
2255
+ disabled: loading,
2256
+ "aria-label": voiceState === "idle" ? "Start voice input" : "Stop recording",
2257
+ title: voiceState === "idle" ? "Voice input" : "Stop",
2258
+ children: [
2259
+ voiceState === "listening" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MicOffIcon, {}) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MicIcon2, {}),
2260
+ voiceState === "listening" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "hsk-cb-mic-pulse" })
2261
+ ]
2262
+ }
2263
+ ),
2264
+ loading || streaming ? /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2265
+ "button",
2266
+ {
2267
+ className: cn("hsk-cb-send", "hsk-cb-send--stop", classNames.sendButton),
2268
+ onClick: stop,
2269
+ "aria-label": "Stop generating",
2270
+ title: "Stop generating",
2271
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(StopIcon, {})
2272
+ }
2273
+ ) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2274
+ "button",
2275
+ {
2276
+ className: cn("hsk-cb-send", classNames.sendButton),
2277
+ onClick: () => handleSend(),
2278
+ disabled: !input.trim() && attachments.length === 0,
2279
+ "aria-label": "Send message",
2280
+ children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ArrowUpIcon2, {})
2281
+ }
2282
+ )
2283
+ ] }),
2284
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-hint", children: "Akropolys AI \xB7 searches the whole catalogue in real time" })
2285
+ ] })
2286
+ ] })
2287
+ ]
2288
+ }
2289
+ )
2356
2290
  }
2357
2291
  );
2358
2292
  }