@retrivora-ai/rag-engine 1.2.1 → 1.2.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 (50) hide show
  1. package/dist/DocumentChunker-BXOUMKoP.d.ts +93 -0
  2. package/dist/DocumentChunker-D1dg5iCi.d.mts +93 -0
  3. package/dist/{chunk-GCPPRD2G.mjs → chunk-WGPNEAK3.mjs} +37 -3
  4. package/dist/handlers/index.d.mts +2 -2
  5. package/dist/handlers/index.d.ts +2 -2
  6. package/dist/handlers/index.js +37 -3
  7. package/dist/handlers/index.mjs +1 -1
  8. package/dist/{index-DbtE8wLM.d.ts → index-B67KQ9NN.d.ts} +1 -1
  9. package/dist/{RagConfig-BOLOz0_O.d.mts → index-Cti1u0y1.d.mts} +86 -94
  10. package/dist/{RagConfig-BOLOz0_O.d.ts → index-Cti1u0y1.d.ts} +86 -94
  11. package/dist/{index-64BDupW3.d.mts → index-kUXnRvuI.d.mts} +1 -1
  12. package/dist/index.d.mts +52 -78
  13. package/dist/index.d.ts +52 -78
  14. package/dist/index.js +313 -124
  15. package/dist/index.mjs +293 -97
  16. package/dist/server.d.mts +5 -4
  17. package/dist/server.d.ts +5 -4
  18. package/dist/server.js +37 -3
  19. package/dist/server.mjs +1 -1
  20. package/package.json +2 -1
  21. package/src/components/ChatWidget.tsx +1 -8
  22. package/src/components/ChatWindow.tsx +120 -29
  23. package/src/components/ConfigProvider.tsx +7 -33
  24. package/src/components/DocumentUpload.tsx +1 -8
  25. package/src/components/DynamicChart.tsx +113 -0
  26. package/src/components/MessageBubble.tsx +51 -13
  27. package/src/components/ProductCard.tsx +1 -7
  28. package/src/components/ProductCarousel.tsx +1 -7
  29. package/src/components/SourceCard.tsx +1 -6
  30. package/src/config/RagConfig.ts +2 -0
  31. package/src/config/uiConstants.ts +23 -0
  32. package/src/core/LangChainAgent.ts +20 -2
  33. package/src/core/Pipeline.ts +19 -1
  34. package/src/core/VectorPlugin.ts +1 -1
  35. package/src/handlers/index.ts +1 -1
  36. package/src/hooks/useRagChat.ts +1 -45
  37. package/src/hooks/useStoredMessages.ts +1 -1
  38. package/src/index.ts +20 -5
  39. package/src/llm/ILLMProvider.ts +1 -13
  40. package/src/llm/providers/AnthropicProvider.ts +2 -1
  41. package/src/llm/providers/GeminiProvider.ts +2 -1
  42. package/src/llm/providers/OllamaProvider.ts +2 -1
  43. package/src/llm/providers/OpenAIProvider.ts +2 -1
  44. package/src/llm/providers/UniversalLLMAdapter.ts +2 -1
  45. package/src/server.ts +2 -2
  46. package/src/types/chat.ts +53 -0
  47. package/src/types/index.ts +3 -0
  48. package/src/types/props.ts +79 -0
  49. package/dist/DocumentChunker-Dh9TvmGG.d.mts +0 -45
  50. package/dist/DocumentChunker-Dh9TvmGG.d.ts +0 -45
package/dist/index.mjs CHANGED
@@ -2,16 +2,17 @@ import {
2
2
  mergeDefined
3
3
  } from "./chunk-YLTMFW4M.mjs";
4
4
  import {
5
+ __objRest,
5
6
  __spreadProps,
6
7
  __spreadValues
7
8
  } from "./chunk-X4TOT24V.mjs";
8
9
 
9
10
  // src/components/ChatWidget.tsx
10
- import React8, { useState as useState5 } from "react";
11
+ import React9, { useState as useState5 } from "react";
11
12
  import { MessageSquare, X as X2 } from "lucide-react";
12
13
 
13
14
  // src/components/ChatWindow.tsx
14
- import React7, { useState as useState4, useRef as useRef3, useEffect as useEffect4, useCallback as useCallback2 } from "react";
15
+ import React8, { useState as useState4, useRef as useRef3, useEffect as useEffect4, useCallback as useCallback2 } from "react";
15
16
  import {
16
17
  Bot as Bot2,
17
18
  Trash2,
@@ -21,11 +22,13 @@ import {
21
22
  TriangleAlert,
22
23
  RotateCcw,
23
24
  Maximize2,
24
- Minimize2
25
+ Minimize2,
26
+ Mic,
27
+ MicOff
25
28
  } from "lucide-react";
26
29
 
27
30
  // src/components/MessageBubble.tsx
28
- import React4 from "react";
31
+ import React5 from "react";
29
32
  import { Bot, User, ChevronDown as ChevronDown2, ChevronRight as ChevronRight2 } from "lucide-react";
30
33
  import ReactMarkdown from "react-markdown";
31
34
  import remarkGfm from "remark-gfm";
@@ -162,6 +165,85 @@ function ProductCarousel({ products, primaryColor = "#6366f1", onAddToCart }) {
162
165
  ));
