@retrivora-ai/rag-engine 1.8.2 → 1.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/dist/handlers/index.js +142 -16
  2. package/dist/handlers/index.mjs +5848 -17
  3. package/dist/index.d.mts +9 -15
  4. package/dist/index.d.ts +9 -15
  5. package/dist/index.js +1355 -919
  6. package/dist/index.mjs +1437 -896
  7. package/dist/server.d.mts +6 -0
  8. package/dist/server.d.ts +6 -0
  9. package/dist/server.js +171 -17
  10. package/dist/server.mjs +5923 -68
  11. package/package.json +6 -6
  12. package/src/app/globals.css +35 -11
  13. package/src/components/ChatWidget.tsx +0 -1
  14. package/src/components/MarkdownComponents.tsx +3 -0
  15. package/src/components/MessageBubble.tsx +3 -2
  16. package/src/components/ObservabilityPanel.tsx +1 -1
  17. package/src/components/UIDispatcher.tsx +0 -3
  18. package/src/config/ConfigBuilder.ts +38 -1
  19. package/src/core/LangChainAgent.ts +1 -4
  20. package/src/core/Pipeline.ts +31 -18
  21. package/src/core/QueryProcessor.ts +65 -0
  22. package/src/rag/Reranker.ts +99 -6
  23. package/src/utils/ProductExtractor.ts +3 -3
  24. package/dist/ChromaDBProvider-MIDOR4FW.mjs +0 -8
  25. package/dist/MilvusProvider-U7SKC27V.mjs +0 -8
  26. package/dist/MongoDBProvider-YNKC7EJ6.mjs +0 -8
  27. package/dist/MultiTablePostgresProvider-ZLGSKTJR.mjs +0 -8
  28. package/dist/PineconeProvider-QZNRKTN2.mjs +0 -8
  29. package/dist/QdrantProvider-RLJTNGPY.mjs +0 -8
  30. package/dist/RedisProvider-SR65SCKV.mjs +0 -8
  31. package/dist/SimpleGraphProvider-SLOXO4M7.mjs +0 -62
  32. package/dist/UniversalVectorProvider-IN67OS56.mjs +0 -9
  33. package/dist/WeaviateProvider-5FWDFITI.mjs +0 -8
  34. package/dist/chunk-5AJ4XHLW.mjs +0 -201
  35. package/dist/chunk-5YGUXK7Z.mjs +0 -80
  36. package/dist/chunk-CFVEZTBJ.mjs +0 -102
  37. package/dist/chunk-ICKRMZQK.mjs +0 -76
  38. package/dist/chunk-IMP6FUCY.mjs +0 -30
  39. package/dist/chunk-LR3VMDVK.mjs +0 -157
  40. package/dist/chunk-LZVVLSDN.mjs +0 -4077
  41. package/dist/chunk-M6JSPGAR.mjs +0 -117
  42. package/dist/chunk-OZFBG4BA.mjs +0 -291
  43. package/dist/chunk-PSFPZXHX.mjs +0 -245
  44. package/dist/chunk-U55XRW3U.mjs +0 -96
  45. package/dist/chunk-VUQJVIJT.mjs +0 -148
  46. package/dist/chunk-X4TOT24V.mjs +0 -89
  47. package/dist/chunk-YLTMFW4M.mjs +0 -49
package/dist/index.js CHANGED
@@ -73,19 +73,19 @@ __export(index_exports, {
73
73
  module.exports = __toCommonJS(index_exports);
74
74
 
75
75
  // src/components/ChatWidget.tsx
76
- var import_react15 = __toESM(require("react"));
76
+ var import_react12 = require("react");
77
77
  var import_lucide_react8 = require("lucide-react");
78
78
 
79
79
  // src/components/ChatWindow.tsx
80
- var import_react14 = __toESM(require("react"));
80
+ var import_react11 = require("react");
81
81
  var import_lucide_react7 = require("lucide-react");
82
82
 
83
83
  // src/components/DocumentUpload.tsx
84
- var import_react2 = __toESM(require("react"));
84
+ var import_react2 = require("react");
85
85
  var import_lucide_react = require("lucide-react");
86
86
 
87
87
  // src/components/ConfigProvider.tsx
88
- var import_react = __toESM(require("react"));
88
+ var import_react = require("react");
89
89
 
90
90
  // src/utils/templateUtils.ts
91
91
  function mergeDefined(base, override) {
@@ -137,6 +137,7 @@ var CHAT_SUGGESTIONS = [
137
137
  ];
138
138
 
139
139
  // src/components/ConfigProvider.tsx
140
+ var import_jsx_runtime = require("react/jsx-runtime");
140
141
  var ConfigContext = (0, import_react.createContext)(DEFAULT_CONFIG);
141
142
  function ConfigProvider({
142
143
  config,
@@ -147,13 +148,14 @@ function ConfigProvider({
147
148
  ui: mergeDefined(DEFAULT_CONFIG.ui, config == null ? void 0 : config.ui),
148
149
  embedding: config == null ? void 0 : config.embedding
149
150
  };
150
- return /* @__PURE__ */ import_react.default.createElement(ConfigContext.Provider, { value: merged }, children);
151
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(ConfigContext.Provider, { value: merged, children });
151
152
  }
152
153
  function useConfig() {
153
154
  return (0, import_react.useContext)(ConfigContext);
154
155
  }
155
156
 
156
157
  // src/components/DocumentUpload.tsx
158
+ var import_jsx_runtime2 = require("react/jsx-runtime");
157
159
  function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
158
160
  var _a;
159
161
  const { ui, embedding } = useConfig();
@@ -224,92 +226,129 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
224
226
  };
225
227
  const isUploading = fileStates.some((s) => s.status === "uploading");
226
228
  const hasIdle = fileStates.some((s) => s.status === "idle");
227
- return /* @__PURE__ */ import_react2.default.createElement(
229
+ return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
228
230
  "div",
229
231
  {
230
232
  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}`,
231
233
  onDragOver,
232
234
  onDragLeave,
233
- onDrop
234
- },
235
- /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ import_react2.default.createElement(
236
- "div",
237
- {
238
- className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
239
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
240
- },
241
- /* @__PURE__ */ import_react2.default.createElement(import_lucide_react.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
242
- ), /* @__PURE__ */ import_react2.default.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ import_react2.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_react2.default.createElement(
243
- "button",
244
- {
245
- onClick: () => {
246
- var _a2;
247
- return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
248
- },
249
- disabled: isUploading,
250
- className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
251
- style: {
252
- backgroundColor: `${ui.primaryColor}15`,
253
- color: ui.primaryColor,
254
- border: `1px solid ${ui.primaryColor}30`
255
- }
256
- },
257
- "Select Files"
258
- ), /* @__PURE__ */ import_react2.default.createElement(
259
- "input",
260
- {
261
- ref: fileInputRef,
262
- type: "file",
263
- multiple: true,
264
- onChange: onFileSelect,
265
- className: "hidden",
266
- accept: ".pdf,.docx,.txt,.md,.json,.csv"
267
- }
268
- ), /* @__PURE__ */ import_react2.default.createElement("div", { className: "mt-6 flex flex-col items-center gap-2 text-sm" }, /* @__PURE__ */ import_react2.default.createElement("label", { className: "text-slate-600 dark:text-white/60 font-medium" }, "Embedding Dimension"), isChangeable ? /* @__PURE__ */ import_react2.default.createElement(
269
- "select",
270
- {
271
- value: dimension,
272
- onChange: (e) => setDimension(Number(e.target.value)),
273
- disabled: isUploading,
274
- className: "px-3 py-1.5 rounded-lg bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 outline-none focus:border-emerald-500 transition-colors"
275
- },
276
- availableDimensions.map((dim) => /* @__PURE__ */ import_react2.default.createElement("option", { key: dim, value: dim, className: "bg-white dark:bg-slate-900" }, dim))
277
- ) : /* @__PURE__ */ import_react2.default.createElement("div", { className: "px-3 py-1.5 rounded-lg bg-slate-100 dark:bg-white/10 border border-slate-200 dark:border-white/10 text-slate-500 dark:text-white/50 cursor-not-allowed text-xs" }, dimension, " (Fixed for ", currentModel, ")"))),
278
- fileStates.length > 0 && /* @__PURE__ */ import_react2.default.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ import_react2.default.createElement(
279
- "div",
280
- {
281
- key: i,
282
- 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"
283
- },
284
- /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ import_react2.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_react2.default.createElement(import_lucide_react.File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ import_react2.default.createElement("div", { className: "truncate" }, /* @__PURE__ */ import_react2.default.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ import_react2.default.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
285
- /* @__PURE__ */ import_react2.default.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ import_react2.default.createElement(import_lucide_react.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ import_react2.default.createElement(import_lucide_react.CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ import_react2.default.createElement("div", { title: state.error }, /* @__PURE__ */ import_react2.default.createElement(import_lucide_react.AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ import_react2.default.createElement(
286
- "button",
287
- {
288
- onClick: () => removeFile(i),
289
- className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
290
- },
291
- /* @__PURE__ */ import_react2.default.createElement(import_lucide_react.X, { className: "w-3.5 h-3.5 text-slate-400" })
292
- ))
293
- )), hasIdle && !isUploading && /* @__PURE__ */ import_react2.default.createElement(
294
- "button",
295
- {
296
- onClick: uploadFiles,
297
- className: "w-full mt-4 py-2.5 rounded-xl text-sm font-semibold text-white shadow-lg transition-all hover:scale-[1.02] active:scale-[0.98]",
298
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
299
- },
300
- "Start Upload"
301
- ))
235
+ onDrop,
236
+ children: [
237
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex flex-col items-center justify-center text-center", children: [
238
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
239
+ "div",
240
+ {
241
+ className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
242
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` },
243
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
244
+ }
245
+ ),
246
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1", children: "Upload Documents" }),
247
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs", children: "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data." }),
248
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
249
+ "button",
250
+ {
251
+ onClick: () => {
252
+ var _a2;
253
+ return (_a2 = fileInputRef.current) == null ? void 0 : _a2.click();
254
+ },
255
+ disabled: isUploading,
256
+ className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
257
+ style: {
258
+ backgroundColor: `${ui.primaryColor}15`,
259
+ color: ui.primaryColor,
260
+ border: `1px solid ${ui.primaryColor}30`
261
+ },
262
+ children: "Select Files"
263
+ }
264
+ ),
265
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
266
+ "input",
267
+ {
268
+ ref: fileInputRef,
269
+ type: "file",
270
+ multiple: true,
271
+ onChange: onFileSelect,
272
+ className: "hidden",
273
+ accept: ".pdf,.docx,.txt,.md,.json,.csv"
274
+ }
275
+ ),
276
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-6 flex flex-col items-center gap-2 text-sm", children: [
277
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("label", { className: "text-slate-600 dark:text-white/60 font-medium", children: "Embedding Dimension" }),
278
+ isChangeable ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
279
+ "select",
280
+ {
281
+ value: dimension,
282
+ onChange: (e) => setDimension(Number(e.target.value)),
283
+ disabled: isUploading,
284
+ className: "px-3 py-1.5 rounded-lg bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 outline-none focus:border-emerald-500 transition-colors",
285
+ children: availableDimensions.map((dim) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("option", { value: dim, className: "bg-white dark:bg-slate-900", children: dim }, dim))
286
+ }
287
+ ) : /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "px-3 py-1.5 rounded-lg bg-slate-100 dark:bg-white/10 border border-slate-200 dark:border-white/10 text-slate-500 dark:text-white/50 cursor-not-allowed text-xs", children: [
288
+ dimension,
289
+ " (Fixed for ",
290
+ currentModel,
291
+ ")"
292
+ ] })
293
+ ] })
294
+ ] }),
295
+ fileStates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "mt-8 space-y-3", children: [
296
+ fileStates.map((state, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
297
+ "div",
298
+ {
299
+ 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",
300
+ children: [
301
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-3 overflow-hidden", children: [
302
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.File, { className: "w-4 h-4 text-slate-400" }) }),
303
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "truncate", children: [
304
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate", children: state.file.name }),
305
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("p", { className: "text-[10px] text-slate-400", children: [
306
+ (state.file.size / 1024).toFixed(1),
307
+ " KB"
308
+ ] })
309
+ ] })
310
+ ] }),
311
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "flex items-center gap-2", children: [
312
+ state.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }),
313
+ state.status === "success" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.CheckCircle, { className: "w-4 h-4 text-emerald-500" }),
314
+ state.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { title: state.error, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.AlertCircle, { className: "w-4 h-4 text-rose-500" }) }),
315
+ state.status !== "uploading" && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
316
+ "button",
317
+ {
318
+ onClick: () => removeFile(i),
319
+ className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors",
320
+ children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react.X, { className: "w-3.5 h-3.5 text-slate-400" })
321
+ }
322
+ )
323
+ ] })
324
+ ]
325
+ },
326
+ i
327
+ )),
328
+ hasIdle && !isUploading && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
329
+ "button",
330
+ {
331
+ onClick: uploadFiles,
332
+ className: "w-full mt-4 py-2.5 rounded-xl text-sm font-semibold text-white shadow-lg transition-all hover:scale-[1.02] active:scale-[0.98]",
333
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
334
+ children: "Start Upload"
335
+ }
336
+ )
337
+ ] })
338
+ ]
339
+ }
302
340
  );
303
341
  }
304
342
 
305
343
  // src/components/MessageBubble.tsx
306
- var import_react12 = __toESM(require("react"));
344
+ var import_react9 = __toESM(require("react"));
307
345
  var import_lucide_react6 = require("lucide-react");
308
346
  var import_react_markdown = __toESM(require("react-markdown"));
309
347
 
310
348
  // src/components/SourceCard.tsx
311
349
  var import_react3 = __toESM(require("react"));
312
350
  var import_lucide_react2 = require("lucide-react");
351
+ var import_jsx_runtime3 = require("react/jsx-runtime");
313
352
  function SourceCard({ source, index }) {
314
353
  var _a, _b;
315
354
  const [expanded, setExpanded] = import_react3.default.useState(false);
@@ -318,62 +357,98 @@ function SourceCard({ source, index }) {
318
357
  const scoreBg = source.score >= 0.8 ? "bg-emerald-50 border-emerald-100 dark:bg-emerald-400/10 dark:border-emerald-400/20" : source.score >= 0.6 ? "bg-amber-50 border-amber-100 dark:bg-amber-400/10 dark:border-amber-400/20" : "bg-rose-50 border-rose-100 dark:bg-rose-400/10 dark:border-rose-400/20";
319
358
  const preview = source.content.slice(0, 120);
320
359
  const hasMore = source.content.length > 120;
321
- return /* @__PURE__ */ import_react3.default.createElement(
360
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(
322
361
  "div",
323
362
  {
324
363
  className: `rounded-xl border backdrop-blur-sm p-3 transition-all duration-200 hover:scale-[1.01] cursor-pointer ${scoreBg}`,
325
- onClick: () => setExpanded((e) => !e)
326
- },
327
- /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ import_react3.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react3.default.createElement("span", { className: "flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 dark:bg-white/10 flex items-center justify-center text-[10px] font-bold text-slate-500 dark:text-white/60" }, index + 1), /* @__PURE__ */ import_react3.default.createElement("span", { className: "text-xs text-slate-500 dark:text-white/50 truncate font-mono" }, (_b = (_a = source.metadata) == null ? void 0 : _a.docId) != null ? _b : source.id)), /* @__PURE__ */ import_react3.default.createElement("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums` }, scorePercent, "%")),
328
- /* @__PURE__ */ import_react3.default.createElement("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed" }, expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}`),
329
- hasMore && /* @__PURE__ */ import_react3.default.createElement("button", { className: "mt-1 text-[10px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-0.5" }, expanded ? /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement(import_lucide_react2.ChevronUp, { className: "w-3 h-3" }), " Show less") : /* @__PURE__ */ import_react3.default.createElement(import_react3.default.Fragment, null, /* @__PURE__ */ import_react3.default.createElement(import_lucide_react2.ChevronDown, { className: "w-3 h-3" }), " Show more"))
364
+ onClick: () => setExpanded((e) => !e),
365
+ children: [
366
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
367
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
368
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 dark:bg-white/10 flex items-center justify-center text-[10px] font-bold text-slate-500 dark:text-white/60", children: index + 1 }),
369
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("span", { className: "text-xs text-slate-500 dark:text-white/50 truncate font-mono", children: (_b = (_a = source.metadata) == null ? void 0 : _a.docId) != null ? _b : source.id })
370
+ ] }),
371
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums`, children: [
372
+ scorePercent,
373
+ "%"
374
+ ] })
375
+ ] }),
376
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed", children: expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}` }),
377
+ hasMore && /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("button", { className: "mt-1 text-[10px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-0.5", children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
378
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.ChevronUp, { className: "w-3 h-3" }),
379
+ " Show less"
380
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime3.jsxs)(import_jsx_runtime3.Fragment, { children: [
381
+ /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(import_lucide_react2.ChevronDown, { className: "w-3 h-3" }),
382
+ " Show more"
383
+ ] }) })
384
+ ]
385
+ }
330
386
  );
331
387
  }
332
388
 
333
389
  // src/components/ProductCarousel.tsx
334
- var import_react5 = __toESM(require("react"));
390
+ var import_react4 = require("react");
335
391
  var import_lucide_react4 = require("lucide-react");
336
392
 
337
393
  // src/components/ProductCard.tsx
338
- var import_react4 = __toESM(require("react"));
339
394
  var import_image = __toESM(require("next/image"));
340
395
  var import_lucide_react3 = require("lucide-react");
