@retrivora-ai/rag-engine 1.0.6 → 1.0.8

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.
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  MongoDBProvider
3
- } from "./chunk-73I6VWU3.mjs";
3
+ } from "./chunk-5AJ4XHLW.mjs";
4
4
  import "./chunk-IMP6FUCY.mjs";
5
5
  import "./chunk-X4TOT24V.mjs";
6
6
  export {
@@ -222,6 +222,8 @@ interface UIConfig {
222
222
  borderRadius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
223
223
  /** Whether to allow file uploads directly from the UI */
224
224
  allowUpload?: boolean;
225
+ /** Whether to allow manual resizing of the chat window. Defaults to true. */
226
+ allowResize?: boolean;
225
227
  }
226
228
  interface RAGConfig {
227
229
  /** Number of top-K chunks retrieved per query */
@@ -222,6 +222,8 @@ interface UIConfig {
222
222
  borderRadius?: 'none' | 'sm' | 'md' | 'lg' | 'xl' | 'full';
223
223
  /** Whether to allow file uploads directly from the UI */
224
224
  allowUpload?: boolean;
225
+ /** Whether to allow manual resizing of the chat window. Defaults to true. */
226
+ allowResize?: boolean;
225
227
  }
226
228
  interface RAGConfig {
227
229
  /** Number of top-K chunks retrieved per query */
@@ -1098,7 +1098,7 @@ var ProviderRegistry = class {
1098
1098
  return PostgreSQLProvider;
1099
1099
  }
1100
1100
  case "mongodb": {
1101
- const { MongoDBProvider } = await import("./MongoDBProvider-BO2Y5DRR.mjs");
1101
+ const { MongoDBProvider } = await import("./MongoDBProvider-YNKC7EJ6.mjs");
1102
1102
  return MongoDBProvider;
1103
1103
  }
1104
1104
  case "milvus": {
@@ -1915,7 +1915,6 @@ var QueryProcessor = class {
1915
1915
  var _a, _b, _c, _d;
1916
1916
  if (!question.trim()) return [];
1917
1917
  const hints = /* @__PURE__ */ new Map();
1918
- const fieldsToSearch = [.../* @__PURE__ */ new Set([...this.COMMON_METADATA_FIELDS, ...validFields])];
1919
1918
  const addHint = (value, field) => {
1920
1919
  const normalizedValue = this.normalizeHintValue(value);
1921
1920
  if (!normalizedValue) return;
@@ -1946,17 +1945,18 @@ var QueryProcessor = class {
1946
1945
  if (name) addHint(name, "name");
1947
1946
  }
1948
1947
  }
1949
- if (fieldsToSearch.length > 0) {
1950
- for (const field of fieldsToSearch) {
1951
- const forwardPattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{2,60})["']?(?=[?.!,]|$)`, "gi");
1952
- for (const match of question.matchAll(forwardPattern)) {
1953
- const value = match[1];
1954
- if (value && !this.isLikelyPromptPhrase(value)) {
1955
- addHint(value, field);
1956
- }
1957
- }
1958
- const reversePattern = new RegExp(`\\b([^"\\n?.!,\\s]{2,60})\\s+${field}\\b`, "gi");
1959
- for (const match of question.matchAll(reversePattern)) {
1948
+ const genericPattern = /\b([a-z][a-z0-9_]{1,30})\s*[:=]\s*["']?([^"'\n?.!,]{1,60})["']?/gi;
1949
+ for (const match of question.matchAll(genericPattern)) {
1950
+ const field = match[1];
1951
+ const value = match[2];
1952
+ if (field && !this.isLikelyPromptPhrase(field)) {
1953
+ addHint(value, field);
1954
+ }
1955
+ }
1956
+ if (validFields.length > 0) {
1957
+ for (const field of validFields) {
1958
+ const pattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{1,60})["']?(?=[?.!,]|$)`, "gi");
1959
+ for (const match of question.matchAll(pattern)) {
1960
1960
  const value = match[1];
1961
1961
  if (value && !this.isLikelyPromptPhrase(value)) {
1962
1962
  addHint(value, field);
@@ -2032,28 +2032,6 @@ var QueryProcessor = class {
2032
2032
  return filter;
2033
2033
  }
2034
2034
  };
2035
- QueryProcessor.COMMON_METADATA_FIELDS = [
2036
- "category",
2037
- "type",
2038
- "brand",
2039
- "status",
2040
- "priority",
2041
- "id",
2042
- "name",
2043
- "email",
2044
- "phone",
2045
- "price",
2046
- "rating",
2047
- "color",
2048
- "size",
2049
- "material",
2050
- "sku",
2051
- "role",
2052
- "department",
2053
- "location",
2054
- "tag",
2055
- "label"
2056
- ];
2057
2035
 
2058
2036
  // src/core/Pipeline.ts
2059
2037
  var LRUEmbeddingCache = class {
@@ -118,6 +118,18 @@ var MongoDBProvider = class extends BaseVectorProvider {
118
118
  }
119
119
  async query(vector, topK, namespace, filter) {
120
120
  const publicFilter = this.sanitizeFilter(filter);
121
+ const vectorSearchFilter = {};
122
+ const matchFilter = {};
123
+ if (namespace) {
124
+ vectorSearchFilter.namespace = namespace;
125
+ }
126
+ for (const [key, value] of Object.entries(publicFilter)) {
127
+ if (key === "namespace") {
128
+ vectorSearchFilter.namespace = value;
129
+ } else {
130
+ matchFilter[key] = value;
131
+ }
132
+ }
121
133
  const pipeline = [
122
134
  {
123
135
  $vectorSearch: __spreadValues({
@@ -125,9 +137,15 @@ var MongoDBProvider = class extends BaseVectorProvider {
125
137
  path: this.embeddingKey,
126
138
  queryVector: vector,
127
139
  numCandidates: this.config.options.numCandidates || Math.max(topK * 20, 200),
128
- limit: topK
129
- }, Object.keys(publicFilter).length > 0 || namespace ? { filter: __spreadValues(__spreadValues({}, publicFilter), namespace ? { namespace } : {}) } : {})
130
- },
140
+ limit: topK * 2
141
+ }, Object.keys(vectorSearchFilter).length > 0 ? { filter: vectorSearchFilter } : {})
142
+ }
143
+ ];
144
+ if (Object.keys(matchFilter).length > 0) {
145
+ pipeline.push({ $match: matchFilter });
146
+ }
147
+ pipeline.push(
148
+ { $limit: topK },
131
149
  {
132
150
  $project: {
133
151
  _id: 1,
@@ -137,7 +155,7 @@ var MongoDBProvider = class extends BaseVectorProvider {
137
155
  score: { $meta: "vectorSearchScore" }
138
156
  }
139
157
  }
140
- ];
158
+ );
141
159
  const results = await this.collection.aggregate(pipeline).toArray();
142
160
  return results.map((res) => ({
143
161
  id: res._id,
@@ -1,3 +1,3 @@
1
- import '../RagConfig-BjC6zSTV.mjs';
2
- export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-CU_fQq__.mjs';
1
+ import '../RagConfig-DVovvPmd.mjs';
2
+ export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-D0_2f-43.mjs';
3
3
  import 'next/server';
@@ -1,3 +1,3 @@
1
- import '../RagConfig-BjC6zSTV.js';
2
- export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-C3bLmWcR.js';
1
+ import '../RagConfig-DVovvPmd.js';
2
+ export { c as createChatHandler, d as createHealthHandler, e as createIngestHandler, f as createStreamHandler, g as createUploadHandler, s as sseErrorFrame, h as sseFrame, i as sseMetaFrame, j as sseTextFrame } from '../index-CQ0zQ7Zk.js';
3
3
  import 'next/server';
@@ -650,6 +650,18 @@ var init_MongoDBProvider = __esm({
650
650
  }
651
651
  async query(vector, topK, namespace, filter) {
652
652
  const publicFilter = this.sanitizeFilter(filter);
653
+ const vectorSearchFilter = {};
654
+ const matchFilter = {};
655
+ if (namespace) {
656
+ vectorSearchFilter.namespace = namespace;
657
+ }
658
+ for (const [key, value] of Object.entries(publicFilter)) {
659
+ if (key === "namespace") {
660
+ vectorSearchFilter.namespace = value;
661
+ } else {
662
+ matchFilter[key] = value;
663
+ }
664
+ }
653
665
  const pipeline = [
654
666
  {
655
667
  $vectorSearch: __spreadValues({
@@ -657,9 +669,15 @@ var init_MongoDBProvider = __esm({
657
669
  path: this.embeddingKey,
658
670
  queryVector: vector,
659
671
  numCandidates: this.config.options.numCandidates || Math.max(topK * 20, 200),
660
- limit: topK
661
- }, Object.keys(publicFilter).length > 0 || namespace ? { filter: __spreadValues(__spreadValues({}, publicFilter), namespace ? { namespace } : {}) } : {})
662
- },
672
+ limit: topK * 2
673
+ }, Object.keys(vectorSearchFilter).length > 0 ? { filter: vectorSearchFilter } : {})
674
+ }
675
+ ];
676
+ if (Object.keys(matchFilter).length > 0) {
677
+ pipeline.push({ $match: matchFilter });
678
+ }
679
+ pipeline.push(
680
+ { $limit: topK },
663
681
  {
664
682
  $project: {
665
683
  _id: 1,
@@ -669,7 +687,7 @@ var init_MongoDBProvider = __esm({
669
687
  score: { $meta: "vectorSearchScore" }
670
688
  }
671
689
  }
672
- ];
690
+ );
673
691
  const results = await this.collection.aggregate(pipeline).toArray();
674
692
  return results.map((res) => ({
675
693
  id: res._id,
@@ -3373,7 +3391,6 @@ var QueryProcessor = class {
3373
3391
  var _a, _b, _c, _d;
3374
3392
  if (!question.trim()) return [];
3375
3393
  const hints = /* @__PURE__ */ new Map();
3376
- const fieldsToSearch = [.../* @__PURE__ */ new Set([...this.COMMON_METADATA_FIELDS, ...validFields])];
3377
3394
  const addHint = (value, field) => {
3378
3395
  const normalizedValue = this.normalizeHintValue(value);
3379
3396
  if (!normalizedValue) return;
@@ -3404,17 +3421,18 @@ var QueryProcessor = class {
3404
3421
  if (name) addHint(name, "name");
3405
3422
  }
3406
3423
  }
3407
- if (fieldsToSearch.length > 0) {
3408
- for (const field of fieldsToSearch) {
3409
- const forwardPattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{2,60})["']?(?=[?.!,]|$)`, "gi");
3410
- for (const match of question.matchAll(forwardPattern)) {
3411
- const value = match[1];
3412
- if (value && !this.isLikelyPromptPhrase(value)) {
3413
- addHint(value, field);
3414
- }
3415
- }
3416
- const reversePattern = new RegExp(`\\b([^"\\n?.!,\\s]{2,60})\\s+${field}\\b`, "gi");
3417
- for (const match of question.matchAll(reversePattern)) {
3424
+ const genericPattern = /\b([a-z][a-z0-9_]{1,30})\s*[:=]\s*["']?([^"'\n?.!,]{1,60})["']?/gi;
3425
+ for (const match of question.matchAll(genericPattern)) {
3426
+ const field = match[1];
3427
+ const value = match[2];
3428
+ if (field && !this.isLikelyPromptPhrase(field)) {
3429
+ addHint(value, field);
3430
+ }
3431
+ }
3432
+ if (validFields.length > 0) {
3433
+ for (const field of validFields) {
3434
+ const pattern = new RegExp(`\\b${field}\\s*(?:is|are|:|of)?\\s+["']?([^"\\n?.!,]{1,60})["']?(?=[?.!,]|$)`, "gi");
3435
+ for (const match of question.matchAll(pattern)) {
3418
3436
  const value = match[1];
3419
3437
  if (value && !this.isLikelyPromptPhrase(value)) {
3420
3438
  addHint(value, field);
@@ -3490,28 +3508,6 @@ var QueryProcessor = class {
3490
3508
  return filter;
3491
3509
  }
3492
3510
  };
3493
- QueryProcessor.COMMON_METADATA_FIELDS = [
3494
- "category",
3495
- "type",
3496
- "brand",
3497
- "status",
3498
- "priority",
3499
- "id",
3500
- "name",
3501
- "email",
3502
- "phone",
3503
- "price",
3504
- "rating",
3505
- "color",
3506
- "size",
3507
- "material",
3508
- "sku",
3509
- "role",
3510
- "department",
3511
- "location",
3512
- "tag",
3513
- "label"
3514
- ];
3515
3511
 
3516
3512
  // src/core/Pipeline.ts
3517
3513
  var LRUEmbeddingCache = class {
@@ -8,7 +8,7 @@ import {
8
8
  sseFrame,
9
9
  sseMetaFrame,
10
10
  sseTextFrame
11
- } from "../chunk-ZCDJSGUW.mjs";
11
+ } from "../chunk-3GKA3PJF.mjs";
12
12
  import "../chunk-YLTMFW4M.mjs";
13
13
  import "../chunk-X4TOT24V.mjs";
14
14
  export {
@@ -1,4 +1,4 @@
1
- import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-BjC6zSTV.js';
1
+ import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-DVovvPmd.js';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
4
  interface ValidationError {
@@ -1,4 +1,4 @@
1
- import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-BjC6zSTV.mjs';
1
+ import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-DVovvPmd.mjs';
2
2
  import { NextRequest, NextResponse } from 'next/server';
3
3
 
4
4
  interface ValidationError {
package/dist/index.d.mts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React$1, { ReactNode } from 'react';
2
- import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-BjC6zSTV.mjs';
3
- export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-BjC6zSTV.mjs';
2
+ import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-DVovvPmd.mjs';
3
+ export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-DVovvPmd.mjs';
4
4
  export { C as Chunk, a as ChunkOptions } from './DocumentChunker-Dh9TvmGG.mjs';
5
5
 
6
6
  interface ChatWidgetProps {
@@ -18,8 +18,18 @@ interface ChatWindowProps {
18
18
  onClose?: () => void;
19
19
  /** Whether to show a close (X) button in the header */
20
20
  showClose?: boolean;
21
+ /** Called when the user starts dragging the resize handle */
22
+ onResizeStart?: (e: React$1.MouseEvent) => void;
23
+ /** Called when the user clicks the reset size button */
24
+ onResetResize?: () => void;
25
+ /** Whether the window has been resized from its default */
26
+ isResized?: boolean;
27
+ /** Called when the user clicks the maximize/minimize button */
28
+ onMaximize?: () => void;
29
+ /** Whether the window is currently maximized */
30
+ isMaximized?: boolean;
21
31
  }
22
- declare function ChatWindow({ className, style, onClose, showClose }: ChatWindowProps): React$1.JSX.Element;
32
+ declare function ChatWindow({ className, style, onClose, showClose, onResizeStart, onResetResize, isResized, onMaximize, isMaximized }: ChatWindowProps): React$1.JSX.Element;
23
33
 
24
34
  interface DocumentUploadProps {
25
35
  /** Optional namespace for the upload */
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
1
  import React$1, { ReactNode } from 'react';
2
- import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-BjC6zSTV.js';
3
- export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-BjC6zSTV.js';
2
+ import { C as ChatMessage, V as VectorMatch, U as UIConfig } from './RagConfig-DVovvPmd.js';
3
+ export { a as ChatOptions, b as ChatResponse, E as EmbedOptions, c as EmbeddingConfig, d as EmbeddingProvider, I as ILLMProvider, e as IngestDocument, L as LLMConfig, f as LLMProvider, R as RAGConfig, g as RagConfig, h as UpsertDocument, i as VectorDBConfig, j as VectorDBProvider } from './RagConfig-DVovvPmd.js';
4
4
  export { C as Chunk, a as ChunkOptions } from './DocumentChunker-Dh9TvmGG.js';
5
5
 
6
6
  interface ChatWidgetProps {
@@ -18,8 +18,18 @@ interface ChatWindowProps {
18
18
  onClose?: () => void;
19
19
  /** Whether to show a close (X) button in the header */
20
20
  showClose?: boolean;
21
+ /** Called when the user starts dragging the resize handle */
22
+ onResizeStart?: (e: React$1.MouseEvent) => void;
23
+ /** Called when the user clicks the reset size button */
24
+ onResetResize?: () => void;
25
+ /** Whether the window has been resized from its default */
26
+ isResized?: boolean;
27
+ /** Called when the user clicks the maximize/minimize button */
28
+ onMaximize?: () => void;
29
+ /** Whether the window is currently maximized */
30
+ isMaximized?: boolean;
21
31
  }
22
- declare function ChatWindow({ className, style, onClose, showClose }: ChatWindowProps): React$1.JSX.Element;
32
+ declare function ChatWindow({ className, style, onClose, showClose, onResizeStart, onResetResize, isResized, onMaximize, isMaximized }: ChatWindowProps): React$1.JSX.Element;
23
33
 
24
34
  interface DocumentUploadProps {
25
35
  /** Optional namespace for the upload */
package/dist/index.js CHANGED
@@ -166,7 +166,8 @@ var defaultConfig = {
166
166
  poweredBy: "RAG",
167
167
  visualStyle: "glass",
168
168
  borderRadius: "xl",
169
- allowUpload: true
169
+ allowUpload: true,
170
+ allowResize: true
170
171
  }
171
172
  };
172
173
  var ConfigContext = (0, import_react3.createContext)(defaultConfig);
@@ -390,7 +391,17 @@ var CHAT_SUGGESTIONS = [
390
391
  ];
391
392
 
392
393
  // src/components/ChatWindow.tsx
393
- function ChatWindow({ className = "", style, onClose, showClose = false }) {
394
+ function ChatWindow({
395
+ className = "",
396
+ style,
397
+ onClose,
398
+ showClose = false,
399
+ onResizeStart,
400
+ onResetResize,
401
+ isResized = false,
402
+ onMaximize,
403
+ isMaximized = false
404
+ }) {
394
405
  var _a;
395
406
  const { ui, projectId } = useConfig();
396
407
  const [input, setInput] = (0, import_react5.useState)("");
@@ -434,9 +445,18 @@ function ChatWindow({ className = "", style, onClose, showClose = false }) {
434
445
  return /* @__PURE__ */ import_react5.default.createElement(
435
446
  "div",
436
447
  {
437
- 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}`,
448
+ 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}`,
438
449
  style: __spreadValues({ "--primary": ui.primaryColor, "--accent": ui.accentColor }, style)
439
450
  },
451
+ onResizeStart && /* @__PURE__ */ import_react5.default.createElement(
452
+ "div",
453
+ {
454
+ onMouseDown: onResizeStart,
455
+ className: "absolute top-0 left-0 w-6 h-6 cursor-nw-resize z-[100] group flex items-start justify-start p-1",
456
+ title: "Drag to resize"
457
+ },
458
+ /* @__PURE__ */ import_react5.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]" })
459
+ ),
440
460
  /* @__PURE__ */ import_react5.default.createElement(
441
461
  "div",
442
462
  {
@@ -454,23 +474,39 @@ function ChatWindow({ className = "", style, onClose, showClose = false }) {
454
474
  },
455
475
  /* @__PURE__ */ import_react5.default.createElement(import_lucide_react3.Bot, { className: "w-5 h-5 text-white" })
456
476
  ), /* @__PURE__ */ import_react5.default.createElement("div", null, /* @__PURE__ */ import_react5.default.createElement("h2", { className: "text-slate-900 dark:text-white font-semibold text-sm leading-tight" }, ui.title), ui.poweredBy && /* @__PURE__ */ import_react5.default.createElement("p", { className: "text-slate-500 dark:text-white/40 text-[11px] leading-tight" }, `Powered by ${ui.poweredBy}`))),
457
- /* @__PURE__ */ import_react5.default.createElement("div", { className: "flex items-center gap-2" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400" }, /* @__PURE__ */ import_react5.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_react5.default.createElement(
477
+ /* @__PURE__ */ import_react5.default.createElement("div", { className: "flex items-center gap-1.5" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "flex items-center gap-1 text-[10px] text-emerald-500 dark:text-emerald-400 mr-2" }, /* @__PURE__ */ import_react5.default.createElement("span", { className: "w-1.5 h-1.5 rounded-full bg-emerald-500 dark:bg-emerald-400 animate-pulse" }), "Online"), /* @__PURE__ */ import_react5.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_react5.default.createElement(
458
478
  "button",
459
479
  {
460
480
  onClick: clearHistory,
461
481
  title: "Clear conversation",
462
- 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"
482
+ 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"
463
483
  },
464
484
  /* @__PURE__ */ import_react5.default.createElement(import_lucide_react3.Trash2, { className: "w-3.5 h-3.5" })
485
+ ), isResized && onResetResize && /* @__PURE__ */ import_react5.default.createElement(
486
+ "button",
487
+ {
488
+ onClick: onResetResize,
489
+ title: "Reset to default size",
490
+ 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"
491
+ },
492
+ /* @__PURE__ */ import_react5.default.createElement(import_lucide_react3.RotateCcw, { className: "w-3.5 h-3.5" })
493
+ ), onMaximize && /* @__PURE__ */ import_react5.default.createElement(
494
+ "button",
495
+ {
496
+ onClick: onMaximize,
497
+ title: isMaximized ? "Minimize" : "Maximize",
498
+ 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"
499
+ },
500
+ isMaximized ? /* @__PURE__ */ import_react5.default.createElement(import_lucide_react3.Minimize2, { className: "w-3.5 h-3.5" }) : /* @__PURE__ */ import_react5.default.createElement(import_lucide_react3.Maximize2, { className: "w-3.5 h-3.5" })
465
501
  ), showClose && onClose && /* @__PURE__ */ import_react5.default.createElement(
466
502
  "button",
467
503
  {
468
504
  onClick: onClose,
469
505
  title: "Close chat",
470
- 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"
506
+ 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"
471
507
  },
472
508
  /* @__PURE__ */ import_react5.default.createElement(import_lucide_react3.X, { className: "w-4 h-4" })
473
- ))
509
+ )))
474
510
  ),
475
511
  /* @__PURE__ */ import_react5.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 ? (
476
512
  /* Welcome state */
@@ -545,10 +581,15 @@ function ChatWindow({ className = "", style, onClose, showClose = false }) {
545
581
  }
546
582
 
547
583
  // src/components/ChatWidget.tsx
584
+ var DEFAULT_DIMENSIONS = { width: 380, height: 600 };
548
585
  function ChatWidget({ position = "bottom-right" }) {
549
586
  const { ui } = useConfig();
550
587
  const [isOpen, setIsOpen] = (0, import_react6.useState)(false);
551
588
  const [hasUnread, setHasUnread] = (0, import_react6.useState)(false);
589
+ const [dimensions, setDimensions] = (0, import_react6.useState)(DEFAULT_DIMENSIONS);
590
+ const [isResizing, setIsResizing] = (0, import_react6.useState)(false);
591
+ const [isMaximized, setIsMaximized] = (0, import_react6.useState)(false);
592
+ const [prevDimensions, setPrevDimensions] = (0, import_react6.useState)(DEFAULT_DIMENSIONS);
552
593
  if (ui.showWidget === false) return null;
553
594
  const positionClass = position === "bottom-left" ? "bottom-6 left-6" : "bottom-6 right-6";
554
595
  const windowPositionClass = position === "bottom-left" ? "bottom-20 left-6" : "bottom-20 right-6";
@@ -557,18 +598,68 @@ function ChatWidget({ position = "bottom-right" }) {
557
598
  setIsOpen(true);
558
599
  setHasUnread(false);
559
600
  };
601
+ const handleResizeStart = (e) => {
602
+ e.preventDefault();
603
+ setIsResizing(true);
604
+ const startX = e.clientX;
605
+ const startY = e.clientY;
606
+ const startWidth = dimensions.width;
607
+ const startHeight = dimensions.height;
608
+ const onMouseMove = (moveEvent) => {
609
+ const deltaX = startX - moveEvent.clientX;
610
+ const deltaY = startY - moveEvent.clientY;
611
+ setDimensions({
612
+ width: Math.max(320, Math.min(startWidth + deltaX, window.innerWidth - 48)),
613
+ height: Math.max(400, Math.min(startHeight + deltaY, window.innerHeight - 100))
614
+ });
615
+ };
616
+ const onMouseUp = () => {
617
+ setIsResizing(false);
618
+ window.removeEventListener("mousemove", onMouseMove);
619
+ window.removeEventListener("mouseup", onMouseUp);
620
+ };
621
+ window.addEventListener("mousemove", onMouseMove);
622
+ window.addEventListener("mouseup", onMouseUp);
623
+ };
624
+ const handleResetResize = () => {
625
+ setDimensions(DEFAULT_DIMENSIONS);
626
+ setIsMaximized(false);
627
+ };
628
+ const handleMaximize = () => {
629
+ if (isMaximized) {
630
+ setDimensions(prevDimensions);
631
+ setIsMaximized(false);
632
+ } else {
633
+ setPrevDimensions(dimensions);
634
+ setDimensions({
635
+ width: Math.min(800, window.innerWidth - 48),
636
+ height: Math.min(800, window.innerHeight - 100)
637
+ });
638
+ setIsMaximized(true);
639
+ }
640
+ };
641
+ const isResized = dimensions.width !== DEFAULT_DIMENSIONS.width || dimensions.height !== DEFAULT_DIMENSIONS.height;
560
642
  return /* @__PURE__ */ import_react6.default.createElement(import_react6.default.Fragment, null, /* @__PURE__ */ import_react6.default.createElement(
561
643
  "div",
562
644
  {
563
- 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"}`,
564
- style: { height: "600px", maxHeight: "calc(100vh - 6rem)" }
645
+ 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"}`,
646
+ style: {
647
+ width: `${dimensions.width}px`,
648
+ height: `${dimensions.height}px`,
649
+ maxHeight: "calc(100vh - 6rem)"
650
+ }
565
651
  },
566
652
  /* @__PURE__ */ import_react6.default.createElement(
567
653
  ChatWindow,
568
654
  {
569
655
  className: "h-full relative z-10",
570
656
  showClose: true,
571
- onClose: () => setIsOpen(false)
657
+ onClose: () => setIsOpen(false),
658
+ onResizeStart: ui.allowResize !== false ? handleResizeStart : void 0,
659
+ onResetResize: ui.allowResize !== false ? handleResetResize : void 0,
660
+ isResized,
661
+ onMaximize: ui.allowResize !== false ? handleMaximize : void 0,
662
+ isMaximized
572
663
  }
573
664
  ),
574
665
  /* @__PURE__ */ import_react6.default.createElement(