163
166
  }
164
167
 
168
+ // src/components/DynamicChart.tsx
169
+ import React4 from "react";
170
+ import {
171
+ BarChart,
172
+ Bar,
173
+ LineChart,
174
+ Line,
175
+ PieChart,
176
+ Pie,
177
+ Cell,
178
+ XAxis,
179
+ YAxis,
180
+ CartesianGrid,
181
+ Tooltip,
182
+ Legend,
183
+ ResponsiveContainer
184
+ } from "recharts";
185
+ var DEFAULT_COLORS = ["#6366f1", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899"];
186
+ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6" }) {
187
+ const { type, data, xAxisKey = "name", dataKeys = [] } = config;
188
+ const colors = config.colors || [primaryColor, accentColor, ...DEFAULT_COLORS];
189
+ if (!data || data.length === 0) {
190
+ return /* @__PURE__ */ React4.createElement("div", { className: "p-4 text-sm text-slate-500" }, "No data available for chart.");
191
+ }
192
+ if (type === "pie") {
193
+ const pieDataKey = dataKeys[0] || Object.keys(data[0]).find((k) => k !== xAxisKey) || "value";
194
+ return /* @__PURE__ */ React4.createElement("div", { className: "w-full h-64 mt-4 mb-2 select-none" }, /* @__PURE__ */ React4.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ React4.createElement(PieChart, null, /* @__PURE__ */ React4.createElement(
195
+ Pie,
196
+ {
197
+ data,
198
+ dataKey: pieDataKey,
199
+ nameKey: xAxisKey,
200
+ cx: "50%",
201
+ cy: "50%",
202
+ outerRadius: 80,
203
+ label: ({ name, percent }) => `${name} ${((percent != null ? percent : 0) * 100).toFixed(0)}%`
204
+ },
205
+ data.map((entry, index) => /* @__PURE__ */ React4.createElement(Cell, { key: `cell-${index}`, fill: colors[index % colors.length] }))
206
+ ), /* @__PURE__ */ React4.createElement(
207
+ Tooltip,
208
+ {
209
+ contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" }
210
+ }
211
+ ), /* @__PURE__ */ React4.createElement(Legend, null))));
212
+ }
213
+ return /* @__PURE__ */ React4.createElement("div", { className: "w-full h-64 mt-4 mb-2 select-none" }, /* @__PURE__ */ React4.createElement(ResponsiveContainer, { width: "100%", height: "100%" }, type === "bar" ? /* @__PURE__ */ React4.createElement(BarChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React4.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React4.createElement(XAxis, { dataKey: xAxisKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ React4.createElement(YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ React4.createElement(
214
+ Tooltip,
215
+ {
216
+ contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" },
217
+ cursor: { fill: "#f1f5f9" }
218
+ }
219
+ ), /* @__PURE__ */ React4.createElement(Legend, { wrapperStyle: { fontSize: 12 } }), dataKeys.map((key, index) => /* @__PURE__ */ React4.createElement(
220
+ Bar,
221
+ {
222
+ key,
223
+ dataKey: key,
224
+ fill: colors[index % colors.length],
225
+ radius: [4, 4, 0, 0],
226
+ barSize: Math.max(20, 60 / data.length)
227
+ }
228
+ ))) : /* @__PURE__ */ React4.createElement(LineChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ React4.createElement(CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ React4.createElement(XAxis, { dataKey: xAxisKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ React4.createElement(YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ React4.createElement(
229
+ Tooltip,
230
+ {
231
+ contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" }
232
+ }
233
+ ), /* @__PURE__ */ React4.createElement(Legend, { wrapperStyle: { fontSize: 12 } }), dataKeys.map((key, index) => /* @__PURE__ */ React4.createElement(
234
+ Line,
235
+ {
236
+ key,
237
+ type: "monotone",
238
+ dataKey: key,
239
+ stroke: colors[index % colors.length],
240
+ strokeWidth: 3,
241
+ dot: { r: 4, strokeWidth: 2 },
242
+ activeDot: { r: 6 }
243
+ }
244
+ )))));
245
+ }
246
+
165
247
  // src/components/MessageBubble.tsx
166
248
  function MessageBubble({
167
249
  message,
@@ -172,7 +254,7 @@ function MessageBubble({
172
254
  onAddToCart
173
255
  }) {
174
256
  const isUser = message.role === "user";
175
- const [showSources, setShowSources] = React4.useState(false);
257
+ const [showSources, setShowSources] = React5.useState(false);
176
258
  const resolveImage = (data) => {
177
259
  if (!data) return void 0;
178
260
  const singleFields = ["image", "img", "thumbnail"];
@@ -185,7 +267,7 @@ function MessageBubble({
185
267
  }
186
268
  return void 0;
187
269
  };
188
- const productsFromSources = React4.useMemo(() => {
270
+ const productsFromSources = React5.useMemo(() => {
189
271
  if (isUser || !sources) return [];
190
272
  return sources.filter((s) => {
191
273
  const m = s.metadata || {};
@@ -203,7 +285,7 @@ function MessageBubble({
203
285
  };
204
286
  });
205
287
  }, [sources, isUser]);
206
- const { productsFromContent, cleanContent } = React4.useMemo(() => {
288
+ const { productsFromContent, cleanContent } = React5.useMemo(() => {
207
289
  if (isUser) return { productsFromContent: [], cleanContent: message.content };
208
290
  const jsonRegex = /```json\s*([\s\S]*?)\s*```/g;
209
291
  const products = [];
@@ -226,7 +308,7 @@ function MessageBubble({
226
308
  }
227
309
  return { productsFromContent: products, cleanContent: content.trim() };
228
310
  }, [message.content, isUser]);
229
- const allProducts = React4.useMemo(() => {
311
+ const allProducts = React5.useMemo(() => {
230
312
  if (productsFromContent.length > 0) return productsFromContent;
231
313
  const uniqueProducts = [];
232
314
  const seenIds = /* @__PURE__ */ new Set();
@@ -244,44 +326,91 @@ function MessageBubble({
244
326
  return uniqueProducts;
245
327
  }, [productsFromSources, productsFromContent, message.content]);
246
328
  const hasProducts = allProducts.length > 0;
247
- return /* @__PURE__ */ React4.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ React4.createElement(
329
+ return /* @__PURE__ */ React5.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ React5.createElement(
248
330
  "div",
249
331
  {
250
332
  className: `flex-shrink-0 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"}`,
251
333
  style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
252
334
  },
253
- isUser ? /* @__PURE__ */ React4.createElement(User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ React4.createElement(Bot, { className: "w-4 h-4" })
254
- ), /* @__PURE__ */ React4.createElement("div", { className: `flex flex-col gap-1 max-w-[90%] ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ React4.createElement(
335
+ isUser ? /* @__PURE__ */ React5.createElement(User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ React5.createElement(Bot, { className: "w-4 h-4" })
336
+ ), /* @__PURE__ */ React5.createElement("div", { className: `flex flex-col gap-1 max-w-[90%] ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ React5.createElement(
255
337
  "div",
256
338
  {
257
339
  className: `relative px-4 py-3 rounded-2xl text-sm leading-relaxed shadow-sm dark:shadow-lg ${isUser ? "text-white rounded-tr-sm" : "bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-800 dark:text-white/90 rounded-tl-sm"}`,
258
340
  style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
259
341
  },
260
- isStreaming && !message.content ? /* @__PURE__ */ React4.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ React4.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ React4.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ React4.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ React4.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ React4.createElement(ReactMarkdown, { remarkPlugins: [remarkGfm] }, cleanContent || message.content), isStreaming && message.content && /* @__PURE__ */ React4.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
261
- ), !isUser && hasProducts && /* @__PURE__ */ React4.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ React4.createElement(
342
+ isStreaming && !message.content ? /* @__PURE__ */ React5.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ React5.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ React5.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ React5.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ React5.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ React5.createElement(
343
+ ReactMarkdown,
344
+ {
345
+ remarkPlugins: [remarkGfm],
346
+ components: {
347
+ table: (_a) => {
348
+ var props = __objRest(_a, []);
349
+ return /* @__PURE__ */ React5.createElement("div", { className: "overflow-x-auto my-4 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ React5.createElement("table", __spreadValues({ className: "w-full text-left border-collapse min-w-[400px]" }, props)));
350
+ },
351
+ thead: (_b) => {
352
+ var props = __objRest(_b, []);
353
+ return /* @__PURE__ */ React5.createElement("thead", __spreadValues({ className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, props));
354
+ },
355
+ th: (_c) => {
356
+ var props = __objRest(_c, []);
357
+ return /* @__PURE__ */ React5.createElement("th", __spreadValues({ className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" }, props));
358
+ },
359
+ td: (_d) => {
360
+ var props = __objRest(_d, []);
361
+ return /* @__PURE__ */ React5.createElement("td", __spreadValues({ className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" }, props));
362
+ },
363
+ code(_e) {
364
+ var _f = _e, { inline, className, children } = _f, props = __objRest(_f, ["inline", "className", "children"]);
365
+ const match = /language-(\w+)/.exec(className || "");
366
+ const isChart = match && match[1] === "chart";
367
+ if (!inline && isChart) {
368
+ try {
369
+ const config = JSON.parse(String(children).replace(/\n$/, ""));
370
+ return /* @__PURE__ */ React5.createElement("div", { className: "my-4 p-4 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ React5.createElement(
371
+ DynamicChart,
372
+ {
373
+ config,
374
+ primaryColor,
375
+ accentColor
376
+ }
377
+ ));
378
+ } catch (e) {
379
+ return /* @__PURE__ */ React5.createElement("div", { className: "p-4 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm" }, "Failed to render chart: Invalid configuration.");
380
+ }
381
+ }
382
+ return /* @__PURE__ */ React5.createElement("code", __spreadValues({ className }, props), children);
383
+ }
384
+ }
385
+ },
386
+ cleanContent || message.content
387
+ ), isStreaming && message.content && /* @__PURE__ */ React5.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
388
+ ), !isUser && hasProducts && /* @__PURE__ */ React5.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ React5.createElement(
262
389
  ProductCarousel,
263
390
  {
264
391
  products: allProducts,
265
392
  primaryColor,
266
393
  onAddToCart
267
394
  }
268
- )), !isUser && sources && sources.length > 0 && /* @__PURE__ */ React4.createElement("div", { className: "w-full" }, /* @__PURE__ */ React4.createElement(
395
+ )), !isUser && sources && sources.length > 0 && /* @__PURE__ */ React5.createElement("div", { className: "w-full" }, /* @__PURE__ */ React5.createElement(
269
396
  "button",
270
397
  {
271
398
  onClick: () => setShowSources((s) => !s),
272
399
  className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
273
400
  },
274
- showSources ? /* @__PURE__ */ React4.createElement(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ React4.createElement(ChevronRight2, { className: "w-3 h-3" }),
401
+ showSources ? /* @__PURE__ */ React5.createElement(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ React5.createElement(ChevronRight2, { className: "w-3 h-3" }),
275
402
  sources.length,
276
403
  " source",
277
404
  sources.length !== 1 ? "s" : "",
278
405
  " used"
279
- ), showSources && /* @__PURE__ */ React4.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ React4.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
406
+ ), showSources && /* @__PURE__ */ React5.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ React5.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
280
407
  }
281
408
 
282
409
  // src/components/ConfigProvider.tsx
283
- import React5, { createContext, useContext } from "react";
284
- var defaultConfig = {
410
+ import React6, { createContext, useContext } from "react";
411
+
412
+ // src/config/uiConstants.ts
413
+ var DEFAULT_CONFIG = {
285
414
  projectId: "default",
286
415
  ui: {
287
416
  title: "AI Assistant",
@@ -297,19 +426,35 @@ var defaultConfig = {
297
426
  visualStyle: "glass",
298
427
  borderRadius: "xl",
299
428
  allowUpload: true,
300
- allowResize: true
429
+ allowResize: true,
430
+ enableVoiceInput: true
301
431
  }
302
432
  };
303
- var ConfigContext = createContext(defaultConfig);
433
+ var BORDER_RADIUS_MAP = {
434
+ none: "rounded-none",
435
+ sm: "rounded-sm",
436
+ md: "rounded-md",
437
+ lg: "rounded-lg",
438
+ xl: "rounded-xl",
439
+ full: "rounded-3xl"
440
+ };
441
+ var CHAT_SUGGESTIONS = [
442
+ "What can you help me with?",
443
+ "Summarise the key topics",
444
+ "Show me an example"
445
+ ];
446
+
447
+ // src/components/ConfigProvider.tsx
448
+ var ConfigContext = createContext(DEFAULT_CONFIG);
304
449
  function ConfigProvider({
305
450
  config,
306
451
  children
307
452
  }) {
308
453
  const merged = {
309
- projectId: (config == null ? void 0 : config.projectId) || defaultConfig.projectId,
310
- ui: mergeDefined(defaultConfig.ui, config == null ? void 0 : config.ui)
454
+ projectId: (config == null ? void 0 : config.projectId) || DEFAULT_CONFIG.projectId,
455
+ ui: mergeDefined(DEFAULT_CONFIG.ui, config == null ? void 0 : config.ui)
311
456
  };
312
- return /* @__PURE__ */ React5.createElement(ConfigContext.Provider, { value: merged }, children);
457
+ return /* @__PURE__ */ React6.createElement(ConfigContext.Provider, { value: merged }, children);
313
458
  }
314
459
  function useConfig() {
315
460
  return useContext(ConfigContext);
@@ -319,7 +464,7 @@ function useConfig() {
319
464
  import { useState as useState3, useCallback, useRef as useRef2, useEffect as useEffect3 } from "react";
320
465
 
321
466
  // src/hooks/useStoredMessages.ts
322
- import * as React6 from "react";
467
+ import * as React7 from "react";
323
468
  function readStoredMessages(storageKey) {
324
469
  if (typeof window === "undefined") {
325
470
  return [];
@@ -336,8 +481,8 @@ function readStoredMessages(storageKey) {
336
481
  }
337
482
  }
338
483
  function useStoredMessages(storageKey, persist) {
339
- const [messages, setMessages] = React6.useState(() => persist ? readStoredMessages(storageKey) : []);
340
- React6.useEffect(() => {
484
+ const [messages, setMessages] = React7.useState(() => persist ? readStoredMessages(storageKey) : []);
485
+ React7.useEffect(() => {
341
486
  if (!persist || typeof window === "undefined") {
342
487
  return;
343
488
  }
@@ -505,21 +650,6 @@ function useRagChat(projectId, options = {}) {
505
650
  };
506
651
  }
507
652
 
508
- // src/config/uiConstants.ts
509
- var BORDER_RADIUS_MAP = {
510
- none: "rounded-none",
511
- sm: "rounded-sm",
512
- md: "rounded-md",
513
- lg: "rounded-lg",
514
- xl: "rounded-xl",
515
- full: "rounded-3xl"
516
- };
517
- var CHAT_SUGGESTIONS = [
518
- "What can you help me with?",
519
- "Summarise the key topics",
520
- "Show me an example"
521
- ];
522
-
523
653
  // src/components/ChatWindow.tsx
524
654
  function ChatWindow({
525
655
  className = "",
@@ -542,6 +672,56 @@ function ChatWindow({
542
672
  const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
543
673
  namespace: projectId
544
674
  });
675
+ const [suggestions, setSuggestions] = useState4([]);
676
+ const [isSuggesting, setIsSuggesting] = useState4(false);
677
+ const [isListening, setIsListening] = useState4(false);
678
+ const recognitionRef = useRef3(null);
679
+ useEffect4(() => {
680
+ if (typeof window !== "undefined") {
681
+ const win = window;
682
+ const SpeechRecognition = win.SpeechRecognition || win.webkitSpeechRecognition;
683
+ if (SpeechRecognition) {
684
+ const recognition = new SpeechRecognition();
685
+ recognition.continuous = true;
686
+ recognition.interimResults = true;
687
+ recognition.onresult = (event) => {
688
+ let finalTranscript = "";
689
+ for (let i = event.resultIndex; i < event.results.length; ++i) {
690
+ if (event.results[i].isFinal) {
691
+ finalTranscript += event.results[i][0].transcript;
692
+ }
693
+ }
694
+ if (finalTranscript) {
695
+ setInput((prev) => (prev ? prev + " " : "") + finalTranscript.trim());
696
+ }
697
+ };
698
+ recognition.onerror = (event) => {
699
+ console.error("Speech recognition error:", event.error);
700
+ setIsListening(false);
701
+ };
702
+ recognition.onend = () => {
703
+ setIsListening(false);
704
+ };
705
+ recognitionRef.current = recognition;
706
+ }
707
+ }
708
+ }, []);
709
+ const toggleListening = () => {
710
+ if (!recognitionRef.current) {
711
+ alert("Speech recognition is not supported in your browser.");
712
+ return;
713
+ }
714
+ if (isListening) {
715
+ recognitionRef.current.stop();
716
+ } else {
717
+ try {
718
+ recognitionRef.current.start();
719
+ setIsListening(true);
720
+ } catch (err) {
721
+ console.error("Failed to start recognition:", err);
722
+ }
723
+ }
724
+ };
545
725
  useEffect4(() => {
546
726
  setMounted(true);
547
727
  }, []);
@@ -552,15 +732,21 @@ function ChatWindow({
552
732
  }
553
733
  }, [messages, isLoading]);
554
734
  const sendMessage = useCallback2(async () => {
735
+ var _a2;
555
736
  const text = input.trim();
556
737
  if (!text || isLoading) return;
738
+ if (isListening) {
739
+ (_a2 = recognitionRef.current) == null ? void 0 : _a2.stop();
740
+ }
557
741
  setInput("");
742
+ setSuggestions([]);
743
+ setIsSuggesting(false);
558
744
  await send(text);
559
745
  window.setTimeout(() => {
560
- var _a2;
561
- return (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
746
+ var _a3;
747
+ return (_a3 = inputRef.current) == null ? void 0 : _a3.focus();
562
748
  }, 50);
563
- }, [input, isLoading, send]);
749
+ }, [input, isLoading, send, isListening]);
564
750
  const handleKeyDown = (e) => {
565
751
  if (e.key === "Enter" && !e.shiftKey) {
566
752
  e.preventDefault();
@@ -569,12 +755,12 @@ function ChatWindow({
569
755
  };
570
756
  const clearHistory = () => {
571
757
  clear();
758
+ setSuggestions([]);
759
+ setIsSuggesting(false);
572
760
  };
573
761
  const isEmpty = messages.length === 0;
574
762
  const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
575
763
  const isGlass = ui.visualStyle !== "solid";
576
- const [suggestions, setSuggestions] = useState4([]);
577
- const [isSuggesting, setIsSuggesting] = useState4(false);
578
764
  useEffect4(() => {
579
765
  if (input.trim().length < 3) {
580
766
  return;
@@ -599,83 +785,83 @@ function ChatWindow({
599
785
  }, 800);
600
786
  return () => clearTimeout(timer);
601
787
  }, [input, projectId]);
602
- return /* @__PURE__ */ React7.createElement(
788
+ return /* @__PURE__ */ React8.createElement(
603
789
  "div",
604
790
  {
605
791
  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}`,
606
792
  style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
607
793
  },
608
- onResizeStart && /* @__PURE__ */ React7.createElement(
794
+ onResizeStart && /* @__PURE__ */ React8.createElement(
609
795
  "div",
610
796
  {
611
797
  onMouseDown: onResizeStart,
612
798
  className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
613
799
  title: "Drag to resize"
614
800
  },
615
- /* @__PURE__ */ React7.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]" })
801
+ /* @__PURE__ */ React8.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]" })
616
802
  ),
617
- /* @__PURE__ */ React7.createElement(
803
+ /* @__PURE__ */ React8.createElement(
618
804
  "div",
619
805
  {
620
806
  className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
621
807
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
622
808
  },
623
- /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
809
+ /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
624
810
  // eslint-disable-next-line @next/next/no-img-element
625
- /* @__PURE__ */ React7.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
626
- ) : /* @__PURE__ */ React7.createElement(
811
+ /* @__PURE__ */ React8.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
812
+ ) : /* @__PURE__ */ React8.createElement(
627
813
  "div",
628
814
  {
629
815
  className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
630
816
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
631
817
  },
632
- /* @__PURE__ */ React7.createElement(Bot2, { className: "w-5 h-5 text-white" })
633
- ), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ React7.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
634
- /* @__PURE__ */ React7.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React7.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ React7.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ React7.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__ */ React7.createElement(
818
+ /* @__PURE__ */ React8.createElement(Bot2, { className: "w-5 h-5 text-white" })
819
+ ), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ React8.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
820
+ /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ React8.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ React8.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ React8.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__ */ React8.createElement(
635
821
  "button",
636
822
  {
637
823
  onClick: clearHistory,
638
824
  title: "Clear conversation",
639
825
  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"
640
826
  },
641
- /* @__PURE__ */ React7.createElement(Trash2, { className: "w-3.5 h-3.5" })
642
- ), isResized && onResetResize && /* @__PURE__ */ React7.createElement(
827
+ /* @__PURE__ */ React8.createElement(Trash2, { className: "w-3.5 h-3.5" })
828
+ ), isResized && onResetResize && /* @__PURE__ */ React8.createElement(
643
829
  "button",
644
830
  {
645
831
  onClick: onResetResize,
646
832
  title: "Reset to default size",
647
833
  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"
648
834
  },
649
- /* @__PURE__ */ React7.createElement(RotateCcw, { className: "w-3.5 h-3.5" })
650
- ), onMaximize && /* @__PURE__ */ React7.createElement(
835
+ /* @__PURE__ */ React8.createElement(RotateCcw, { className: "w-3.5 h-3.5" })
836
+ ), onMaximize && /* @__PURE__ */ React8.createElement(
651
837
  "button",
652
838
  {
653
839
  onClick: onMaximize,
654
840
  title: isMaximized ? "Minimize" : "Maximize",
655
841
  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"
656
842
  },
657
- isMaximized ? /* @__PURE__ */ React7.createElement(Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ React7.createElement(Maximize2, { className: "w-3.5 h-3.5" })
658
- ), showClose && onClose && /* @__PURE__ */ React7.createElement(
843
+ isMaximized ? /* @__PURE__ */ React8.createElement(Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ React8.createElement(Maximize2, { className: "w-3.5 h-3.5" })
844
+ ), showClose && onClose && /* @__PURE__ */ React8.createElement(
659
845
  "button",
660
846
  {
661
847
  onClick: onClose,
662
848
  title: "Close chat",
663
849
  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"
664
850
  },
665
- /* @__PURE__ */ React7.createElement(X, { className: "w-4 h-4" })
851
+ /* @__PURE__ */ React8.createElement(X, { className: "w-4 h-4" })
666
852
  )))
667
853
  ),
668
- /* @__PURE__ */ React7.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 ? (
854
+ /* @__PURE__ */ React8.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 ? (
669
855
  /* Welcome state */
670
- /* @__PURE__ */ React7.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ React7.createElement(
856
+ /* @__PURE__ */ React8.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ React8.createElement(
671
857
  "div",
672
858
  {
673
859
  className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
674
860
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
675
861
  },
676
- /* @__PURE__ */ React7.createElement(Sparkles, { className: "w-8 h-8 text-white" })
677
- ), /* @__PURE__ */ React7.createElement("div", null, /* @__PURE__ */ React7.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ React7.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ React7.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
678
- (suggestion) => /* @__PURE__ */ React7.createElement(
862
+ /* @__PURE__ */ React8.createElement(Sparkles, { className: "w-8 h-8 text-white" })
863
+ ), /* @__PURE__ */ React8.createElement("div", null, /* @__PURE__ */ React8.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ React8.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ React8.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
864
+ (suggestion) => /* @__PURE__ */ React8.createElement(
679
865
  "button",
680
866
  {
681
867
  key: suggestion,
@@ -689,7 +875,7 @@ function ChatWindow({
689
875
  suggestion
690
876
  )
691
877
  )))
692
- ) : messages.map((msg, index) => /* @__PURE__ */ React7.createElement(
878
+ ) : messages.map((msg, index) => /* @__PURE__ */ React8.createElement(
693
879
  MessageBubble,
694
880
  {
695
881
  key: msg.id,
@@ -700,17 +886,17 @@ function ChatWindow({
700
886
  accentColor: ui.accentColor,
701
887
  onAddToCart
702
888
  }
703
- )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ React7.createElement(
889
+ )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ React8.createElement(
704
890
  MessageBubble,
705
891
  {
706
- message: { role: "assistant", content: "" },
892
+ message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
707
893
  isStreaming: true,
708
894
  primaryColor: ui.primaryColor,
709
895
  accentColor: ui.accentColor,
710
896
  onAddToCart
711
897
  }
712
- ), error && /* @__PURE__ */ React7.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__ */ React7.createElement(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ React7.createElement("span", null, error)), /* @__PURE__ */ React7.createElement("div", { ref: bottomRef })),
713
- /* @__PURE__ */ React7.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__ */ React7.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__ */ React7.createElement(
898
+ ), error && /* @__PURE__ */ React8.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__ */ React8.createElement(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ React8.createElement("span", null, error)), /* @__PURE__ */ React8.createElement("div", { ref: bottomRef })),
899
+ /* @__PURE__ */ React8.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__ */ React8.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__ */ React8.createElement(
714
900
  "button",
715
901
  {
716
902
  key: suggestion,
@@ -722,9 +908,9 @@ function ChatWindow({
722
908
  },
723
909
  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"
724
910
  },
725
- /* @__PURE__ */ React7.createElement(Sparkles, { className: "w-3 h-3 text-amber-400" }),
911
+ /* @__PURE__ */ React8.createElement(Sparkles, { className: "w-3 h-3 text-amber-400" }),
726
912
  suggestion
727
- )), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ React7.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__ */ React7.createElement(Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ React7.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__ */ React7.createElement(
913
+ )), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ React8.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__ */ React8.createElement(Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ React8.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__ */ React8.createElement(
728
914
  "textarea",
729
915
  {
730
916
  ref: inputRef,
@@ -743,7 +929,17 @@ function ChatWindow({
743
929
  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",
744
930
  style: { scrollbarWidth: "none" }
745
931
  }
746
- ), /* @__PURE__ */ React7.createElement(
932
+ ), ui.enableVoiceInput !== false && /* @__PURE__ */ React8.createElement(
933
+ "button",
934
+ {
935
+ type: "button",
936
+ onClick: toggleListening,
937
+ disabled: isLoading,
938
+ 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"}`,
939
+ title: isListening ? "Stop listening" : "Start voice input"
940
+ },
941
+ isListening ? /* @__PURE__ */ React8.createElement(MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ React8.createElement(Mic, { className: "w-4 h-4" })
942
+ ), /* @__PURE__ */ React8.createElement(
747
943
  "button",
748
944
  {
749
945
  onClick: sendMessage,
@@ -754,8 +950,8 @@ function ChatWindow({
754
950
  // slate-400/20 for light mode disabled
755
951
  }
756
952
  },
757
- /* @__PURE__ */ React7.createElement(ArrowUp, { className: "w-4 h-4 text-white" })
758
- )), /* @__PURE__ */ React7.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"))
953
+ /* @__PURE__ */ React8.createElement(ArrowUp, { className: "w-4 h-4 text-white" })
954
+ )), /* @__PURE__ */ React8.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"))
759
955
  );
760
956
  }
761
957
 
@@ -818,7 +1014,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
818
1014
  }
819
1015
  };
820
1016
  const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
821
- return /* @__PURE__ */ React8.createElement(React8.Fragment, null, /* @__PURE__ */ React8.createElement(
1017
+ return /* @__PURE__ */ React9.createElement(React9.Fragment, null, /* @__PURE__ */ React9.createElement(
822
1018
  "div",
823
1019
  {
824
1020
  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"}`,
@@ -828,7 +1024,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
828
1024
  maxHeight: "calc(100vh - 6rem)"
829
1025
  }
830
1026
  },
831
- /* @__PURE__ */ React8.createElement(
1027
+ /* @__PURE__ */ React9.createElement(
832
1028
  ChatWindow,
833
1029
  {
834
1030
  className: "h-full relative z-10",
@@ -842,13 +1038,13 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
842
1038
  onAddToCart
843
1039
  }
844
1040
  ),
845
- /* @__PURE__ */ React8.createElement(
1041
+ /* @__PURE__ */ React9.createElement(
846
1042
  "div",
847
1043
  {
848
1044
  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"}`
849
1045
  }
850
1046
  )
851
- ), /* @__PURE__ */ React8.createElement(
1047
+ ), /* @__PURE__ */ React9.createElement(
852
1048
  "button",
853
1049
  {
854
1050
  onClick: isOpen ? () => setIsOpen(false) : handleOpen,
@@ -856,26 +1052,26 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
856
1052
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
857
1053
  "aria-label": "Open chat"
858
1054
  },
859
- /* @__PURE__ */ React8.createElement(
1055
+ /* @__PURE__ */ React9.createElement(
860
1056
  "span",
861
1057
  {
862
1058
  className: "absolute inset-0 rounded-full animate-ping opacity-20",
863
1059
  style: { background: ui.primaryColor }
864
1060
  }
865
1061
  ),
866
- /* @__PURE__ */ React8.createElement(
1062
+ /* @__PURE__ */ React9.createElement(
867
1063
  "span",
868
1064
  {
869
1065
  className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
870
1066
  },
871
- isOpen ? /* @__PURE__ */ React8.createElement(X2, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ React8.createElement(MessageSquare, { className: "w-6 h-6 text-white" })
1067
+ isOpen ? /* @__PURE__ */ React9.createElement(X2, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ React9.createElement(MessageSquare, { className: "w-6 h-6 text-white" })
872
1068
  ),
873
- hasUnread && !isOpen && /* @__PURE__ */ React8.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")
1069
+ hasUnread && !isOpen && /* @__PURE__ */ React9.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")
874
1070
  ));
875
1071
  }
876
1072
 
877
1073
  // src/components/DocumentUpload.tsx
878
- import React9, { useState as useState6, useRef as useRef4 } from "react";
1074
+ import React10, { useState as useState6, useRef as useRef4 } from "react";
879
1075
  import { Upload, File, X as X3, CheckCircle, AlertCircle, Loader2 } from "lucide-react";
880
1076
  function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
881
1077
  const { ui } = useConfig();
@@ -931,7 +1127,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
931
1127
  };
932
1128
  const isUploading = fileStates.some((s) => s.status === "uploading");
933
1129
  const hasIdle = fileStates.some((s) => s.status === "idle");
934
- return /* @__PURE__ */ React9.createElement(
1130
+ return /* @__PURE__ */ React10.createElement(
935
1131
  "div",
936
1132
  {
937
1133
  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}`,
@@ -939,14 +1135,14 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
939
1135
  onDragLeave,
940
1136
  onDrop
941
1137
  },
942
- /* @__PURE__ */ React9.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ React9.createElement(
1138
+ /* @__PURE__ */ React10.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ React10.createElement(
943
1139
  "div",
944
1140
  {
945
1141
  className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
946
1142
  style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
947
1143
  },
948
- /* @__PURE__ */ React9.createElement(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
949
- ), /* @__PURE__ */ React9.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ React9.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__ */ React9.createElement(
1144
+ /* @__PURE__ */ React10.createElement(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
1145
+ ), /* @__PURE__ */ React10.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ React10.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__ */ React10.createElement(
950
1146
  "button",
951
1147
  {
952
1148
  onClick: () => {
@@ -962,7 +1158,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
962
1158
  }
963
1159
  },
964
1160
  "Select Files"
965
- ), /* @__PURE__ */ React9.createElement(
1161
+ ), /* @__PURE__ */ React10.createElement(
966
1162
  "input",
967
1163
  {
968
1164
  ref: fileInputRef,
@@ -973,22 +1169,22 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
973
1169
  accept: ".pdf,.docx,.txt,.md,.json,.csv"
974
1170
  }
975
1171
  )),
976
- fileStates.length > 0 && /* @__PURE__ */ React9.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ React9.createElement(
1172
+ fileStates.length > 0 && /* @__PURE__ */ React10.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ React10.createElement(
977
1173
  "div",
978
1174
  {
979
1175
  key: i,
980
1176
  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"
981
1177
  },
982
- /* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ React9.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ React9.createElement(File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ React9.createElement("div", { className: "truncate" }, /* @__PURE__ */ React9.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ React9.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
983
- /* @__PURE__ */ React9.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ React9.createElement(Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ React9.createElement(CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ React9.createElement("div", { title: state.error }, /* @__PURE__ */ React9.createElement(AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ React9.createElement(
1178
+ /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ React10.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ React10.createElement(File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ React10.createElement("div", { className: "truncate" }, /* @__PURE__ */ React10.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ React10.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
1179
+ /* @__PURE__ */ React10.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ React10.createElement(Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ React10.createElement(CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ React10.createElement("div", { title: state.error }, /* @__PURE__ */ React10.createElement(AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ React10.createElement(
984
1180
  "button",
985
1181
  {
986
1182
  onClick: () => removeFile(i),
987
1183
  className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
988
1184
  },
989
- /* @__PURE__ */ React9.createElement(X3, { className: "w-3.5 h-3.5 text-slate-400" })
1185
+ /* @__PURE__ */ React10.createElement(X3, { className: "w-3.5 h-3.5 text-slate-400" })
990
1186
  ))
991
- )), hasIdle && !isUploading && /* @__PURE__ */ React9.createElement(
1187
+ )), hasIdle && !isUploading && /* @__PURE__ */ React10.createElement(
992
1188
  "button",
993
1189
  {
994
1190
  onClick: uploadFiles,