@retrivora-ai/rag-engine 1.9.0 → 1.9.1
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/{ILLMProvider-BOJFz3Na.d.mts → ILLMProvider-BQyKZLnd.d.mts} +10 -0
- package/dist/{ILLMProvider-BOJFz3Na.d.ts → ILLMProvider-BQyKZLnd.d.ts} +10 -0
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +1719 -467
- package/dist/handlers/index.mjs +1718 -466
- package/dist/{index-BwpcaziY.d.ts → index-A0GqPsaG.d.ts} +1 -1
- package/dist/{index-D3V9Et2M.d.mts → index-CDftK3qs.d.mts} +1 -1
- package/dist/index.css +26 -0
- package/dist/index.d.mts +2 -2
- package/dist/index.d.ts +2 -2
- package/dist/index.js +246 -76
- package/dist/index.mjs +248 -76
- package/dist/server.d.mts +32 -5
- package/dist/server.d.ts +32 -5
- package/dist/server.js +1726 -671
- package/dist/server.mjs +1724 -669
- package/package.json +1 -1
- package/src/components/MarkdownComponents.tsx +3 -3
- package/src/components/MessageBubble.tsx +49 -2
- package/src/components/ProductCard.tsx +33 -6
- package/src/components/UIDispatcher.tsx +1 -0
- package/src/components/VisualizationRenderer.tsx +143 -11
- package/src/config/EmbeddingStrategy.ts +5 -4
- package/src/config/RagConfig.ts +10 -0
- package/src/config/serverConfig.ts +16 -1
- package/src/core/LLMRouter.ts +79 -0
- package/src/core/Pipeline.ts +262 -45
- package/src/core/ProviderRegistry.ts +6 -0
- package/src/core/QueryProcessor.ts +98 -0
- package/src/handlers/index.ts +8 -5
- package/src/hooks/useRagChat.ts +53 -17
- package/src/llm/providers/UniversalLLMAdapter.ts +110 -13
- package/src/providers/vectordb/ChromaDBProvider.ts +13 -2
- package/src/providers/vectordb/MilvusProvider.ts +18 -2
- package/src/providers/vectordb/MultiTablePostgresProvider.ts +12 -12
- package/src/providers/vectordb/PostgreSQLProvider.ts +1 -1
- package/src/providers/vectordb/QdrantProvider.ts +1 -1
- package/src/providers/vectordb/RedisProvider.ts +3 -4
- package/src/providers/vectordb/WeaviateProvider.ts +41 -3
- package/src/types/index.ts +26 -0
- package/src/utils/ProductExtractor.ts +5 -3
- package/src/utils/UITransformer.ts +1348 -489
- package/src/utils/synonyms.ts +2 -0
package/dist/index.js
CHANGED
|
@@ -395,7 +395,20 @@ var import_lucide_react4 = require("lucide-react");
|
|
|
395
395
|
var import_image = __toESM(require("next/image"));
|
|
396
396
|
var import_lucide_react3 = require("lucide-react");
|
|
397
397
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
398
|
+
function cleanProductDescription(raw) {
|
|
399
|
+
var _a;
|
|
400
|
+
if (raw === null || raw === void 0) return "";
|
|
401
|
+
const source = String(raw);
|
|
402
|
+
const bodyMatch = source.match(
|
|
403
|
+
/\bBody\s*\(HTML\)\s*:\s*([\s\S]*?)(?=\s*[,.]?\s+\b(?:Handle|Title|Vendor|Type|Tags|Published|Option\d*\s+Name|Option\d*\s+Value|Option|Variant|Image|SKU|Price|Status|Category)\b\s*:|$)/i
|
|
404
|
+
);
|
|
405
|
+
const descriptionMatch = bodyMatch != null ? bodyMatch : source.match(
|
|
406
|
+
/\b(?:Description|Summary|Details|Body)\s*:\s*([\s\S]*?)(?=\s*[,.]?\s+\b(?:Handle|Title|Vendor|Type|Tags|Published|Option\d*\s+Name|Option\d*\s+Value|Option|Variant|Image|SKU|Price|Status|Category)\b\s*:|$)/i
|
|
407
|
+
);
|
|
408
|
+
return ((_a = descriptionMatch == null ? void 0 : descriptionMatch[1]) != null ? _a : source).replace(/<[^>]*>/g, " ").replace(/ /gi, " ").replace(/&/gi, "&").replace(/"/gi, '"').replace(/'/gi, "'").replace(/\[[^\]]*TYPE[^\]]*\]/gi, " ").replace(/\b(?:Handle|Title|Vendor|Type|Tags|Published|Option\d*\s+Name|Option\d*\s+Value|Option|Variant|Image|SKU|Price|Status|Category)\s*:\s*[^,.\n:]+[,.]?/gi, " ").replace(/\bBody\s*\(HTML\)\s*:\s*/gi, " ").replace(/\b(?:Description|Summary|Details|Body|Content)\s*:\s*/gi, " ").replace(/\s+/g, " ").trim();
|
|
409
|
+
}
|
|
398
410
|
function ProductCard({ product, primaryColor = "#6366f1", onAddToCart }) {
|
|
411
|
+
const description = cleanProductDescription(product.description);
|
|
399
412
|
return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex-shrink-0 w-full bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 group", children: [
|
|
400
413
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative h-40 w-full bg-slate-100 dark:bg-white/5 flex items-center justify-center overflow-hidden", children: [
|
|
401
414
|
product.image ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
|
|
@@ -407,7 +420,7 @@ function ProductCard({ product, primaryColor = "#6366f1", onAddToCart }) {
|
|
|
407
420
|
unoptimized: true,
|
|
408
421
|
className: "object-cover group-hover:scale-105 transition-transform duration-500"
|
|
409
422
|
}
|
|
410
|
-
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-slate-400 dark:text-white/20", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ShoppingCart, { className: "w-12 h-12" }) }),
|
|
423
|
+
) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-slate-400 dark:text-white/20 cursor-pointer", onClick: () => onAddToCart == null ? void 0 : onAddToCart(product), children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ShoppingCart, { className: "w-12 h-12" }) }),
|
|
411
424
|
product.brand && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "absolute top-2 left-2 px-2 py-1 bg-white/90 dark:bg-black/60 backdrop-blur-md rounded-md text-[10px] font-bold uppercase tracking-wider text-slate-700 dark:text-white/90 shadow-sm", children: product.brand })
|
|
412
425
|
] }),
|
|
413
426
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "p-4 flex flex-col gap-2", children: [
|
|
@@ -415,13 +428,13 @@ function ProductCard({ product, primaryColor = "#6366f1", onAddToCart }) {
|
|
|
415
428
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "text-sm font-semibold text-slate-800 dark:text-white/90 line-clamp-1", children: product.name }),
|
|
416
429
|
product.price && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-sm font-bold", style: { color: primaryColor }, children: typeof product.price === "number" ? `$${product.price}` : String(product.price).match(/^[\d.]/) ? `$${product.price}` : product.price })
|
|
417
430
|
] }),
|
|
418
|
-
|
|
431
|
+
description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[11px] text-slate-500 dark:text-white/50 line-clamp-2 leading-relaxed", children: description }),
|
|
419
432
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mt-2 flex gap-2", children: [
|
|
420
433
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
|
|
421
434
|
"button",
|
|
422
435
|
{
|
|
423
436
|
onClick: () => onAddToCart == null ? void 0 : onAddToCart(product),
|
|
424
|
-
className: "flex-1 py-2 px-3 rounded-lg text-[11px] font-medium text-white shadow-sm hover:opacity-90 transition-opacity flex items-center justify-center gap-1.5",
|
|
437
|
+
className: "flex-1 py-2 px-3 rounded-lg text-[11px] font-medium text-white shadow-sm hover:opacity-90 transition-opacity flex items-center justify-center gap-1.5 cursor-pointer",
|
|
425
438
|
style: { background: primaryColor },
|
|
426
439
|
children: [
|
|
427
440
|
/* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ShoppingCart, { className: "w-3 h-3" }),
|
|
@@ -720,6 +733,9 @@ var import_jsx_runtime7 = require("react/jsx-runtime");
|
|
|
720
733
|
function getColor(index) {
|
|
721
734
|
return CHART_COLORS[index % CHART_COLORS.length];
|
|
722
735
|
}
|
|
736
|
+
function stripLeakedAnswerWrappers(raw) {
|
|
737
|
+
return raw.replace(/<prose\s+answer(?:\s+in\s+[^>]*)?>\s*([\s\S]*?)\s*<\/prose>/gi, "$1").replace(/<\/?prose(?:\s+answer)?[^>]*>/gi, "").trim();
|
|
738
|
+
}
|
|
723
739
|
function CustomTooltip({
|
|
724
740
|
active,
|
|
725
741
|
payload,
|
|
@@ -769,10 +785,20 @@ function renderVisualization(type, data, onAddToCart, primaryColor, isStreaming)
|
|
|
769
785
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PieChartView, { data, isStreaming });
|
|
770
786
|
case "bar_chart":
|
|
771
787
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BarChartView, { data, primaryColor, isStreaming });
|
|
788
|
+
case "histogram":
|
|
789
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BarChartView, { data, primaryColor, isStreaming });
|
|
790
|
+
case "horizontal_bar":
|
|
791
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BarChartView, { data, primaryColor, isStreaming, layout: "vertical" });
|
|
772
792
|
case "line_chart":
|
|
773
793
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LineChartView, { data, primaryColor, isStreaming });
|
|
794
|
+
case "scatter_plot":
|
|
795
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ScatterPlotView, { data, primaryColor, isStreaming });
|
|
774
796
|
case "radar_chart":
|
|
775
797
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RadarChartView, { data, isStreaming });
|
|
798
|
+
case "metric_card":
|
|
799
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(MetricCardView, { data, isStreaming });
|
|
800
|
+
case "geo_map":
|
|
801
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BarChartView, { data, primaryColor, isStreaming });
|
|
776
802
|
case "table":
|
|
777
803
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableView, { data, isStreaming });
|
|
778
804
|
case "product_carousel":
|
|
@@ -807,28 +833,74 @@ function PieChartView({ data, isStreaming }) {
|
|
|
807
833
|
}
|
|
808
834
|
const chartData = data.map((item) => ({
|
|
809
835
|
name: item.label,
|
|
810
|
-
value: item.value
|
|
836
|
+
value: item.value,
|
|
837
|
+
inStockCount: item.inStockCount,
|
|
838
|
+
outOfStockCount: item.outOfStockCount
|
|
811
839
|
}));
|
|
812
|
-
|
|
813
|
-
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
|
|
818
|
-
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
|
|
840
|
+
const hasStockBreakdown = chartData.some(
|
|
841
|
+
(item) => item.inStockCount !== void 0 || item.outOfStockCount !== void 0
|
|
842
|
+
);
|
|
843
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: [
|
|
844
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 280, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_recharts2.PieChart, { children: [
|
|
845
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
846
|
+
import_recharts2.Pie,
|
|
847
|
+
{
|
|
848
|
+
data: chartData,
|
|
849
|
+
dataKey: "value",
|
|
850
|
+
nameKey: "name",
|
|
851
|
+
cx: "50%",
|
|
852
|
+
cy: "50%",
|
|
853
|
+
outerRadius: "68%",
|
|
854
|
+
label: false,
|
|
855
|
+
labelLine: false,
|
|
856
|
+
children: chartData.map((_entry, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Cell, { fill: getColor(index) }, `cell-${index}`))
|
|
857
|
+
}
|
|
858
|
+
),
|
|
859
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CustomTooltip, {}) }),
|
|
860
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })
|
|
861
|
+
] }) }),
|
|
862
|
+
hasStockBreakdown && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-3 grid gap-2 sm:grid-cols-2", children: chartData.map((item, index) => {
|
|
863
|
+
var _a, _b;
|
|
864
|
+
const inStock = Number((_a = item.inStockCount) != null ? _a : 0);
|
|
865
|
+
const outOfStock = Number((_b = item.outOfStockCount) != null ? _b : 0);
|
|
866
|
+
const status = inStock > 0 ? `${inStock} in stock` : "Out of stock";
|
|
867
|
+
const mutedStatus = outOfStock > 0 ? `${outOfStock} out` : null;
|
|
868
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
869
|
+
"div",
|
|
870
|
+
{
|
|
871
|
+
className: "flex min-w-0 items-center justify-between gap-3 rounded-md border border-slate-100 px-2.5 py-2 text-xs dark:border-white/10",
|
|
872
|
+
children: [
|
|
873
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex min-w-0 items-center gap-2 text-slate-700 dark:text-white/75", children: [
|
|
874
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
875
|
+
"span",
|
|
876
|
+
{
|
|
877
|
+
className: "h-2.5 w-2.5 flex-shrink-0 rounded-full",
|
|
878
|
+
style: { background: getColor(index) }
|
|
879
|
+
}
|
|
880
|
+
),
|
|
881
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "truncate", children: item.name })
|
|
882
|
+
] }),
|
|
883
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: inStock > 0 ? "whitespace-nowrap font-medium text-emerald-600" : "whitespace-nowrap font-medium text-rose-600", children: [
|
|
884
|
+
status,
|
|
885
|
+
mutedStatus && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "ml-1 text-slate-400", children: [
|
|
886
|
+
"(",
|
|
887
|
+
mutedStatus,
|
|
888
|
+
")"
|
|
889
|
+
] })
|
|
890
|
+
] })
|
|
891
|
+
]
|
|
892
|
+
},
|
|
893
|
+
item.name
|
|
894
|
+
);
|
|
895
|
+
}) })
|
|
896
|
+
] });
|
|
830
897
|
}
|
|
831
|
-
function BarChartView({
|
|
898
|
+
function BarChartView({
|
|
899
|
+
data,
|
|
900
|
+
primaryColor,
|
|
901
|
+
isStreaming,
|
|
902
|
+
layout = "horizontal"
|
|
903
|
+
}) {
|
|
832
904
|
if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "bar" });
|
|
833
905
|
if (!Array.isArray(data) || data.length === 0) {
|
|
834
906
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid bar chart data" });
|
|
@@ -839,26 +911,66 @@ function BarChartView({ data, primaryColor, isStreaming }) {
|
|
|
839
911
|
}, item.inStockCount !== void 0 && { inStockCount: item.inStockCount }), item.outOfStockCount !== void 0 && { outOfStockCount: item.outOfStockCount }));
|
|
840
912
|
const barColor = primaryColor != null ? primaryColor : getColor(0);
|
|
841
913
|
const hasStock = chartData.some((d) => "inStockCount" in d);
|
|
842
|
-
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 260, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
|
|
857
|
-
|
|
858
|
-
|
|
859
|
-
|
|
914
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 260, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
|
|
915
|
+
import_recharts2.BarChart,
|
|
916
|
+
{
|
|
917
|
+
data: chartData,
|
|
918
|
+
layout,
|
|
919
|
+
margin: { top: 10, right: 10, left: layout === "vertical" ? 20 : -20, bottom: 0 },
|
|
920
|
+
children: [
|
|
921
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
|
|
922
|
+
layout === "vertical" ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
923
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.XAxis, { type: "number", tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }),
|
|
924
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.YAxis, { type: "category", dataKey: "category", width: 110, tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false })
|
|
925
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
926
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
|
|
927
|
+
import_recharts2.XAxis,
|
|
928
|
+
{
|
|
929
|
+
dataKey: "category",
|
|
930
|
+
tick: { fontSize: 11, fill: "#64748b" },
|
|
931
|
+
tickLine: false,
|
|
932
|
+
axisLine: { stroke: "#cbd5e1" }
|
|
933
|
+
}
|
|
934
|
+
),
|
|
935
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false })
|
|
936
|
+
] }),
|
|
937
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CustomTooltip, {}), cursor: { fill: "#f1f5f9" } }),
|
|
938
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }),
|
|
939
|
+
hasStock ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
|
|
940
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Bar, { dataKey: "inStockCount", name: "In Stock", fill: getColor(1), radius: [4, 4, 0, 0] }),
|
|
941
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Bar, { dataKey: "outOfStockCount", name: "Out of Stock", fill: getColor(3), radius: [4, 4, 0, 0] })
|
|
942
|
+
] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Bar, { dataKey: "value", name: "Value", fill: barColor, radius: [4, 4, 0, 0] })
|
|
943
|
+
]
|
|
944
|
+
}
|
|
945
|
+
) }) });
|
|
946
|
+
}
|
|
947
|
+
function ScatterPlotView({ data, primaryColor, isStreaming }) {
|
|
948
|
+
if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "bar" });
|
|
949
|
+
if (!Array.isArray(data) || data.length === 0) {
|
|
950
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid scatter plot data" });
|
|
951
|
+
}
|
|
952
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 260, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_recharts2.ScatterChart, { margin: { top: 10, right: 10, left: -20, bottom: 0 }, children: [
|
|
953
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", stroke: "#e2e8f0" }),
|
|
954
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.XAxis, { type: "number", dataKey: "x", tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }),
|
|
955
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.YAxis, { type: "number", dataKey: "y", tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }),
|
|
956
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CustomTooltip, {}), cursor: { strokeDasharray: "3 3" } }),
|
|
957
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Scatter, { name: "Value", data, fill: primaryColor != null ? primaryColor : getColor(0) })
|
|
860
958
|
] }) }) });
|
|
861
959
|
}
|
|
960
|
+
function MetricCardView({ data, isStreaming }) {
|
|
961
|
+
if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "bar" });
|
|
962
|
+
if (!data || typeof data.value !== "number") {
|
|
963
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid metric data" });
|
|
964
|
+
}
|
|
965
|
+
return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "rounded-xl border border-slate-200 bg-white p-4 shadow-sm dark:border-white/10 dark:bg-slate-900", children: [
|
|
966
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs font-medium uppercase text-slate-500 dark:text-slate-400", children: data.label }),
|
|
967
|
+
/* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mt-2 text-3xl font-semibold text-slate-900 dark:text-white", children: [
|
|
968
|
+
data.value.toLocaleString(),
|
|
969
|
+
data.unit && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "ml-1 text-base text-slate-500", children: data.unit })
|
|
970
|
+
] }),
|
|
971
|
+
data.operation && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mt-1 text-xs text-slate-500 dark:text-slate-400", children: data.operation })
|
|
972
|
+
] });
|
|
973
|
+
}
|
|
862
974
|
function LineChartView({ data, primaryColor, isStreaming }) {
|
|
863
975
|
if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "bar" });
|
|
864
976
|
if (!Array.isArray(data) || data.length === 0) {
|
|
@@ -992,7 +1104,7 @@ function CarouselView({
|
|
|
992
1104
|
) });
|
|
993
1105
|
}
|
|
994
1106
|
function TextView({ data }) {
|
|
995
|
-
const content = (data == null ? void 0 : data.content) || String(data != null ? data : "");
|
|
1107
|
+
const content = stripLeakedAnswerWrappers((data == null ? void 0 : data.content) || String(data != null ? data : ""));
|
|
996
1108
|
return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-sm text-slate-700 dark:text-slate-300 whitespace-pre-wrap leading-relaxed", children: content }) });
|
|
997
1109
|
}
|
|
998
1110
|
|
|
@@ -1430,6 +1542,14 @@ var FIELD_SYNONYMS = {
|
|
|
1430
1542
|
"in stock",
|
|
1431
1543
|
"status"
|
|
1432
1544
|
],
|
|
1545
|
+
category: [
|
|
1546
|
+
"product_category",
|
|
1547
|
+
"product category",
|
|
1548
|
+
"category_name",
|
|
1549
|
+
"category name",
|
|
1550
|
+
"department",
|
|
1551
|
+
"collection"
|
|
1552
|
+
],
|
|
1433
1553
|
description: ["summary", "content", "body", "text", "info", "details"],
|
|
1434
1554
|
link: ["url", "href", "product_url", "page_url", "link"]
|
|
1435
1555
|
};
|
|
@@ -1637,11 +1757,12 @@ function extractProductsFromSources(sources, isUser) {
|
|
|
1637
1757
|
var _a;
|
|
1638
1758
|
const m = (_a = s.metadata) != null ? _a : {};
|
|
1639
1759
|
const keys = Object.keys(m).map((k) => k.toLowerCase());
|
|
1640
|
-
const
|
|
1641
|
-
(k) => ["price", "image", "img", "thumbnail", "images", "
|
|
1760
|
+
const hasStrongProductKey = keys.some(
|
|
1761
|
+
(k) => ["price", "image", "img", "thumbnail", "images", "product", "sku", "cost"].includes(k)
|
|
1642
1762
|
);
|
|
1763
|
+
const hasProductIdentity = keys.some((k) => ["brand", "model"].includes(k)) && keys.some((k) => ["name", "title", "product_name", "product"].includes(k));
|
|
1643
1764
|
const hasPricePattern = /\$\s*\d+/.test(s.content);
|
|
1644
|
-
return
|
|
1765
|
+
return hasStrongProductKey || hasProductIdentity || hasPricePattern || m.type === "product";
|
|
1645
1766
|
}).map((s) => {
|
|
1646
1767
|
var _a, _b;
|
|
1647
1768
|
const m = (_a = s.metadata) != null ? _a : {};
|
|
@@ -1828,6 +1949,7 @@ function resolveStructuredRows(config) {
|
|
|
1828
1949
|
}
|
|
1829
1950
|
function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAddToCart, viewportSize = "large" }) {
|
|
1830
1951
|
var _a;
|
|
1952
|
+
console.log("rawContent", rawContent);
|
|
1831
1953
|
const result = import_react7.default.useMemo(() => {
|
|
1832
1954
|
try {
|
|
1833
1955
|
const clean = rawContent.replace(/^```[a-z]*\s*/i, "").replace(/```\s*$/, "").trim();
|
|
@@ -1962,12 +2084,11 @@ function createMarkdownComponents({
|
|
|
1962
2084
|
viewportSize
|
|
1963
2085
|
}) {
|
|
1964
2086
|
return {
|
|
1965
|
-
p: (
|
|
2087
|
+
// p: ({ ...props }: React.HTMLAttributes<HTMLParagraphElement>) => (
|
|
2088
|
+
// <p className="whitespace-pre-line" {...props} />
|
|
2089
|
+
// ),
|
|
2090
|
+
table: (_a) => {
|
|
1966
2091
|
var props = __objRest(_a, []);
|
|
1967
|
-
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", __spreadValues({ className: "whitespace-pre-line" }, props));
|
|
1968
|
-
},
|
|
1969
|
-
table: (_b) => {
|
|
1970
|
-
var props = __objRest(_b, []);
|
|
1971
2092
|
if (isStreaming) {
|
|
1972
2093
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "my-5 p-6 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex items-center justify-center gap-3 select-none", children: [
|
|
1973
2094
|
/* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }),
|
|
@@ -1981,8 +2102,8 @@ function createMarkdownComponents({
|
|
|
1981
2102
|
}, props)
|
|
1982
2103
|
) }) });
|
|
1983
2104
|
},
|
|
1984
|
-
thead: (
|
|
1985
|
-
var props = __objRest(
|
|
2105
|
+
thead: (_b) => {
|
|
2106
|
+
var props = __objRest(_b, []);
|
|
1986
2107
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
1987
2108
|
"thead",
|
|
1988
2109
|
__spreadValues({
|
|
@@ -1990,12 +2111,12 @@ function createMarkdownComponents({
|
|
|
1990
2111
|
}, props)
|
|
1991
2112
|
);
|
|
1992
2113
|
},
|
|
1993
|
-
tbody: (
|
|
1994
|
-
var props = __objRest(
|
|
2114
|
+
tbody: (_c) => {
|
|
2115
|
+
var props = __objRest(_c, []);
|
|
1995
2116
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
|
|
1996
2117
|
},
|
|
1997
|
-
tr: (
|
|
1998
|
-
var props = __objRest(
|
|
2118
|
+
tr: (_d) => {
|
|
2119
|
+
var props = __objRest(_d, []);
|
|
1999
2120
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2000
2121
|
"tr",
|
|
2001
2122
|
__spreadValues({
|
|
@@ -2003,8 +2124,8 @@ function createMarkdownComponents({
|
|
|
2003
2124
|
}, props)
|
|
2004
2125
|
);
|
|
2005
2126
|
},
|
|
2006
|
-
th: (
|
|
2007
|
-
var
|
|
2127
|
+
th: (_e) => {
|
|
2128
|
+
var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
|
|
2008
2129
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2009
2130
|
"th",
|
|
2010
2131
|
__spreadProps(__spreadValues({
|
|
@@ -2014,8 +2135,8 @@ function createMarkdownComponents({
|
|
|
2014
2135
|
})
|
|
2015
2136
|
);
|
|
2016
2137
|
},
|
|
2017
|
-
td: (
|
|
2018
|
-
var
|
|
2138
|
+
td: (_g) => {
|
|
2139
|
+
var _h = _g, { children } = _h, props = __objRest(_h, ["children"]);
|
|
2019
2140
|
return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
|
|
2020
2141
|
"td",
|
|
2021
2142
|
__spreadProps(__spreadValues({
|
|
@@ -2025,12 +2146,12 @@ function createMarkdownComponents({
|
|
|
2025
2146
|
})
|
|
2026
2147
|
);
|
|
2027
2148
|
},
|
|
2028
|
-
code(
|
|
2029
|
-
var
|
|
2149
|
+
code(_i) {
|
|
2150
|
+
var _j = _i, {
|
|
2030
2151
|
inline,
|
|
2031
2152
|
className,
|
|
2032
2153
|
children
|
|
2033
|
-
} =
|
|
2154
|
+
} = _j, props = __objRest(_j, [
|
|
2034
2155
|
"inline",
|
|
2035
2156
|
"className",
|
|
2036
2157
|
"children"
|
|
@@ -2080,6 +2201,16 @@ function normaliseChild(children) {
|
|
|
2080
2201
|
|
|
2081
2202
|
// src/components/MessageBubble.tsx
|
|
2082
2203
|
var import_jsx_runtime12 = require("react/jsx-runtime");
|
|
2204
|
+
function normalizePlusSeparatedLists(raw) {
|
|
2205
|
+
return raw.split("\n").map((line) => {
|
|
2206
|
+
const productListLine = /[—:]\s*\d+\s+\+\s+[A-Za-z]/.test(line) || /\b(products?|categories?|in stock|out of stock)\b/i.test(line);
|
|
2207
|
+
if (!productListLine) return line;
|
|
2208
|
+
return line.replace(/\s+\+\s+(?=[A-Za-z0-9])/g, ", ");
|
|
2209
|
+
}).join("\n");
|
|
2210
|
+
}
|
|
2211
|
+
function stripLeakedAnswerWrappers2(raw) {
|
|
2212
|
+
return raw.replace(/<prose\s+answer(?:\s+in\s+[^>]*)?>\s*([\s\S]*?)\s*<\/prose>/gi, "$1").replace(/<\/?prose(?:\s+answer)?[^>]*>/gi, "").replace(/\n{3,}/g, "\n\n").trim();
|
|
2213
|
+
}
|
|
2083
2214
|
function MessageBubble({
|
|
2084
2215
|
message,
|
|
2085
2216
|
sources,
|
|
@@ -2089,6 +2220,7 @@ function MessageBubble({
|
|
|
2089
2220
|
onAddToCart,
|
|
2090
2221
|
viewportSize = "large"
|
|
2091
2222
|
}) {
|
|
2223
|
+
var _a;
|
|
2092
2224
|
const isUser = message.role === "user";
|
|
2093
2225
|
const isCompact = viewportSize === "compact";
|
|
2094
2226
|
const isMedium = viewportSize === "medium";
|
|
@@ -2108,6 +2240,10 @@ function MessageBubble({
|
|
|
2108
2240
|
}
|
|
2109
2241
|
return false;
|
|
2110
2242
|
}, [message.uiTransformation, structuredContent.payload]);
|
|
2243
|
+
const uiTransformationType = (_a = message.uiTransformation) == null ? void 0 : _a.type;
|
|
2244
|
+
const shouldSuppressProductCarousel = Boolean(
|
|
2245
|
+
uiTransformationType && !["text", "product_carousel", "carousel"].includes(uiTransformationType)
|
|
2246
|
+
);
|
|
2111
2247
|
const shouldRenderStructuredOnly = !isUser && hasRichUI && isLikelyUiOnlyMessage(structuredContent.text);
|
|
2112
2248
|
const productsFromSources = import_react9.default.useMemo(() => {
|
|
2113
2249
|
return extractProductsFromSources(sources, isUser);
|
|
@@ -2133,6 +2269,14 @@ function MessageBubble({
|
|
|
2133
2269
|
}, [productsFromSources, productsFromContent, message.content]);
|
|
2134
2270
|
const processedMarkdown = import_react9.default.useMemo(() => {
|
|
2135
2271
|
let raw = structuredContent.payload ? structuredContent.text : cleanContent || message.content;
|
|
2272
|
+
raw = raw.replace(/\$\s*(\d+)(?!\.\d)/g, "$1");
|
|
2273
|
+
raw = normalizePlusSeparatedLists(raw);
|
|
2274
|
+
raw = stripLeakedAnswerWrappers2(raw);
|
|
2275
|
+
raw = raw.replace(/\*\*([^*\n]+)\*\*(\s*[—\-–:]\s*)/g, "$1$2");
|
|
2276
|
+
raw = raw.split("\n").filter((line, idx, arr) => {
|
|
2277
|
+
const trimmed = line.trim();
|
|
2278
|
+
return !trimmed || arr.findIndex((l) => l.trim() === trimmed) === idx;
|
|
2279
|
+
}).join("\n");
|
|
2136
2280
|
const hasStructuredUiBlock = Boolean(structuredContent.payload) || /```(?:ui|json|chart)\s*[\s\S]*?"(?:view|chartType|type|data|items|rows|products|results)"\s*:/i.test(raw);
|
|
2137
2281
|
raw = raw.replace(/([^\n])\n\|/g, "$1\n\n|").replace(/(\|[^\n]*\|)\n\n+(?=\|)/g, "$1\n");
|
|
2138
2282
|
if (!isStreaming) {
|
|
@@ -2206,11 +2350,11 @@ ${match.trim()}
|
|
|
2206
2350
|
}
|
|
2207
2351
|
),
|
|
2208
2352
|
(() => {
|
|
2209
|
-
var
|
|
2353
|
+
var _a2, _b;
|
|
2210
2354
|
if (isUser || structuredContent.payload || !message.uiTransformation) return null;
|
|
2211
2355
|
const ui = message.uiTransformation;
|
|
2212
|
-
const textContent = (_b = (
|
|
2213
|
-
const shouldShow = ui.type === "table"
|
|
2356
|
+
const textContent = (_b = (_a2 = ui.data) == null ? void 0 : _a2.content) != null ? _b : "";
|
|
2357
|
+
const shouldShow = ui.type === "table" || !["text", "table"].includes(ui.type) || ui.type === "text" && !hasRichUI && allProducts.length === 0 && textContent && !processedMarkdown.toLowerCase().includes(textContent.trim().toLowerCase());
|
|
2214
2358
|
if (!shouldShow) return null;
|
|
2215
2359
|
return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2216
2360
|
VisualizationRenderer,
|
|
@@ -2223,7 +2367,7 @@ ${match.trim()}
|
|
|
2223
2367
|
}
|
|
2224
2368
|
) });
|
|
2225
2369
|
})(),
|
|
2226
|
-
!isUser && !hasRichUI && allProducts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full mt-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2370
|
+
!isUser && !hasRichUI && !shouldSuppressProductCarousel && allProducts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full mt-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
|
|
2227
2371
|
ProductCarousel,
|
|
2228
2372
|
{
|
|
2229
2373
|
products: allProducts,
|
|
@@ -2377,6 +2521,23 @@ function useRagChat(projectId, options = {}) {
|
|
|
2377
2521
|
let uiTransformation = null;
|
|
2378
2522
|
let trace;
|
|
2379
2523
|
let buffer = "";
|
|
2524
|
+
let pendingFlush = false;
|
|
2525
|
+
const pendingContentRef = { current: "" };
|
|
2526
|
+
const flushTextUpdate = (msgId) => {
|
|
2527
|
+
pendingFlush = false;
|
|
2528
|
+
const snapshot = pendingContentRef.current;
|
|
2529
|
+
setMessages(
|
|
2530
|
+
(prev) => prev.map(
|
|
2531
|
+
(msg) => msg.id === msgId ? __spreadProps(__spreadValues({}, msg), { content: snapshot }) : msg
|
|
2532
|
+
)
|
|
2533
|
+
);
|
|
2534
|
+
};
|
|
2535
|
+
const scheduleFlush = (msgId) => {
|
|
2536
|
+
if (!pendingFlush) {
|
|
2537
|
+
pendingFlush = true;
|
|
2538
|
+
requestAnimationFrame(() => flushTextUpdate(msgId));
|
|
2539
|
+
}
|
|
2540
|
+
};
|
|
2380
2541
|
const assistantMessageId = `assistant_${Date.now()}`;
|
|
2381
2542
|
setMessages((prev) => [
|
|
2382
2543
|
...prev,
|
|
@@ -2395,28 +2556,37 @@ function useRagChat(projectId, options = {}) {
|
|
|
2395
2556
|
if (lastBoundary === -1) continue;
|
|
2396
2557
|
const complete = buffer.slice(0, lastBoundary + 2);
|
|
2397
2558
|
buffer = buffer.slice(lastBoundary + 2);
|
|
2559
|
+
let hasNonTextFrame = false;
|
|
2398
2560
|
for (const frame of parseSseChunk(complete)) {
|
|
2399
2561
|
if (frame.type === "text" && frame.text) {
|
|
2400
2562
|
assistantContent += frame.text;
|
|
2563
|
+
pendingContentRef.current = assistantContent;
|
|
2564
|
+
scheduleFlush(assistantMessageId);
|
|
2401
2565
|
} else if (frame.type === "metadata") {
|
|
2402
2566
|
sources = (_a = frame.sources) != null ? _a : [];
|
|
2567
|
+
hasNonTextFrame = true;
|
|
2403
2568
|
} else if (frame.type === "ui_transformation") {
|
|
2404
2569
|
uiTransformation = frame.data;
|
|
2570
|
+
hasNonTextFrame = true;
|
|
2405
2571
|
} else if (frame.type === "observability") {
|
|
2406
2572
|
trace = frame.data;
|
|
2573
|
+
hasNonTextFrame = true;
|
|
2407
2574
|
} else if (frame.type === "error") {
|
|
2408
2575
|
setError(frame.error || "Stream error");
|
|
2409
2576
|
}
|
|
2410
2577
|
}
|
|
2411
|
-
|
|
2412
|
-
|
|
2413
|
-
|
|
2414
|
-
|
|
2415
|
-
|
|
2416
|
-
|
|
2417
|
-
|
|
2418
|
-
|
|
2419
|
-
|
|
2578
|
+
if (hasNonTextFrame) {
|
|
2579
|
+
pendingFlush = false;
|
|
2580
|
+
setMessages(
|
|
2581
|
+
(prev) => prev.map(
|
|
2582
|
+
(msg) => msg.id === assistantMessageId ? __spreadProps(__spreadValues({}, msg), {
|
|
2583
|
+
content: assistantContent,
|
|
2584
|
+
sources: sources.length > 0 ? sources : msg.sources,
|
|
2585
|
+
uiTransformation: uiTransformation || msg.uiTransformation
|
|
2586
|
+
}) : msg
|
|
2587
|
+
)
|
|
2588
|
+
);
|
|
2589
|
+
}
|
|
2420
2590
|
}
|
|
2421
2591
|
if (buffer.trim()) {
|
|
2422
2592
|
for (const frame of parseSseChunk(buffer)) {
|