396
+ var import_jsx_runtime4 = require("react/jsx-runtime");
341
397
  function ProductCard({ product, primaryColor = "#6366f1", onAddToCart }) {
342
- return /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex-shrink-0 w-full bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 group" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "relative h-40 w-full bg-slate-100 dark:bg-white/5 flex items-center justify-center overflow-hidden" }, product.image ? /* @__PURE__ */ import_react4.default.createElement(
343
- import_image.default,
344
- {
345
- src: product.image,
346
- alt: product.name,
347
- fill: true,
348
- unoptimized: true,
349
- className: "object-cover group-hover:scale-105 transition-transform duration-500"
350
- }
351
- ) : /* @__PURE__ */ import_react4.default.createElement("div", { className: "text-slate-400 dark:text-white/20" }, /* @__PURE__ */ import_react4.default.createElement(import_lucide_react3.ShoppingCart, { className: "w-12 h-12" })), product.brand && /* @__PURE__ */ import_react4.default.createElement("div", { className: "absolute top-2 left-2 px-2 py-1 bg-white/90 dark:bg-black/60 backdrop-blur-md rounded-md text-[10px] font-bold uppercase tracking-wider text-slate-700 dark:text-white/90 shadow-sm" }, product.brand)), /* @__PURE__ */ import_react4.default.createElement("div", { className: "p-4 flex flex-col gap-2" }, /* @__PURE__ */ import_react4.default.createElement("div", { className: "flex justify-between items-start gap-2" }, /* @__PURE__ */ import_react4.default.createElement("h3", { className: "text-sm font-semibold text-slate-800 dark:text-white/90 line-clamp-1" }, product.name), product.price && /* @__PURE__ */ import_react4.default.createElement("span", { className: "text-sm font-bold", style: { color: primaryColor } }, typeof product.price === "number" ? `$${product.price}` : String(product.price).match(/^[\d.]/) ? `$${product.price}` : product.price)), product.description && /* @__PURE__ */ import_react4.default.createElement("p", { className: "text-[11px] text-slate-500 dark:text-white/50 line-clamp-2 leading-relaxed" }, product.description), /* @__PURE__ */ import_react4.default.createElement("div", { className: "mt-2 flex gap-2" }, /* @__PURE__ */ import_react4.default.createElement(
352
- "button",
353
- {
354
- onClick: () => onAddToCart == null ? void 0 : onAddToCart(product),
355
- className: "flex-1 py-2 px-3 rounded-lg text-[11px] font-medium text-white shadow-sm hover:opacity-90 transition-opacity flex items-center justify-center gap-1.5",
356
- style: { background: primaryColor }
357
- },
358
- /* @__PURE__ */ import_react4.default.createElement(import_lucide_react3.ShoppingCart, { className: "w-3 h-3" }),
359
- "Add to Cart"
360
- ), product.link && /* @__PURE__ */ import_react4.default.createElement(
361
- "a",
362
- {
363
- href: product.link,
364
- target: "_blank",
365
- rel: "noopener noreferrer",
366
- className: "p-2 rounded-lg bg-slate-100 dark:bg-white/10 text-slate-600 dark:text-white/70 hover:bg-slate-200 dark:hover:bg-white/20 transition-colors"
367
- },
368
- /* @__PURE__ */ import_react4.default.createElement(import_lucide_react3.ExternalLink, { className: "w-3.5 h-3.5" })
369
- ))));
398
+ return /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex-shrink-0 w-full bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 rounded-xl overflow-hidden shadow-sm hover:shadow-md transition-all duration-300 group", children: [
399
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "relative h-40 w-full bg-slate-100 dark:bg-white/5 flex items-center justify-center overflow-hidden", children: [
400
+ product.image ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
401
+ import_image.default,
402
+ {
403
+ src: product.image,
404
+ alt: product.name,
405
+ fill: true,
406
+ unoptimized: true,
407
+ className: "object-cover group-hover:scale-105 transition-transform duration-500"
408
+ }
409
+ ) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "text-slate-400 dark:text-white/20", children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ShoppingCart, { className: "w-12 h-12" }) }),
410
+ product.brand && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("div", { className: "absolute top-2 left-2 px-2 py-1 bg-white/90 dark:bg-black/60 backdrop-blur-md rounded-md text-[10px] font-bold uppercase tracking-wider text-slate-700 dark:text-white/90 shadow-sm", children: product.brand })
411
+ ] }),
412
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "p-4 flex flex-col gap-2", children: [
413
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "flex justify-between items-start gap-2", children: [
414
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("h3", { className: "text-sm font-semibold text-slate-800 dark:text-white/90 line-clamp-1", children: product.name }),
415
+ product.price && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { className: "text-sm font-bold", style: { color: primaryColor }, children: typeof product.price === "number" ? `$${product.price}` : String(product.price).match(/^[\d.]/) ? `$${product.price}` : product.price })
416
+ ] }),
417
+ product.description && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("p", { className: "text-[11px] text-slate-500 dark:text-white/50 line-clamp-2 leading-relaxed", children: product.description }),
418
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)("div", { className: "mt-2 flex gap-2", children: [
419
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsxs)(
420
+ "button",
421
+ {
422
+ onClick: () => onAddToCart == null ? void 0 : onAddToCart(product),
423
+ className: "flex-1 py-2 px-3 rounded-lg text-[11px] font-medium text-white shadow-sm hover:opacity-90 transition-opacity flex items-center justify-center gap-1.5",
424
+ style: { background: primaryColor },
425
+ children: [
426
+ /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ShoppingCart, { className: "w-3 h-3" }),
427
+ "Add to Cart"
428
+ ]
429
+ }
430
+ ),
431
+ product.link && /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(
432
+ "a",
433
+ {
434
+ href: product.link,
435
+ target: "_blank",
436
+ rel: "noopener noreferrer",
437
+ className: "p-2 rounded-lg bg-slate-100 dark:bg-white/10 text-slate-600 dark:text-white/70 hover:bg-slate-200 dark:hover:bg-white/20 transition-colors",
438
+ children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)(import_lucide_react3.ExternalLink, { className: "w-3.5 h-3.5" })
439
+ }
440
+ )
441
+ ] })
442
+ ] })
443
+ ] });
370
444
  }
371
445
 
372
446
  // src/components/ProductCarousel.tsx
447
+ var import_jsx_runtime5 = require("react/jsx-runtime");
373
448
  function ProductCarousel({ products, primaryColor = "#6366f1", onAddToCart }) {
374
- const scrollRef = (0, import_react5.useRef)(null);
375
- const [canScroll, setCanScroll] = (0, import_react5.useState)(false);
376
- (0, import_react5.useEffect)(() => {
449
+ const scrollRef = (0, import_react4.useRef)(null);
450
+ const [canScroll, setCanScroll] = (0, import_react4.useState)(false);
451
+ (0, import_react4.useEffect)(() => {
377
452
  const checkScroll = () => {
378
453
  if (scrollRef.current) {
379
454
  const hasOverflow = scrollRef.current.scrollWidth > scrollRef.current.clientWidth;
@@ -397,55 +472,61 @@ function ProductCarousel({ products, primaryColor = "#6366f1", onAddToCart }) {
397
472
  };
398
473
  if (!products || products.length === 0) return null;
399
474
  if (products.length === 1) {
400
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "my-4 w-[min(88%,18rem)] min-w-0 max-w-full animate-fade-in-up" }, /* @__PURE__ */ import_react5.default.createElement(ProductCard, { product: products[0], primaryColor, onAddToCart }));
475
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "my-4 w-[min(88%,18rem)] min-w-0 max-w-full animate-fade-in-up", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProductCard, { product: products[0], primaryColor, onAddToCart }) });
401
476
  }
402
- return /* @__PURE__ */ import_react5.default.createElement("div", { className: "relative w-full my-4 group/carousel animate-fade-in-up" }, canScroll && /* @__PURE__ */ import_react5.default.createElement(import_react5.default.Fragment, null, /* @__PURE__ */ import_react5.default.createElement("div", { className: "absolute -left-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react5.default.createElement(
403
- "button",
404
- {
405
- onClick: (e) => {
406
- e.stopPropagation();
407
- scroll("left");
408
- },
409
- className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
410
- "aria-label": "Scroll left"
411
- },
412
- /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.ChevronLeft, { className: "w-5 h-5" })
413
- )), /* @__PURE__ */ import_react5.default.createElement("div", { className: "absolute -right-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity" }, /* @__PURE__ */ import_react5.default.createElement(
414
- "button",
415
- {
416
- onClick: (e) => {
417
- e.stopPropagation();
418
- scroll("right");
419
- },
420
- className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
421
- "aria-label": "Scroll right"
422
- },
423
- /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.ChevronRight, { className: "w-5 h-5" })
424
- ))), /* @__PURE__ */ import_react5.default.createElement(
425
- "div",
426
- {
427
- ref: scrollRef,
428
- className: "flex gap-4 overflow-x-auto pb-4 px-1 scrollbar-hide snap-x snap-mandatory",
429
- style: { scrollbarWidth: "none", msOverflowStyle: "none" }
430
- },
431
- products.map((product) => /* @__PURE__ */ import_react5.default.createElement(
477
+ return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "relative w-full my-4 group/carousel animate-fade-in-up", children: [
478
+ canScroll && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(import_jsx_runtime5.Fragment, { children: [
479
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "absolute -left-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
480
+ "button",
481
+ {
482
+ onClick: (e) => {
483
+ e.stopPropagation();
484
+ scroll("left");
485
+ },
486
+ className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
487
+ "aria-label": "Scroll left",
488
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.ChevronLeft, { className: "w-5 h-5" })
489
+ }
490
+ ) }),
491
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "absolute -right-4 top-1/2 -translate-y-1/2 z-20 opacity-100 md:opacity-0 md:group-hover/carousel:opacity-100 transition-opacity", children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
492
+ "button",
493
+ {
494
+ onClick: (e) => {
495
+ e.stopPropagation();
496
+ scroll("right");
497
+ },
498
+ className: "p-2 rounded-full bg-white dark:bg-slate-800 shadow-xl border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/80 hover:text-indigo-500 dark:hover:text-indigo-400 transition-all hover:scale-110 active:scale-95",
499
+ "aria-label": "Scroll right",
500
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.ChevronRight, { className: "w-5 h-5" })
501
+ }
502
+ ) })
503
+ ] }),
504
+ /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
432
505
  "div",
433
506
  {
434
- key: product.id,
435
- className: "snap-start flex-shrink-0 w-[min(88%,18rem)] min-w-[11rem] max-w-full"
436
- },
437
- /* @__PURE__ */ import_react5.default.createElement(ProductCard, { product, primaryColor, onAddToCart })
438
- ))
439
- ));
507
+ ref: scrollRef,
508
+ className: "flex gap-4 overflow-x-auto pb-4 px-1 scrollbar-hide snap-x snap-mandatory",
509
+ style: { scrollbarWidth: "none", msOverflowStyle: "none" },
510
+ children: products.map((product) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
511
+ "div",
512
+ {
513
+ className: "snap-start flex-shrink-0 w-[min(88%,18rem)] min-w-[11rem] max-w-full",
514
+ children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(ProductCard, { product, primaryColor, onAddToCart })
515
+ },
516
+ product.id
517
+ ))
518
+ }
519
+ )
520
+ ] });
440
521
  }
441
522
 
442
523
  // src/components/VisualizationRenderer.tsx
443
- var import_react7 = __toESM(require("react"));
444
524
  var import_recharts2 = require("recharts");
445
525
 
446
526
  // src/components/DynamicChart.tsx
447
- var import_react6 = __toESM(require("react"));
527
+ var import_react5 = __toESM(require("react"));
448
528
  var import_recharts = require("recharts");
529
+ var import_jsx_runtime6 = require("react/jsx-runtime");
449
530
  var CHART_COLORS = ["#6366f1", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899"];
450
531
  function DynamicChart({
451
532
  config,
@@ -456,9 +537,9 @@ function DynamicChart({
456
537
  }) {
457
538
  const { type, data } = config;
458
539
  const colors = config.colors || [primaryColor, accentColor, ...CHART_COLORS];
459
- const containerRef = import_react6.default.useRef(null);
460
- const [containerWidth, setContainerWidth] = import_react6.default.useState(0);
461
- import_react6.default.useEffect(() => {
540
+ const containerRef = import_react5.default.useRef(null);
541
+ const [containerWidth, setContainerWidth] = import_react5.default.useState(0);
542
+ import_react5.default.useEffect(() => {
462
543
  const element = containerRef.current;
463
544
  if (!element || typeof ResizeObserver === "undefined") return;
464
545
  const updateWidth = (width) => {
@@ -484,7 +565,7 @@ function DynamicChart({
484
565
  return text.length > maxLength ? `${text.slice(0, maxLength)}\u2026` : text;
485
566
  };
486
567
  const chartMargin = isTiny ? { top: 8, right: 4, left: -28, bottom: 0 } : isCompact ? { top: 10, right: 6, left: -24, bottom: 0 } : { top: 10, right: 10, left: -20, bottom: 0 };
487
- const sanitizedData = import_react6.default.useMemo(() => {
568
+ const sanitizedData = import_react5.default.useMemo(() => {
488
569
  if (!data) return [];
489
570
  return data.map((item) => {
490
571
  const newItem = {};
@@ -518,17 +599,17 @@ function DynamicChart({
518
599
  }, [data]);
519
600
  if (isStreaming) {
520
601
  const bars = type === "pie" ? 6 : 5;
521
- return /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse" }, type === "pie" ? /* @__PURE__ */ import_react6.default.createElement("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }) : /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex items-end gap-2 h-32 px-2" }, Array.from({ length: bars }).map((_, i) => /* @__PURE__ */ import_react6.default.createElement(
602
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-full mt-4 mb-2 animate-pulse", children: type === "pie" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "flex items-end gap-2 h-32 px-2", children: Array.from({ length: bars }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
522
603
  "div",
523
604
  {
524
- key: i,
525
605
  className: "flex-1 rounded-t-md bg-slate-100 dark:bg-white/10",
526
606
  style: { height: `${40 + i % 3 * 25}%` }
527
- }
528
- ))));
607
+ },
608
+ i
609
+ )) }) });
529
610
  }
530
611
  if (!data || data.length === 0) {
531
- return /* @__PURE__ */ import_react6.default.createElement("div", { className: "p-4 text-sm text-slate-500" }, "No data available for chart.");
612
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "p-4 text-sm text-slate-500", children: "No data available for chart." });
532
613
  }
533
614
  const firstItem = sanitizedData[0];
534
615
  const allKeys = Object.keys(firstItem);
@@ -553,14 +634,20 @@ function DynamicChart({
553
634
  const renderTooltip = (row, label) => {
554
635
  var _a, _b;
555
636
  if (!row) return null;
556
- return /* @__PURE__ */ import_react6.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" }, /* @__PURE__ */ import_react6.default.createElement("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90" }, String((_b = (_a = row[finalXKey]) != null ? _a : label) != null ? _b : "Details")), Object.entries(row).map(([key, value]) => {
557
- var _a2;
558
- if (value === null || value === void 0 || key === finalXKey) return null;
559
- if (typeof value === "object") return null;
560
- const forbiddenKeys = ["fill", "color", "payload", "percent", "stroke", "inStock"];
561
- if (forbiddenKeys.includes(key)) return null;
562
- return /* @__PURE__ */ import_react6.default.createElement("div", { key, className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70" }, /* @__PURE__ */ import_react6.default.createElement("span", null, (_a2 = tooltipLabelMap[key]) != null ? _a2 : key), /* @__PURE__ */ import_react6.default.createElement("span", { className: "font-medium text-slate-900 dark:text-white/90" }, String(value)));
563
- }));
637
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("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", children: [
638
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90", children: String((_b = (_a = row[finalXKey]) != null ? _a : label) != null ? _b : "Details") }),
639
+ Object.entries(row).map(([key, value]) => {
640
+ var _a2;
641
+ if (value === null || value === void 0 || key === finalXKey) return null;
642
+ if (typeof value === "object") return null;
643
+ const forbiddenKeys = ["fill", "color", "payload", "percent", "stroke", "inStock"];
644
+ if (forbiddenKeys.includes(key)) return null;
645
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)("div", { className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70", children: [
646
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { children: (_a2 = tooltipLabelMap[key]) != null ? _a2 : key }),
647
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "font-medium text-slate-900 dark:text-white/90", children: String(value) })
648
+ ] }, key);
649
+ })
650
+ ] });
564
651
  };
565
652
  const getTooltipRow = (payload) => {
566
653
  if (!Array.isArray(payload) || payload.length === 0) return null;
@@ -571,45 +658,64 @@ function DynamicChart({
571
658
  return row;
572
659
  };
573
660
  if (type === "pie") {
574
- return /* @__PURE__ */ import_react6.default.createElement("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "mx-auto w-full max-w-full aspect-square" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.PieChart, null, /* @__PURE__ */ import_react6.default.createElement(
575
- import_recharts.Pie,
661
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "mx-auto w-full max-w-full aspect-square", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.ResponsiveContainer, { width: "100%", height: "100%", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_recharts.PieChart, { children: [
662
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
663
+ import_recharts.Pie,
664
+ {
665
+ data: sanitizedData,
666
+ dataKey: pieDataKey,
667
+ nameKey: finalXKey,
668
+ cx: "50%",
669
+ cy: "50%",
670
+ outerRadius: pieOuterRadius,
671
+ label: false,
672
+ labelLine: false,
673
+ children: sanitizedData.map((_entry, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.Cell, { fill: colors[index % colors.length] }, `cell-${index}`))
674
+ }
675
+ ),
676
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }),
677
+ showLegend && !isCompact && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })
678
+ ] }) }) }) });
679
+ }
680
+ return /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("div", { className: "w-full aspect-[4/3]", children: /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.ResponsiveContainer, { width: "100%", height: "100%", children: type === "bar" ? /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_recharts.BarChart, { data: sanitizedData, margin: chartMargin, children: [
681
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
682
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }),
683
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.YAxis, { tick: axisTick, tickLine: false, axisLine: false }),
684
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0), cursor: { fill: "#f1f5f9" } }),
685
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }),
686
+ finalDataKeys.map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
687
+ import_recharts.Bar,
576
688
  {
577
- data: sanitizedData,
578
- dataKey: pieDataKey,
579
- nameKey: finalXKey,
580
- cx: "50%",
581
- cy: "50%",
582
- outerRadius: pieOuterRadius,
583
- label: false,
584
- labelLine: false
689
+ dataKey: key,
690
+ fill: colors[index % colors.length],
691
+ radius: [4, 4, 0, 0],
692
+ barSize: isTiny ? Math.max(10, 28 / data.length) : isCompact ? Math.max(14, 42 / data.length) : Math.max(20, 60 / data.length)
585
693
  },
586
- sanitizedData.map((_entry, index) => /* @__PURE__ */ import_react6.default.createElement(import_recharts.Cell, { key: `cell-${index}`, fill: colors[index % colors.length] }))
587
- ), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }), showLegend && !isCompact && /* @__PURE__ */ import_react6.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })))));
588
- }
589
- return /* @__PURE__ */ import_react6.default.createElement("div", { ref: containerRef, className: "w-full min-w-0 mt-4 mb-2 select-none overflow-hidden" }, /* @__PURE__ */ import_react6.default.createElement("div", { className: "w-full aspect-[4/3]" }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, type === "bar" ? /* @__PURE__ */ import_react6.default.createElement(import_recharts.BarChart, { data: sanitizedData, margin: chartMargin }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { tick: axisTick, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0), cursor: { fill: "#f1f5f9" } }), showLegend && /* @__PURE__ */ import_react6.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ import_react6.default.createElement(
590
- import_recharts.Bar,
591
- {
592
- key,
593
- dataKey: key,
594
- fill: colors[index % colors.length],
595
- radius: [4, 4, 0, 0],
596
- barSize: isTiny ? Math.max(10, 28 / data.length) : isCompact ? Math.max(14, 42 / data.length) : Math.max(20, 60 / data.length)
597
- }
598
- ))) : /* @__PURE__ */ import_react6.default.createElement(import_recharts.LineChart, { data: sanitizedData, margin: chartMargin }, /* @__PURE__ */ import_react6.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.YAxis, { tick: axisTick, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react6.default.createElement(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }), showLegend && /* @__PURE__ */ import_react6.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }), finalDataKeys.map((key, index) => /* @__PURE__ */ import_react6.default.createElement(
599
- import_recharts.Line,
600
- {
601
- key,
602
- type: "monotone",
603
- dataKey: key,
604
- stroke: colors[index % colors.length],
605
- strokeWidth: isTiny ? 1.75 : isCompact ? 2 : 3,
606
- dot: { r: isTiny ? 2.5 : isCompact ? 3 : 4, strokeWidth: 2 },
607
- activeDot: { r: isTiny ? 4 : isCompact ? 5 : 6 }
608
- }
609
- ))))));
694
+ key
695
+ ))
696
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_recharts.LineChart, { data: sanitizedData, margin: chartMargin, children: [
697
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
698
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.XAxis, { dataKey: finalXKey, tick: axisTick, tickFormatter: truncateAxisLabel, tickLine: false, axisLine: { stroke: "#cbd5e1" }, interval: 0, minTickGap: isTiny ? 2 : isCompact ? 6 : 12 }),
699
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.YAxis, { tick: axisTick, tickLine: false, axisLine: false }),
700
+ /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.Tooltip, { content: (props) => renderTooltip(getTooltipRow(props.payload), typeof props.label === "string" ? props.label : void 0) }),
701
+ showLegend && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_recharts.Legend, { wrapperStyle: { fontSize: isCompact ? 10 : 12 } }),
702
+ finalDataKeys.map((key, index) => /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
703
+ import_recharts.Line,
704
+ {
705
+ type: "monotone",
706
+ dataKey: key,
707
+ stroke: colors[index % colors.length],
708
+ strokeWidth: isTiny ? 1.75 : isCompact ? 2 : 3,
709
+ dot: { r: isTiny ? 2.5 : isCompact ? 3 : 4, strokeWidth: 2 },
710
+ activeDot: { r: isTiny ? 4 : isCompact ? 5 : 6 }
711
+ },
712
+ key
713
+ ))
714
+ ] }) }) }) });
610
715
  }
