@retrivora-ai/rag-engine 1.8.0 → 1.8.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.
Files changed (46) hide show
  1. package/dist/DocumentChunker-Dh9TvmGG.d.mts +45 -0
  2. package/dist/DocumentChunker-Dh9TvmGG.d.ts +45 -0
  3. package/dist/{index-DPsQodME.d.mts → ILLMProvider-BfRgI1Xh.d.mts} +58 -1
  4. package/dist/{index-DPsQodME.d.ts → ILLMProvider-BfRgI1Xh.d.ts} +58 -1
  5. package/dist/MultiTablePostgresProvider-YY7LPNJK.mjs +8 -0
  6. package/dist/{chunk-PV3MFHWU.mjs → chunk-BFYLQYQU.mjs} +808 -439
  7. package/dist/chunk-R3RGUMHE.mjs +218 -0
  8. package/dist/handlers/index.d.mts +2 -2
  9. package/dist/handlers/index.d.ts +2 -2
  10. package/dist/handlers/index.js +995 -603
  11. package/dist/handlers/index.mjs +1 -1
  12. package/dist/{index-Bb2yEopi.d.mts → index-1Z4GuYBi.d.ts} +7 -1
  13. package/dist/{index-CkbTzj9J.d.ts → index-BV0z5mb6.d.mts} +7 -1
  14. package/dist/index.d.mts +3 -3
  15. package/dist/index.d.ts +3 -3
  16. package/dist/index.js +491 -316
  17. package/dist/index.mjs +411 -217
  18. package/dist/server.d.mts +35 -5
  19. package/dist/server.d.ts +35 -5
  20. package/dist/server.js +1146 -777
  21. package/dist/server.mjs +163 -176
  22. package/package.json +4 -2
  23. package/src/app/page.tsx +1 -2
  24. package/src/components/MessageBubble.tsx +211 -69
  25. package/src/components/ProductCard.tsx +2 -2
  26. package/src/components/VisualizationRenderer.tsx +347 -247
  27. package/src/config/RagConfig.ts +5 -0
  28. package/src/config/serverConfig.ts +3 -1
  29. package/src/core/Pipeline.ts +65 -206
  30. package/src/core/ProviderRegistry.ts +2 -2
  31. package/src/core/VectorPlugin.ts +9 -0
  32. package/src/handlers/index.ts +23 -7
  33. package/src/hooks/useRagChat.ts +2 -2
  34. package/src/llm/LLMFactory.ts +54 -2
  35. package/src/llm/providers/AnthropicProvider.ts +12 -8
  36. package/src/llm/providers/GeminiProvider.ts +188 -143
  37. package/src/llm/providers/OllamaProvider.ts +7 -3
  38. package/src/llm/providers/OpenAIProvider.ts +12 -8
  39. package/src/types/chat.ts +6 -0
  40. package/src/types/index.ts +80 -0
  41. package/src/utils/SchemaMapper.ts +129 -0
  42. package/src/utils/UITransformer.ts +491 -181
  43. package/dist/DocumentChunker-C1GEEosY.d.ts +0 -93
  44. package/dist/DocumentChunker-CFEiRopR.d.mts +0 -93
  45. package/dist/PostgreSQLProvider-BMOETDZA.mjs +0 -8
  46. package/dist/chunk-FLOSGE6A.mjs +0 -202
package/dist/index.js CHANGED
@@ -71,18 +71,17 @@ __export(index_exports, {
71
71
  module.exports = __toCommonJS(index_exports);
72
72
 
73
73
  // src/components/ChatWidget.tsx
74
- var import_react9 = __toESM(require("react"));
74
+ var import_react10 = __toESM(require("react"));
75
75
  var import_lucide_react6 = require("lucide-react");
76
76
 
77
77
  // src/components/ChatWindow.tsx
78
- var import_react8 = __toESM(require("react"));
78
+ var import_react9 = __toESM(require("react"));
79
79
  var import_lucide_react5 = require("lucide-react");
80
80
 
81
81
  // src/components/MessageBubble.tsx
82
- var import_react5 = __toESM(require("react"));
82
+ var import_react6 = __toESM(require("react"));
83
83
  var import_lucide_react4 = require("lucide-react");
84
84
  var import_react_markdown = __toESM(require("react-markdown"));
85
- var import_remark_gfm = __toESM(require("remark-gfm"));
86
85
 
87
86
  // src/components/SourceCard.tsx
88
87
  var import_react = __toESM(require("react"));
@@ -371,175 +370,232 @@ function DynamicChart({
371
370
  }
372
371
 
373
372
  // src/components/VisualizationRenderer.tsx
374
- var import_image2 = __toESM(require("next/image"));
373
+ var import_react5 = __toESM(require("react"));
374
+ var import_recharts2 = require("recharts");
375
+ var CHART_COLORS = [
376
+ "#6366f1",
377
+ // indigo
378
+ "#10b981",
379
+ // emerald
380
+ "#f59e0b",
381
+ // amber
382
+ "#ef4444",
383
+ // red
384
+ "#8b5cf6",
385
+ // purple
386
+ "#ec4899",
387
+ // pink
388
+ "#06b6d4",
389
+ // cyan
390
+ "#f97316"
391
+ // orange
392
+ ];
393
+ function getColor(index) {
394
+ return CHART_COLORS[index % CHART_COLORS.length];
395
+ }
396
+ function CustomTooltip({
397
+ active,
398
+ payload,
399
+ label
400
+ }) {
401
+ if (!active || !payload || payload.length === 0) return null;
402
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "rounded-xl border border-slate-200 bg-white px-3 py-2 text-xs shadow-xl dark:border-white/10 dark:bg-slate-950" }, label && /* @__PURE__ */ import_react5.default.createElement("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90" }, label), payload.map((entry, i) => /* @__PURE__ */ import_react5.default.createElement("div", { key: i, className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex items-center gap-1.5" }, entry.color && /* @__PURE__ */ import_react5.default.createElement(
403
+ "span",
404
+ {
405
+ className: "inline-block w-2 h-2 rounded-full flex-shrink-0",
406
+ style: { background: entry.color }
407
+ }
408
+ ), entry.name), /* @__PURE__ */ import_react5.default.createElement("span", { className: "font-medium text-slate-900 dark:text-white/90" }, entry.value))));
409
+ }
375
410
  function VisualizationRenderer({
376
411
  data,
377
- className = ""
412
+ className = "",
413
+ primaryColor,
414
+ onAddToCart
378
415
  }) {
416
+ var _a;
379
417
  if (!data) {
380
- return /* @__PURE__ */ React.createElement("div", { className: `p-4 text-gray-500 ${className}` }, "No data available for visualization");
418
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: `p-4 text-gray-500 ${className}` }, "No data available for visualization");
381
419
  }
382
- return /* @__PURE__ */ React.createElement("div", { className: `space-y-4 ${className}` }, /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ React.createElement("h3", { className: "text-lg font-semibold text-gray-900 dark:text-white" }, data.title), data.description && /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-600 dark:text-gray-400" }, data.description)), renderVisualization(data.type, data.data));
420
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: `space-y-4 ${className}` }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react5.default.createElement("h3", { className: "text-sm font-semibold text-slate-900 dark:text-white" }, data.title), data.description && data.description !== ((_a = data.data) == null ? void 0 : _a.content) && /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-xs text-slate-500 dark:text-slate-400" }, data.description)), renderVisualization(data.type, data.data, onAddToCart, primaryColor));
383
421
  }
384
- function renderVisualization(type, data) {
385
- switch (type) {
386
- case "pie_chart":
387
- return renderPieChart(data);
388
- case "bar_chart":
389
- return renderBarChart(data);
390
- case "line_chart":
391
- return renderLineChart(data);
392
- case "table":
393
- return renderTable(data);
394
- case "product_carousel":
395
- return renderProductCarousel(data);
396
- case "text":
397
- default:
398
- return renderText(data);
422
+ function renderVisualization(type, data, onAddToCart, primaryColor) {
423
+ try {
424
+ switch (type) {
425
+ case "pie_chart":
426
+ return /* @__PURE__ */ import_react5.default.createElement(PieChartView, { data });
427
+ case "bar_chart":
428
+ return /* @__PURE__ */ import_react5.default.createElement(BarChartView, { data, primaryColor });
429
+ case "line_chart":
430
+ return /* @__PURE__ */ import_react5.default.createElement(LineChartView, { data, primaryColor });
431
+ case "radar_chart":
432
+ return /* @__PURE__ */ import_react5.default.createElement(RadarChartView, { data });
433
+ case "table":
434
+ return /* @__PURE__ */ import_react5.default.createElement(TableView, { data });
435
+ case "product_carousel":
436
+ case "carousel":
437
+ return /* @__PURE__ */ import_react5.default.createElement(CarouselView, { data, onAddToCart, primaryColor });
438
+ case "text":
439
+ default:
440
+ return /* @__PURE__ */ import_react5.default.createElement(TextView, { data });
441
+ }
442
+ } catch (error) {
443
+ console.warn("[VisualizationRenderer] Rendering failed, falling back to text:", error);
444
+ return /* @__PURE__ */ import_react5.default.createElement(TextView, { data: { content: "Unable to render the requested visualization." } });
399
445
  }
400
446
  }
401
- function renderPieChart(data) {
402
- if (!Array.isArray(data)) {
403
- return /* @__PURE__ */ React.createElement("div", { className: "text-red-500" }, "Invalid pie chart data");
447
+ function PieChartView({ data }) {
448
+ if (!Array.isArray(data) || data.length === 0) {
449
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid pie chart data");
404
450
  }
405
- return /* @__PURE__ */ React.createElement("div", { className: "bg-white dark:bg-gray-800 p-4 rounded-lg shadow" }, /* @__PURE__ */ React.createElement("div", { className: "flex flex-wrap gap-2" }, data.map((item, idx) => /* @__PURE__ */ React.createElement(
406
- "div",
451
+ const chartData = data.map((item) => ({
452
+ name: item.label,
453
+ value: item.value
454
+ }));
455
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 280 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PieChart, null, /* @__PURE__ */ import_react5.default.createElement(
456
+ import_recharts2.Pie,
407
457
  {
408
- key: idx,
409
- className: "flex items-center gap-2 p-2 bg-gray-50 dark:bg-gray-700 rounded"
458
+ data: chartData,
459
+ dataKey: "value",
460
+ nameKey: "name",
461
+ cx: "50%",
462
+ cy: "50%",
463
+ outerRadius: "68%",
464
+ label: false,
465
+ labelLine: false
410
466
  },
411
- /* @__PURE__ */ React.createElement(
412
- "div",
413
- {
414
- className: "w-3 h-3 rounded-full",
415
- style: { backgroundColor: generateColor(idx) }
416
- }
417
- ),
418
- /* @__PURE__ */ React.createElement("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300" }, item.label, ": ", item.value),
419
- item.inStock !== void 0 && /* @__PURE__ */ React.createElement(
420
- "span",
421
- {
422
- className: `text-xs px-2 py-1 rounded ${item.inStock ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}`
423
- },
424
- item.inStock ? "In Stock" : "Out of Stock"
425
- )
426
- ))));
467
+ chartData.map((_entry, index) => /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Cell, { key: `cell-${index}`, fill: getColor(index) }))
468
+ ), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" }))));
427
469
  }
428
- function renderBarChart(data) {
429
- if (!Array.isArray(data)) {
430
- return /* @__PURE__ */ React.createElement("div", { className: "text-red-500" }, "Invalid bar chart data");
470
+ function BarChartView({ data, primaryColor }) {
471
+ if (!Array.isArray(data) || data.length === 0) {
472
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid bar chart data");
431
473
  }
432
- return /* @__PURE__ */ React.createElement("div", { className: "bg-white dark:bg-gray-800 p-4 rounded-lg shadow overflow-x-auto" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-3" }, data.map((item, idx) => /* @__PURE__ */ React.createElement("div", { key: idx, className: "space-y-1" }, /* @__PURE__ */ React.createElement("div", { className: "flex justify-between items-center" }, /* @__PURE__ */ React.createElement("span", { className: "text-sm font-medium text-gray-700 dark:text-gray-300" }, item.category), /* @__PURE__ */ React.createElement("span", { className: "text-sm text-gray-600 dark:text-gray-400" }, item.value)), /* @__PURE__ */ React.createElement("div", { className: "w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2" }, /* @__PURE__ */ React.createElement(
433
- "div",
474
+ const chartData = data.map((item) => __spreadValues(__spreadValues({
475
+ category: item.category,
476
+ value: item.value
477
+ }, item.inStockCount !== void 0 && { inStockCount: item.inStockCount }), item.outOfStockCount !== void 0 && { outOfStockCount: item.outOfStockCount }));
478
+ const barColor = primaryColor != null ? primaryColor : getColor(0);
479
+ const hasStock = chartData.some((d) => "inStockCount" in d);
480
+ return /* @__PURE__ */ import_react5.default.createElement("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" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 260 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.BarChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react5.default.createElement(
481
+ import_recharts2.XAxis,
434
482
  {
435
- className: "h-full rounded-full transition-all",
436
- style: {
437
- width: `${item.value / Math.max(...data.map((d) => d.value)) * 100}%`,
438
- backgroundColor: generateColor(idx)
439
- }
483
+ dataKey: "category",
484
+ tick: { fontSize: 11, fill: "#64748b" },
485
+ tickLine: false,
486
+ axisLine: { stroke: "#cbd5e1" }
440
487
  }
441
- )), item.inStock !== void 0 && /* @__PURE__ */ React.createElement(
442
- "span",
443
- {
444
- className: `text-xs px-2 py-1 rounded inline-block ${item.inStock ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}`
445
- },
446
- item.inStock ? "In Stock" : "Out of Stock"
447
- )))));
488
+ ), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null), cursor: { fill: "#f1f5f9" } }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }), hasStock ? /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Bar, { dataKey: "inStockCount", name: "In Stock", fill: getColor(1), radius: [4, 4, 0, 0] }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Bar, { dataKey: "outOfStockCount", name: "Out of Stock", fill: getColor(3), radius: [4, 4, 0, 0] })) : /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Bar, { dataKey: "value", name: "Value", fill: barColor, radius: [4, 4, 0, 0] }))));
448
489
  }
449
- function renderLineChart(data) {
450
- if (!Array.isArray(data)) {
451
- return /* @__PURE__ */ React.createElement("div", { className: "text-red-500" }, "Invalid line chart data");
490
+ function LineChartView({ data, primaryColor }) {
491
+ if (!Array.isArray(data) || data.length === 0) {
492
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid line chart data");
452
493
  }
453
- return /* @__PURE__ */ React.createElement("div", { className: "bg-white dark:bg-gray-800 p-4 rounded-lg shadow overflow-x-auto" }, /* @__PURE__ */ React.createElement("div", { className: "space-y-2" }, data.map((point, idx) => /* @__PURE__ */ React.createElement(
454
- "div",
494
+ const chartData = data.map((point) => {
495
+ var _a;
496
+ return {
497
+ label: String((_a = point.label) != null ? _a : point.timestamp),
498
+ value: Number(point.value)
499
+ };
500
+ });
501
+ const lineColor = primaryColor != null ? primaryColor : getColor(0);
502
+ return /* @__PURE__ */ import_react5.default.createElement("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" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 260 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.LineChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react5.default.createElement(
503
+ import_recharts2.XAxis,
455
504
  {
456
- key: idx,
457
- className: "flex justify-between items-center p-2 bg-gray-50 dark:bg-gray-700 rounded"
458
- },
459
- /* @__PURE__ */ React.createElement("span", { className: "text-sm text-gray-600 dark:text-gray-400" }, point.label || point.timestamp),
460
- /* @__PURE__ */ React.createElement("span", { className: "text-sm font-semibold text-gray-900 dark:text-white" }, typeof point.value === "number" ? point.value.toFixed(2) : point.value)
505
+ dataKey: "label",
506
+ tick: { fontSize: 11, fill: "#64748b" },
507
+ tickLine: false,
508
+ axisLine: { stroke: "#cbd5e1" }
509
+ }
510
+ ), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react5.default.createElement(
511
+ import_recharts2.Line,
512
+ {
513
+ type: "monotone",
514
+ dataKey: "value",
515
+ name: "Value",
516
+ stroke: lineColor,
517
+ strokeWidth: 2.5,
518
+ dot: { r: 3.5, strokeWidth: 2, fill: lineColor },
519
+ activeDot: { r: 5 }
520
+ }
461
521
  ))));
462
522
  }
463
- function renderTable(data) {
464
- if (!data.columns || !data.rows) {
465
- return /* @__PURE__ */ React.createElement("div", { className: "text-red-500" }, "Invalid table data");
523
+ function RadarChartView({ data }) {
524
+ if (!Array.isArray(data) || data.length === 0) {
525
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid radar chart data");
466
526
  }
467
- return /* @__PURE__ */ React.createElement("div", { className: "bg-white dark:bg-gray-800 rounded-lg shadow overflow-x-auto" }, /* @__PURE__ */ React.createElement("table", { className: "w-full text-sm" }, /* @__PURE__ */ React.createElement("thead", { className: "bg-gray-100 dark:bg-gray-700 border-b border-gray-200 dark:border-gray-600" }, /* @__PURE__ */ React.createElement("tr", null, data.columns.map((col, idx) => /* @__PURE__ */ React.createElement(
527
+ const productNames = Array.from(
528
+ new Set(data.flatMap((item) => Object.keys(item).filter((key) => key !== "attribute")))
529
+ );
530
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 300 }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.RadarChart, { cx: "50%", cy: "50%", outerRadius: "80%", data }, /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PolarGrid, { stroke: "#e2e8f0" }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PolarAngleAxis, { dataKey: "attribute", tick: { fontSize: 11, fill: "#64748b" } }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.PolarRadiusAxis, { tick: { fontSize: 10, fill: "#64748b" } }), productNames.map((productName, index) => /* @__PURE__ */ import_react5.default.createElement(
531
+ import_recharts2.Radar,
532
+ {
533
+ key: productName,
534
+ name: productName,
535
+ dataKey: productName,
536
+ stroke: getColor(index),
537
+ fill: getColor(index),
538
+ fillOpacity: 0.4
539
+ }
540
+ )), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react5.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react5.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }))));
541
+ }
542
+ function TableView({ data }) {
543
+ if (!(data == null ? void 0 : data.columns) || !(data == null ? void 0 : data.rows)) {
544
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid table data");
545
+ }
546
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react5.default.createElement("table", { className: "w-full text-sm border-collapse" }, /* @__PURE__ */ import_react5.default.createElement("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react5.default.createElement("tr", null, data.columns.map((col, idx) => /* @__PURE__ */ import_react5.default.createElement(
468
547
  "th",
469
548
  {
470
549
  key: idx,
471
- className: "px-4 py-2 text-left font-semibold text-gray-900 dark:text-white"
550
+ className: "px-4 py-3 text-left text-xs font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap uppercase tracking-wider"
472
551
  },
473
552
  col
474
- )))), /* @__PURE__ */ React.createElement("tbody", { className: "divide-y divide-gray-200 dark:divide-gray-600" }, data.rows.map((row, rowIdx) => /* @__PURE__ */ React.createElement(
553
+ )))), /* @__PURE__ */ import_react5.default.createElement("tbody", { className: "divide-y divide-slate-100 dark:divide-white/5" }, data.rows.map((row, rowIdx) => /* @__PURE__ */ import_react5.default.createElement(
475
554
  "tr",
476
555
  {
477
556
  key: rowIdx,
478
- className: "hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors"
557
+ className: "hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors"
479
558
  },
480
- row.map((cell, cellIdx) => /* @__PURE__ */ React.createElement(
559
+ row.map((cell, cellIdx) => /* @__PURE__ */ import_react5.default.createElement(
481
560
  "td",
482
561
  {
483
562
  key: cellIdx,
484
- className: "px-4 py-2 text-gray-700 dark:text-gray-300"
563
+ className: "px-4 py-3 text-slate-600 dark:text-white/70 text-sm"
485
564
  },
486
565
  String(cell)
487
566
  ))
488
- )))));
567
+ ))))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30" }, data.rows.length, " row", data.rows.length !== 1 ? "s" : "")));
489
568
  }
490
- function renderProductCarousel(data) {
569
+ function CarouselView({
570
+ data,
571
+ onAddToCart,
572
+ primaryColor
573
+ }) {
491
574
  if (!Array.isArray(data)) {
492
- return /* @__PURE__ */ React.createElement("div", { className: "text-red-500" }, "Invalid carousel data");
575
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid carousel data");
493
576
  }
494
- return /* @__PURE__ */ React.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ React.createElement("div", { className: "flex gap-4 pb-4" }, data.map((product) => /* @__PURE__ */ React.createElement(
495
- "div",
577
+ const products = data.map((product) => ({
578
+ id: product.id,
579
+ name: product.name,
580
+ brand: product.brand,
581
+ price: product.price,
582
+ image: product.image,
583
+ link: typeof product.link === "string" ? product.link : void 0,
584
+ description: product.description,
585
+ inStock: product.inStock
586
+ }));
587
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react5.default.createElement(
588
+ ProductCarousel,
496
589
  {
497
- key: product.id,
498
- className: "flex-shrink-0 w-64 bg-white dark:bg-gray-800 rounded-lg shadow-md overflow-hidden hover:shadow-lg transition-shadow"
499
- },
500
- product.image && /* @__PURE__ */ React.createElement("div", { className: "relative w-full h-40 bg-gray-200" }, /* @__PURE__ */ React.createElement(
501
- import_image2.default,
502
- {
503
- src: product.image,
504
- alt: product.name,
505
- fill: true,
506
- className: "object-cover",
507
- sizes: "(max-width: 768px) 100vw, (max-width: 1200px) 50vw, 33vw"
508
- }
509
- )),
510
- /* @__PURE__ */ React.createElement("div", { className: "p-4 space-y-2" }, /* @__PURE__ */ React.createElement("h4", { className: "font-semibold text-gray-900 dark:text-white line-clamp-2" }, product.name), product.brand && /* @__PURE__ */ React.createElement("p", { className: "text-xs text-gray-500 dark:text-gray-400" }, "Brand: ", product.brand), product.price && /* @__PURE__ */ React.createElement("p", { className: "text-lg font-bold text-gray-900 dark:text-white" }, "$", typeof product.price === "number" ? product.price.toFixed(2) : product.price), product.description && /* @__PURE__ */ React.createElement("p", { className: "text-sm text-gray-600 dark:text-gray-400 line-clamp-2" }, product.description), /* @__PURE__ */ React.createElement("div", { className: "flex gap-2 pt-2" }, /* @__PURE__ */ React.createElement(
511
- "span",
512
- {
513
- className: `text-xs px-2 py-1 rounded flex-1 text-center ${product.inStock ? "bg-green-100 text-green-800" : "bg-red-100 text-red-800"}`
514
- },
515
- product.inStock ? "In Stock" : "Out of Stock"
516
- )))
517
- ))));
518
- }
519
- function renderText(data) {
520
- const content = (data == null ? void 0 : data.content) || String(data);
521
- return /* @__PURE__ */ React.createElement("div", { className: "bg-white dark:bg-gray-800 p-4 rounded-lg shadow prose dark:prose-invert max-w-none" }, /* @__PURE__ */ React.createElement("p", { className: "text-gray-700 dark:text-gray-300 whitespace-pre-wrap" }, content));
590
+ products,
591
+ primaryColor: primaryColor != null ? primaryColor : "#6366f1",
592
+ onAddToCart: (p) => onAddToCart == null ? void 0 : onAddToCart(p)
593
+ }
594
+ ));
522
595
  }
