@akropolys/kiku 1.5.0 → 1.5.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.js +179 -61
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +179 -61
- package/dist/index.mjs.map +1 -1
- package/dist/styles.css +59 -0
- package/dist/styles.css.map +1 -1
- package/package.json +2 -2
package/dist/index.mjs
CHANGED
|
@@ -170,7 +170,7 @@ import { useKiku } from "@akropolys/sdk";
|
|
|
170
170
|
// src/utils/markdown.tsx
|
|
171
171
|
import { Fragment as Fragment2, jsx as jsx2 } from "react/jsx-runtime";
|
|
172
172
|
var parseInline = (text, keyPrefix) => {
|
|
173
|
-
const tokenRegex = /(\[[^\]]+\]\([^)]+\)|\*\*[^*]+\*\*|`[^`]+`)/g;
|
|
173
|
+
const tokenRegex = /(!\[[^\]]*\]\([^)]+\)|\[[^\]]+\]\([^)]+\)|\*\*[^*]+\*\*|`[^`]+`)/g;
|
|
174
174
|
const parts = text.split(tokenRegex);
|
|
175
175
|
return parts.map((part, index) => {
|
|
176
176
|
if (!part) return null;
|
|
@@ -181,6 +181,28 @@ var parseInline = (text, keyPrefix) => {
|
|
|
181
181
|
if (part.startsWith("**") && part.endsWith("**")) {
|
|
182
182
|
return /* @__PURE__ */ jsx2("strong", { children: parseInline(part.slice(2, -2), key) }, key);
|
|
183
183
|
}
|
|
184
|
+
const imageMatch = part.match(/^!\[([^\]]*)\]\(([^)]+)\)$/);
|
|
185
|
+
if (imageMatch) {
|
|
186
|
+
const alt = imageMatch[1];
|
|
187
|
+
const url = imageMatch[2];
|
|
188
|
+
const isSafeUrl = /^(https?|data:image):/i.test(url);
|
|
189
|
+
if (isSafeUrl) {
|
|
190
|
+
return /* @__PURE__ */ jsx2(
|
|
191
|
+
"img",
|
|
192
|
+
{
|
|
193
|
+
src: url,
|
|
194
|
+
alt: alt || "Product image",
|
|
195
|
+
className: "hsk-markdown-img",
|
|
196
|
+
loading: "lazy",
|
|
197
|
+
onError: (e) => {
|
|
198
|
+
e.target.style.display = "none";
|
|
199
|
+
}
|
|
200
|
+
},
|
|
201
|
+
key
|
|
202
|
+
);
|
|
203
|
+
}
|
|
204
|
+
return null;
|
|
205
|
+
}
|
|
184
206
|
const linkMatch = part.match(/^\[([^\]]+)\]\(([^)]+)\)$/);
|
|
185
207
|
if (linkMatch) {
|
|
186
208
|
const url = linkMatch[2];
|
|
@@ -204,6 +226,30 @@ function renderMarkdown(content) {
|
|
|
204
226
|
i++;
|
|
205
227
|
continue;
|
|
206
228
|
}
|
|
229
|
+
const standaloneImageMatch = line.trim().match(/^!\[([^\]]*)\]\(([^)]+)\)$/);
|
|
230
|
+
if (standaloneImageMatch) {
|
|
231
|
+
const alt = standaloneImageMatch[1];
|
|
232
|
+
const url = standaloneImageMatch[2];
|
|
233
|
+
const isSafeUrl = /^(https?|data:image):/i.test(url);
|
|
234
|
+
if (isSafeUrl) {
|
|
235
|
+
elements.push(
|
|
236
|
+
/* @__PURE__ */ jsx2("div", { className: "hsk-markdown-img-block", children: /* @__PURE__ */ jsx2(
|
|
237
|
+
"img",
|
|
238
|
+
{
|
|
239
|
+
src: url,
|
|
240
|
+
alt: alt || "Product image",
|
|
241
|
+
className: "hsk-markdown-img",
|
|
242
|
+
loading: "lazy",
|
|
243
|
+
onError: (e) => {
|
|
244
|
+
e.target.style.display = "none";
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
) }, key)
|
|
248
|
+
);
|
|
249
|
+
}
|
|
250
|
+
i++;
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
207
253
|
const headerMatch = line.match(/^(#{1,3})\s+(.*)/);
|
|
208
254
|
if (headerMatch) {
|
|
209
255
|
const level = headerMatch[1].length;
|
|
@@ -391,18 +437,31 @@ var ArrowUpIcon = () => /* @__PURE__ */ jsxs4("svg", { width: "18", height: "18"
|
|
|
391
437
|
/* @__PURE__ */ jsx5("path", { d: "m5 12 7-7 7 7" }),
|
|
392
438
|
/* @__PURE__ */ jsx5("path", { d: "M12 19V5" })
|
|
393
439
|
] });
|
|
394
|
-
function SourceCard({
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
440
|
+
function SourceCard({
|
|
441
|
+
source,
|
|
442
|
+
defaultCurrency,
|
|
443
|
+
onSelect,
|
|
444
|
+
isReferenced
|
|
445
|
+
}) {
|
|
446
|
+
return /* @__PURE__ */ jsxs4(
|
|
447
|
+
"div",
|
|
448
|
+
{
|
|
449
|
+
className: cn("hsk-source-card", isReferenced && "hsk-source-card--referenced"),
|
|
450
|
+
onClick: () => onSelect?.(source),
|
|
451
|
+
children: [
|
|
452
|
+
source.image && /* @__PURE__ */ jsx5("img", { src: source.image, alt: source.name, className: "hsk-source-img" }),
|
|
453
|
+
/* @__PURE__ */ jsxs4("div", { style: { flex: 1, minWidth: 0, position: "relative" }, children: [
|
|
454
|
+
isReferenced && /* @__PURE__ */ jsx5("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", style: { top: "0", right: "0" }, children: /* @__PURE__ */ jsx5(SparkleIcon, {}) }),
|
|
455
|
+
/* @__PURE__ */ jsx5("div", { className: "hsk-source-name", style: { paddingRight: isReferenced ? "20px" : void 0 }, children: source.name }),
|
|
456
|
+
source.price && /* @__PURE__ */ jsxs4("div", { className: "hsk-source-price", children: [
|
|
457
|
+
source.currency ?? defaultCurrency,
|
|
458
|
+
" ",
|
|
459
|
+
source.price
|
|
460
|
+
] })
|
|
461
|
+
] })
|
|
462
|
+
]
|
|
463
|
+
}
|
|
464
|
+
);
|
|
406
465
|
}
|
|
407
466
|
function ChatWidget({
|
|
408
467
|
title = "AI Shopping Assistant",
|
|
@@ -418,7 +477,7 @@ function ChatWidget({
|
|
|
418
477
|
enableVision = false,
|
|
419
478
|
visionCategoryHint
|
|
420
479
|
}) {
|
|
421
|
-
const { messages, sources, loading: chatLoading, error, send, reset } = useKiku();
|
|
480
|
+
const { messages, sources, referencedIds, loading: chatLoading, streaming, error, send, reset } = useKiku();
|
|
422
481
|
const [input, setInput] = useState4("");
|
|
423
482
|
const [visualLoading, setVisualLoading] = useState4(false);
|
|
424
483
|
const bottomRef = useRef4(null);
|
|
@@ -576,7 +635,54 @@ I couldn't find any matching products in the store.`;
|
|
|
576
635
|
] })
|
|
577
636
|
] }),
|
|
578
637
|
msg.role === "assistant" && msg.visualSources && msg.visualSources.length > 0 && /* @__PURE__ */ jsx5("div", { className: "hsk-sources-container", children: /* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: msg.visualSources.map((src, si) => /* @__PURE__ */ jsx5(SourceCard, { source: src, defaultCurrency, onSelect: onSelectSource }, si)) }) }),
|
|
579
|
-
msg.role === "assistant" && idx === chatHistory.length - 1 && !msg.visualSources && sources.length > 0 &&
|
|
638
|
+
msg.role === "assistant" && idx === chatHistory.length - 1 && !msg.visualSources && sources.length > 0 && (() => {
|
|
639
|
+
const isStreamingActive = chatLoading || streaming;
|
|
640
|
+
if (isStreamingActive) {
|
|
641
|
+
return /* @__PURE__ */ jsx5("div", { className: "hsk-sources-container", children: /* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: sources.map((src, si) => {
|
|
642
|
+
const isReferenced = !!(src.id && referencedIds.includes(src.id));
|
|
643
|
+
return /* @__PURE__ */ jsx5(
|
|
644
|
+
SourceCard,
|
|
645
|
+
{
|
|
646
|
+
source: src,
|
|
647
|
+
defaultCurrency,
|
|
648
|
+
onSelect: onSelectSource,
|
|
649
|
+
isReferenced
|
|
650
|
+
},
|
|
651
|
+
si
|
|
652
|
+
);
|
|
653
|
+
}) }) });
|
|
654
|
+
}
|
|
655
|
+
const featured = sources.filter((src) => src.id && referencedIds.includes(src.id));
|
|
656
|
+
const general = sources.filter((src) => !src.id || !referencedIds.includes(src.id));
|
|
657
|
+
return /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-container", children: [
|
|
658
|
+
featured.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-group", style: { marginBottom: "10px" }, children: [
|
|
659
|
+
/* @__PURE__ */ jsx5("div", { className: "hsk-sources-group-title", children: "\u2B50 Featured in response" }),
|
|
660
|
+
/* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: featured.map((src, si) => /* @__PURE__ */ jsx5(
|
|
661
|
+
SourceCard,
|
|
662
|
+
{
|
|
663
|
+
source: src,
|
|
664
|
+
defaultCurrency,
|
|
665
|
+
onSelect: onSelectSource,
|
|
666
|
+
isReferenced: true
|
|
667
|
+
},
|
|
668
|
+
`feat-${si}`
|
|
669
|
+
)) })
|
|
670
|
+
] }),
|
|
671
|
+
general.length > 0 && /* @__PURE__ */ jsxs4("div", { className: "hsk-sources-group", children: [
|
|
672
|
+
featured.length > 0 && /* @__PURE__ */ jsx5("div", { className: "hsk-sources-group-title", children: "All matches" }),
|
|
673
|
+
/* @__PURE__ */ jsx5("div", { className: "hsk-sources", children: general.map((src, si) => /* @__PURE__ */ jsx5(
|
|
674
|
+
SourceCard,
|
|
675
|
+
{
|
|
676
|
+
source: src,
|
|
677
|
+
defaultCurrency,
|
|
678
|
+
onSelect: onSelectSource,
|
|
679
|
+
isReferenced: false
|
|
680
|
+
},
|
|
681
|
+
`gen-${si}`
|
|
682
|
+
)) })
|
|
683
|
+
] })
|
|
684
|
+
] });
|
|
685
|
+
})()
|
|
580
686
|
] }, idx)),
|
|
581
687
|
loading && /* @__PURE__ */ jsxs4("div", { className: "hsk-msg-row", children: [
|
|
582
688
|
/* @__PURE__ */ jsx5("div", { className: "hsk-msg-avatar ai", children: /* @__PURE__ */ jsx5(SparkleIcon, {}) }),
|
|
@@ -1106,8 +1212,10 @@ function ActionPills({ cart, actionType, onSend, loading }) {
|
|
|
1106
1212
|
const pills = [];
|
|
1107
1213
|
if (hasItems && lastItem) {
|
|
1108
1214
|
if (actionType === "add_to_cart") {
|
|
1109
|
-
|
|
1110
|
-
|
|
1215
|
+
const name = lastItem.name || "item";
|
|
1216
|
+
const shortName = name.split(" ")[0] || "item";
|
|
1217
|
+
pills.push({ emoji: "\u2795", label: "Add 1 more", query: `Add one more ${name} to my cart` });
|
|
1218
|
+
pills.push({ emoji: "\u{1F5D1}\uFE0F", label: `Remove ${shortName}`, query: `Remove the ${name} from my cart` });
|
|
1111
1219
|
}
|
|
1112
1220
|
if (cart.items.length > 1) {
|
|
1113
1221
|
pills.push({ emoji: "\u{1F6D2}", label: "View cart", query: "Show me my cart" });
|
|
@@ -1138,7 +1246,7 @@ function ActionPills({ cart, actionType, onSend, loading }) {
|
|
|
1138
1246
|
pill.query
|
|
1139
1247
|
)) });
|
|
1140
1248
|
}
|
|
1141
|
-
function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
|
|
1249
|
+
function SourcesCarousel({ sources, defaultCurrency, onSelectSource, referencedIds = [] }) {
|
|
1142
1250
|
const client = useAkropolysContext3();
|
|
1143
1251
|
const isProperty = client?.vertical === "property";
|
|
1144
1252
|
const railRef = useRef5(null);
|
|
@@ -1165,44 +1273,51 @@ function SourcesCarousel({ sources, defaultCurrency, onSelectSource }) {
|
|
|
1165
1273
|
railRef.current?.scrollBy({ left: 170, behavior: "smooth" });
|
|
1166
1274
|
};
|
|
1167
1275
|
return /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-sources-wrap", children: [
|
|
1168
|
-
/* @__PURE__ */ jsx7("div", { className: "hsk-cb-sources", ref: railRef, children: sources.map((src, si) =>
|
|
1169
|
-
|
|
1170
|
-
|
|
1171
|
-
|
|
1172
|
-
|
|
1173
|
-
|
|
1174
|
-
|
|
1175
|
-
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
|
|
1181
|
-
|
|
1182
|
-
|
|
1183
|
-
|
|
1184
|
-
|
|
1185
|
-
|
|
1186
|
-
|
|
1187
|
-
|
|
1188
|
-
|
|
1189
|
-
|
|
1190
|
-
|
|
1191
|
-
|
|
1192
|
-
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
|
|
1196
|
-
|
|
1197
|
-
|
|
1198
|
-
" ",
|
|
1199
|
-
|
|
1276
|
+
/* @__PURE__ */ jsx7("div", { className: "hsk-cb-sources", ref: railRef, children: sources.map((src, si) => {
|
|
1277
|
+
const isReferenced = !!(src.id && referencedIds.includes(src.id));
|
|
1278
|
+
return /* @__PURE__ */ jsxs6(
|
|
1279
|
+
"div",
|
|
1280
|
+
{
|
|
1281
|
+
className: cn("hsk-cb-source", isReferenced && "hsk-cb-source--referenced"),
|
|
1282
|
+
style: { animationDelay: `${si * 50}ms` },
|
|
1283
|
+
onClick: () => onSelectSource?.(src),
|
|
1284
|
+
children: [
|
|
1285
|
+
src.image ? /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-imgwrap", style: { position: "relative" }, children: [
|
|
1286
|
+
/* @__PURE__ */ jsx7("img", { src: src.image, alt: src.name, loading: "lazy" }),
|
|
1287
|
+
isReferenced && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 10 }) }),
|
|
1288
|
+
isProperty && /* @__PURE__ */ jsx7("div", { style: {
|
|
1289
|
+
position: "absolute",
|
|
1290
|
+
top: "6px",
|
|
1291
|
+
right: "6px",
|
|
1292
|
+
background: "rgba(14, 14, 15, 0.75)",
|
|
1293
|
+
backdropFilter: "blur(4px)",
|
|
1294
|
+
borderRadius: "50%",
|
|
1295
|
+
width: "24px",
|
|
1296
|
+
height: "24px",
|
|
1297
|
+
display: "flex",
|
|
1298
|
+
alignItems: "center",
|
|
1299
|
+
justifyContent: "center",
|
|
1300
|
+
color: "#fbbf24",
|
|
1301
|
+
// Gold sparkle badge
|
|
1302
|
+
boxShadow: "0 2px 4px rgba(0,0,0,0.2)"
|
|
1303
|
+
}, children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 12 }) })
|
|
1304
|
+
] }) : /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-imgwrap-empty", style: { position: "relative" }, children: [
|
|
1305
|
+
/* @__PURE__ */ jsx7(SparkleIcon2, {}),
|
|
1306
|
+
isReferenced && /* @__PURE__ */ jsx7("div", { className: "hsk-cb-source-ref-badge", title: "Featured in response", children: /* @__PURE__ */ jsx7(SparkleIcon2, { size: 10 }) })
|
|
1307
|
+
] }),
|
|
1308
|
+
/* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-info", children: [
|
|
1309
|
+
/* @__PURE__ */ jsx7("div", { className: "hsk-cb-src-name", children: src.name }),
|
|
1310
|
+
src.price && /* @__PURE__ */ jsxs6("div", { className: "hsk-cb-src-price", children: [
|
|
1311
|
+
src.currency ?? defaultCurrency,
|
|
1312
|
+
" ",
|
|
1313
|
+
parseFloat(String(src.price).replace(/[^0-9.]/g, "") || "0").toLocaleString()
|
|
1314
|
+
] })
|
|
1200
1315
|
] })
|
|
1201
|
-
]
|
|
1202
|
-
|
|
1203
|
-
|
|
1204
|
-
|
|
1205
|
-
)
|
|
1316
|
+
]
|
|
1317
|
+
},
|
|
1318
|
+
si
|
|
1319
|
+
);
|
|
1320
|
+
}) }),
|
|
1206
1321
|
showNext && /* @__PURE__ */ jsxs6(Fragment3, { children: [
|
|
1207
1322
|
/* @__PURE__ */ jsx7(
|
|
1208
1323
|
"div",
|
|
@@ -1250,11 +1365,12 @@ function SmartContextPills({
|
|
|
1250
1365
|
});
|
|
1251
1366
|
}
|
|
1252
1367
|
if (cheapest && !isProperty) {
|
|
1253
|
-
const
|
|
1368
|
+
const name = cheapest.name || "";
|
|
1369
|
+
const short = name.split(" ").slice(0, 3).join(" ");
|
|
1254
1370
|
pills.push({
|
|
1255
1371
|
emoji: "\u{1F6D2}",
|
|
1256
1372
|
label: `Add ${short}`,
|
|
1257
|
-
query: `Add the ${
|
|
1373
|
+
query: `Add the ${name} to my cart`
|
|
1258
1374
|
});
|
|
1259
1375
|
}
|
|
1260
1376
|
if (isProperty) {
|
|
@@ -1264,11 +1380,12 @@ function SmartContextPills({
|
|
|
1264
1380
|
}
|
|
1265
1381
|
} else if (intent === "compare" && sources.length > 0) {
|
|
1266
1382
|
if (cheapest && !isProperty) {
|
|
1267
|
-
const
|
|
1383
|
+
const name = cheapest.name || "";
|
|
1384
|
+
const short = name.split(" ").slice(0, 3).join(" ");
|
|
1268
1385
|
pills.push({
|
|
1269
1386
|
emoji: "\u{1F6D2}",
|
|
1270
1387
|
label: `Add ${short}`,
|
|
1271
|
-
query: `Add the ${
|
|
1388
|
+
query: `Add the ${name} to my cart`
|
|
1272
1389
|
});
|
|
1273
1390
|
}
|
|
1274
1391
|
if (firstName) {
|
|
@@ -1371,7 +1488,7 @@ function ChatModal({
|
|
|
1371
1488
|
visionCategoryHint
|
|
1372
1489
|
}) {
|
|
1373
1490
|
const client = useAkropolysContext3();
|
|
1374
|
-
const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset } = useKiku2();
|
|
1491
|
+
const { messages, sources, loading, streaming, error, lastAction, lastIntent, send, reset, referencedIds } = useKiku2();
|
|
1375
1492
|
const [input, setInput] = useState5("");
|
|
1376
1493
|
const [loadingMessageIndex, setLoadingMessageIndex] = useState5(0);
|
|
1377
1494
|
const [attachments, setAttachments] = useState5([]);
|
|
@@ -1716,7 +1833,8 @@ function ChatModal({
|
|
|
1716
1833
|
{
|
|
1717
1834
|
sources,
|
|
1718
1835
|
defaultCurrency,
|
|
1719
|
-
onSelectSource: handleSourceClick
|
|
1836
|
+
onSelectSource: handleSourceClick,
|
|
1837
|
+
referencedIds
|
|
1720
1838
|
}
|
|
1721
1839
|
),
|
|
1722
1840
|
msg.cartSnapshot && msg.cartSnapshot.items?.length > 0 && /* @__PURE__ */ jsx7(
|