@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.
- package/dist/{MongoDBProvider-BO2Y5DRR.mjs → MongoDBProvider-YNKC7EJ6.mjs} +1 -1
- package/dist/{RagConfig-BjC6zSTV.d.mts → RagConfig-DVovvPmd.d.mts} +2 -0
- package/dist/{RagConfig-BjC6zSTV.d.ts → RagConfig-DVovvPmd.d.ts} +2 -0
- package/dist/{chunk-ZCDJSGUW.mjs → chunk-3GKA3PJF.mjs} +13 -35
- package/dist/{chunk-73I6VWU3.mjs → chunk-5AJ4XHLW.mjs} +22 -4
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +34 -38
- package/dist/handlers/index.mjs +1 -1
- package/dist/{index-C3bLmWcR.d.ts → index-CQ0zQ7Zk.d.ts} +1 -1
- package/dist/{index-CU_fQq__.d.mts → index-D0_2f-43.d.mts} +1 -1
- package/dist/index.d.mts +13 -3
- package/dist/index.d.ts +13 -3
- package/dist/index.js +101 -10
- package/dist/index.mjs +105 -11
- package/dist/server.d.mts +3 -3
- package/dist/server.d.ts +3 -3
- package/dist/server.js +34 -38
- package/dist/server.mjs +2 -2
- package/package.json +1 -1
- package/src/components/ChatWidget.tsx +67 -3
- package/src/components/ChatWindow.tsx +77 -22
- package/src/components/ConfigProvider.tsx +1 -0
- package/src/config/RagConfig.ts +2 -0
- package/src/core/QueryProcessor.ts +15 -20
- package/src/providers/vectordb/MongoDBProvider.ts +32 -6
|
@@ -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-
|
|
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
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1956
|
-
|
|
1957
|
-
|
|
1958
|
-
|
|
1959
|
-
|
|
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(
|
|
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-
|
|
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-
|
|
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';
|
package/dist/handlers/index.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import '../RagConfig-
|
|
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-
|
|
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';
|
package/dist/handlers/index.js
CHANGED
|
@@ -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(
|
|
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
|
-
|
|
3408
|
-
|
|
3409
|
-
|
|
3410
|
-
|
|
3411
|
-
|
|
3412
|
-
|
|
3413
|
-
|
|
3414
|
-
|
|
3415
|
-
|
|
3416
|
-
|
|
3417
|
-
|
|
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 {
|
package/dist/handlers/index.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as RagConfig, C as ChatMessage, b as ChatResponse, e as IngestDocument } from './RagConfig-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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-
|
|
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({
|
|
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-
|
|
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-
|
|
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-
|
|
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]
|
|
564
|
-
style: {
|
|
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(
|