@retrivora-ai/rag-engine 1.0.0 → 1.0.2

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 (44) hide show
  1. package/dist/{ChromaDBProvider-APQVJ5F7.mjs → ChromaDBProvider-MIDOR4FW.mjs} +2 -2
  2. package/dist/{MilvusProvider-35US67MS.mjs → MilvusProvider-U7SKC27V.mjs} +2 -2
  3. package/dist/{MongoDBProvider-COVYZDP6.mjs → MongoDBProvider-BO2Y5DRR.mjs} +2 -2
  4. package/dist/{PineconeProvider-AWFJQDZL.mjs → PineconeProvider-QZNRKTN2.mjs} +2 -2
  5. package/dist/{PostgreSQLProvider-IEYRJ7XJ.mjs → PostgreSQLProvider-BMOETDZA.mjs} +1 -1
  6. package/dist/{QdrantProvider-M6TQYZRO.mjs → QdrantProvider-YNUNEOZH.mjs} +2 -2
  7. package/dist/{RedisProvider-3G5PBLZ4.mjs → RedisProvider-SR65SCKV.mjs} +2 -2
  8. package/dist/{SimpleGraphProvider-UK7DJW37.mjs → SimpleGraphProvider-SLOXO4M7.mjs} +1 -1
  9. package/dist/{UniversalVectorProvider-FYQ3B2PW.mjs → UniversalVectorProvider-IN67OS56.mjs} +3 -3
  10. package/dist/{WeaviateProvider-ITHO36IL.mjs → WeaviateProvider-5FWDFITI.mjs} +2 -2
  11. package/dist/{chunk-4A47RCG2.mjs → chunk-3DSHW676.mjs} +1 -1
  12. package/dist/{chunk-NXUCKY5L.mjs → chunk-5YGUXK7Z.mjs} +1 -1
  13. package/dist/{chunk-7SOSCZGS.mjs → chunk-73I6VWU3.mjs} +2 -2
  14. package/dist/{chunk-WGSZNY3X.mjs → chunk-CFVEZTBJ.mjs} +1 -1
  15. package/dist/{chunk-U6KHVZLF.mjs → chunk-LR3VMDVK.mjs} +2 -2
  16. package/dist/{chunk-OOQXNLXD.mjs → chunk-M6JSPGAR.mjs} +1 -1
  17. package/dist/{chunk-P4HAQ7KB.mjs → chunk-OJNAKSQ2.mjs} +90 -34
  18. package/dist/{chunk-TYHTZIDP.mjs → chunk-U55XRW3U.mjs} +1 -1
  19. package/dist/{chunk-ZNBKHNJ4.mjs → chunk-VUQJVIJT.mjs} +1 -1
  20. package/dist/{chunk-QMIKLALV.mjs → chunk-X4TOT24V.mjs} +32 -0
  21. package/dist/{chunk-67AJ6SMD.mjs → chunk-YLTMFW4M.mjs} +1 -1
  22. package/dist/handlers/index.d.mts +1 -1
  23. package/dist/handlers/index.d.ts +1 -1
  24. package/dist/handlers/index.js +109 -22
  25. package/dist/handlers/index.mjs +5 -3
  26. package/dist/{index-CrGMwXfO.d.ts → index-B2mutkgp.d.ts} +5 -1
  27. package/dist/{index-v669iV-k.d.mts → index-Bjy0es5a.d.mts} +5 -1
  28. package/dist/index.d.mts +13 -7
  29. package/dist/index.d.ts +13 -7
  30. package/dist/index.js +325 -380
  31. package/dist/index.mjs +315 -370
  32. package/dist/server.d.mts +7 -22
  33. package/dist/server.d.ts +7 -22
  34. package/dist/server.js +48 -22
  35. package/dist/server.mjs +11 -11
  36. package/package.json +1 -1
  37. package/src/components/ChatWindow.tsx +4 -3
  38. package/src/components/MessageBubble.tsx +5 -2
  39. package/src/core/Pipeline.ts +1 -0
  40. package/src/core/VectorPlugin.ts +13 -22
  41. package/src/handlers/index.ts +53 -0
  42. package/src/hooks/useRagChat.ts +79 -15
  43. package/src/providers/vectordb/MongoDBProvider.ts +1 -1
  44. package/src/rag/EntityExtractor.ts +3 -0
package/dist/index.mjs CHANGED
@@ -1,17 +1,17 @@
1
1
  import {
2
2
  mergeDefined
3
- } from "./chunk-67AJ6SMD.mjs";
3
+ } from "./chunk-YLTMFW4M.mjs";
4
4
  import {
5
5
  __spreadProps,
6
6
  __spreadValues
7
- } from "./chunk-QMIKLALV.mjs";
7
+ } from "./chunk-X4TOT24V.mjs";
8
8
 
9
9
  // src/components/ChatWidget.tsx
10
- import { useState as useState4 } from "react";
10
+ import React7, { useState as useState4 } from "react";
11
11
  import { MessageSquare as MessageSquare2, X as X2 } from "lucide-react";
12
12
 
13
13
  // src/components/ChatWindow.tsx