611
716
 
612
717
  // src/components/VisualizationRenderer.tsx
718
+ var import_jsx_runtime7 = require("react/jsx-runtime");
613
719
  function getColor(index) {
614
720
  return CHART_COLORS[index % CHART_COLORS.length];
615
721
  }
@@ -619,13 +725,22 @@ function CustomTooltip({
619
725
  label
620
726
  }) {
621
727
  if (!active || !payload || payload.length === 0) return null;
622
- return /* @__PURE__ */ import_react7.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_react7.default.createElement("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90" }, label), payload.map((entry, i) => /* @__PURE__ */ import_react7.default.createElement("div", { key: i, className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70" }, /* @__PURE__ */ import_react7.default.createElement("span", { className: "flex items-center gap-1.5" }, entry.color && /* @__PURE__ */ import_react7.default.createElement(
623
- "span",
624
- {
625
- className: "inline-block w-2 h-2 rounded-full flex-shrink-0",
626
- style: { background: entry.color }
627
- }
628
- ), entry.name), /* @__PURE__ */ import_react7.default.createElement("span", { className: "font-medium text-slate-900 dark:text-white/90" }, entry.value))));
728
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("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", children: [
729
+ label && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "mb-2 font-semibold text-slate-800 dark:text-white/90", children: label }),
730
+ payload.map((entry, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center justify-between gap-3 text-slate-600 dark:text-white/70", children: [
731
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("span", { className: "flex items-center gap-1.5", children: [
732
+ entry.color && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
733
+ "span",
734
+ {
735
+ className: "inline-block w-2 h-2 rounded-full flex-shrink-0",
736
+ style: { background: entry.color }
737
+ }
738
+ ),
739
+ entry.name
740
+ ] }),
741
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("span", { className: "font-medium text-slate-900 dark:text-white/90", children: entry.value })
742
+ ] }, i))
743
+ ] });
629
744
  }
630
745
  function VisualizationRenderer({
631
746
  data,
@@ -636,72 +751,86 @@ function VisualizationRenderer({
636
751
  }) {
637
752
  var _a;
638
753
  if (!data) {
639
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: `p-4 text-gray-500 ${className}` }, "No data available for visualization");
754
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: `p-4 text-gray-500 ${className}`, children: "No data available for visualization" });
640
755
  }
641
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: `space-y-4 ${className}` }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "space-y-1" }, /* @__PURE__ */ import_react7.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_react7.default.createElement("p", { className: "text-xs text-slate-500 dark:text-slate-400" }, data.description)), renderVisualization(data.type, data.data, onAddToCart, primaryColor, isStreaming));
756
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: `space-y-4 ${className}`, children: [
757
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "space-y-1", children: [
758
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "text-sm font-semibold text-slate-900 dark:text-white", children: data.title }),
759
+ data.description && data.description !== ((_a = data.data) == null ? void 0 : _a.content) && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-xs text-slate-500 dark:text-slate-400", children: data.description })
760
+ ] }),
761
+ renderVisualization(data.type, data.data, onAddToCart, primaryColor, isStreaming)
762
+ ] });
642
763
  }
643
764
  function renderVisualization(type, data, onAddToCart, primaryColor, isStreaming) {
644
765
  try {
645
766
  switch (type) {
646
767
  case "pie_chart":
647
- return /* @__PURE__ */ import_react7.default.createElement(PieChartView, { data, isStreaming });
768
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(PieChartView, { data, isStreaming });
648
769
  case "bar_chart":
649
- return /* @__PURE__ */ import_react7.default.createElement(BarChartView, { data, primaryColor, isStreaming });
770
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(BarChartView, { data, primaryColor, isStreaming });
650
771
  case "line_chart":
651
- return /* @__PURE__ */ import_react7.default.createElement(LineChartView, { data, primaryColor, isStreaming });
772
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(LineChartView, { data, primaryColor, isStreaming });
652
773
  case "radar_chart":
653
- return /* @__PURE__ */ import_react7.default.createElement(RadarChartView, { data, isStreaming });
774
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(RadarChartView, { data, isStreaming });
654
775
  case "table":
655
- return /* @__PURE__ */ import_react7.default.createElement(TableView, { data, isStreaming });
776
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TableView, { data, isStreaming });
656
777
  case "product_carousel":
657
778
  case "carousel":
658
- return /* @__PURE__ */ import_react7.default.createElement(CarouselView, { data, onAddToCart, primaryColor });
779
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CarouselView, { data, onAddToCart, primaryColor });
659
780
  case "text":
660
781
  default:
661
- return /* @__PURE__ */ import_react7.default.createElement(TextView, { data });
782
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TextView, { data });
662
783
  }
663
784
  } catch (error) {
664
785
  console.warn("[VisualizationRenderer] Rendering failed, falling back to text:", error);
665
- return /* @__PURE__ */ import_react7.default.createElement(TextView, { data: { content: "Unable to render the requested visualization." } });
786
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(TextView, { data: { content: "Unable to render the requested visualization." } });
666
787
  }
667
788
  }
668
789
  function ChartSkeleton({ type }) {
669
790
  if (type === "pie") {
670
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }));
791
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-full mt-4 mb-2 animate-pulse", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "mx-auto w-40 h-40 rounded-full bg-slate-100 dark:bg-white/10" }) });
671
792
  }
672
793
  if (type === "table") {
673
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse space-y-2" }, /* @__PURE__ */ import_react7.default.createElement("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }), /* @__PURE__ */ import_react7.default.createElement("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }));
794
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "w-full mt-4 mb-2 animate-pulse space-y-2", children: [
795
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }),
796
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" }),
797
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "h-8 bg-slate-100 dark:bg-white/10 rounded" })
798
+ ] });
674
799
  }
675
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full mt-4 mb-2 animate-pulse flex items-end gap-2 h-32 px-2" }, Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ import_react7.default.createElement("div", { key: i, className: "flex-1 rounded-t-md bg-slate-100 dark:bg-white/10", style: { height: `${40 + i % 3 * 25}%` } })));
800
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-full mt-4 mb-2 animate-pulse flex items-end gap-2 h-32 px-2", children: Array.from({ length: 5 }).map((_, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "flex-1 rounded-t-md bg-slate-100 dark:bg-white/10", style: { height: `${40 + i % 3 * 25}%` } }, i)) });
676
801
  }
677
802
  function PieChartView({ data, isStreaming }) {
678
- if (isStreaming) return /* @__PURE__ */ import_react7.default.createElement(ChartSkeleton, { type: "pie" });
803
+ if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "pie" });
679
804
  if (!Array.isArray(data) || data.length === 0) {
680
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid pie chart data");
805
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid pie chart data" });
681
806
  }
682
807
  const chartData = data.map((item) => ({
683
808
  name: item.label,
684
809
  value: item.value
685
810
  }));
686
- return /* @__PURE__ */ import_react7.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_react7.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 280 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.PieChart, null, /* @__PURE__ */ import_react7.default.createElement(
687
- import_recharts2.Pie,
688
- {
689
- data: chartData,
690
- dataKey: "value",
691
- nameKey: "name",
692
- cx: "50%",
693
- cy: "50%",
694
- outerRadius: "68%",
695
- label: false,
696
- labelLine: false
697
- },
698
- chartData.map((_entry, index) => /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Cell, { key: `cell-${index}`, fill: getColor(index) }))
699
- ), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react7.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" }))));
811
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 280, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_recharts2.PieChart, { children: [
812
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
813
+ import_recharts2.Pie,
814
+ {
815
+ data: chartData,
816
+ dataKey: "value",
817
+ nameKey: "name",
818
+ cx: "50%",
819
+ cy: "50%",
820
+ outerRadius: "68%",
821
+ label: false,
822
+ labelLine: false,
823
+ children: chartData.map((_entry, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Cell, { fill: getColor(index) }, `cell-${index}`))
824
+ }
825
+ ),
826
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CustomTooltip, {}) }),
827
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 }, verticalAlign: "bottom" })
828
+ ] }) }) });
700
829
  }
701
830
  function BarChartView({ data, primaryColor, isStreaming }) {
702
- if (isStreaming) return /* @__PURE__ */ import_react7.default.createElement(ChartSkeleton, { type: "bar" });
831
+ if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "bar" });
703
832
  if (!Array.isArray(data) || data.length === 0) {
704
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid bar chart data");
833
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid bar chart data" });
705
834
  }
706
835
  const chartData = data.map((item) => __spreadValues(__spreadValues({
707
836
  category: item.category,
@@ -709,20 +838,30 @@ function BarChartView({ data, primaryColor, isStreaming }) {
709
838
  }, item.inStockCount !== void 0 && { inStockCount: item.inStockCount }), item.outOfStockCount !== void 0 && { outOfStockCount: item.outOfStockCount }));
710
839
  const barColor = primaryColor != null ? primaryColor : getColor(0);
711
840
  const hasStock = chartData.some((d) => "inStockCount" in d);
712
- return /* @__PURE__ */ import_react7.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_react7.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 260 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.BarChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react7.default.createElement(
713
- import_recharts2.XAxis,
714
- {
715
- dataKey: "category",
716
- tick: { fontSize: 11, fill: "#64748b" },
717
- tickLine: false,
718
- axisLine: { stroke: "#cbd5e1" }
719
- }
720
- ), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react7.default.createElement(CustomTooltip, null), cursor: { fill: "#f1f5f9" } }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }), hasStock ? /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Bar, { dataKey: "inStockCount", name: "In Stock", fill: getColor(1), radius: [4, 4, 0, 0] }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Bar, { dataKey: "outOfStockCount", name: "Out of Stock", fill: getColor(3), radius: [4, 4, 0, 0] })) : /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Bar, { dataKey: "value", name: "Value", fill: barColor, radius: [4, 4, 0, 0] }))));
841
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 260, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_recharts2.BarChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 }, children: [
842
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
843
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
844
+ import_recharts2.XAxis,
845
+ {
846
+ dataKey: "category",
847
+ tick: { fontSize: 11, fill: "#64748b" },
848
+ tickLine: false,
849
+ axisLine: { stroke: "#cbd5e1" }
850
+ }
851
+ ),
852
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }),
853
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CustomTooltip, {}), cursor: { fill: "#f1f5f9" } }),
854
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }),
855
+ hasStock ? /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_jsx_runtime7.Fragment, { children: [
856
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Bar, { dataKey: "inStockCount", name: "In Stock", fill: getColor(1), radius: [4, 4, 0, 0] }),
857
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Bar, { dataKey: "outOfStockCount", name: "Out of Stock", fill: getColor(3), radius: [4, 4, 0, 0] })
858
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Bar, { dataKey: "value", name: "Value", fill: barColor, radius: [4, 4, 0, 0] })
859
+ ] }) }) });
721
860
  }
722
861
  function LineChartView({ data, primaryColor, isStreaming }) {
723
- if (isStreaming) return /* @__PURE__ */ import_react7.default.createElement(ChartSkeleton, { type: "bar" });
862
+ if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "bar" });
724
863
  if (!Array.isArray(data) || data.length === 0) {
725
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid line chart data");
864
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid line chart data" });
726
865
  }
727
866
  const chartData = data.map((point) => {
728
867
  var _a;
@@ -732,74 +871,97 @@ function LineChartView({ data, primaryColor, isStreaming }) {
732
871
  };
733
872
  });
734
873
  const lineColor = primaryColor != null ? primaryColor : getColor(0);
735
- return /* @__PURE__ */ import_react7.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_react7.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 260 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.LineChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react7.default.createElement(
736
- import_recharts2.XAxis,
737
- {
738
- dataKey: "label",
739
- tick: { fontSize: 11, fill: "#64748b" },
740
- tickLine: false,
741
- axisLine: { stroke: "#cbd5e1" }
742
- }
743
- ), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react7.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react7.default.createElement(
744
- import_recharts2.Line,
745
- {
746
- type: "monotone",
747
- dataKey: "value",
748
- name: "Value",
749
- stroke: lineColor,
750
- strokeWidth: 2.5,
751
- dot: { r: 3.5, strokeWidth: 2, fill: lineColor },
752
- activeDot: { r: 5 }
753
- }
754
- ))));
874
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 260, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_recharts2.LineChart, { data: chartData, margin: { top: 10, right: 10, left: -20, bottom: 0 }, children: [
875
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }),
876
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
877
+ import_recharts2.XAxis,
878
+ {
879
+ dataKey: "label",
880
+ tick: { fontSize: 11, fill: "#64748b" },
881
+ tickLine: false,
882
+ axisLine: { stroke: "#cbd5e1" }
883
+ }
884
+ ),
885
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.YAxis, { tick: { fontSize: 11, fill: "#64748b" }, tickLine: false, axisLine: false }),
886
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CustomTooltip, {}) }),
887
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
888
+ import_recharts2.Line,
889
+ {
890
+ type: "monotone",
891
+ dataKey: "value",
892
+ name: "Value",
893
+ stroke: lineColor,
894
+ strokeWidth: 2.5,
895
+ dot: { r: 3.5, strokeWidth: 2, fill: lineColor },
896
+ activeDot: { r: 5 }
897
+ }
898
+ )
899
+ ] }) }) });
755
900
  }
756
901
  function RadarChartView({ data, isStreaming }) {
757
- if (isStreaming) return /* @__PURE__ */ import_react7.default.createElement(ChartSkeleton, { type: "pie" });
902
+ if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "pie" });
758
903
  if (!Array.isArray(data) || data.length === 0) {
759
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid radar chart data");
904
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid radar chart data" });
760
905
  }
761
906
  const productNames = Array.from(
762
907
  new Set(data.flatMap((item) => Object.keys(item).filter((key) => key !== "attribute")))
763
908
  );
764
- return /* @__PURE__ */ import_react7.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_react7.default.createElement(import_recharts2.ResponsiveContainer, { width: "100%", height: 300 }, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.RadarChart, { cx: "50%", cy: "50%", outerRadius: "80%", data }, /* @__PURE__ */ import_react7.default.createElement(import_recharts2.PolarGrid, { stroke: "#e2e8f0" }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.PolarAngleAxis, { dataKey: "attribute", tick: { fontSize: 11, fill: "#64748b" } }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.PolarRadiusAxis, { tick: { fontSize: 10, fill: "#64748b" } }), productNames.map((productName, index) => /* @__PURE__ */ import_react7.default.createElement(
765
- import_recharts2.Radar,
766
- {
767
- key: productName,
768
- name: productName,
769
- dataKey: productName,
770
- stroke: getColor(index),
771
- fill: getColor(index),
772
- fillOpacity: 0.4
773
- }
774
- )), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Tooltip, { content: /* @__PURE__ */ import_react7.default.createElement(CustomTooltip, null) }), /* @__PURE__ */ import_react7.default.createElement(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } }))));
909
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.ResponsiveContainer, { width: "100%", height: 300, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(import_recharts2.RadarChart, { cx: "50%", cy: "50%", outerRadius: "80%", data, children: [
910
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.PolarGrid, { stroke: "#e2e8f0" }),
911
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.PolarAngleAxis, { dataKey: "attribute", tick: { fontSize: 11, fill: "#64748b" } }),
912
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.PolarRadiusAxis, { tick: { fontSize: 10, fill: "#64748b" } }),
913
+ productNames.map((productName, index) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
914
+ import_recharts2.Radar,
915
+ {
916
+ name: productName,
917
+ dataKey: productName,
918
+ stroke: getColor(index),
919
+ fill: getColor(index),
920
+ fillOpacity: 0.4
921
+ },
922
+ productName
923
+ )),
924
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Tooltip, { content: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(CustomTooltip, {}) }),
925
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_recharts2.Legend, { wrapperStyle: { fontSize: 12 } })
926
+ ] }) }) });
775
927
  }
776
928
  function TableView({ data, isStreaming }) {
777
- if (isStreaming) return /* @__PURE__ */ import_react7.default.createElement(ChartSkeleton, { type: "table" });
929
+ if (isStreaming) return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(ChartSkeleton, { type: "table" });
778
930
  if (!(data == null ? void 0 : data.columns) || !(data == null ? void 0 : data.rows)) {
779
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid table data");
931
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid table data" });
780
932
  }
781
- return /* @__PURE__ */ import_react7.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_react7.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react7.default.createElement("table", { className: "w-full text-sm border-collapse" }, /* @__PURE__ */ import_react7.default.createElement("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, /* @__PURE__ */ import_react7.default.createElement("tr", null, data.columns.map((col, idx) => /* @__PURE__ */ import_react7.default.createElement(
782
- "th",
783
- {
784
- key: idx,
785
- className: "px-4 py-3 text-left text-xs font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap uppercase tracking-wider"
786
- },
787
- col
788
- )))), /* @__PURE__ */ import_react7.default.createElement("tbody", { className: "divide-y divide-slate-100 dark:divide-white/5" }, data.rows.map((row, rowIdx) => /* @__PURE__ */ import_react7.default.createElement(
789
- "tr",
790
- {
791
- key: rowIdx,
792
- className: "hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors"
793
- },
794
- row.map((cell, cellIdx) => /* @__PURE__ */ import_react7.default.createElement(
795
- "td",
796
- {
797
- key: cellIdx,
798
- className: "px-4 py-3 text-slate-600 dark:text-white/70 text-sm"
799
- },
800
- String(cell)
801
- ))
802
- ))))), /* @__PURE__ */ import_react7.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_react7.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30" }, data.rows.length, " row", data.rows.length !== 1 ? "s" : "")));
933
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm overflow-hidden", children: [
934
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("table", { className: "w-full text-sm border-collapse", children: [
935
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("thead", { className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tr", { children: data.columns.map((col, idx) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
936
+ "th",
937
+ {
938
+ className: "px-4 py-3 text-left text-xs font-semibold text-slate-700 dark:text-white/90 whitespace-nowrap uppercase tracking-wider",
939
+ children: col
940
+ },
941
+ idx
942
+ )) }) }),
943
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("tbody", { className: "divide-y divide-slate-100 dark:divide-white/5", children: data.rows.map((row, rowIdx) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
944
+ "tr",
945
+ {
946
+ className: "hover:bg-slate-50/60 dark:hover:bg-white/5 transition-colors",
947
+ children: row.map((cell, cellIdx) => /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
948
+ "td",
949
+ {
950
+ className: "px-4 py-3 text-slate-600 dark:text-white/70 text-sm",
951
+ children: String(cell)
952
+ },
953
+ cellIdx
954
+ ))
955
+ },
956
+ rowIdx
957
+ )) })
958
+ ] }) }),
959
+ /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "px-4 py-2 bg-slate-50 dark:bg-white/5 border-t border-slate-100 dark:border-white/5", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[11px] text-slate-400 dark:text-white/30", children: [
960
+ data.rows.length,
961
+ " row",
962
+ data.rows.length !== 1 ? "s" : ""
963
+ ] }) })
964
+ ] });
803
965
  }
