@retrivora-ai/rag-engine 1.3.1 → 1.3.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/{chunk-AYOQ4LF4.mjs → chunk-FQ7OYZLF.mjs} +4 -2
- package/dist/handlers/index.js +4 -2
- package/dist/handlers/index.mjs +1 -1
- package/dist/index.js +205 -110
- package/dist/index.mjs +205 -110
- package/dist/server.js +4 -2
- package/dist/server.mjs +1 -1
- package/package.json +1 -1
- package/src/components/DynamicChart.tsx +29 -15
- package/src/components/MessageBubble.tsx +246 -160
- package/src/core/LangChainAgent.ts +2 -1
- package/src/core/Pipeline.ts +2 -1
|
@@ -1703,7 +1703,8 @@ When presenting structured data, statistics, or comparisons, decide if it is bes
|
|
|
1703
1703
|
1. Use ONLY valid JSON (double quotes, no trailing commas).
|
|
1704
1704
|
2. NO math expressions (e.g., use 100, NOT 50+50).
|
|
1705
1705
|
3. dataKeys MUST exactly match the property names in the data objects.
|
|
1706
|
-
4.
|
|
1706
|
+
4. data objects MUST be FLAT (no nested objects or arrays).
|
|
1707
|
+
5. DO NOT output naked JSON; it MUST be wrapped in \`\`\`chart ... \`\`\`.
|
|
1707
1708
|
\`\`\`chart
|
|
1708
1709
|
{
|
|
1709
1710
|
"type": "bar" | "line" | "pie",
|
|
@@ -2265,7 +2266,8 @@ When presenting structured data, statistics, or comparisons, decide if it is bes
|
|
|
2265
2266
|
1. Use ONLY valid JSON (double quotes, no trailing commas).
|
|
2266
2267
|
2. NO math expressions (e.g., use 100, NOT 50+50).
|
|
2267
2268
|
3. dataKeys MUST exactly match the property names in the data objects.
|
|
2268
|
-
4.
|
|
2269
|
+
4. data objects MUST be FLAT (no nested objects or arrays).
|
|
2270
|
+
5. DO NOT output naked JSON; it MUST be wrapped in \`\`\`chart ... \`\`\`.
|
|
2269
2271
|
\`\`\`chart
|
|
2270
2272
|
{
|
|
2271
2273
|
"type": "bar" | "line" | "pie",
|
package/dist/handlers/index.js
CHANGED
|
@@ -3272,7 +3272,8 @@ When presenting structured data, statistics, or comparisons, decide if it is bes
|
|
|
3272
3272
|
1. Use ONLY valid JSON (double quotes, no trailing commas).
|
|
3273
3273
|
2. NO math expressions (e.g., use 100, NOT 50+50).
|
|
3274
3274
|
3. dataKeys MUST exactly match the property names in the data objects.
|
|
3275
|
-
4.
|
|
3275
|
+
4. data objects MUST be FLAT (no nested objects or arrays).
|
|
3276
|
+
5. DO NOT output naked JSON; it MUST be wrapped in \`\`\`chart ... \`\`\`.
|
|
3276
3277
|
\`\`\`chart
|
|
3277
3278
|
{
|
|
3278
3279
|
"type": "bar" | "line" | "pie",
|
|
@@ -3828,7 +3829,8 @@ When presenting structured data, statistics, or comparisons, decide if it is bes
|
|
|
3828
3829
|
1. Use ONLY valid JSON (double quotes, no trailing commas).
|
|
3829
3830
|
2. NO math expressions (e.g., use 100, NOT 50+50).
|
|
3830
3831
|
3. dataKeys MUST exactly match the property names in the data objects.
|
|
3831
|
-
4.
|
|
3832
|
+
4. data objects MUST be FLAT (no nested objects or arrays).
|
|
3833
|
+
5. DO NOT output naked JSON; it MUST be wrapped in \`\`\`chart ... \`\`\`.
|
|
3832
3834
|
\`\`\`chart
|
|
3833
3835
|
{
|
|
3834
3836
|
"type": "bar" | "line" | "pie",
|
package/dist/handlers/index.mjs
CHANGED
package/dist/index.js
CHANGED
|
@@ -223,6 +223,30 @@ var DEFAULT_COLORS = ["#6366f1", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#e
|
|
|
223
223
|
function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6" }) {
|
|
224
224
|
const { type, data } = config;
|
|
225
225
|
const colors = config.colors || [primaryColor, accentColor, ...DEFAULT_COLORS];
|
|
226
|
+
const sanitizedData = import_react4.default.useMemo(() => {
|
|
227
|
+
if (!data) return [];
|
|
228
|
+
return data.map((item) => {
|
|
229
|
+
const newItem = {};
|
|
230
|
+
Object.keys(item).forEach((k) => {
|
|
231
|
+
const val = item[k];
|
|
232
|
+
if (Array.isArray(val)) {
|
|
233
|
+
val.forEach((subItem) => {
|
|
234
|
+
if (typeof subItem === "object" && subItem !== null) {
|
|
235
|
+
Object.keys(subItem).forEach((sk) => {
|
|
236
|
+
const subVal = subItem[sk];
|
|
237
|
+
if (typeof subVal !== "object" || subVal === null) {
|
|
238
|
+
newItem[sk] = subVal;
|
|
239
|
+
}
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
});
|
|
243
|
+
} else if (typeof val !== "object" || val === null) {
|
|
244
|
+
newItem[k] = val;
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
return newItem;
|
|
248
|
+
});
|
|
249
|
+
}, [data]);
|
|
226
250
|
if (!data || data.length === 0) {
|
|
227
251
|
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "p-4 text-sm text-slate-500" }, "No data available for chart.");
|
|
228
252
|
}
|
|
@@ -238,18 +262,6 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
238
262
|
}).slice(0, 5);
|
|
239
263
|
const finalXKey = String(resolvedXKey);
|
|
240
264
|
const finalDataKeys = resolvedDataKeys.map(String).filter((k) => k !== "undefined");
|
|
241
|
-
const sanitizedData = import_react4.default.useMemo(() => {
|
|
242
|
-
return data.map((item) => {
|
|
243
|
-
const newItem = {};
|
|
244
|
-
Object.keys(item).forEach((k) => {
|
|
245
|
-
const val = item[k];
|
|
246
|
-
if (typeof val !== "object" || val === null) {
|
|
247
|
-
newItem[k] = val;
|
|
248
|
-
}
|
|
249
|
-
});
|
|
250
|
-
return newItem;
|
|
251
|
-
});
|
|
252
|
-
}, [data]);
|
|
253
265
|
if (type === "pie") {
|
|
254
266
|
const pieDataKey = finalDataKeys[0] || "value";
|
|
255
267
|
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full h-72 min-h-[280px] mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.ResponsiveContainer, { width: "99%", height: "100%" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.PieChart, null, /* @__PURE__ */ import_react4.default.createElement(
|
|
@@ -306,6 +318,90 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
|
|
|
306
318
|
}
|
|
307
319
|
|
|
308
320
|
// src/components/MessageBubble.tsx
|
|
321
|
+
function sanitizeJson(raw) {
|
|
322
|
+
let s = raw.trim();
|
|
323
|
+
s = s.replace(
|
|
324
|
+
/:\s*(-?\d+(?:\.\d+)?)\s*([+\-*/])\s*(-?\d+(?:\.\d+)?)/g,
|
|
325
|
+
(_, a, op, b) => {
|
|
326
|
+
const n1 = parseFloat(a);
|
|
327
|
+
const n2 = parseFloat(b);
|
|
328
|
+
const result = op === "+" ? n1 + n2 : op === "-" ? n1 - n2 : op === "*" ? n1 * n2 : n2 !== 0 ? n1 / n2 : n1;
|
|
329
|
+
return `: ${result}`;
|
|
330
|
+
}
|
|
331
|
+
);
|
|
332
|
+
s = s.replace(/\/\/[^\n]*/g, "");
|
|
333
|
+
s = s.replace(/([{,]\s*)([A-Za-z_$][A-Za-z0-9_$]*)\s*:/g, '$1"$2":');
|
|
334
|
+
s = s.replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"');
|
|
335
|
+
s = s.replace(/,\s*([}\]])/g, "$1");
|
|
336
|
+
s = s.replace(/([{,])\s*""\s*(?=[,}])/g, "$1");
|
|
337
|
+
{
|
|
338
|
+
let inString = false;
|
|
339
|
+
let escape = false;
|
|
340
|
+
let braces = 0;
|
|
341
|
+
let brackets = 0;
|
|
342
|
+
for (const ch of s) {
|
|
343
|
+
if (escape) {
|
|
344
|
+
escape = false;
|
|
345
|
+
continue;
|
|
346
|
+
}
|
|
347
|
+
if (ch === "\\" && inString) {
|
|
348
|
+
escape = true;
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
if (ch === '"') {
|
|
352
|
+
inString = !inString;
|
|
353
|
+
continue;
|
|
354
|
+
}
|
|
355
|
+
if (inString) continue;
|
|
356
|
+
if (ch === "{") braces++;
|
|
357
|
+
else if (ch === "}") braces--;
|
|
358
|
+
else if (ch === "[") brackets++;
|
|
359
|
+
else if (ch === "]") brackets--;
|
|
360
|
+
}
|
|
361
|
+
if (inString) s += '"';
|
|
362
|
+
while (brackets > 0) {
|
|
363
|
+
s += "]";
|
|
364
|
+
brackets--;
|
|
365
|
+
}
|
|
366
|
+
while (braces > 0) {
|
|
367
|
+
s += "}";
|
|
368
|
+
braces--;
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
const lastClose = Math.max(s.lastIndexOf("}"), s.lastIndexOf("]"));
|
|
372
|
+
if (lastClose !== -1 && lastClose < s.length - 1) {
|
|
373
|
+
s = s.substring(0, lastClose + 1);
|
|
374
|
+
}
|
|
375
|
+
return s;
|
|
376
|
+
}
|
|
377
|
+
function resolveImage(data) {
|
|
378
|
+
for (const key of ["image", "img", "thumbnail"]) {
|
|
379
|
+
const v = data[key];
|
|
380
|
+
if (typeof v === "string" && v) return v;
|
|
381
|
+
}
|
|
382
|
+
if (Array.isArray(data.images) && typeof data.images[0] === "string") {
|
|
383
|
+
return data.images[0];
|
|
384
|
+
}
|
|
385
|
+
return void 0;
|
|
386
|
+
}
|
|
387
|
+
function ChartBlock({ rawContent, primaryColor, accentColor }) {
|
|
388
|
+
const result = import_react5.default.useMemo(() => {
|
|
389
|
+
if (!rawContent || rawContent === "undefined") return { error: "Empty chart config." };
|
|
390
|
+
try {
|
|
391
|
+
const sanitized = sanitizeJson(rawContent);
|
|
392
|
+
const config = JSON.parse(sanitized);
|
|
393
|
+
return { config };
|
|
394
|
+
} catch (err) {
|
|
395
|
+
const sanitized = sanitizeJson(rawContent);
|
|
396
|
+
console.error("[ChartBlock] Parsing failed.\nError:", err, "\nSanitized:\n", sanitized);
|
|
397
|
+
return { error: String(err) };
|
|
398
|
+
}
|
|
399
|
+
}, [rawContent]);
|
|
400
|
+
if ("error" in result) {
|
|
401
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "p-4 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm border border-red-100 dark:border-red-900/30" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "font-medium mb-1" }, "Failed to render chart"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "opacity-70 text-xs" }, "The generated configuration is invalid. Check the console for details."));
|
|
402
|
+
}
|
|
403
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "my-4 p-4 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement(DynamicChart, { config: result.config, primaryColor, accentColor }));
|
|
404
|
+
}
|
|
309
405
|
function MessageBubble({
|
|
310
406
|
message,
|
|
311
407
|
sources,
|
|
@@ -316,28 +412,18 @@ function MessageBubble({
|
|
|
316
412
|
}) {
|
|
317
413
|
const isUser = message.role === "user";
|
|
318
414
|
const [showSources, setShowSources] = import_react5.default.useState(false);
|
|
319
|
-
const resolveImage = (data) => {
|
|
320
|
-
if (!data) return void 0;
|
|
321
|
-
const singleFields = ["image", "img", "thumbnail"];
|
|
322
|
-
for (const field of singleFields) {
|
|
323
|
-
const val = data[field];
|
|
324
|
-
if (typeof val === "string" && val) return val;
|
|
325
|
-
}
|
|
326
|
-
if (Array.isArray(data.images) && data.images.length > 0) {
|
|
327
|
-
if (typeof data.images[0] === "string") return data.images[0];
|
|
328
|
-
}
|
|
329
|
-
return void 0;
|
|
330
|
-
};
|
|
331
415
|
const productsFromSources = import_react5.default.useMemo(() => {
|
|
332
416
|
if (isUser || !sources) return [];
|
|
333
417
|
return sources.filter((s) => {
|
|
334
|
-
|
|
418
|
+
var _a;
|
|
419
|
+
const m = (_a = s.metadata) != null ? _a : {};
|
|
335
420
|
return m.price || m.image || m.img || m.thumbnail || m.images || m.brand || m.type === "product";
|
|
336
421
|
}).map((s) => {
|
|
337
|
-
|
|
422
|
+
var _a, _b, _c, _d;
|
|
423
|
+
const m = (_a = s.metadata) != null ? _a : {};
|
|
338
424
|
return {
|
|
339
425
|
id: s.id,
|
|
340
|
-
name: m.name
|
|
426
|
+
name: (_d = (_c = (_b = m.name) != null ? _b : m.title) != null ? _c : s.content.split("\n")[0]) != null ? _d : "Unknown Product",
|
|
341
427
|
brand: m.brand,
|
|
342
428
|
price: m.price,
|
|
343
429
|
image: resolveImage(m),
|
|
@@ -352,16 +438,19 @@ function MessageBubble({
|
|
|
352
438
|
const products = [];
|
|
353
439
|
let content = message.content;
|
|
354
440
|
if (content.includes('"type": "products"') || content.includes('"type":"products"')) {
|
|
355
|
-
const
|
|
356
|
-
for (const m of matches) {
|
|
441
|
+
for (const match of content.matchAll(jsonRegex)) {
|
|
357
442
|
try {
|
|
358
|
-
const data = JSON.parse(
|
|
443
|
+
const data = JSON.parse(match[1]);
|
|
359
444
|
if (data.type === "products" && Array.isArray(data.items)) {
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
445
|
+
products.push(
|
|
446
|
+
...data.items.map((item) => {
|
|
447
|
+
var _a;
|
|
448
|
+
return __spreadProps(__spreadValues({}, item), {
|
|
449
|
+
image: (_a = item.image) != null ? _a : resolveImage(item)
|
|
450
|
+
});
|
|
451
|
+
})
|
|
452
|
+
);
|
|
453
|
+
content = content.replace(match[0], "");
|
|
365
454
|
}
|
|
366
455
|
} catch (e) {
|
|
367
456
|
}
|
|
@@ -371,22 +460,82 @@ function MessageBubble({
|
|
|
371
460
|
}, [message.content, isUser]);
|
|
372
461
|
const allProducts = import_react5.default.useMemo(() => {
|
|
373
462
|
if (productsFromContent.length > 0) return productsFromContent;
|
|
374
|
-
const
|
|
375
|
-
const seenIds = /* @__PURE__ */ new Set();
|
|
463
|
+
const seen = /* @__PURE__ */ new Set();
|
|
376
464
|
const contentLower = message.content.toLowerCase();
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
const
|
|
382
|
-
if (
|
|
383
|
-
|
|
384
|
-
|
|
465
|
+
return productsFromSources.filter((p) => {
|
|
466
|
+
var _a;
|
|
467
|
+
const id = String((_a = p.id) != null ? _a : p.name);
|
|
468
|
+
if (seen.has(id)) return false;
|
|
469
|
+
const mentioned = contentLower.includes(p.name.toLowerCase()) || (p.brand ? contentLower.includes(p.brand.toLowerCase()) : false);
|
|
470
|
+
if (mentioned) {
|
|
471
|
+
seen.add(id);
|
|
472
|
+
return true;
|
|
385
473
|
}
|
|
386
|
-
|
|
387
|
-
|
|
474
|
+
return false;
|
|
475
|
+
});
|
|
388
476
|
}, [productsFromSources, productsFromContent, message.content]);
|
|
389
|
-
const
|
|
477
|
+
const markdownComponents = import_react5.default.useMemo(
|
|
478
|
+
() => ({
|
|
479
|
+
table: (_a) => {
|
|
480
|
+
var props = __objRest(_a, []);
|
|
481
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "overflow-x-auto my-4 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement("table", __spreadValues({ className: "w-full text-left border-collapse min-w-[400px]" }, props)));
|
|
482
|
+
},
|
|
483
|
+
thead: (_b) => {
|
|
484
|
+
var props = __objRest(_b, []);
|
|
485
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
486
|
+
"thead",
|
|
487
|
+
__spreadValues({
|
|
488
|
+
className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10"
|
|
489
|
+
}, props)
|
|
490
|
+
);
|
|
491
|
+
},
|
|
492
|
+
th: (_c) => {
|
|
493
|
+
var _d = _c, { children } = _d, props = __objRest(_d, ["children"]);
|
|
494
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
495
|
+
"th",
|
|
496
|
+
__spreadValues({
|
|
497
|
+
className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl"
|
|
498
|
+
}, props),
|
|
499
|
+
normaliseChild(children)
|
|
500
|
+
);
|
|
501
|
+
},
|
|
502
|
+
td: (_e) => {
|
|
503
|
+
var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
|
|
504
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
505
|
+
"td",
|
|
506
|
+
__spreadValues({
|
|
507
|
+
className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70"
|
|
508
|
+
}, props),
|
|
509
|
+
normaliseChild(children)
|
|
510
|
+
);
|
|
511
|
+
},
|
|
512
|
+
code(_g) {
|
|
513
|
+
var _h = _g, {
|
|
514
|
+
inline,
|
|
515
|
+
className,
|
|
516
|
+
children
|
|
517
|
+
} = _h, props = __objRest(_h, [
|
|
518
|
+
"inline",
|
|
519
|
+
"className",
|
|
520
|
+
"children"
|
|
521
|
+
]);
|
|
522
|
+
var _a;
|
|
523
|
+
const lang = (_a = /language-(\w+)/.exec(className != null ? className : "")) == null ? void 0 : _a[1];
|
|
524
|
+
if (!inline && lang === "chart") {
|
|
525
|
+
return /* @__PURE__ */ import_react5.default.createElement(
|
|
526
|
+
ChartBlock,
|
|
527
|
+
{
|
|
528
|
+
rawContent: String(children != null ? children : "").trim(),
|
|
529
|
+
primaryColor,
|
|
530
|
+
accentColor
|
|
531
|
+
}
|
|
532
|
+
);
|
|
533
|
+
}
|
|
534
|
+
return /* @__PURE__ */ import_react5.default.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
|
|
535
|
+
}
|
|
536
|
+
}),
|
|
537
|
+
[primaryColor, accentColor]
|
|
538
|
+
);
|
|
390
539
|
return /* @__PURE__ */ import_react5.default.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ import_react5.default.createElement(
|
|
391
540
|
"div",
|
|
392
541
|
{
|
|
@@ -400,68 +549,8 @@ function MessageBubble({
|
|
|
400
549
|
className: `relative px-4 py-3 rounded-2xl text-sm leading-relaxed shadow-sm dark:shadow-lg ${isUser ? "text-white rounded-tr-sm" : "bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 rounded-tl-sm"}`,
|
|
401
550
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
402
551
|
},
|
|
403
|
-
isStreaming && !message.content ? /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ import_react5.default.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ import_react5.default.createElement(
|
|
404
|
-
|
|
405
|
-
{
|
|
406
|
-
remarkPlugins: [import_remark_gfm.default],
|
|
407
|
-
components: {
|
|
408
|
-
table: (_a) => {
|
|
409
|
-
var props = __objRest(_a, []);
|
|
410
|
-
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "overflow-x-auto my-4 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement("table", __spreadValues({ className: "w-full text-left border-collapse min-w-[400px]" }, props)));
|
|
411
|
-
},
|
|
412
|
-
thead: (_b) => {
|
|
413
|
-
var props = __objRest(_b, []);
|
|
414
|
-
return /* @__PURE__ */ import_react5.default.createElement("thead", __spreadValues({ className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, props));
|
|
415
|
-
},
|
|
416
|
-
th: (_c) => {
|
|
417
|
-
var _d = _c, { children } = _d, props = __objRest(_d, ["children"]);
|
|
418
|
-
return /* @__PURE__ */ import_react5.default.createElement("th", __spreadValues({ className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" }, props), typeof children === "object" && children !== null && !Array.isArray(children) && !children.$$typeof ? JSON.stringify(children) : children);
|
|
419
|
-
},
|
|
420
|
-
td: (_e) => {
|
|
421
|
-
var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
|
|
422
|
-
return /* @__PURE__ */ import_react5.default.createElement("td", __spreadValues({ className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" }, props), typeof children === "object" && children !== null && !Array.isArray(children) && !children.$$typeof ? JSON.stringify(children) : children);
|
|
423
|
-
},
|
|
424
|
-
code(_g) {
|
|
425
|
-
var _h = _g, { inline, className, children } = _h, props = __objRest(_h, ["inline", "className", "children"]);
|
|
426
|
-
const match = /language-(\w+)/.exec(className || "");
|
|
427
|
-
const isChart = match && match[1] === "chart";
|
|
428
|
-
if (!inline && isChart) {
|
|
429
|
-
const rawContent = String(children || "").trim();
|
|
430
|
-
if (!rawContent || rawContent === "undefined") {
|
|
431
|
-
return null;
|
|
432
|
-
}
|
|
433
|
-
const sanitizeJson = (json) => {
|
|
434
|
-
return json.replace(/:\s*(\d+(\.\d+)?)\s*([\+\-\*\/])\s*(\d+(\.\d+)?)/g, (_, n1, __, op, n2) => {
|
|
435
|
-
var _a;
|
|
436
|
-
const v1 = parseFloat(n1);
|
|
437
|
-
const v2 = parseFloat(n2);
|
|
438
|
-
const ops = { "+": v1 + v2, "-": v1 - v2, "*": v1 * v2, "/": v1 / v2 };
|
|
439
|
-
return `: ${(_a = ops[op]) != null ? _a : v1}`;
|
|
440
|
-
}).replace(/([{,])\s*([a-zA-Z_][a-zA-Z0-9_]*)\s*:/g, '$1 "$2":').replace(/'([^'\\]*(?:\\.[^'\\]*)*)'/g, '"$1"').replace(/,\s*([\]}])/g, "$1").replace(/}\s*{/g, "},{").replace(/]\s*\[/g, "],[").replace(/\/\/.*$/gm, "").replace(/([{,])\s*""\s*([,}])/g, "$1$2");
|
|
441
|
-
};
|
|
442
|
-
try {
|
|
443
|
-
const sanitized = sanitizeJson(rawContent);
|
|
444
|
-
const config = JSON.parse(sanitized);
|
|
445
|
-
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "my-4 p-4 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
446
|
-
DynamicChart,
|
|
447
|
-
{
|
|
448
|
-
config,
|
|
449
|
-
primaryColor,
|
|
450
|
-
accentColor
|
|
451
|
-
}
|
|
452
|
-
));
|
|
453
|
-
} catch (err) {
|
|
454
|
-
console.error("[MessageBubble] Chart parsing failed:", err, "\nSanitized content:", sanitizeJson(rawContent));
|
|
455
|
-
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "p-4 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm border border-red-100 dark:border-red-900/30" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "font-medium mb-1" }, "Failed to render chart"), /* @__PURE__ */ import_react5.default.createElement("p", { className: "opacity-70 text-xs" }, "The generated configuration is invalid. Check console for details."));
|
|
456
|
-
}
|
|
457
|
-
}
|
|
458
|
-
return /* @__PURE__ */ import_react5.default.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
|
|
459
|
-
}
|
|
460
|
-
}
|
|
461
|
-
},
|
|
462
|
-
cleanContent || message.content
|
|
463
|
-
), isStreaming && message.content && /* @__PURE__ */ import_react5.default.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
|
|
464
|
-
), !isUser && hasProducts && /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
552
|
+
isStreaming && !message.content ? /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ import_react5.default.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ import_react5.default.createElement(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default], components: markdownComponents }, cleanContent || message.content), isStreaming && message.content && /* @__PURE__ */ import_react5.default.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
|
|
553
|
+
), !isUser && allProducts.length > 0 && /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
465
554
|
ProductCarousel,
|
|
466
555
|
{
|
|
467
556
|
products: allProducts,
|
|
@@ -481,6 +570,12 @@ function MessageBubble({
|
|
|
481
570
|
" used"
|
|
482
571
|
), showSources && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ import_react5.default.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
|
|
483
572
|
}
|
|
573
|
+
function normaliseChild(children) {
|
|
574
|
+
if (typeof children === "object" && children !== null && !Array.isArray(children) && !import_react5.default.isValidElement(children)) {
|
|
575
|
+
return JSON.stringify(children);
|
|
576
|
+
}
|
|
577
|
+
return children;
|
|
578
|
+
}
|
|
484
579
|
|
|
485
580
|
// src/components/ConfigProvider.tsx
|
|
486
581
|
var import_react6 = __toESM(require("react"));
|