14
- import { useState as useState3, useRef as useRef2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
14
+ import React6, { useState as useState3, useRef as useRef2, useEffect as useEffect3, useCallback as useCallback2 } from "react";
15
15
  import {
16
16
  Bot as Bot3,
17
17
  Trash2,
@@ -30,7 +30,6 @@ import remarkGfm from "remark-gfm";
30
30
  // src/components/SourceCard.tsx
31
31
  import React from "react";
32
32
  import { ChevronDown, ChevronUp } from "lucide-react";
33
- import { Fragment, jsx, jsxs } from "react/jsx-runtime";
34
33
  function SourceCard({ source, index }) {
35
34
  var _a, _b;
36
35
  const [expanded, setExpanded] = React.useState(false);
@@ -39,37 +38,19 @@ function SourceCard({ source, index }) {
39
38
  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";
40
39
  const preview = source.content.slice(0, 120);
41
40
  const hasMore = source.content.length > 120;
42
- return /* @__PURE__ */ jsxs(
41
+ return /* @__PURE__ */ React.createElement(
43
42
  "div",
44
43
  {
45
44
  className: `rounded-xl border backdrop-blur-sm p-3 transition-all duration-200 hover:scale-[1.01] cursor-pointer ${scoreBg}`,
46
- onClick: () => setExpanded((e) => !e),
47
- children: [
48
- /* @__PURE__ */ jsxs("div", { className: "flex items-start justify-between gap-2", children: [
49
- /* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 min-w-0", children: [
50
- /* @__PURE__ */ 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 }),
51
- /* @__PURE__ */ 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 })
52
- ] }),
53
- /* @__PURE__ */ jsxs("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums`, children: [
54
- scorePercent,
55
- "%"
56
- ] })
57
- ] }),
58
- /* @__PURE__ */ jsx("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed", children: expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}` }),
59
- hasMore && /* @__PURE__ */ 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__ */ jsxs(Fragment, { children: [
60
- /* @__PURE__ */ jsx(ChevronUp, { className: "w-3 h-3" }),
61
- " Show less"
62
- ] }) : /* @__PURE__ */ jsxs(Fragment, { children: [
63
- /* @__PURE__ */ jsx(ChevronDown, { className: "w-3 h-3" }),
64
- " Show more"
65
- ] }) })
66
- ]
67
- }
45
+ onClick: () => setExpanded((e) => !e)
46
+ },
47
+ /* @__PURE__ */ React.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ React.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ React.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__ */ React.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__ */ React.createElement("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums` }, scorePercent, "%")),
48
+ /* @__PURE__ */ React.createElement("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed" }, expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}`),
49
+ hasMore && /* @__PURE__ */ React.createElement("button", { className: "mt-1 text-[10px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-0.5" }, expanded ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ChevronUp, { className: "w-3 h-3" }), " Show less") : /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(ChevronDown, { className: "w-3 h-3" }), " Show more"))
68
50
  );
69
51
  }
70
52
 
71
53
  // src/components/MessageBubble.tsx
72
- import { jsx as jsx2, jsxs as jsxs2 } from "react/jsx-runtime";
73
54
  function MessageBubble({
74
55
  message,
75
56
  sources,
@@ -79,52 +60,36 @@ function MessageBubble({
79
60
  }) {
80
61
  const isUser = message.role === "user";
81
62
  const [showSources, setShowSources] = React2.useState(false);
82
- return /* @__PURE__ */ jsxs2("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start`, children: [
83
- /* @__PURE__ */ jsx2(
84
- "div",
85
- {
86
- 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"}`,
87
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
88
- children: isUser ? /* @__PURE__ */ jsx2(User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ jsx2(Bot, { className: "w-4 h-4" })
89
- }
90
- ),
91
- /* @__PURE__ */ jsxs2("div", { className: `flex flex-col gap-1 max-w-[75%] ${isUser ? "items-end" : "items-start"}`, children: [
92
- /* @__PURE__ */ jsx2(
93
- "div",
94
- {
95
- 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"}`,
96
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
97
- children: isStreaming ? /* @__PURE__ */ jsxs2("span", { className: "flex items-center gap-1", children: [
98
- /* @__PURE__ */ jsx2("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }),
99
- /* @__PURE__ */ jsx2("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }),
100
- /* @__PURE__ */ jsx2("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })
101
- ] }) : /* @__PURE__ */ jsx2("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}`, children: /* @__PURE__ */ jsx2(ReactMarkdown, { remarkPlugins: [remarkGfm], children: message.content }) })
102
- }
103
- ),
104
- !isUser && sources && sources.length > 0 && /* @__PURE__ */ jsxs2("div", { className: "w-full", children: [
105
- /* @__PURE__ */ jsxs2(
106
- "button",
107
- {
108
- onClick: () => setShowSources((s) => !s),
109
- className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1",
110
- children: [
111
- showSources ? /* @__PURE__ */ jsx2(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ jsx2(ChevronRight, { className: "w-3 h-3" }),
112
- sources.length,
113
- " source",
114
- sources.length !== 1 ? "s" : "",
115
- " used"
116
- ]
117
- }
118
- ),
119
- showSources && /* @__PURE__ */ jsx2("div", { className: "mt-2 flex flex-col gap-2", children: sources.map((src, i) => /* @__PURE__ */ jsx2(SourceCard, { source: src, index: i }, src.id)) })
120
- ] })
121
- ] })
122
- ] });
63
+ return /* @__PURE__ */ React2.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ React2.createElement(
64
+ "div",
65
+ {
66
+ 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"}`,
67
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
68
+ },
69
+ isUser ? /* @__PURE__ */ React2.createElement(User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ React2.createElement(Bot, { className: "w-4 h-4" })
70
+ ), /* @__PURE__ */ React2.createElement("div", { className: `flex flex-col gap-1 max-w-[75%] ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ React2.createElement(
71
+ "div",
72
+ {
73
+ 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"}`,
74
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
75
+ },
76
+ isStreaming && !message.content ? /* @__PURE__ */ React2.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ React2.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ React2.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ React2.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ React2.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ React2.createElement(ReactMarkdown, { remarkPlugins: [remarkGfm] }, message.content), isStreaming && message.content && /* @__PURE__ */ React2.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
77
+ ), !isUser && sources && sources.length > 0 && /* @__PURE__ */ React2.createElement("div", { className: "w-full" }, /* @__PURE__ */ React2.createElement(
78
+ "button",
79
+ {
80
+ onClick: () => setShowSources((s) => !s),
81
+ className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
82
+ },
83
+ showSources ? /* @__PURE__ */ React2.createElement(ChevronDown2, { className: "w-3 h-3" }) : /* @__PURE__ */ React2.createElement(ChevronRight, { className: "w-3 h-3" }),
84
+ sources.length,
85
+ " source",
86
+ sources.length !== 1 ? "s" : "",
87
+ " used"
88
+ ), showSources && /* @__PURE__ */ React2.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ React2.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
123
89
  }
124
90
 
125
91
  // src/components/ConfigProvider.tsx
126
- import { createContext, useContext } from "react";
127
- import { jsx as jsx3 } from "react/jsx-runtime";
92
+ import React3, { createContext, useContext } from "react";
128
93
  var defaultConfig = {
129
94
  projectId: "default",
130
95
  ui: {
@@ -152,7 +117,7 @@ function ConfigProvider({
152
117
  projectId: (config == null ? void 0 : config.projectId) || defaultConfig.projectId,
153
118
  ui: mergeDefined(defaultConfig.ui, config == null ? void 0 : config.ui)
154
119
  };
155
- return /* @__PURE__ */ jsx3(ConfigContext.Provider, { value: merged, children });
120
+ return /* @__PURE__ */ React3.createElement(ConfigContext.Provider, { value: merged }, children);
156
121
  }
157
122
  function useConfig() {
158
123
  return useContext(ConfigContext);
@@ -160,7 +125,6 @@ function useConfig() {
160
125
 
161
126
  // src/hooks/useRagChat.ts
162
127
  import { useState as useState2, useCallback, useRef, useEffect as useEffect2 } from "react";
163
- import axios from "axios";
164
128
 
165
129
  // src/hooks/useStoredMessages.ts
166
130
  import * as React4 from "react";
@@ -214,7 +178,6 @@ function useRagChat(projectId, options = {}) {
214
178
  }, [messages]);
215
179
  const sendMessage = useCallback(
216
180
  async (text, options2) => {
217
- var _a, _b, _c;
218
181
  const trimmed = text.trim();
219
182
  if (!trimmed || isLoading) return;
220
183
  lastInputRef.current = trimmed;
@@ -231,22 +194,77 @@ function useRagChat(projectId, options = {}) {
231
194
  setIsLoading(true);
232
195
  try {
233
196
  const history = messagesRef.current.map(({ role, content }) => ({ role, content }));
234
- const { data } = await axios.post(apiUrl, {
235
- message: trimmed,
236
- history,
237
- namespace: namespace != null ? namespace : projectId
197
+ const response = await fetch(apiUrl, {
198
+ method: "POST",
199
+ headers: { "Content-Type": "application/json" },
200
+ body: JSON.stringify({
201
+ message: trimmed,
202
+ history,
203
+ namespace: namespace != null ? namespace : projectId
204
+ })
238
205
  });
239
- const assistantMessage = {
240
- id: `assistant_${Date.now()}`,
206
+ if (!response.ok) {
207
+ const errorData = await response.json().catch(() => ({}));
208
+ throw new Error(errorData.error || `Server returned ${response.status}`);
209
+ }
210
+ if (!response.body) {
211
+ throw new Error("No response body received from server");
212
+ }
213
+ const reader = response.body.getReader();
214
+ const decoder = new TextDecoder();
215
+ let assistantContent = "";
216
+ let sources = [];
217
+ const assistantMessageId = `assistant_${Date.now()}`;
218
+ setMessages((prev) => [
219
+ ...prev,
220
+ {
221
+ id: assistantMessageId,
222
+ role: "assistant",
223
+ content: "",
224
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
225
+ }
226
+ ]);
227
+ while (true) {
228
+ const { done, value } = await reader.read();
229
+ if (done) break;
230
+ const chunk = decoder.decode(value, { stream: true });
231
+ if (chunk.includes("__METADATA__")) {
232
+ const [text2, metadataStr] = chunk.split("__METADATA__");
233
+ if (text2) assistantContent += text2;
234
+ try {
235
+ const meta = JSON.parse(metadataStr);
236
+ sources = meta.sources || [];
237
+ } catch (e) {
238
+ console.warn("[useRagChat] Failed to parse metadata");
239
+ }
240
+ } else if (chunk.includes("__ERROR__")) {
241
+ const [text2, errorStr] = chunk.split("__ERROR__");
242
+ if (text2) assistantContent += text2;
243
+ try {
244
+ const err = JSON.parse(errorStr);
245
+ setError(err.error || "Stream error");
246
+ } catch (e) {
247
+ setError("An error occurred during streaming");
248
+ }
249
+ } else {
250
+ assistantContent += chunk;
251
+ }
252
+ setMessages(
253
+ (prev) => prev.map(
254
+ (msg) => msg.id === assistantMessageId ? __spreadProps(__spreadValues({}, msg), { content: assistantContent, sources: sources.length > 0 ? sources : msg.sources }) : msg
255
+ )
256
+ );
257
+ }
258
+ const finalAssistantMessage = {
259
+ id: assistantMessageId,
241
260
  role: "assistant",
242
- content: data.reply,
243
- sources: data.sources,
261
+ content: assistantContent,
262
+ sources: sources.length > 0 ? sources : void 0,
244
263
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
245
264
  };
246
- setMessages((prev) => [...prev, assistantMessage]);
247
- onReply == null ? void 0 : onReply(assistantMessage);
265
+ onReply == null ? void 0 : onReply(finalAssistantMessage);
248
266
  } catch (err) {
249
- const msg = axios.isAxiosError(err) ? (_c = (_b = (_a = err.response) == null ? void 0 : _a.data) == null ? void 0 : _b.error) != null ? _c : err.message : "Something went wrong. Please try again.";
267
+ const msg = err instanceof Error ? err.message : "Something went wrong. Please try again.";
250
268
  setError(msg);
251
269
  onError == null ? void 0 : onError(msg);
252
270
  } finally {
@@ -280,6 +298,7 @@ function useRagChat(projectId, options = {}) {
280
298
  }
281
299
 
282
300
  // src/app/constants.tsx
301
+ import React5 from "react";
283
302
  import {
284
303
  Zap,
285
304
  Database,
@@ -299,7 +318,6 @@ import {
299
318
  Puzzle,
300
319
  MessageSquare
301
320
  } from "lucide-react";
302
- import { jsx as jsx4 } from "react/jsx-runtime";
303
321
  var CHAT_SUGGESTIONS = [
304
322
  "What can you help me with?",
305
323
  "Summarise the key topics",
@@ -315,8 +333,8 @@ var BORDER_RADIUS_MAP = {
315
333
  };
316
334
 
317
335
  // src/components/ChatWindow.tsx
318
- import { jsx as jsx5, jsxs as jsxs3 } from "react/jsx-runtime";
319
336
  function ChatWindow({ className = "", style, onClose, showClose = false }) {
337
+ var _a;
320
338
  const { ui, projectId } = useConfig();
321
339
  const [input, setInput] = useState3("");
322
340
  const [mounted, setMounted] = useState3(false);
@@ -329,9 +347,9 @@ function ChatWindow({ className = "", style, onClose, showClose = false }) {
329
347
  setMounted(true);
330
348
  }, []);
331
349
  useEffect3(() => {
332
- var _a;
350
+ var _a2;
333
351
  if (messages.length > 0 || isLoading) {
334
- (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
352
+ (_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
335
353
  }
336
354
  }, [messages, isLoading]);
337
355
  const sendMessage = useCallback2(async () => {
@@ -340,8 +358,8 @@ function ChatWindow({ className = "", style, onClose, showClose = false }) {
340
358
  setInput("");
341
359
  await send(text);
342
360
  window.setTimeout(() => {
343
- var _a;
344
- return (_a = inputRef.current) == null ? void 0 : _a.focus();
361
+ var _a2;
362
+ return (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
345
363
  }, 50);
346
364
  }, [input, isLoading, send]);
347
365
  const handleKeyDown = (e) => {
@@ -356,158 +374,120 @@ function ChatWindow({ className = "", style, onClose, showClose = false }) {
356
374
  const isEmpty = messages.length === 0;
357
375
  const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
358
376
  const isGlass = ui.visualStyle !== "solid";
359
- return /* @__PURE__ */ jsxs3(
377
+ return /* @__PURE__ */ React6.createElement(
360
378
  "div",
361
379
  {
362
380
  className: `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}`,
363
- style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style),
364
- children: [
365
- /* @__PURE__ */ jsxs3(
366
- "div",
381
+ style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
382
+ },
383
+ /* @__PURE__ */ React6.createElement(
384
+ "div",
385
+ {
386
+ className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
387
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
388
+ },
389
+ /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
390
+ // eslint-disable-next-line @next/next/no-img-element
391
+ /* @__PURE__ */ React6.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
392
+ ) : /* @__PURE__ */ React6.createElement(
393
+ "div",
394
+ {
395
+ className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
396
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
397
+ },
398
+ /* @__PURE__ */ React6.createElement(Bot3, { className: "w-5 h-5 text-white" })
399
+ ), /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ React6.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
400
+ /* @__PURE__ */ React6.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ React6.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400" }, /* @__PURE__ */ React6.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), mounted && messages.length > 0 && /* @__PURE__ */ React6.createElement(
401
+ "button",
402
+ {
403
+ onClick: clearHistory,
404
+ title: "Clear conversation",
405
+ className: "w-7 h-7 rounded-lg flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-slate-100 dark:hover:bg-white/10 transition-all cursor-pointer"
406
+ },
407
+ /* @__PURE__ */ React6.createElement(Trash2, { className: "w-3.5 h-3.5" })
408
+ ), showClose && onClose && /* @__PURE__ */ React6.createElement(
409
+ "button",
410
+ {
411
+ onClick: onClose,
412
+ title: "Close chat",
413
+ className: "w-7 h-7 rounded-lg flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-slate-100 dark:hover:bg-white/10 transition-all cursor-pointer"
414
+ },
415
+ /* @__PURE__ */ React6.createElement(X, { className: "w-4 h-4" })
416
+ ))
417
+ ),
418
+ /* @__PURE__ */ React6.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 ? (
419
+ /* Welcome state */
420
+ /* @__PURE__ */ React6.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ React6.createElement(
421
+ "div",
422
+ {
423
+ className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
424
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
425
+ },
426
+ /* @__PURE__ */ React6.createElement(Sparkles2, { className: "w-8 h-8 text-white" })
427
+ ), /* @__PURE__ */ React6.createElement("div", null, /* @__PURE__ */ React6.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ React6.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ React6.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
428
+ (suggestion) => /* @__PURE__ */ React6.createElement(
429
+ "button",
367
430
  {
368
- className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
369
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` },
370
- children: [
371
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-3", children: [
372
- ui.logoUrl ? (
373
- // eslint-disable-next-line @next/next/no-img-element
374
- /* @__PURE__ */ jsx5("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
375
- ) : /* @__PURE__ */ jsx5(
376
- "div",
377
- {
378
- className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
379
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
380
- children: /* @__PURE__ */ jsx5(Bot3, { className: "w-5 h-5 text-white" })
381
- }
382
- ),
383
- /* @__PURE__ */ jsxs3("div", { children: [
384
- /* @__PURE__ */ jsx5("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight", children: ui.title }),
385
- ui.poweredBy && /* @__PURE__ */ jsx5("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight", children: `Powered by ${ui.poweredBy}` })
386
- ] })
387
- ] }),
388
- /* @__PURE__ */ jsxs3("div", { className: "flex items-center gap-2", children: [
389
- /* @__PURE__ */ jsxs3("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400", children: [
390
- /* @__PURE__ */ jsx5("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }),
391
- "Online"
392
- ] }),
393
- mounted && messages.length > 0 && /* @__PURE__ */ jsx5(
394
- "button",
395
- {
396
- onClick: clearHistory,
397
- title: "Clear conversation",
398
- className: "w-7 h-7 rounded-lg flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-slate-100 dark:hover:bg-white/10 transition-all cursor-pointer",
399
- children: /* @__PURE__ */ jsx5(Trash2, { className: "w-3.5 h-3.5" })
400
- }
401
- ),
402
- showClose && onClose && /* @__PURE__ */ jsx5(
403
- "button",
404
- {
405
- onClick: onClose,
406
- title: "Close chat",
407
- className: "w-7 h-7 rounded-lg flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-slate-100 dark:hover:bg-white/10 transition-all cursor-pointer",
408
- children: /* @__PURE__ */ jsx5(X, { className: "w-4 h-4" })
409
- }
410
- )
411
- ] })
412
- ]
413
- }
414
- ),
415
- /* @__PURE__ */ jsxs3("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: [
416
- !mounted || isEmpty ? (
417
- /* Welcome state */
418
- /* @__PURE__ */ jsxs3("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12", children: [
419
- /* @__PURE__ */ jsx5(
420
- "div",
421
- {
422
- className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
423
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
424
- children: /* @__PURE__ */ jsx5(Sparkles2, { className: "w-8 h-8 text-white" })
425
- }
426
- ),
427
- /* @__PURE__ */ jsxs3("div", { children: [
428
- /* @__PURE__ */ jsx5("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed", children: ui.welcomeMessage }),
429
- /* @__PURE__ */ jsx5("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2", children: "Ask a question to get started" })
430
- ] }),
431
- /* @__PURE__ */ jsx5("div", { className: "flex flex-wrap gap-2 justify-center mt-2", children: CHAT_SUGGESTIONS.map(
432
- (suggestion) => /* @__PURE__ */ jsx5(
433
- "button",
434
- {
435
- onClick: () => {
436
- var _a;
437
- setInput(suggestion);
438
- (_a = inputRef.current) == null ? void 0 : _a.focus();
439
- },
440
- 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",
441
- children: suggestion
442
- },
443
- suggestion
444
- )
445
- ) })
446
- ] })
447
- ) : messages.map((msg) => /* @__PURE__ */ jsx5(
448
- MessageBubble,
449
- {
450
- message: msg,
451
- sources: msg.sources,
452
- primaryColor: ui.primaryColor,
453
- accentColor: ui.accentColor
431
+ key: suggestion,
432
+ onClick: () => {
433
+ var _a2;
434
+ setInput(suggestion);
435
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
454
436
  },
455
- msg.id
456
- )),
457
- isLoading && /* @__PURE__ */ jsx5(
458
- MessageBubble,
459
- {
460
- message: { role: "assistant", content: "" },
461
- isStreaming: true,
462
- primaryColor: ui.primaryColor,
463
- accentColor: ui.accentColor
464
- }
465
- ),
466
- error && /* @__PURE__ */ jsxs3("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: [
467
- /* @__PURE__ */ jsx5(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }),
468
- /* @__PURE__ */ jsx5("span", { children: error })
469
- ] }),
470
- /* @__PURE__ */ jsx5("div", { ref: bottomRef })
471
- ] }),
472
- /* @__PURE__ */ jsxs3("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: [
473
- /* @__PURE__ */ jsxs3("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: [
474
- /* @__PURE__ */ jsx5(
475
- "textarea",
476
- {
477
- ref: inputRef,
478
- value: input,
479
- onChange: (e) => setInput(e.target.value),
480
- onKeyDown: handleKeyDown,
481
- placeholder: ui.placeholder,
482
- rows: 1,
483
- disabled: isLoading,
484
- 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",
485
- style: { scrollbarWidth: "none" }
486
- }
487
- ),
488
- /* @__PURE__ */ jsx5(
489
- "button",
490
- {
491
- onClick: sendMessage,
492
- disabled: !input.trim() || isLoading,
493
- 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",
494
- style: {
495
- background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
496
- // slate-400/20 for light mode disabled
497
- },
498
- children: /* @__PURE__ */ jsx5(ArrowUp, { className: "w-4 h-4 text-white" })
499
- }
500
- )
501
- ] }),
502
- /* @__PURE__ */ jsx5("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" })
503
- ] })
504
- ]
505
- }
437
+ 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"
438
+ },
439
+ suggestion
440
+ )
441
+ )))
442
+ ) : messages.map((msg, index) => /* @__PURE__ */ React6.createElement(
443
+ MessageBubble,
444
+ {
445
+ key: msg.id,
446
+ message: msg,
447
+ sources: msg.sources,
448
+ isStreaming: isLoading && index === messages.length - 1 && msg.role === "assistant",
449
+ primaryColor: ui.primaryColor,
450
+ accentColor: ui.accentColor
451
+ }
452
+ )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ React6.createElement(
453
+ MessageBubble,
454
+ {
455
+ message: { role: "assistant", content: "" },
456
+ isStreaming: true,
457
+ primaryColor: ui.primaryColor,
458
+ accentColor: ui.accentColor
459
+ }
460
+ ), error && /* @__PURE__ */ React6.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__ */ React6.createElement(TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ React6.createElement("span", null, error)), /* @__PURE__ */ React6.createElement("div", { ref: bottomRef })),
461
+ /* @__PURE__ */ React6.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]"}` }, /* @__PURE__ */ React6.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__ */ React6.createElement(
462
+ "textarea",
463
+ {
464
+ ref: inputRef,
465
+ value: input,
466
+ onChange: (e) => setInput(e.target.value),
467
+ onKeyDown: handleKeyDown,
468
+ placeholder: ui.placeholder,
469
+ rows: 1,
470
+ disabled: isLoading,
471
+ 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",
472
+ style: { scrollbarWidth: "none" }
473
+ }
474
+ ), /* @__PURE__ */ React6.createElement(
475
+ "button",
476
+ {
477
+ onClick: sendMessage,
478
+ disabled: !input.trim() || isLoading,
479
+ 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",
480
+ style: {
481
+ background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
482
+ // slate-400/20 for light mode disabled
483
+ }
484
+ },
485
+ /* @__PURE__ */ React6.createElement(ArrowUp, { className: "w-4 h-4 text-white" })
486
+ )), /* @__PURE__ */ React6.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"))
506
487
  );
507
488
  }
508
489
 
509
490
  // src/components/ChatWidget.tsx
510
- import { Fragment as Fragment2, jsx as jsx6, jsxs as jsxs4 } from "react/jsx-runtime";
511
491
  function ChatWidget({ position = "bottom-right" }) {
512
492
  const { ui } = useConfig();
513
493
  const [isOpen, setIsOpen] = useState4(false);
@@ -520,63 +500,55 @@ function ChatWidget({ position = "bottom-right" }) {
520
500
  setIsOpen(true);
521
501
  setHasUnread(false);
522
502
  };
523
- return /* @__PURE__ */ jsxs4(Fragment2, { children: [
524
- /* @__PURE__ */ jsxs4(
525
- "div",
503
+ return /* @__PURE__ */ React7.createElement(React7.Fragment, null, /* @__PURE__ */ React7.createElement(
504
+ "div",
505
+ {
506
+ className: `fixed z-[9998] w-[380px] max-w-[calc(100vw-3rem)] transition-all duration-300 ease-in-out ${windowPositionClass} ${isOpen ? "opacity-100 translate-y-0 pointer-events-auto" : "opacity-0 translate-y-4 pointer-events-none"}`,
507
+ style: { height: "600px", maxHeight: "calc(100vh - 6rem)" }
508
+ },
509
+ /* @__PURE__ */ React7.createElement(
510
+ ChatWindow,
526
511
  {
527
- className: `fixed z-[9998] w-[380px] max-w-[calc(100vw-3rem)] transition-all duration-300 ease-in-out ${windowPositionClass} ${isOpen ? "opacity-100 translate-y-0 pointer-events-auto" : "opacity-0 translate-y-4 pointer-events-none"}`,
528
- style: { height: "600px", maxHeight: "calc(100vh - 6rem)" },
529
- children: [
530
- /* @__PURE__ */ jsx6(
531
- ChatWindow,
532
- {
533
- className: "h-full relative z-10",
534
- showClose: true,
535
- onClose: () => setIsOpen(false)
536
- }
537
- ),
538
- /* @__PURE__ */ jsx6(
539
- "div",
540
- {
541
- 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"}`
542
- }
543
- )
544
- ]
512
+ className: "h-full relative z-10",
513
+ showClose: true,
514
+ onClose: () => setIsOpen(false)
545
515
  }
546
516
  ),
547
- /* @__PURE__ */ jsxs4(
548
- "button",
517
+ /* @__PURE__ */ React7.createElement(
518
+ "div",
549
519
  {
550
- onClick: isOpen ? () => setIsOpen(false) : handleOpen,
551
- 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}`,
552
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
553
- "aria-label": "Open chat",
554
- children: [
555
- /* @__PURE__ */ jsx6(
556
- "span",
557
- {
558
- className: "absolute inset-0 rounded-full animate-ping opacity-20",
559
- style: { background: ui.primaryColor }
560
- }
561
- ),
562
- /* @__PURE__ */ jsx6(
563
- "span",
564
- {
565
- className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`,
566
- children: isOpen ? /* @__PURE__ */ jsx6(X2, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ jsx6(MessageSquare2, { className: "w-6 h-6 text-white" })
567
- }
568
- ),
569
- hasUnread && !isOpen && /* @__PURE__ */ jsx6("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" })
570
- ]
520
+ 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"}`
571
521
  }
572
522
  )
573
- ] });
523
+ ), /* @__PURE__ */ React7.createElement(
524
+ "button",
525
+ {
526
+ onClick: isOpen ? () => setIsOpen(false) : handleOpen,
527
+ 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}`,
528
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
529
+ "aria-label": "Open chat"
530
+ },
531
+ /* @__PURE__ */ React7.createElement(
532
+ "span",
533
+ {
534
+ className: "absolute inset-0 rounded-full animate-ping opacity-20",
535
+ style: { background: ui.primaryColor }
536
+ }
537
+ ),
538
+ /* @__PURE__ */ React7.createElement(
539
+ "span",
540
+ {
541
+ className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
542
+ },
543
+ isOpen ? /* @__PURE__ */ React7.createElement(X2, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ React7.createElement(MessageSquare2, { className: "w-6 h-6 text-white" })
544
+ ),
545
+ hasUnread && !isOpen && /* @__PURE__ */ React7.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")
546
+ ));
574
547
  }
575
548
 
576
549
  // src/components/DocumentUpload.tsx
577
- import { useState as useState5, useRef as useRef3 } from "react";
550
+ import React8, { useState as useState5, useRef as useRef3 } from "react";
578
551
  import { Upload, File, X as X3, CheckCircle, AlertCircle, Loader2 } from "lucide-react";
579
- import { jsx as jsx7, jsxs as jsxs5 } from "react/jsx-runtime";
580
552
  function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
581
553
  const { ui } = useConfig();
582
554
  const [fileStates, setFileStates] = useState5([]);
@@ -631,99 +603,72 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
631
603
  };
632
604
  const isUploading = fileStates.some((s) => s.status === "uploading");
633
605
  const hasIdle = fileStates.some((s) => s.status === "idle");
634
- return /* @__PURE__ */ jsxs5(
606
+ return /* @__PURE__ */ React8.createElement(
635
607
  "div",
636
608
  {
637
609
  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}`,
638
610
  onDragOver,
639
611
  onDragLeave,
640
- onDrop,
641
- children: [
642
- /* @__PURE__ */ jsxs5("div", { className: "flex flex-col items-center justify-center text-center", children: [
643
- /* @__PURE__ */ jsx7(
644
- "div",
645
- {
646
- className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
647
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` },
648
- children: /* @__PURE__ */ jsx7(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
649
- }
650
- ),
651
- /* @__PURE__ */ jsx7("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1", children: "Upload Documents" }),
652
- /* @__PURE__ */ jsx7("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." }),
653
- /* @__PURE__ */ jsx7(
654
- "button",
655
- {
656
- onClick: () => {
657
- var _a;
658
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
659
- },
660
- disabled: isUploading,
661
- className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
662
- style: {
663
- backgroundColor: `${ui.primaryColor}15`,
664
- color: ui.primaryColor,
665
- border: `1px solid ${ui.primaryColor}30`
666
- },
667
- children: "Select Files"
668
- }
669
- ),
670
- /* @__PURE__ */ jsx7(
671
- "input",
672
- {
673
- ref: fileInputRef,
674
- type: "file",
675
- multiple: true,
676
- onChange: onFileSelect,
677
- className: "hidden",
678
- accept: ".pdf,.docx,.txt,.md,.json,.csv"
679
- }
680
- )
681
- ] }),
682
- fileStates.length > 0 && /* @__PURE__ */ jsxs5("div", { className: "mt-8 space-y-3", children: [
683
- fileStates.map((state, i) => /* @__PURE__ */ jsxs5(
684
- "div",
685
- {
686
- 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",
687
- children: [
688
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-3 overflow-hidden", children: [
689
- /* @__PURE__ */ jsx7("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm", children: /* @__PURE__ */ jsx7(File, { className: "w-4 h-4 text-slate-400" }) }),
690
- /* @__PURE__ */ jsxs5("div", { className: "truncate", children: [
691
- /* @__PURE__ */ jsx7("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate", children: state.file.name }),
692
- /* @__PURE__ */ jsxs5("p", { className: "text-[10px] text-slate-400", children: [
693
- (state.file.size / 1024).toFixed(1),
694
- " KB"
695
- ] })
696
- ] })
697
- ] }),
698
- /* @__PURE__ */ jsxs5("div", { className: "flex items-center gap-2", children: [
699
- state.status === "uploading" && /* @__PURE__ */ jsx7(Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }),
700
- state.status === "success" && /* @__PURE__ */ jsx7(CheckCircle, { className: "w-4 h-4 text-emerald-500" }),
701
- state.status === "error" && /* @__PURE__ */ jsx7("div", { title: state.error, children: /* @__PURE__ */ jsx7(AlertCircle, { className: "w-4 h-4 text-rose-500" }) }),
702
- state.status !== "uploading" && /* @__PURE__ */ jsx7(
703
- "button",
704
- {
705
- onClick: () => removeFile(i),
706
- className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors",
707
- children: /* @__PURE__ */ jsx7(X3, { className: "w-3.5 h-3.5 text-slate-400" })
708
- }
709
- )
710
- ] })
711
- ]
712
- },
713
- i
714
- )),
715
- hasIdle && !isUploading && /* @__PURE__ */ jsx7(
716
- "button",
717
- {
718
- onClick: uploadFiles,
719
- 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]",
720
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
721
- children: "Start Upload"
722
- }
723
- )
724
- ] })
725
- ]
726
- }
612
+ onDrop
613
+ },
614
+ /* @__PURE__ */ React8.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ React8.createElement(
615
+ "div",
616
+ {
617
+ className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
618
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
619
+ },
620
+ /* @__PURE__ */ React8.createElement(Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
621
+ ), /* @__PURE__ */ React8.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ React8.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__ */ React8.createElement(
622
+ "button",
623
+ {
624
+ onClick: () => {
625
+ var _a;
626
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
627
+ },
628
+ disabled: isUploading,
629
+ className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
630
+ style: {
631
+ backgroundColor: `${ui.primaryColor}15`,
632
+ color: ui.primaryColor,
633
+ border: `1px solid ${ui.primaryColor}30`
634
+ }
635
+ },
636
+ "Select Files"
637
+ ), /* @__PURE__ */ React8.createElement(
638
+ "input",
639
+ {
640
+ ref: fileInputRef,
641
+ type: "file",
642
+ multiple: true,
643
+ onChange: onFileSelect,
644
+ className: "hidden",
645
+ accept: ".pdf,.docx,.txt,.md,.json,.csv"
646
+ }
647
+ )),
648
+ fileStates.length > 0 && /* @__PURE__ */ React8.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ React8.createElement(
649
+ "div",
650
+ {
651
+ key: i,
652
+ 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"
653
+ },
654
+ /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ React8.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ React8.createElement(File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ React8.createElement("div", { className: "truncate" }, /* @__PURE__ */ React8.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ React8.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
655
+ /* @__PURE__ */ React8.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ React8.createElement(Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ React8.createElement(CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ React8.createElement("div", { title: state.error }, /* @__PURE__ */ React8.createElement(AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ React8.createElement(
656
+ "button",
657
+ {
658
+ onClick: () => removeFile(i),
659
+ className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
660
+ },
661
+ /* @__PURE__ */ React8.createElement(X3, { className: "w-3.5 h-3.5 text-slate-400" })
662
+ ))
663
+ )), hasIdle && !isUploading && /* @__PURE__ */ React8.createElement(
664
+ "button",
665
+ {
666
+ onClick: uploadFiles,
667
+ 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]",
668
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
669
+ },
670
+ "Start Upload"
671
+ ))
727
672
  );
728
673
  }
729
674
  export {