@akropolys/kiku 1.5.14 → 1.5.17

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
@@ -688,7 +688,7 @@ I couldn't find any matching products in the store.`;
688
688
  }) }) });
689
689
  }
690
690
  const featured = sources.filter((src) => src.id && referencedIds.includes(src.id));
691
- const general = sources.filter((src) => !src.id || !referencedIds.includes(src.id));
691
+ const general = featured.length > 0 ? [] : sources.filter((src) => !src.id || !referencedIds.includes(src.id));
692
692
  return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-sources-container", children: [
693
693
  featured.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "hsk-sources-group", style: { marginBottom: "10px" }, children: [
694
694
  /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "hsk-sources-group-title", children: "\u2B50 Featured in response" }),
@@ -1359,8 +1359,10 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedI
1359
1359
  const scrollNext = () => {
1360
1360
  railRef.current?.scrollBy({ left: 170, behavior: "smooth" });
1361
1361
  };
1362
+ const referenced = sources.filter((s) => s.id && referencedIds.includes(s.id));
1363
+ const display = referenced.length > 0 ? referenced : sources;
1362
1364
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-sources-wrap", children: [
1363
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sources", ref: railRef, children: sources.map((src, si) => {
1365
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-sources", ref: railRef, children: display.map((src, si) => {
1364
1366
  const isReferenced = !!(src.id && referencedIds.includes(src.id));
1365
1367
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
1366
1368
  "div",
@@ -1540,6 +1542,18 @@ var getFriendlyError = (err) => {
1540
1542
  return str;
1541
1543
  }
1542
1544
  };
