@retrivora-ai/rag-engine 1.2.1 → 1.2.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/DocumentChunker-BXOUMKoP.d.ts +93 -0
- package/dist/DocumentChunker-D1dg5iCi.d.mts +93 -0
- package/dist/{chunk-GCPPRD2G.mjs → chunk-WGPNEAK3.mjs} +37 -3
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +37 -3
- package/dist/handlers/index.mjs +1 -1
- package/dist/{index-DbtE8wLM.d.ts → index-B67KQ9NN.d.ts} +1 -1
- package/dist/{RagConfig-BOLOz0_O.d.mts → index-Cti1u0y1.d.mts} +86 -94
- package/dist/{RagConfig-BOLOz0_O.d.ts → index-Cti1u0y1.d.ts} +86 -94
- package/dist/{index-64BDupW3.d.mts → index-kUXnRvuI.d.mts} +1 -1
- package/dist/index.d.mts +52 -78
- package/dist/index.d.ts +52 -78
- package/dist/index.js +313 -124
- package/dist/index.mjs +293 -97
- package/dist/server.d.mts +5 -4
- package/dist/server.d.ts +5 -4
- package/dist/server.js +37 -3
- package/dist/server.mjs +1 -1
- package/package.json +2 -1
- package/src/components/ChatWidget.tsx +1 -8
- package/src/components/ChatWindow.tsx +120 -29
- package/src/components/ConfigProvider.tsx +7 -33
- package/src/components/DocumentUpload.tsx +1 -8
- package/src/components/DynamicChart.tsx +113 -0
- package/src/components/MessageBubble.tsx +51 -13
- package/src/components/ProductCard.tsx +1 -7
- package/src/components/ProductCarousel.tsx +1 -7
- package/src/components/SourceCard.tsx +1 -6
- package/src/config/RagConfig.ts +2 -0
- package/src/config/uiConstants.ts +23 -0
- package/src/core/LangChainAgent.ts +20 -2
- package/src/core/Pipeline.ts +19 -1
- package/src/core/VectorPlugin.ts +1 -1
- package/src/handlers/index.ts +1 -1
- package/src/hooks/useRagChat.ts +1 -45
- package/src/hooks/useStoredMessages.ts +1 -1
- package/src/index.ts +20 -5
- package/src/llm/ILLMProvider.ts +1 -13
- package/src/llm/providers/AnthropicProvider.ts +2 -1
- package/src/llm/providers/GeminiProvider.ts +2 -1
- package/src/llm/providers/OllamaProvider.ts +2 -1
- package/src/llm/providers/OpenAIProvider.ts +2 -1
- package/src/llm/providers/UniversalLLMAdapter.ts +2 -1
- package/src/server.ts +2 -2
- package/src/types/chat.ts +53 -0
- package/src/types/index.ts +3 -0
- package/src/types/props.ts +79 -0
- package/dist/DocumentChunker-Dh9TvmGG.d.mts +0 -45
- package/dist/DocumentChunker-Dh9TvmGG.d.ts +0 -45
package/dist/index.js
CHANGED
|
@@ -22,6 +22,18 @@ var __spreadValues = (a, b) => {
|
|
|
22
22
|
return a;
|
|
23
23
|
};
|
|
24
24
|
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
25
|
+
var __objRest = (source, exclude) => {
|
|
26
|
+
var target = {};
|
|
27
|
+
for (var prop in source)
|
|
28
|
+
if (__hasOwnProp.call(source, prop) && exclude.indexOf(prop) < 0)
|
|
29
|
+
target[prop] = source[prop];
|
|
30
|
+
if (source != null && __getOwnPropSymbols)
|
|
31
|
+
for (var prop of __getOwnPropSymbols(source)) {
|
|
32
|
+
if (exclude.indexOf(prop) < 0 && __propIsEnum.call(source, prop))
|
|
33
|
+
target[prop] = source[prop];
|
|
34
|
+
}
|
|
35
|
+
return target;
|
|
36
|
+
};
|
|
25
37
|
var __export = (target, all) => {
|
|
26
38
|
for (var name in all)
|
|
27
39
|
__defProp(target, name, { get: all[name], enumerable: true });
|
|
@@ -59,15 +71,15 @@ __export(index_exports, {
|
|
|
59
71
|
module.exports = __toCommonJS(index_exports);
|
|
60
72
|
|
|
61
73
|
// src/components/ChatWidget.tsx
|
|
62
|
-
var
|
|
74
|
+
var import_react9 = __toESM(require("react"));
|
|
63
75
|
var import_lucide_react6 = require("lucide-react");
|
|
64
76
|
|
|
65
77
|
// src/components/ChatWindow.tsx
|
|
66
|
-
var
|
|
78
|
+
var import_react8 = __toESM(require("react"));
|
|
67
79
|
var import_lucide_react5 = require("lucide-react");
|
|
68
80
|
|
|
69
81
|
// src/components/MessageBubble.tsx
|
|
70
|
-
var
|
|
82
|
+
var import_react5 = __toESM(require("react"));
|
|
71
83
|
var import_lucide_react4 = require("lucide-react");
|
|
72
84
|
var import_react_markdown = __toESM(require("react-markdown"));
|
|
73
85
|
var import_remark_gfm = __toESM(require("remark-gfm"));
|
|
@@ -204,6 +216,71 @@ function ProductCarousel({ products, primaryColor = "#6366f1", onAddToCart }) {
|
|
|
204
216
|
));
|
|
205
217
|
}
|
|
206
218
|
|
|
219
|
+
// src/components/DynamicChart.tsx
|
|
220
|
+
var import_react4 = __toESM(require("react"));
|
|
221
|
+
var import_recharts = require("recharts");
|
|
222
|
+
var DEFAULT_COLORS = ["#6366f1", "#10b981", "#f59e0b", "#ef4444", "#8b5cf6", "#ec4899"];
|
|
223
|
+
function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6" }) {
|
|
224
|
+
const { type, data, xAxisKey = "name", dataKeys = [] } = config;
|
|
225
|
+
const colors = config.colors || [primaryColor, accentColor, ...DEFAULT_COLORS];
|
|
226
|
+
if (!data || data.length === 0) {
|
|
227
|
+
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "p-4 text-sm text-slate-500" }, "No data available for chart.");
|
|
228
|
+
}
|
|
229
|
+
if (type === "pie") {
|
|
230
|
+
const pieDataKey = dataKeys[0] || Object.keys(data[0]).find((k) => k !== xAxisKey) || "value";
|
|
231
|
+
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full h-64 mt-4 mb-2 select-none" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.PieChart, null, /* @__PURE__ */ import_react4.default.createElement(
|
|
232
|
+
import_recharts.Pie,
|
|
233
|
+
{
|
|
234
|
+
data,
|
|
235
|
+
dataKey: pieDataKey,
|
|
236
|
+
nameKey: xAxisKey,
|
|
237
|
+
cx: "50%",
|
|
238
|
+
cy: "50%",
|
|
239
|
+
outerRadius: 80,
|
|
240
|
+
label: ({ name, percent }) => `${name} ${((percent != null ? percent : 0) * 100).toFixed(0)}%`
|
|
241
|
+
},
|
|
242
|
+
data.map((entry, index) => /* @__PURE__ */ import_react4.default.createElement(import_recharts.Cell, { key: `cell-${index}`, fill: colors[index % colors.length] }))
|
|
243
|
+
), /* @__PURE__ */ import_react4.default.createElement(
|
|
244
|
+
import_recharts.Tooltip,
|
|
245
|
+
{
|
|
246
|
+
contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" }
|
|
247
|
+
}
|
|
248
|
+
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, null))));
|
|
249
|
+
}
|
|
250
|
+
return /* @__PURE__ */ import_react4.default.createElement("div", { className: "w-full h-64 mt-4 mb-2 select-none" }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.ResponsiveContainer, { width: "100%", height: "100%" }, type === "bar" ? /* @__PURE__ */ import_react4.default.createElement(import_recharts.BarChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.XAxis, { dataKey: xAxisKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react4.default.createElement(
|
|
251
|
+
import_recharts.Tooltip,
|
|
252
|
+
{
|
|
253
|
+
contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" },
|
|
254
|
+
cursor: { fill: "#f1f5f9" }
|
|
255
|
+
}
|
|
256
|
+
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }), dataKeys.map((key, index) => /* @__PURE__ */ import_react4.default.createElement(
|
|
257
|
+
import_recharts.Bar,
|
|
258
|
+
{
|
|
259
|
+
key,
|
|
260
|
+
dataKey: key,
|
|
261
|
+
fill: colors[index % colors.length],
|
|
262
|
+
radius: [4, 4, 0, 0],
|
|
263
|
+
barSize: Math.max(20, 60 / data.length)
|
|
264
|
+
}
|
|
265
|
+
))) : /* @__PURE__ */ import_react4.default.createElement(import_recharts.LineChart, { data, margin: { top: 10, right: 10, left: -20, bottom: 0 } }, /* @__PURE__ */ import_react4.default.createElement(import_recharts.CartesianGrid, { strokeDasharray: "3 3", vertical: false, stroke: "#e2e8f0" }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.XAxis, { dataKey: xAxisKey, tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: { stroke: "#cbd5e1" } }), /* @__PURE__ */ import_react4.default.createElement(import_recharts.YAxis, { tick: { fontSize: 12, fill: "#64748b" }, tickLine: false, axisLine: false }), /* @__PURE__ */ import_react4.default.createElement(
|
|
266
|
+
import_recharts.Tooltip,
|
|
267
|
+
{
|
|
268
|
+
contentStyle: { borderRadius: "8px", border: "none", boxShadow: "0 4px 6px -1px rgb(0 0 0 / 0.1)" }
|
|
269
|
+
}
|
|
270
|
+
), /* @__PURE__ */ import_react4.default.createElement(import_recharts.Legend, { wrapperStyle: { fontSize: 12 } }), dataKeys.map((key, index) => /* @__PURE__ */ import_react4.default.createElement(
|
|
271
|
+
import_recharts.Line,
|
|
272
|
+
{
|
|
273
|
+
key,
|
|
274
|
+
type: "monotone",
|
|
275
|
+
dataKey: key,
|
|
276
|
+
stroke: colors[index % colors.length],
|
|
277
|
+
strokeWidth: 3,
|
|
278
|
+
dot: { r: 4, strokeWidth: 2 },
|
|
279
|
+
activeDot: { r: 6 }
|
|
280
|
+
}
|
|
281
|
+
)))));
|
|
282
|
+
}
|
|
283
|
+
|
|
207
284
|
// src/components/MessageBubble.tsx
|
|
208
285
|
function MessageBubble({
|
|
209
286
|
message,
|
|
@@ -214,7 +291,7 @@ function MessageBubble({
|
|
|
214
291
|
onAddToCart
|
|
215
292
|
}) {
|
|
216
293
|
const isUser = message.role === "user";
|
|
217
|
-
const [showSources, setShowSources] =
|
|
294
|
+
const [showSources, setShowSources] = import_react5.default.useState(false);
|
|
218
295
|
const resolveImage = (data) => {
|
|
219
296
|
if (!data) return void 0;
|
|
220
297
|
const singleFields = ["image", "img", "thumbnail"];
|
|
@@ -227,7 +304,7 @@ function MessageBubble({
|
|
|
227
304
|
}
|
|
228
305
|
return void 0;
|
|
229
306
|
};
|
|
230
|
-
const productsFromSources =
|
|
307
|
+
const productsFromSources = import_react5.default.useMemo(() => {
|
|
231
308
|
if (isUser || !sources) return [];
|
|
232
309
|
return sources.filter((s) => {
|
|
233
310
|
const m = s.metadata || {};
|
|
@@ -245,7 +322,7 @@ function MessageBubble({
|
|
|
245
322
|
};
|
|
246
323
|
});
|
|
247
324
|
}, [sources, isUser]);
|
|
248
|
-
const { productsFromContent, cleanContent } =
|
|
325
|
+
const { productsFromContent, cleanContent } = import_react5.default.useMemo(() => {
|
|
249
326
|
if (isUser) return { productsFromContent: [], cleanContent: message.content };
|
|
250
327
|
const jsonRegex = /```json\s*([\s\S]*?)\s*```/g;
|
|
251
328
|
const products = [];
|
|
@@ -268,7 +345,7 @@ function MessageBubble({
|
|
|
268
345
|
}
|
|
269
346
|
return { productsFromContent: products, cleanContent: content.trim() };
|
|
270
347
|
}, [message.content, isUser]);
|
|
271
|
-
const allProducts =
|
|
348
|
+
const allProducts = import_react5.default.useMemo(() => {
|
|
272
349
|
if (productsFromContent.length > 0) return productsFromContent;
|
|
273
350
|
const uniqueProducts = [];
|
|
274
351
|
const seenIds = /* @__PURE__ */ new Set();
|
|
@@ -286,43 +363,88 @@ function MessageBubble({
|
|
|
286
363
|
return uniqueProducts;
|
|
287
364
|
}, [productsFromSources, productsFromContent, message.content]);
|
|
288
365
|
const hasProducts = allProducts.length > 0;
|
|
289
|
-
return /* @__PURE__ */
|
|
366
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: `flex gap-3 ${isUser ? "flex-row-reverse" : "flex-row"} items-start` }, /* @__PURE__ */ import_react5.default.createElement(
|
|
290
367
|
"div",
|
|
291
368
|
{
|
|
292
369
|
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"}`,
|
|
293
370
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
294
371
|
},
|
|
295
|
-
isUser ? /* @__PURE__ */
|
|
296
|
-
), /* @__PURE__ */
|
|
372
|
+
isUser ? /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.User, { className: "w-4 h-4 text-white" }) : /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.Bot, { className: "w-4 h-4" })
|
|
373
|
+
), /* @__PURE__ */ import_react5.default.createElement("div", { className: `flex flex-col gap-1 max-w-[90%] ${isUser ? "items-end" : "items-start"}` }, /* @__PURE__ */ import_react5.default.createElement(
|
|
297
374
|
"div",
|
|
298
375
|
{
|
|
299
376
|
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"}`,
|
|
300
377
|
style: isUser ? { background: `linear-gradient(135deg, ${primaryColor}, ${accentColor})` } : {}
|
|
301
378
|
},
|
|
302
|
-
isStreaming && !message.content ? /* @__PURE__ */
|
|
303
|
-
|
|
379
|
+
isStreaming && !message.content ? /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex items-center gap-1 py-1" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:0ms]" }), /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:150ms]" }), /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-slate-400 dark:bg-white/60 animate-bounce [animation-delay:300ms]" })) : /* @__PURE__ */ import_react5.default.createElement("div", { className: `prose prose-sm max-w-none ${isUser ? "prose-invert" : "dark:prose-invert"}` }, /* @__PURE__ */ import_react5.default.createElement(
|
|
380
|
+
import_react_markdown.default,
|
|
381
|
+
{
|
|
382
|
+
remarkPlugins: [import_remark_gfm.default],
|
|
383
|
+
components: {
|
|
384
|
+
table: (_a) => {
|
|
385
|
+
var props = __objRest(_a, []);
|
|
386
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "overflow-x-auto my-4 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement("table", __spreadValues({ className: "w-full text-left border-collapse min-w-[400px]" }, props)));
|
|
387
|
+
},
|
|
388
|
+
thead: (_b) => {
|
|
389
|
+
var props = __objRest(_b, []);
|
|
390
|
+
return /* @__PURE__ */ import_react5.default.createElement("thead", __spreadValues({ className: "bg-slate-50 dark:bg-white/5 border-b border-slate-200 dark:border-white/10" }, props));
|
|
391
|
+
},
|
|
392
|
+
th: (_c) => {
|
|
393
|
+
var props = __objRest(_c, []);
|
|
394
|
+
return /* @__PURE__ */ import_react5.default.createElement("th", __spreadValues({ className: "p-3 font-semibold text-slate-700 dark:text-white/90 first:rounded-tl-xl last:rounded-tr-xl" }, props));
|
|
395
|
+
},
|
|
396
|
+
td: (_d) => {
|
|
397
|
+
var props = __objRest(_d, []);
|
|
398
|
+
return /* @__PURE__ */ import_react5.default.createElement("td", __spreadValues({ className: "p-3 border-b border-slate-100 dark:border-white/5 last:border-0 text-slate-600 dark:text-white/70" }, props));
|
|
399
|
+
},
|
|
400
|
+
code(_e) {
|
|
401
|
+
var _f = _e, { inline, className, children } = _f, props = __objRest(_f, ["inline", "className", "children"]);
|
|
402
|
+
const match = /language-(\w+)/.exec(className || "");
|
|
403
|
+
const isChart = match && match[1] === "chart";
|
|
404
|
+
if (!inline && isChart) {
|
|
405
|
+
try {
|
|
406
|
+
const config = JSON.parse(String(children).replace(/\n$/, ""));
|
|
407
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "my-4 p-4 bg-white dark:bg-slate-900 rounded-xl border border-slate-200 dark:border-white/10 shadow-sm" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
408
|
+
DynamicChart,
|
|
409
|
+
{
|
|
410
|
+
config,
|
|
411
|
+
primaryColor,
|
|
412
|
+
accentColor
|
|
413
|
+
}
|
|
414
|
+
));
|
|
415
|
+
} catch (e) {
|
|
416
|
+
return /* @__PURE__ */ import_react5.default.createElement("div", { className: "p-4 bg-red-50 dark:bg-red-900/20 text-red-600 dark:text-red-400 rounded-lg text-sm" }, "Failed to render chart: Invalid configuration.");
|
|
417
|
+
}
|
|
418
|
+
}
|
|
419
|
+
return /* @__PURE__ */ import_react5.default.createElement("code", __spreadValues({ className }, props), children);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
},
|
|
423
|
+
cleanContent || message.content
|
|
424
|
+
), isStreaming && message.content && /* @__PURE__ */ import_react5.default.createElement("span", { className: "inline-block w-1.5 h-3.5 ml-1 bg-emerald-500 animate-pulse align-middle" }))
|
|
425
|
+
), !isUser && hasProducts && /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full mt-1" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
304
426
|
ProductCarousel,
|
|
305
427
|
{
|
|
306
428
|
products: allProducts,
|
|
307
429
|
primaryColor,
|
|
308
430
|
onAddToCart
|
|
309
431
|
}
|
|
310
|
-
)), !isUser && sources && sources.length > 0 && /* @__PURE__ */
|
|
432
|
+
)), !isUser && sources && sources.length > 0 && /* @__PURE__ */ import_react5.default.createElement("div", { className: "w-full" }, /* @__PURE__ */ import_react5.default.createElement(
|
|
311
433
|
"button",
|
|
312
434
|
{
|
|
313
435
|
onClick: () => setShowSources((s) => !s),
|
|
314
436
|
className: "text-[11px] text-indigo-400 hover:text-indigo-300 transition-colors flex items-center gap-1 mt-1"
|
|
315
437
|
},
|
|
316
|
-
showSources ? /* @__PURE__ */
|
|
438
|
+
showSources ? /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.ChevronDown, { className: "w-3 h-3" }) : /* @__PURE__ */ import_react5.default.createElement(import_lucide_react4.ChevronRight, { className: "w-3 h-3" }),
|
|
317
439
|
sources.length,
|
|
318
440
|
" source",
|
|
319
441
|
sources.length !== 1 ? "s" : "",
|
|
320
442
|
" used"
|
|
321
|
-
), showSources && /* @__PURE__ */
|
|
443
|
+
), showSources && /* @__PURE__ */ import_react5.default.createElement("div", { className: "mt-2 flex flex-col gap-2" }, sources.map((src, i) => /* @__PURE__ */ import_react5.default.createElement(SourceCard, { key: src.id, source: src, index: i }))))));
|
|
322
444
|
}
|
|
323
445
|
|
|
324
446
|
// src/components/ConfigProvider.tsx
|
|
325
|
-
var
|
|
447
|
+
var import_react6 = __toESM(require("react"));
|
|
326
448
|
|
|
327
449
|
// src/utils/templateUtils.ts
|
|
328
450
|
function mergeDefined(base, override) {
|
|
@@ -338,8 +460,8 @@ function mergeDefined(base, override) {
|
|
|
338
460
|
return merged;
|
|
339
461
|
}
|
|
340
462
|
|
|
341
|
-
// src/
|
|
342
|
-
var
|
|
463
|
+
// src/config/uiConstants.ts
|
|
464
|
+
var DEFAULT_CONFIG = {
|
|
343
465
|
projectId: "default",
|
|
344
466
|
ui: {
|
|
345
467
|
title: "AI Assistant",
|
|
@@ -355,29 +477,45 @@ var defaultConfig = {
|
|
|
355
477
|
visualStyle: "glass",
|
|
356
478
|
borderRadius: "xl",
|
|
357
479
|
allowUpload: true,
|
|
358
|
-
allowResize: true
|
|
480
|
+
allowResize: true,
|
|
481
|
+
enableVoiceInput: true
|
|
359
482
|
}
|
|
360
483
|
};
|
|
361
|
-
var
|
|
484
|
+
var BORDER_RADIUS_MAP = {
|
|
485
|
+
none: "rounded-none",
|
|
486
|
+
sm: "rounded-sm",
|
|
487
|
+
md: "rounded-md",
|
|
488
|
+
lg: "rounded-lg",
|
|
489
|
+
xl: "rounded-xl",
|
|
490
|
+
full: "rounded-3xl"
|
|
491
|
+
};
|
|
492
|
+
var CHAT_SUGGESTIONS = [
|
|
493
|
+
"What can you help me with?",
|
|
494
|
+
"Summarise the key topics",
|
|
495
|
+
"Show me an example"
|
|
496
|
+
];
|
|
497
|
+
|
|
498
|
+
// src/components/ConfigProvider.tsx
|
|
499
|
+
var ConfigContext = (0, import_react6.createContext)(DEFAULT_CONFIG);
|
|
362
500
|
function ConfigProvider({
|
|
363
501
|
config,
|
|
364
502
|
children
|
|
365
503
|
}) {
|
|
366
504
|
const merged = {
|
|
367
|
-
projectId: (config == null ? void 0 : config.projectId) ||
|
|
368
|
-
ui: mergeDefined(
|
|
505
|
+
projectId: (config == null ? void 0 : config.projectId) || DEFAULT_CONFIG.projectId,
|
|
506
|
+
ui: mergeDefined(DEFAULT_CONFIG.ui, config == null ? void 0 : config.ui)
|
|
369
507
|
};
|
|
370
|
-
return /* @__PURE__ */
|
|
508
|
+
return /* @__PURE__ */ import_react6.default.createElement(ConfigContext.Provider, { value: merged }, children);
|
|
371
509
|
}
|
|
372
510
|
function useConfig() {
|
|
373
|
-
return (0,
|
|
511
|
+
return (0, import_react6.useContext)(ConfigContext);
|
|
374
512
|
}
|
|
375
513
|
|
|
376
514
|
// src/hooks/useRagChat.ts
|
|
377
|
-
var
|
|
515
|
+
var import_react7 = require("react");
|
|
378
516
|
|
|
379
517
|
// src/hooks/useStoredMessages.ts
|
|
380
|
-
var
|
|
518
|
+
var React7 = __toESM(require("react"));
|
|
381
519
|
function readStoredMessages(storageKey) {
|
|
382
520
|
if (typeof window === "undefined") {
|
|
383
521
|
return [];
|
|
@@ -394,8 +532,8 @@ function readStoredMessages(storageKey) {
|
|
|
394
532
|
}
|
|
395
533
|
}
|
|
396
534
|
function useStoredMessages(storageKey, persist) {
|
|
397
|
-
const [messages, setMessages] =
|
|
398
|
-
|
|
535
|
+
const [messages, setMessages] = React7.useState(() => persist ? readStoredMessages(storageKey) : []);
|
|
536
|
+
React7.useEffect(() => {
|
|
399
537
|
if (!persist || typeof window === "undefined") {
|
|
400
538
|
return;
|
|
401
539
|
}
|
|
@@ -435,14 +573,14 @@ function useRagChat(projectId, options = {}) {
|
|
|
435
573
|
} = options;
|
|
436
574
|
const storageKey = `rag_chat_${projectId}`;
|
|
437
575
|
const [messages, setMessages] = useStoredMessages(storageKey, persist);
|
|
438
|
-
const [isLoading, setIsLoading] = (0,
|
|
439
|
-
const [error, setError] = (0,
|
|
440
|
-
const lastInputRef = (0,
|
|
441
|
-
const messagesRef = (0,
|
|
442
|
-
(0,
|
|
576
|
+
const [isLoading, setIsLoading] = (0, import_react7.useState)(false);
|
|
577
|
+
const [error, setError] = (0, import_react7.useState)(null);
|
|
578
|
+
const lastInputRef = (0, import_react7.useRef)("");
|
|
579
|
+
const messagesRef = (0, import_react7.useRef)(messages);
|
|
580
|
+
(0, import_react7.useEffect)(() => {
|
|
443
581
|
messagesRef.current = messages;
|
|
444
582
|
}, [messages]);
|
|
445
|
-
const sendMessage = (0,
|
|
583
|
+
const sendMessage = (0, import_react7.useCallback)(
|
|
446
584
|
async (text, opts) => {
|
|
447
585
|
var _a, _b;
|
|
448
586
|
const trimmed = text.trim();
|
|
@@ -539,12 +677,12 @@ function useRagChat(projectId, options = {}) {
|
|
|
539
677
|
},
|
|
540
678
|
[apiUrl, isLoading, namespace, onError, onReply, projectId, setMessages]
|
|
541
679
|
);
|
|
542
|
-
const clear = (0,
|
|
680
|
+
const clear = (0, import_react7.useCallback)(() => {
|
|
543
681
|
setMessages([]);
|
|
544
682
|
setError(null);
|
|
545
683
|
if (persist) localStorage.removeItem(storageKey);
|
|
546
684
|
}, [persist, setMessages, storageKey]);
|
|
547
|
-
const retry = (0,
|
|
685
|
+
const retry = (0, import_react7.useCallback)(async () => {
|
|
548
686
|
if (lastInputRef.current) {
|
|
549
687
|
const latestMessage = messagesRef.current[messagesRef.current.length - 1];
|
|
550
688
|
await sendMessage(lastInputRef.current, {
|
|
@@ -563,21 +701,6 @@ function useRagChat(projectId, options = {}) {
|
|
|
563
701
|
};
|
|
564
702
|
}
|
|
565
703
|
|
|
566
|
-
// src/config/uiConstants.ts
|
|
567
|
-
var BORDER_RADIUS_MAP = {
|
|
568
|
-
none: "rounded-none",
|
|
569
|
-
sm: "rounded-sm",
|
|
570
|
-
md: "rounded-md",
|
|
571
|
-
lg: "rounded-lg",
|
|
572
|
-
xl: "rounded-xl",
|
|
573
|
-
full: "rounded-3xl"
|
|
574
|
-
};
|
|
575
|
-
var CHAT_SUGGESTIONS = [
|
|
576
|
-
"What can you help me with?",
|
|
577
|
-
"Summarise the key topics",
|
|
578
|
-
"Show me an example"
|
|
579
|
-
];
|
|
580
|
-
|
|
581
704
|
// src/components/ChatWindow.tsx
|
|
582
705
|
function ChatWindow({
|
|
583
706
|
className = "",
|
|
@@ -593,32 +716,88 @@ function ChatWindow({
|
|
|
593
716
|
}) {
|
|
594
717
|
var _a;
|
|
595
718
|
const { ui, projectId } = useConfig();
|
|
596
|
-
const [input, setInput] = (0,
|
|
597
|
-
const [mounted, setMounted] = (0,
|
|
598
|
-
const bottomRef = (0,
|
|
599
|
-
const inputRef = (0,
|
|
719
|
+
const [input, setInput] = (0, import_react8.useState)("");
|
|
720
|
+
const [mounted, setMounted] = (0, import_react8.useState)(false);
|
|
721
|
+
const bottomRef = (0, import_react8.useRef)(null);
|
|
722
|
+
const inputRef = (0, import_react8.useRef)(null);
|
|
600
723
|
const { messages, send, clear, isLoading, error } = useRagChat(projectId, {
|
|
601
724
|
namespace: projectId
|
|
602
725
|
});
|
|
603
|
-
(0,
|
|
726
|
+
const [suggestions, setSuggestions] = (0, import_react8.useState)([]);
|
|
727
|
+
const [isSuggesting, setIsSuggesting] = (0, import_react8.useState)(false);
|
|
728
|
+
const [isListening, setIsListening] = (0, import_react8.useState)(false);
|
|
729
|
+
const recognitionRef = (0, import_react8.useRef)(null);
|
|
730
|
+
(0, import_react8.useEffect)(() => {
|
|
731
|
+
if (typeof window !== "undefined") {
|
|
732
|
+
const win = window;
|
|
733
|
+
const SpeechRecognition = win.SpeechRecognition || win.webkitSpeechRecognition;
|
|
734
|
+
if (SpeechRecognition) {
|
|
735
|
+
const recognition = new SpeechRecognition();
|
|
736
|
+
recognition.continuous = true;
|
|
737
|
+
recognition.interimResults = true;
|
|
738
|
+
recognition.onresult = (event) => {
|
|
739
|
+
let finalTranscript = "";
|
|
740
|
+
for (let i = event.resultIndex; i < event.results.length; ++i) {
|
|
741
|
+
if (event.results[i].isFinal) {
|
|
742
|
+
finalTranscript += event.results[i][0].transcript;
|
|
743
|
+
}
|
|
744
|
+
}
|
|
745
|
+
if (finalTranscript) {
|
|
746
|
+
setInput((prev) => (prev ? prev + " " : "") + finalTranscript.trim());
|
|
747
|
+
}
|
|
748
|
+
};
|
|
749
|
+
recognition.onerror = (event) => {
|
|
750
|
+
console.error("Speech recognition error:", event.error);
|
|
751
|
+
setIsListening(false);
|
|
752
|
+
};
|
|
753
|
+
recognition.onend = () => {
|
|
754
|
+
setIsListening(false);
|
|
755
|
+
};
|
|
756
|
+
recognitionRef.current = recognition;
|
|
757
|
+
}
|
|
758
|
+
}
|
|
759
|
+
}, []);
|
|
760
|
+
const toggleListening = () => {
|
|
761
|
+
if (!recognitionRef.current) {
|
|
762
|
+
alert("Speech recognition is not supported in your browser.");
|
|
763
|
+
return;
|
|
764
|
+
}
|
|
765
|
+
if (isListening) {
|
|
766
|
+
recognitionRef.current.stop();
|
|
767
|
+
} else {
|
|
768
|
+
try {
|
|
769
|
+
recognitionRef.current.start();
|
|
770
|
+
setIsListening(true);
|
|
771
|
+
} catch (err) {
|
|
772
|
+
console.error("Failed to start recognition:", err);
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
};
|
|
776
|
+
(0, import_react8.useEffect)(() => {
|
|
604
777
|
setMounted(true);
|
|
605
778
|
}, []);
|
|
606
|
-
(0,
|
|
779
|
+
(0, import_react8.useEffect)(() => {
|
|
607
780
|
var _a2;
|
|
608
781
|
if (messages.length > 0 || isLoading) {
|
|
609
782
|
(_a2 = bottomRef.current) == null ? void 0 : _a2.scrollIntoView({ behavior: "smooth" });
|
|
610
783
|
}
|
|
611
784
|
}, [messages, isLoading]);
|
|
612
|
-
const sendMessage = (0,
|
|
785
|
+
const sendMessage = (0, import_react8.useCallback)(async () => {
|
|
786
|
+
var _a2;
|
|
613
787
|
const text = input.trim();
|
|
614
788
|
if (!text || isLoading) return;
|
|
789
|
+
if (isListening) {
|
|
790
|
+
(_a2 = recognitionRef.current) == null ? void 0 : _a2.stop();
|
|
791
|
+
}
|
|
615
792
|
setInput("");
|
|
793
|
+
setSuggestions([]);
|
|
794
|
+
setIsSuggesting(false);
|
|
616
795
|
await send(text);
|
|
617
796
|
window.setTimeout(() => {
|
|
618
|
-
var
|
|
619
|
-
return (
|
|
797
|
+
var _a3;
|
|
798
|
+
return (_a3 = inputRef.current) == null ? void 0 : _a3.focus();
|
|
620
799
|
}, 50);
|
|
621
|
-
}, [input, isLoading, send]);
|
|
800
|
+
}, [input, isLoading, send, isListening]);
|
|
622
801
|
const handleKeyDown = (e) => {
|
|
623
802
|
if (e.key === "Enter" && !e.shiftKey) {
|
|
624
803
|
e.preventDefault();
|
|
@@ -627,13 +806,13 @@ function ChatWindow({
|
|
|
627
806
|
};
|
|
628
807
|
const clearHistory = () => {
|
|
629
808
|
clear();
|
|
809
|
+
setSuggestions([]);
|
|
810
|
+
setIsSuggesting(false);
|
|
630
811
|
};
|
|
631
812
|
const isEmpty = messages.length === 0;
|
|
632
813
|
const currentRadius = BORDER_RADIUS_MAP[ui.borderRadius || "xl"];
|
|
633
814
|
const isGlass = ui.visualStyle !== "solid";
|
|
634
|
-
|
|
635
|
-
const [isSuggesting, setIsSuggesting] = (0, import_react7.useState)(false);
|
|
636
|
-
(0, import_react7.useEffect)(() => {
|
|
815
|
+
(0, import_react8.useEffect)(() => {
|
|
637
816
|
if (input.trim().length < 3) {
|
|
638
817
|
return;
|
|
639
818
|
}
|
|
@@ -657,83 +836,83 @@ function ChatWindow({
|
|
|
657
836
|
}, 800);
|
|
658
837
|
return () => clearTimeout(timer);
|
|
659
838
|
}, [input, projectId]);
|
|
660
|
-
return /* @__PURE__ */
|
|
839
|
+
return /* @__PURE__ */ import_react8.default.createElement(
|
|
661
840
|
"div",
|
|
662
841
|
{
|
|
663
842
|
className: `relative flex flex-col border border-slate-200 dark:border-white/10 shadow-2xl transition-all duration-300 ${currentRadius} ${isGlass ? "bg-white/90 dark:bg-[#0f0f1a]/90 backdrop-blur-xl" : "bg-white dark:bg-[#0f0f1a]"} ${className}`,
|
|
664
843
|
style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
|
|
665
844
|
},
|
|
666
|
-
onResizeStart && /* @__PURE__ */
|
|
845
|
+
onResizeStart && /* @__PURE__ */ import_react8.default.createElement(
|
|
667
846
|
"div",
|
|
668
847
|
{
|
|
669
848
|
onMouseDown: onResizeStart,
|
|
670
849
|
className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
|
|
671
850
|
title: "Drag to resize"
|
|
672
851
|
},
|
|
673
|
-
/* @__PURE__ */
|
|
852
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "w-2.5 h-2.5 border-t-2 border-l-2 border-slate-300 dark:border-white/20 group-hover:border-slate-500 dark:group-hover:border-white/50 transition-colors rounded-tl-[2px]" })
|
|
674
853
|
),
|
|
675
|
-
/* @__PURE__ */
|
|
854
|
+
/* @__PURE__ */ import_react8.default.createElement(
|
|
676
855
|
"div",
|
|
677
856
|
{
|
|
678
857
|
className: "flex items-center justify-between px-5 py-4 border-b border-slate-200 dark:border-white/10",
|
|
679
858
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}15, ${ui.accentColor}10)` }
|
|
680
859
|
},
|
|
681
|
-
/* @__PURE__ */
|
|
860
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-3" }, ui.logoUrl ? (
|
|
682
861
|
// eslint-disable-next-line @next/next/no-img-element
|
|
683
|
-
/* @__PURE__ */
|
|
684
|
-
) : /* @__PURE__ */
|
|
862
|
+
/* @__PURE__ */ import_react8.default.createElement("img", { src: ui.logoUrl, alt: "logo", className: "w-8 h-8 rounded-lg object-cover" })
|
|
863
|
+
) : /* @__PURE__ */ import_react8.default.createElement(
|
|
685
864
|
"div",
|
|
686
865
|
{
|
|
687
866
|
className: `w-9 h-9 flex items-center justify-center shadow-md ${ui.borderRadius === "full" ? "rounded-full" : "rounded-xl"}`,
|
|
688
867
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
689
868
|
},
|
|
690
|
-
/* @__PURE__ */
|
|
691
|
-
), /* @__PURE__ */
|
|
692
|
-
/* @__PURE__ */
|
|
869
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Bot, { className: "w-5 h-5 text-white" })
|
|
870
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
|
|
871
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ import_react8.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center bg-slate-100/50 dark:bg-white/5 rounded-lg p-0.5 border border-slate-200/50 dark:border-white/5" }, mounted && messages.length > 0 && /* @__PURE__ */ import_react8.default.createElement(
|
|
693
872
|
"button",
|
|
694
873
|
{
|
|
695
874
|
onClick: clearHistory,
|
|
696
875
|
title: "Clear conversation",
|
|
697
876
|
className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-rose-500 dark:text-white/40 dark:hover:text-rose-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
|
|
698
877
|
},
|
|
699
|
-
/* @__PURE__ */
|
|
700
|
-
), isResized && onResetResize && /* @__PURE__ */
|
|
878
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Trash2, { className: "w-3.5 h-3.5" })
|
|
879
|
+
), isResized && onResetResize && /* @__PURE__ */ import_react8.default.createElement(
|
|
701
880
|
"button",
|
|
702
881
|
{
|
|
703
882
|
onClick: onResetResize,
|
|
704
883
|
title: "Reset to default size",
|
|
705
884
|
className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
|
|
706
885
|
},
|
|
707
|
-
/* @__PURE__ */
|
|
708
|
-
), onMaximize && /* @__PURE__ */
|
|
886
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.RotateCcw, { className: "w-3.5 h-3.5" })
|
|
887
|
+
), onMaximize && /* @__PURE__ */ import_react8.default.createElement(
|
|
709
888
|
"button",
|
|
710
889
|
{
|
|
711
890
|
onClick: onMaximize,
|
|
712
891
|
title: isMaximized ? "Minimize" : "Maximize",
|
|
713
892
|
className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-blue-500 dark:text-white/40 dark:hover:text-blue-400 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
|
|
714
893
|
},
|
|
715
|
-
isMaximized ? /* @__PURE__ */
|
|
716
|
-
), showClose && onClose && /* @__PURE__ */
|
|
894
|
+
isMaximized ? /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Maximize2, { className: "w-3.5 h-3.5" })
|
|
895
|
+
), showClose && onClose && /* @__PURE__ */ import_react8.default.createElement(
|
|
717
896
|
"button",
|
|
718
897
|
{
|
|
719
898
|
onClick: onClose,
|
|
720
899
|
title: "Close chat",
|
|
721
900
|
className: "w-7 h-7 rounded-md flex items-center justify-center text-slate-400 hover:text-slate-600 dark:text-white/40 dark:hover:text-white/70 hover:bg-white dark:hover:bg-white/10 transition-all cursor-pointer"
|
|
722
901
|
},
|
|
723
|
-
/* @__PURE__ */
|
|
902
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.X, { className: "w-4 h-4" })
|
|
724
903
|
)))
|
|
725
904
|
),
|
|
726
|
-
/* @__PURE__ */
|
|
905
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "flex-1 overflow-y-auto px-4 py-4 space-y-5 scrollbar-thin scrollbar-thumb-slate-200 dark:scrollbar-thumb-white/10 scrollbar-track-transparent min-h-0 bg-slate-50 dark:bg-transparent" }, !mounted || isEmpty ? (
|
|
727
906
|
/* Welcome state */
|
|
728
|
-
/* @__PURE__ */
|
|
907
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: "h-full flex flex-col items-center justify-center text-center gap-4 px-6 py-12" }, /* @__PURE__ */ import_react8.default.createElement(
|
|
729
908
|
"div",
|
|
730
909
|
{
|
|
731
910
|
className: `w-16 h-16 flex items-center justify-center shadow-lg ${ui.borderRadius === "full" ? "rounded-full" : "rounded-2xl"}`,
|
|
732
911
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` }
|
|
733
912
|
},
|
|
734
|
-
/* @__PURE__ */
|
|
735
|
-
), /* @__PURE__ */
|
|
736
|
-
(suggestion) => /* @__PURE__ */
|
|
913
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Sparkles, { className: "w-8 h-8 text-white" })
|
|
914
|
+
), /* @__PURE__ */ import_react8.default.createElement("div", null, /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-slate-800 dark:text-white/80 font-medium leading-relaxed" }, ui.welcomeMessage), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-slate-500 dark:text-white/30 text-sm mt-2" }, "Ask a question to get started")), /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex flex-wrap gap-2 justify-center mt-2" }, CHAT_SUGGESTIONS.map(
|
|
915
|
+
(suggestion) => /* @__PURE__ */ import_react8.default.createElement(
|
|
737
916
|
"button",
|
|
738
917
|
{
|
|
739
918
|
key: suggestion,
|
|
@@ -747,7 +926,7 @@ function ChatWindow({
|
|
|
747
926
|
suggestion
|
|
748
927
|
)
|
|
749
928
|
)))
|
|
750
|
-
) : messages.map((msg, index) => /* @__PURE__ */
|
|
929
|
+
) : messages.map((msg, index) => /* @__PURE__ */ import_react8.default.createElement(
|
|
751
930
|
MessageBubble,
|
|
752
931
|
{
|
|
753
932
|
key: msg.id,
|
|
@@ -758,17 +937,17 @@ function ChatWindow({
|
|
|
758
937
|
accentColor: ui.accentColor,
|
|
759
938
|
onAddToCart
|
|
760
939
|
}
|
|
761
|
-
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */
|
|
940
|
+
)), isLoading && ((_a = messages[messages.length - 1]) == null ? void 0 : _a.role) !== "assistant" && /* @__PURE__ */ import_react8.default.createElement(
|
|
762
941
|
MessageBubble,
|
|
763
942
|
{
|
|
764
|
-
message: { role: "assistant", content: "" },
|
|
943
|
+
message: { id: "loading", role: "assistant", content: "", createdAt: (/* @__PURE__ */ new Date()).toISOString() },
|
|
765
944
|
isStreaming: true,
|
|
766
945
|
primaryColor: ui.primaryColor,
|
|
767
946
|
accentColor: ui.accentColor,
|
|
768
947
|
onAddToCart
|
|
769
948
|
}
|
|
770
|
-
), error && /* @__PURE__ */
|
|
771
|
-
/* @__PURE__ */
|
|
949
|
+
), error && /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-2 text-rose-500 dark:text-rose-400 text-sm bg-rose-50 dark:bg-rose-400/10 border border-rose-200 dark:border-rose-400/20 rounded-xl px-4 py-3" }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.TriangleAlert, { className: "w-4 h-4 flex-shrink-0" }), /* @__PURE__ */ import_react8.default.createElement("span", null, error)), /* @__PURE__ */ import_react8.default.createElement("div", { ref: bottomRef })),
|
|
950
|
+
/* @__PURE__ */ import_react8.default.createElement("div", { className: `px-4 pb-4 pt-2 border-t border-slate-200 dark:border-white/10 ${isGlass ? "bg-transparent" : "bg-white dark:bg-[#0f0f1a]"}` }, (suggestions.length > 0 || isSuggesting) && !isLoading && /* @__PURE__ */ import_react8.default.createElement("div", { className: "mb-3 flex flex-wrap gap-2 animate-in fade-in slide-in-from-bottom-2 duration-300" }, suggestions.map((suggestion) => /* @__PURE__ */ import_react8.default.createElement(
|
|
772
951
|
"button",
|
|
773
952
|
{
|
|
774
953
|
key: suggestion,
|
|
@@ -780,9 +959,9 @@ function ChatWindow({
|
|
|
780
959
|
},
|
|
781
960
|
className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium bg-white dark:bg-white/5 border border-slate-200 dark:border-white/10 text-slate-600 dark:text-white/60 hover:text-slate-900 dark:hover:text-white/90 hover:border-slate-300 dark:hover:border-white/20 transition-all shadow-sm cursor-pointer group"
|
|
782
961
|
},
|
|
783
|
-
/* @__PURE__ */
|
|
962
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3 text-amber-400" }),
|
|
784
963
|
suggestion
|
|
785
|
-
)), isSuggesting && suggestions.length === 0 && /* @__PURE__ */
|
|
964
|
+
)), isSuggesting && suggestions.length === 0 && /* @__PURE__ */ import_react8.default.createElement("div", { className: "flex items-center gap-1.5 px-3 py-1.5 rounded-xl text-[11px] font-medium text-slate-400 dark:text-white/30 animate-pulse" }, /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Sparkles, { className: "w-3 h-3" }), "Thinking...")), /* @__PURE__ */ import_react8.default.createElement("div", { className: `flex items-end gap-2 bg-slate-50 dark:bg-white/5 border border-slate-200 dark:border-white/10 p-2 focus-within:border-slate-300 dark:focus-within:border-white/20 transition-all ${ui.borderRadius === "full" ? "rounded-3xl" : "rounded-2xl"}` }, /* @__PURE__ */ import_react8.default.createElement(
|
|
786
965
|
"textarea",
|
|
787
966
|
{
|
|
788
967
|
ref: inputRef,
|
|
@@ -801,7 +980,17 @@ function ChatWindow({
|
|
|
801
980
|
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",
|
|
802
981
|
style: { scrollbarWidth: "none" }
|
|
803
982
|
}
|
|
804
|
-
), /* @__PURE__ */
|
|
983
|
+
), ui.enableVoiceInput !== false && /* @__PURE__ */ import_react8.default.createElement(
|
|
984
|
+
"button",
|
|
985
|
+
{
|
|
986
|
+
type: "button",
|
|
987
|
+
onClick: toggleListening,
|
|
988
|
+
disabled: isLoading,
|
|
989
|
+
className: `flex-shrink-0 w-9 h-9 rounded-xl flex items-center justify-center transition-all hover:scale-105 active:scale-95 disabled:opacity-50 disabled:cursor-not-allowed disabled:hover:scale-100 disabled:active:scale-100 ${isListening ? "bg-rose-500 text-white animate-pulse shadow-md shadow-rose-500/20" : "text-slate-400 dark:text-white/40 hover:bg-slate-200 dark:hover:bg-white/10"}`,
|
|
990
|
+
title: isListening ? "Stop listening" : "Start voice input"
|
|
991
|
+
},
|
|
992
|
+
isListening ? /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.MicOff, { className: "w-4 h-4" }) : /* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.Mic, { className: "w-4 h-4" })
|
|
993
|
+
), /* @__PURE__ */ import_react8.default.createElement(
|
|
805
994
|
"button",
|
|
806
995
|
{
|
|
807
996
|
onClick: sendMessage,
|
|
@@ -812,8 +1001,8 @@ function ChatWindow({
|
|
|
812
1001
|
// slate-400/20 for light mode disabled
|
|
813
1002
|
}
|
|
814
1003
|
},
|
|
815
|
-
/* @__PURE__ */
|
|
816
|
-
)), /* @__PURE__ */
|
|
1004
|
+
/* @__PURE__ */ import_react8.default.createElement(import_lucide_react5.ArrowUp, { className: "w-4 h-4 text-white" })
|
|
1005
|
+
)), /* @__PURE__ */ import_react8.default.createElement("p", { className: "text-center text-[10px] text-slate-400 dark:text-white/20 mt-2" }, "Press Enter to send \xB7 Shift+Enter for new line"))
|
|
817
1006
|
);
|
|
818
1007
|
}
|
|
819
1008
|
|
|
@@ -821,12 +1010,12 @@ function ChatWindow({
|
|
|
821
1010
|
var DEFAULT_DIMENSIONS = { width: 380, height: 600 };
|
|
822
1011
|
function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
823
1012
|
const { ui } = useConfig();
|
|
824
|
-
const [isOpen, setIsOpen] = (0,
|
|
825
|
-
const [hasUnread, setHasUnread] = (0,
|
|
826
|
-
const [dimensions, setDimensions] = (0,
|
|
827
|
-
const [isResizing, setIsResizing] = (0,
|
|
828
|
-
const [isMaximized, setIsMaximized] = (0,
|
|
829
|
-
const [prevDimensions, setPrevDimensions] = (0,
|
|
1013
|
+
const [isOpen, setIsOpen] = (0, import_react9.useState)(false);
|
|
1014
|
+
const [hasUnread, setHasUnread] = (0, import_react9.useState)(false);
|
|
1015
|
+
const [dimensions, setDimensions] = (0, import_react9.useState)(DEFAULT_DIMENSIONS);
|
|
1016
|
+
const [isResizing, setIsResizing] = (0, import_react9.useState)(false);
|
|
1017
|
+
const [isMaximized, setIsMaximized] = (0, import_react9.useState)(false);
|
|
1018
|
+
const [prevDimensions, setPrevDimensions] = (0, import_react9.useState)(DEFAULT_DIMENSIONS);
|
|
830
1019
|
if (ui.showWidget === false) return null;
|
|
831
1020
|
const positionClass = position === "bottom-left" ? "bottom-6 left-6" : "bottom-6 right-6";
|
|
832
1021
|
const windowPositionClass = position === "bottom-left" ? "bottom-20 left-6" : "bottom-20 right-6";
|
|
@@ -876,7 +1065,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
876
1065
|
}
|
|
877
1066
|
};
|
|
878
1067
|
const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
|
|
879
|
-
return /* @__PURE__ */
|
|
1068
|
+
return /* @__PURE__ */ import_react9.default.createElement(import_react9.default.Fragment, null, /* @__PURE__ */ import_react9.default.createElement(
|
|
880
1069
|
"div",
|
|
881
1070
|
{
|
|
882
1071
|
className: `fixed z-[9998] max-w-[calc(100vw-3rem)] ease-in-out ${windowPositionClass} ${isOpen ? "opacity-100 translate-y-0 pointer-events-auto" : "opacity-0 translate-y-4 pointer-events-none"} ${isResizing ? "" : "transition-all duration-300"}`,
|
|
@@ -886,7 +1075,7 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
886
1075
|
maxHeight: "calc(100vh - 6rem)"
|
|
887
1076
|
}
|
|
888
1077
|
},
|
|
889
|
-
/* @__PURE__ */
|
|
1078
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
890
1079
|
ChatWindow,
|
|
891
1080
|
{
|
|
892
1081
|
className: "h-full relative z-10",
|
|
@@ -900,13 +1089,13 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
900
1089
|
onAddToCart
|
|
901
1090
|
}
|
|
902
1091
|
),
|
|
903
|
-
/* @__PURE__ */
|
|
1092
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
904
1093
|
"div",
|
|
905
1094
|
{
|
|
906
1095
|
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"}`
|
|
907
1096
|
}
|
|
908
1097
|
)
|
|
909
|
-
), /* @__PURE__ */
|
|
1098
|
+
), /* @__PURE__ */ import_react9.default.createElement(
|
|
910
1099
|
"button",
|
|
911
1100
|
{
|
|
912
1101
|
onClick: isOpen ? () => setIsOpen(false) : handleOpen,
|
|
@@ -914,32 +1103,32 @@ function ChatWidget({ position = "bottom-right", onAddToCart }) {
|
|
|
914
1103
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}, ${ui.accentColor})` },
|
|
915
1104
|
"aria-label": "Open chat"
|
|
916
1105
|
},
|
|
917
|
-
/* @__PURE__ */
|
|
1106
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
918
1107
|
"span",
|
|
919
1108
|
{
|
|
920
1109
|
className: "absolute inset-0 rounded-full animate-ping opacity-20",
|
|
921
1110
|
style: { background: ui.primaryColor }
|
|
922
1111
|
}
|
|
923
1112
|
),
|
|
924
|
-
/* @__PURE__ */
|
|
1113
|
+
/* @__PURE__ */ import_react9.default.createElement(
|
|
925
1114
|
"span",
|
|
926
1115
|
{
|
|
927
1116
|
className: `transition-transform duration-300 ${isOpen ? "rotate-90 scale-90" : "rotate-0 scale-100"}`
|
|
928
1117
|
},
|
|
929
|
-
isOpen ? /* @__PURE__ */
|
|
1118
|
+
isOpen ? /* @__PURE__ */ import_react9.default.createElement(import_lucide_react6.X, { className: "w-6 h-6 text-white" }) : /* @__PURE__ */ import_react9.default.createElement(import_lucide_react6.MessageSquare, { className: "w-6 h-6 text-white" })
|
|
930
1119
|
),
|
|
931
|
-
hasUnread && !isOpen && /* @__PURE__ */
|
|
1120
|
+
hasUnread && !isOpen && /* @__PURE__ */ import_react9.default.createElement("span", { className: "absolute top-0 right-0 w-4 h-4 bg-rose-500 rounded-full border-2 border-white flex items-center justify-center text-[9px] font-bold text-white" }, "1")
|
|
932
1121
|
));
|
|
933
1122
|
}
|
|
934
1123
|
|
|
935
1124
|
// src/components/DocumentUpload.tsx
|
|
936
|
-
var
|
|
1125
|
+
var import_react10 = __toESM(require("react"));
|
|
937
1126
|
var import_lucide_react7 = require("lucide-react");
|
|
938
1127
|
function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
939
1128
|
const { ui } = useConfig();
|
|
940
|
-
const [fileStates, setFileStates] = (0,
|
|
941
|
-
const [isDragging, setIsDragging] = (0,
|
|
942
|
-
const fileInputRef = (0,
|
|
1129
|
+
const [fileStates, setFileStates] = (0, import_react10.useState)([]);
|
|
1130
|
+
const [isDragging, setIsDragging] = (0, import_react10.useState)(false);
|
|
1131
|
+
const fileInputRef = (0, import_react10.useRef)(null);
|
|
943
1132
|
const addFiles = (files) => {
|
|
944
1133
|
const newStates = files.map((file) => ({ file, status: "idle" }));
|
|
945
1134
|
setFileStates((prev) => [...prev, ...newStates]);
|
|
@@ -989,7 +1178,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
989
1178
|
};
|
|
990
1179
|
const isUploading = fileStates.some((s) => s.status === "uploading");
|
|
991
1180
|
const hasIdle = fileStates.some((s) => s.status === "idle");
|
|
992
|
-
return /* @__PURE__ */
|
|
1181
|
+
return /* @__PURE__ */ import_react10.default.createElement(
|
|
993
1182
|
"div",
|
|
994
1183
|
{
|
|
995
1184
|
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}`,
|
|
@@ -997,14 +1186,14 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
997
1186
|
onDragLeave,
|
|
998
1187
|
onDrop
|
|
999
1188
|
},
|
|
1000
|
-
/* @__PURE__ */
|
|
1189
|
+
/* @__PURE__ */ import_react10.default.createElement("div", { className: "flex flex-col items-center justify-center text-center" }, /* @__PURE__ */ import_react10.default.createElement(
|
|
1001
1190
|
"div",
|
|
1002
1191
|
{
|
|
1003
1192
|
className: "w-12 h-12 rounded-full flex items-center justify-center mb-4 shadow-sm",
|
|
1004
1193
|
style: { background: `linear-gradient(135deg, ${ui.primaryColor}20, ${ui.accentColor}20)` }
|
|
1005
1194
|
},
|
|
1006
|
-
/* @__PURE__ */
|
|
1007
|
-
), /* @__PURE__ */
|
|
1195
|
+
/* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.Upload, { className: "w-6 h-6", style: { color: ui.primaryColor } })
|
|
1196
|
+
), /* @__PURE__ */ import_react10.default.createElement("h3", { className: "text-slate-900 dark:text-white font-semibold mb-1" }, "Upload Documents"), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-sm mb-6 max-w-xs" }, "Drag and drop PDF, DOCX, TXT, or JSON files to train your AI on your own data."), /* @__PURE__ */ import_react10.default.createElement(
|
|
1008
1197
|
"button",
|
|
1009
1198
|
{
|
|
1010
1199
|
onClick: () => {
|
|
@@ -1020,7 +1209,7 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
1020
1209
|
}
|
|
1021
1210
|
},
|
|
1022
1211
|
"Select Files"
|
|
1023
|
-
), /* @__PURE__ */
|
|
1212
|
+
), /* @__PURE__ */ import_react10.default.createElement(
|
|
1024
1213
|
"input",
|
|
1025
1214
|
{
|
|
1026
1215
|
ref: fileInputRef,
|
|
@@ -1031,22 +1220,22 @@ function DocumentUpload({ namespace, onUploadComplete, className = "" }) {
|
|
|
1031
1220
|
accept: ".pdf,.docx,.txt,.md,.json,.csv"
|
|
1032
1221
|
}
|
|
1033
1222
|
)),
|
|
1034
|
-
fileStates.length > 0 && /* @__PURE__ */
|
|
1223
|
+
fileStates.length > 0 && /* @__PURE__ */ import_react10.default.createElement("div", { className: "mt-8 space-y-3" }, fileStates.map((state, i) => /* @__PURE__ */ import_react10.default.createElement(
|
|
1035
1224
|
"div",
|
|
1036
1225
|
{
|
|
1037
1226
|
key: i,
|
|
1038
1227
|
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"
|
|
1039
1228
|
},
|
|
1040
|
-
/* @__PURE__ */
|
|
1041
|
-
/* @__PURE__ */
|
|
1229
|
+
/* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-3 overflow-hidden" }, /* @__PURE__ */ import_react10.default.createElement("div", { className: "w-8 h-8 rounded-lg bg-white dark:bg-white/10 flex items-center justify-center shadow-sm" }, /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.File, { className: "w-4 h-4 text-slate-400" })), /* @__PURE__ */ import_react10.default.createElement("div", { className: "truncate" }, /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-xs font-medium text-slate-700 dark:text-white/80 truncate" }, state.file.name), /* @__PURE__ */ import_react10.default.createElement("p", { className: "text-[10px] text-slate-400" }, (state.file.size / 1024).toFixed(1), " KB"))),
|
|
1230
|
+
/* @__PURE__ */ import_react10.default.createElement("div", { className: "flex items-center gap-2" }, state.status === "uploading" && /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.Loader2, { className: "w-4 h-4 text-slate-400 animate-spin" }), state.status === "success" && /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.CheckCircle, { className: "w-4 h-4 text-emerald-500" }), state.status === "error" && /* @__PURE__ */ import_react10.default.createElement("div", { title: state.error }, /* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.AlertCircle, { className: "w-4 h-4 text-rose-500" })), state.status !== "uploading" && /* @__PURE__ */ import_react10.default.createElement(
|
|
1042
1231
|
"button",
|
|
1043
1232
|
{
|
|
1044
1233
|
onClick: () => removeFile(i),
|
|
1045
1234
|
className: "p-1 rounded-md hover:bg-slate-200 dark:hover:bg-white/10 transition-colors"
|
|
1046
1235
|
},
|
|
1047
|
-
/* @__PURE__ */
|
|
1236
|
+
/* @__PURE__ */ import_react10.default.createElement(import_lucide_react7.X, { className: "w-3.5 h-3.5 text-slate-400" })
|
|
1048
1237
|
))
|
|
1049
|
-
)), hasIdle && !isUploading && /* @__PURE__ */
|
|
1238
|
+
)), hasIdle && !isUploading && /* @__PURE__ */ import_react10.default.createElement(
|
|
1050
1239
|
"button",
|
|
1051
1240
|
{
|
|
1052
1241
|
onClick: uploadFiles,
|