@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.js CHANGED
@@ -59,11 +59,11 @@ __export(index_exports, {
59
59
  module.exports = __toCommonJS(index_exports);
60
60
 
61
61
  // src/components/ChatWidget.tsx
62
- var import_react6 = require("react");
62
+ var import_react7 = __toESM(require("react"));
63
63
  var import_lucide_react5 = require("lucide-react");
64
64
 
65
65
  // src/components/ChatWindow.tsx
66
- var import_react5 = require("react");
66
+ var import_react6 = __toESM(require("react"));
67
67
  var import_lucide_react4 = require("lucide-react");
68
68
 
69
69
  // src/components/MessageBubble.tsx
@@ -75,7 +75,6 @@ var import_remark_gfm = __toESM(require("remark-gfm"));
75
75
  // src/components/SourceCard.tsx
76
76
  var import_react = __toESM(require("react"));
77
77
  var import_lucide_react = require("lucide-react");
78
- var import_jsx_runtime = require("react/jsx-runtime");
79
78
  function SourceCard({ source, index }) {
80
79
  var _a, _b;
81
80
  const [expanded, setExpanded] = import_react.default.useState(false);
@@ -84,37 +83,19 @@ function SourceCard({ source, index }) {
84
83
  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";
85
84
  const preview = source.content.slice(0, 120);
86
85
  const hasMore = source.content.length > 120;
87
- return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(
86
+ return /* @__PURE__ */ import_react.default.createElement(
88
87
  "div",
89
88
  {
90
89
  className: `rounded-xl border backdrop-blur-sm p-3 transition-all duration-200 hover:scale-[1.01] cursor-pointer ${scoreBg}`,
91
- onClick: () => setExpanded((e) => !e),
92
- children: [
93
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-start justify-between gap-2", children: [
94
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { className: "flex items-center gap-2 min-w-0", children: [
95
- /* @__PURE__ */ (0, import_jsx_runtime.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 }),
96
- /* @__PURE__ */ (0, import_jsx_runtime.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 })
97
- ] }),
98
- /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums`, children: [
99
- scorePercent,
100
- "%"
101
- ] })
102
- ] }),
103
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed", children: expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}` }),
104
- hasMore && /* @__PURE__ */ (0, import_jsx_runtime.jsx)("button", { className: "mt-1 text-[10px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-0.5", children: expanded ? /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
105
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronUp, { className: "w-3 h-3" }),
106
- " Show less"
107
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime.jsxs)(import_jsx_runtime.Fragment, { children: [
108
- /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_lucide_react.ChevronDown, { className: "w-3 h-3" }),
109
- " Show more"
110
- ] }) })
111
- ]
112
- }
90
+ onClick: () => setExpanded((e) => !e)
91
+ },
92
+ /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-start justify-between gap-2" }, /* @__PURE__ */ import_react.default.createElement("div", { className: "flex items-center gap-2 min-w-0" }, /* @__PURE__ */ import_react.default.createElement("span", { className: "flex-shrink-0 w-5 h-5 rounded-full bg-slate-200 dark:bg-white/10 flex items-center justify-center text-[10px] font-bold text-slate-500 dark:text-white/60" }, index + 1), /* @__PURE__ */ import_react.default.createElement("span", { className: "text-xs text-slate-500 dark:text-white/50 truncate font-mono" }, (_b = (_a = source.metadata) == null ? void 0 : _a.docId) != null ? _b : source.id)), /* @__PURE__ */ import_react.default.createElement("span", { className: `flex-shrink-0 text-xs font-semibold ${scoreColor} tabular-nums` }, scorePercent, "%")),
93
+ /* @__PURE__ */ import_react.default.createElement("p", { className: "mt-2 text-xs text-slate-600 dark:text-white/70 leading-relaxed" }, expanded ? source.content : `${preview}${hasMore && !expanded ? "\u2026" : ""}`),
94
+ hasMore && /* @__PURE__ */ import_react.default.createElement("button", { className: "mt-1 text-[10px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-0.5" }, expanded ? /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronUp, { className: "w-3 h-3" }), " Show less") : /* @__PURE__ */ import_react.default.createElement(import_react.default.Fragment, null, /* @__PURE__ */ import_react.default.createElement(import_lucide_react.ChevronDown, { className: "w-3 h-3" }), " Show more"))
113
95
  );
114
96
  }
115
97
 
116
98
  // src/components/MessageBubble.tsx