804
966
  function CarouselView({
805
967
  data,
@@ -807,7 +969,7 @@ function CarouselView({
807
969
  primaryColor
808
970
  }) {
809
971
  if (!Array.isArray(data)) {
810
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "text-xs text-red-500" }, "Invalid carousel data");
972
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "text-xs text-red-500", children: "Invalid carousel data" });
811
973
  }
812
974
  const products = data.map((product) => ({
813
975
  id: product.id,
@@ -819,23 +981,24 @@ function CarouselView({
819
981
  description: product.description,
820
982
  inStock: product.inStock
821
983
  }));
822
- return /* @__PURE__ */ import_react7.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react7.default.createElement(
984
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-full", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
823
985
  ProductCarousel,
824
986
  {
825
987
  products,
826
988
  primaryColor: primaryColor != null ? primaryColor : "#6366f1",
827
989
  onAddToCart: (p) => onAddToCart == null ? void 0 : onAddToCart(p)
828
990
  }
829
- ));
991
+ ) });
830
992
  }
831
993
  function TextView({ data }) {
832
994
  const content = (data == null ? void 0 : data.content) || String(data != null ? data : "");
833
- return /* @__PURE__ */ import_react7.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_react7.default.createElement("p", { className: "text-sm text-slate-700 dark:text-slate-300 whitespace-pre-wrap leading-relaxed" }, content));
995
+ return /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 p-4 shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-sm text-slate-700 dark:text-slate-300 whitespace-pre-wrap leading-relaxed", children: content }) });
834
996
  }
835
997
 
836
998
  // src/components/ObservabilityPanel.tsx
837
- var import_react8 = __toESM(require("react"));
999
+ var import_react6 = __toESM(require("react"));
838
1000
  var import_lucide_react5 = require("lucide-react");
1001
+ var import_jsx_runtime8 = require("react/jsx-runtime");
839
1002
  function fmtMs(ms) {
840
1003
  return ms >= 1e3 ? `${(ms / 1e3).toFixed(2)}s` : `${Math.round(ms)}ms`;
841
1004
  }
@@ -845,25 +1008,55 @@ function fmtTokens(n) {
845
1008
  function ScoreBadge({ score }) {
846
1009
  const pct = Math.round(score * 100);
847
1010
  const color = pct <= 20 ? "text-emerald-600 bg-emerald-50 border-emerald-200 dark:text-emerald-400 dark:bg-emerald-500/10 dark:border-emerald-500/20" : pct <= 50 ? "text-amber-600 bg-amber-50 border-amber-200 dark:text-amber-400 dark:bg-amber-500/10 dark:border-amber-500/20" : "text-red-600 bg-red-50 border-red-200 dark:text-red-400 dark:bg-red-500/10 dark:border-red-500/20";
848
- return /* @__PURE__ */ import_react8.default.createElement("span", { className: `inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-semibold border ${color}` }, pct <= 20 ? /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.CheckCircle, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.AlertCircle, { className: "w-3 h-3" }), pct, "% hallucination risk");
1011
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: `inline-flex items-center gap-1 px-2 py-0.5 rounded-full text-[11px] font-semibold border ${color}`, children: [
1012
+ pct <= 20 ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.CheckCircle, { className: "w-3 h-3" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.AlertCircle, { className: "w-3 h-3" }),
1013
+ pct,
1014
+ "% hallucination risk"
1015
+ ] });
849
1016
  }
850
1017
  function RetrievalTab({ trace }) {
851
- return /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-2" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-slate-500 dark:text-white/40" }, trace.chunks.length, " chunk", trace.chunks.length !== 1 ? "s" : "", " retrieved", trace.rewrittenQuery && /* @__PURE__ */ import_react8.default.createElement("span", { className: "ml-2 italic" }, "(query rewritten: ", /* @__PURE__ */ import_react8.default.createElement("em", { className: "text-indigo-500" }, trace.rewrittenQuery), ")")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-1.5 max-h-56 overflow-y-auto pr-1 custom-scrollbar" }, trace.chunks.map((chunk, i) => /* @__PURE__ */ import_react8.default.createElement(
852
- "div",
853
- {
854
- key: String(chunk.id),
855
- className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5"
856
- },
857
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-between mb-1" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30" }, "[", i + 1, "] ", String(chunk.id).slice(0, 20)), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400" }, "score: ", chunk.score.toFixed(3))),
858
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "h-1 rounded-full bg-slate-200 dark:bg-white/10 mb-2 overflow-hidden" }, /* @__PURE__ */ import_react8.default.createElement(
1018
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-2", children: [
1019
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("p", { className: "text-[11px] text-slate-500 dark:text-white/40", children: [
1020
+ trace.chunks.length,
1021
+ " chunk",
1022
+ trace.chunks.length !== 1 ? "s" : "",
1023
+ " retrieved",
1024
+ trace.rewrittenQuery && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "ml-2 italic", children: [
1025
+ "(query rewritten: ",
1026
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("em", { className: "text-indigo-500", children: trace.rewrittenQuery }),
1027
+ ")"
1028
+ ] })
1029
+ ] }),
1030
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "space-y-1.5 max-h-56 overflow-y-auto pr-1 custom-scrollbar", children: trace.chunks.map((chunk, i) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
859
1031
  "div",
860
1032
  {
861
- className: "h-full rounded-full bg-indigo-500 dark:bg-indigo-400 transition-all",
862
- style: { width: `${Math.min(100, chunk.score * 100)}%` }
863
- }
864
- )),
865
- /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-slate-600 dark:text-white/60 line-clamp-2 leading-relaxed" }, chunk.content)
866
- ))));
1033
+ className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5",
1034
+ children: [
1035
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between mb-1", children: [
1036
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30", children: [
1037
+ "[",
1038
+ i + 1,
1039
+ "] ",
1040
+ String(chunk.id).slice(0, 20)
1041
+ ] }),
1042
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400", children: [
1043
+ "score: ",
1044
+ chunk.score.toFixed(3)
1045
+ ] })
1046
+ ] }),
1047
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "h-1 rounded-full bg-slate-200 dark:bg-white/10 mb-2 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1048
+ "div",
1049
+ {
1050
+ className: "h-full rounded-full bg-indigo-500 dark:bg-indigo-400 transition-all",
1051
+ style: { width: `${Math.min(100, chunk.score * 100)}%` }
1052
+ }
1053
+ ) }),
1054
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-slate-600 dark:text-white/60 line-clamp-2 leading-relaxed", children: chunk.content })
1055
+ ]
1056
+ },
1057
+ String(chunk.id)
1058
+ )) })
1059
+ ] });
867
1060
  }
868
1061
  function LatencyTab({ trace }) {
869
1062
  const { latency } = trace;
@@ -874,73 +1067,153 @@ function LatencyTab({ trace }) {
874
1067
  { label: "Generate", ms: latency.generateMs, color: "#8b5cf6" }
875
1068
  ];
876
1069
  const maxMs = Math.max(...bars.map((b) => b.ms), 1);
877
- return /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] text-slate-500 dark:text-white/40" }, "Pipeline stages"), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] font-semibold text-slate-700 dark:text-white/70" }, "Total: ", fmtMs(latency.totalMs))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-2" }, bars.map((bar) => /* @__PURE__ */ import_react8.default.createElement("div", { key: bar.label, className: "space-y-0.5" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] text-slate-600 dark:text-white/60" }, bar.label), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40" }, fmtMs(bar.ms))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "h-2 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden" }, /* @__PURE__ */ import_react8.default.createElement(
878
- "div",
879
- {
880
- className: "h-full rounded-full transition-all duration-700",
881
- style: {
882
- width: `${bar.ms / maxMs * 100}%`,
883
- background: bar.color,
884
- opacity: 0.85
885
- }
886
- }
887
- ))))));
1070
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-3", children: [
1071
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between", children: [
1072
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[11px] text-slate-500 dark:text-white/40", children: "Pipeline stages" }),
1073
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[11px] font-semibold text-slate-700 dark:text-white/70", children: [
1074
+ "Total: ",
1075
+ fmtMs(latency.totalMs)
1076
+ ] })
1077
+ ] }),
1078
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "space-y-2", children: bars.map((bar) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-0.5", children: [
1079
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between", children: [
1080
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[11px] text-slate-600 dark:text-white/60", children: bar.label }),
1081
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40", children: fmtMs(bar.ms) })
1082
+ ] }),
1083
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "h-2 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1084
+ "div",
1085
+ {
1086
+ className: "h-full rounded-full transition-all duration-700",
1087
+ style: {
1088
+ width: `${bar.ms / maxMs * 100}%`,
1089
+ background: bar.color,
1090
+ opacity: 0.85
1091
+ }
1092
+ }
1093
+ ) })
1094
+ ] }, bar.label)) })
1095
+ ] });
888
1096
  }
889
1097
  function TokensTab({ trace }) {
890
1098
  const { tokens } = trace;
891
1099
  if (!tokens) {
892
- return /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic" }, "Token data not available.");
1100
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic", children: "Token data not available." });
893
1101
  }
894
1102
  const stats = [
895
1103
  { label: "Prompt Tokens", value: fmtTokens(tokens.promptTokens), color: "text-indigo-600 dark:text-indigo-400" },
896
1104
  { label: "Completion Tokens", value: fmtTokens(tokens.completionTokens), color: "text-emerald-600 dark:text-emerald-400" },
897
1105
  { label: "Total Tokens", value: fmtTokens(tokens.totalTokens), color: "text-slate-700 dark:text-white/80" }
898
1106
  ];
899
- return /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "grid grid-cols-3 gap-2" }, stats.map((s) => /* @__PURE__ */ import_react8.default.createElement("div", { key: s.label, className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5 text-center" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: `text-lg font-bold ${s.color}` }, s.value), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[10px] text-slate-400 dark:text-white/30 mt-0.5" }, s.label)))), tokens.estimatedCostUsd != null && /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-between rounded-lg border border-emerald-100 dark:border-emerald-500/20 bg-emerald-50 dark:bg-emerald-500/10 px-3 py-2" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] text-emerald-700 dark:text-emerald-400 font-medium" }, "Estimated Cost"), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] font-bold text-emerald-700 dark:text-emerald-400" }, "$", tokens.estimatedCostUsd < 1e-4 ? tokens.estimatedCostUsd.toExponential(2) : tokens.estimatedCostUsd.toFixed(5), " USD")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "h-2 rounded-full overflow-hidden flex" }, /* @__PURE__ */ import_react8.default.createElement(
900
- "div",
901
- {
902
- className: "h-full bg-indigo-500 dark:bg-indigo-400",
903
- style: { width: `${tokens.promptTokens / tokens.totalTokens * 100}%` },
904
- title: "Prompt tokens"
905
- }
906
- ), /* @__PURE__ */ import_react8.default.createElement(
907
- "div",
908
- {
909
- className: "h-full bg-emerald-500 dark:bg-emerald-400",
910
- style: { width: `${tokens.completionTokens / tokens.totalTokens * 100}%` },
911
- title: "Completion tokens"
912
- }
913
- )), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex gap-3 text-[10px] text-slate-400 dark:text-white/30" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-indigo-500" }), " Prompt"), /* @__PURE__ */ import_react8.default.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }), " Completion")));
1107
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-3", children: [
1108
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "grid grid-cols-3 gap-2", children: stats.map((s) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5 text-center", children: [
1109
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: `text-lg font-bold ${s.color}`, children: s.value }),
1110
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[10px] text-slate-400 dark:text-white/30 mt-0.5", children: s.label })
1111
+ ] }, s.label)) }),
1112
+ tokens.estimatedCostUsd != null && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between rounded-lg border border-emerald-100 dark:border-emerald-500/20 bg-emerald-50 dark:bg-emerald-500/10 px-3 py-2", children: [
1113
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[11px] text-emerald-700 dark:text-emerald-400 font-medium", children: "Estimated Cost" }),
1114
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[11px] font-bold text-emerald-700 dark:text-emerald-400", children: [
1115
+ "$",
1116
+ tokens.estimatedCostUsd < 1e-4 ? tokens.estimatedCostUsd.toExponential(2) : tokens.estimatedCostUsd.toFixed(5),
1117
+ " USD"
1118
+ ] })
1119
+ ] }),
1120
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "h-2 rounded-full overflow-hidden flex", children: [
1121
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1122
+ "div",
1123
+ {
1124
+ className: "h-full bg-indigo-500 dark:bg-indigo-400",
1125
+ style: { width: `${tokens.promptTokens / tokens.totalTokens * 100}%` },
1126
+ title: "Prompt tokens"
1127
+ }
1128
+ ),
1129
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1130
+ "div",
1131
+ {
1132
+ className: "h-full bg-emerald-500 dark:bg-emerald-400",
1133
+ style: { width: `${tokens.completionTokens / tokens.totalTokens * 100}%` },
1134
+ title: "Completion tokens"
1135
+ }
1136
+ )
1137
+ ] }),
1138
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex gap-3 text-[10px] text-slate-400 dark:text-white/30", children: [
1139
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex items-center gap-1", children: [
1140
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-block w-2 h-2 rounded-full bg-indigo-500" }),
1141
+ " Prompt"
1142
+ ] }),
1143
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex items-center gap-1", children: [
1144
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }),
1145
+ " Completion"
1146
+ ] })
1147
+ ] })
1148
+ ] });
914
1149
  }
915
1150
  function HallucinationTab({ trace }) {
916
1151
  if (trace.hallucinationScore == null) {
917
- return /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic" }, "Hallucination scoring not available for this response.");
1152
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-slate-400 dark:text-white/30 italic", children: "Hallucination scoring not available for this response." });
918
1153
  }
919
1154
  const score = trace.hallucinationScore;
920
1155
  const pct = Math.round(score * 100);
921
1156
  const barColor = pct <= 20 ? "#10b981" : pct <= 50 ? "#f59e0b" : "#ef4444";
922
- return /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center justify-between" }, /* @__PURE__ */ import_react8.default.createElement(ScoreBadge, { score }), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40" }, pct, "/100")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "h-3 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden" }, /* @__PURE__ */ import_react8.default.createElement(
923
- "div",
924
- {
925
- className: "h-full rounded-full transition-all duration-700",
926
- style: { width: `${pct}%`, background: barColor }
927
- }
928
- )), trace.hallucinationReason && /* @__PURE__ */ import_react8.default.createElement("div", { className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-slate-500 dark:text-white/40 font-medium mb-0.5" }, "AI self-assessment"), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-slate-700 dark:text-white/70 leading-relaxed" }, trace.hallucinationReason)), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex gap-2 text-[10px] text-slate-400 dark:text-white/30" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }), " 0\u201320%: Grounded"), /* @__PURE__ */ import_react8.default.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-amber-500" }), " 21\u201350%: Uncertain"), /* @__PURE__ */ import_react8.default.createElement("span", { className: "flex items-center gap-1" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "inline-block w-2 h-2 rounded-full bg-red-500" }), " 51\u2013100%: Risk")));
1157
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-3", children: [
1158
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center justify-between", children: [
1159
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ScoreBadge, { score }),
1160
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[11px] font-mono text-slate-500 dark:text-white/40", children: [
1161
+ pct,
1162
+ "/100"
1163
+ ] })
1164
+ ] }),
1165
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "h-3 rounded-full bg-slate-100 dark:bg-white/8 overflow-hidden", children: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(
1166
+ "div",
1167
+ {
1168
+ className: "h-full rounded-full transition-all duration-700",
1169
+ style: { width: `${pct}%`, background: barColor }
1170
+ }
1171
+ ) }),
1172
+ trace.hallucinationReason && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 p-2.5", children: [
1173
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-slate-500 dark:text-white/40 font-medium mb-0.5", children: "AI self-assessment" }),
1174
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-slate-700 dark:text-white/70 leading-relaxed", children: trace.hallucinationReason })
1175
+ ] }),
1176
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex gap-2 text-[10px] text-slate-400 dark:text-white/30", children: [
1177
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex items-center gap-1", children: [
1178
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-block w-2 h-2 rounded-full bg-emerald-500" }),
1179
+ " 0\u201320%: Grounded"
1180
+ ] }),
1181
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex items-center gap-1", children: [
1182
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-block w-2 h-2 rounded-full bg-amber-500" }),
1183
+ " 21\u201350%: Uncertain"
1184
+ ] }),
1185
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "flex items-center gap-1", children: [
1186
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "inline-block w-2 h-2 rounded-full bg-red-500" }),
1187
+ " 51\u2013100%: Risk"
1188
+ ] })
1189
+ ] })
1190
+ ] });
929
1191
  }
930
1192
  function PromptTab({ trace }) {
931
- const [showSystem, setShowSystem] = import_react8.default.useState(false);
932
- return /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-3" }, /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement(
933
- "button",
934
- {
935
- onClick: () => setShowSystem((s) => !s),
936
- className: "flex items-center gap-1.5 text-[11px] font-semibold text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/80 transition-colors mb-1.5"
937
- },
938
- showSystem ? /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.ChevronRight, { className: "w-3 h-3" }),
939
- "System Prompt"
940
- ), showSystem && /* @__PURE__ */ import_react8.default.createElement("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed" }, trace.systemPrompt || "(empty)")), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] font-semibold text-slate-600 dark:text-white/60 mb-1.5" }, "User Prompt"), /* @__PURE__ */ import_react8.default.createElement("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed" }, trace.userPrompt)));
1193
+ const [showSystem, setShowSystem] = import_react6.default.useState(false);
1194
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "space-y-3", children: [
1195
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1196
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1197
+ "button",
1198
+ {
1199
+ onClick: () => setShowSystem((s) => !s),
1200
+ className: "flex items-center gap-1.5 text-[11px] font-semibold text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/80 transition-colors mb-1.5",
1201
+ children: [
1202
+ showSystem ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.ChevronRight, { className: "w-3 h-3" }),
1203
+ "System Prompt"
1204
+ ]
1205
+ }
1206
+ ),
1207
+ showSystem && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed", children: trace.systemPrompt || "(empty)" })
1208
+ ] }),
1209
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1210
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] font-semibold text-slate-600 dark:text-white/60 mb-1.5", children: "User Prompt" }),
1211
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { className: "text-[10px] font-mono text-slate-600 dark:text-white/60 bg-slate-900 dark:bg-black/30 rounded-lg p-3 overflow-auto max-h-40 whitespace-pre-wrap leading-relaxed", children: trace.userPrompt })
1212
+ ] })
1213
+ ] });
941
1214
  }