1545
+ var MK_ADJ = ["flying", "silent", "golden", "lucky", "brave", "swift", "royal", "cosmic"];
1546
+ var MK_NOUN = ["thunder", "falcon", "river", "ember", "tiger", "comet", "willow", "onyx"];
1547
+ function generateMagicWord() {
1548
+ return MK_ADJ[Math.floor(Math.random() * MK_ADJ.length)] + MK_NOUN[Math.floor(Math.random() * MK_NOUN.length)];
1549
+ }
1550
+ function parseMemoryKey(raw) {
1551
+ const cleaned = raw.trim().replace(/\s+/g, "");
1552
+ const m = cleaned.match(/^(\d{6,})([a-zA-Z].*)?$/);
1553
+ const phone = m?.[1] || cleaned.replace(/\D/g, "");
1554
+ const word = (m?.[2] || "").toLowerCase() || generateMagicWord();
1555
+ return { phone, word };
1556
+ }
1543
1557
  function parseThinking(text) {
1544
1558
  const openMatch = text.match(/<\s*thinking\s*>/i);
1545
1559
  if (!openMatch) {
@@ -1681,17 +1695,34 @@ function ChatModal({
1681
1695
  const SR = window.SpeechRecognition || window.webkitSpeechRecognition;
1682
1696
  const recognition = new SR();
1683
1697
  recognition.lang = "en-US";
1684
- recognition.interimResults = false;
1698
+ recognition.interimResults = true;
1685
1699
  recognition.maxAlternatives = 1;
1686
1700
  recognitionRef.current = recognition;
1687
1701
  recognition.onstart = () => setVoiceState("listening");
1688
1702
  recognition.onresult = (event) => {
1689
- const transcript = event.results[0][0].transcript;
1690
- setInput(transcript);
1691
- pendingVoiceRef.current = transcript;
1692
- setVoiceState("processing");
1703
+ let finalText = "";
1704
+ let interimText = "";
1705
+ for (let i = 0; i < event.results.length; i++) {
1706
+ const seg = event.results[i][0].transcript;
1707
+ if (event.results[i].isFinal) finalText += seg;
1708
+ else interimText += seg;
1709
+ }
1710
+ const live = (finalText + " " + interimText).trim();
1711
+ if (live) setInput(live);
1712
+ if (finalText.trim()) {
1713
+ pendingVoiceRef.current = finalText.trim();
1714
+ setVoiceState("processing");
1715
+ }
1716
+ };
1717
+ recognition.onerror = (event) => {
1718
+ const err = event?.error;
1719
+ if (err === "not-allowed" || err === "service-not-allowed") {
1720
+ setInput("Microphone access was blocked \u2014 enable it in your browser to use voice.");
1721
+ } else if (err === "no-speech") {
1722
+ setInput("Didn't catch that \u2014 tap the mic and try again.");
1723
+ }
1724
+ setVoiceState("idle");
1693
1725
  };
1694
- recognition.onerror = () => setVoiceState("idle");
1695
1726
  recognition.onend = () => {
1696
1727
  setVoiceState((prev) => prev === "listening" ? "idle" : prev);
1697
1728
  };
@@ -1719,6 +1750,7 @@ function ChatModal({
1719
1750
  });
1720
1751
  const [merchantRef, setMerchantRef] = (0, import_react5.useState)(null);
1721
1752
  const [paymentPhase, setPaymentPhase] = (0, import_react5.useState)("idle");
1753
+ const [memoryKey, setMemoryKey] = (0, import_react5.useState)(null);
1722
1754
  const [sessions, setSessions] = (0, import_react5.useState)(() => loadSessions());
1723
1755
  const [sidebarOpen, setSidebarOpen] = (0, import_react5.useState)(false);
1724
1756
  const [replayMessages, setReplayMessages] = (0, import_react5.useState)(null);
@@ -1760,6 +1792,10 @@ function ChatModal({
1760
1792
  }
1761
1793
  const isHistoryIntent = lastIntent === "capture" || lastIntent === "delete" || lastIntent === "view_history";
1762
1794
  if (isHistoryIntent) {
1795
+ const { phone, word } = parseMemoryKey(phoneInput);
1796
+ if (!phone) return;
1797
+ client.setShopperIdentity(phone, word);
1798
+ setMemoryKey(phone + word);
1763
1799
  setPaymentPhase("idle");
1764
1800
  const lastUserMsg = [...messages].reverse().find((m) => m.role === "user");
1765
1801
  if (lastUserMsg) {
@@ -2065,7 +2101,25 @@ function ChatModal({
2065
2101
  !replayMessages && paymentPhase === "prompt_phone" && (() => {
2066
2102
  const isHistoryIntent = lastIntent === "capture" || lastIntent === "delete" || lastIntent === "view_history";
2067
2103
  if (isHistoryIntent) {
2068
- return null;
2104
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2105
+ /* @__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, {}) }),
2106
+ /* @__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: [
2107
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("label", { className: "hsk-cb-phone-label", children: "Your phone number \u2014 or paste your memory key" }),
2108
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
2109
+ "input",
2110
+ {
2111
+ type: "text",
2112
+ className: "hsk-cb-phone-input",
2113
+ placeholder: "0712345678 or 0712345678flyingthunder",
2114
+ value: phoneInput,
2115
+ onChange: (e) => setPhoneInput(e.target.value.replace(/[^0-9a-zA-Z]/g, "")),
2116
+ onKeyDown: (e) => e.key === "Enter" && handlePhoneSubmit(),
2117
+ autoFocus: true
2118
+ }
2119
+ ),
2120
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", onClick: handlePhoneSubmit, children: "Save & sync my items" })
2121
+ ] }) }) })
2122
+ ] });
2069
2123
  }
2070
2124
  return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2071
2125
  /* @__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, {}) }),
@@ -2087,6 +2141,22 @@ function ChatModal({
2087
2141
  ] }) }) })
2088
2142
  ] });
2089
2143
  })(),
2144
+ !replayMessages && memoryKey && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-ai-msg", children: [
2145
+ /* @__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, {}) }),
2146
+ /* @__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: [
2147
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { style: { fontSize: 12, fontWeight: 600, marginBottom: 4 }, children: "\u{1F511} Your memory key" }),
2148
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("code", { style: { display: "block", fontSize: 14, fontWeight: 700, marginBottom: 6, wordBreak: "break-all" }, children: memoryKey }),
2149
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { style: { display: "flex", gap: 8, alignItems: "center" }, children: [
2150
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("button", { className: "hsk-cb-phone-submit", style: { padding: "4px 10px" }, onClick: () => {
2151
+ try {
2152
+ navigator.clipboard?.writeText(memoryKey);
2153
+ } catch {
2154
+ }
2155
+ }, children: "Copy" }),
2156
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: 11, opacity: 0.7 }, children: "Save it \u2014 enter it on any site to get your items back." })
2157
+ ] })
2158
+ ] }) }) })
2159
+ ] }),
2090
2160
  !replayMessages && paymentPhase === "awaiting" && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "hsk-cb-payment-prompt hsk-cb-payment-prompt--awaiting", children: [
2091
2161
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-payment-pulse-ring" }),
2092
2162
  /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "hsk-cb-payment-icon-wrap", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { style: { fontSize: "2rem" }, children: "\u{1F4F1}" }) }),
@@ -2183,7 +2253,7 @@ function ChatModal({
2183
2253
  value: input,
2184
2254
  onChange: handleInput,
2185
2255
  onKeyDown: handleKeyDown,
2186
- placeholder: activePlaceholder,
2256
+ placeholder: voiceState === "listening" ? "\u{1F399}\uFE0F Listening\u2026 tap the mic to stop" : voiceState === "processing" ? "Got it \u2014 sending\u2026" : activePlaceholder,
2187
2257
  rows: 1,
2188
2258
  disabled: loading,
2189
2259
  autoFocus: true