117
- var import_jsx_runtime2 = require("react/jsx-runtime");
118
99
  function MessageBubble({
119
100
  message,
120
101
  sources,
@@ -124,51 +105,36 @@ function MessageBubble({
124
105
  }) {
125
106
  const isUser = message.role === "user";
126
107
  const [showSources, setShowSources] = import_react2.default.useState(false);
127
- return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start`, children: [
128
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
129
- "div",
130
- {
131
- 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"}`,
132
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
133
- children: isUser ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.Bot, { className: "w-4 h-4" })
134
- }
135
- ),
136
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: `flex flex-col gap-1 max-w-[75%] ${isUser ? "items-end" : "items-start"}`, children: [
137
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
138
- "div",
139
- {
140
- 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"}`,
141
- style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {},
142
- children: isStreaming ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { className: "flex items-center gap-1", children: [
143
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }),
144
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }),
145
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })
146
- ] }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}`, children: /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default], children: message.content }) })
147
- }
148
- ),
149
- !isUser && sources && sources.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { className: "w-full", children: [
150
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)(
151
- "button",
152
- {
153
- onClick: () => setShowSources((s) => !s),
154
- className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1",
155
- children: [
156
- showSources ? /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(import_lucide_react2.ChevronRight, { className: "w-3 h-3" }),
157
- sources.length,
158
- " source",
159
- sources.length !== 1 ? "s" : "",
160
- " used"
161
- ]
162
- }
163
- ),
164
- showSources && /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { className: "mt-2 flex flex-col gap-2", children: sources.map((src, i) => /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(SourceCard, { source: src, index: i }, src.id)) })
165
- ] })
166
- ] })
167
- ] });
108
+ return /* @__PURE__ */ import_react2.default.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ import_react2.default.createElement(
109
+ "div",
110
+ {
111
+ 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"}`,
112
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
113
+ },
114
+ isUser ? /* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.Bot, { className: "w-4 h-4" })
115
+ ), /* @__PURE__ */ import_react2.default.createElement("div", { className: `flex flex-col gap-1 max-w-[75%] ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ import_react2.default.createElement(
116
+ "div",
117
+ {
118
+ 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"}`,
119
+ style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
120
+ },
121
+ isStreaming && !message.content ? /* @__PURE__ */ import_react2.default.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ import_react2.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ import_react2.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ import_react2.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ import_react2.default.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ import_react2.default.createElement(import_react_markdown.default, { remarkPlugins: [import_remark_gfm.default] }, message.content), isStreaming && message.content && /* @__PURE__ */ import_react2.default.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
122
+ ), !isUser && sources && sources.length > 0 && /* @__PURE__ */ import_react2.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react2.default.createElement(
123
+ "button",
124
+ {
125
+ onClick: () => setShowSources((s) => !s),
126
+ className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
127
+ },
128
+ showSources ? /* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react2.default.createElement(import_lucide_react2.ChevronRight, { className: "w-3 h-3" }),
129
+ sources.length,
130
+ " source",
131
+ sources.length !== 1 ? "s" : "",
132
+ " used"
133
+ ), showSources && /* @__PURE__ */ import_react2.default.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ import_react2.default.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
168
134
  }
169
135
 
170
136
  // src/components/ConfigProvider.tsx
171
- var import_react3 = require("react");
137
+ var import_react3 = __toESM(require("react"));
172
138
 
173
139
  // src/utils/templateUtils.ts
