@akropolys/kiku 1.6.1 → 1.6.3

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.mjs CHANGED
@@ -1167,6 +1167,25 @@ var ShoppingBagIcon = () => /* @__PURE__ */ jsxs6("svg", { width: "13", height:
1167
1167
  /* @__PURE__ */ jsx7("line", { x1: "3", y1: "6", x2: "21", y2: "6" }),
1168
1168
  /* @__PURE__ */ jsx7("path", { d: "M16 10a4 4 0 0 1-8 0" })
1169
1169
  ] });
1170
+ var SecureShieldIcon = ({ className, size = 18 }) => /* @__PURE__ */ jsxs6(
1171
+ "svg",
1172
+ {
1173
+ className,
1174
+ width: size,
1175
+ height: size,
1176
+ viewBox: "0 0 24 24",
1177
+ fill: "none",
1178
+ stroke: "currentColor",
1179
+ strokeWidth: "2.5",
1180
+ strokeLinecap: "round",
1181
+ strokeLinejoin: "round",
1182
+ children: [
1183
+ /* @__PURE__ */ jsx7("path", { d: "M12 22s8-4 8-10V5l-8-3-8 3v7c0 6 8 10 8 10z" }),
1184
+ /* @__PURE__ */ jsx7("path", { d: "M12 11a2.5 2.5 0 1 0 0-5 2.5 2.5 0 0 0 0 5z" }),
1185
+ /* @__PURE__ */ jsx7("path", { d: "M12 11v4" })
1186
+ ]
1187
+ }
1188
+ );
1170
1189
  var PaperclipIcon = () => /* @__PURE__ */ jsx7("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: /* @__PURE__ */ jsx7("path", { d: "m21.44 11.05-9.19 9.19a6 6 0 0 1-8.49-8.49l8.57-8.57A4 4 0 1 1 18 8.84l-8.59 8.57a2 2 0 0 1-2.83-2.83l8.49-8.48" }) });
1171
1190
  var MicIcon2 = () => /* @__PURE__ */ jsxs6("svg", { width: "16", height: "16", viewBox: "0 0 24 24", fill: "none", stroke: "currentColor", strokeWidth: "2", strokeLinecap: "round", strokeLinejoin: "round", children: [
1172
1191
  /* @__PURE__ */ jsx7("path", { d: "M12 2a3 3 0 0 0-3 3v7a3 3 0 0 0 6 0V5a3 3 0 0 0-3-3z" }),
@@ -1189,6 +1208,173 @@ var DEFAULT_CHIPS = [
1189
1208
  ];
1190
1209
  var SESSIONS_KEY = "akropolys_chat_sessions";
1191
1210
  var MAX_SESSIONS = 20;
1211
+ function parseAtKiku(raw) {
1212
+ const trimmed = raw.trim();
1213
+ if (!/^@kiku\b/i.test(trimmed)) return null;
1214
+ const rest = trimmed.slice(5).trim();
1215
+ if (rest === "" || /^(capture|save)\b/i.test(rest)) {
1216
+ return {
1217
+ intent: "capture",
1218
+ cleanQuery: rest.replace(/^(capture|save)\s*/i, "").trim() || trimmed
1219
+ };
1220
+ }
1221
+ if (/^(history|what have you|show my|my items|what did you|saved|captures|recall)\b/i.test(rest)) {
1222
+ return { intent: "view_history", cleanQuery: "show my saved items" };
1223
+ }
1224
+ if (/^(delete|forget|remove|unsave)\b/i.test(rest)) {
1225
+ return {
1226
+ intent: "delete",
1227
+ cleanQuery: rest.replace(/^(delete|forget|remove|unsave)\s*/i, "").trim() || trimmed
1228
+ };
1229
+ }
1230
+ return { intent: "capture", cleanQuery: rest || trimmed };
1231
+ }
1232
+ function KikuPickerMenu({
1233
+ sources,
1234
+ referencedIds,
1235
+ defaultCurrency,
1236
+ onCapture,
1237
+ onCaptureAll,
1238
+ onViewHistory,
1239
+ onDelete,
1240
+ onDismiss
1241
+ }) {
1242
+ const discussed = sources.filter((s) => s.id && referencedIds.includes(s.id));
1243
+ return /* @__PURE__ */ jsxs6(
1244
+ "div",
1245
+ {
1246
+ className: "hsk-kiku-picker",
1247
+ role: "menu",
1248
+ "aria-label": "@kiku commands",
1249
+ onMouseDown: (e) => e.preventDefault(),
1250
+ children: [
1251
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-kiku-picker-header", children: [
1252
+ /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-at", children: "@kiku" }),
1253
+ /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-hint", children: "What would you like to do?" }),
1254
+ /* @__PURE__ */ jsx7("button", { className: "hsk-kiku-picker-close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx7(CloseIcon, {}) })
1255
+ ] }),
1256
+ discussed.length > 0 && /* @__PURE__ */ jsxs6(Fragment3, { children: [
1257
+ /* @__PURE__ */ jsx7("div", { className: "hsk-kiku-picker-section", children: "Discussed in this chat" }),
1258
+ discussed.map((src, i) => /* @__PURE__ */ jsxs6(
1259
+ "button",
1260
+ {
1261
+ className: "hsk-kiku-picker-item",
1262
+ role: "menuitem",
1263
+ onClick: () => {
1264
+ onCapture(src);
1265
+ onDismiss();
1266
+ },
1267
+ children: [
1268
+ src.image ? /* @__PURE__ */ jsx7("img", { src: src.image, alt: src.name, className: "hsk-kiku-picker-img" }) : /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-img-placeholder", children: /* @__PURE__ */ jsx7(SecureShieldIcon, { size: 14 }) }),
1269
+ /* @__PURE__ */ jsxs6("span", { className: "hsk-kiku-picker-item-body", children: [
1270
+ /* @__PURE__ */ jsxs6("span", { className: "hsk-kiku-picker-item-name", children: [
1271
+ "\u{1F4CC} ",
1272
+ src.name
1273
+ ] }),
1274
+ src.price && /* @__PURE__ */ jsxs6("span", { className: "hsk-kiku-picker-item-price", children: [
1275
+ src.currency ?? defaultCurrency,
1276
+ " ",
1277
+ parseFloat(String(src.price).replace(/[^0-9.]/g, "") || "0").toLocaleString()
1278
+ ] })
1279
+ ] })
1280
+ ]
1281
+ },
1282
+ src.id ?? i
1283
+ )),
1284
+ discussed.length > 1 && /* @__PURE__ */ jsx7(
1285
+ "button",
1286
+ {
1287
+ className: "hsk-kiku-picker-item hsk-kiku-picker-item--all",
1288
+ role: "menuitem",
1289
+ onClick: () => {
1290
+ onCaptureAll(discussed);
1291
+ onDismiss();
1292
+ },
1293
+ children: /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-body", children: /* @__PURE__ */ jsxs6("span", { className: "hsk-kiku-picker-item-name", children: [
1294
+ "\u{1F4CC} Capture all (",
1295
+ discussed.length,
1296
+ " items)"
1297
+ ] }) })
1298
+ }
1299
+ ),
1300
+ /* @__PURE__ */ jsx7("div", { className: "hsk-kiku-picker-divider" })
1301
+ ] }),
1302
+ discussed.length === 0 && /* @__PURE__ */ jsxs6(Fragment3, { children: [
1303
+ /* @__PURE__ */ jsx7(
1304
+ "button",
1305
+ {
1306
+ className: "hsk-kiku-picker-item",
1307
+ role: "menuitem",
1308
+ onClick: () => {
1309
+ onCapture({ name: "current page", id: void 0 });
1310
+ onDismiss();
1311
+ },
1312
+ children: /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-body", children: /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-name", children: "\u{1F4CC} Capture current page" }) })
1313
+ }
1314
+ ),
1315
+ /* @__PURE__ */ jsx7("div", { className: "hsk-kiku-picker-divider" })
1316
+ ] }),
1317
+ /* @__PURE__ */ jsx7(
1318
+ "button",
1319
+ {
1320
+ className: "hsk-kiku-picker-item",
1321
+ role: "menuitem",
1322
+ onClick: () => {
1323
+ onViewHistory();
1324
+ onDismiss();
1325
+ },
1326
+ children: /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-body", children: /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-name", children: "\u{1F4CB} What have you saved?" }) })
1327
+ }
1328
+ ),
1329
+ /* @__PURE__ */ jsx7(
1330
+ "button",
1331
+ {
1332
+ className: "hsk-kiku-picker-item",
1333
+ role: "menuitem",
1334
+ onClick: () => {
1335
+ onDelete();
1336
+ onDismiss();
1337
+ },
1338
+ children: /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-body", children: /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-name", children: "\u{1F5D1}\uFE0F Delete this" }) })
1339
+ }
1340
+ )
1341
+ ]
1342
+ }
1343
+ );
1344
+ }
1345
+ function AtPickerMenu({ onSelect, onDismiss }) {
1346
+ return /* @__PURE__ */ jsxs6(
1347
+ "div",
1348
+ {
1349
+ className: "hsk-kiku-picker",
1350
+ role: "menu",
1351
+ "aria-label": "Extensions",
1352
+ onMouseDown: (e) => e.preventDefault(),
1353
+ children: [
1354
+ /* @__PURE__ */ jsxs6("div", { className: "hsk-kiku-picker-header", children: [
1355
+ /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-at", children: "@" }),
1356
+ /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-hint", children: "Use an extension" }),
1357
+ /* @__PURE__ */ jsx7("button", { className: "hsk-kiku-picker-close", onClick: onDismiss, "aria-label": "Close", children: /* @__PURE__ */ jsx7(CloseIcon, {}) })
1358
+ ] }),
1359
+ /* @__PURE__ */ jsxs6(
1360
+ "button",
1361
+ {
1362
+ className: "hsk-kiku-picker-item",
1363
+ role: "menuitem",
1364
+ onClick: () => onSelect("@kiku"),
1365
+ children: [
1366
+ /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-img-placeholder", style: { background: "color-mix(in srgb, var(--hsk-primary, #7c5cfc) 15%, transparent)", color: "var(--hsk-primary, #7c5cfc)" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
1367
+ /* @__PURE__ */ jsxs6("span", { className: "hsk-kiku-picker-item-body", children: [
1368
+ /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-name", children: "@kiku" }),
1369
+ /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-picker-item-price", style: { fontSize: "11px", whiteSpace: "normal", lineHeight: "1.3" }, children: "Ask Kiku to capture pages, remember items, or show your history" })
1370
+ ] })
1371
+ ]
1372
+ }
1373
+ )
1374
+ ]
1375
+ }
1376
+ );
1377
+ }
1192
1378
  function loadSessions() {
1193
1379
  try {
1194
1380
  if (typeof window === "undefined") return [];
@@ -1499,6 +1685,9 @@ var getFriendlyError = (err) => {
1499
1685
  if (lower.includes("token limit")) {
1500
1686
  return "You've reached your usage limit. Please update your billing limits in your dashboard to continue.";
1501
1687
  }
1688
+ if (lower.includes("failed to fetch") || lower.includes("networkerror") || lower.includes("request failed")) {
1689
+ return "The assistant couldn't respond just now \u2014 please try again in a moment.";
1690
+ }
1502
1691
  try {
1503
1692
  const parsed = JSON.parse(str);
1504
1693
  return parsed.error || parsed.message || str;
@@ -1714,6 +1903,8 @@ function ChatModal({
1714
1903
  });
1715
1904
  const [paymentPhase, setPaymentPhase] = useState5("idle");
1716
1905
  const [memoryKey, setMemoryKey] = useState5(null);
1906
+ const [showKikuPicker, setShowKikuPicker] = useState5(false);
1907
+ const [showAtPicker, setShowAtPicker] = useState5(false);
1717
1908
  const [sessions, setSessions] = useState5(() => loadSessions());
1718
1909
  const [sidebarOpen, setSidebarOpen] = useState5(false);
1719
1910
  const [replayMessages, setReplayMessages] = useState5(null);
@@ -1784,27 +1975,97 @@ function ChatModal({
1784
1975
  const q = `Tell me more about the ${src.name}${src.price ? ` (${src.currency ?? defaultCurrency} ${src.price})` : ""} \u2014 what are its key specs, who is it best for, and is it worth buying?`;
1785
1976
  send(q);
1786
1977
  };
1787
- const handleSend = async (text, extraAttachments) => {
1788
- const q = (text ?? input).trim();
1789
- if (!q || loading) return;
1978
+ const handleSend = async (text, extraAttachments, forcedIntent, captureTargets) => {
1979
+ const raw = (text ?? input).trim();
1980
+ if (!raw || loading) return;
1981
+ const kiku = parseAtKiku(raw);
1982
+ const q = kiku ? kiku.cleanQuery : raw;
1983
+ const resolvedForcedIntent = forcedIntent ?? kiku?.intent;
1790
1984
  setReplayMessages(null);
1791
1985
  setSelectedProduct(null);
1986
+ setShowKikuPicker(false);
1987
+ setShowAtPicker(false);
1792
1988
  setInput("");
1793
1989
  if (textareaRef.current) {
1794
1990
  textareaRef.current.style.height = "auto";
1795
1991
  }
1796
1992
  const toSend = extraAttachments ?? attachments;
1797
1993
  setAttachments([]);
1798
- await send(q, void 0, toSend.length > 0 ? toSend : void 0);
1994
+ await send(q, raw, toSend.length > 0 ? toSend : void 0, resolvedForcedIntent, captureTargets);
1799
1995
  };
1996
+ const handleSelectExtension = (ext) => {
1997
+ setInput(ext + " ");
1998
+ setShowAtPicker(false);
1999
+ setShowKikuPicker(true);
2000
+ if (textareaRef.current) {
2001
+ textareaRef.current.focus();
2002
+ }
2003
+ };
2004
+ const handleKikuCapture = useCallback2((product) => {
2005
+ const name = product.name || "";
2006
+ const display = `@kiku capture${name ? " " + name : ""}`;
2007
+ const q = name || "capture current page";
2008
+ setInput("");
2009
+ setReplayMessages(null);
2010
+ setSelectedProduct(null);
2011
+ const toSend = attachments;
2012
+ setAttachments([]);
2013
+ send(q, display, toSend.length > 0 ? toSend : void 0, "capture");
2014
+ }, [attachments, send]);
2015
+ const handleKikuCaptureAll = useCallback2((products) => {
2016
+ const targets = products.filter((p) => p.id).map((p) => ({
2017
+ name: p.name || "",
2018
+ url: p.url || "",
2019
+ image: p.image || "",
2020
+ price: p.price ? String(p.price) : "",
2021
+ currency: p.currency || defaultCurrency
2022
+ }));
2023
+ const names = products.map((p) => p.name).filter(Boolean).join(", ");
2024
+ const display = `@kiku capture all (${products.length} items)`;
2025
+ setInput("");
2026
+ setReplayMessages(null);
2027
+ setSelectedProduct(null);
2028
+ setAttachments([]);
2029
+ send(names || "capture all", display, void 0, "capture_all", targets);
2030
+ }, [defaultCurrency, send]);
2031
+ const handleKikuViewHistory = useCallback2(() => {
2032
+ const display = "@kiku what have you saved?";
2033
+ setInput("");
2034
+ setReplayMessages(null);
2035
+ setSelectedProduct(null);
2036
+ setAttachments([]);
2037
+ send("show my saved items", display, void 0, "view_history");
2038
+ }, [send]);
2039
+ const handleKikuDelete = useCallback2(() => {
2040
+ const display = "@kiku delete this";
2041
+ setInput("");
2042
+ setReplayMessages(null);
2043
+ setSelectedProduct(null);
2044
+ setAttachments([]);
2045
+ send("delete this", display, void 0, "delete");
2046
+ }, [send]);
1800
2047
  const handleKeyDown = (e) => {
2048
+ if (e.key === "Escape" && showKikuPicker) {
2049
+ e.preventDefault();
2050
+ setShowKikuPicker(false);
2051
+ return;
2052
+ }
2053
+ if (e.key === "Escape" && showAtPicker) {
2054
+ e.preventDefault();
2055
+ setShowAtPicker(false);
2056
+ return;
2057
+ }
1801
2058
  if (e.key === "Enter" && !e.shiftKey) {
1802
2059
  e.preventDefault();
1803
2060
  handleSend();
1804
2061
  }
1805
2062
  };
1806
2063
  const handleInput = (e) => {
1807
- setInput(e.target.value);
2064
+ const val = e.target.value;
2065
+ setInput(val);
2066
+ const trimmed = val.trim();
2067
+ setShowAtPicker(trimmed === "@");
2068
+ setShowKikuPicker(/^@kiku\b/i.test(trimmed));
1808
2069
  const t = e.target;
1809
2070
  t.style.height = "auto";
1810
2071
  t.style.height = `${Math.min(t.scrollHeight, 140)}px`;
@@ -1941,7 +2202,10 @@ function ChatModal({
1941
2202
  const displayContent = !isUser && isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages ? stripMarkdownTables(msg.content) : msg.content;
1942
2203
  return /* @__PURE__ */ jsx7("div", { className: "hsk-cb-msg-group", children: isUser ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-user-msg", children: [
1943
2204
  msg.images && msg.images.length > 0 && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-user-imgs", children: msg.images.map((img, i) => /* @__PURE__ */ jsx7("img", { src: img, alt: `attachment ${i + 1}`, className: "hsk-cb-user-img-thumb" }, i)) }),
1944
- msg.content && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-user-bubble", children: msg.content })
2205
+ msg.content && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-user-bubble", children: [
2206
+ /^@kiku\b/i.test(msg.content) && /* @__PURE__ */ jsx7("span", { className: "hsk-kiku-badge", children: "@kiku" }),
2207
+ msg.content
2208
+ ] })
1945
2209
  ] }) : /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-msg", children: [
1946
2210
  /* @__PURE__ */ jsx7("div", { className: "hsk-cb-ai-icon", style: { display: "flex", alignItems: "center" }, children: /* @__PURE__ */ jsx7(SparkleIcon2, {}) }),
1947
2211
  /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-ai-body", children: [
@@ -1956,7 +2220,7 @@ function ChatModal({
1956
2220
  ] });
1957
2221
  })(),
1958
2222
  isLast && lastIntent === "compare" && sources.length >= 2 && !replayMessages && /* @__PURE__ */ jsx7(ComparisonMatrix, { sources, defaultCurrency }),
1959
- isLast && referencedIds.length > 0 && lastIntent !== "compare" && lastAction?.type !== "request_phone" && lastAction?.type !== "awaiting_payment" && lastAction?.type !== "checkout" && !msg.cartSnapshot && /* @__PURE__ */ jsx7(
2223
+ isLast && referencedIds.length > 0 && lastIntent !== "compare" && lastAction?.type !== "request_phone" && lastAction?.type !== "awaiting_payment" && lastAction?.type !== "checkout" && lastAction?.type !== "capture" && lastAction?.type !== "delete" && lastAction?.type !== "view_history" && !msg.cartSnapshot && /* @__PURE__ */ jsx7(
1960
2224
  SourcesCarousel,
1961
2225
  {
1962
2226
  sources,
@@ -2067,6 +2331,26 @@ function ChatModal({
2067
2331
  /* @__PURE__ */ jsx7("div", { ref: bottomRef, style: { height: 1 } })
2068
2332
  ] }),
2069
2333
  !replayMessages && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-input-wrap", children: [
2334
+ showAtPicker && /* @__PURE__ */ jsx7(
2335
+ AtPickerMenu,
2336
+ {
2337
+ onSelect: handleSelectExtension,
2338
+ onDismiss: () => setShowAtPicker(false)
2339
+ }
2340
+ ),
2341
+ showKikuPicker && /* @__PURE__ */ jsx7(
2342
+ KikuPickerMenu,
2343
+ {
2344
+ sources,
2345
+ referencedIds,
2346
+ defaultCurrency,
2347
+ onCapture: handleKikuCapture,
2348
+ onCaptureAll: handleKikuCaptureAll,
2349
+ onViewHistory: handleKikuViewHistory,
2350
+ onDelete: handleKikuDelete,
2351
+ onDismiss: () => setShowKikuPicker(false)
2352
+ }
2353
+ ),
2070
2354
  attachments.length > 0 && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-img-strip", children: attachments.map((att, i) => /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-img-thumb-wrap", children: [
2071
2355
  /* @__PURE__ */ jsx7("img", { src: att.data, alt: `attachment ${i + 1}`, className: "hsk-cb-img-thumb" }),
2072
2356
  /* @__PURE__ */ jsx7(