523
- function generateColor(index) {
524
- const colors = [
525
- "#3B82F6",
526
- // blue
527
- "#10B981",
528
- // green
529
- "#F59E0B",
530
- // amber
531
- "#EF4444",
532
- // red
533
- "#8B5CF6",
534
- // purple
535
- "#EC4899",
536
- // pink
537
- "#06B6D4",
538
- // cyan
539
- "#F97316"
540
- // orange
541
- ];
542
- return colors[index % colors.length];
596
+ function TextView({ data }) {
597
+ const content = (data == null ? void 0 : data.content) || String(data != null ? data : "");
598
+ return /* @__PURE__ */ import_react5.default.createElement("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-sm text-slate-700 dark:text-slate-300 whitespace-pre-wrap leading-relaxed" }, content));
543
599
  }
544
600
 
545
601
  // src/components/MessageBubble.tsx
@@ -623,41 +679,51 @@ function stripStructuredUiLabels(raw) {
623
679
  );
624
680
  }
625
681
  function extractBareJsonObject(raw) {
626
- const start = raw.indexOf("{");
682
+ let start = raw.indexOf("{");
627
683
  if (start === -1) return null;
628
- let depth = 0;
629
- let inString = false;
630
- let escape = false;
631
- for (let i = start; i < raw.length; i += 1) {
632
- const ch = raw[i];
633
- if (escape) {
634
- escape = false;
635
- continue;
636
- }
637
- if (ch === "\\" && inString) {
638
- escape = true;
639
- continue;
640
- }
641
- if (ch === '"') {
642
- inString = !inString;
643
- continue;
644
- }
645
- if (inString) continue;
646
- if (ch === "{") depth += 1;
647
- if (ch === "}") {
648
- depth -= 1;
649
- if (depth === 0) {
650
- return raw.slice(start, i + 1);
684
+ let bestJson = null;
685
+ let maxLen = 0;
686
+ while (start !== -1) {
687
+ let depth = 0;
688
+ let inString = false;
689
+ let escape = false;
690
+ for (let i = start; i < raw.length; i += 1) {
691
+ const ch = raw[i];
692
+ if (escape) {
693
+ escape = false;
694
+ continue;
695
+ }
696
+ if (ch === "\\" && inString) {
697
+ escape = true;
698
+ continue;
699
+ }
700
+ if (ch === '"') {
701
+ inString = !inString;
702
+ continue;
703
+ }
704
+ if (inString) continue;
705
+ if (ch === "{") depth += 1;
706
+ else if (ch === "}") {
707
+ depth -= 1;
708
+ if (depth === 0) {
709
+ const candidate = raw.slice(start, i + 1);
710
+ if (candidate.length > maxLen) {
711
+ maxLen = candidate.length;
712
+ bestJson = candidate;
713
+ }
714
+ break;
715
+ }
651
716
  }
652
717
  }
718
+ start = raw.indexOf("{", start + 1);
653
719
  }
654
- return null;
720
+ return bestJson;
655
721
  }
656
722
  function extractStructuredPayload(raw) {
657
723
  var _a, _b;
658
724
  let working = raw;
659
725
  const fenceRegex = /```(?:[a-z]+)?\s*([\s\S]*?)```/gi;
660
- for (const match of raw.matchAll(fenceRegex)) {
726
+ for (const match of Array.from(raw.matchAll(fenceRegex))) {
661
727
  const body = (_b = (_a = match[1]) == null ? void 0 : _a.trim()) != null ? _b : "";
662
728
  if (!looksLikeStructuredPayload(body)) continue;
663
729
  working = working.replace(match[0], "");
@@ -681,21 +747,30 @@ function extractStructuredPayload(raw) {
681
747
  }
682
748
  function isLikelyUiOnlyMessage(text) {
683
749
  const trimmed = text.trim();
684
- return trimmed.length === 0 || /^(chart data|table data|visualization|visual representation|product catalog|product recommendations|catalog summary)\s*:?\s*$/i.test(trimmed);
750
+ return trimmed.length === 0 || trimmed.length < 30 || /^(chart data|table data|visualization|visual representation|product catalog|product recommendations|catalog summary|availability|inventory status|details)\s*:?\s*$/i.test(trimmed);
685
751
  }
686
752
  function resolveImage(data) {
687
753
  const isPlaceholder = (val) => typeof val === "string" && (val === "..." || val === "" || val.toLowerCase() === "null" || val.toLowerCase() === "undefined");
688
- for (const key of ["image", "img", "thumbnail"]) {
754
+ for (const key of ["image", "img", "thumbnail", "images", "product_image", "Image", "Thumbnail"]) {
689
755
  const v = data[key];
690
756
  if (typeof v === "string" && v && !isPlaceholder(v)) return v;
691
- }
692
- if (Array.isArray(data.images) && typeof data.images[0] === "string" && !isPlaceholder(data.images[0])) {
693
- return data.images[0];
757
+ if (Array.isArray(v) && typeof v[0] === "string" && v[0] && !isPlaceholder(v[0])) return v[0];
694
758
  }
695
759
  return void 0;
696
760
  }
761
+ function getMetadataValue(meta, keys) {
762
+ const searchKeys = keys.map((k) => k.toLowerCase());
763
+ const metaKeys = Object.keys(meta);
764
+ const foundKey = metaKeys.find((k) => searchKeys.includes(k.toLowerCase()));
765
+ if (foundKey) return meta[foundKey];
766
+ const partialKey = metaKeys.find((k) => {
767
+ const kLow = k.toLowerCase();
768
+ return searchKeys.some((sk) => kLow.includes(sk) || sk.includes(kLow));
769
+ });
770
+ return partialKey ? meta[partialKey] : void 0;
771
+ }
697
772
  function normaliseChild(children) {
698
- if (typeof children === "object" && children !== null && !Array.isArray(children) && !import_react5.default.isValidElement(children)) {
773
+ if (typeof children === "object" && children !== null && !Array.isArray(children) && !import_react6.default.isValidElement(children)) {
699
774
  return JSON.stringify(children);
700
775
  }
701
776
  return children;
@@ -709,7 +784,7 @@ function formatColumnLabel(value) {
709
784
  function DataTable({ config, viewportSize = "large" }) {
710
785
  const isCompact = viewportSize === "compact";
711
786
  const isMedium = viewportSize === "medium";
712
- const columns = import_react5.default.useMemo(() => {
787
+ const columns = import_react6.default.useMemo(() => {
713
788
  const rowKeys = Array.from(
714
789
  new Set(
715
790
  config.data.flatMap((row) => Object.keys(row))
@@ -739,27 +814,27 @@ function DataTable({ config, viewportSize = "large" }) {
739
814
  return rowKeys.map((key) => ({ label: formatColumnLabel(key), accessor: key }));
740
815
  }, [config]);
741
816
  if (!config.data.length || !columns.length) {
742
- return /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-xs text-slate-400 italic my-2" }, "No data to display.");
817
+ return /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-400 italic my-2" }, "No data to display.");
743
818
  }
744
819
  const formatCell = (val) => {
745
820
  if (val === null || val === void 0) return "\u2014";
746
821
  if (typeof val === "boolean") return val ? "\u2713" : "\u2717";
747
822
  return String(val);
748
823
  };
749
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "my-4 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden" }, config.title && /* @__PURE__ */ import_react5.default.createElement("div", { className: "px-4 py-2.5 bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-xs font-semibold text-slate-600 dark:text-white/70 uppercase tracking-wide" }, config.title)), /* @__PURE__ */ import_react5.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react5.default.createElement("table", { className: `w-full text-left border-collapse ${isCompact ? "min-w-[240px] text-xs" : isMedium ? "min-w-[280px] text-[13px]" : "min-w-[320px] text-sm"}` }, /* @__PURE__ */ import_react5.default.createElement("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react5.default.createElement("tr", null, columns.map((column) => /* @__PURE__ */ import_react5.default.createElement(
824
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-4 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden" }, config.title && /* @__PURE__ */ import_react6.default.createElement("div", { className: "px-4 py-2.5 bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs font-semibold text-slate-600 dark:text-white/70 uppercase tracking-wide" }, config.title)), /* @__PURE__ */ import_react6.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react6.default.createElement("table", { className: `w-full text-left border-collapse ${isCompact ? "min-w-[240px] text-xs" : isMedium ? "min-w-[280px] text-[13px]" : "min-w-[320px] text-sm"}` }, /* @__PURE__ */ import_react6.default.createElement("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react6.default.createElement("tr", null, columns.map((column) => /* @__PURE__ */ import_react6.default.createElement(
750
825
  "th",
751
826
  {
752
827
  key: column.label,
753
828
  className: `${isCompact ? "px-2.5 py-2" : "px-4 py-3"} font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap`
754
829
  },
755
830
  column.label
756
- )))), /* @__PURE__ */ import_react5.default.createElement("tbody", null, config.data.map((row, ri) => /* @__PURE__ */ import_react5.default.createElement(
831
+ )))), /* @__PURE__ */ import_react6.default.createElement("tbody", null, config.data.map((row, ri) => /* @__PURE__ */ import_react6.default.createElement(
757
832
  "tr",
758
833
  {
759
834
  key: ri,
760
835
  className: "border-b border-slate-100 dark:border-white/5 last:border-0 hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors"
761
836
  },
762
- columns.map((column) => /* @__PURE__ */ import_react5.default.createElement(
837
+ columns.map((column) => /* @__PURE__ */ import_react6.default.createElement(
763
838
  "td",
764
839
  {
765
840
  key: column.label,
@@ -767,10 +842,17 @@ function DataTable({ config, viewportSize = "large" }) {
767
842
  },
768
843
  formatCell(row[column.accessor])
769
844
  ))
770
- ))))), /* @__PURE__ */ import_react5.default.createElement("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5" }, /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30" }, config.data.length, " row", config.data.length !== 1 ? "s" : "")));
845
+ ))))), /* @__PURE__ */ import_react6.default.createElement("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5" }, /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30" }, config.data.length, " row", config.data.length !== 1 ? "s" : "")));
771
846
  }
772
847
  function normalizeTabularRows(rows, columns) {
773
848
  if (!Array.isArray(rows)) return [];
849
+ const SYNONYMS = {
850
+ name: ["product", "item", "title", "label", "heading", "product name", "item name"],
851
+ price: ["cost", "amount", "msrp", "price", "rate", "value", "price_usd"],
852
+ brand: ["manufacturer", "vendor", "make", "company", "brand_name", "supplier"],
853
+ image: ["imageUrl", "thumbnail", "img", "url", "photo", "picture", "media"],
854
+ stock: ["inventory", "quantity", "count", "availability", "stock_level", "in stock", "status"]
855
+ };
774
856
  return rows.map((row) => {
775
857
  if (Array.isArray(row)) {
776
858
  const keys = Array.isArray(columns) && columns.length > 0 ? columns : row.map((_, index) => `column_${index + 1}`);
@@ -780,7 +862,36 @@ function normalizeTabularRows(rows, columns) {
780
862
  }, {});
781
863
  }
782
864
  if (row && typeof row === "object") {
783
- return row;
865
+ const result = __spreadValues({}, row);
866
+ if (Array.isArray(columns)) {
867
+ columns.forEach((col) => {
868
+ if (result[col] !== void 0) return;
869
+ const rowKeys = Object.keys(row);
870
+ const colLower = col.toLowerCase().replace(/_/g, " ");
871
+ const foundKey = rowKeys.find((rk) => {
872
+ const rkLower = rk.toLowerCase().replace(/_/g, " ");
873
+ return rkLower === colLower || rkLower.includes(colLower) || colLower.includes(rkLower);
874
+ });
875
+ if (foundKey) {
876
+ result[col] = row[foundKey];
877
+ return;
878
+ }
879
+ for (const [target, aliases] of Object.entries(SYNONYMS)) {
880
+ const isMatch = target === colLower || aliases.some((a) => colLower.includes(a) || a.includes(colLower));
881
+ if (isMatch) {
882
+ const mappedKey = rowKeys.find((rk) => {
883
+ const rkL = rk.toLowerCase();
884
+ return rkL === target || aliases.some((a) => rkL.includes(a) || a.includes(rkL));
885
+ });
886
+ if (mappedKey) {
887
+ result[col] = row[mappedKey];
888
+ break;
889
+ }
890
+ }
891
+ }
892
+ });
893
+ }
894
+ return result;
784
895
  }
785
896
  return { value: row };
786
897
  }).filter((row) => Object.keys(row).length > 0);
@@ -800,7 +911,7 @@ function resolveStructuredRows(config) {
800
911
  }
801
912
  function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAddToCart, viewportSize = "large" }) {
802
913
  var _a;
803
- const result = import_react5.default.useMemo(() => {
914
+ const result = import_react6.default.useMemo(() => {
804
915
  if (isStreaming) return { loading: true };
805
916
  try {
806
917
  const clean = rawContent.replace(/^```[a-z]*\s*/i, "").replace(/```\s*$/, "").trim();
@@ -845,10 +956,10 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
845
956
  }
846
957
  }, [rawContent, isStreaming]);
847
958
  if ("loading" in result) {
848
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "my-4 p-8 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex flex-col items-center justify-center gap-3 animate-pulse" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-5 h-5 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic" }, "Preparing view..."));
959
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-4 p-8 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex flex-col items-center justify-center gap-3 animate-pulse" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-5 h-5 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic" }, "Preparing view..."));
849
960
  }
850
961
  if ("error" in result) {
851
- return /* @__PURE__ */ import_react5.default.createElement("pre", { className: "p-4 my-2 bg-slate-900 text-slate-100 rounded-lg text-[10px] overflow-auto max-h-40" }, /* @__PURE__ */ import_react5.default.createElement("code", null, rawContent));
962
+ return /* @__PURE__ */ import_react6.default.createElement("pre", { className: "p-4 my-2 bg-slate-900 text-slate-100 rounded-lg text-[10px] overflow-auto max-h-40" }, /* @__PURE__ */ import_react6.default.createElement("code", null, rawContent));
852
963
  }
853
964
  const { config } = result;
854
965
  const isCompact = viewportSize === "compact";
@@ -856,7 +967,7 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
856
967
  const hasDescription = typeof config.description === "string" && config.description.trim().length > 0;
857
968
  switch (config.view) {
858
969
  case "chart":
859
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: `${isCompact ? "my-4 p-3" : "my-6 p-4"} bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden` }, config.title && /* @__PURE__ */ import_react5.default.createElement("h4", { className: `${isCompact ? "text-[11px] mb-3" : "text-xs mb-4"} font-semibold text-slate-500 px-2` }, config.title), hasDescription && /* @__PURE__ */ import_react5.default.createElement("p", { className: `px-2 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react5.default.createElement(
970
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: `${isCompact ? "my-4 p-3" : "my-6 p-4"} bg-white dark:bg-slate-900 rounded-2xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden` }, config.title && /* @__PURE__ */ import_react6.default.createElement("h4", { className: `${isCompact ? "text-[11px] mb-3" : "text-xs mb-4"} font-semibold text-slate-500 px-2` }, config.title), hasDescription && /* @__PURE__ */ import_react6.default.createElement("p", { className: `px-2 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react6.default.createElement(
860
971
  DynamicChart,
861
972
  {
862
973
  config: {
@@ -870,7 +981,7 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
870
981
  accentColor,
871
982
  viewportSize
872
983
  }
873
- ), hasInsights && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mt-4 flex flex-wrap gap-2 px-2" }, (_a = config.insights) == null ? void 0 : _a.map((insight, i) => /* @__PURE__ */ import_react5.default.createElement(
984
+ ), hasInsights && /* @__PURE__ */ import_react6.default.createElement("div", { className: "mt-4 flex flex-wrap gap-2 px-2" }, (_a = config.insights) == null ? void 0 : _a.map((insight, i) => /* @__PURE__ */ import_react6.default.createElement(
874
985
  "span",
875
986
  {
876
987
  key: `insight-${i}`,
@@ -879,14 +990,14 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
879
990
  String(insight)
880
991
  ))));
881
992
  case "carousel":
882
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "my-4" }, config.title && /* @__PURE__ */ import_react5.default.createElement("h4", { className: `${isCompact ? "mb-1.5 text-[11px]" : "mb-2 text-xs"} font-semibold text-slate-500` }, config.title), hasDescription && /* @__PURE__ */ import_react5.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react5.default.createElement(ProductCarousel, { products: config.data.map((item) => {
993
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: "my-4" }, config.title && /* @__PURE__ */ import_react6.default.createElement("h4", { className: `${isCompact ? "mb-1.5 text-[11px]" : "mb-2 text-xs"} font-semibold text-slate-500` }, config.title), hasDescription && /* @__PURE__ */ import_react6.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react6.default.createElement(ProductCarousel, { products: config.data.map((item) => {
883
994
  var _a2;
884
995
  return __spreadProps(__spreadValues({}, item), {
885
996
  image: (_a2 = item.image) != null ? _a2 : typeof resolveImage === "function" ? resolveImage(item) : void 0
886
997
  });
887
998
  }), primaryColor, onAddToCart }));
888
999
  case "table":
889
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: `${isCompact ? "my-3 p-3 max-h-[320px]" : "my-4 p-4 max-h-[400px]"} bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-auto` }, config.title && /* @__PURE__ */ import_react5.default.createElement("h4", { className: `${isCompact ? "text-[11px]" : "text-xs"} font-semibold text-slate-500 mb-2` }, config.title), hasDescription && /* @__PURE__ */ import_react5.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react5.default.createElement(DataTable, { config: {
1000
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: `${isCompact ? "my-3 p-3 max-h-[320px]" : "my-4 p-4 max-h-[400px]"} bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-auto` }, config.title && /* @__PURE__ */ import_react6.default.createElement("h4", { className: `${isCompact ? "text-[11px]" : "text-xs"} font-semibold text-slate-500 mb-2` }, config.title), hasDescription && /* @__PURE__ */ import_react6.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react6.default.createElement(DataTable, { config: {
890
1001
  type: "table",
891
1002
  title: config.title,
892
1003
  description: config.description,
@@ -911,44 +1022,59 @@ function MessageBubble({
911
1022
  const isUser = message.role === "user";
912
1023
  const isCompact = viewportSize === "compact";
913
1024
  const isMedium = viewportSize === "medium";
914
- const [showSources, setShowSources] = import_react5.default.useState(false);
915
- const hasStructuredProductBlock = import_react5.default.useMemo(
916
- () => /```(?:ui|json|chart)\s*[\s\S]*?"?(?:view|type|data|products)"?\s*:\s*"?(?:carousel|products|table)"?/i.test(message.content) || /\{[\s\S]*?"?(?:view|type|data|products)"?\s*:\s*"?(?:carousel|products)"?[\s\S]*\}/i.test(message.content) && looksLikeStructuredPayload(message.content),
917
- [message.content]
918
- );
919
- const structuredContent = import_react5.default.useMemo(
1025
+ const [showSources, setShowSources] = import_react6.default.useState(false);
1026
+ const structuredContent = import_react6.default.useMemo(
920
1027
  () => isUser ? { payload: null, text: message.content } : extractStructuredPayload(message.content),
921
1028
  [isUser, message.content]
922
1029
  );
923
- const shouldRenderStructuredOnly = !isUser && Boolean(structuredContent.payload) && isLikelyUiOnlyMessage(structuredContent.text);
924
- const productsFromSources = import_react5.default.useMemo(() => {
1030
+ const hasRichUI = import_react6.default.useMemo(() => {
1031
+ if (message.uiTransformation) {
1032
+ const type = message.uiTransformation.type;
1033
+ if (type && !["text", "table"].includes(type)) return true;
1034
+ }
1035
+ if (structuredContent.payload) {
1036
+ return /"?(?:view|type|chartType)"?\s*:\s*"?(?:chart|carousel|pie|bar|line|product_carousel)"?/i.test(structuredContent.payload);
1037
+ }
1038
+ return false;
1039
+ }, [message.uiTransformation, structuredContent.payload]);
1040
+ const shouldRenderStructuredOnly = !isUser && hasRichUI && isLikelyUiOnlyMessage(structuredContent.text);
1041
+ const productsFromSources = import_react6.default.useMemo(() => {
925
1042
  if (isUser || !sources) return [];
926
1043
  return sources.filter((s) => {
927
1044
  var _a;
928
1045
  const m = (_a = s.metadata) != null ? _a : {};
929
- return m.price || m.image || m.img || m.thumbnail || m.images || m.brand || m.type === "product";
1046
+ const keys = Object.keys(m).map((k) => k.toLowerCase());
1047
+ const hasProductKey = keys.some(
1048
+ (k) => ["price", "image", "img", "thumbnail", "images", "brand", "product", "sku", "category", "model", "cost"].includes(k)
1049
+ );
1050
+ const hasPricePattern = /\$\s*\d+/.test(s.content);
1051
+ return hasProductKey || hasPricePattern || m.type === "product";
930
1052
  }).map((s) => {
931
- var _a, _b, _c, _d;
1053
+ var _a, _b;
932
1054
  const m = (_a = s.metadata) != null ? _a : {};
1055
+ const name = getMetadataValue(m, ["name", "product", "title", "label", "item"]);
1056
+ const brand = getMetadataValue(m, ["brand", "manufacturer", "vendor", "make"]);
1057
+ const price = getMetadataValue(m, ["price", "cost", "amount", "msrp", "rate"]);
933
1058
  return {
934
1059
  id: s.id,
935
- name: (_d = (_c = (_b = m.name) != null ? _b : m.title) != null ? _c : s.content.split("\n")[0]) != null ? _d : "Unknown Product",
936
- brand: m.brand,
937
- price: m.price,
1060
+ name: (_b = name != null ? name : s.content.split("\n")[0]) != null ? _b : "Unknown Product",
1061
+ brand,
1062
+ price,
938
1063
  image: resolveImage(m),
939
- link: m.link,
1064
+ link: getMetadataValue(m, ["link", "url", "product_url"]),
940
1065
  description: s.content
941
1066
  };
942
1067
  });
943
1068
  }, [sources, isUser]);
944
- const { productsFromContent, cleanContent } = import_react5.default.useMemo(() => {
1069
+ const { productsFromContent, cleanContent } = import_react6.default.useMemo(() => {
1070
+ var _a, _b;
945
1071
  if (isUser) {
946
1072
  return { productsFromContent: [], cleanContent: message.content };
947
1073
  }
948
1074
  const jsonRegex = /```(?:json|ui)?\s*([\s\S]*?)\s*```/g;
949
1075
  const products = [];
950
1076
  let content = structuredContent.text;
951
- const payloadCandidates = [structuredContent.payload, ...content.matchAll(jsonRegex).map((match) => match[1])].filter(Boolean);
1077
+ const payloadCandidates = [structuredContent.payload, ...Array.from(content.matchAll(jsonRegex)).map((match) => match[1])].filter(Boolean);
952
1078
  for (const candidate of payloadCandidates) {
953
1079
  try {
954
1080
  const data = JSON.parse(sanitizeJson(candidate));
@@ -956,9 +1082,9 @@ function MessageBubble({
956
1082
  if ((data.type === "products" || data.view === "carousel" || data.view === "table" || Array.isArray(data.products)) && itemSet) {
957
1083
  products.push(
958
1084
  ...itemSet.map((item) => {
959
- var _a;
1085
+ var _a2;
960
1086
  return __spreadProps(__spreadValues({}, item), {
961
- image: (_a = item.image) != null ? _a : resolveImage(item)
1087
+ image: (_a2 = item.image) != null ? _a2 : resolveImage(item)
962
1088
  });
963
1089
  })
964
1090
  );
@@ -967,15 +1093,15 @@ function MessageBubble({
967
1093
  }
968
1094
  }
969
1095
  if (content.includes('"type": "products"') || content.includes('"type":"products"')) {
970
- for (const match of content.matchAll(jsonRegex)) {
1096
+ for (const match of Array.from(content.matchAll(jsonRegex))) {
971
1097
  try {
972
1098
  const data = JSON.parse(sanitizeJson(match[1]));
973
1099
  if (data.type === "products" && Array.isArray(data.items)) {
974
1100
  products.push(
975
1101
  ...data.items.map((item) => {
976
- var _a;
1102
+ var _a2;
977
1103
  return __spreadProps(__spreadValues({}, item), {
978
- image: (_a = item.image) != null ? _a : resolveImage(item)
1104
+ image: (_a2 = item.image) != null ? _a2 : resolveImage(item)
979
1105
  });
980
1106
  })
981
1107
  );
@@ -985,9 +1111,42 @@ function MessageBubble({
985
1111
  }
986
1112
  }
987
1113
  }
1114
+ const bulletRegex = /(?:[•*-]\s*)?([^•\n\-\$*–—\(]+?)(?:\s*\(?Price\s*[:\-–—]?\s*)?(?:\s*[:\-–—]\s*|\s+)\$?([\d,.]+)(?:\s*USD)?/gi;
1115
+ const matches = Array.from(content.matchAll(bulletRegex));
1116
+ if (matches.length >= 2) {
1117
+ const normalize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
1118
+ for (const match of matches) {
1119
+ let name = ((_a = match[1]) == null ? void 0 : _a.trim()) || "";
1120
+ name = name.replace(/\s*\(?Price\s*$/i, "").replace(/[:\-–—]\s*$/g, "").trim();
1121
+ let price = ((_b = match[2]) == null ? void 0 : _b.trim()) || "";
1122
+ price = price.replace(/[,\s]+$/, "").trim();
1123
+ if (name && price) {
1124
+ const newProduct = {
1125
+ id: `text-prod-${name}-${price}`,
1126
+ name,
1127
+ price: `$${price}`
1128
+ };
1129
+ const normName = normalize(name);
1130
+ const sourceMatch = productsFromSources.find((s) => {
1131
+ const sn = normalize(s.name);
1132
+ return sn.includes(normName) || normName.includes(sn);
1133
+ });
1134
+ if (sourceMatch) {
1135
+ newProduct.image = sourceMatch.image;
1136
+ newProduct.brand = sourceMatch.brand;
1137
+ newProduct.link = sourceMatch.link;
1138
+ newProduct.description = sourceMatch.description;
1139
+ }
1140
+ products.push(newProduct);
1141
+ content = content.replace(match[0], `
1142
+ **${name}** \u2014 $${price}`);
1143
+ }
1144
+ }
1145
+ content = content.replace(/\n{3,}/g, "\n\n").trim();
1146
+ }
988
1147
  return { productsFromContent: products, cleanContent: content.trim() };
989
- }, [message.content, isUser, structuredContent]);
990
- const allProducts = import_react5.default.useMemo(() => {
1148
+ }, [message.content, isUser, structuredContent, productsFromSources]);
1149
+ const allProducts = import_react6.default.useMemo(() => {
991
1150
  if (productsFromContent.length > 0) return productsFromContent;
992
1151
  const seen = /* @__PURE__ */ new Set();
993
1152
  const contentLower = message.content.toLowerCase();
@@ -1003,7 +1162,7 @@ function MessageBubble({
1003
1162
  return false;
1004
1163
  });
1005
1164
  }, [productsFromSources, productsFromContent, message.content]);
1006
- const processedMarkdown = import_react5.default.useMemo(() => {
1165
+ const processedMarkdown = import_react6.default.useMemo(() => {
1007
1166
  let raw = structuredContent.payload ? structuredContent.text : cleanContent || message.content;
1008
1167
  const hasStructuredUiBlock = Boolean(structuredContent.payload) || /```(?:ui|json|chart)\s*[\s\S]*?"(?:view|chartType|type|data|items|rows|products|results)"\s*:/i.test(raw);
1009
1168
  raw = raw.replace(/([^\n])\n\|/g, "$1\n\n|").replace(/(\|[^\n]*\|)\n\n+(?=\|)/g, "$1\n");
@@ -1037,16 +1196,16 @@ ${match.trim()}
1037
1196
  }
1038
1197
  return raw;
1039
1198
  }, [cleanContent, message.content, isStreaming, structuredContent]);
1040
- const markdownComponents = import_react5.default.useMemo(
1199
+ const markdownComponents = import_react6.default.useMemo(
1041
1200
  () => ({
1042
1201
  // Wrap in not-prose so Tailwind Typography resets don't clobber our styles.
1043
1202
  // prose applies display:block and padding:0 to table/th/td — not-prose opts out.
1044
1203
  table: (_a) => {
1045
1204
  var props = __objRest(_a, []);
1046
1205
  if (isStreaming) {
1047
- return /* @__PURE__ */ import_react5.default.createElement("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" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
1206
+ return /* @__PURE__ */ import_react6.default.createElement("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" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
1048
1207
  }
1049
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "not-prose overflow-hidden my-5 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm bg-white dark:bg-slate-900/50" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react5.default.createElement(
1208
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: "not-prose overflow-hidden my-5 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm bg-white dark:bg-slate-900/50" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react6.default.createElement(
1050
1209
  "table",
1051
1210
  __spreadValues({
1052
1211
  className: "!table w-full text-left border-collapse min-w-[400px] text-sm"
@@ -1055,7 +1214,7 @@ ${match.trim()}
1055
1214
  },
1056
1215
  thead: (_b) => {
1057
1216
  var props = __objRest(_b, []);
1058
- return /* @__PURE__ */ import_react5.default.createElement(
1217
+ return /* @__PURE__ */ import_react6.default.createElement(
1059
1218
  "thead",
1060
1219
  __spreadValues({
1061
1220
  className: "!table-header-group bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10"
@@ -1064,11 +1223,11 @@ ${match.trim()}
1064
1223
  },
1065
1224
  tbody: (_c) => {
1066
1225
  var props = __objRest(_c, []);
1067
- return /* @__PURE__ */ import_react5.default.createElement("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
1226
+ return /* @__PURE__ */ import_react6.default.createElement("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
1068
1227
  },
1069
1228
  tr: (_d) => {
1070
1229
  var props = __objRest(_d, []);
1071
- return /* @__PURE__ */ import_react5.default.createElement(
1230
+ return /* @__PURE__ */ import_react6.default.createElement(
1072
1231
  "tr",
1073
1232
  __spreadValues({
1074
1233
  className: "!table-row hover:bg-slate-50/70 dark:hover:bg-white/5 transition-colors"
@@ -1077,7 +1236,7 @@ ${match.trim()}
1077
1236
  },
1078
1237
  th: (_e) => {
1079
1238
  var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
1080
- return /* @__PURE__ */ import_react5.default.createElement(
1239
+ return /* @__PURE__ */ import_react6.default.createElement(
1081
1240
  "th",
1082
1241
  __spreadValues({
1083
1242
  className: "!table-cell px-4 py-3 font-bold text-slate-700 dark:text-white/90 whitespace-nowrap text-[11px] uppercase tracking-wider text-left"
@@ -1087,7 +1246,7 @@ ${match.trim()}
1087
1246
  },
1088
1247
  td: (_g) => {
1089
1248
  var _h = _g, { children } = _h, props = __objRest(_h, ["children"]);
1090
- return /* @__PURE__ */ import_react5.default.createElement(
1249
+ return /* @__PURE__ */ import_react6.default.createElement(
1091
1250
  "td",
1092
1251
  __spreadValues({
1093
1252
  className: "!table-cell px-4 py-3 text-slate-600 dark:text-white/70 whitespace-nowrap text-sm"
@@ -1108,7 +1267,7 @@ ${match.trim()}
1108
1267
  var _a;
1109
1268
  const lang = (_a = /language-(\w+)/.exec(className != null ? className : "")) == null ? void 0 : _a[1];
1110
1269
  if (!inline && (lang === "ui" || lang === "chart")) {
1111
- return /* @__PURE__ */ import_react5.default.createElement(
1270
+ return /* @__PURE__ */ import_react6.default.createElement(
1112
1271
  UIDispatcher,
1113
1272
  {
1114
1273
  rawContent: String(children != null ? children : "").trim(),
@@ -1123,7 +1282,7 @@ ${match.trim()}
1123
1282
  if (!inline && lang === "json") {
1124
1283
  const content = String(children != null ? children : "").trim();
1125
1284
  if (looksLikeStructuredPayload(content)) {
1126
- return /* @__PURE__ */ import_react5.default.createElement(
1285
+ return /* @__PURE__ */ import_react6.default.createElement(
1127
1286
  UIDispatcher,
1128
1287
  {
1129
1288
  rawContent: content,
@@ -1139,7 +1298,7 @@ ${match.trim()}
1139
1298
  if (!inline) {
1140
1299
  const content = String(children != null ? children : "").trim();
1141
1300
  if (looksLikeStructuredPayload(content)) {
1142
- return /* @__PURE__ */ import_react5.default.createElement(
1301
+ return /* @__PURE__ */ import_react6.default.createElement(
1143
1302
  UIDispatcher,
1144
1303
  {
1145
1304
  rawContent: content,
@@ -1153,27 +1312,27 @@ ${match.trim()}
1153
1312
  }
1154
1313
  }
1155
1314
  if (!inline && lang === "table-loading") {
1156
- return /* @__PURE__ */ import_react5.default.createElement("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" }, /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
1315
+ return /* @__PURE__ */ import_react6.default.createElement("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" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
1157
1316
  }
1158
- return /* @__PURE__ */ import_react5.default.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
1317
+ return /* @__PURE__ */ import_react6.default.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
1159
1318
  }
1160
1319
  }),
1161
1320
  [primaryColor, accentColor, isStreaming, onAddToCart, viewportSize]
1162
1321
  );
1163
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: `flex ${isCompact ? "gap-2" : "gap-3"} ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ import_react5.default.createElement(
1322
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: `flex ${isCompact ? "gap-2" : "gap-3"} ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ import_react6.default.createElement(
1164
1323
  "div",
1165
1324
  {
1166
1325
  className: `flex-shrink-0 ${isCompact ? "w-7 h-7" : "w-8 h-8"} rounded-full flex items-center justify-center shadow-lg ${isUser ? "text-white" : "bg-slate-100 dark:bg-white/10 text-slate-700 dark:text-white/80"}`,
1167
1326
  style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
1168
1327
  },
1169
- isUser ? /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.User, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"} text-white` }) : /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.Bot, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"}` })
1170
- ), /* @__PURE__ */ import_react5.default.createElement("div", { className: `flex flex-col gap-1 ${isCompact ? "max-w-[94%]" : isMedium ? "max-w-[92%]" : "max-w-[90%]"} ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ import_react5.default.createElement(
1328
+ isUser ? /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.User, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"} text-white` }) : /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.Bot, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"}` })
1329
+ ), /* @__PURE__ */ import_react6.default.createElement("div", { className: `flex flex-col gap-1 ${isCompact ? "max-w-[94%]" : isMedium ? "max-w-[92%]" : "max-w-[90%]"} ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ import_react6.default.createElement(
1171
1330
  "div",
1172
1331
  {
1173
1332
  className: `relative ${isCompact ? "px-3 py-2.5 text-[13px]" : "px-4 py-3 text-sm"} rounded-2xl 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"}`,
1174
1333
  style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
1175
1334
  },
1176
- 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 ${isCompact ? "prose-xs" : "prose-sm"} max-w-none break-words ${isUser ? "prose-invert" : "dark:prose-invert"}` }, !isUser && structuredContent.payload && /* @__PURE__ */ import_react5.default.createElement(
1335
+ isStreaming && !message.content ? /* @__PURE__ */ import_react6.default.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ import_react6.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_react6.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_react6.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_react6.default.createElement("div", { className: `prose ${isCompact ? "prose-xs" : "prose-sm"} max-w-none break-words ${isUser ? "prose-invert" : "dark:prose-invert"}` }, !isUser && structuredContent.payload && /* @__PURE__ */ import_react6.default.createElement(
1177
1336
  UIDispatcher,
1178
1337
  {
1179
1338
  rawContent: structuredContent.payload,
@@ -1183,30 +1342,46 @@ ${match.trim()}
1183
1342
  onAddToCart,
1184
1343
  viewportSize
1185
1344
  }
1186
- ), !shouldRenderStructuredOnly && /* @__PURE__ */ import_react5.default.createElement(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default], components: markdownComponents }, processedMarkdown), !isUser && !structuredContent.payload && !!message.uiTransformation && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mt-4 border-t border-slate-100 dark:border-white/5 pt-4" }, /* @__PURE__ */ import_react5.default.createElement(VisualizationRenderer, { data: message.uiTransformation })), 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" }))
1187
- ), !isUser && !hasStructuredProductBlock && allProducts.length > 0 && /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ import_react5.default.createElement(
1345
+ ), !shouldRenderStructuredOnly && /* @__PURE__ */ import_react6.default.createElement(import_react_markdown.default, { components: markdownComponents }, processedMarkdown), isStreaming && message.content && /* @__PURE__ */ import_react6.default.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
1346
+ ), (() => {
1347
+ var _a, _b;
1348
+ if (isUser || structuredContent.payload || !message.uiTransformation) return null;
1349
+ const ui = message.uiTransformation;
1350
+ const textContent = (_b = (_a = ui.data) == null ? void 0 : _a.content) != null ? _b : "";
1351
+ const shouldShow = ui.type === "table" && allProducts.length === 0 || !["text", "table"].includes(ui.type) || ui.type === "text" && !hasRichUI && allProducts.length === 0 && textContent && !processedMarkdown.toLowerCase().includes(textContent.trim().toLowerCase());
1352
+ if (!shouldShow) return null;
1353
+ return /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full mt-3" }, /* @__PURE__ */ import_react6.default.createElement(
1354
+ VisualizationRenderer,
1355
+ {
1356
+ data: ui,
1357
+ primaryColor,
1358
+ onAddToCart,
1359
+ className: "rounded-3xl border border-slate-200/60 dark:border-white/10 bg-white/90 dark:bg-slate-900/80 p-4"
1360
+ }
1361
+ ));
1362
+ })(), !isUser && !hasRichUI && allProducts.length > 0 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ import_react6.default.createElement(
1188
1363
  ProductCarousel,
1189
1364
  {
1190
1365
  products: allProducts,
1191
1366
  primaryColor,
1192
1367
  onAddToCart
1193
1368
  }
1194
- )), !isUser && sources && sources.length > 0 && /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react5.default.createElement(
1369
+ )), !isUser && sources && sources.length > 0 && /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react6.default.createElement(
1195
1370
  "button",
1196
1371
  {
1197
1372
  onClick: () => setShowSources((s) => !s),
1198
1373
  className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
1199
1374
  },
1200
- showSources ? /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.ChevronRight, { className: "w-3 h-3" }),
1375
+ showSources ? /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.ChevronRight, { className: "w-3 h-3" }),
1201
1376
  sources.length,
1202
1377
  " source",
1203
1378
  sources.length !== 1 ? "s" : "",
1204
1379
  " used"
1205
- ), 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 }))))));
1380
+ ), showSources && /* @__PURE__ */ import_react6.default.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ import_react6.default.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
1206
1381
  }
1207
1382
 
1208
1383
  // src/components/ConfigProvider.tsx
1209
- var import_react6 = __toESM(require("react"));
1384
+ var import_react7 = __toESM(require("react"));
1210
1385
 
1211
1386
  // src/utils/templateUtils.ts
1212
1387
  function mergeDefined(base, override) {
@@ -1258,7 +1433,7 @@ var CHAT_SUGGESTIONS = [
1258
1433
  ];
1259
1434
 
1260
1435
  // src/components/ConfigProvider.tsx
1261
- var ConfigContext = (0, import_react6.createContext)(DEFAULT_CONFIG);
1436
+ var ConfigContext = (0, import_react7.createContext)(DEFAULT_CONFIG);
1262
1437
  function ConfigProvider({
1263
1438
  config,
1264
1439
  children
@@ -1267,14 +1442,14 @@ function ConfigProvider({
1267
1442
  projectId: (config == null ? void 0 : config.projectId) || DEFAULT_CONFIG.projectId,
1268
1443
  ui: mergeDefined(DEFAULT_CONFIG.ui, config == null ? void 0 : config.ui)
1269
1444
  };
1270
- return /* @__PURE__ */ import_react6.default.createElement(ConfigContext.Provider, { value: merged }, children);
1445
+ return /* @__PURE__ */ import_react7.default.createElement(ConfigContext.Provider, { value: merged }, children);
1271
1446
  }
1272
1447
  function useConfig() {
1273
- return (0, import_react6.useContext)(ConfigContext);
1448
+ return (0, import_react7.useContext)(ConfigContext);
1274
1449
  }
1275
1450
 
1276
1451
  // src/hooks/useRagChat.ts
1277
- var import_react7 = require("react");
1452
+ var import_react8 = require("react");
1278
1453
 
1279
1454
  // src/hooks/useStoredMessages.ts
1280
1455
  var React8 = __toESM(require("react"));
@@ -1335,14 +1510,14 @@ function useRagChat(projectId, options = {}) {
1335
1510
  } = options;
1336
1511
  const storageKey = `rag_chat_${projectId}`;
1337
1512
  const [messages, setMessages] = useStoredMessages(storageKey, persist);
1338
- const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
1339
- const [error, setError] = (0, import_react7.useState)(null);
1340
- const lastInputRef = (0, import_react7.useRef)("");
1341
- const messagesRef = (0, import_react7.useRef)(messages);
1342
- (0, import_react7.useEffect)(() => {
1513
+ const [isLoading, setIsLoading] = (0, import_react8.useState)(false);
1514
+ const [error, setError] = (0, import_react8.useState)(null);
1515
+ const lastInputRef = (0, import_react8.useRef)("");
1516
+ const messagesRef = (0, import_react8.useRef)(messages);
1517
+ (0, import_react8.useEffect)(() => {
1343
1518
  messagesRef.current = messages;
1344
1519
  }, [messages]);
1345
- const sendMessage = (0, import_react7.useCallback)(
1520
+ const sendMessage = (0, import_react8.useCallback)(
1346
1521
  async (text, opts) => {
1347
1522
  var _a, _b;
1348
1523
  const trimmed = text.trim();
@@ -1402,7 +1577,7 @@ function useRagChat(projectId, options = {}) {
1402
1577
  const complete = buffer.slice(0, lastBoundary + 2);
1403
1578
  buffer = buffer.slice(lastBoundary + 2);
1404
1579
  for (const frame of parseSseChunk(complete)) {
1405
- if (frame.type === "text") {
1580
+ if (frame.type === "text" && frame.text) {
1406
1581
  assistantContent += frame.text;
1407
1582
  } else if (frame.type === "metadata") {
1408
1583
  sources = (_a = frame.sources) != null ? _a : [];
@@ -1424,7 +1599,7 @@ function useRagChat(projectId, options = {}) {
1424
1599
  }
1425
1600
  if (buffer.trim()) {
1426
1601
  for (const frame of parseSseChunk(buffer)) {
1427
- if (frame.type === "text") assistantContent += frame.text;
1602
+ if (frame.type === "text" && frame.text) assistantContent += frame.text;
1428
1603
  else if (frame.type === "metadata") sources = (_b = frame.sources) != null ? _b : [];
1429
1604
  }
1430
1605
  }
@@ -1447,12 +1622,12 @@ function useRagChat(projectId, options = {}) {
1447
1622
  },
1448
1623
  [apiUrl, isLoading, namespace, onError, onReply, projectId, setMessages]
1449
1624
  );
1450
- const clear = (0, import_react7.useCallback)(() => {
1625
+ const clear = (0, import_react8.useCallback)(() => {
1451
1626
  setMessages([]);
1452
1627
  setError(null);
1453
1628
  if (persist) localStorage.removeItem(storageKey);
1454
1629
  }, [persist, setMessages, storageKey]);
1455
- const retry = (0, import_react7.useCallback)(async () => {
1630
+ const retry = (0, import_react8.useCallback)(async () => {
1456
1631
  if (lastInputRef.current) {
1457
1632
  const latestMessage = messagesRef.current[messagesRef.current.length - 1];
1458
1633
  await sendMessage(lastInputRef.current, {
@@ -1486,20 +1661,20 @@ function ChatWindow({
1486
1661
  }) {
1487
1662
  var _a;
1488
1663
  const { ui, projectId } = useConfig();
1489
- const [input, setInput] = (0, import_react8.useState)("");
1490
- const [mounted, setMounted] = (0, import_react8.useState)(false);
1491
- const [viewportSize, setViewportSize] = (0, import_react8.useState)("large");
1492
- const windowRef = (0, import_react8.useRef)(null);
1493
- const bottomRef = (0, import_react8.useRef)(null);
1494
- const inputRef = (0, import_react8.useRef)(null);
1664
+ const [input, setInput] = (0, import_react9.useState)("");
1665
+ const [mounted, setMounted] = (0, import_react9.useState)(false);
1666
+ const [viewportSize, setViewportSize] = (0, import_react9.useState)("large");
1667
+ const windowRef = (0, import_react9.useRef)(null);
1668
+ const bottomRef = (0, import_react9.useRef)(null);
1669
+ const inputRef = (0, import_react9.useRef)(null);
1495
1670
  const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
1496
1671
  namespace: projectId
1497
1672
  });
1498
- const [suggestions, setSuggestions] = (0, import_react8.useState)([]);
1499
- const [isSuggesting, setIsSuggesting] = (0, import_react8.useState)(false);
1500
- const [isListening, setIsListening] = (0, import_react8.useState)(false);
1501
- const recognitionRef = (0, import_react8.useRef)(null);
1502
- (0, import_react8.useEffect)(() => {
1673
+ const [suggestions, setSuggestions] = (0, import_react9.useState)([]);
1674
+ const [isSuggesting, setIsSuggesting] = (0, import_react9.useState)(false);
1675
+ const [isListening, setIsListening] = (0, import_react9.useState)(false);
1676
+ const recognitionRef = (0, import_react9.useRef)(null);
1677
+ (0, import_react9.useEffect)(() => {
1503
1678
  if (typeof window !== "undefined") {
1504
1679
  const win = window;
1505
1680
  const SpeechRecognition = win.SpeechRecognition || win.webkitSpeechRecognition;
@@ -1545,10 +1720,10 @@ function ChatWindow({
1545
1720
  }
1546
1721
  }
1547
1722
  };
1548
- (0, import_react8.useEffect)(() => {
1723
+ (0, import_react9.useEffect)(() => {
1549
1724
  setMounted(true);
1550
1725
  }, []);
1551
- (0, import_react8.useEffect)(() => {
1726
+ (0, import_react9.useEffect)(() => {
1552
1727
  const element = windowRef.current;
1553
1728
  if (!element || typeof ResizeObserver === "undefined") return;
1554
1729
  const resolveViewportSize = (width) => {
@@ -1564,13 +1739,13 @@ function ChatWindow({
1564
1739
  observer.observe(element);
1565
1740
  return () => observer.disconnect();
1566
1741
  }, []);
1567
- (0, import_react8.useEffect)(() => {
1742
+ (0, import_react9.useEffect)(() => {
1568
1743
  var _a2;
1569
1744
  if (messages.length > 0 || isLoading) {
1570
1745
  (_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
1571
1746
  }
1572
1747
  }, [messages, isLoading]);
1573
- const sendMessage = (0, import_react8.useCallback)(async () => {
1748
+ const sendMessage = (0, import_react9.useCallback)(async () => {
1574
1749
  var _a2;
1575
1750
  const text = input.trim();
1576
1751
  if (!text || isLoading) return;
@@ -1600,7 +1775,7 @@ function ChatWindow({
1600
1775
  const isEmpty = messages.length === 0;
1601
1776
  const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
1602
1777
  const isGlass = ui.visualStyle !== "solid";
1603
- (0, import_react8.useEffect)(() => {
1778
+ (0, import_react9.useEffect)(() => {
1604
1779
  if (input.trim().length < 3) {
1605
1780
  return;
1606
1781
  }
@@ -1624,84 +1799,84 @@ function ChatWindow({
1624
1799
  }, 800);
1625
1800
  return () => clearTimeout(timer);
1626
1801
  }, [input, projectId]);
1627
- return /* @__PURE__ */ import_react8.default.createElement(
1802
+ return /* @__PURE__ */ import_react9.default.createElement(
1628
1803
  "div",
1629
1804
  {
1630
1805
  ref: windowRef,
1631
1806
  className: `relative flex flex-col border border-slate-200 dark:border-white/10 shadow-2xl transition-all duration-300 ${currentRadius} ${isGlass ? "bg-white/90 dark:bg-[#0f0f1a]/90 backdrop-blur-xl" : "bg-white dark:bg-[#0f0f1a]"} ${className}`,
1632
1807
  style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
1633
1808
  },
1634
- onResizeStart && /* @__PURE__ */ import_react8.default.createElement(
1809
+ onResizeStart && /* @__PURE__ */ import_react9.default.createElement(
1635
1810
  "div",
1636
1811
  {
1637
1812
  onMouseDown: onResizeStart,
1638
1813
  className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
1639
1814
  title: "Drag to resize"
1640
1815
  },
1641
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "w-2.5 h-2.5 border-t-2 border-l-2 border-slate-300 dark:border-white/20 group-hover:border-slate-500 dark:group-hover:border-white/50 transition-colors rounded-tl-[2px]" })
1816
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: "w-2.5 h-2.5 border-t-2 border-l-2 border-slate-300 dark:border-white/20 group-hover:border-slate-500 dark:group-hover:border-white/50 transition-colors rounded-tl-[2px]" })
1642
1817
  ),
1643
- /* @__PURE__ */ import_react8.default.createElement(
1818
+ /* @__PURE__ */ import_react9.default.createElement(
1644
1819
  "div",
1645
1820
  {
1646
1821
  className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
1647
1822
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
1648
1823
  },
1649
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
1824
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
1650
1825
  // eslint-disable-next-line @next/next/no-img-element
1651
- /* @__PURE__ */ import_react8.default.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
1652
- ) : /* @__PURE__ */ import_react8.default.createElement(
1826
+ /* @__PURE__ */ import_react9.default.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
1827
+ ) : /* @__PURE__ */ import_react9.default.createElement(
1653
1828
  "div",
1654
1829
  {
1655
1830
  className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
1656
1831
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
1657
1832
  },
1658
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Bot, { className: "w-5 h-5 text-white" })
1659
- ), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
1660
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center bg-slate-100/50 dark:bg-white/5 rounded-lg p-0.5 border border-slate-200/50 dark:border-white/5" }, mounted && messages.length > 0 && /* @__PURE__ */ import_react8.default.createElement(
1833
+ /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Bot, { className: "w-5 h-5 text-white" })
1834
+ ), /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
1835
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react9.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ import_react9.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center bg-slate-100/50 dark:bg-white/5 rounded-lg p-0.5 border border-slate-200/50 dark:border-white/5" }, mounted && messages.length > 0 && /* @__PURE__ */ import_react9.default.createElement(
1661
1836
  "button",
1662
1837
  {
1663
1838
  onClick: clearHistory,
1664
1839
  title: "Clear conversation",
1665
1840
  className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-rose-500 dark:text-white/40 dark:hover:text-rose-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
1666
1841
  },
1667
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Trash2, { className: "w-3.5 h-3.5" })
1668
- ), isResized && onResetResize && /* @__PURE__ */ import_react8.default.createElement(
1842
+ /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Trash2, { className: "w-3.5 h-3.5" })
1843
+ ), isResized && onResetResize && /* @__PURE__ */ import_react9.default.createElement(
1669
1844
  "button",
1670
1845
  {
1671
1846
  onClick: onResetResize,
1672
1847
  title: "Reset to default size",
1673
1848
  className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
1674
1849
  },
1675
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.RotateCcw, { className: "w-3.5 h-3.5" })
1676
- ), onMaximize && /* @__PURE__ */ import_react8.default.createElement(
1850
+ /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.RotateCcw, { className: "w-3.5 h-3.5" })
1851
+ ), onMaximize && /* @__PURE__ */ import_react9.default.createElement(
1677
1852
  "button",
1678
1853
  {
1679
1854
  onClick: onMaximize,
1680
1855
  title: isMaximized ? "Minimize" : "Maximize",
1681
1856
  className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
1682
1857
  },
1683
- isMaximized ? /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Maximize2, { className: "w-3.5 h-3.5" })
1684
- ), showClose && onClose && /* @__PURE__ */ import_react8.default.createElement(
1858
+ isMaximized ? /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Maximize2, { className: "w-3.5 h-3.5" })
1859
+ ), showClose && onClose && /* @__PURE__ */ import_react9.default.createElement(
1685
1860
  "button",
1686
1861
  {
1687
1862
  onClick: onClose,
1688
1863
  title: "Close chat",
1689
1864
  className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
1690
1865
  },
1691
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.X, { className: "w-4 h-4" })
1866
+ /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.X, { className: "w-4 h-4" })
1692
1867
  )))
1693
1868
  ),
1694
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent" }, !mounted || isEmpty ? (
1869
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent" }, !mounted || isEmpty ? (
1695
1870
  /* Welcome state */
1696
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ import_react8.default.createElement(
1871
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ import_react9.default.createElement(
1697
1872
  "div",
1698
1873
  {
1699
1874
  className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
1700
1875
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
1701
1876
  },
1702
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Sparkles, { className: "w-8 h-8 text-white" })
1703
- ), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
1704
- (suggestion) => /* @__PURE__ */ import_react8.default.createElement(
1877
+ /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Sparkles, { className: "w-8 h-8 text-white" })
1878
+ ), /* @__PURE__ */ import_react9.default.createElement("div", null, /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
1879
+ (suggestion) => /* @__PURE__ */ import_react9.default.createElement(
1705
1880
  "button",
1706
1881
  {
1707
1882
  key: suggestion,
@@ -1715,7 +1890,7 @@ function ChatWindow({
1715
1890
  suggestion
1716
1891
  )
1717
1892
  )))
1718
- ) : messages.map((msg, index) => /* @__PURE__ */ import_react8.default.createElement(
1893
+ ) : messages.map((msg, index) => /* @__PURE__ */ import_react9.default.createElement(
1719
1894
  MessageBubble,
1720
1895
  {
1721
1896
  key: msg.id,
@@ -1727,7 +1902,7 @@ function ChatWindow({
1727
1902
  onAddToCart,
1728
1903
  viewportSize
1729
1904
  }
1730
- )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ import_react8.default.createElement(
1905
+ )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ import_react9.default.createElement(
1731
1906
  MessageBubble,
1732
1907
  {
1733
1908
  message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
@@ -1737,8 +1912,8 @@ function ChatWindow({
1737
1912
  onAddToCart,
1738
1913
  viewportSize
1739
1914
  }
1740
- ), error && /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3" }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ import_react8.default.createElement("span", null, error)), /* @__PURE__ */ import_react8.default.createElement("div", { ref: bottomRef })),
1741
- /* @__PURE__ */ import_react8.default.createElement("div", { className: `px-4 pb-4 pt-2 border-t border-slate-200 dark:border-white/10 ${isGlass ? "bg-transparent" : "bg-white dark:bg-[#0f0f1a]"}` }, (suggestions.length > 0 || isSuggesting) && !isLoading && /* @__PURE__ */ import_react8.default.createElement("div", { className: "mb-3 flex flex-wrap gap-2 animate-in fade-in slide-in-from-bottom-2 duration-300" }, suggestions.map((suggestion) => /* @__PURE__ */ import_react8.default.createElement(
1915
+ ), error && /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3" }, /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ import_react9.default.createElement("span", null, error)), /* @__PURE__ */ import_react9.default.createElement("div", { ref: bottomRef })),
1916
+ /* @__PURE__ */ import_react9.default.createElement("div", { className: `px-4 pb-4 pt-2 border-t border-slate-200 dark:border-white/10 ${isGlass ? "bg-transparent" : "bg-white dark:bg-[#0f0f1a]"}` }, (suggestions.length > 0 || isSuggesting) && !isLoading && /* @__PURE__ */ import_react9.default.createElement("div", { className: "mb-3 flex flex-wrap gap-2 animate-in fade-in slide-in-from-bottom-2 duration-300" }, suggestions.map((suggestion) => /* @__PURE__ */ import_react9.default.createElement(
1742
1917
  "button",
1743
1918
  {
1744
1919
  key: suggestion,
@@ -1750,9 +1925,9 @@ function ChatWindow({
1750
1925
  },
1751
1926
  className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/90 hover:border-slate-300 dark:hover:border-white/20 transition-all shadow-sm cursor-pointer group"
1752
1927
  },
1753
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3 text-amber-400" }),
1928
+ /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3 text-amber-400" }),
1754
1929
  suggestion
1755
- )), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium text-slate-400 dark:text-white/30 animate-pulse" }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ import_react8.default.createElement("div", { className: `flex items-end gap-2 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 p-2 focus-within:border-slate-300 dark:focus-within:border-white/20 transition-all ${ui.borderRadius === "full" ? "rounded-3xl" : "rounded-2xl"}` }, /* @__PURE__ */ import_react8.default.createElement(
1930
+ )), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ import_react9.default.createElement("div", { className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium text-slate-400 dark:text-white/30 animate-pulse" }, /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ import_react9.default.createElement("div", { className: `flex items-end gap-2 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 p-2 focus-within:border-slate-300 dark:focus-within:border-white/20 transition-all ${ui.borderRadius === "full" ? "rounded-3xl" : "rounded-2xl"}` }, /* @__PURE__ */ import_react9.default.createElement(
1756
1931
  "textarea",
1757
1932
  {
1758
1933
  ref: inputRef,
@@ -1771,7 +1946,7 @@ function ChatWindow({
1771
1946
  className: "flex-1 bg-transparent text-slate-900 dark:text-white/90 placeholder-slate-400 dark:placeholder-white/30 text-sm resize-none outline-none py-1.5 px-2 max-h-32 leading-relaxed disabled:opacity-50",
1772
1947
  style: { scrollbarWidth: "none" }
1773
1948
  }
1774
- ), ui.enableVoiceInput !== false && /* @__PURE__ */ import_react8.default.createElement(
1949
+ ), ui.enableVoiceInput !== false && /* @__PURE__ */ import_react9.default.createElement(
1775
1950
  "button",
1776
1951
  {
1777
1952
  type: "button",
@@ -1780,8 +1955,8 @@ function ChatWindow({
1780
1955
  className: `flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:active:scale-100 ${isListening ? "bg-rose-500 text-white animate-pulse shadow-md shadow-rose-500/20" : "text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10"}`,
1781
1956
  title: isListening ? "Stop listening" : "Start voice input"
1782
1957
  },
1783
- isListening ? /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Mic, { className: "w-4 h-4" })
1784
- ), /* @__PURE__ */ import_react8.default.createElement(
1958
+ isListening ? /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.Mic, { className: "w-4 h-4" })
1959
+ ), /* @__PURE__ */ import_react9.default.createElement(
1785
1960
  "button",
1786
1961
  {
1787
1962
  onClick: sendMessage,
@@ -1792,8 +1967,8 @@ function ChatWindow({
1792
1967
  // slate-400/20 for light mode disabled
1793
1968
  }
1794
1969
  },
1795
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.ArrowUp, { className: "w-4 h-4 text-white" })
1796
- )), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2" }, "Press Enter to send \xB7 Shift+Enter for new line"))
1970
+ /* @__PURE__ */ import_react9.default.createElement(import_lucide_react5.ArrowUp, { className: "w-4 h-4 text-white" })
1971
+ )), /* @__PURE__ */ import_react9.default.createElement("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2" }, "Press Enter to send \xB7 Shift+Enter for new line"))
1797
1972
  );
1798
1973
  }
1799
1974
 
@@ -1801,12 +1976,12 @@ function ChatWindow({
1801
1976
  var DEFAULT_DIMENSIONS = { width: 380, height: 600 };
1802
1977
  function ChatWidget({ position = "bottom-right", onAddToCart }) {
1803
1978
  const { ui } = useConfig();
1804
- const [isOpen, setIsOpen] = (0, import_react9.useState)(false);
1805
- const [hasUnread, setHasUnread] = (0, import_react9.useState)(false);
1806
- const [dimensions, setDimensions] = (0, import_react9.useState)(DEFAULT_DIMENSIONS);
1807
- const [isResizing, setIsResizing] = (0, import_react9.useState)(false);
1808
- const [isMaximized, setIsMaximized] = (0, import_react9.useState)(false);
1809
- const [prevDimensions, setPrevDimensions] = (0, import_react9.useState)(DEFAULT_DIMENSIONS);
1979
+ const [isOpen, setIsOpen] = (0, import_react10.useState)(false);
1980
+ const [hasUnread, setHasUnread] = (0, import_react10.useState)(false);
1981
+ const [dimensions, setDimensions] = (0, import_react10.useState)(DEFAULT_DIMENSIONS);
1982
+ const [isResizing, setIsResizing] = (0, import_react10.useState)(false);
1983
+ const [isMaximized, setIsMaximized] = (0, import_react10.useState)(false);
1984
+ const [prevDimensions, setPrevDimensions] = (0, import_react10.useState)(DEFAULT_DIMENSIONS);
1810
1985
  if (ui.showWidget === false) return null;
1811
1986
  const positionClass = position === "bottom-left" ? "bottom-6 left-6" : "bottom-6 right-6";
1812
1987
  const windowPositionClass = position === "bottom-left" ? "bottom-20 left-6" : "bottom-20 right-6";
@@ -1856,7 +2031,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
1856
2031
  }
1857
2032
  };
1858
2033
  const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
1859
- return /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(
2034
+ return /* @__PURE__ */ import_react10.default.createElement(import_react10.default.Fragment, null, /* @__PURE__ */ import_react10.default.createElement(
1860
2035
  "div",
1861
2036
  {
1862
2037
  className: `fixed z-[9998] max-w-[calc(100vw-3rem)] ease-in-out ${windowPositionClass} ${isOpen ? "opacity-100 translate-y-0 pointer-events-auto" : "opacity-0 translate-y-4 pointer-events-none"} ${isResizing ? "" : "transition-all duration-300"}`,
@@ -1866,7 +2041,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
1866
2041
  maxHeight: "calc(100vh - 6rem)"
1867
2042
  }
1868
2043
  },
1869
- /* @__PURE__ */ import_react9.default.createElement(
2044
+ /* @__PURE__ */ import_react10.default.createElement(
1870
2045
  ChatWindow,
1871
2046
  {
1872
2047
  className: "h-full relative z-10",
@@ -1880,13 +2055,13 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
1880
2055
  onAddToCart
1881
2056
  }
1882
2057
  ),
1883
- /* @__PURE__ */ import_react9.default.createElement(
2058
+ /* @__PURE__ */ import_react10.default.createElement(
1884
2059
  "div",
1885
2060
  {
1886
2061
  className: `absolute -bottom-1.5 w-4 h-4 rotate-45 border-r border-b border-slate-200 dark:border-white/10 z-0 ${ui.visualStyle === "solid" ? "bg-white dark:bg-[#0f0f1a]" : "bg-white/90 dark:bg-[#0f0f1a]/90 backdrop-blur-xl"} ${position === "bottom-left" ? "left-5" : "right-5"}`
1887
2062
  }
1888
2063
  )
1889
- ), /* @__PURE__ */ import_react9.default.createElement(
2064
+ ), /* @__PURE__ */ import_react10.default.createElement(
1890
2065
  "button",
1891
2066
  {
1892
2067
  onClick: isOpen ? () => setIsOpen(false) : handleOpen,
@@ -1894,32 +2069,32 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
1894
2069
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
1895
2070
  "aria-label": "Open chat"
1896
2071
  },
1897
- /* @__PURE__ */ import_react9.default.createElement(
2072
+ /* @__PURE__ */ import_react10.default.createElement(
1898
2073
  "span",
1899
2074
  {
1900
2075
  className: "absolute inset-0 rounded-full animate-ping opacity-20",
1901
2076
  style: { background: ui.primaryColor }
1902
2077
  }
1903
2078
  ),
1904
- /* @__PURE__ */ import_react9.default.createElement(
2079
+ /* @__PURE__ */ import_react10.default.createElement(
1905
2080
  "span",
1906
2081
  {
1907
2082
  className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
1908
2083
  },
1909
- isOpen ? /* @__PURE__ */ import_react9.default.createElement(import_lucide_react6.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ import_react9.default.createElement(import_lucide_react6.MessageSquare, { className: "w-6 h-6 text-white" })
2084
+ isOpen ? /* @__PURE__ */ import_react10.default.createElement(import_lucide_react6.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ import_react10.default.createElement(import_lucide_react6.MessageSquare, { className: "w-6 h-6 text-white" })
1910
2085
  ),
1911
- hasUnread && !isOpen && /* @__PURE__ */ import_react9.default.createElement("span", { className: "absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white" }, "1")
2086
+ hasUnread && !isOpen && /* @__PURE__ */ import_react10.default.createElement("span", { className: "absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white" }, "1")
1912
2087
  ));
1913
2088
  }
1914
2089
 
1915
2090
  // src/components/DocumentUpload.tsx
1916
- var import_react10 = __toESM(require("react"));
2091
+ var import_react11 = __toESM(require("react"));
1917
2092
  var import_lucide_react7 = require("lucide-react");
1918
2093
  function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
1919
2094
  const { ui } = useConfig();
1920
- const [fileStates, setFileStates] = (0, import_react10.useState)([]);
1921
- const [isDragging, setIsDragging] = (0, import_react10.useState)(false);
1922
- const fileInputRef = (0, import_react10.useRef)(null);
2095
+ const [fileStates, setFileStates] = (0, import_react11.useState)([]);
2096
+ const [isDragging, setIsDragging] = (0, import_react11.useState)(false);
2097
+ const fileInputRef = (0, import_react11.useRef)(null);
1923
2098
  const addFiles = (files) => {
1924
2099
  const newStates = files.map((file) => ({ file, status: "idle" }));
1925
2100
  setFileStates((prev) => [...prev, ...newStates]);
@@ -1969,7 +2144,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
1969
2144
  };
1970
2145
  const isUploading = fileStates.some((s) => s.status === "uploading");
1971
2146
  const hasIdle = fileStates.some((s) => s.status === "idle");
1972
- return /* @__PURE__ */ import_react10.default.createElement(
2147
+ return /* @__PURE__ */ import_react11.default.createElement(
1973
2148
  "div",
1974
2149
  {
1975
2150
  className: `p-6 border-2 border-dashed transition-all duration-300 rounded-2xl ${isDragging ? "border-emerald-500 bg-emerald-50/50 dark:bg-emerald-500/5" : "border-slate-200 dark:border-white/10 bg-white dark:bg-white/5"} ${className}`,
@@ -1977,14 +2152,14 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
1977
2152
  onDragLeave,
1978
2153
  onDrop
1979
2154
  },
1980
- /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ import_react10.default.createElement(
2155
+ /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ import_react11.default.createElement(
1981
2156
  "div",
1982
2157
  {
1983
2158
  className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
1984
2159
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
1985
2160
  },
1986
- /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
1987
- ), /* @__PURE__ */ import_react10.default.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs" }, "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data."), /* @__PURE__ */ import_react10.default.createElement(
2161
+ /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
2162
+ ), /* @__PURE__ */ import_react11.default.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs" }, "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data."), /* @__PURE__ */ import_react11.default.createElement(
1988
2163
  "button",
1989
2164
  {
1990
2165
  onClick: () => {
@@ -2000,7 +2175,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
2000
2175
  }
2001
2176
  },
2002
2177
  "Select Files"
2003
- ), /* @__PURE__ */ import_react10.default.createElement(
2178
+ ), /* @__PURE__ */ import_react11.default.createElement(
2004
2179
  "input",
2005
2180
  {
2006
2181
  ref: fileInputRef,
@@ -2011,22 +2186,22 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
2011
2186
  accept: ".pdf,.docx,.txt,.md,.json,.csv"
2012
2187
  }
2013
2188
  )),
2014
- fileStates.length > 0 && /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ import_react10.default.createElement(
2189
+ fileStates.length > 0 && /* @__PURE__ */ import_react11.default.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ import_react11.default.createElement(
2015
2190
  "div",
2016
2191
  {
2017
2192
  key: i,
2018
2193
  className: "flex items-center justify-between p-3 rounded-xl bg-slate-50 dark:bg-white/5 border border-slate-100 dark:border-white/10"
2019
2194
  },
2020
- /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ import_react10.default.createElement("div", { className: "truncate" }, /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
2021
- /* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ import_react10.default.createElement("div", { title: state.error }, /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ import_react10.default.createElement(
2195
+ /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ import_react11.default.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ import_react11.default.createElement("div", { className: "truncate" }, /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
2196
+ /* @__PURE__ */ import_react11.default.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ import_react11.default.createElement("div", { title: state.error }, /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ import_react11.default.createElement(
2022
2197
  "button",
2023
2198
  {
2024
2199
  onClick: () => removeFile(i),
2025
2200
  className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
2026
2201
  },
2027
- /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.X, { className: "w-3.5 h-3.5 text-slate-400" })
2202
+ /* @__PURE__ */ import_react11.default.createElement(import_lucide_react7.X, { className: "w-3.5 h-3.5 text-slate-400" })
2028
2203
  ))
2029
- )), hasIdle && !isUploading && /* @__PURE__ */ import_react10.default.createElement(
2204
+ )), hasIdle && !isUploading && /* @__PURE__ */ import_react11.default.createElement(
2030
2205
  "button",
2031
2206
  {
2032
2207
  onClick: uploadFiles,