174
140
  function mergeDefined(base, override) {
@@ -185,7 +151,6 @@ function mergeDefined(base, override) {
185
151
  }
186
152
 
187
153
  // src/components/ConfigProvider.tsx
188
- var import_jsx_runtime3 = require("react/jsx-runtime");
189
154
  var defaultConfig = {
190
155
  projectId: "default",
191
156
  ui: {
@@ -213,7 +178,7 @@ function ConfigProvider({
213
178
  projectId: (config == null ? void 0 : config.projectId) || defaultConfig.projectId,
214
179
  ui: mergeDefined(defaultConfig.ui, config == null ? void 0 : config.ui)
215
180
  };
216
- return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(ConfigContext.Provider, { value: merged, children });
181
+ return /* @__PURE__ */ import_react3.default.createElement(ConfigContext.Provider, { value: merged }, children);
217
182
  }
218
183
  function useConfig() {
219
184
  return (0, import_react3.useContext)(ConfigContext);
@@ -221,7 +186,6 @@ function useConfig() {
221
186
 
222
187
  // src/hooks/useRagChat.ts
223
188
  var import_react4 = require("react");
224
- var import_axios = __toESM(require("axios"));
225
189
 
226
190
  // src/hooks/useStoredMessages.ts
227
191
  var React4 = __toESM(require("react"));
@@ -275,7 +239,6 @@ function useRagChat(projectId, options = {}) {
275
239
  }, [messages]);
276
240
  const sendMessage = (0, import_react4.useCallback)(
277
241
  async (text, options2) => {
278
- var _a, _b, _c;
279
242
  const trimmed = text.trim();
280
243
  if (!trimmed || isLoading) return;
281
244
  lastInputRef.current = trimmed;
@@ -292,22 +255,77 @@ function useRagChat(projectId, options = {}) {
292
255
  setIsLoading(true);
293
256
  try {
294
257
  const history = messagesRef.current.map(({ role, content }) => ({ role, content }));
295
- const { data } = await import_axios.default.post(apiUrl, {
296
- message: trimmed,
297
- history,
298
- namespace: namespace != null ? namespace : projectId
258
+ const response = await fetch(apiUrl, {
259
+ method: "POST",
260
+ headers: { "Content-Type": "application/json" },
261
+ body: JSON.stringify({
262
+ message: trimmed,
263
+ history,
264
+ namespace: namespace != null ? namespace : projectId
265
+ })
299
266
  });
300
- const assistantMessage = {
301
- id: `assistant_${Date.now()}`,
267
+ if (!response.ok) {
268
+ const errorData = await response.json().catch(() => ({}));
269
+ throw new Error(errorData.error || `Server returned ${response.status}`);
270
+ }
271
+ if (!response.body) {
272
+ throw new Error("No response body received from server");
273
+ }
274
+ const reader = response.body.getReader();
275
+ const decoder = new TextDecoder();
276
+ let assistantContent = "";
277
+ let sources = [];
278
+ const assistantMessageId = `assistant_${Date.now()}`;
279
+ setMessages((prev) => [
280
+ ...prev,
281
+ {
282
+ id: assistantMessageId,
283
+ role: "assistant",
284
+ content: "",
285
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
286
+ }
287
+ ]);
288
+ while (true) {
289
+ const { done, value } = await reader.read();
290
+ if (done) break;
291
+ const chunk = decoder.decode(value, { stream: true });
292
+ if (chunk.includes("__METADATA__")) {
293
+ const [text2, metadataStr] = chunk.split("__METADATA__");
294
+ if (text2) assistantContent += text2;
295
+ try {
296
+ const meta = JSON.parse(metadataStr);
297
+ sources = meta.sources || [];
298
+ } catch (e) {
299
+ console.warn("[useRagChat] Failed to parse metadata");
300
+ }
301
+ } else if (chunk.includes("__ERROR__")) {
302
+ const [text2, errorStr] = chunk.split("__ERROR__");
303
+ if (text2) assistantContent += text2;
304
+ try {
305
+ const err = JSON.parse(errorStr);
306
+ setError(err.error || "Stream error");
307
+ } catch (e) {
308
+ setError("An error occurred during streaming");
309
+ }
310
+ } else {
311
+ assistantContent += chunk;
312
+ }
313
+ setMessages(
314
+ (prev) => prev.map(
315
+ (msg) => msg.id === assistantMessageId ? __spreadProps(__spreadValues({}, msg), { content: assistantContent, sources: sources.length > 0 ? sources : msg.sources }) : msg
316
+ )
317
+ );
318
+ }
319
+ const finalAssistantMessage = {
320
+ id: assistantMessageId,
302
321
  role: "assistant",
303
- content: data.reply,
304
- sources: data.sources,
322
+ content: assistantContent,
323
+ sources: sources.length > 0 ? sources : void 0,
305
324
  createdAt: (/* @__PURE__ */ new Date()).toISOString()
306
325
  };
307
- setMessages((prev) => [...prev, assistantMessage]);
308
- onReply == null ? void 0 : onReply(assistantMessage);
326
+ onReply == null ? void 0 : onReply(finalAssistantMessage);
309
327
  } catch (err) {
310
- const msg = import_axios.default.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.";
328
+ const msg = err instanceof Error ? err.message : "Something went wrong. Please try again.";
311
329
  setError(msg);
312
330
  onError == null ? void 0 : onError(msg);
313
331
  } finally {
@@ -341,8 +359,8 @@ function useRagChat(projectId, options = {}) {
341
359
  }
342
360
 
343
361
  // src/app/constants.tsx
362
+ var import_react5 = __toESM(require("react"));
344
363
  var import_lucide_react3 = require("lucide-react");
345
- var import_jsx_runtime4 = require("react/jsx-runtime");
346
364
  var CHAT_SUGGESTIONS = [
347
365
  "What can you help me with?",
348
366
  "Summarise the key topics",
@@ -358,36 +376,33 @@ var BORDER_RADIUS_MAP = {
358
376
  };
359
377
 
360
378
  // src/components/ChatWindow.tsx
361
- var import_jsx_runtime5 = (
362
- // eslint-disable-next-line @next/next/no-img-element
363
- require("react/jsx-runtime")
364
- );
365
379
  function ChatWindow({ className = "", style, onClose, showClose = false }) {
380
+ var _a;
366
381
  const { ui, projectId } = useConfig();
367
- const [input, setInput] = (0, import_react5.useState)("");
368
- const [mounted, setMounted] = (0, import_react5.useState)(false);
369
- const bottomRef = (0, import_react5.useRef)(null);
370
- const inputRef = (0, import_react5.useRef)(null);
382
+ const [input, setInput] = (0, import_react6.useState)("");
383
+ const [mounted, setMounted] = (0, import_react6.useState)(false);
384
+ const bottomRef = (0, import_react6.useRef)(null);
385
+ const inputRef = (0, import_react6.useRef)(null);
371
386
  const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
372
387
  namespace: projectId
373
388
  });
374
- (0, import_react5.useEffect)(() => {
389
+ (0, import_react6.useEffect)(() => {
375
390
  setMounted(true);
376
391
  }, []);
377
- (0, import_react5.useEffect)(() => {
378
- var _a;
392
+ (0, import_react6.useEffect)(() => {
393
+ var _a2;
379
394
  if (messages.length > 0 || isLoading) {
380
- (_a = bottomRef.current) == null ? void 0 : _a.scrollIntoView({ behavior: "smooth" });
395
+ (_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
381
396
  }
382
397
  }, [messages, isLoading]);
383
- const sendMessage = (0, import_react5.useCallback)(async () => {
398
+ const sendMessage = (0, import_react6.useCallback)(async () => {
384
399
  const text = input.trim();
385
400
  if (!text || isLoading) return;
386
401
  setInput("");
387
402
  await send(text);
388
403
  window.setTimeout(() => {
389
- var _a;
390
- return (_a = inputRef.current) == null ? void 0 : _a.focus();
404
+ var _a2;
405
+ return (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
391
406
  }, 50);
392
407
  }, [input, isLoading, send]);
393
408
  const handleKeyDown = (e) => {
@@ -402,159 +417,124 @@ function ChatWindow({ className = "", style, onClose, showClose = false }) {
402
417
  const isEmpty = messages.length === 0;
403
418
  const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
404
419
  const isGlass = ui.visualStyle !== "solid";
405
- return /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
420
+ return /* @__PURE__ */ import_react6.default.createElement(
406
421
  "div",
407
422
  {
408
423
  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}`,
409
- style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style),
410
- children: [
411
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)(
412
- "div",
424
+ style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
425
+ },
426
+ /* @__PURE__ */ import_react6.default.createElement(
427
+ "div",
428
+ {
429
+ className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
430
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
431
+ },
432
+ /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
433
+ // eslint-disable-next-line @next/next/no-img-element
434
+ /* @__PURE__ */ import_react6.default.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
435
+ ) : /* @__PURE__ */ import_react6.default.createElement(
436
+ "div",
437
+ {
438
+ className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
439
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
440
+ },
441
+ /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.Bot, { className: "w-5 h-5 text-white" })
442
+ ), /* @__PURE__ */ import_react6.default.createElement("div", null, /* @__PURE__ */ import_react6.default.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
443
+ /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react6.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400" }, /* @__PURE__ */ import_react6.default.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__ */ import_react6.default.createElement(
444
+ "button",
445
+ {
446
+ onClick: clearHistory,
447
+ title: "Clear conversation",
448
+ 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"
449
+ },
450
+ /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.Trash2, { className: "w-3.5 h-3.5" })
451
+ ), showClose && onClose && /* @__PURE__ */ import_react6.default.createElement(
452
+ "button",
453
+ {
454
+ onClick: onClose,
455
+ title: "Close chat",
456
+ 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"
457
+ },
458
+ /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.X, { className: "w-4 h-4" })
459
+ ))
460
+ ),
461
+ /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent" }, !mounted || isEmpty ? (
462
+ /* Welcome state */
463
+ /* @__PURE__ */ import_react6.default.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ import_react6.default.createElement(
464
+ "div",
465
+ {
466
+ className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
467
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
468
+ },
469
+ /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.Sparkles, { className: "w-8 h-8 text-white" })
470
+ ), /* @__PURE__ */ import_react6.default.createElement("div", null, /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
471
+ (suggestion) => /* @__PURE__ */ import_react6.default.createElement(
472
+ "button",
413
473
  {
414
- className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
415
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` },
416
- children: [
417
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-3", children: [
418
- ui.logoUrl ? /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" }) : /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
419
- "div",
420
- {
421
- className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
422
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
423
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Bot, { className: "w-5 h-5 text-white" })
424
- }
425
- ),
426
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
427
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight", children: ui.title }),
428
- ui.poweredBy && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight", children: `Powered by ${ui.poweredBy}` })
429
- ] })
430
- ] }),
431
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2", children: [
432
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400", children: [
433
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }),
434
- "Online"
435
- ] }),
436
- mounted && messages.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
437
- "button",
438
- {
439
- onClick: clearHistory,
440
- title: "Clear conversation",
441
- 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",
442
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Trash2, { className: "w-3.5 h-3.5" })
443
- }
444
- ),
445
- showClose && onClose && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
446
- "button",
447
- {
448
- onClick: onClose,
449
- title: "Close chat",
450
- 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",
451
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.X, { className: "w-4 h-4" })
452
- }
453
- )
454
- ] })
455
- ]
456
- }
457
- ),
458
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent", children: [
459
- !mounted || isEmpty ? (
460
- /* Welcome state */
461
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12", children: [
462
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
463
- "div",
464
- {
465
- className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
466
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
467
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.Sparkles, { className: "w-8 h-8 text-white" })
468
- }
469
- ),
470
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { children: [
471
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed", children: ui.welcomeMessage }),
472
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2", children: "Ask a question to get started" })
473
- ] }),
474
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { className: "flex flex-wrap gap-2 justify-center mt-2", children: CHAT_SUGGESTIONS.map(
475
- (suggestion) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
476
- "button",
477
- {
478
- onClick: () => {
479
- var _a;
480
- setInput(suggestion);
481
- (_a = inputRef.current) == null ? void 0 : _a.focus();
482
- },
483
- 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",
484
- children: suggestion
485
- },
486
- suggestion
487
- )
488
- ) })
489
- ] })
490
- ) : messages.map((msg) => /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
491
- MessageBubble,
492
- {
493
- message: msg,
494
- sources: msg.sources,
495
- primaryColor: ui.primaryColor,
496
- accentColor: ui.accentColor
474
+ key: suggestion,
475
+ onClick: () => {
476
+ var _a2;
477
+ setInput(suggestion);
478
+ (_a2 = inputRef.current) == null ? void 0 : _a2.focus();
497
479
  },
498
- msg.id
499
- )),
500
- isLoading && /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
501
- MessageBubble,
502
- {
503
- message: { role: "assistant", content: "" },
504
- isStreaming: true,
505
- primaryColor: ui.primaryColor,
506
- accentColor: ui.accentColor
507
- }
508
- ),
509
- error && /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: "flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3", children: [
510
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }),
511
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("span", { children: error })
512
- ] }),
513
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("div", { ref: bottomRef })
514
- ] }),
515
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `px-4 pb-4 pt-2 border-t border-slate-200 dark:border-white/10 ${isGlass ? "bg-transparent" : "bg-white dark:bg-[#0f0f1a]"}`, children: [
516
- /* @__PURE__ */ (0, import_jsx_runtime5.jsxs)("div", { className: `flex items-end gap-2 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 p-2 focus-within:border-slate-300 dark:focus-within:border-white/20 transition-all ${ui.borderRadius === "full" ? "rounded-3xl" : "rounded-2xl"}`, children: [
517
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
518
- "textarea",
519
- {
520
- ref: inputRef,
521
- value: input,
522
- onChange: (e) => setInput(e.target.value),
523
- onKeyDown: handleKeyDown,
524
- placeholder: ui.placeholder,
525
- rows: 1,
526
- disabled: isLoading,
527
- 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",
528
- style: { scrollbarWidth: "none" }
529
- }
530
- ),
531
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(
532
- "button",
533
- {
534
- onClick: sendMessage,
535
- disabled: !input.trim() || isLoading,
536
- 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",
537
- style: {
538
- background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
539
- // slate-400/20 for light mode disabled
540
- },
541
- children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(import_lucide_react4.ArrowUp, { className: "w-4 h-4 text-white" })
542
- }
543
- )
544
- ] }),
545
- /* @__PURE__ */ (0, import_jsx_runtime5.jsx)("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2", children: "Press Enter to send \xB7 Shift+Enter for new line" })
546
- ] })
547
- ]
548
- }
480
+ 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"
481
+ },
482
+ suggestion
483
+ )
484
+ )))
485
+ ) : messages.map((msg, index) => /* @__PURE__ */ import_react6.default.createElement(
486
+ MessageBubble,
487
+ {
488
+ key: msg.id,
489
+ message: msg,
490
+ sources: msg.sources,
491
+ isStreaming: isLoading && index === messages.length - 1 && msg.role === "assistant",
492
+ primaryColor: ui.primaryColor,
493
+ accentColor: ui.accentColor
494
+ }
495
+ )), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ import_react6.default.createElement(
496
+ MessageBubble,
497
+ {
498
+ message: { role: "assistant", content: "" },
499
+ isStreaming: true,
500
+ primaryColor: ui.primaryColor,
501
+ accentColor: ui.accentColor
502
+ }
503
+ ), error && /* @__PURE__ */ import_react6.default.createElement("div", { className: "flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3" }, /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ import_react6.default.createElement("span", null, error)), /* @__PURE__ */ import_react6.default.createElement("div", { ref: bottomRef })),
504
+ /* @__PURE__ */ import_react6.default.createElement("div", { className: `px-4 pb-4 pt-2 border-t border-slate-200 dark:border-white/10 ${isGlass ? "bg-transparent" : "bg-white dark:bg-[#0f0f1a]"}` }, /* @__PURE__ */ import_react6.default.createElement("div", { className: `flex items-end gap-2 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 p-2 focus-within:border-slate-300 dark:focus-within:border-white/20 transition-all ${ui.borderRadius === "full" ? "rounded-3xl" : "rounded-2xl"}` }, /* @__PURE__ */ import_react6.default.createElement(
505
+ "textarea",
506
+ {
507
+ ref: inputRef,
508
+ value: input,
509
+ onChange: (e) => setInput(e.target.value),
510
+ onKeyDown: handleKeyDown,
511
+ placeholder: ui.placeholder,
512
+ rows: 1,
513
+ disabled: isLoading,
514
+ 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",
515
+ style: { scrollbarWidth: "none" }
516
+ }
517
+ ), /* @__PURE__ */ import_react6.default.createElement(
518
+ "button",
519
+ {
520
+ onClick: sendMessage,
521
+ disabled: !input.trim() || isLoading,
522
+ 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",
523
+ style: {
524
+ background: input.trim() && !isLoading ? `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` : "rgba(148, 163, 184, 0.2)"
525
+ // slate-400/20 for light mode disabled
526
+ }
527
+ },
528
+ /* @__PURE__ */ import_react6.default.createElement(import_lucide_react4.ArrowUp, { className: "w-4 h-4 text-white" })
529
+ )), /* @__PURE__ */ import_react6.default.createElement("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2" }, "Press Enter to send \xB7 Shift+Enter for new line"))
549
530
  );