942
1215
  function ChunksTab({ trace }) {
943
- const [expanded, setExpanded] = import_react8.default.useState(/* @__PURE__ */ new Set());
1216
+ const [expanded, setExpanded] = import_react6.default.useState(/* @__PURE__ */ new Set());
944
1217
  const toggle = (i) => setExpanded((prev) => {
945
1218
  const next = new Set(prev);
946
1219
  if (next.has(i)) {
@@ -950,74 +1223,111 @@ function ChunksTab({ trace }) {
950
1223
  }
951
1224
  return next;
952
1225
  });
953
- return /* @__PURE__ */ import_react8.default.createElement("div", { className: "space-y-1.5 max-h-64 overflow-y-auto pr-1 custom-scrollbar" }, trace.chunks.map((chunk, i) => {
1226
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "space-y-1.5 max-h-64 overflow-y-auto pr-1 custom-scrollbar", children: trace.chunks.map((chunk, i) => {
954
1227
  const isOpen = expanded.has(i);
955
- return /* @__PURE__ */ import_react8.default.createElement(
1228
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
956
1229
  "div",
957
1230
  {
958
- key: String(chunk.id),
959
- className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 overflow-hidden"
1231
+ className: "rounded-lg border border-slate-100 dark:border-white/8 bg-slate-50 dark:bg-white/3 overflow-hidden",
1232
+ children: [
1233
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1234
+ "button",
1235
+ {
1236
+ onClick: () => toggle(i),
1237
+ className: "w-full flex items-center justify-between px-3 py-2 text-left hover:bg-slate-100 dark:hover:bg-white/5 transition-colors",
1238
+ children: [
1239
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "flex items-center gap-2", children: [
1240
+ isOpen ? /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.ChevronDown, { className: "w-3 h-3 text-slate-400" }) : /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.ChevronRight, { className: "w-3 h-3 text-slate-400" }),
1241
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("span", { className: "text-[11px] font-medium text-slate-700 dark:text-white/70", children: [
1242
+ "Chunk ",
1243
+ i + 1
1244
+ ] }),
1245
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30", children: String(chunk.id).slice(0, 16) })
1246
+ ] }),
1247
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400", children: chunk.score.toFixed(3) })
1248
+ ]
1249
+ }
1250
+ ),
1251
+ isOpen && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "px-3 pb-3 space-y-2 border-t border-slate-100 dark:border-white/5 pt-2", children: [
1252
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1253
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1", children: "Content" }),
1254
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[11px] text-slate-600 dark:text-white/60 leading-relaxed whitespace-pre-wrap", children: chunk.content })
1255
+ ] }),
1256
+ Object.keys(chunk.metadata).length > 0 && /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { children: [
1257
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1", children: "Metadata" }),
1258
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("pre", { className: "text-[10px] font-mono text-slate-500 dark:text-white/40 bg-slate-900 dark:bg-black/30 rounded-md p-2 overflow-auto max-h-24", children: JSON.stringify(chunk.metadata, null, 2) })
1259
+ ] })
1260
+ ] })
1261
+ ]
960
1262
  },
961
- /* @__PURE__ */ import_react8.default.createElement(
962
- "button",
963
- {
964
- onClick: () => toggle(i),
965
- className: "w-full flex items-center justify-between px-3 py-2 text-left hover:bg-slate-100 dark:hover:bg-white/5 transition-colors"
966
- },
967
- /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2" }, isOpen ? /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.ChevronDown, { className: "w-3 h-3 text-slate-400" }) : /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.ChevronRight, { className: "w-3 h-3 text-slate-400" }), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[11px] font-medium text-slate-700 dark:text-white/70" }, "Chunk ", i + 1), /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] font-mono text-slate-400 dark:text-white/30" }, String(chunk.id).slice(0, 16))),
968
- /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] font-semibold text-indigo-600 dark:text-indigo-400" }, chunk.score.toFixed(3))
969
- ),
970
- isOpen && /* @__PURE__ */ import_react8.default.createElement("div", { className: "px-3 pb-3 space-y-2 border-t border-slate-100 dark:border-white/5 pt-2" }, /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1" }, "Content"), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[11px] text-slate-600 dark:text-white/60 leading-relaxed whitespace-pre-wrap" }, chunk.content)), Object.keys(chunk.metadata).length > 0 && /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[10px] text-slate-400 dark:text-white/30 font-semibold uppercase tracking-wider mb-1" }, "Metadata"), /* @__PURE__ */ import_react8.default.createElement("pre", { className: "text-[10px] font-mono text-slate-500 dark:text-white/40 bg-slate-900 dark:bg-black/30 rounded-md p-2 overflow-auto max-h-24" }, JSON.stringify(chunk.metadata, null, 2))))
1263
+ String(chunk.id)
971
1264
  );
972
- }));
1265
+ }) });
973
1266
  }
974
1267
  var TABS = [
975
- { id: "retrieval", label: "Retrieval", icon: /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Layers, { className: "w-3 h-3" }) },
976
- { id: "latency", label: "Latency", icon: /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Clock, { className: "w-3 h-3" }) },
977
- { id: "tokens", label: "Tokens", icon: /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Cpu, { className: "w-3 h-3" }) },
978
- { id: "hallucination", label: "Grounding", icon: /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.AlertTriangle, { className: "w-3 h-3" }) },
979
- { id: "prompt", label: "Prompt", icon: /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.FileText, { className: "w-3 h-3" }) },
980
- { id: "chunks", label: "Chunks", icon: /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Zap, { className: "w-3 h-3" }) }
1268
+ { id: "retrieval", label: "Retrieval", icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.Layers, { className: "w-3 h-3" }) },
1269
+ { id: "latency", label: "Latency", icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.Clock, { className: "w-3 h-3" }) },
1270
+ { id: "tokens", label: "Tokens", icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.Cpu, { className: "w-3 h-3" }) },
1271
+ { id: "hallucination", label: "Grounding", icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.AlertTriangle, { className: "w-3 h-3" }) },
1272
+ { id: "prompt", label: "Prompt", icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.FileText, { className: "w-3 h-3" }) },
1273
+ { id: "chunks", label: "Chunks", icon: /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.Zap, { className: "w-3 h-3" }) }
981
1274
  ];
982
1275
  function ObservabilityPanel({ trace, primaryColor = "#6366f1" }) {
983
- const [activeTab, setActiveTab] = import_react8.default.useState("retrieval");
984
- return /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-2 w-full rounded-xl border border-slate-200 dark:border-white/8 bg-white dark:bg-slate-900/60 shadow-sm overflow-hidden text-[12px]" }, /* @__PURE__ */ import_react8.default.createElement(
985
- "div",
986
- {
987
- className: "flex items-center gap-2 px-3 py-2 border-b border-slate-100 dark:border-white/8",
988
- style: { background: `${primaryColor}08` }
989
- },
990
- /* @__PURE__ */ import_react8.default.createElement(
991
- "span",
1276
+ const [activeTab, setActiveTab] = import_react6.default.useState("retrieval");
1277
+ return /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "mt-2 w-[500px] max-w-full rounded-xl border border-slate-200 dark:border-white/8 bg-white dark:bg-slate-900/60 shadow-sm overflow-hidden text-[12px]", children: [
1278
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1279
+ "div",
992
1280
  {
993
- className: "inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider",
994
- style: { color: primaryColor }
995
- },
996
- /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Zap, { className: "w-3 h-3" }),
997
- "Observability Trace"
1281
+ className: "flex items-center gap-2 px-3 py-2 border-b border-slate-100 dark:border-white/8",
1282
+ style: { background: `${primaryColor}08` },
1283
+ children: [
1284
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1285
+ "span",
1286
+ {
1287
+ className: "inline-flex items-center gap-1 text-[10px] font-bold uppercase tracking-wider",
1288
+ style: { color: primaryColor },
1289
+ children: [
1290
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(import_lucide_react5.Zap, { className: "w-3 h-3" }),
1291
+ "Observability Trace"
1292
+ ]
1293
+ }
1294
+ ),
1295
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("span", { className: "text-[10px] text-slate-400 dark:text-white/30 ml-auto font-mono", children: trace.requestId })
1296
+ ]
1297
+ }
998
1298
  ),
999
- /* @__PURE__ */ import_react8.default.createElement("span", { className: "text-[10px] text-slate-400 dark:text-white/30 ml-auto font-mono" }, trace.requestId)
1000
- ), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex border-b border-slate-100 dark:border-white/8 overflow-x-auto" }, TABS.map((tab) => /* @__PURE__ */ import_react8.default.createElement(
1001
- "button",
1002
- {
1003
- key: tab.id,
1004
- onClick: () => setActiveTab(tab.id),
1005
- className: `flex items-center gap-1.5 px-3 py-2 text-[10px] font-semibold whitespace-nowrap transition-colors border-b-2 ${activeTab === tab.id ? "border-b-2 text-indigo-600 dark:text-indigo-400" : "border-transparent text-slate-400 dark:text-white/30 hover:text-slate-600 dark:hover:text-white/60"}`,
1006
- style: activeTab === tab.id ? { borderBottomColor: primaryColor, color: primaryColor } : {}
1007
- },
1008
- tab.icon,
1009
- tab.label
1010
- ))), /* @__PURE__ */ import_react8.default.createElement("div", { className: "p-3" }, activeTab === "retrieval" && /* @__PURE__ */ import_react8.default.createElement(RetrievalTab, { trace }), activeTab === "latency" && /* @__PURE__ */ import_react8.default.createElement(LatencyTab, { trace }), activeTab === "tokens" && /* @__PURE__ */ import_react8.default.createElement(TokensTab, { trace }), activeTab === "hallucination" && /* @__PURE__ */ import_react8.default.createElement(HallucinationTab, { trace }), activeTab === "prompt" && /* @__PURE__ */ import_react8.default.createElement(PromptTab, { trace }), activeTab === "chunks" && /* @__PURE__ */ import_react8.default.createElement(ChunksTab, { trace })));
1299
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsx)("div", { className: "flex border-b border-slate-100 dark:border-white/8 overflow-x-auto", children: TABS.map((tab) => /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)(
1300
+ "button",
1301
+ {
1302
+ onClick: () => setActiveTab(tab.id),
1303
+ className: `flex items-center gap-1.5 px-3 py-2 text-[10px] font-semibold whitespace-nowrap transition-colors border-b-2 ${activeTab === tab.id ? "border-b-2 text-indigo-600 dark:text-indigo-400" : "border-transparent text-slate-400 dark:text-white/30 hover:text-slate-600 dark:hover:text-white/60"}`,
1304
+ style: activeTab === tab.id ? { borderBottomColor: primaryColor, color: primaryColor } : {},
1305
+ children: [
1306
+ tab.icon,
1307
+ tab.label
1308
+ ]
1309
+ },
1310
+ tab.id
1311
+ )) }),
1312
+ /* @__PURE__ */ (0, import_jsx_runtime8.jsxs)("div", { className: "p-3", children: [
1313
+ activeTab === "retrieval" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(RetrievalTab, { trace }),
1314
+ activeTab === "latency" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(LatencyTab, { trace }),
1315
+ activeTab === "tokens" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(TokensTab, { trace }),
1316
+ activeTab === "hallucination" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(HallucinationTab, { trace }),
1317
+ activeTab === "prompt" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(PromptTab, { trace }),
1318
+ activeTab === "chunks" && /* @__PURE__ */ (0, import_jsx_runtime8.jsx)(ChunksTab, { trace })
1319
+ ] })
1320
+ ] });
1011
1321
  }
1012
1322
 
1013
1323
  // src/components/HourglassLoader.tsx
1014
- var import_react9 = __toESM(require("react"));
1324
+ var import_jsx_runtime9 = require("react/jsx-runtime");
1015
1325
  var HourglassLoader = ({
1016
1326
  size = 16,
1017
1327
  primaryColor = "#10b981",
1018
1328
  glow = false
1019
1329
  }) => {
1020
- return /* @__PURE__ */ import_react9.default.createElement(
1330
+ return /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1021
1331
  "svg",
1022
1332
  {
1023
1333
  xmlns: "http://www.w3.org/2000/svg",
@@ -1028,58 +1338,64 @@ var HourglassLoader = ({
1028
1338
  height: size,
1029
1339
  background: "transparent",
1030
1340
  filter: glow ? `drop-shadow(0 0 4px ${primaryColor})` : "none"
1031
- }
1032
- },
1033
- /* @__PURE__ */ import_react9.default.createElement("g", null, /* @__PURE__ */ import_react9.default.createElement(
1034
- "animateTransform",
1035
- {
1036
- attributeName: "transform",
1037
- type: "rotate",
1038
- calcMode: "spline",
1039
- values: "0 50 50; 0 50 50; 180 50 50",
1040
- keyTimes: "0; 0.8; 1",
1041
- keySplines: "0 0 1 1; 0.4 0 0.2 1",
1042
- dur: "2s",
1043
- repeatCount: "indefinite"
1044
- }
1045
- ), /* @__PURE__ */ import_react9.default.createElement(
1046
- "path",
1047
- {
1048
- d: "M 25 15 L 75 15 L 75 20 L 55 50 L 75 80 L 75 85 L 25 85 L 25 80 L 45 50 L 25 20 Z",
1049
- fill: "none",
1050
- stroke: primaryColor,
1051
- strokeWidth: "5",
1052
- strokeLinejoin: "round",
1053
- strokeLinecap: "round"
1054
- }
1055
- ), /* @__PURE__ */ import_react9.default.createElement("path", { fill: primaryColor }, /* @__PURE__ */ import_react9.default.createElement(
1056
- "animate",
1057
- {
1058
- attributeName: "d",
1059
- values: "M 30 20 L 70 20 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z",
1060
- keyTimes: "0; 0.8; 1",
1061
- dur: "2s",
1062
- repeatCount: "indefinite"
1063
- }
1064
- )), /* @__PURE__ */ import_react9.default.createElement("path", { fill: primaryColor }, /* @__PURE__ */ import_react9.default.createElement(
1065
- "animate",
1066
- {
1067
- attributeName: "d",
1068
- values: "M 30 80 L 70 80 L 70 80 L 30 80 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z",
1069
- keyTimes: "0; 0.8; 1",
1070
- dur: "2s",
1071
- repeatCount: "indefinite"
1072
- }
1073
- )), /* @__PURE__ */ import_react9.default.createElement("line", { x1: "50", y1: "50", x2: "50", y2: "80", stroke: primaryColor, strokeWidth: "3" }, /* @__PURE__ */ import_react9.default.createElement(
1074
- "animate",
1075
- {
1076
- attributeName: "opacity",
1077
- values: "0; 1; 1; 0; 0",
1078
- keyTimes: "0; 0.1; 0.7; 0.8; 1",
1079
- dur: "2s",
1080
- repeatCount: "indefinite"
1081
- }
1082
- )))
1341
+ },
1342
+ children: /* @__PURE__ */ (0, import_jsx_runtime9.jsxs)("g", { children: [
1343
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1344
+ "animateTransform",
1345
+ {
1346
+ attributeName: "transform",
1347
+ type: "rotate",
1348
+ calcMode: "spline",
1349
+ values: "0 50 50; 0 50 50; 180 50 50",
1350
+ keyTimes: "0; 0.8; 1",
1351
+ keySplines: "0 0 1 1; 0.4 0 0.2 1",
1352
+ dur: "2s",
1353
+ repeatCount: "indefinite"
1354
+ }
1355
+ ),
1356
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1357
+ "path",
1358
+ {
1359
+ d: "M 25 15 L 75 15 L 75 20 L 55 50 L 75 80 L 75 85 L 25 85 L 25 80 L 45 50 L 25 20 Z",
1360
+ fill: "none",
1361
+ stroke: primaryColor,
1362
+ strokeWidth: "5",
1363
+ strokeLinejoin: "round",
1364
+ strokeLinecap: "round"
1365
+ }
1366
+ ),
1367
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { fill: primaryColor, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1368
+ "animate",
1369
+ {
1370
+ attributeName: "d",
1371
+ values: "M 30 20 L 70 20 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z; M 50 50 L 50 50 L 50 50 L 50 50 Z",
1372
+ keyTimes: "0; 0.8; 1",
1373
+ dur: "2s",
1374
+ repeatCount: "indefinite"
1375
+ }
1376
+ ) }),
1377
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("path", { fill: primaryColor, children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1378
+ "animate",
1379
+ {
1380
+ attributeName: "d",
1381
+ values: "M 30 80 L 70 80 L 70 80 L 30 80 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z; M 30 80 L 70 80 L 50 50 L 50 50 Z",
1382
+ keyTimes: "0; 0.8; 1",
1383
+ dur: "2s",
1384
+ repeatCount: "indefinite"
1385
+ }
1386
+ ) }),
1387
+ /* @__PURE__ */ (0, import_jsx_runtime9.jsx)("line", { x1: "50", y1: "50", x2: "50", y2: "80", stroke: primaryColor, strokeWidth: "3", children: /* @__PURE__ */ (0, import_jsx_runtime9.jsx)(
1388
+ "animate",
1389
+ {
1390
+ attributeName: "opacity",
1391
+ values: "0; 1; 1; 0; 0",
1392
+ keyTimes: "0; 0.1; 0.7; 0.8; 1",
1393
+ dur: "2s",
1394
+ repeatCount: "indefinite"
1395
+ }
1396
+ ) })
1397
+ ] })
1398
+ }
1083
1399
  );
1084
1400
  };
1085
1401
  var HourglassLoader_default = HourglassLoader;
@@ -1332,7 +1648,6 @@ function extractProductsFromSources(sources, isUser) {
1332
1648
  const brand = resolveMetadataValue(m, "brand");
1333
1649
  const price = resolveMetadataValue(m, "price");
1334
1650
  const description = resolveMetadataValue(m, "description");
1335
- console.log("\u{1F680} ~ extractProductsFromSources ~ description:", s);
1336
1651
  return {
1337
1652
  id: s.id,
1338
1653
  name: (_b = name != null ? name : s.content.split("\n")[0]) != null ? _b : "Unknown Product",
@@ -1345,7 +1660,7 @@ function extractProductsFromSources(sources, isUser) {
1345
1660
  };
1346
1661
  });
1347
1662
  }
1348
- function extractProductsFromContent(content, payloadText, payloadCandidates, productsFromSources) {
1663
+ function extractProductsFromContent(content, payloadText, payloadCandidates, productsFromSources, isStreaming = false) {
1349
1664
  var _a, _b;
1350
1665
  const jsonRegex = /```(?:json|ui)?\s*([\s\S]*?)\s*```/g;
1351
1666
  const products = [];
@@ -1388,7 +1703,7 @@ function extractProductsFromContent(content, payloadText, payloadCandidates, pro
1388
1703
  }
1389
1704
  const bulletRegex = /^[ \t]*(?:[•*-]|\d+\.)\s+(?:\*\*)?([^\n\-\$–—\(]+?)(?:\*\*)?(?:\s*\(?Price\s*[:\-–—]?\s*)?(?:\s*[:\-–—]\s*|\s+)\$?([\d,.]+)(?:\s*USD)?/gim;
1390
1705
  const matches = Array.from(cleanContent.matchAll(bulletRegex));
1391
- if (matches.length >= 2) {
1706
+ if (!isStreaming && matches.length >= 2) {
1392
1707
  const normalize = (s) => s.toLowerCase().replace(/[^a-z0-9]/g, "");
1393
1708
  for (const match of matches) {
1394
1709
  let name = ((_a = match[1]) == null ? void 0 : _a.trim()) || "";
@@ -1440,10 +1755,11 @@ function deduplicateProducts(productsFromSources, productsFromContent, messageCo
1440
1755
  }
1441
1756
 
1442
1757
  // src/components/MarkdownComponents.tsx
1443
- var import_react11 = __toESM(require("react"));
1758
+ var import_react8 = __toESM(require("react"));
1444
1759
 
1445
1760
  // src/components/UIDispatcher.tsx
1446
- var import_react10 = __toESM(require("react"));
1761
+ var import_react7 = __toESM(require("react"));
1762
+ var import_jsx_runtime10 = require("react/jsx-runtime");
1447
1763
  function normalizeTabularRows(rows, columns) {
1448
1764
  if (!Array.isArray(rows)) return [];
1449
1765
  const SYNONYMS = {
@@ -1511,7 +1827,7 @@ function resolveStructuredRows(config) {
1511
1827
  }
1512
1828
  function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAddToCart, viewportSize = "large" }) {
1513
1829
  var _a;
1514
- const result = import_react10.default.useMemo(() => {
1830
+ const result = import_react7.default.useMemo(() => {
1515
1831
  try {
1516
1832
  const clean = rawContent.replace(/^```[a-z]*\s*/i, "").replace(/```\s*$/, "").trim();
1517
1833
  const parsed = JSON.parse(sanitizeJson(extractLikelyJsonBlock(clean)));
@@ -1556,72 +1872,87 @@ function UIDispatcher({ rawContent, primaryColor, accentColor, isStreaming, onAd
1556
1872
  }
1557
1873
  }, [rawContent, isStreaming]);
1558
1874
  if ("loading" in result) {
1559
- return /* @__PURE__ */ import_react10.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_react10.default.createElement("div", { className: "w-5 h-5 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic" }, "Preparing view..."));
1875
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("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", children: [
1876
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "w-5 h-5 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }),
1877
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: "text-xs text-slate-500 font-medium italic", children: "Preparing view..." })
1878
+ ] });
1560
1879
  }
1561
1880
  if ("error" in result) {
1562
- return /* @__PURE__ */ import_react10.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_react10.default.createElement("code", null, rawContent));
1881
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("pre", { className: "p-4 my-2 bg-slate-900 text-slate-100 rounded-lg text-[10px] overflow-auto max-h-40", children: /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("code", { children: rawContent }) });
1563
1882
  }
1564
1883
  const { config } = result;
1565
1884
  const isCompact = viewportSize === "compact";
1566
1885
  const hasInsights = Array.isArray(config.insights) && config.insights.length > 0;
1567
1886
  const hasDescription = typeof config.description === "string" && config.description.trim().length > 0;
1568
- console.log("\u{1F680} ~ UIDispatcher ~ description:", config.description);
1569
- console.log("\u{1F680} ~ UIDispatcher ~ hasDescription:", hasDescription);
1570
1887
  switch (config.view) {
1571
1888
  case "chart":
1572
- return /* @__PURE__ */ import_react10.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_react10.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_react10.default.createElement("p", { className: `px-2 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react10.default.createElement(
1573
- DynamicChart,
1574
- {
1575
- config: {
1576
- type: config.chartType || "bar",
1577
- data: config.data,
1578
- xAxisKey: config.xAxisKey,
1579
- dataKeys: config.dataKeys,
1580
- colors: config.colors
1889
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("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`, children: [
1890
+ config.title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h4", { className: `${isCompact ? "text-[11px] mb-3" : "text-xs mb-4"} font-semibold text-slate-500 px-2`, children: config.title }),
1891
+ hasDescription && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: `px-2 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60`, children: config.description }),
1892
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1893
+ DynamicChart,
1894
+ {
1895
+ config: {
1896
+ type: config.chartType || "bar",
1897
+ data: config.data,
1898
+ xAxisKey: config.xAxisKey,
1899
+ dataKeys: config.dataKeys,
1900
+ colors: config.colors
1901
+ },
1902
+ primaryColor,
1903
+ accentColor,
1904
+ viewportSize,
1905
+ isStreaming
1906
+ }
1907
+ ),
1908
+ hasInsights && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("div", { className: "mt-4 flex flex-wrap gap-2 px-2", children: (_a = config.insights) == null ? void 0 : _a.map((insight, i) => /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1909
+ "span",
1910
+ {
1911
+ className: `rounded-full border border-emerald-200 bg-emerald-50 ${isCompact ? "px-2.5 py-1 text-[10px]" : "px-3 py-1 text-[11px]"} font-medium text-emerald-700 dark:border-emerald-500/20 dark:bg-emerald-500/10 dark:text-emerald-300`,
1912
+ children: String(insight)
1581
1913
  },
1582
- primaryColor,
1583
- accentColor,
1584
- viewportSize,
1585
- isStreaming
1586
- }
1587
- ), hasInsights && /* @__PURE__ */ import_react10.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_react10.default.createElement(
1588
- "span",
1589
- {
1590
- key: `insight-${i}`,
1591
- className: `rounded-full border border-emerald-200 bg-emerald-50 ${isCompact ? "px-2.5 py-1 text-[10px]" : "px-3 py-1 text-[11px]"} font-medium text-emerald-700 dark:border-emerald-500/20 dark:bg-emerald-500/10 dark:text-emerald-300`
1592
- },
1593
- String(insight)
1594
- ))));
1914
+ `insight-${i}`
1915
+ )) })
1916
+ ] });
1595
1917
  case "carousel":
1596
- return /* @__PURE__ */ import_react10.default.createElement("div", { className: "my-4" }, config.title && /* @__PURE__ */ import_react10.default.createElement("h4", { className: `${isCompact ? "mb-1.5 text-[11px]" : "mb-2 text-xs"} font-semibold text-slate-500` }, config.title), hasDescription && /* @__PURE__ */ import_react10.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react10.default.createElement(ProductCarousel, { products: config.data.map((item) => {
1597
- var _a2;
1598
- return __spreadProps(__spreadValues({}, item), {
1599
- image: (_a2 = item.image) != null ? _a2 : typeof resolveImage === "function" ? resolveImage(item) : void 0
1600
- });
1601
- }), primaryColor, onAddToCart }));
1918
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("div", { className: "my-4", children: [
1919
+ config.title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h4", { className: `${isCompact ? "mb-1.5 text-[11px]" : "mb-2 text-xs"} font-semibold text-slate-500`, children: config.title }),
1920
+ hasDescription && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60`, children: config.description }),
1921
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(ProductCarousel, { products: config.data.map((item) => {
1922
+ var _a2;
1923
+ return __spreadProps(__spreadValues({}, item), {
1924
+ image: (_a2 = item.image) != null ? _a2 : typeof resolveImage === "function" ? resolveImage(item) : void 0
1925
+ });
1926
+ }), primaryColor, onAddToCart })
1927
+ ] });
1602
1928
  case "table":
1603
- return /* @__PURE__ */ import_react10.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_react10.default.createElement("h4", { className: `${isCompact ? "text-[11px]" : "text-xs"} font-semibold text-slate-500 mb-2` }, config.title), hasDescription && /* @__PURE__ */ import_react10.default.createElement("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60` }, config.description), /* @__PURE__ */ import_react10.default.createElement(
1604
- VisualizationRenderer,
1605
- {
1606
- data: {
1607
- type: "table",
1608
- title: config.title || "",
1609
- description: config.description,
1929
+ return /* @__PURE__ */ (0, import_jsx_runtime10.jsxs)("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`, children: [
1930
+ config.title && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("h4", { className: `${isCompact ? "text-[11px]" : "text-xs"} font-semibold text-slate-500 mb-2`, children: config.title }),
1931
+ hasDescription && /* @__PURE__ */ (0, import_jsx_runtime10.jsx)("p", { className: `mb-3 ${isCompact ? "text-xs" : "text-sm"} text-slate-500 dark:text-white/60`, children: config.description }),
1932
+ /* @__PURE__ */ (0, import_jsx_runtime10.jsx)(
1933
+ VisualizationRenderer,
1934
+ {
1610
1935
  data: {
1611
- columns: config.columns || Object.keys(config.data[0] || {}),
1612
- rows: config.data.map((row) => Object.values(row))
1613
- }
1614
- },
1615
- primaryColor,
1616
- isStreaming
1617
- }
1618
- ));
1936
+ type: "table",
1937
+ title: config.title || "",
1938
+ description: config.description,
1939
+ data: {
1940
+ columns: config.columns || Object.keys(config.data[0] || {}),
1941
+ rows: config.data.map((row) => Object.values(row))
1942
+ }
1943
+ },
1944
+ primaryColor,
1945
+ isStreaming
1946
+ }
1947
+ )
1948
+ ] });
1619
1949
  default:
1620
1950
  return null;
1621
1951
  }
1622
1952
  }
1623
1953
 
1624
1954
  // src/components/MarkdownComponents.tsx
1955
+ var import_jsx_runtime11 = require("react/jsx-runtime");
1625
1956
  function createMarkdownComponents({
1626
1957
  primaryColor,
1627
1958
  accentColor,
@@ -1630,66 +1961,75 @@ function createMarkdownComponents({
1630
1961
  viewportSize
1631
1962
  }) {
1632
1963
  return {
1633
- table: (_a) => {
1964
+ p: (_a) => {
1634
1965
  var props = __objRest(_a, []);
1966
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", __spreadValues({ className: "whitespace-pre-line" }, props));
1967
+ },
1968
+ table: (_b) => {
1969
+ var props = __objRest(_b, []);
1635
1970
  if (isStreaming) {
1636
- return /* @__PURE__ */ import_react11.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_react11.default.createElement("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }), /* @__PURE__ */ import_react11.default.createElement("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse" }, "Generating data table..."));
1971
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsxs)("div", { className: "my-5 p-6 bg-slate-50 dark:bg-white/5 rounded-xl border border-dashed border-slate-300 dark:border-white/10 flex items-center justify-center gap-3 select-none", children: [
1972
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "w-4 h-4 border-2 border-indigo-500 border-t-transparent rounded-full animate-spin" }),
1973
+ /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("p", { className: "text-xs text-slate-500 font-medium italic animate-pulse", children: "Generating data table..." })
1974
+ ] });
1637
1975
  }
1638
- return /* @__PURE__ */ import_react11.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_react11.default.createElement("div", { className: "overflow-x-auto" }, /* @__PURE__ */ import_react11.default.createElement(
1976
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("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", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("div", { className: "overflow-x-auto", children: /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1639
1977
  "table",
1640
1978
  __spreadValues({
1641
1979
  className: "!table w-full text-left border-collapse min-w-[400px] text-sm"
1642
1980
  }, props)
1643
- )));
1981
+ ) }) });
1644
1982
  },
1645
- thead: (_b) => {
1646
- var props = __objRest(_b, []);
1647
- return /* @__PURE__ */ import_react11.default.createElement(
1983
+ thead: (_c) => {
1984
+ var props = __objRest(_c, []);
1985
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1648
1986
  "thead",
1649
1987
  __spreadValues({
1650
1988
  className: "!table-header-group bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10"
1651
1989
  }, props)
1652
1990
  );
1653
1991
  },
1654
- tbody: (_c) => {
1655
- var props = __objRest(_c, []);
1656
- return /* @__PURE__ */ import_react11.default.createElement("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
1657
- },
1658
- tr: (_d) => {
1992
+ tbody: (_d) => {
1659
1993
  var props = __objRest(_d, []);
1660
- return /* @__PURE__ */ import_react11.default.createElement(
1994
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("tbody", __spreadValues({ className: "!table-row-group divide-y divide-slate-100 dark:divide-white/5" }, props));
1995
+ },
1996
+ tr: (_e) => {
1997
+ var props = __objRest(_e, []);
1998
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1661
1999
  "tr",
1662
2000
  __spreadValues({
1663
2001
  className: "!table-row hover:bg-slate-50/70 dark:hover:bg-white/5 transition-colors"
1664
2002
  }, props)
1665
2003
  );
1666
2004
  },
1667
- th: (_e) => {
1668
- var _f = _e, { children } = _f, props = __objRest(_f, ["children"]);
1669
- return /* @__PURE__ */ import_react11.default.createElement(
2005
+ th: (_f) => {
2006
+ var _g = _f, { children } = _g, props = __objRest(_g, ["children"]);
2007
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1670
2008
  "th",
1671
- __spreadValues({
2009
+ __spreadProps(__spreadValues({
1672
2010
  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"
1673
- }, props),
1674
- normaliseChild(children)
2011
+ }, props), {
2012
+ children: normaliseChild(children)
2013
+ })
1675
2014
  );
1676
2015
  },
1677
- td: (_g) => {
1678
- var _h = _g, { children } = _h, props = __objRest(_h, ["children"]);
1679
- return /* @__PURE__ */ import_react11.default.createElement(
2016
+ td: (_h) => {
2017
+ var _i = _h, { children } = _i, props = __objRest(_i, ["children"]);
2018
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1680
2019
  "td",
1681
- __spreadValues({
2020
+ __spreadProps(__spreadValues({
1682
2021
  className: "!table-cell px-4 py-3 text-slate-600 dark:text-white/70 whitespace-nowrap text-sm"
1683
- }, props),
1684
- normaliseChild(children)
2022
+ }, props), {
2023
+ children: normaliseChild(children)
2024
+ })
1685
2025
  );
1686
2026
  },
1687
- code(_i) {
1688
- var _j = _i, {
2027
+ code(_j) {
2028
+ var _k = _j, {
1689
2029
  inline,
1690
2030
  className,
1691
2031
  children
1692
- } = _j, props = __objRest(_j, [
2032
+ } = _k, props = __objRest(_k, [
1693
2033
  "inline",
1694
2034
  "className",
1695
2035
  "children"
@@ -1698,7 +2038,7 @@ function createMarkdownComponents({
1698
2038
  const lang = (_a = /language-(\w+)/.exec(className != null ? className : "")) == null ? void 0 : _a[1];
1699
2039
  if (!inline && (lang === "ui" || lang === "chart" || lang === "json")) {
1700
2040
  const content = String(children != null ? children : "").trim();
1701
- return /* @__PURE__ */ import_react11.default.createElement(
2041
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1702
2042
  UIDispatcher,
1703
2043
  {
1704
2044
  rawContent: content,
@@ -1713,7 +2053,7 @@ function createMarkdownComponents({
1713
2053
  if (!inline) {
1714
2054
  const content = String(children != null ? children : "").trim();
1715
2055
  if (content.startsWith("{") && content.endsWith("}")) {
1716
- return /* @__PURE__ */ import_react11.default.createElement(
2056
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)(
1717
2057
  UIDispatcher,
1718
2058
  {
1719
2059
  rawContent: content,
@@ -1726,18 +2066,19 @@ function createMarkdownComponents({
1726
2066
  );
1727
2067
  }
1728
2068
  }
1729
- return /* @__PURE__ */ import_react11.default.createElement("code", __spreadValues({ className }, props), typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children));
2069
+ return /* @__PURE__ */ (0, import_jsx_runtime11.jsx)("code", __spreadProps(__spreadValues({ className }, props), { children: typeof children === "string" || typeof children === "number" ? children : JSON.stringify(children) }));
1730
2070
  }
1731
2071
  };
1732
2072
  }
1733
2073
  function normaliseChild(children) {
1734
- if (typeof children === "object" && children !== null && !Array.isArray(children) && !import_react11.default.isValidElement(children)) {
2074
+ if (typeof children === "object" && children !== null && !Array.isArray(children) && !import_react8.default.isValidElement(children)) {
1735
2075
  return JSON.stringify(children);
1736
2076
  }
1737
2077
  return children;
1738
2078
  }
1739
2079
 
1740
2080
  // src/components/MessageBubble.tsx
2081
+ var import_jsx_runtime12 = require("react/jsx-runtime");
1741
2082
  function MessageBubble({
1742
2083
  message,
1743
2084
  sources,
@@ -1750,13 +2091,13 @@ function MessageBubble({
1750
2091
  const isUser = message.role === "user";
1751
2092
  const isCompact = viewportSize === "compact";
1752
2093
  const isMedium = viewportSize === "medium";
1753
- const [showSources, setShowSources] = import_react12.default.useState(false);
1754
- const [showTrace, setShowTrace] = import_react12.default.useState(false);
1755
- const structuredContent = import_react12.default.useMemo(
2094
+ const [showSources, setShowSources] = import_react9.default.useState(false);
2095
+ const [showTrace, setShowTrace] = import_react9.default.useState(false);
2096
+ const structuredContent = import_react9.default.useMemo(
1756
2097
  () => isUser ? { payload: null, text: message.content } : extractStructuredPayload(message.content),
1757
2098
  [isUser, message.content]
1758
2099
  );
1759
- const hasRichUI = import_react12.default.useMemo(() => {
2100
+ const hasRichUI = import_react9.default.useMemo(() => {
1760
2101
  if (message.uiTransformation) {
1761
2102
  const type = message.uiTransformation.type;
1762
2103
  if (type && !["text", "table"].includes(type)) return true;
@@ -1767,10 +2108,10 @@ function MessageBubble({
1767
2108
  return false;
1768
2109
  }, [message.uiTransformation, structuredContent.payload]);
1769
2110
  const shouldRenderStructuredOnly = !isUser && hasRichUI && isLikelyUiOnlyMessage(structuredContent.text);
1770
- const productsFromSources = import_react12.default.useMemo(() => {
2111
+ const productsFromSources = import_react9.default.useMemo(() => {
1771
2112
  return extractProductsFromSources(sources, isUser);
1772
2113
  }, [sources, isUser]);
1773
- const { productsFromContent, cleanContent } = import_react12.default.useMemo(() => {
2114
+ const { productsFromContent, cleanContent } = import_react9.default.useMemo(() => {
1774
2115
  if (isUser) {
1775
2116
  return { productsFromContent: [], cleanContent: message.content };
1776
2117
  }
@@ -1782,13 +2123,14 @@ function MessageBubble({
1782
2123
  message.content,
1783
2124
  structuredContent.text,
1784
2125
  payloadCandidates,
1785
- productsFromSources
2126
+ productsFromSources,
2127
+ isStreaming
1786
2128
  );
1787
- }, [message.content, isUser, structuredContent, productsFromSources]);
1788
- const allProducts = import_react12.default.useMemo(() => {
2129
+ }, [message.content, isUser, structuredContent, productsFromSources, isStreaming]);
2130
+ const allProducts = import_react9.default.useMemo(() => {
1789
2131
  return deduplicateProducts(productsFromSources, productsFromContent, message.content);
1790
2132
  }, [productsFromSources, productsFromContent, message.content]);
1791
- const processedMarkdown = import_react12.default.useMemo(() => {
2133
+ const processedMarkdown = import_react9.default.useMemo(() => {
1792
2134
  let raw = structuredContent.payload ? structuredContent.text : cleanContent || message.content;
1793
2135
  const hasStructuredUiBlock = Boolean(structuredContent.payload) || /```(?:ui|json|chart)\s*[\s\S]*?"(?:view|chartType|type|data|items|rows|products|results)"\s*:/i.test(raw);
1794
2136
  raw = raw.replace(/([^\n])\n\|/g, "$1\n\n|").replace(/(\|[^\n]*\|)\n\n+(?=\|)/g, "$1\n");
@@ -1811,93 +2153,123 @@ ${match.trim()}
1811
2153
  }
1812
2154
  return raw;
1813
2155
  }, [cleanContent, message.content, isStreaming, structuredContent]);
1814
- const markdownComponents = import_react12.default.useMemo(
2156
+ const markdownComponents = import_react9.default.useMemo(
1815
2157
  () => createMarkdownComponents({ primaryColor, accentColor, isStreaming, onAddToCart, viewportSize }),
1816
2158
  [primaryColor, accentColor, isStreaming, onAddToCart, viewportSize]
1817
2159
  );
1818
- return /* @__PURE__ */ import_react12.default.createElement("div", { className: `flex ${isCompact ? "gap-2" : "gap-3"} ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ import_react12.default.createElement(
1819
- "div",
1820
- {
1821
- 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"}`,
1822
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
1823
- },
1824
- isUser ? /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.User, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"} text-white` }) : /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.Bot, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"}` })
1825
- ), /* @__PURE__ */ import_react12.default.createElement("div", { className: `flex flex-col gap-1 min-w-0 ${isCompact ? "max-w-[94%]" : isMedium ? "max-w-[92%]" : "max-w-[90%]"} ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ import_react12.default.createElement(
1826
- "div",
1827
- {
1828
- 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"}`,
1829
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
1830
- },
1831
- isStreaming && !message.content ? /* @__PURE__ */ import_react12.default.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ import_react12.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_react12.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_react12.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_react12.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_react12.default.createElement(
1832
- UIDispatcher,
1833
- {
1834
- rawContent: structuredContent.payload,
1835
- primaryColor,
1836
- accentColor,
1837
- isStreaming,
1838
- onAddToCart,
1839
- viewportSize
1840
- }
1841
- ), !shouldRenderStructuredOnly && /* @__PURE__ */ import_react12.default.createElement(import_react_markdown.default, { components: markdownComponents }, processedMarkdown), isStreaming && /* @__PURE__ */ import_react12.default.createElement("span", { className: "inline-flex items-center gap-1.5 ml-2 text-emerald-500 animate-pulse align-middle text-xs font-medium" }, /* @__PURE__ */ import_react12.default.createElement(
1842
- HourglassLoader_default,
1843
- {
1844
- size: 18,
1845
- primaryColor,
1846
- accentColor,
1847
- glow: false
1848
- }
1849
- ), "Thinking..."))
1850
- ), (() => {
1851
- var _a, _b;
1852
- if (isUser || structuredContent.payload || !message.uiTransformation) return null;
1853
- const ui = message.uiTransformation;
1854
- const textContent = (_b = (_a = ui.data) == null ? void 0 : _a.content) != null ? _b : "";
1855
- 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());
1856
- if (!shouldShow) return null;
1857
- return /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-full mt-3" }, /* @__PURE__ */ import_react12.default.createElement(
1858
- VisualizationRenderer,
2160
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `flex ${isCompact ? "gap-2" : "gap-3"} ${isUser ? "flex-row-reverse" : "flex-row"} items-start`, children: [
2161
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2162
+ "div",
1859
2163
  {
1860
- data: ui,
1861
- primaryColor,
1862
- onAddToCart,
1863
- className: "rounded-3xl border border-slate-200/60 dark:border-white/10 bg-white/90 dark:bg-slate-900/80 p-4",
1864
- isStreaming
2164
+ 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"}`,
2165
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
2166
+ children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.User, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"} text-white` }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.Bot, { className: `${isCompact ? "w-3.5 h-3.5" : "w-4 h-4"}` })
1865
2167
  }
1866
- ));
1867
- })(), !isUser && !hasRichUI && allProducts.length > 0 && /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ import_react12.default.createElement(
1868
- ProductCarousel,
1869
- {
1870
- products: allProducts,
1871
- primaryColor,
1872
- onAddToCart
1873
- }
1874
- )), !isUser && /* @__PURE__ */ import_react12.default.createElement("div", { className: "flex items-center gap-4 mt-1 w-full flex-wrap" }, sources && sources.length > 0 && /* @__PURE__ */ import_react12.default.createElement(
1875
- "button",
1876
- {
1877
- onClick: () => setShowSources((s) => !s),
1878
- className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1"
1879
- },
1880
- showSources ? /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.ChevronRight, { className: "w-3 h-3" }),
1881
- sources.length,
1882
- " source",
1883
- sources.length !== 1 ? "s" : "",
1884
- " used"
1885
- ), message.trace && /* @__PURE__ */ import_react12.default.createElement(
1886
- "button",
1887
- {
1888
- onClick: () => setShowTrace((t) => !t),
1889
- className: "text-[11px] text-emerald-500 hover:text-emerald-400 transition-colors flex items-center gap-1"
1890
- },
1891
- /* @__PURE__ */ import_react12.default.createElement(import_lucide_react6.Activity, { className: "w-3 h-3" }),
1892
- showTrace ? "Hide Trace" : "Trace"
1893
- )), /* @__PURE__ */ import_react12.default.createElement("div", { className: "w-full flex flex-col gap-2 min-w-0" }, showSources && sources && sources.length > 0 && /* @__PURE__ */ import_react12.default.createElement("div", { className: "mt-1 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ import_react12.default.createElement(SourceCard, { key: src.id, source: src, index: i }))), showTrace && message.trace && /* @__PURE__ */ import_react12.default.createElement(ObservabilityPanel, { trace: message.trace, primaryColor }))));
2168
+ ),
2169
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `flex flex-col gap-1 min-w-0 ${isCompact ? "max-w-[94%]" : isMedium ? "max-w-[92%]" : "max-w-[90%]"} ${isUser ? "items-end" : "items-start"}`, children: [
2170
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2171
+ "div",
2172
+ {
2173
+ 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"}`,
2174
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
2175
+ children: isStreaming && !message.content ? /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "flex items-center gap-1 py-1", children: [
2176
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }),
2177
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }),
2178
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })
2179
+ ] }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: `prose ${isCompact ? "prose-xs" : "prose-sm"} max-w-none break-words ${isUser ? "prose-invert" : "dark:prose-invert"}`, children: [
2180
+ !isUser && structuredContent.payload && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2181
+ UIDispatcher,
2182
+ {
2183
+ rawContent: structuredContent.payload,
2184
+ primaryColor,
2185
+ accentColor,
2186
+ isStreaming,
2187
+ onAddToCart,
2188
+ viewportSize
2189
+ }
2190
+ ),
2191
+ !shouldRenderStructuredOnly && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_react_markdown.default, { components: markdownComponents, children: processedMarkdown }),
2192
+ isStreaming && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("span", { className: "inline-flex items-center gap-1.5 ml-2 text-emerald-500 animate-pulse align-middle text-xs font-medium", children: [
2193
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2194
+ HourglassLoader_default,
2195
+ {
2196
+ size: 18,
2197
+ primaryColor,
2198
+ accentColor,
2199
+ glow: false
2200
+ }
2201
+ ),
2202
+ "Thinking..."
2203
+ ] })
2204
+ ] })
2205
+ }
2206
+ ),
2207
+ (() => {
2208
+ var _a, _b;
2209
+ if (isUser || structuredContent.payload || !message.uiTransformation) return null;
2210
+ const ui = message.uiTransformation;
2211
+ const textContent = (_b = (_a = ui.data) == null ? void 0 : _a.content) != null ? _b : "";
2212
+ 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());
2213
+ if (!shouldShow) return null;
2214
+ return /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full mt-3", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2215
+ VisualizationRenderer,
2216
+ {
2217
+ data: ui,
2218
+ primaryColor,
2219
+ onAddToCart,
2220
+ className: "rounded-3xl border border-slate-200/60 dark:border-white/10 bg-white/90 dark:bg-slate-900/80 p-4",
2221
+ isStreaming
2222
+ }
2223
+ ) });
2224
+ })(),
2225
+ !isUser && !hasRichUI && allProducts.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "w-full mt-1", children: /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(
2226
+ ProductCarousel,
2227
+ {
2228
+ products: allProducts,
2229
+ primaryColor,
2230
+ onAddToCart
2231
+ }
2232
+ ) }),
2233
+ !isUser && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "flex items-center gap-4 mt-1 w-full flex-wrap", children: [
2234
+ sources && sources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2235
+ "button",
2236
+ {
2237
+ onClick: () => setShowSources((s) => !s),
2238
+ className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1",
2239
+ children: [
2240
+ showSources ? /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.ChevronRight, { className: "w-3 h-3" }),
2241
+ sources.length,
2242
+ " source",
2243
+ sources.length !== 1 ? "s" : "",
2244
+ " used"
2245
+ ]
2246
+ }
2247
+ ),
2248
+ message.trace && /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)(
2249
+ "button",
2250
+ {
2251
+ onClick: () => setShowTrace((t) => !t),
2252
+ className: "text-[11px] text-emerald-500 hover:text-emerald-400 transition-colors flex items-center gap-1",
2253
+ children: [
2254
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(import_lucide_react6.Activity, { className: "w-3 h-3" }),
2255
+ showTrace ? "Hide Trace" : "Trace"
2256
+ ]
2257
+ }
2258
+ )
2259
+ ] }),
2260
+ /* @__PURE__ */ (0, import_jsx_runtime12.jsxs)("div", { className: "w-full flex flex-col gap-2 min-w-0", children: [
2261
+ showSources && sources && sources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)("div", { className: "mt-1 flex flex-col gap-2", children: sources.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(SourceCard, { source: src, index: i }, src.id)) }),
2262
+ showTrace && message.trace && /* @__PURE__ */ (0, import_jsx_runtime12.jsx)(ObservabilityPanel, { trace: message.trace, primaryColor })
2263
+ ] })
2264
+ ] })
2265
+ ] });
1894
2266
  }
1895
2267
 
1896
2268
  // src/hooks/useRagChat.ts
1897
- var import_react13 = require("react");
2269
+ var import_react10 = require("react");
1898
2270
 
1899
2271
  // src/hooks/useStoredMessages.ts
1900
- var React13 = __toESM(require("react"));
2272
+ var React10 = __toESM(require("react"));
1901
2273
  function readStoredMessages(storageKey) {
1902
2274
  if (typeof window === "undefined") {
1903
2275
  return [];
@@ -1914,8 +2286,8 @@ function readStoredMessages(storageKey) {
1914
2286
  }
1915
2287
  }
1916
2288
  function useStoredMessages(storageKey, persist) {
1917
- const [messages, setMessages] = React13.useState(() => persist ? readStoredMessages(storageKey) : []);
1918
- React13.useEffect(() => {
2289
+ const [messages, setMessages] = React10.useState(() => persist ? readStoredMessages(storageKey) : []);
2290
+ React10.useEffect(() => {
1919
2291
  if (!persist || typeof window === "undefined") {
1920
2292
  return;
1921
2293
  }
@@ -1955,14 +2327,14 @@ function useRagChat(projectId, options = {}) {
1955
2327
  } = options;
1956
2328
  const storageKey = `rag_chat_${projectId}`;
1957
2329
  const [messages, setMessages] = useStoredMessages(storageKey, persist);
1958
- const [isLoading, setIsLoading] = (0, import_react13.useState)(false);
1959
- const [error, setError] = (0, import_react13.useState)(null);
1960
- const lastInputRef = (0, import_react13.useRef)("");
1961
- const messagesRef = (0, import_react13.useRef)(messages);
1962
- (0, import_react13.useEffect)(() => {
2330
+ const [isLoading, setIsLoading] = (0, import_react10.useState)(false);
2331
+ const [error, setError] = (0, import_react10.useState)(null);
2332
+ const lastInputRef = (0, import_react10.useRef)("");
2333
+ const messagesRef = (0, import_react10.useRef)(messages);
2334
+ (0, import_react10.useEffect)(() => {
1963
2335
  messagesRef.current = messages;
1964
2336
  }, [messages]);
1965
- const sendMessage = (0, import_react13.useCallback)(
2337
+ const sendMessage = (0, import_react10.useCallback)(
1966
2338
  async (text, opts) => {
1967
2339
  var _a, _b;
1968
2340
  const trimmed = text.trim();
@@ -2075,12 +2447,12 @@ function useRagChat(projectId, options = {}) {
2075
2447
  },
2076
2448
  [apiUrl, isLoading, namespace, onError, onReply, projectId, setMessages]
2077
2449
  );
2078
- const clear = (0, import_react13.useCallback)(() => {
2450
+ const clear = (0, import_react10.useCallback)(() => {
2079
2451
  setMessages([]);
2080
2452
  setError(null);
2081
2453
  if (persist) localStorage.removeItem(storageKey);
2082
2454
  }, [persist, setMessages, storageKey]);
2083
- const retry = (0, import_react13.useCallback)(async () => {
2455
+ const retry = (0, import_react10.useCallback)(async () => {
2084
2456
  if (lastInputRef.current) {
2085
2457
  const latestMessage = messagesRef.current[messagesRef.current.length - 1];
2086
2458
  await sendMessage(lastInputRef.current, {
@@ -2100,6 +2472,7 @@ function useRagChat(projectId, options = {}) {
2100
2472
  }
2101
2473
 
2102
2474
  // src/components/ChatWindow.tsx
2475
+ var import_jsx_runtime13 = require("react/jsx-runtime");
2103
2476
  function ChatWindow({
2104
2477
  className = "",
2105
2478
  style,
@@ -2114,21 +2487,21 @@ function ChatWindow({
2114
2487
  }) {
2115
2488
  var _a;
2116
2489
  const { ui, projectId } = useConfig();
2117
- const [input, setInput] = (0, import_react14.useState)("");
2118
- const [mounted, setMounted] = (0, import_react14.useState)(false);
2119
- const [viewportSize, setViewportSize] = (0, import_react14.useState)("large");
2120
- const windowRef = (0, import_react14.useRef)(null);
2121
- const bottomRef = (0, import_react14.useRef)(null);
2122
- const inputRef = (0, import_react14.useRef)(null);
2490
+ const [input, setInput] = (0, import_react11.useState)("");
2491
+ const [mounted, setMounted] = (0, import_react11.useState)(false);
2492
+ const [viewportSize, setViewportSize] = (0, import_react11.useState)("large");
2493
+ const windowRef = (0, import_react11.useRef)(null);
2494
+ const bottomRef = (0, import_react11.useRef)(null);
2495
+ const inputRef = (0, import_react11.useRef)(null);
2123
2496
  const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
2124
2497
  namespace: projectId
2125
2498
  });
2126
- const [suggestions, setSuggestions] = (0, import_react14.useState)([]);
2127
- const [isSuggesting, setIsSuggesting] = (0, import_react14.useState)(false);
2128
- const [isListening, setIsListening] = (0, import_react14.useState)(false);
2129
- const [isUploadModalOpen, setIsUploadModalOpen] = (0, import_react14.useState)(false);
2130
- const recognitionRef = (0, import_react14.useRef)(null);
2131
- (0, import_react14.useEffect)(() => {
2499
+ const [suggestions, setSuggestions] = (0, import_react11.useState)([]);
2500
+ const [isSuggesting, setIsSuggesting] = (0, import_react11.useState)(false);
2501
+ const [isListening, setIsListening] = (0, import_react11.useState)(false);
2502
+ const [isUploadModalOpen, setIsUploadModalOpen] = (0, import_react11.useState)(false);
2503
+ const recognitionRef = (0, import_react11.useRef)(null);
2504
+ (0, import_react11.useEffect)(() => {
2132
2505
  if (typeof window !== "undefined") {
2133
2506
  const win = window;
2134
2507
  const SpeechRecognition = win.SpeechRecognition || win.webkitSpeechRecognition;
@@ -2174,10 +2547,10 @@ function ChatWindow({
2174
2547
  }
2175
2548
  }
2176
2549
  };
2177
- (0, import_react14.useEffect)(() => {
2550
+ (0, import_react11.useEffect)(() => {
2178
2551
  setMounted(true);
2179
2552
  }, []);
2180
- (0, import_react14.useEffect)(() => {
2553
+ (0, import_react11.useEffect)(() => {
2181
2554
  const element = windowRef.current;
2182
2555
  if (!element || typeof ResizeObserver === "undefined") return;
2183
2556
  const resolveViewportSize = (width) => {
@@ -2193,13 +2566,13 @@ function ChatWindow({
2193
2566
  observer.observe(element);
2194
2567
  return () => observer.disconnect();
2195
2568
  }, []);
2196
- (0, import_react14.useEffect)(() => {
2569
+ (0, import_react11.useEffect)(() => {
2197
2570
  var _a2;
2198
2571
  if (messages.length > 0 || isLoading) {
2199
2572
  (_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
2200
2573
  }
2201
2574
  }, [messages, isLoading]);
2202
- const sendMessage = (0, import_react14.useCallback)(async () => {
2575
+ const sendMessage = (0, import_react11.useCallback)(async () => {
2203
2576
  var _a2;
2204
2577
  const text = input.trim();
2205
2578
  if (!text || isLoading) return;
@@ -2229,7 +2602,7 @@ function ChatWindow({
2229
2602
  const isEmpty = messages.length === 0;
2230
2603
  const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
2231
2604
  const isGlass = ui.visualStyle !== "solid";
2232
- (0, import_react14.useEffect)(() => {
2605
+ (0, import_react11.useEffect)(() => {
2233
2606
  if (input.trim().length < 3) {
2234
2607
  return;
2235
2608
  }
@@ -2253,217 +2626,273 @@ function ChatWindow({
2253
2626
  }, 800);
2254
2627
  return () => clearTimeout(timer);
2255
2628
  }, [input, projectId]);
2256
- return /* @__PURE__ */ import_react14.default.createElement(
2629
+ return /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2257
2630
  "div",
2258
2631
  {
2259
2632
  ref: windowRef,
2260
2633
  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}`,
2261
- style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
2262
- },
2263
- onResizeStart && /* @__PURE__ */ import_react14.default.createElement(
2264
- "div",
2265
- {
2266
- onMouseDown: onResizeStart,
2267
- className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
2268
- title: "Drag to resize"
2269
- },
2270
- /* @__PURE__ */ import_react14.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]" })
2271
- ),
2272
- /* @__PURE__ */ import_react14.default.createElement(
2273
- "div",
2274
- {
2275
- className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
2276
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
2277
- },
2278
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
2279
- // eslint-disable-next-line @next/next/no-img-element
2280
- /* @__PURE__ */ import_react14.default.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
2281
- ) : /* @__PURE__ */ import_react14.default.createElement(
2282
- "div",
2283
- {
2284
- className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
2285
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
2286
- },
2287
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Bot, { className: "w-5 h-5 text-white" })
2288
- ), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
2289
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ import_react14.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ import_react14.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_react14.default.createElement(
2290
- "button",
2291
- {
2292
- onClick: clearHistory,
2293
- title: "Clear conversation",
2294
- 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"
2295
- },
2296
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Trash2, { className: "w-3.5 h-3.5" })
2297
- ), isResized && onResetResize && /* @__PURE__ */ import_react14.default.createElement(
2298
- "button",
2299
- {
2300
- onClick: onResetResize,
2301
- title: "Reset to default size",
2302
- 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"
2303
- },
2304
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.RotateCcw, { className: "w-3.5 h-3.5" })
2305
- ), onMaximize && /* @__PURE__ */ import_react14.default.createElement(
2306
- "button",
2307
- {
2308
- onClick: onMaximize,
2309
- title: isMaximized ? "Minimize" : "Maximize",
2310
- 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"
2311
- },
2312
- isMaximized ? /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Maximize2, { className: "w-3.5 h-3.5" })
2313
- ), showClose && onClose && /* @__PURE__ */ import_react14.default.createElement(
2314
- "button",
2315
- {
2316
- onClick: onClose,
2317
- title: "Close chat",
2318
- 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"
2319
- },
2320
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-4 h-4" })
2321
- )))
2322
- ),
2323
- /* @__PURE__ */ import_react14.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 ? (
2324
- /* Welcome state */
2325
- /* @__PURE__ */ import_react14.default.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ import_react14.default.createElement(
2326
- "div",
2327
- {
2328
- className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
2329
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
2330
- },
2331
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Sparkles, { className: "w-8 h-8 text-white" })
2332
- ), /* @__PURE__ */ import_react14.default.createElement("div", null, /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ import_react14.default.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ import_react14.default.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
2333
- (suggestion) => /* @__PURE__ */ import_react14.default.createElement(
2334
- "button",
2634
+ style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style),
2635
+ children: [
2636
+ onResizeStart && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2637
+ "div",
2335
2638
  {
2336
- key: suggestion,
2337
- onClick: () => {
2338
- var _a2;
2339
- setInput(suggestion);
2340
- (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2341
- },
2342
- className: "px-3 py-1.5 rounded-full text-xs border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/50 hover:text-slate-900 dark:hover:text-white/80 hover:border-slate-300 dark:hover:border-white/20 hover:bg-slate-100 dark:hover:bg-white/5 transition-all"
2343
- },
2344
- suggestion
2345
- )
2346
- )))
2347
- ) : messages.map((msg, index) => /* @__PURE__ */ import_react14.default.createElement(
2348
- MessageBubble,
2349
- {
2350
- key: msg.id,
2351
- message: msg,
2352
- sources: msg.sources,
2353
- isStreaming: isLoading && index === messages.length - 1 && msg.role === "assistant",
2354
- primaryColor: ui.primaryColor,
2355
- accentColor: ui.accentColor,
2356
- onAddToCart,
2357
- viewportSize
2358
- }
2359
- )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ import_react14.default.createElement(
2360
- MessageBubble,
2361
- {
2362
- message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
2363
- isStreaming: true,
2364
- primaryColor: ui.primaryColor,
2365
- accentColor: ui.accentColor,
2366
- onAddToCart,
2367
- viewportSize
2368
- }
2369
- ), error && /* @__PURE__ */ import_react14.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_react14.default.createElement(import_lucide_react7.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ import_react14.default.createElement("span", null, error)), /* @__PURE__ */ import_react14.default.createElement("div", { ref: bottomRef })),
2370
- isUploadModalOpen && /* @__PURE__ */ import_react14.default.createElement("div", { className: "absolute inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/50 backdrop-blur-sm rounded-inherit" }, /* @__PURE__ */ import_react14.default.createElement("div", { className: "relative w-full max-w-md bg-white dark:bg-[#0f0f1a] rounded-2xl shadow-2xl overflow-hidden animate-in zoom-in-95 duration-200" }, /* @__PURE__ */ import_react14.default.createElement(
2371
- "button",
2372
- {
2373
- onClick: () => setIsUploadModalOpen(false),
2374
- className: "absolute top-4 right-4 p-1.5 rounded-lg text-slate-400 hover:text-slate-600 hover:bg-slate-100 dark:hover:text-white/80 dark:hover:bg-white/10 transition-colors z-10"
2375
- },
2376
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.X, { className: "w-5 h-5" })
2377
- ), /* @__PURE__ */ import_react14.default.createElement(
2378
- DocumentUpload,
2379
- {
2380
- namespace: projectId,
2381
- onUploadComplete: () => setIsUploadModalOpen(false)
2382
- }
2383
- ))),
2384
- /* @__PURE__ */ import_react14.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_react14.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_react14.default.createElement(
2385
- "button",
2386
- {
2387
- key: suggestion,
2388
- onClick: () => {
2389
- var _a2;
2390
- setInput(suggestion);
2391
- setSuggestions([]);
2392
- (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2393
- },
2394
- 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"
2395
- },
2396
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Sparkles, { className: "w-3 h-3 text-amber-400" }),
2397
- suggestion
2398
- )), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ import_react14.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_react14.default.createElement(import_lucide_react7.Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ import_react14.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_react14.default.createElement(
2399
- "textarea",
2400
- {
2401
- ref: inputRef,
2402
- value: input,
2403
- onChange: (e) => {
2404
- const val = e.target.value;
2405
- setInput(val);
2406
- if (val.trim().length < 3) {
2407
- setSuggestions([]);
2639
+ onMouseDown: onResizeStart,
2640
+ className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
2641
+ title: "Drag to resize",
2642
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("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]" })
2408
2643
  }
2409
- },
2410
- onKeyDown: handleKeyDown,
2411
- placeholder: ui.placeholder,
2412
- rows: 1,
2413
- disabled: isLoading,
2414
- 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",
2415
- style: { scrollbarWidth: "none" }
2416
- }
2417
- ), ui.enableVoiceInput !== false && /* @__PURE__ */ import_react14.default.createElement(
2418
- "button",
2419
- {
2420
- type: "button",
2421
- onClick: toggleListening,
2422
- disabled: isLoading,
2423
- 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"}`,
2424
- title: isListening ? "Stop listening" : "Start voice input"
2425
- },
2426
- isListening ? /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Mic, { className: "w-4 h-4" })
2427
- ), ui.allowUpload !== false && /* @__PURE__ */ import_react14.default.createElement(
2428
- "button",
2429
- {
2430
- type: "button",
2431
- onClick: () => setIsUploadModalOpen(true),
2432
- className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10",
2433
- title: "Upload Document"
2434
- },
2435
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.Paperclip, { className: "w-4 h-4" })
2436
- ), /* @__PURE__ */ import_react14.default.createElement(
2437
- "button",
2438
- {
2439
- onClick: sendMessage,
2440
- disabled: !input.trim() || isLoading,
2441
- className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all disabled:opacity-30 disabled:cursor-not-allowed hover:scale-105 active:scale-95 shadow-md",
2442
- style: {
2443
- background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
2444
- // slate-400/20 for light mode disabled
2445
- }
2446
- },
2447
- /* @__PURE__ */ import_react14.default.createElement(import_lucide_react7.ArrowUp, { className: "w-4 h-4 text-white" })
2448
- )), /* @__PURE__ */ import_react14.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"))
2644
+ ),
2645
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2646
+ "div",
2647
+ {
2648
+ className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
2649
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` },
2650
+ children: [
2651
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-3", children: [
2652
+ ui.logoUrl ? (
2653
+ // eslint-disable-next-line @next/next/no-img-element
2654
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
2655
+ ) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2656
+ "div",
2657
+ {
2658
+ className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
2659
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2660
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Bot, { className: "w-5 h-5 text-white" })
2661
+ }
2662
+ ),
2663
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2664
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight", children: ui.title }),
2665
+ ui.poweredBy && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight", children: `Powered by ${ui.poweredBy}` })
2666
+ ] })
2667
+ ] }),
2668
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "flex items-center gap-1.5", children: [
2669
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2", children: [
2670
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }),
2671
+ "Online"
2672
+ ] }),
2673
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("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", children: [
2674
+ mounted && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2675
+ "button",
2676
+ {
2677
+ onClick: clearHistory,
2678
+ title: "Clear conversation",
2679
+ 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",
2680
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Trash2, { className: "w-3.5 h-3.5" })
2681
+ }
2682
+ ),
2683
+ isResized && onResetResize && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2684
+ "button",
2685
+ {
2686
+ onClick: onResetResize,
2687
+ title: "Reset to default size",
2688
+ 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",
2689
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.RotateCcw, { className: "w-3.5 h-3.5" })
2690
+ }
2691
+ ),
2692
+ onMaximize && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2693
+ "button",
2694
+ {
2695
+ onClick: onMaximize,
2696
+ title: isMaximized ? "Minimize" : "Maximize",
2697
+ 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",
2698
+ children: isMaximized ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Maximize2, { className: "w-3.5 h-3.5" })
2699
+ }
2700
+ ),
2701
+ showClose && onClose && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2702
+ "button",
2703
+ {
2704
+ onClick: onClose,
2705
+ title: "Close chat",
2706
+ 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",
2707
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.X, { className: "w-4 h-4" })
2708
+ }
2709
+ )
2710
+ ] })
2711
+ ] })
2712
+ ]
2713
+ }
2714
+ ),
2715
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("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", children: [
2716
+ !mounted || isEmpty ? (
2717
+ /* Welcome state */
2718
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12", children: [
2719
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2720
+ "div",
2721
+ {
2722
+ className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
2723
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2724
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Sparkles, { className: "w-8 h-8 text-white" })
2725
+ }
2726
+ ),
2727
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { children: [
2728
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed", children: ui.welcomeMessage }),
2729
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2", children: "Ask a question to get started" })
2730
+ ] }),
2731
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "flex flex-wrap gap-2 justify-center mt-2", children: CHAT_SUGGESTIONS.map(
2732
+ (suggestion) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2733
+ "button",
2734
+ {
2735
+ onClick: () => {
2736
+ var _a2;
2737
+ setInput(suggestion);
2738
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2739
+ },
2740
+ className: "px-3 py-1.5 rounded-full text-xs border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/50 hover:text-slate-900 dark:hover:text-white/80 hover:border-slate-300 dark:hover:border-white/20 hover:bg-slate-100 dark:hover:bg-white/5 transition-all",
2741
+ children: suggestion
2742
+ },
2743
+ suggestion
2744
+ )
2745
+ ) })
2746
+ ] })
2747
+ ) : messages.map((msg, index) => /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2748
+ MessageBubble,
2749
+ {
2750
+ message: msg,
2751
+ sources: msg.sources,
2752
+ isStreaming: isLoading && index === messages.length - 1 && msg.role === "assistant",
2753
+ primaryColor: ui.primaryColor,
2754
+ accentColor: ui.accentColor,
2755
+ onAddToCart,
2756
+ viewportSize
2757
+ },
2758
+ msg.id
2759
+ )),
2760
+ isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2761
+ MessageBubble,
2762
+ {
2763
+ message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
2764
+ isStreaming: true,
2765
+ primaryColor: ui.primaryColor,
2766
+ accentColor: ui.accentColor,
2767
+ onAddToCart,
2768
+ viewportSize
2769
+ }
2770
+ ),
2771
+ error && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("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", children: [
2772
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }),
2773
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("span", { children: error })
2774
+ ] }),
2775
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { ref: bottomRef })
2776
+ ] }),
2777
+ isUploadModalOpen && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("div", { className: "absolute inset-0 z-50 flex items-center justify-center p-4 bg-slate-900/50 backdrop-blur-sm rounded-inherit", children: /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "relative w-full max-w-md bg-white dark:bg-[#0f0f1a] rounded-2xl shadow-2xl overflow-hidden animate-in zoom-in-95 duration-200", children: [
2778
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2779
+ "button",
2780
+ {
2781
+ onClick: () => setIsUploadModalOpen(false),
2782
+ className: "absolute top-4 right-4 p-1.5 rounded-lg text-slate-400 hover:text-slate-600 hover:bg-slate-100 dark:hover:text-white/80 dark:hover:bg-white/10 transition-colors z-10",
2783
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.X, { className: "w-5 h-5" })
2784
+ }
2785
+ ),
2786
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2787
+ DocumentUpload,
2788
+ {
2789
+ namespace: projectId,
2790
+ onUploadComplete: () => setIsUploadModalOpen(false)
2791
+ }
2792
+ )
2793
+ ] }) }),
2794
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("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]"}`, children: [
2795
+ (suggestions.length > 0 || isSuggesting) && !isLoading && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("div", { className: "mb-3 flex flex-wrap gap-2 animate-in fade-in slide-in-from-bottom-2 duration-300", children: [
2796
+ suggestions.map((suggestion) => /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)(
2797
+ "button",
2798
+ {
2799
+ onClick: () => {
2800
+ var _a2;
2801
+ setInput(suggestion);
2802
+ setSuggestions([]);
2803
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
2804
+ },
2805
+ 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",
2806
+ children: [
2807
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Sparkles, { className: "w-3 h-3 text-amber-400" }),
2808
+ suggestion
2809
+ ]
2810
+ },
2811
+ suggestion
2812
+ )),
2813
+ isSuggesting && suggestions.length === 0 && /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("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", children: [
2814
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Sparkles, { className: "w-3 h-3" }),
2815
+ "Thinking..."
2816
+ ] })
2817
+ ] }),
2818
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsxs)("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"}`, children: [
2819
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2820
+ "textarea",
2821
+ {
2822
+ ref: inputRef,
2823
+ value: input,
2824
+ onChange: (e) => {
2825
+ const val = e.target.value;
2826
+ setInput(val);
2827
+ if (val.trim().length < 3) {
2828
+ setSuggestions([]);
2829
+ }
2830
+ },
2831
+ onKeyDown: handleKeyDown,
2832
+ placeholder: ui.placeholder,
2833
+ rows: 1,
2834
+ disabled: isLoading,
2835
+ 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",
2836
+ style: { scrollbarWidth: "none" }
2837
+ }
2838
+ ),
2839
+ ui.enableVoiceInput !== false && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2840
+ "button",
2841
+ {
2842
+ type: "button",
2843
+ onClick: toggleListening,
2844
+ disabled: isLoading,
2845
+ 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"}`,
2846
+ title: isListening ? "Stop listening" : "Start voice input",
2847
+ children: isListening ? /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Mic, { className: "w-4 h-4" })
2848
+ }
2849
+ ),
2850
+ ui.allowUpload !== false && /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2851
+ "button",
2852
+ {
2853
+ type: "button",
2854
+ onClick: () => setIsUploadModalOpen(true),
2855
+ className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10",
2856
+ title: "Upload Document",
2857
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.Paperclip, { className: "w-4 h-4" })
2858
+ }
2859
+ ),
2860
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(
2861
+ "button",
2862
+ {
2863
+ onClick: sendMessage,
2864
+ disabled: !input.trim() || isLoading,
2865
+ className: "flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all disabled:opacity-30 disabled:cursor-not-allowed hover:scale-105 active:scale-95 shadow-md",
2866
+ style: {
2867
+ background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
2868
+ // slate-400/20 for light mode disabled
2869
+ },
2870
+ children: /* @__PURE__ */ (0, import_jsx_runtime13.jsx)(import_lucide_react7.ArrowUp, { className: "w-4 h-4 text-white" })
2871
+ }
2872
+ )
2873
+ ] }),
2874
+ /* @__PURE__ */ (0, import_jsx_runtime13.jsx)("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2", children: "Press Enter to send \xB7 Shift+Enter for new line" })
2875
+ ] })
2876
+ ]
2877
+ }
2449
2878
  );
2450
2879
  }
2451
2880
 
2452
2881
  // src/components/ChatWidget.tsx
2882
+ var import_jsx_runtime14 = require("react/jsx-runtime");
2453
2883
  var DEFAULT_DIMENSIONS = { width: 380, height: 600 };
2454
2884
  function ChatWidget({ position = "bottom-right", onAddToCart }) {
2455
2885
  const { ui } = useConfig();
2456
- const [isOpen, setIsOpen] = (0, import_react15.useState)(false);
2457
- const [hasUnread, setHasUnread] = (0, import_react15.useState)(false);
2458
- const [dimensions, setDimensions] = (0, import_react15.useState)(DEFAULT_DIMENSIONS);
2459
- const [isResizing, setIsResizing] = (0, import_react15.useState)(false);
2460
- const [isMaximized, setIsMaximized] = (0, import_react15.useState)(false);
2461
- const [prevDimensions, setPrevDimensions] = (0, import_react15.useState)(DEFAULT_DIMENSIONS);
2886
+ const [isOpen, setIsOpen] = (0, import_react12.useState)(false);
2887
+ const [hasUnread, setHasUnread] = (0, import_react12.useState)(false);
2888
+ const [dimensions, setDimensions] = (0, import_react12.useState)(DEFAULT_DIMENSIONS);
2889
+ const [isResizing, setIsResizing] = (0, import_react12.useState)(false);
2890
+ const [isMaximized, setIsMaximized] = (0, import_react12.useState)(false);
2891
+ const [prevDimensions, setPrevDimensions] = (0, import_react12.useState)(DEFAULT_DIMENSIONS);
2462
2892
  if (ui.showWidget === false) return null;
2463
2893
  const positionClass = position === "bottom-left" ? "bottom-6 left-6" : "bottom-6 right-6";
2464
2894
  const windowPositionClass = position === "bottom-left" ? "bottom-20 left-6" : "bottom-20 right-6";
2465
2895
  const handleOpen = () => {
2466
- console.log("ChatWidget: Opening...");
2467
2896
  setIsOpen(true);
2468
2897
  setHasUnread(false);
2469
2898
  };
@@ -2508,60 +2937,67 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
2508
2937
  }
2509
2938
  };
2510
2939
  const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
2511
- return /* @__PURE__ */ import_react15.default.createElement(import_react15.default.Fragment, null, /* @__PURE__ */ import_react15.default.createElement(
2512
- "div",
2513
- {
2514
- 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"}`,
2515
- style: {
2516
- width: `${dimensions.width}px`,
2517
- height: `${dimensions.height}px`,
2518
- maxHeight: "calc(100vh - 6rem)"
2519
- }
2520
- },
2521
- /* @__PURE__ */ import_react15.default.createElement(
2522
- ChatWindow,
2940
+ return /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(import_jsx_runtime14.Fragment, { children: [
2941
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2942
+ "div",
2523
2943
  {
2524
- className: "h-full relative z-10",
2525
- showClose: true,
2526
- onClose: () => setIsOpen(false),
2527
- onResizeStart: ui.allowResize !== false ? handleResizeStart : void 0,
2528
- onResetResize: ui.allowResize !== false ? handleResetResize : void 0,
2529
- isResized,
2530
- onMaximize: ui.allowResize !== false ? handleMaximize : void 0,
2531
- isMaximized,
2532
- onAddToCart
2944
+ 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"}`,
2945
+ style: {
2946
+ width: `${dimensions.width}px`,
2947
+ height: `${dimensions.height}px`,
2948
+ maxHeight: "calc(100vh - 6rem)"
2949
+ },
2950
+ children: [
2951
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2952
+ ChatWindow,
2953
+ {
2954
+ className: "h-full relative z-10",
2955
+ showClose: true,
2956
+ onClose: () => setIsOpen(false),
2957
+ onResizeStart: ui.allowResize !== false ? handleResizeStart : void 0,
2958
+ onResetResize: ui.allowResize !== false ? handleResetResize : void 0,
2959
+ isResized,
2960
+ onMaximize: ui.allowResize !== false ? handleMaximize : void 0,
2961
+ isMaximized,
2962
+ onAddToCart
2963
+ }
2964
+ ),
2965
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2966
+ "div",
2967
+ {
2968
+ 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"}`
2969
+ }
2970
+ )
2971
+ ]
2533
2972
  }
2534
2973
  ),
2535
- /* @__PURE__ */ import_react15.default.createElement(
2536
- "div",
2974
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsxs)(
2975
+ "button",
2537
2976
  {
2538
- 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"}`
2977
+ onClick: isOpen ? () => setIsOpen(false) : handleOpen,
2978
+ className: `fixed z-[9999] w-14 h-14 shadow-2xl flex items-center justify-center transition-all duration-300 cursor-pointer hover:scale-110 active:scale-95 ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"} ${positionClass}`,
2979
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2980
+ "aria-label": "Open chat",
2981
+ children: [
2982
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2983
+ "span",
2984
+ {
2985
+ className: "absolute inset-0 rounded-full animate-ping opacity-20",
2986
+ style: { background: ui.primaryColor }
2987
+ }
2988
+ ),
2989
+ /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(
2990
+ "span",
2991
+ {
2992
+ className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`,
2993
+ children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react8.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ (0, import_jsx_runtime14.jsx)(import_lucide_react8.MessageSquare, { className: "w-6 h-6 text-white" })
2994
+ }
2995
+ ),
2996
+ hasUnread && !isOpen && /* @__PURE__ */ (0, import_jsx_runtime14.jsx)("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", children: "1" })
2997
+ ]
2539
2998
  }
2540
2999
  )
2541
- ), /* @__PURE__ */ import_react15.default.createElement(
2542
- "button",
2543
- {
2544
- onClick: isOpen ? () => setIsOpen(false) : handleOpen,
2545
- className: `fixed z-[9999] w-14 h-14 shadow-2xl flex items-center justify-center transition-all duration-300 cursor-pointer hover:scale-110 active:scale-95 ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"} ${positionClass}`,
2546
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
2547
- "aria-label": "Open chat"
2548
- },
2549
- /* @__PURE__ */ import_react15.default.createElement(
2550
- "span",
2551
- {
2552
- className: "absolute inset-0 rounded-full animate-ping opacity-20",
2553
- style: { background: ui.primaryColor }
2554
- }
2555
- ),
2556
- /* @__PURE__ */ import_react15.default.createElement(
2557
- "span",
2558
- {
2559
- className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
2560
- },
2561
- isOpen ? /* @__PURE__ */ import_react15.default.createElement(import_lucide_react8.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ import_react15.default.createElement(import_lucide_react8.MessageSquare, { className: "w-6 h-6 text-white" })
2562
- ),
2563
- hasUnread && !isOpen && /* @__PURE__ */ import_react15.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")
2564
- ));
3000
+ ] });
2565
3001
  }
2566
3002
  // Annotate the CommonJS export names for ESM import in node:
2567
3003
  0 && (module.exports = {