550
531
  }
551
532
 
552
533
  // src/components/ChatWidget.tsx
553
- var import_jsx_runtime6 = require("react/jsx-runtime");
554
534
  function ChatWidget({ position = "bottom-right" }) {
555
535
  const { ui } = useConfig();
556
- const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
557
- const [hasUnread, setHasUnread] = (0, import_react6.useState)(false);
536
+ const [isOpen, setIsOpen] = (0, import_react7.useState)(false);
537
+ const [hasUnread, setHasUnread] = (0, import_react7.useState)(false);
558
538
  if (ui.showWidget === false) return null;
559
539
  const positionClass = position === "bottom-left" ? "bottom-6 left-6" : "bottom-6 right-6";
560
540
  const windowPositionClass = position === "bottom-left" ? "bottom-20 left-6" : "bottom-20 right-6";
@@ -563,68 +543,60 @@ function ChatWidget({ position = "bottom-right" }) {
563
543
  setIsOpen(true);
564
544
  setHasUnread(false);
565
545
  };
566
- return /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(import_jsx_runtime6.Fragment, { children: [
567
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
568
- "div",
546
+ return /* @__PURE__ */ import_react7.default.createElement(import_react7.default.Fragment, null, /* @__PURE__ */ import_react7.default.createElement(
547
+ "div",
548
+ {
549
+ 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"}`,
550
+ style: { height: "600px", maxHeight: "calc(100vh - 6rem)" }
551
+ },
552
+ /* @__PURE__ */ import_react7.default.createElement(
553
+ ChatWindow,
569
554
  {
570
- 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"}`,
571
- style: { height: "600px", maxHeight: "calc(100vh - 6rem)" },
572
- children: [
573
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
574
- ChatWindow,
575
- {
576
- className: "h-full relative z-10",
577
- showClose: true,
578
- onClose: () => setIsOpen(false)
579
- }
580
- ),
581
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
582
- "div",
583
- {
584
- 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"}`
585
- }
586
- )
587
- ]
555
+ className: "h-full relative z-10",
556
+ showClose: true,
557
+ onClose: () => setIsOpen(false)
588
558
  }
589
559
  ),
590
- /* @__PURE__ */ (0, import_jsx_runtime6.jsxs)(
591
- "button",
560
+ /* @__PURE__ */ import_react7.default.createElement(
561
+ "div",
592
562
  {
593
- onClick: isOpen ? () => setIsOpen(false) : handleOpen,
594
- 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}`,
595
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
596
- "aria-label": "Open chat",
597
- children: [
598
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
599
- "span",
600
- {
601
- className: "absolute inset-0 rounded-full animate-ping opacity-20",
602
- style: { background: ui.primaryColor }
603
- }
604
- ),
605
- /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(
606
- "span",
607
- {
608
- className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`,
609
- children: isOpen ? /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react5.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ (0, import_jsx_runtime6.jsx)(import_lucide_react5.MessageSquare, { className: "w-6 h-6 text-white" })
610
- }
611
- ),
612
- hasUnread && !isOpen && /* @__PURE__ */ (0, import_jsx_runtime6.jsx)("span", { className: "absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white", children: "1" })
613
- ]
563
+ 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"}`
614
564
  }
615
565
  )
616
- ] });
566
+ ), /* @__PURE__ */ import_react7.default.createElement(
567
+ "button",
568
+ {
569
+ onClick: isOpen ? () => setIsOpen(false) : handleOpen,
570
+ 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}`,
571
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
572
+ "aria-label": "Open chat"
573
+ },
574
+ /* @__PURE__ */ import_react7.default.createElement(
575
+ "span",
576
+ {
577
+ className: "absolute inset-0 rounded-full animate-ping opacity-20",
578
+ style: { background: ui.primaryColor }
579
+ }
580
+ ),
581
+ /* @__PURE__ */ import_react7.default.createElement(
582
+ "span",
583
+ {
584
+ className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
585
+ },
586
+ isOpen ? /* @__PURE__ */ import_react7.default.createElement(import_lucide_react5.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ import_react7.default.createElement(import_lucide_react5.MessageSquare, { className: "w-6 h-6 text-white" })
587
+ ),
588
+ hasUnread && !isOpen && /* @__PURE__ */ import_react7.default.createElement("span", { className: "absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white" }, "1")
589
+ ));
617
590
  }
618
591
 
619
592
  // src/components/DocumentUpload.tsx
620
- var import_react7 = require("react");
593
+ var import_react8 = __toESM(require("react"));
621
594
  var import_lucide_react6 = require("lucide-react");
622
- var import_jsx_runtime7 = require("react/jsx-runtime");
623
595
  function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
624
596
  const { ui } = useConfig();
625
- const [fileStates, setFileStates] = (0, import_react7.useState)([]);
626
- const [isDragging, setIsDragging] = (0, import_react7.useState)(false);
627
- const fileInputRef = (0, import_react7.useRef)(null);
597
+ const [fileStates, setFileStates] = (0, import_react8.useState)([]);
598
+ const [isDragging, setIsDragging] = (0, import_react8.useState)(false);
599
+ const fileInputRef = (0, import_react8.useRef)(null);
628
600
  const addFiles = (files) => {
629
601
  const newStates = files.map((file) => ({ file, status: "idle" }));
630
602
  setFileStates((prev) => [...prev, ...newStates]);
@@ -674,99 +646,72 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
674
646
  };
675
647
  const isUploading = fileStates.some((s) => s.status === "uploading");
676
648
  const hasIdle = fileStates.some((s) => s.status === "idle");
677
- return /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
649
+ return /* @__PURE__ */ import_react8.default.createElement(
678
650
  "div",
679
651
  {
680
652
  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}`,
681
653
  onDragOver,
682
654
  onDragLeave,
683
- onDrop,
684
- children: [
685
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex flex-col items-center justify-center text-center", children: [
686
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
687
- "div",
688
- {
689
- className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
690
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` },
691
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
692
- }
693
- ),
694
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1", children: "Upload Documents" }),
695
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs", children: "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data." }),
696
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
697
- "button",
698
- {
699
- onClick: () => {
700
- var _a;
701
- return (_a = fileInputRef.current) == null ? void 0 : _a.click();
702
- },
703
- disabled: isUploading,
704
- className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
705
- style: {
706
- backgroundColor: `${ui.primaryColor}15`,
707
- color: ui.primaryColor,
708
- border: `1px solid ${ui.primaryColor}30`
709
- },
710
- children: "Select Files"
711
- }
712
- ),
713
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
714
- "input",
715
- {
716
- ref: fileInputRef,
717
- type: "file",
718
- multiple: true,
719
- onChange: onFileSelect,
720
- className: "hidden",
721
- accept: ".pdf,.docx,.txt,.md,.json,.csv"
722
- }
723
- )
724
- ] }),
725
- fileStates.length > 0 && /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "mt-8 space-y-3", children: [
726
- fileStates.map((state, i) => /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)(
727
- "div",
728
- {
729
- 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",
730
- children: [
731
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-3 overflow-hidden", children: [
732
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm", children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.File, { className: "w-4 h-4 text-slate-400" }) }),
733
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "truncate", children: [
734
- /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate", children: state.file.name }),
735
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("p", { className: "text-[10px] text-slate-400", children: [
736
- (state.file.size / 1024).toFixed(1),
737
- " KB"
738
- ] })
739
- ] })
740
- ] }),
741
- /* @__PURE__ */ (0, import_jsx_runtime7.jsxs)("div", { className: "flex items-center gap-2", children: [
742
- state.status === "uploading" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }),
743
- state.status === "success" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.CheckCircle, { className: "w-4 h-4 text-emerald-500" }),
744
- state.status === "error" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)("div", { title: state.error, children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.AlertCircle, { className: "w-4 h-4 text-rose-500" }) }),
745
- state.status !== "uploading" && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
746
- "button",
747
- {
748
- onClick: () => removeFile(i),
749
- className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors",
750
- children: /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(import_lucide_react6.X, { className: "w-3.5 h-3.5 text-slate-400" })
751
- }
752
- )
753
- ] })
754
- ]
755
- },
756
- i
757
- )),
758
- hasIdle && !isUploading && /* @__PURE__ */ (0, import_jsx_runtime7.jsx)(
759
- "button",
760
- {
761
- onClick: uploadFiles,
762
- 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]",
763
- style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
764
- children: "Start Upload"
765
- }
766
- )
767
- ] })
768
- ]
769
- }
655
+ onDrop
656
+ },
657
+ /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ import_react8.default.createElement(
658
+ "div",
659
+ {
660
+ className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
661
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
662
+ },
663
+ /* @__PURE__ */ import_react8.default.createElement(import_lucide_react6.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
664
+ ), /* @__PURE__ */ import_react8.default.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs" }, "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data."), /* @__PURE__ */ import_react8.default.createElement(
665
+ "button",
666
+ {
667
+ onClick: () => {
668
+ var _a;
669
+ return (_a = fileInputRef.current) == null ? void 0 : _a.click();
670
+ },
671
+ disabled: isUploading,
672
+ className: "px-4 py-2 rounded-lg text-sm font-medium transition-all hover:scale-105 active:scale-95 disabled:opacity-50",
673
+ style: {
674
+ backgroundColor: `${ui.primaryColor}15`,
675
+ color: ui.primaryColor,
676
+ border: `1px solid ${ui.primaryColor}30`
677
+ }
678
+ },
679
+ "Select Files"
680
+ ), /* @__PURE__ */ import_react8.default.createElement(
681
+ "input",
682
+ {
683
+ ref: fileInputRef,
684
+ type: "file",
685
+ multiple: true,
686
+ onChange: onFileSelect,
687
+ className: "hidden",
688
+ accept: ".pdf,.docx,.txt,.md,.json,.csv"
689
+ }
690
+ )),
691
+ fileStates.length > 0 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ import_react8.default.createElement(
692
+ "div",
693
+ {
694
+ key: i,
695
+ 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"
696
+ },
697
+ /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ import_react8.default.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react6.File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ import_react8.default.createElement("div", { className: "truncate" }, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
698
+ /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ import_react8.default.createElement(import_lucide_react6.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ import_react8.default.createElement(import_lucide_react6.CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ import_react8.default.createElement("div", { title: state.error }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react6.AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ import_react8.default.createElement(
699
+ "button",
700
+ {
701
+ onClick: () => removeFile(i),
702
+ className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
703
+ },
704
+ /* @__PURE__ */ import_react8.default.createElement(import_lucide_react6.X, { className: "w-3.5 h-3.5 text-slate-400" })
705
+ ))
706
+ )), hasIdle && !isUploading && /* @__PURE__ */ import_react8.default.createElement(
707
+ "button",
708
+ {
709
+ onClick: uploadFiles,
710
+ 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]",
711
+ style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
712
+ },
713
+ "Start Upload"
714
+ ))
770
715
  );
771
716
  }
772
717
  // Annotate the CommonJS export names for ESM import in node: