@retrivora-ai/rag-engine 1.9.6 → 1.9.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/README.md +130 -113
- package/dist/{ILLMProvider-DNhyOYoK.d.mts → ILLMProvider-B8ROITYK.d.mts} +59 -8
- package/dist/{ILLMProvider-DNhyOYoK.d.ts → ILLMProvider-B8ROITYK.d.ts} +59 -8
- package/dist/handlers/index.d.mts +2 -2
- package/dist/handlers/index.d.ts +2 -2
- package/dist/handlers/index.js +2376 -489
- package/dist/handlers/index.mjs +2372 -489
- package/dist/{index-CjQdL0cX.d.ts → index-B8PbEFSY.d.mts} +17 -3
- package/dist/{index-CHL1jdYm.d.mts → index-BCPKUAVL.d.ts} +33 -41
- package/dist/{index-Hgbwl9X4.d.ts → index-CrxCy36A.d.mts} +33 -41
- package/dist/{index-C9v7-tWd.d.mts → index-DNvoi-sV.d.ts} +17 -3
- package/dist/index.css +695 -203
- package/dist/index.d.mts +37 -7
- package/dist/index.d.ts +37 -7
- package/dist/index.js +1197 -286
- package/dist/index.mjs +1221 -297
- package/dist/server.d.mts +62 -6
- package/dist/server.d.ts +62 -6
- package/dist/server.js +2526 -574
- package/dist/server.mjs +2517 -573
- package/package.json +12 -10
- package/src/app/constants.tsx +207 -212
- package/src/app/layout.tsx +4 -28
- package/src/app/types.ts +17 -17
- package/src/components/AmbientBackground.tsx +10 -10
- package/src/components/ArchitectureCard.tsx +43 -7
- package/src/components/ArchitectureCardsSection.tsx +37 -4
- package/src/components/ChatWidget.tsx +4 -1
- package/src/components/ChatWindow.tsx +9 -2
- package/src/components/CodeViewer.tsx +19 -14
- package/src/components/DocViewer.tsx +75 -15
- package/src/components/Documentation.tsx +111 -28
- package/src/components/Hero.tsx +103 -20
- package/src/components/Lifecycle.tsx +65 -25
- package/src/components/MarkdownComponents.tsx +44 -1
- package/src/components/MessageBubble.tsx +162 -50
- package/src/components/constants.tsx +279 -0
- package/src/config/RagConfig.ts +56 -10
- package/src/config/constants.ts +5 -0
- package/src/config/serverConfig.ts +15 -0
- package/src/core/ConfigResolver.ts +30 -25
- package/src/core/DatabaseStorage.ts +469 -0
- package/src/core/LicenseVerifier.ts +154 -0
- package/src/core/MultiAgentCoordinator.ts +239 -0
- package/src/core/Pipeline.ts +148 -16
- package/src/core/ProviderRegistry.ts +5 -5
- package/src/core/Retrivora.ts +52 -6
- package/src/core/VectorPlugin.ts +74 -11
- package/src/core/mcp.ts +261 -0
- package/src/exceptions/index.ts +52 -0
- package/src/handlers/index.ts +504 -47
- package/src/hooks/useRagChat.ts +100 -43
- package/src/hooks/useStoredMessages.ts +15 -4
- package/src/index.ts +7 -0
- package/src/llm/LLMFactory.ts +15 -6
- package/src/llm/providers/GroqProvider.ts +176 -0
- package/src/llm/providers/QwenProvider.ts +191 -0
- package/src/server.ts +23 -13
- package/src/types/chat.ts +16 -0
- package/src/types/props.ts +50 -1
- package/.env.example +0 -80
- package/LICENSE.txt +0 -21
package/dist/server.js
CHANGED
|
@@ -10,9 +10,6 @@ var __getProtoOf = Object.getPrototypeOf;
|
|
|
10
10
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
11
11
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
12
12
|
var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
|
|
13
|
-
var __typeError = (msg) => {
|
|
14
|
-
throw TypeError(msg);
|
|
15
|
-
};
|
|
16
13
|
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
|
|
17
14
|
var __spreadValues = (a, b) => {
|
|
18
15
|
for (var prop in b || (b = {}))
|
|
@@ -77,43 +74,15 @@ var __asyncGenerator = (__this, __arguments, generator) => {
|
|
|
77
74
|
}, method = (k, call, wait, clear) => it[k] = (x) => (call = new Promise((yes, no, run) => (run = () => resume(k, x, yes, no), q ? q.then(run) : run())), clear = () => q === wait && (q = 0), q = wait = call.then(clear, clear), call), q, it = {};
|
|
78
75
|
return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it;
|
|
79
76
|
};
|
|
80
|
-
var __yieldStar = (value) => {
|
|
81
|
-
var obj = value[__knownSymbol("asyncIterator")], isAwait = false, method, it = {};
|
|
82
|
-
if (obj == null) {
|
|
83
|
-
obj = value[__knownSymbol("iterator")]();
|
|
84
|
-
method = (k) => it[k] = (x) => obj[k](x);
|
|
85
|
-
} else {
|
|
86
|
-
obj = obj.call(value);
|
|
87
|
-
method = (k) => it[k] = (v) => {
|
|
88
|
-
if (isAwait) {
|
|
89
|
-
isAwait = false;
|
|
90
|
-
if (k === "throw") throw v;
|
|
91
|
-
return v;
|
|
92
|
-
}
|
|
93
|
-
isAwait = true;
|
|
94
|
-
return {
|
|
95
|
-
done: false,
|
|
96
|
-
value: new __await(new Promise((resolve) => {
|
|
97
|
-
var x = obj[k](v);
|
|
98
|
-
if (!(x instanceof Object)) __typeError("Object expected");
|
|
99
|
-
resolve(x);
|
|
100
|
-
}), 1)
|
|
101
|
-
};
|
|
102
|
-
};
|
|
103
|
-
}
|
|
104
|
-
return it[__knownSymbol("iterator")] = () => it, method("next"), "throw" in obj ? method("throw") : it.throw = (x) => {
|
|
105
|
-
throw x;
|
|
106
|
-
}, "return" in obj && method("return"), it;
|
|
107
|
-
};
|
|
108
77
|
var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")]) ? it.call(obj) : (obj = obj[__knownSymbol("iterator")](), it = {}, method = (key, fn) => (fn = obj[key]) && (it[key] = (arg) => new Promise((yes, no, done) => (arg = fn.call(obj, arg), done = arg.done, Promise.resolve(arg.value).then((value) => yes({ value, done }), no)))), method("next"), method("return"), it);
|
|
109
78
|
|
|
110
79
|
// src/utils/templateUtils.ts
|
|
111
80
|
function isRecord(value) {
|
|
112
81
|
return typeof value === "object" && value !== null;
|
|
113
82
|
}
|
|
114
|
-
function resolvePath(obj,
|
|
115
|
-
if (!
|
|
116
|
-
return
|
|
83
|
+
function resolvePath(obj, path2) {
|
|
84
|
+
if (!path2 || !obj) return void 0;
|
|
85
|
+
return path2.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
|
|
117
86
|
if (!isRecord(current) && !Array.isArray(current)) {
|
|
118
87
|
return void 0;
|
|
119
88
|
}
|
|
@@ -223,7 +192,7 @@ var init_PineconeProvider = __esm({
|
|
|
223
192
|
static getHealthChecker() {
|
|
224
193
|
return {
|
|
225
194
|
async check(config) {
|
|
226
|
-
var
|
|
195
|
+
var _a2, _b;
|
|
227
196
|
const opts = config.options || {};
|
|
228
197
|
const indexName = config.indexName;
|
|
229
198
|
const timestamp = Date.now();
|
|
@@ -231,7 +200,7 @@ var init_PineconeProvider = __esm({
|
|
|
231
200
|
const { Pinecone: Pinecone2 } = await import("@pinecone-database/pinecone");
|
|
232
201
|
const client = new Pinecone2({ apiKey: opts.apiKey });
|
|
233
202
|
const indexes = await client.listIndexes();
|
|
234
|
-
const indexNames = (_b = (
|
|
203
|
+
const indexNames = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
|
|
235
204
|
if (!indexNames.includes(indexName)) {
|
|
236
205
|
return {
|
|
237
206
|
healthy: false,
|
|
@@ -258,10 +227,10 @@ var init_PineconeProvider = __esm({
|
|
|
258
227
|
};
|
|
259
228
|
}
|
|
260
229
|
async initialize() {
|
|
261
|
-
var
|
|
230
|
+
var _a2, _b;
|
|
262
231
|
this.client = new import_pinecone.Pinecone({ apiKey: this.apiKey });
|
|
263
232
|
const indexes = await this.client.listIndexes();
|
|
264
|
-
const names = (_b = (
|
|
233
|
+
const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
|
|
265
234
|
if (!names.includes(this.indexName)) {
|
|
266
235
|
throw new Error(
|
|
267
236
|
`[PineconeProvider] Index "${this.indexName}" not found. Available: ${names.join(", ")}`
|
|
@@ -273,12 +242,12 @@ var init_PineconeProvider = __esm({
|
|
|
273
242
|
return namespace ? idx.namespace(namespace) : idx.namespace("");
|
|
274
243
|
}
|
|
275
244
|
async upsert(doc, namespace) {
|
|
276
|
-
var
|
|
245
|
+
var _a2;
|
|
277
246
|
await this.index(namespace).upsert({
|
|
278
247
|
records: [{
|
|
279
248
|
id: String(doc.id),
|
|
280
249
|
values: doc.vector,
|
|
281
|
-
metadata: __spreadValues({ content: doc.content }, (
|
|
250
|
+
metadata: __spreadValues({ content: doc.content }, (_a2 = doc.metadata) != null ? _a2 : {})
|
|
282
251
|
}]
|
|
283
252
|
});
|
|
284
253
|
}
|
|
@@ -286,29 +255,29 @@ var init_PineconeProvider = __esm({
|
|
|
286
255
|
const BATCH = 100;
|
|
287
256
|
for (let i = 0; i < docs.length; i += BATCH) {
|
|
288
257
|
const records = docs.slice(i, i + BATCH).map((d) => {
|
|
289
|
-
var
|
|
258
|
+
var _a2;
|
|
290
259
|
return {
|
|
291
260
|
id: String(d.id),
|
|
292
261
|
values: d.vector,
|
|
293
|
-
metadata: __spreadValues({ content: d.content }, (
|
|
262
|
+
metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
|
|
294
263
|
};
|
|
295
264
|
});
|
|
296
265
|
await this.index(namespace).upsert({ records });
|
|
297
266
|
}
|
|
298
267
|
}
|
|
299
268
|
async query(vector, topK, namespace, filter) {
|
|
300
|
-
var
|
|
269
|
+
var _a2;
|
|
301
270
|
const pineconeFilter = this.sanitizeFilter(filter);
|
|
302
271
|
const result = await this.index(namespace).query(__spreadValues({
|
|
303
272
|
vector,
|
|
304
273
|
topK,
|
|
305
274
|
includeMetadata: true
|
|
306
275
|
}, Object.keys(pineconeFilter).length > 0 ? { filter: pineconeFilter } : {}));
|
|
307
|
-
return ((
|
|
308
|
-
var
|
|
276
|
+
return ((_a2 = result.matches) != null ? _a2 : []).map((m) => {
|
|
277
|
+
var _a3, _b;
|
|
309
278
|
return {
|
|
310
279
|
id: m.id,
|
|
311
|
-
score: (
|
|
280
|
+
score: (_a3 = m.score) != null ? _a3 : 0,
|
|
312
281
|
content: ((_b = m.metadata) == null ? void 0 : _b.content) || "",
|
|
313
282
|
metadata: m.metadata
|
|
314
283
|
};
|
|
@@ -347,13 +316,13 @@ var init_PostgreSQLProvider = __esm({
|
|
|
347
316
|
init_BaseVectorProvider();
|
|
348
317
|
PostgreSQLProvider = class extends BaseVectorProvider {
|
|
349
318
|
constructor(config) {
|
|
350
|
-
var
|
|
319
|
+
var _a2;
|
|
351
320
|
super(config);
|
|
352
321
|
this.tableName = this.indexName.replace(/[^a-z0-9_]/gi, "_");
|
|
353
322
|
const opts = config.options;
|
|
354
323
|
if (!opts.connectionString) throw new Error("[PostgreSQLProvider] options.connectionString is required");
|
|
355
324
|
this.connectionString = opts.connectionString;
|
|
356
|
-
this.dimensions = (
|
|
325
|
+
this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 1536;
|
|
357
326
|
}
|
|
358
327
|
static getValidator() {
|
|
359
328
|
return {
|
|
@@ -434,7 +403,7 @@ var init_PostgreSQLProvider = __esm({
|
|
|
434
403
|
}
|
|
435
404
|
}
|
|
436
405
|
async upsert(doc, namespace = "") {
|
|
437
|
-
var
|
|
406
|
+
var _a2;
|
|
438
407
|
const vectorLiteral = `[${doc.vector.join(",")}]`;
|
|
439
408
|
await this.pool.query(
|
|
440
409
|
`INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
|
|
@@ -444,7 +413,7 @@ var init_PostgreSQLProvider = __esm({
|
|
|
444
413
|
content = EXCLUDED.content,
|
|
445
414
|
metadata = EXCLUDED.metadata,
|
|
446
415
|
embedding = EXCLUDED.embedding`,
|
|
447
|
-
[doc.id, namespace, doc.content, JSON.stringify((
|
|
416
|
+
[doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), vectorLiteral]
|
|
448
417
|
);
|
|
449
418
|
}
|
|
450
419
|
async batchUpsert(docs, namespace = "") {
|
|
@@ -457,9 +426,9 @@ var init_PostgreSQLProvider = __esm({
|
|
|
457
426
|
const batch = docs.slice(i, i + BATCH_SIZE);
|
|
458
427
|
const values = [];
|
|
459
428
|
const valuePlaceholders = batch.map((doc, idx) => {
|
|
460
|
-
var
|
|
429
|
+
var _a2;
|
|
461
430
|
const offset = idx * 5;
|
|
462
|
-
values.push(doc.id, namespace, doc.content, JSON.stringify((
|
|
431
|
+
values.push(doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), `[${doc.vector.join(",")}]`);
|
|
463
432
|
return `($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}::vector)`;
|
|
464
433
|
}).join(", ");
|
|
465
434
|
const query = `
|
|
@@ -542,8 +511,8 @@ var init_PostgreSQLProvider = __esm({
|
|
|
542
511
|
|
|
543
512
|
// src/utils/synonyms.ts
|
|
544
513
|
function resolveMetadataValue(meta, uiKey) {
|
|
545
|
-
var
|
|
546
|
-
const synonyms = (
|
|
514
|
+
var _a2;
|
|
515
|
+
const synonyms = (_a2 = FIELD_SYNONYMS[uiKey]) != null ? _a2 : [];
|
|
547
516
|
const keys = Object.keys(meta);
|
|
548
517
|
const systemKeys = ["namespace", "filename", "filesize", "filetype", "docid", "uploadedat", "dimension", "chunkindex"];
|
|
549
518
|
let match = keys.find((k) => k.toLowerCase() === uiKey.toLowerCase());
|
|
@@ -630,14 +599,14 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
630
599
|
init_synonyms();
|
|
631
600
|
MultiTablePostgresProvider = class extends BaseVectorProvider {
|
|
632
601
|
constructor(config) {
|
|
633
|
-
var
|
|
602
|
+
var _a2, _b, _c;
|
|
634
603
|
super(config);
|
|
635
604
|
const opts = config.options || {};
|
|
636
605
|
if (!opts.connectionString) {
|
|
637
606
|
throw new Error("[MultiTablePostgresProvider] options.connectionString is required");
|
|
638
607
|
}
|
|
639
608
|
this.connectionString = opts.connectionString;
|
|
640
|
-
this.dimensions = (
|
|
609
|
+
this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 768;
|
|
641
610
|
this.tables = [];
|
|
642
611
|
const rawSearchFields = (_c = (_b = opts.searchFields) != null ? _b : process.env.VECTOR_DB_SEARCH_FIELDS) != null ? _c : ["name", "product_name", "productname", "title"];
|
|
643
612
|
this.searchFields = typeof rawSearchFields === "string" ? rawSearchFields.split(",").map((f) => f.trim()).filter(Boolean) : rawSearchFields;
|
|
@@ -695,11 +664,11 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
695
664
|
* Batch upsert documents by dynamically provisioning tables and columns based on CSV headers.
|
|
696
665
|
*/
|
|
697
666
|
async batchUpsert(docs, namespace = "") {
|
|
698
|
-
var
|
|
667
|
+
var _a2;
|
|
699
668
|
if (docs.length === 0) return;
|
|
700
669
|
const docsByFile = {};
|
|
701
670
|
for (const doc of docs) {
|
|
702
|
-
const fileName = ((
|
|
671
|
+
const fileName = ((_a2 = doc.metadata) == null ? void 0 : _a2.fileName) || this.uploadTable;
|
|
703
672
|
if (!docsByFile[fileName]) docsByFile[fileName] = [];
|
|
704
673
|
docsByFile[fileName].push(doc);
|
|
705
674
|
}
|
|
@@ -752,11 +721,11 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
752
721
|
const headerColumns = csvHeaders.map((h) => `"${h}"`).join(", ");
|
|
753
722
|
const allColumns = `id, ${headerColumns ? headerColumns + ", " : ""}namespace, content, metadata, embedding`;
|
|
754
723
|
const valuePlaceholders = batch.map((doc, idx) => {
|
|
755
|
-
var
|
|
724
|
+
var _a3, _b;
|
|
756
725
|
const offset = idx * (5 + csvHeaders.length);
|
|
757
726
|
values.push(doc.id);
|
|
758
727
|
for (const h of csvHeaders) {
|
|
759
|
-
values.push(String(((
|
|
728
|
+
values.push(String(((_a3 = doc.metadata) == null ? void 0 : _a3[h]) || ""));
|
|
760
729
|
}
|
|
761
730
|
values.push(namespace, doc.content, JSON.stringify((_b = doc.metadata) != null ? _b : {}), `[${doc.vector.join(",")}]`);
|
|
762
731
|
const docPlaceholders = [];
|
|
@@ -795,7 +764,7 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
795
764
|
* Query all configured tables and merge results, sorted by cosine similarity score.
|
|
796
765
|
*/
|
|
797
766
|
async query(vector, topK, _namespace, _filter) {
|
|
798
|
-
var
|
|
767
|
+
var _a2;
|
|
799
768
|
if (!this.pool) {
|
|
800
769
|
throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
|
|
801
770
|
}
|
|
@@ -826,11 +795,11 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
826
795
|
const filterParams = [];
|
|
827
796
|
if (metadataFilters && Object.keys(metadataFilters).length > 0) {
|
|
828
797
|
const conditions = Object.entries(metadataFilters).map(([key, val]) => {
|
|
829
|
-
var
|
|
798
|
+
var _a4;
|
|
830
799
|
filterParams.push(String(val));
|
|
831
800
|
const baseOffset = queryText && dynamicKeywordQuery ? 2 : 1;
|
|
832
801
|
const paramIdx = baseOffset + filterParams.length;
|
|
833
|
-
const synonyms = (
|
|
802
|
+
const synonyms = (_a4 = FIELD_SYNONYMS[key]) != null ? _a4 : [];
|
|
834
803
|
const keysToCheck = [key, ...synonyms];
|
|
835
804
|
const coalesceExprs = keysToCheck.flatMap((k) => [
|
|
836
805
|
`metadata->>'${k}'`,
|
|
@@ -899,7 +868,7 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
899
868
|
}
|
|
900
869
|
const tableResults = [];
|
|
901
870
|
for (const row of result.rows) {
|
|
902
|
-
const
|
|
871
|
+
const _a3 = row, { hybrid_score, id } = _a3, rest = __objRest(_a3, ["hybrid_score", "id"]);
|
|
903
872
|
delete rest.embedding;
|
|
904
873
|
delete rest.vector_score;
|
|
905
874
|
delete rest.keyword_score;
|
|
@@ -928,10 +897,10 @@ var init_MultiTablePostgresProvider = __esm({
|
|
|
928
897
|
}
|
|
929
898
|
allResults.sort((a, b) => b.score - a.score);
|
|
930
899
|
if (allResults.length === 0) return [];
|
|
931
|
-
const bestMatchTable = (
|
|
900
|
+
const bestMatchTable = (_a2 = allResults[0].metadata) == null ? void 0 : _a2.source_table;
|
|
932
901
|
const finalSorted = allResults.filter((res) => {
|
|
933
|
-
var
|
|
934
|
-
return ((
|
|
902
|
+
var _a3;
|
|
903
|
+
return ((_a3 = res.metadata) == null ? void 0 : _a3.source_table) === bestMatchTable;
|
|
935
904
|
});
|
|
936
905
|
console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
|
|
937
906
|
console.log(`[MultiTablePostgresProvider] Final top match from "${bestMatchTable}" with score ${finalSorted[0].score.toFixed(4)}`);
|
|
@@ -1336,14 +1305,14 @@ var init_QdrantProvider = __esm({
|
|
|
1336
1305
|
* Samples points from the collection to discover available payload fields.
|
|
1337
1306
|
*/
|
|
1338
1307
|
async discoverSchema() {
|
|
1339
|
-
var
|
|
1308
|
+
var _a2;
|
|
1340
1309
|
try {
|
|
1341
1310
|
const { data } = await this.http.post(`/collections/${this.indexName}/points/scroll`, {
|
|
1342
1311
|
limit: 20,
|
|
1343
1312
|
with_payload: true,
|
|
1344
1313
|
with_vector: false
|
|
1345
1314
|
});
|
|
1346
|
-
const points = ((
|
|
1315
|
+
const points = ((_a2 = data.result) == null ? void 0 : _a2.points) || [];
|
|
1347
1316
|
const keys = /* @__PURE__ */ new Set();
|
|
1348
1317
|
for (const point of points) {
|
|
1349
1318
|
const payload = point.payload || {};
|
|
@@ -1369,12 +1338,12 @@ var init_QdrantProvider = __esm({
|
|
|
1369
1338
|
* Ensures the collection exists. Creates it if missing.
|
|
1370
1339
|
*/
|
|
1371
1340
|
async ensureCollection() {
|
|
1372
|
-
var
|
|
1341
|
+
var _a2;
|
|
1373
1342
|
try {
|
|
1374
1343
|
await this.http.get(`/collections/${this.indexName}`);
|
|
1375
1344
|
console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
|
|
1376
1345
|
} catch (err) {
|
|
1377
|
-
if (import_axios4.default.isAxiosError(err) && ((
|
|
1346
|
+
if (import_axios4.default.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
|
|
1378
1347
|
const opts = this.config.options;
|
|
1379
1348
|
const dimensionsForCreate = opts.dimensions || 1536;
|
|
1380
1349
|
console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
|
|
@@ -1394,7 +1363,7 @@ var init_QdrantProvider = __esm({
|
|
|
1394
1363
|
* Ensures that a payload field has an index.
|
|
1395
1364
|
*/
|
|
1396
1365
|
async ensureIndex(fieldName, schema = "keyword") {
|
|
1397
|
-
var
|
|
1366
|
+
var _a2;
|
|
1398
1367
|
let fullPath = fieldName;
|
|
1399
1368
|
if (!this.isFlatPayload && !fieldName.includes(".") && fieldName !== "namespace" && fieldName !== this.contentField) {
|
|
1400
1369
|
fullPath = `${this.metadataField}.${fieldName}`;
|
|
@@ -1407,7 +1376,7 @@ var init_QdrantProvider = __esm({
|
|
|
1407
1376
|
console.log(`[QdrantProvider] \u2705 Ensured ${schema} index for "${fullPath}"`);
|
|
1408
1377
|
} catch (err) {
|
|
1409
1378
|
let status;
|
|
1410
|
-
if (import_axios4.default.isAxiosError(err)) status = (
|
|
1379
|
+
if (import_axios4.default.isAxiosError(err)) status = (_a2 = err.response) == null ? void 0 : _a2.status;
|
|
1411
1380
|
if (status === 409) return;
|
|
1412
1381
|
console.warn(`[QdrantProvider] \u26A0\uFE0F Could not ensure index for "${fullPath}":`, err instanceof Error ? err.message : String(err));
|
|
1413
1382
|
}
|
|
@@ -1436,7 +1405,7 @@ var init_QdrantProvider = __esm({
|
|
|
1436
1405
|
await this.http.put(`/collections/${this.indexName}/points`, payload);
|
|
1437
1406
|
}
|
|
1438
1407
|
async query(vector, topK, namespace, _filter) {
|
|
1439
|
-
var
|
|
1408
|
+
var _a2;
|
|
1440
1409
|
const must = [];
|
|
1441
1410
|
if (namespace) {
|
|
1442
1411
|
must.push({ key: "namespace", match: { value: namespace } });
|
|
@@ -1458,7 +1427,7 @@ var init_QdrantProvider = __esm({
|
|
|
1458
1427
|
limit: topK,
|
|
1459
1428
|
with_payload: true,
|
|
1460
1429
|
params: {
|
|
1461
|
-
hnsw_ef: ((
|
|
1430
|
+
hnsw_ef: ((_a2 = this.config.options) == null ? void 0 : _a2.efSearch) || Math.max(topK * 20, 128),
|
|
1462
1431
|
exact: false
|
|
1463
1432
|
},
|
|
1464
1433
|
filter: must.length > 0 ? { must } : void 0
|
|
@@ -1553,13 +1522,13 @@ var init_ChromaDBProvider = __esm({
|
|
|
1553
1522
|
* Get or create the ChromaDB collection.
|
|
1554
1523
|
*/
|
|
1555
1524
|
async initialize() {
|
|
1556
|
-
var
|
|
1525
|
+
var _a2;
|
|
1557
1526
|
try {
|
|
1558
1527
|
const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
|
|
1559
1528
|
this.collectionId = data.id;
|
|
1560
1529
|
console.log(`[ChromaDBProvider] \u2705 Collection "${this.indexName}" found (id: ${this.collectionId})`);
|
|
1561
1530
|
} catch (err) {
|
|
1562
|
-
if (import_axios5.default.isAxiosError(err) && ((
|
|
1531
|
+
if (import_axios5.default.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
|
|
1563
1532
|
console.log(`[ChromaDBProvider] \u23F3 Collection "${this.indexName}" not found. Creating...`);
|
|
1564
1533
|
const { data } = await this.http.post("/api/v1/collections", {
|
|
1565
1534
|
name: this.indexName
|
|
@@ -1780,7 +1749,7 @@ var init_WeaviateProvider = __esm({
|
|
|
1780
1749
|
await this.http.post("/v1/batch/objects", payload);
|
|
1781
1750
|
}
|
|
1782
1751
|
async query(vector, topK, namespace, _filter) {
|
|
1783
|
-
var
|
|
1752
|
+
var _a2, _b;
|
|
1784
1753
|
const queryText = _filter == null ? void 0 : _filter.queryText;
|
|
1785
1754
|
const sanitizedFilter = this.sanitizeFilter(_filter);
|
|
1786
1755
|
const searchParams = queryText ? `hybrid: { query: ${JSON.stringify(queryText)}, alpha: 0.5 }` : `nearVector: { vector: ${JSON.stringify(vector)} }`;
|
|
@@ -1806,7 +1775,7 @@ var init_WeaviateProvider = __esm({
|
|
|
1806
1775
|
`
|
|
1807
1776
|
};
|
|
1808
1777
|
const { data } = await this.http.post("/v1/graphql", graphqlQuery);
|
|
1809
|
-
const results = ((_b = (
|
|
1778
|
+
const results = ((_b = (_a2 = data.data) == null ? void 0 : _a2.Get) == null ? void 0 : _b[this.indexName]) || [];
|
|
1810
1779
|
return results.map((res) => ({
|
|
1811
1780
|
id: res["_additional"].id,
|
|
1812
1781
|
score: 1 - res["_additional"].distance,
|
|
@@ -1859,10 +1828,10 @@ var init_WeaviateProvider = __esm({
|
|
|
1859
1828
|
return `{ operator: And, operands: [${operands.join(", ")}] }`;
|
|
1860
1829
|
}
|
|
1861
1830
|
weaviateOperand(key, value) {
|
|
1862
|
-
const
|
|
1863
|
-
if (typeof value === "number") return `{ ${
|
|
1864
|
-
if (typeof value === "boolean") return `{ ${
|
|
1865
|
-
return `{ ${
|
|
1831
|
+
const path2 = `path: [${JSON.stringify(key)}], operator: Equal`;
|
|
1832
|
+
if (typeof value === "number") return `{ ${path2}, valueNumber: ${value} }`;
|
|
1833
|
+
if (typeof value === "boolean") return `{ ${path2}, valueBoolean: ${value} }`;
|
|
1834
|
+
return `{ ${path2}, valueString: ${JSON.stringify(value)} }`;
|
|
1866
1835
|
}
|
|
1867
1836
|
};
|
|
1868
1837
|
}
|
|
@@ -1889,21 +1858,21 @@ var init_UniversalVectorProvider = __esm({
|
|
|
1889
1858
|
}
|
|
1890
1859
|
}
|
|
1891
1860
|
async initialize() {
|
|
1892
|
-
var
|
|
1861
|
+
var _a2;
|
|
1893
1862
|
this.http = import_axios8.default.create({
|
|
1894
1863
|
baseURL: this.opts.baseUrl,
|
|
1895
1864
|
headers: __spreadValues({
|
|
1896
1865
|
"Content-Type": "application/json"
|
|
1897
1866
|
}, this.opts.headers),
|
|
1898
|
-
timeout: (
|
|
1867
|
+
timeout: (_a2 = this.opts.timeout) != null ? _a2 : 3e4
|
|
1899
1868
|
});
|
|
1900
1869
|
if (!await this.ping()) {
|
|
1901
1870
|
throw new Error(`[UniversalVectorProvider] Failed to connect to ${this.opts.baseUrl}`);
|
|
1902
1871
|
}
|
|
1903
1872
|
}
|
|
1904
1873
|
async upsert(doc, namespace) {
|
|
1905
|
-
var
|
|
1906
|
-
const endpoint = (
|
|
1874
|
+
var _a2, _b, _c;
|
|
1875
|
+
const endpoint = (_a2 = this.opts.upsertEndpoint) != null ? _a2 : "/upsert";
|
|
1907
1876
|
const template = (_b = this.opts.upsertTemplate) != null ? _b : JSON.stringify({
|
|
1908
1877
|
id: "{{id}}",
|
|
1909
1878
|
vector: "{{vector}}",
|
|
@@ -1936,8 +1905,8 @@ var init_UniversalVectorProvider = __esm({
|
|
|
1936
1905
|
}
|
|
1937
1906
|
}
|
|
1938
1907
|
async query(vector, topK, namespace, filter) {
|
|
1939
|
-
var
|
|
1940
|
-
const endpoint = (
|
|
1908
|
+
var _a2, _b;
|
|
1909
|
+
const endpoint = (_a2 = this.opts.queryEndpoint) != null ? _a2 : "/query";
|
|
1941
1910
|
const template = (_b = this.opts.queryTemplate) != null ? _b : JSON.stringify({
|
|
1942
1911
|
vector: "{{vector}}",
|
|
1943
1912
|
limit: "{{topK}}",
|
|
@@ -1963,12 +1932,12 @@ var init_UniversalVectorProvider = __esm({
|
|
|
1963
1932
|
);
|
|
1964
1933
|
}
|
|
1965
1934
|
return results.map((item) => {
|
|
1966
|
-
var
|
|
1935
|
+
var _a3, _b2, _c, _d, _e, _f, _g2;
|
|
1967
1936
|
return {
|
|
1968
|
-
id: item[(
|
|
1937
|
+
id: item[(_a3 = this.opts.queryIdField) != null ? _a3 : "id"],
|
|
1969
1938
|
score: (_c = item[(_b2 = this.opts.queryScoreField) != null ? _b2 : "score"]) != null ? _c : 0,
|
|
1970
1939
|
content: (_e = item[(_d = this.opts.queryContentField) != null ? _d : "content"]) != null ? _e : "",
|
|
1971
|
-
metadata: (
|
|
1940
|
+
metadata: (_g2 = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g2 : {}
|
|
1972
1941
|
};
|
|
1973
1942
|
});
|
|
1974
1943
|
} catch (error) {
|
|
@@ -1978,8 +1947,8 @@ var init_UniversalVectorProvider = __esm({
|
|
|
1978
1947
|
}
|
|
1979
1948
|
}
|
|
1980
1949
|
async delete(id, namespace) {
|
|
1981
|
-
var
|
|
1982
|
-
const endpoint = (
|
|
1950
|
+
var _a2, _b;
|
|
1951
|
+
const endpoint = (_a2 = this.opts.deleteEndpoint) != null ? _a2 : "/delete";
|
|
1983
1952
|
const template = (_b = this.opts.deleteTemplate) != null ? _b : JSON.stringify({
|
|
1984
1953
|
id: "{{id}}",
|
|
1985
1954
|
namespace: "{{namespace}}"
|
|
@@ -1997,8 +1966,8 @@ var init_UniversalVectorProvider = __esm({
|
|
|
1997
1966
|
}
|
|
1998
1967
|
}
|
|
1999
1968
|
async deleteNamespace(namespace) {
|
|
2000
|
-
var
|
|
2001
|
-
const endpoint = (
|
|
1969
|
+
var _a2;
|
|
1970
|
+
const endpoint = (_a2 = this.opts.deleteNamespaceEndpoint) != null ? _a2 : "/delete-namespace";
|
|
2002
1971
|
try {
|
|
2003
1972
|
await this.http.post(endpoint, { namespace });
|
|
2004
1973
|
} catch (error) {
|
|
@@ -2008,9 +1977,9 @@ var init_UniversalVectorProvider = __esm({
|
|
|
2008
1977
|
}
|
|
2009
1978
|
}
|
|
2010
1979
|
async ping() {
|
|
2011
|
-
var
|
|
1980
|
+
var _a2;
|
|
2012
1981
|
try {
|
|
2013
|
-
const endpoint = (
|
|
1982
|
+
const endpoint = (_a2 = this.opts.pingEndpoint) != null ? _a2 : "/health";
|
|
2014
1983
|
const response = await this.http.get(endpoint, { timeout: 5e3 });
|
|
2015
1984
|
return response.status >= 200 && response.status < 300;
|
|
2016
1985
|
} catch (e) {
|
|
@@ -2115,8 +2084,10 @@ __export(server_exports, {
|
|
|
2115
2084
|
EmbeddingFailedException: () => EmbeddingFailedException,
|
|
2116
2085
|
EmbeddingStrategy: () => EmbeddingStrategy,
|
|
2117
2086
|
EmbeddingStrategyResolver: () => EmbeddingStrategyResolver,
|
|
2087
|
+
GroqProvider: () => GroqProvider,
|
|
2118
2088
|
LLMFactory: () => LLMFactory,
|
|
2119
2089
|
LLM_PROFILES: () => LLM_PROFILES,
|
|
2090
|
+
LicenseVerifier: () => LicenseVerifier,
|
|
2120
2091
|
MilvusProvider: () => MilvusProvider,
|
|
2121
2092
|
MongoDBProvider: () => MongoDBProvider,
|
|
2122
2093
|
MultiTablePostgresProvider: () => MultiTablePostgresProvider,
|
|
@@ -2130,6 +2101,7 @@ __export(server_exports, {
|
|
|
2130
2101
|
ProviderNotFoundException: () => ProviderNotFoundException,
|
|
2131
2102
|
ProviderRegistry: () => ProviderRegistry,
|
|
2132
2103
|
QdrantProvider: () => QdrantProvider,
|
|
2104
|
+
QwenProvider: () => QwenProvider,
|
|
2133
2105
|
RateLimitException: () => RateLimitException,
|
|
2134
2106
|
RedisProvider: () => RedisProvider,
|
|
2135
2107
|
RetrievalException: () => RetrievalException,
|
|
@@ -2141,16 +2113,21 @@ __export(server_exports, {
|
|
|
2141
2113
|
VectorPlugin: () => VectorPlugin,
|
|
2142
2114
|
WeaviateProvider: () => WeaviateProvider,
|
|
2143
2115
|
createChatHandler: () => createChatHandler,
|
|
2116
|
+
createFeedbackHandler: () => createFeedbackHandler,
|
|
2144
2117
|
createFromPreset: () => createFromPreset,
|
|
2145
2118
|
createHealthHandler: () => createHealthHandler,
|
|
2119
|
+
createHistoryHandler: () => createHistoryHandler,
|
|
2146
2120
|
createIngestHandler: () => createIngestHandler,
|
|
2121
|
+
createRagHandler: () => createRagHandler,
|
|
2122
|
+
createSessionsHandler: () => createSessionsHandler,
|
|
2147
2123
|
createStreamHandler: () => createStreamHandler,
|
|
2148
2124
|
createUploadHandler: () => createUploadHandler,
|
|
2149
2125
|
getRagConfig: () => getRagConfig,
|
|
2150
2126
|
sseErrorFrame: () => sseErrorFrame,
|
|
2151
2127
|
sseFrame: () => sseFrame,
|
|
2152
2128
|
sseMetaFrame: () => sseMetaFrame,
|
|
2153
|
-
sseTextFrame: () => sseTextFrame
|
|
2129
|
+
sseTextFrame: () => sseTextFrame,
|
|
2130
|
+
wrapError: () => wrapError
|
|
2154
2131
|
});
|
|
2155
2132
|
module.exports = __toCommonJS(server_exports);
|
|
2156
2133
|
|
|
@@ -2177,6 +2154,8 @@ var LLM_PROVIDERS = [
|
|
|
2177
2154
|
"anthropic",
|
|
2178
2155
|
"ollama",
|
|
2179
2156
|
"gemini",
|
|
2157
|
+
"groq",
|
|
2158
|
+
"qwen",
|
|
2180
2159
|
"rest",
|
|
2181
2160
|
"universal_rest",
|
|
2182
2161
|
"custom"
|
|
@@ -2185,6 +2164,7 @@ var EMBEDDING_PROVIDERS = [
|
|
|
2185
2164
|
"openai",
|
|
2186
2165
|
"ollama",
|
|
2187
2166
|
"gemini",
|
|
2167
|
+
"qwen",
|
|
2188
2168
|
"rest",
|
|
2189
2169
|
"universal_rest",
|
|
2190
2170
|
"custom"
|
|
@@ -2193,6 +2173,7 @@ var PROVIDERS_WITH_EMBEDDINGS = [
|
|
|
2193
2173
|
"openai",
|
|
2194
2174
|
"ollama",
|
|
2195
2175
|
"gemini",
|
|
2176
|
+
"qwen",
|
|
2196
2177
|
"rest",
|
|
2197
2178
|
"universal_rest"
|
|
2198
2179
|
];
|
|
@@ -2200,8 +2181,8 @@ var UI_BORDER_RADIUS_OPTIONS = ["none", "sm", "md", "lg", "xl", "full"];
|
|
|
2200
2181
|
|
|
2201
2182
|
// src/config/serverConfig.ts
|
|
2202
2183
|
function readString(env, name) {
|
|
2203
|
-
var
|
|
2204
|
-
const value = (
|
|
2184
|
+
var _a2;
|
|
2185
|
+
const value = (_a2 = env[name]) == null ? void 0 : _a2.trim();
|
|
2205
2186
|
return value ? value : void 0;
|
|
2206
2187
|
}
|
|
2207
2188
|
function readNumber(env, name, fallback) {
|
|
@@ -2214,8 +2195,8 @@ function readNumber(env, name, fallback) {
|
|
|
2214
2195
|
return parsed;
|
|
2215
2196
|
}
|
|
2216
2197
|
function readEnum(env, name, fallback, allowed) {
|
|
2217
|
-
var
|
|
2218
|
-
const value = (
|
|
2198
|
+
var _a2;
|
|
2199
|
+
const value = (_a2 = readString(env, name)) != null ? _a2 : fallback;
|
|
2219
2200
|
if (allowed.includes(value)) {
|
|
2220
2201
|
return value;
|
|
2221
2202
|
}
|
|
@@ -2225,15 +2206,15 @@ function getRagConfig(baseConfig, env = process.env) {
|
|
|
2225
2206
|
return getEnvConfig(env, baseConfig);
|
|
2226
2207
|
}
|
|
2227
2208
|
function getEnvConfig(env = process.env, base) {
|
|
2228
|
-
var
|
|
2229
|
-
const projectId = (_c = (_b = (
|
|
2209
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa;
|
|
2210
|
+
const projectId = (_c = (_b = (_a2 = readString(env, "RAG_PROJECT_ID")) != null ? _a2 : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : base == null ? void 0 : base.projectId) != null ? _c : "__default__";
|
|
2230
2211
|
const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
|
|
2231
2212
|
const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
|
|
2232
2213
|
const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
|
|
2233
2214
|
const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
|
|
2234
2215
|
const vectorDbOptions = {};
|
|
2235
2216
|
if (vectorProvider === "pinecone") {
|
|
2236
|
-
vectorDbOptions.apiKey = (
|
|
2217
|
+
vectorDbOptions.apiKey = (_g2 = (_f = readString(env, "PINECONE_API_KEY")) != null ? _f : (_e = (_d = base == null ? void 0 : base.vectorDb) == null ? void 0 : _d.options) == null ? void 0 : _e.apiKey) != null ? _g2 : "";
|
|
2237
2218
|
vectorDbOptions.indexName = (_l = (_i = readString(env, "PINECONE_INDEX")) != null ? _i : (_h = base == null ? void 0 : base.vectorDb) == null ? void 0 : _h.indexName) != null ? _l : (_k = (_j = base == null ? void 0 : base.vectorDb) == null ? void 0 : _j.options) == null ? void 0 : _k.indexName;
|
|
2238
2219
|
} else if (vectorProvider === "pgvector" || vectorProvider === "postgresql") {
|
|
2239
2220
|
vectorDbOptions.connectionString = (_q = (_p = (_m = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _m : readString(env, "POSTGRES_URL")) != null ? _p : (_o = (_n = base == null ? void 0 : base.vectorDb) == null ? void 0 : _n.options) == null ? void 0 : _o.connectionString) != null ? _q : "";
|
|
@@ -2295,17 +2276,18 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2295
2276
|
rest: "default",
|
|
2296
2277
|
custom: "default"
|
|
2297
2278
|
};
|
|
2298
|
-
return __spreadValues({
|
|
2279
|
+
return __spreadProps(__spreadValues({
|
|
2299
2280
|
projectId,
|
|
2281
|
+
licenseKey: (_ha = (_ga = readString(env, "RETRIVORA_LICENSE_KEY")) != null ? _ga : readString(env, "LICENSE_KEY")) != null ? _ha : base == null ? void 0 : base.licenseKey,
|
|
2300
2282
|
vectorDb: {
|
|
2301
2283
|
provider: vectorProvider,
|
|
2302
|
-
indexName: (
|
|
2284
|
+
indexName: (_ja = (_ia = readString(env, "VECTOR_DB_INDEX")) != null ? _ia : vectorDbOptions.indexName) != null ? _ja : "rag-index",
|
|
2303
2285
|
options: vectorDbOptions
|
|
2304
2286
|
},
|
|
2305
2287
|
llm: {
|
|
2306
2288
|
provider: llmProvider,
|
|
2307
|
-
model: (
|
|
2308
|
-
apiKey: (
|
|
2289
|
+
model: (_la = (_ka = readString(env, "LLM_MODEL")) != null ? _ka : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _la : "gpt-4o",
|
|
2290
|
+
apiKey: (_ma = llmApiKeyByProvider[llmProvider]) != null ? _ma : "",
|
|
2309
2291
|
baseUrl: readString(env, "LLM_BASE_URL"),
|
|
2310
2292
|
systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
|
|
2311
2293
|
maxTokens: readNumber(env, "LLM_MAX_TOKENS", 4096),
|
|
@@ -2318,7 +2300,7 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2318
2300
|
},
|
|
2319
2301
|
embedding: {
|
|
2320
2302
|
provider: embeddingProvider,
|
|
2321
|
-
model: (
|
|
2303
|
+
model: (_na = readString(env, "EMBEDDING_MODEL")) != null ? _na : "text-embedding-3-small",
|
|
2322
2304
|
apiKey: embeddingApiKeyByProvider[embeddingProvider],
|
|
2323
2305
|
baseUrl: readString(env, "EMBEDDING_BASE_URL"),
|
|
2324
2306
|
dimensions: embeddingDimensions,
|
|
@@ -2329,30 +2311,30 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2329
2311
|
}
|
|
2330
2312
|
},
|
|
2331
2313
|
ui: {
|
|
2332
|
-
title: (
|
|
2333
|
-
subtitle: (
|
|
2334
|
-
primaryColor: (
|
|
2335
|
-
accentColor: (
|
|
2336
|
-
logoUrl: (
|
|
2337
|
-
placeholder: (
|
|
2338
|
-
showSources: ((
|
|
2339
|
-
welcomeMessage: (
|
|
2340
|
-
visualStyle: (
|
|
2341
|
-
borderRadius: (
|
|
2342
|
-
allowUpload: ((
|
|
2314
|
+
title: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _oa : readString(env, "UI_TITLE")) != null ? _pa : "AI Assistant",
|
|
2315
|
+
subtitle: (_ra = (_qa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _qa : readString(env, "UI_SUBTITLE")) != null ? _ra : "Powered by RAG",
|
|
2316
|
+
primaryColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _sa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ta : "#10b981",
|
|
2317
|
+
accentColor: (_va = (_ua = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _ua : readString(env, "UI_ACCENT_COLOR")) != null ? _va : "#3b82f6",
|
|
2318
|
+
logoUrl: (_wa = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _wa : readString(env, "UI_LOGO_URL"),
|
|
2319
|
+
placeholder: (_ya = (_xa = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _xa : readString(env, "UI_PLACEHOLDER")) != null ? _ya : "Ask me anything\u2026",
|
|
2320
|
+
showSources: ((_Aa = (_za = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _za : readString(env, "UI_SHOW_SOURCES")) != null ? _Aa : "true") !== "false",
|
|
2321
|
+
welcomeMessage: (_Ca = (_Ba = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _Ba : readString(env, "UI_WELCOME_MESSAGE")) != null ? _Ca : "Hello! I'm your AI assistant. Ask me anything about your documents.",
|
|
2322
|
+
visualStyle: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Da : readString(env, "UI_VISUAL_STYLE")) != null ? _Ea : "glass",
|
|
2323
|
+
borderRadius: (_Ga = (_Fa = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Fa : readString(env, "UI_BORDER_RADIUS")) != null ? _Ga : "xl",
|
|
2324
|
+
allowUpload: ((_Ia = (_Ha = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Ha : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ia : "false") === "true"
|
|
2343
2325
|
},
|
|
2344
2326
|
rag: {
|
|
2345
2327
|
topK: readNumber(env, "RAG_TOP_K", 5),
|
|
2346
2328
|
scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
|
|
2347
2329
|
chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
|
|
2348
2330
|
chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200),
|
|
2349
|
-
filterableFields: (
|
|
2331
|
+
filterableFields: (_Ja = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ja.split(",").map((f) => f.trim()),
|
|
2350
2332
|
// Query pipeline toggles — read from .env.local
|
|
2351
2333
|
useQueryTransformation: readString(env, "RAG_USE_QUERY_TRANSFORMATION") === "true",
|
|
2352
2334
|
useReranking: readString(env, "RAG_USE_RERANKING") === "true",
|
|
2353
2335
|
useGraphRetrieval: readString(env, "RAG_USE_GRAPH_RETRIEVAL") === "true",
|
|
2354
|
-
architecture: (
|
|
2355
|
-
chunkingStrategy: (
|
|
2336
|
+
architecture: (_Ka = readString(env, "RAG_ARCHITECTURE")) != null ? _Ka : "simple",
|
|
2337
|
+
chunkingStrategy: (_La = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _La : "recursive",
|
|
2356
2338
|
uiMapping: (() => {
|
|
2357
2339
|
const raw = readString(env, "RAG_UI_MAPPING");
|
|
2358
2340
|
if (!raw) return void 0;
|
|
@@ -2362,6 +2344,10 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2362
2344
|
return void 0;
|
|
2363
2345
|
}
|
|
2364
2346
|
})()
|
|
2347
|
+
},
|
|
2348
|
+
telemetry: {
|
|
2349
|
+
enabled: readString(env, "TELEMETRY_ENABLED") === "true" || readString(env, "NEXT_PUBLIC_TELEMETRY_ENABLED") === "true" || ((_Ma = base == null ? void 0 : base.telemetry) == null ? void 0 : _Ma.enabled) || false,
|
|
2350
|
+
url: (_Qa = (_Pa = (_Na = readString(env, "TELEMETRY_URL")) != null ? _Na : readString(env, "NEXT_PUBLIC_TELEMETRY_URL")) != null ? _Pa : (_Oa = base == null ? void 0 : base.telemetry) == null ? void 0 : _Oa.url) != null ? _Qa : "/api/telemetry"
|
|
2365
2351
|
}
|
|
2366
2352
|
}, readString(env, "GRAPH_DB_PROVIDER") ? {
|
|
2367
2353
|
graphDb: {
|
|
@@ -2372,49 +2358,21 @@ function getEnvConfig(env = process.env, base) {
|
|
|
2372
2358
|
password: readString(env, "GRAPH_DB_PASSWORD")
|
|
2373
2359
|
}
|
|
2374
2360
|
}
|
|
2375
|
-
} : {})
|
|
2361
|
+
} : {}), {
|
|
2362
|
+
mcpServers: (() => {
|
|
2363
|
+
var _a3;
|
|
2364
|
+
const raw = (_a3 = readString(env, "MCP_SERVERS")) != null ? _a3 : readString(env, "NEXT_PUBLIC_MCP_SERVERS");
|
|
2365
|
+
if (!raw) return void 0;
|
|
2366
|
+
try {
|
|
2367
|
+
return JSON.parse(raw);
|
|
2368
|
+
} catch (e) {
|
|
2369
|
+
console.warn("[serverConfig] Failed to parse MCP_SERVERS env:", e);
|
|
2370
|
+
return void 0;
|
|
2371
|
+
}
|
|
2372
|
+
})()
|
|
2373
|
+
});
|
|
2376
2374
|
}
|
|
2377
2375
|
|
|
2378
|
-
// src/exceptions/index.ts
|
|
2379
|
-
var RetrivoraError = class extends Error {
|
|
2380
|
-
constructor(message, code, details) {
|
|
2381
|
-
super(message);
|
|
2382
|
-
this.name = new.target.name;
|
|
2383
|
-
this.code = code;
|
|
2384
|
-
this.details = details;
|
|
2385
|
-
}
|
|
2386
|
-
};
|
|
2387
|
-
var ProviderNotFoundException = class extends RetrivoraError {
|
|
2388
|
-
constructor(providerType, provider, details) {
|
|
2389
|
-
super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
|
|
2390
|
-
}
|
|
2391
|
-
};
|
|
2392
|
-
var EmbeddingFailedException = class extends RetrivoraError {
|
|
2393
|
-
constructor(message = "Embedding generation failed", details) {
|
|
2394
|
-
super(message, "EMBEDDING_FAILED", details);
|
|
2395
|
-
}
|
|
2396
|
-
};
|
|
2397
|
-
var RetrievalException = class extends RetrivoraError {
|
|
2398
|
-
constructor(message = "Retrieval failed", details) {
|
|
2399
|
-
super(message, "RETRIEVAL_FAILED", details);
|
|
2400
|
-
}
|
|
2401
|
-
};
|
|
2402
|
-
var RateLimitException = class extends RetrivoraError {
|
|
2403
|
-
constructor(message = "Provider rate limit exceeded", details) {
|
|
2404
|
-
super(message, "RATE_LIMITED", details);
|
|
2405
|
-
}
|
|
2406
|
-
};
|
|
2407
|
-
var ConfigurationException = class extends RetrivoraError {
|
|
2408
|
-
constructor(message, details) {
|
|
2409
|
-
super(message, "CONFIGURATION_ERROR", details);
|
|
2410
|
-
}
|
|
2411
|
-
};
|
|
2412
|
-
var AuthenticationException = class extends RetrivoraError {
|
|
2413
|
-
constructor(message = "Provider authentication failed", details) {
|
|
2414
|
-
super(message, "AUTHENTICATION_ERROR", details);
|
|
2415
|
-
}
|
|
2416
|
-
};
|
|
2417
|
-
|
|
2418
2376
|
// src/core/ConfigResolver.ts
|
|
2419
2377
|
var ConfigResolver = class {
|
|
2420
2378
|
/**
|
|
@@ -2438,7 +2396,8 @@ var ConfigResolver = class {
|
|
|
2438
2396
|
options: __spreadValues(__spreadValues({}, envConfig.embedding.options || {}), hostConfig.embedding.options || {})
|
|
2439
2397
|
}) : envConfig.embedding,
|
|
2440
2398
|
ui: hostConfig.ui ? mergeDefined(envConfig.ui, hostConfig.ui) : envConfig.ui,
|
|
2441
|
-
rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag
|
|
2399
|
+
rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag,
|
|
2400
|
+
telemetry: hostConfig.telemetry ? __spreadValues(__spreadValues({}, envConfig.telemetry), hostConfig.telemetry) : envConfig.telemetry
|
|
2442
2401
|
});
|
|
2443
2402
|
}
|
|
2444
2403
|
/**
|
|
@@ -2447,10 +2406,10 @@ var ConfigResolver = class {
|
|
|
2447
2406
|
* fallback behavior.
|
|
2448
2407
|
*/
|
|
2449
2408
|
static resolveUniversal(hostConfig, env = process.env) {
|
|
2450
|
-
var
|
|
2409
|
+
var _a2;
|
|
2451
2410
|
if (!hostConfig) return this.resolve(void 0, env);
|
|
2452
2411
|
const normalized = __spreadProps(__spreadValues({}, hostConfig), {
|
|
2453
|
-
vectorDb: (
|
|
2412
|
+
vectorDb: (_a2 = hostConfig.vectorDb) != null ? _a2 : hostConfig.vectorDatabase,
|
|
2454
2413
|
rag: this.mergeRetrievalWorkflow(hostConfig.rag, hostConfig.retrieval, hostConfig.workflow)
|
|
2455
2414
|
});
|
|
2456
2415
|
return this.resolve(normalized, env);
|
|
@@ -2460,21 +2419,21 @@ var ConfigResolver = class {
|
|
|
2460
2419
|
*/
|
|
2461
2420
|
static validate(config) {
|
|
2462
2421
|
if (!config.projectId) {
|
|
2463
|
-
throw new
|
|
2422
|
+
throw new Error("[ConfigResolver] projectId is required");
|
|
2464
2423
|
}
|
|
2465
2424
|
if (!config.vectorDb.provider) {
|
|
2466
|
-
throw new
|
|
2425
|
+
throw new Error("[ConfigResolver] vectorDb.provider is required");
|
|
2467
2426
|
}
|
|
2468
2427
|
if (!config.llm.provider) {
|
|
2469
|
-
throw new
|
|
2428
|
+
throw new Error("[ConfigResolver] llm.provider is required");
|
|
2470
2429
|
}
|
|
2471
2430
|
}
|
|
2472
2431
|
static mergeRetrievalWorkflow(rag, retrieval, workflow) {
|
|
2473
|
-
var
|
|
2432
|
+
var _a2, _b, _c, _d, _e;
|
|
2474
2433
|
if (!rag && !retrieval && !workflow) return void 0;
|
|
2475
2434
|
const normalized = __spreadValues({}, rag != null ? rag : {});
|
|
2476
2435
|
if (retrieval) {
|
|
2477
|
-
normalized.topK = (
|
|
2436
|
+
normalized.topK = (_a2 = retrieval.topK) != null ? _a2 : normalized.topK;
|
|
2478
2437
|
normalized.scoreThreshold = (_b = retrieval.scoreThreshold) != null ? _b : normalized.scoreThreshold;
|
|
2479
2438
|
normalized.useReranking = (_c = retrieval.useReranking) != null ? _c : normalized.useReranking;
|
|
2480
2439
|
if (retrieval.strategy === "hybrid") normalized.architecture = (_d = normalized.architecture) != null ? _d : "hybrid";
|
|
@@ -2556,8 +2515,8 @@ var OpenAIProvider = class {
|
|
|
2556
2515
|
const apiKey = config.apiKey;
|
|
2557
2516
|
const modelName = config.model;
|
|
2558
2517
|
try {
|
|
2559
|
-
const
|
|
2560
|
-
const client = new
|
|
2518
|
+
const OpenAI4 = await import("openai");
|
|
2519
|
+
const client = new OpenAI4.default({ apiKey });
|
|
2561
2520
|
const models = await client.models.list();
|
|
2562
2521
|
const hasModel = models.data.some((m) => m.id === modelName);
|
|
2563
2522
|
return {
|
|
@@ -2578,8 +2537,8 @@ var OpenAIProvider = class {
|
|
|
2578
2537
|
};
|
|
2579
2538
|
}
|
|
2580
2539
|
async chat(messages, context, options) {
|
|
2581
|
-
var
|
|
2582
|
-
const basePrompt = (_b = (
|
|
2540
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
|
|
2541
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
2583
2542
|
const systemMessage = {
|
|
2584
2543
|
role: "system",
|
|
2585
2544
|
content: buildSystemContent(basePrompt, context)
|
|
@@ -2598,12 +2557,12 @@ var OpenAIProvider = class {
|
|
|
2598
2557
|
temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
|
|
2599
2558
|
stop: options == null ? void 0 : options.stop
|
|
2600
2559
|
});
|
|
2601
|
-
return (_i = (_h = (
|
|
2560
|
+
return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
|
|
2602
2561
|
}
|
|
2603
2562
|
chatStream(messages, context, options) {
|
|
2604
2563
|
return __asyncGenerator(this, null, function* () {
|
|
2605
|
-
var
|
|
2606
|
-
const basePrompt = (_b = (
|
|
2564
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h;
|
|
2565
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
2607
2566
|
const systemMessage = {
|
|
2608
2567
|
role: "system",
|
|
2609
2568
|
content: buildSystemContent(basePrompt, context)
|
|
@@ -2629,7 +2588,7 @@ var OpenAIProvider = class {
|
|
|
2629
2588
|
try {
|
|
2630
2589
|
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
2631
2590
|
const chunk = temp.value;
|
|
2632
|
-
const content = ((_h = (
|
|
2591
|
+
const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
|
|
2633
2592
|
if (content) yield content;
|
|
2634
2593
|
}
|
|
2635
2594
|
} catch (temp) {
|
|
@@ -2649,8 +2608,8 @@ var OpenAIProvider = class {
|
|
|
2649
2608
|
return results[0];
|
|
2650
2609
|
}
|
|
2651
2610
|
async batchEmbed(texts, options) {
|
|
2652
|
-
var
|
|
2653
|
-
const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (
|
|
2611
|
+
var _a2, _b, _c, _d, _e;
|
|
2612
|
+
const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _c : "text-embedding-3-small";
|
|
2654
2613
|
const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
|
|
2655
2614
|
const client = apiKey !== this.llmConfig.apiKey ? new import_openai.default({ apiKey }) : this.client;
|
|
2656
2615
|
const response = await client.embeddings.create({ model, input: texts });
|
|
@@ -2727,8 +2686,8 @@ var AnthropicProvider = class {
|
|
|
2727
2686
|
};
|
|
2728
2687
|
}
|
|
2729
2688
|
async chat(messages, context, options) {
|
|
2730
|
-
var
|
|
2731
|
-
const basePrompt = (_b = (
|
|
2689
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
|
|
2690
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
|
|
2732
2691
|
const system = buildSystemContent(basePrompt, context);
|
|
2733
2692
|
const anthropicMessages = messages.map((m) => ({
|
|
2734
2693
|
role: m.role === "assistant" ? "assistant" : "user",
|
|
@@ -2739,7 +2698,7 @@ var AnthropicProvider = class {
|
|
|
2739
2698
|
const extraParams = {};
|
|
2740
2699
|
if (isThinkingEnabled && isClaude37) {
|
|
2741
2700
|
extraParams.betas = ["interleaved-thinking-2025-05-14"];
|
|
2742
|
-
const maxTokens = (
|
|
2701
|
+
const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
|
|
2743
2702
|
const budget = Math.min(
|
|
2744
2703
|
typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
|
|
2745
2704
|
maxTokens - 1
|
|
@@ -2766,8 +2725,8 @@ var AnthropicProvider = class {
|
|
|
2766
2725
|
}
|
|
2767
2726
|
chatStream(messages, context, options) {
|
|
2768
2727
|
return __asyncGenerator(this, null, function* () {
|
|
2769
|
-
var
|
|
2770
|
-
const basePrompt = (_b = (
|
|
2728
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
|
|
2729
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
|
|
2771
2730
|
const system = buildSystemContent(basePrompt, context);
|
|
2772
2731
|
const anthropicMessages = messages.map((m) => ({
|
|
2773
2732
|
role: m.role === "assistant" ? "assistant" : "user",
|
|
@@ -2778,7 +2737,7 @@ var AnthropicProvider = class {
|
|
|
2778
2737
|
const extraParams = {};
|
|
2779
2738
|
if (isThinkingEnabled && isClaude37) {
|
|
2780
2739
|
extraParams.betas = ["interleaved-thinking-2025-05-14"];
|
|
2781
|
-
const maxTokens = (
|
|
2740
|
+
const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
|
|
2782
2741
|
const budget = Math.min(
|
|
2783
2742
|
typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
|
|
2784
2743
|
maxTokens - 1
|
|
@@ -2851,8 +2810,8 @@ var AnthropicProvider = class {
|
|
|
2851
2810
|
var import_axios = __toESM(require("axios"));
|
|
2852
2811
|
var OllamaProvider = class {
|
|
2853
2812
|
constructor(llmConfig, embeddingConfig) {
|
|
2854
|
-
var
|
|
2855
|
-
const baseURL = (
|
|
2813
|
+
var _a2, _b;
|
|
2814
|
+
const baseURL = (_a2 = llmConfig.baseUrl) != null ? _a2 : "http://localhost:11434";
|
|
2856
2815
|
const timeout = Number((_b = llmConfig.options) == null ? void 0 : _b.timeout) || 3e5;
|
|
2857
2816
|
this.http = import_axios.default.create({ baseURL, timeout });
|
|
2858
2817
|
this.llmConfig = llmConfig;
|
|
@@ -2910,8 +2869,8 @@ var OllamaProvider = class {
|
|
|
2910
2869
|
};
|
|
2911
2870
|
}
|
|
2912
2871
|
async chat(messages, context, options) {
|
|
2913
|
-
var
|
|
2914
|
-
const basePrompt = (_b = (
|
|
2872
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
2873
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
|
|
2915
2874
|
const system = buildSystemContent(basePrompt, context);
|
|
2916
2875
|
const { data } = await this.http.post("/api/chat", {
|
|
2917
2876
|
model: this.llmConfig.model,
|
|
@@ -2929,8 +2888,8 @@ var OllamaProvider = class {
|
|
|
2929
2888
|
}
|
|
2930
2889
|
chatStream(messages, context, options) {
|
|
2931
2890
|
return __asyncGenerator(this, null, function* () {
|
|
2932
|
-
var
|
|
2933
|
-
const basePrompt = (_b = (
|
|
2891
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h;
|
|
2892
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
|
|
2934
2893
|
const system = buildSystemContent(basePrompt, context);
|
|
2935
2894
|
const response = yield new __await(this.http.post("/api/chat", {
|
|
2936
2895
|
model: this.llmConfig.model,
|
|
@@ -2959,7 +2918,7 @@ var OllamaProvider = class {
|
|
|
2959
2918
|
if (!line.trim()) continue;
|
|
2960
2919
|
try {
|
|
2961
2920
|
const json = JSON.parse(line);
|
|
2962
|
-
if ((
|
|
2921
|
+
if ((_g2 = json.message) == null ? void 0 : _g2.content) {
|
|
2963
2922
|
yield json.message.content;
|
|
2964
2923
|
}
|
|
2965
2924
|
if (json.done) return;
|
|
@@ -2988,10 +2947,10 @@ var OllamaProvider = class {
|
|
|
2988
2947
|
});
|
|
2989
2948
|
}
|
|
2990
2949
|
async embed(text, options) {
|
|
2991
|
-
var
|
|
2992
|
-
const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (
|
|
2950
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
|
|
2951
|
+
const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _c : "nomic-embed-text";
|
|
2993
2952
|
const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
|
|
2994
|
-
const client = baseURL !== ((
|
|
2953
|
+
const client = baseURL !== ((_g2 = this.llmConfig.baseUrl) != null ? _g2 : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
|
|
2995
2954
|
let prompt = text;
|
|
2996
2955
|
const queryPrefix = (_i = (_h = this.embeddingConfig) == null ? void 0 : _h.queryPrefix) != null ? _i : model.includes("nomic") ? "search_query: " : "";
|
|
2997
2956
|
const docPrefix = (_k = (_j = this.embeddingConfig) == null ? void 0 : _j.documentPrefix) != null ? _k : model.includes("nomic") ? "search_document: " : "";
|
|
@@ -3090,9 +3049,9 @@ var GeminiProvider = class {
|
|
|
3090
3049
|
static getHealthChecker() {
|
|
3091
3050
|
return {
|
|
3092
3051
|
async check(config) {
|
|
3093
|
-
var
|
|
3052
|
+
var _a2, _b;
|
|
3094
3053
|
const timestamp = Date.now();
|
|
3095
|
-
const apiKey = (_b = (
|
|
3054
|
+
const apiKey = (_b = (_a2 = config.apiKey) != null ? _a2 : process.env.GOOGLE_GENAI_API_KEY) != null ? _b : "";
|
|
3096
3055
|
const modelName = sanitizeModel(config.model);
|
|
3097
3056
|
try {
|
|
3098
3057
|
const { GoogleGenerativeAI: GoogleGenerativeAI2 } = await import("@google/generative-ai");
|
|
@@ -3122,16 +3081,16 @@ var GeminiProvider = class {
|
|
|
3122
3081
|
/** Resolve the embedding client — uses a separate client when the embedding
|
|
3123
3082
|
* API key differs from the LLM API key. */
|
|
3124
3083
|
get embeddingClient() {
|
|
3125
|
-
var
|
|
3126
|
-
if (((
|
|
3084
|
+
var _a2;
|
|
3085
|
+
if (((_a2 = this.embeddingConfig) == null ? void 0 : _a2.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
|
|
3127
3086
|
return buildClient(this.embeddingConfig.apiKey);
|
|
3128
3087
|
}
|
|
3129
3088
|
return this.client;
|
|
3130
3089
|
}
|
|
3131
3090
|
/** Resolve the embedding model to use, in order of specificity. */
|
|
3132
3091
|
resolveEmbeddingModel(optionsModel) {
|
|
3133
|
-
var
|
|
3134
|
-
return sanitizeModel((_b = optionsModel != null ? optionsModel : (
|
|
3092
|
+
var _a2, _b;
|
|
3093
|
+
return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
|
|
3135
3094
|
}
|
|
3136
3095
|
/**
|
|
3137
3096
|
* Convert ChatMessage[] to the Gemini contents format.
|
|
@@ -3151,8 +3110,8 @@ var GeminiProvider = class {
|
|
|
3151
3110
|
// ILLMProvider — chat
|
|
3152
3111
|
// -------------------------------------------------------------------------
|
|
3153
3112
|
async chat(messages, context, options) {
|
|
3154
|
-
var
|
|
3155
|
-
const basePrompt = (_b = (
|
|
3113
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
3114
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
3156
3115
|
const model = this.client.getGenerativeModel({
|
|
3157
3116
|
model: this.llmConfig.model,
|
|
3158
3117
|
systemInstruction: buildSystemContent(basePrompt, context)
|
|
@@ -3169,8 +3128,8 @@ var GeminiProvider = class {
|
|
|
3169
3128
|
}
|
|
3170
3129
|
chatStream(messages, context, options) {
|
|
3171
3130
|
return __asyncGenerator(this, null, function* () {
|
|
3172
|
-
var
|
|
3173
|
-
const basePrompt = (_b = (
|
|
3131
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
3132
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
3174
3133
|
const model = this.client.getGenerativeModel({
|
|
3175
3134
|
model: this.llmConfig.model,
|
|
3176
3135
|
systemInstruction: buildSystemContent(basePrompt, context)
|
|
@@ -3205,11 +3164,11 @@ var GeminiProvider = class {
|
|
|
3205
3164
|
// ILLMProvider — embeddings
|
|
3206
3165
|
// -------------------------------------------------------------------------
|
|
3207
3166
|
async embed(text, options) {
|
|
3208
|
-
var
|
|
3167
|
+
var _a2, _b;
|
|
3209
3168
|
const content = applyPrefix(
|
|
3210
3169
|
text,
|
|
3211
3170
|
options == null ? void 0 : options.taskType,
|
|
3212
|
-
(
|
|
3171
|
+
(_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
|
|
3213
3172
|
(_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
|
|
3214
3173
|
);
|
|
3215
3174
|
const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
|
|
@@ -3226,7 +3185,7 @@ var GeminiProvider = class {
|
|
|
3226
3185
|
const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
|
|
3227
3186
|
const model = this.embeddingClient.getGenerativeModel({ model: modelName });
|
|
3228
3187
|
const requests = texts.map((text) => {
|
|
3229
|
-
var
|
|
3188
|
+
var _a2, _b;
|
|
3230
3189
|
return {
|
|
3231
3190
|
content: {
|
|
3232
3191
|
role: "user",
|
|
@@ -3234,7 +3193,7 @@ var GeminiProvider = class {
|
|
|
3234
3193
|
text: applyPrefix(
|
|
3235
3194
|
text,
|
|
3236
3195
|
options == null ? void 0 : options.taskType,
|
|
3237
|
-
(
|
|
3196
|
+
(_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
|
|
3238
3197
|
(_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
|
|
3239
3198
|
)
|
|
3240
3199
|
}]
|
|
@@ -3251,8 +3210,8 @@ var GeminiProvider = class {
|
|
|
3251
3210
|
throw err;
|
|
3252
3211
|
});
|
|
3253
3212
|
return response.embeddings.map((e) => {
|
|
3254
|
-
var
|
|
3255
|
-
return (
|
|
3213
|
+
var _a2;
|
|
3214
|
+
return (_a2 = e.values) != null ? _a2 : [];
|
|
3256
3215
|
});
|
|
3257
3216
|
}
|
|
3258
3217
|
// -------------------------------------------------------------------------
|
|
@@ -3272,163 +3231,482 @@ var GeminiProvider = class {
|
|
|
3272
3231
|
}
|
|
3273
3232
|
};
|
|
3274
3233
|
|
|
3275
|
-
// src/llm/providers/
|
|
3276
|
-
var
|
|
3277
|
-
|
|
3278
|
-
|
|
3279
|
-
|
|
3280
|
-
|
|
3281
|
-
|
|
3282
|
-
|
|
3283
|
-
|
|
3284
|
-
|
|
3285
|
-
|
|
3286
|
-
|
|
3287
|
-
var LLM_PROFILES = {
|
|
3288
|
-
"openai-compatible": OPENAI_BASE,
|
|
3289
|
-
"litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
3290
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
|
|
3291
|
-
}),
|
|
3292
|
-
"anthropic-claude": {
|
|
3293
|
-
chatPath: "/v1/messages",
|
|
3294
|
-
responseExtractPath: "content[0].text",
|
|
3295
|
-
headers: { "anthropic-version": "2023-06-01" },
|
|
3296
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
|
|
3297
|
-
},
|
|
3298
|
-
"google-gemini": {
|
|
3299
|
-
chatPath: "/v1beta/models/{{model}}:generateContent",
|
|
3300
|
-
responseExtractPath: "candidates[0].content.parts[0].text",
|
|
3301
|
-
chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
|
|
3302
|
-
},
|
|
3303
|
-
"github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
3304
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
|
|
3305
|
-
}),
|
|
3306
|
-
"ollama-standard": {
|
|
3307
|
-
chatPath: "/api/chat",
|
|
3308
|
-
embedPath: "/api/embeddings",
|
|
3309
|
-
responseExtractPath: "message.content",
|
|
3310
|
-
embedExtractPath: "embedding",
|
|
3311
|
-
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
|
|
3312
|
-
embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
|
|
3234
|
+
// src/llm/providers/GroqProvider.ts
|
|
3235
|
+
var import_openai2 = __toESM(require("openai"));
|
|
3236
|
+
var GroqProvider = class {
|
|
3237
|
+
constructor(llmConfig, embeddingConfig) {
|
|
3238
|
+
void embeddingConfig;
|
|
3239
|
+
const apiKey = llmConfig.apiKey || process.env.GROQ_API_KEY;
|
|
3240
|
+
if (!apiKey) throw new Error("[GroqProvider] llmConfig.apiKey or GROQ_API_KEY environment variable is required");
|
|
3241
|
+
this.client = new import_openai2.default({
|
|
3242
|
+
apiKey,
|
|
3243
|
+
baseURL: llmConfig.baseUrl || "https://api.groq.com/openai/v1"
|
|
3244
|
+
});
|
|
3245
|
+
this.llmConfig = llmConfig;
|
|
3313
3246
|
}
|
|
3314
|
-
|
|
3315
|
-
|
|
3316
|
-
|
|
3317
|
-
|
|
3318
|
-
|
|
3319
|
-
|
|
3320
|
-
|
|
3321
|
-
|
|
3322
|
-
|
|
3323
|
-
|
|
3324
|
-
|
|
3325
|
-
|
|
3326
|
-
|
|
3327
|
-
|
|
3328
|
-
|
|
3329
|
-
|
|
3330
|
-
|
|
3331
|
-
|
|
3332
|
-
|
|
3333
|
-
|
|
3334
|
-
|
|
3335
|
-
|
|
3336
|
-
|
|
3337
|
-
upsertPath: "/api/v1/collections/{{index}}/add",
|
|
3338
|
-
responseExtractPath: "matches",
|
|
3339
|
-
idPath: "id",
|
|
3340
|
-
scorePath: "distance",
|
|
3341
|
-
contentPath: "document",
|
|
3342
|
-
metadataPath: "metadata"
|
|
3343
|
-
},
|
|
3344
|
-
"qdrant": {
|
|
3345
|
-
queryPath: "/collections/{{index}}/points/search",
|
|
3346
|
-
upsertPath: "/collections/{{index}}/points",
|
|
3347
|
-
responseExtractPath: "result",
|
|
3348
|
-
idPath: "id",
|
|
3349
|
-
scorePath: "score",
|
|
3350
|
-
contentPath: "payload.content",
|
|
3351
|
-
metadataPath: "payload"
|
|
3247
|
+
static getValidator() {
|
|
3248
|
+
return {
|
|
3249
|
+
validate(config) {
|
|
3250
|
+
const errors = [];
|
|
3251
|
+
if (!config.apiKey && !process.env.GROQ_API_KEY) {
|
|
3252
|
+
errors.push({
|
|
3253
|
+
field: "llm.apiKey",
|
|
3254
|
+
message: "Groq API key is required",
|
|
3255
|
+
suggestion: "Set GROQ_API_KEY environment variable",
|
|
3256
|
+
severity: "error"
|
|
3257
|
+
});
|
|
3258
|
+
}
|
|
3259
|
+
if (!config.model) {
|
|
3260
|
+
errors.push({
|
|
3261
|
+
field: "llm.model",
|
|
3262
|
+
message: "Groq model name is required",
|
|
3263
|
+
suggestion: 'e.g., "llama-3.3-70b-versatile"',
|
|
3264
|
+
severity: "error"
|
|
3265
|
+
});
|
|
3266
|
+
}
|
|
3267
|
+
return errors;
|
|
3268
|
+
}
|
|
3269
|
+
};
|
|
3352
3270
|
}
|
|
3353
|
-
|
|
3354
|
-
|
|
3355
|
-
|
|
3356
|
-
|
|
3357
|
-
|
|
3358
|
-
|
|
3359
|
-
|
|
3360
|
-
|
|
3361
|
-
|
|
3362
|
-
|
|
3363
|
-
|
|
3364
|
-
|
|
3365
|
-
|
|
3366
|
-
|
|
3367
|
-
|
|
3368
|
-
|
|
3369
|
-
|
|
3370
|
-
|
|
3371
|
-
|
|
3372
|
-
|
|
3373
|
-
|
|
3374
|
-
|
|
3375
|
-
|
|
3376
|
-
|
|
3377
|
-
|
|
3378
|
-
|
|
3379
|
-
|
|
3380
|
-
|
|
3381
|
-
|
|
3382
|
-
|
|
3383
|
-
timeout: (_h = this.opts.timeout) != null ? _h : 6e4
|
|
3384
|
-
});
|
|
3271
|
+
static getHealthChecker() {
|
|
3272
|
+
return {
|
|
3273
|
+
async check(config) {
|
|
3274
|
+
const timestamp = Date.now();
|
|
3275
|
+
const apiKey = config.apiKey || process.env.GROQ_API_KEY || "";
|
|
3276
|
+
const modelName = config.model;
|
|
3277
|
+
try {
|
|
3278
|
+
const OpenAI4 = await import("openai");
|
|
3279
|
+
const client = new OpenAI4.default({
|
|
3280
|
+
apiKey,
|
|
3281
|
+
baseURL: config.baseUrl || "https://api.groq.com/openai/v1"
|
|
3282
|
+
});
|
|
3283
|
+
const models = await client.models.list();
|
|
3284
|
+
const hasModel = models.data.some((m) => m.id === modelName);
|
|
3285
|
+
return {
|
|
3286
|
+
healthy: true,
|
|
3287
|
+
provider: "groq",
|
|
3288
|
+
capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
|
|
3289
|
+
timestamp
|
|
3290
|
+
};
|
|
3291
|
+
} catch (error) {
|
|
3292
|
+
return {
|
|
3293
|
+
healthy: false,
|
|
3294
|
+
provider: "groq",
|
|
3295
|
+
error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3296
|
+
timestamp
|
|
3297
|
+
};
|
|
3298
|
+
}
|
|
3299
|
+
}
|
|
3300
|
+
};
|
|
3385
3301
|
}
|
|
3386
|
-
async chat(messages, context) {
|
|
3387
|
-
var
|
|
3388
|
-
const
|
|
3302
|
+
async chat(messages, context, options) {
|
|
3303
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
|
|
3304
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
3305
|
+
const systemMessage = {
|
|
3306
|
+
role: "system",
|
|
3307
|
+
content: buildSystemContent(basePrompt, context)
|
|
3308
|
+
};
|
|
3389
3309
|
const formattedMessages = [
|
|
3390
|
-
|
|
3391
|
-
|
|
3392
|
-
|
|
3393
|
-
|
|
3394
|
-
|
|
3310
|
+
systemMessage,
|
|
3311
|
+
...messages.map((m) => ({
|
|
3312
|
+
role: m.role,
|
|
3313
|
+
content: m.content
|
|
3314
|
+
}))
|
|
3395
3315
|
];
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
|
|
3401
|
-
|
|
3402
|
-
|
|
3403
|
-
|
|
3404
|
-
} else {
|
|
3405
|
-
payload = {
|
|
3406
|
-
model: this.model,
|
|
3407
|
-
messages: formattedMessages,
|
|
3408
|
-
max_tokens: this.maxTokens,
|
|
3409
|
-
temperature: this.temperature
|
|
3410
|
-
};
|
|
3411
|
-
}
|
|
3412
|
-
const { data } = await this.http.post(path, payload);
|
|
3413
|
-
const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
|
|
3414
|
-
const result = resolvePath(data, extractPath);
|
|
3415
|
-
if (result === void 0) {
|
|
3416
|
-
throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
|
|
3417
|
-
}
|
|
3418
|
-
return String(result);
|
|
3316
|
+
const completion = await this.client.chat.completions.create({
|
|
3317
|
+
model: this.llmConfig.model,
|
|
3318
|
+
messages: formattedMessages,
|
|
3319
|
+
max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
|
|
3320
|
+
temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
|
|
3321
|
+
stop: options == null ? void 0 : options.stop
|
|
3322
|
+
});
|
|
3323
|
+
return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
|
|
3419
3324
|
}
|
|
3420
|
-
|
|
3421
|
-
* Streaming chat using native fetch + ReadableStream.
|
|
3422
|
-
* Parses OpenAI-compatible SSE frames: `data: {...}\n\n`
|
|
3423
|
-
* Works with vLLM, LMStudio, Together AI, Fireworks, and any OpenAI-compatible API.
|
|
3424
|
-
*/
|
|
3425
|
-
chatStream(messages, context) {
|
|
3325
|
+
chatStream(messages, context, options) {
|
|
3426
3326
|
return __asyncGenerator(this, null, function* () {
|
|
3427
|
-
var
|
|
3428
|
-
const
|
|
3429
|
-
const
|
|
3430
|
-
|
|
3431
|
-
|
|
3327
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h;
|
|
3328
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
3329
|
+
const systemMessage = {
|
|
3330
|
+
role: "system",
|
|
3331
|
+
content: buildSystemContent(basePrompt, context)
|
|
3332
|
+
};
|
|
3333
|
+
const formattedMessages = [
|
|
3334
|
+
systemMessage,
|
|
3335
|
+
...messages.map((m) => ({
|
|
3336
|
+
role: m.role,
|
|
3337
|
+
content: m.content
|
|
3338
|
+
}))
|
|
3339
|
+
];
|
|
3340
|
+
const stream = yield new __await(this.client.chat.completions.create({
|
|
3341
|
+
model: this.llmConfig.model,
|
|
3342
|
+
messages: formattedMessages,
|
|
3343
|
+
max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
|
|
3344
|
+
temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
|
|
3345
|
+
stop: options == null ? void 0 : options.stop,
|
|
3346
|
+
stream: true
|
|
3347
|
+
}));
|
|
3348
|
+
if (!stream) {
|
|
3349
|
+
throw new Error("[GroqProvider] completions.create stream is undefined");
|
|
3350
|
+
}
|
|
3351
|
+
try {
|
|
3352
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
3353
|
+
const chunk = temp.value;
|
|
3354
|
+
const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
|
|
3355
|
+
if (content) yield content;
|
|
3356
|
+
}
|
|
3357
|
+
} catch (temp) {
|
|
3358
|
+
error = [temp];
|
|
3359
|
+
} finally {
|
|
3360
|
+
try {
|
|
3361
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
3362
|
+
} finally {
|
|
3363
|
+
if (error)
|
|
3364
|
+
throw error[0];
|
|
3365
|
+
}
|
|
3366
|
+
}
|
|
3367
|
+
});
|
|
3368
|
+
}
|
|
3369
|
+
async embed(text, options) {
|
|
3370
|
+
void text;
|
|
3371
|
+
void options;
|
|
3372
|
+
throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
|
|
3373
|
+
}
|
|
3374
|
+
async batchEmbed(texts, options) {
|
|
3375
|
+
void texts;
|
|
3376
|
+
void options;
|
|
3377
|
+
throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
|
|
3378
|
+
}
|
|
3379
|
+
async ping() {
|
|
3380
|
+
try {
|
|
3381
|
+
await this.client.models.list();
|
|
3382
|
+
return true;
|
|
3383
|
+
} catch (err) {
|
|
3384
|
+
console.error("[GroqProvider] Ping failed:", err);
|
|
3385
|
+
return false;
|
|
3386
|
+
}
|
|
3387
|
+
}
|
|
3388
|
+
};
|
|
3389
|
+
|
|
3390
|
+
// src/llm/providers/QwenProvider.ts
|
|
3391
|
+
var import_openai3 = __toESM(require("openai"));
|
|
3392
|
+
var QwenProvider = class {
|
|
3393
|
+
constructor(llmConfig, embeddingConfig) {
|
|
3394
|
+
const apiKey = llmConfig.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY;
|
|
3395
|
+
if (!apiKey) throw new Error("[QwenProvider] llmConfig.apiKey, DASHSCOPE_API_KEY, or QWEN_API_KEY environment variable is required");
|
|
3396
|
+
this.client = new import_openai3.default({
|
|
3397
|
+
apiKey,
|
|
3398
|
+
baseURL: llmConfig.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
3399
|
+
});
|
|
3400
|
+
this.llmConfig = llmConfig;
|
|
3401
|
+
this.embeddingConfig = embeddingConfig;
|
|
3402
|
+
}
|
|
3403
|
+
static getValidator() {
|
|
3404
|
+
return {
|
|
3405
|
+
validate(config) {
|
|
3406
|
+
const errors = [];
|
|
3407
|
+
const isEmbedding = config.provider === "qwen" && "dimensions" in config;
|
|
3408
|
+
const prefix = isEmbedding ? "embedding" : "llm";
|
|
3409
|
+
if (!config.apiKey && !process.env.DASHSCOPE_API_KEY && !process.env.QWEN_API_KEY) {
|
|
3410
|
+
errors.push({
|
|
3411
|
+
field: `${prefix}.apiKey`,
|
|
3412
|
+
message: "Qwen API key is required",
|
|
3413
|
+
suggestion: "Set DASHSCOPE_API_KEY or QWEN_API_KEY environment variable",
|
|
3414
|
+
severity: "error"
|
|
3415
|
+
});
|
|
3416
|
+
}
|
|
3417
|
+
if (!config.model) {
|
|
3418
|
+
errors.push({
|
|
3419
|
+
field: `${prefix}.model`,
|
|
3420
|
+
message: "Qwen model name is required",
|
|
3421
|
+
suggestion: isEmbedding ? 'e.g., "text-embedding-v3"' : 'e.g., "qwen-plus" or "qwen-max"',
|
|
3422
|
+
severity: "error"
|
|
3423
|
+
});
|
|
3424
|
+
}
|
|
3425
|
+
return errors;
|
|
3426
|
+
}
|
|
3427
|
+
};
|
|
3428
|
+
}
|
|
3429
|
+
static getHealthChecker() {
|
|
3430
|
+
return {
|
|
3431
|
+
async check(config) {
|
|
3432
|
+
const timestamp = Date.now();
|
|
3433
|
+
const apiKey = config.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY || "";
|
|
3434
|
+
const modelName = config.model;
|
|
3435
|
+
try {
|
|
3436
|
+
const OpenAI4 = await import("openai");
|
|
3437
|
+
const client = new OpenAI4.default({
|
|
3438
|
+
apiKey,
|
|
3439
|
+
baseURL: config.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
3440
|
+
});
|
|
3441
|
+
const models = await client.models.list();
|
|
3442
|
+
const hasModel = models.data.some((m) => m.id === modelName);
|
|
3443
|
+
return {
|
|
3444
|
+
healthy: true,
|
|
3445
|
+
provider: "qwen",
|
|
3446
|
+
capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
|
|
3447
|
+
timestamp
|
|
3448
|
+
};
|
|
3449
|
+
} catch (error) {
|
|
3450
|
+
return {
|
|
3451
|
+
healthy: false,
|
|
3452
|
+
provider: "qwen",
|
|
3453
|
+
error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
3454
|
+
timestamp
|
|
3455
|
+
};
|
|
3456
|
+
}
|
|
3457
|
+
}
|
|
3458
|
+
};
|
|
3459
|
+
}
|
|
3460
|
+
async chat(messages, context, options) {
|
|
3461
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
|
|
3462
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
3463
|
+
const systemMessage = {
|
|
3464
|
+
role: "system",
|
|
3465
|
+
content: buildSystemContent(basePrompt, context)
|
|
3466
|
+
};
|
|
3467
|
+
const formattedMessages = [
|
|
3468
|
+
systemMessage,
|
|
3469
|
+
...messages.map((m) => ({
|
|
3470
|
+
role: m.role,
|
|
3471
|
+
content: m.content
|
|
3472
|
+
}))
|
|
3473
|
+
];
|
|
3474
|
+
const completion = await this.client.chat.completions.create({
|
|
3475
|
+
model: this.llmConfig.model,
|
|
3476
|
+
messages: formattedMessages,
|
|
3477
|
+
max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
|
|
3478
|
+
temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
|
|
3479
|
+
stop: options == null ? void 0 : options.stop
|
|
3480
|
+
});
|
|
3481
|
+
return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
|
|
3482
|
+
}
|
|
3483
|
+
chatStream(messages, context, options) {
|
|
3484
|
+
return __asyncGenerator(this, null, function* () {
|
|
3485
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h;
|
|
3486
|
+
const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
|
|
3487
|
+
const systemMessage = {
|
|
3488
|
+
role: "system",
|
|
3489
|
+
content: buildSystemContent(basePrompt, context)
|
|
3490
|
+
};
|
|
3491
|
+
const formattedMessages = [
|
|
3492
|
+
systemMessage,
|
|
3493
|
+
...messages.map((m) => ({
|
|
3494
|
+
role: m.role,
|
|
3495
|
+
content: m.content
|
|
3496
|
+
}))
|
|
3497
|
+
];
|
|
3498
|
+
const stream = yield new __await(this.client.chat.completions.create({
|
|
3499
|
+
model: this.llmConfig.model,
|
|
3500
|
+
messages: formattedMessages,
|
|
3501
|
+
max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
|
|
3502
|
+
temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
|
|
3503
|
+
stop: options == null ? void 0 : options.stop,
|
|
3504
|
+
stream: true
|
|
3505
|
+
}));
|
|
3506
|
+
if (!stream) {
|
|
3507
|
+
throw new Error("[QwenProvider] completions.create stream is undefined");
|
|
3508
|
+
}
|
|
3509
|
+
try {
|
|
3510
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
3511
|
+
const chunk = temp.value;
|
|
3512
|
+
const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
|
|
3513
|
+
if (content) yield content;
|
|
3514
|
+
}
|
|
3515
|
+
} catch (temp) {
|
|
3516
|
+
error = [temp];
|
|
3517
|
+
} finally {
|
|
3518
|
+
try {
|
|
3519
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
3520
|
+
} finally {
|
|
3521
|
+
if (error)
|
|
3522
|
+
throw error[0];
|
|
3523
|
+
}
|
|
3524
|
+
}
|
|
3525
|
+
});
|
|
3526
|
+
}
|
|
3527
|
+
async embed(text, options) {
|
|
3528
|
+
const results = await this.batchEmbed([text], options);
|
|
3529
|
+
return results[0];
|
|
3530
|
+
}
|
|
3531
|
+
async batchEmbed(texts, options) {
|
|
3532
|
+
var _a2, _b, _c, _d, _e, _f;
|
|
3533
|
+
const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _c : "text-embedding-v1";
|
|
3534
|
+
const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
|
|
3535
|
+
const client = apiKey !== this.llmConfig.apiKey ? new import_openai3.default({
|
|
3536
|
+
apiKey,
|
|
3537
|
+
baseURL: ((_f = this.embeddingConfig) == null ? void 0 : _f.baseUrl) || "https://dashscope.aliyuncs.com/compatible-mode/v1"
|
|
3538
|
+
}) : this.client;
|
|
3539
|
+
const response = await client.embeddings.create({ model, input: texts });
|
|
3540
|
+
return response.data.map((d) => d.embedding);
|
|
3541
|
+
}
|
|
3542
|
+
async ping() {
|
|
3543
|
+
try {
|
|
3544
|
+
await this.client.models.list();
|
|
3545
|
+
return true;
|
|
3546
|
+
} catch (err) {
|
|
3547
|
+
console.error("[QwenProvider] Ping failed:", err);
|
|
3548
|
+
return false;
|
|
3549
|
+
}
|
|
3550
|
+
}
|
|
3551
|
+
};
|
|
3552
|
+
|
|
3553
|
+
// src/llm/providers/UniversalLLMAdapter.ts
|
|
3554
|
+
var import_axios2 = __toESM(require("axios"));
|
|
3555
|
+
init_templateUtils();
|
|
3556
|
+
|
|
3557
|
+
// src/config/UniversalProfiles.ts
|
|
3558
|
+
var OPENAI_BASE = {
|
|
3559
|
+
chatPath: "/chat/completions",
|
|
3560
|
+
embedPath: "/embeddings",
|
|
3561
|
+
responseExtractPath: "choices[0].message.content",
|
|
3562
|
+
embedExtractPath: "data[0].embedding",
|
|
3563
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
|
|
3564
|
+
};
|
|
3565
|
+
var LLM_PROFILES = {
|
|
3566
|
+
"openai-compatible": OPENAI_BASE,
|
|
3567
|
+
"litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
3568
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
|
|
3569
|
+
}),
|
|
3570
|
+
"anthropic-claude": {
|
|
3571
|
+
chatPath: "/v1/messages",
|
|
3572
|
+
responseExtractPath: "content[0].text",
|
|
3573
|
+
headers: { "anthropic-version": "2023-06-01" },
|
|
3574
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
|
|
3575
|
+
},
|
|
3576
|
+
"google-gemini": {
|
|
3577
|
+
chatPath: "/v1beta/models/{{model}}:generateContent",
|
|
3578
|
+
responseExtractPath: "candidates[0].content.parts[0].text",
|
|
3579
|
+
chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
|
|
3580
|
+
},
|
|
3581
|
+
"github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
|
|
3582
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
|
|
3583
|
+
}),
|
|
3584
|
+
"ollama-standard": {
|
|
3585
|
+
chatPath: "/api/chat",
|
|
3586
|
+
embedPath: "/api/embeddings",
|
|
3587
|
+
responseExtractPath: "message.content",
|
|
3588
|
+
embedExtractPath: "embedding",
|
|
3589
|
+
chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
|
|
3590
|
+
embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
|
|
3591
|
+
}
|
|
3592
|
+
};
|
|
3593
|
+
var VECTOR_PROFILES = {
|
|
3594
|
+
"pinecone-rest": {
|
|
3595
|
+
queryPath: "/query",
|
|
3596
|
+
upsertPath: "/vectors/upsert",
|
|
3597
|
+
responseExtractPath: "matches",
|
|
3598
|
+
idPath: "id",
|
|
3599
|
+
scorePath: "score",
|
|
3600
|
+
contentPath: "metadata.content",
|
|
3601
|
+
metadataPath: "metadata",
|
|
3602
|
+
queryPayloadTemplate: '{"vector":{{vector}},"topK":{{topK}},"includeMetadata":true,"namespace":"{{namespace}}"}'
|
|
3603
|
+
},
|
|
3604
|
+
"mongodb-atlas": {
|
|
3605
|
+
queryPath: "/action/aggregate",
|
|
3606
|
+
responseExtractPath: "documents",
|
|
3607
|
+
idPath: "_id",
|
|
3608
|
+
scorePath: "score",
|
|
3609
|
+
contentPath: "content",
|
|
3610
|
+
metadataPath: "metadata",
|
|
3611
|
+
queryPayloadTemplate: '{"collection":"{{index}}","database":"ai_db","dataSource":"Cluster0","pipeline":[{"$vectorSearch":{"index":"vector_index","path":"embedding","queryVector":{{vector}},"numCandidates":100,"limit":{{topK}}}},{"$project":{"_id":1,"content":1,"metadata":1,"score":{"$meta":"vectorSearchScore"}}}]}'
|
|
3612
|
+
},
|
|
3613
|
+
"chromadb": {
|
|
3614
|
+
queryPath: "/api/v1/collections/{{index}}/query",
|
|
3615
|
+
upsertPath: "/api/v1/collections/{{index}}/add",
|
|
3616
|
+
responseExtractPath: "matches",
|
|
3617
|
+
idPath: "id",
|
|
3618
|
+
scorePath: "distance",
|
|
3619
|
+
contentPath: "document",
|
|
3620
|
+
metadataPath: "metadata"
|
|
3621
|
+
},
|
|
3622
|
+
"qdrant": {
|
|
3623
|
+
queryPath: "/collections/{{index}}/points/search",
|
|
3624
|
+
upsertPath: "/collections/{{index}}/points",
|
|
3625
|
+
responseExtractPath: "result",
|
|
3626
|
+
idPath: "id",
|
|
3627
|
+
scorePath: "score",
|
|
3628
|
+
contentPath: "payload.content",
|
|
3629
|
+
metadataPath: "payload"
|
|
3630
|
+
}
|
|
3631
|
+
};
|
|
3632
|
+
|
|
3633
|
+
// src/llm/providers/UniversalLLMAdapter.ts
|
|
3634
|
+
var UniversalLLMAdapter = class {
|
|
3635
|
+
constructor(config) {
|
|
3636
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h;
|
|
3637
|
+
this.model = config.model;
|
|
3638
|
+
const llmConfig = config;
|
|
3639
|
+
const options = (_a2 = llmConfig.options) != null ? _a2 : {};
|
|
3640
|
+
let profile = {};
|
|
3641
|
+
if (typeof options.profile === "string") {
|
|
3642
|
+
profile = LLM_PROFILES[options.profile] || {};
|
|
3643
|
+
} else if (typeof options.profile === "object" && options.profile !== null) {
|
|
3644
|
+
profile = options.profile;
|
|
3645
|
+
}
|
|
3646
|
+
this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
|
|
3647
|
+
this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
|
|
3648
|
+
this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
|
|
3649
|
+
this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
|
|
3650
|
+
this.apiKey = config.apiKey;
|
|
3651
|
+
this.baseUrl = (_g2 = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g2 : "";
|
|
3652
|
+
if (!this.baseUrl) {
|
|
3653
|
+
throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
|
|
3654
|
+
}
|
|
3655
|
+
this.resolvedHeaders = __spreadValues(__spreadValues({
|
|
3656
|
+
"Content-Type": "application/json"
|
|
3657
|
+
}, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {});
|
|
3658
|
+
this.http = import_axios2.default.create({
|
|
3659
|
+
baseURL: this.baseUrl,
|
|
3660
|
+
headers: this.resolvedHeaders,
|
|
3661
|
+
timeout: (_h = this.opts.timeout) != null ? _h : 6e4
|
|
3662
|
+
});
|
|
3663
|
+
}
|
|
3664
|
+
async chat(messages, context) {
|
|
3665
|
+
var _a2, _b;
|
|
3666
|
+
const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
|
|
3667
|
+
const formattedMessages = [
|
|
3668
|
+
{ role: "system", content: `${this.systemPrompt}
|
|
3669
|
+
|
|
3670
|
+
Context:
|
|
3671
|
+
${context != null ? context : "None"}` },
|
|
3672
|
+
...messages
|
|
3673
|
+
];
|
|
3674
|
+
let payload;
|
|
3675
|
+
if (this.opts.chatPayloadTemplate) {
|
|
3676
|
+
payload = buildPayload(this.opts.chatPayloadTemplate, {
|
|
3677
|
+
model: this.model,
|
|
3678
|
+
messages: formattedMessages,
|
|
3679
|
+
maxTokens: this.maxTokens,
|
|
3680
|
+
temperature: this.temperature
|
|
3681
|
+
});
|
|
3682
|
+
} else {
|
|
3683
|
+
payload = {
|
|
3684
|
+
model: this.model,
|
|
3685
|
+
messages: formattedMessages,
|
|
3686
|
+
max_tokens: this.maxTokens,
|
|
3687
|
+
temperature: this.temperature
|
|
3688
|
+
};
|
|
3689
|
+
}
|
|
3690
|
+
const { data } = await this.http.post(path2, payload);
|
|
3691
|
+
const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
|
|
3692
|
+
const result = resolvePath(data, extractPath);
|
|
3693
|
+
if (result === void 0) {
|
|
3694
|
+
throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
|
|
3695
|
+
}
|
|
3696
|
+
return String(result);
|
|
3697
|
+
}
|
|
3698
|
+
/**
|
|
3699
|
+
* Streaming chat using native fetch + ReadableStream.
|
|
3700
|
+
* Parses OpenAI-compatible SSE frames: `data: {...}\n\n`
|
|
3701
|
+
* Works with vLLM, LMStudio, Together AI, Fireworks, and any OpenAI-compatible API.
|
|
3702
|
+
*/
|
|
3703
|
+
chatStream(messages, context) {
|
|
3704
|
+
return __asyncGenerator(this, null, function* () {
|
|
3705
|
+
var _a2, _b, _c;
|
|
3706
|
+
const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
|
|
3707
|
+
const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
|
|
3708
|
+
const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
|
|
3709
|
+
const formattedMessages = [
|
|
3432
3710
|
{ role: "system", content: `${this.systemPrompt}
|
|
3433
3711
|
|
|
3434
3712
|
Context:
|
|
@@ -3504,8 +3782,8 @@ ${context != null ? context : "None"}` },
|
|
|
3504
3782
|
});
|
|
3505
3783
|
}
|
|
3506
3784
|
async embed(text) {
|
|
3507
|
-
var
|
|
3508
|
-
const
|
|
3785
|
+
var _a2, _b;
|
|
3786
|
+
const path2 = (_a2 = this.opts.embedPath) != null ? _a2 : "/embeddings";
|
|
3509
3787
|
let payload;
|
|
3510
3788
|
if (this.opts.embedPayloadTemplate) {
|
|
3511
3789
|
payload = buildPayload(this.opts.embedPayloadTemplate, {
|
|
@@ -3518,7 +3796,7 @@ ${context != null ? context : "None"}` },
|
|
|
3518
3796
|
input: text
|
|
3519
3797
|
};
|
|
3520
3798
|
}
|
|
3521
|
-
const { data } = await this.http.post(
|
|
3799
|
+
const { data } = await this.http.post(path2, payload);
|
|
3522
3800
|
const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
|
|
3523
3801
|
const vector = resolvePath(data, extractPath);
|
|
3524
3802
|
if (!Array.isArray(vector)) {
|
|
@@ -3546,6 +3824,78 @@ ${context != null ? context : "None"}` },
|
|
|
3546
3824
|
}
|
|
3547
3825
|
};
|
|
3548
3826
|
|
|
3827
|
+
// src/exceptions/index.ts
|
|
3828
|
+
var RetrivoraError = class extends Error {
|
|
3829
|
+
constructor(message, code, details) {
|
|
3830
|
+
super(message);
|
|
3831
|
+
this.name = new.target.name;
|
|
3832
|
+
this.code = code;
|
|
3833
|
+
this.details = details;
|
|
3834
|
+
}
|
|
3835
|
+
};
|
|
3836
|
+
var ProviderNotFoundException = class extends RetrivoraError {
|
|
3837
|
+
constructor(providerType, provider, details) {
|
|
3838
|
+
super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
|
|
3839
|
+
}
|
|
3840
|
+
};
|
|
3841
|
+
var EmbeddingFailedException = class extends RetrivoraError {
|
|
3842
|
+
constructor(message = "Embedding generation failed", details) {
|
|
3843
|
+
super(message, "EMBEDDING_FAILED", details);
|
|
3844
|
+
}
|
|
3845
|
+
};
|
|
3846
|
+
var RetrievalException = class extends RetrivoraError {
|
|
3847
|
+
constructor(message = "Retrieval failed", details) {
|
|
3848
|
+
super(message, "RETRIEVAL_FAILED", details);
|
|
3849
|
+
}
|
|
3850
|
+
};
|
|
3851
|
+
var RateLimitException = class extends RetrivoraError {
|
|
3852
|
+
constructor(message = "Provider rate limit exceeded", details) {
|
|
3853
|
+
super(message, "RATE_LIMITED", details);
|
|
3854
|
+
}
|
|
3855
|
+
};
|
|
3856
|
+
var ConfigurationException = class extends RetrivoraError {
|
|
3857
|
+
constructor(message, details) {
|
|
3858
|
+
super(message, "CONFIGURATION_ERROR", details);
|
|
3859
|
+
}
|
|
3860
|
+
};
|
|
3861
|
+
var AuthenticationException = class extends RetrivoraError {
|
|
3862
|
+
constructor(message = "Provider authentication failed", details) {
|
|
3863
|
+
super(message, "AUTHENTICATION_ERROR", details);
|
|
3864
|
+
}
|
|
3865
|
+
};
|
|
3866
|
+
function wrapError(err, defaultCode, defaultMessage) {
|
|
3867
|
+
var _a2;
|
|
3868
|
+
if (err instanceof RetrivoraError) {
|
|
3869
|
+
return err;
|
|
3870
|
+
}
|
|
3871
|
+
const error = err;
|
|
3872
|
+
const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
|
|
3873
|
+
const status = (error == null ? void 0 : error.status) || (error == null ? void 0 : error.statusCode) || ((_a2 = error == null ? void 0 : error.response) == null ? void 0 : _a2.status);
|
|
3874
|
+
const code = error == null ? void 0 : error.code;
|
|
3875
|
+
if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
|
|
3876
|
+
return new RateLimitException(message, err);
|
|
3877
|
+
}
|
|
3878
|
+
if (status === 401 || status === 403 || /unauthorized|auth|api[- ]?key/i.test(message) || code === "INVALID_API_KEY") {
|
|
3879
|
+
return new AuthenticationException(message, err);
|
|
3880
|
+
}
|
|
3881
|
+
switch (defaultCode) {
|
|
3882
|
+
case "PROVIDER_NOT_FOUND":
|
|
3883
|
+
return new ProviderNotFoundException("provider", message, err);
|
|
3884
|
+
case "EMBEDDING_FAILED":
|
|
3885
|
+
return new EmbeddingFailedException(message, err);
|
|
3886
|
+
case "RETRIEVAL_FAILED":
|
|
3887
|
+
return new RetrievalException(message, err);
|
|
3888
|
+
case "RATE_LIMITED":
|
|
3889
|
+
return new RateLimitException(message, err);
|
|
3890
|
+
case "CONFIGURATION_ERROR":
|
|
3891
|
+
return new ConfigurationException(message, err);
|
|
3892
|
+
case "AUTHENTICATION_ERROR":
|
|
3893
|
+
return new AuthenticationException(message, err);
|
|
3894
|
+
default:
|
|
3895
|
+
return new RetrivoraError(message, defaultCode, err);
|
|
3896
|
+
}
|
|
3897
|
+
}
|
|
3898
|
+
|
|
3549
3899
|
// src/llm/LLMFactory.ts
|
|
3550
3900
|
var customProviders = /* @__PURE__ */ new Map();
|
|
3551
3901
|
var LLMFactory = class _LLMFactory {
|
|
@@ -3584,6 +3934,8 @@ var LLMFactory = class _LLMFactory {
|
|
|
3584
3934
|
"anthropic",
|
|
3585
3935
|
"ollama",
|
|
3586
3936
|
"gemini",
|
|
3937
|
+
"groq",
|
|
3938
|
+
"qwen",
|
|
3587
3939
|
"rest",
|
|
3588
3940
|
"universal_rest",
|
|
3589
3941
|
"custom",
|
|
@@ -3591,7 +3943,7 @@ var LLMFactory = class _LLMFactory {
|
|
|
3591
3943
|
];
|
|
3592
3944
|
}
|
|
3593
3945
|
static create(llmConfig, embeddingConfig) {
|
|
3594
|
-
var
|
|
3946
|
+
var _a2, _b, _c;
|
|
3595
3947
|
switch (llmConfig.provider) {
|
|
3596
3948
|
case "openai":
|
|
3597
3949
|
return new OpenAIProvider(llmConfig, embeddingConfig);
|
|
@@ -3601,12 +3953,16 @@ var LLMFactory = class _LLMFactory {
|
|
|
3601
3953
|
return new OllamaProvider(llmConfig, embeddingConfig);
|
|
3602
3954
|
case "gemini":
|
|
3603
3955
|
return new GeminiProvider(llmConfig, embeddingConfig);
|
|
3956
|
+
case "groq":
|
|
3957
|
+
return new GroqProvider(llmConfig, embeddingConfig);
|
|
3958
|
+
case "qwen":
|
|
3959
|
+
return new QwenProvider(llmConfig, embeddingConfig);
|
|
3604
3960
|
case "rest":
|
|
3605
3961
|
case "universal_rest":
|
|
3606
3962
|
case "custom":
|
|
3607
3963
|
return new UniversalLLMAdapter(llmConfig);
|
|
3608
3964
|
default: {
|
|
3609
|
-
const providerName = String((
|
|
3965
|
+
const providerName = String((_a2 = llmConfig.provider) != null ? _a2 : "").toLowerCase();
|
|
3610
3966
|
const customFactory = customProviders.get(providerName);
|
|
3611
3967
|
if (customFactory) {
|
|
3612
3968
|
return customFactory(llmConfig);
|
|
@@ -3615,9 +3971,12 @@ var LLMFactory = class _LLMFactory {
|
|
|
3615
3971
|
return new UniversalLLMAdapter(llmConfig);
|
|
3616
3972
|
}
|
|
3617
3973
|
throw new ProviderNotFoundException(
|
|
3618
|
-
"
|
|
3619
|
-
|
|
3620
|
-
|
|
3974
|
+
"llm",
|
|
3975
|
+
(_c = llmConfig.provider) != null ? _c : "undefined",
|
|
3976
|
+
{
|
|
3977
|
+
message: `Unknown provider "${llmConfig.provider}". Register a custom provider with LLMFactory.register().`,
|
|
3978
|
+
available: _LLMFactory.listProviders()
|
|
3979
|
+
}
|
|
3621
3980
|
);
|
|
3622
3981
|
}
|
|
3623
3982
|
}
|
|
@@ -3640,6 +3999,10 @@ var LLMFactory = class _LLMFactory {
|
|
|
3640
3999
|
return OllamaProvider;
|
|
3641
4000
|
case "gemini":
|
|
3642
4001
|
return GeminiProvider;
|
|
4002
|
+
case "groq":
|
|
4003
|
+
return GroqProvider;
|
|
4004
|
+
case "qwen":
|
|
4005
|
+
return QwenProvider;
|
|
3643
4006
|
case "rest":
|
|
3644
4007
|
case "universal_rest":
|
|
3645
4008
|
case "custom":
|
|
@@ -3701,7 +4064,7 @@ var ProviderRegistry = class {
|
|
|
3701
4064
|
return null;
|
|
3702
4065
|
}
|
|
3703
4066
|
static async loadVectorProviderClass(provider) {
|
|
3704
|
-
var
|
|
4067
|
+
var _a2;
|
|
3705
4068
|
if (this.vectorProviders[provider]) return this.vectorProviders[provider];
|
|
3706
4069
|
switch (provider) {
|
|
3707
4070
|
case "pinecone": {
|
|
@@ -3710,7 +4073,7 @@ var ProviderRegistry = class {
|
|
|
3710
4073
|
}
|
|
3711
4074
|
case "pgvector":
|
|
3712
4075
|
case "postgresql": {
|
|
3713
|
-
const postgresMode = ((
|
|
4076
|
+
const postgresMode = ((_a2 = process.env.POSTGRES_MODE) != null ? _a2 : "multi").toLowerCase();
|
|
3714
4077
|
if (postgresMode === "single") {
|
|
3715
4078
|
const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
|
|
3716
4079
|
return PostgreSQLProvider2;
|
|
@@ -3930,6 +4293,125 @@ var ConfigValidator = class {
|
|
|
3930
4293
|
}
|
|
3931
4294
|
};
|
|
3932
4295
|
|
|
4296
|
+
// src/core/LicenseVerifier.ts
|
|
4297
|
+
var crypto2 = __toESM(require("crypto"));
|
|
4298
|
+
var LicenseVerifier = class {
|
|
4299
|
+
/**
|
|
4300
|
+
* Decodes, verifies signature, and checks metadata of a license key.
|
|
4301
|
+
*
|
|
4302
|
+
* @param licenseKey - Base64url signed JWT license key.
|
|
4303
|
+
* @param currentProjectId - Project namespace ID.
|
|
4304
|
+
* @param publicKeyOverride - Optional override for unit/integration tests.
|
|
4305
|
+
*/
|
|
4306
|
+
static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
|
|
4307
|
+
const isProduction = process.env.NODE_ENV === "production";
|
|
4308
|
+
if (!licenseKey) {
|
|
4309
|
+
if (isProduction) {
|
|
4310
|
+
throw new ConfigurationException(
|
|
4311
|
+
"[Retrivora SDK] License key (licenseKey) is required in production environments."
|
|
4312
|
+
);
|
|
4313
|
+
}
|
|
4314
|
+
console.warn(
|
|
4315
|
+
`\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
|
|
4316
|
+
);
|
|
4317
|
+
return {
|
|
4318
|
+
projectId: currentProjectId,
|
|
4319
|
+
expiresAt: Math.floor(Date.now() / 1e3) + 86400,
|
|
4320
|
+
// Valid for 24h
|
|
4321
|
+
tier: "hobby"
|
|
4322
|
+
};
|
|
4323
|
+
}
|
|
4324
|
+
try {
|
|
4325
|
+
const parts = licenseKey.split(".");
|
|
4326
|
+
if (parts.length !== 3) {
|
|
4327
|
+
throw new Error("Malformed token structure (expected 3 parts).");
|
|
4328
|
+
}
|
|
4329
|
+
const [headerB64, payloadB64, signatureB64] = parts;
|
|
4330
|
+
const dataToVerify = `${headerB64}.${payloadB64}`;
|
|
4331
|
+
const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
|
|
4332
|
+
const signature = Buffer.from(signatureB64, "base64url");
|
|
4333
|
+
const data = Buffer.from(dataToVerify);
|
|
4334
|
+
const isValid = crypto2.verify(
|
|
4335
|
+
"sha256",
|
|
4336
|
+
data,
|
|
4337
|
+
publicKey,
|
|
4338
|
+
signature
|
|
4339
|
+
);
|
|
4340
|
+
if (!isValid) {
|
|
4341
|
+
throw new Error("Signature verification failed.");
|
|
4342
|
+
}
|
|
4343
|
+
const payload = JSON.parse(
|
|
4344
|
+
Buffer.from(payloadB64, "base64url").toString("utf8")
|
|
4345
|
+
);
|
|
4346
|
+
if (!payload.projectId) {
|
|
4347
|
+
throw new Error('License payload is missing "projectId".');
|
|
4348
|
+
}
|
|
4349
|
+
if (payload.projectId !== currentProjectId) {
|
|
4350
|
+
throw new Error(
|
|
4351
|
+
`Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
|
|
4352
|
+
);
|
|
4353
|
+
}
|
|
4354
|
+
if (!payload.expiresAt) {
|
|
4355
|
+
throw new Error('License payload is missing expiration ("expiresAt").');
|
|
4356
|
+
}
|
|
4357
|
+
const currentTimestampSec = Math.floor(Date.now() / 1e3);
|
|
4358
|
+
if (currentTimestampSec > payload.expiresAt) {
|
|
4359
|
+
throw new Error(
|
|
4360
|
+
`License key has expired. Expiration: ${new Date(
|
|
4361
|
+
payload.expiresAt * 1e3
|
|
4362
|
+
).toDateString()}`
|
|
4363
|
+
);
|
|
4364
|
+
}
|
|
4365
|
+
if (isProduction && provider) {
|
|
4366
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
4367
|
+
const normalizedProvider = provider.toLowerCase();
|
|
4368
|
+
if (tier === "hobby") {
|
|
4369
|
+
const allowedHobby = ["postgresql", "pgvector", "supabase"];
|
|
4370
|
+
if (!allowedHobby.includes(normalizedProvider)) {
|
|
4371
|
+
throw new Error(
|
|
4372
|
+
`The database provider "${provider}" is not allowed on the Hobby tier. Hobby tier is restricted to PostgreSQL and Supabase. Please upgrade to a Developer Pro or Enterprise plan.`
|
|
4373
|
+
);
|
|
4374
|
+
}
|
|
4375
|
+
} else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth") {
|
|
4376
|
+
const allowedPro = [
|
|
4377
|
+
"postgresql",
|
|
4378
|
+
"pgvector",
|
|
4379
|
+
"supabase",
|
|
4380
|
+
"pinecone",
|
|
4381
|
+
"qdrant",
|
|
4382
|
+
"mongodb",
|
|
4383
|
+
"milvus",
|
|
4384
|
+
"chroma",
|
|
4385
|
+
"chromadb"
|
|
4386
|
+
];
|
|
4387
|
+
if (!allowedPro.includes(normalizedProvider)) {
|
|
4388
|
+
throw new Error(
|
|
4389
|
+
`The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
|
|
4390
|
+
);
|
|
4391
|
+
}
|
|
4392
|
+
}
|
|
4393
|
+
}
|
|
4394
|
+
return payload;
|
|
4395
|
+
} catch (err) {
|
|
4396
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
4397
|
+
throw new ConfigurationException(
|
|
4398
|
+
`[Retrivora SDK] License key validation failed: ${message}`
|
|
4399
|
+
);
|
|
4400
|
+
}
|
|
4401
|
+
}
|
|
4402
|
+
};
|
|
4403
|
+
// Retrivora's Public Key used to verify the license key signature.
|
|
4404
|
+
// In production, this matches the private key held by Retrivora SaaS.
|
|
4405
|
+
LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
|
|
4406
|
+
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
|
|
4407
|
+
XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
|
|
4408
|
+
xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
|
|
4409
|
+
NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
|
|
4410
|
+
iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
|
|
4411
|
+
+Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
|
|
4412
|
+
MwIDAQAB
|
|
4413
|
+
-----END PUBLIC KEY-----`;
|
|
4414
|
+
|
|
3933
4415
|
// src/rag/DocumentChunker.ts
|
|
3934
4416
|
var DocumentChunker = class {
|
|
3935
4417
|
constructor(chunkSize = 1e3, chunkOverlap = 200, separators = ["\n# ", "\n## ", "\n### ", "\n#### ", "\n\n", "\n", " ", ""]) {
|
|
@@ -4159,11 +4641,11 @@ var LlamaIndexIngestor = class {
|
|
|
4159
4641
|
* than standard character-count splitting.
|
|
4160
4642
|
*/
|
|
4161
4643
|
async chunk(text, options = {}) {
|
|
4162
|
-
var
|
|
4644
|
+
var _a2, _b;
|
|
4163
4645
|
try {
|
|
4164
4646
|
const { Document, SentenceSplitter, MetadataMode } = await import(`${"llamaindex"}`);
|
|
4165
4647
|
const splitter = new SentenceSplitter({
|
|
4166
|
-
chunkSize: (
|
|
4648
|
+
chunkSize: (_a2 = options.chunkSize) != null ? _a2 : 1e3,
|
|
4167
4649
|
chunkOverlap: (_b = options.chunkOverlap) != null ? _b : 200
|
|
4168
4650
|
});
|
|
4169
4651
|
const doc = new Document({ text, metadata: options.metadata || {} });
|
|
@@ -4250,47 +4732,478 @@ When presenting structured data, statistics, or comparisons, decide if it is bes
|
|
|
4250
4732
|
if (!finalSystemPrompt.includes("chart")) {
|
|
4251
4733
|
finalSystemPrompt += chartInstruction;
|
|
4252
4734
|
}
|
|
4253
|
-
this.agent = createAgent({
|
|
4254
|
-
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4255
|
-
model: chatModel,
|
|
4256
|
-
tools: [searchTool],
|
|
4257
|
-
systemPrompt: finalSystemPrompt
|
|
4735
|
+
this.agent = createAgent({
|
|
4736
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
4737
|
+
model: chatModel,
|
|
4738
|
+
tools: [searchTool],
|
|
4739
|
+
systemPrompt: finalSystemPrompt
|
|
4740
|
+
});
|
|
4741
|
+
} catch (error) {
|
|
4742
|
+
const isMissing = error instanceof Error && error.message.includes("Cannot find module");
|
|
4743
|
+
const hint = isMissing ? " Make sure 'langchain' and '@langchain/core' are installed:\n npm install langchain @langchain/core" : "";
|
|
4744
|
+
throw new Error(
|
|
4745
|
+
`[LangChainAgent] Failed to initialize.${hint}
|
|
4746
|
+
${error instanceof Error ? error.message : String(error)}`
|
|
4747
|
+
);
|
|
4748
|
+
}
|
|
4749
|
+
}
|
|
4750
|
+
/**
|
|
4751
|
+
* Run the agentic flow.
|
|
4752
|
+
*
|
|
4753
|
+
* LangChain v1.x: invoke takes `{ messages: [...] }` instead of `{ input, chat_history }`.
|
|
4754
|
+
* The agent returns `{ messages: [...] }` — the last message is the final answer.
|
|
4755
|
+
*/
|
|
4756
|
+
async run(input, chatHistory = []) {
|
|
4757
|
+
var _a2, _b, _c;
|
|
4758
|
+
if (!this.agent) {
|
|
4759
|
+
throw new Error("[LangChainAgent] Agent not initialized. Call initialize() first.");
|
|
4760
|
+
}
|
|
4761
|
+
const { HumanMessage, AIMessage } = await import("@langchain/core/messages");
|
|
4762
|
+
const historyMessages = chatHistory.map(
|
|
4763
|
+
(m) => m.role === "user" ? new HumanMessage(m.content) : new AIMessage(m.content)
|
|
4764
|
+
);
|
|
4765
|
+
const response = await this.agent.invoke({
|
|
4766
|
+
messages: [...historyMessages, new HumanMessage(input)]
|
|
4767
|
+
});
|
|
4768
|
+
const lastMessage = (_a2 = response == null ? void 0 : response.messages) == null ? void 0 : _a2.at(-1);
|
|
4769
|
+
if (lastMessage && typeof lastMessage.content === "string") {
|
|
4770
|
+
return lastMessage.content;
|
|
4771
|
+
}
|
|
4772
|
+
if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
|
|
4773
|
+
return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
|
|
4774
|
+
}
|
|
4775
|
+
return String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
|
|
4776
|
+
}
|
|
4777
|
+
};
|
|
4778
|
+
|
|
4779
|
+
// src/core/mcp.ts
|
|
4780
|
+
var import_child_process = require("child_process");
|
|
4781
|
+
var MCPClient = class {
|
|
4782
|
+
constructor(config) {
|
|
4783
|
+
this.config = config;
|
|
4784
|
+
this.messageIdCounter = 0;
|
|
4785
|
+
this.pendingRequests = /* @__PURE__ */ new Map();
|
|
4786
|
+
this.stdioBuffer = "";
|
|
4787
|
+
this.initialized = false;
|
|
4788
|
+
}
|
|
4789
|
+
getNextMessageId() {
|
|
4790
|
+
return ++this.messageIdCounter;
|
|
4791
|
+
}
|
|
4792
|
+
/**
|
|
4793
|
+
* Connect and initialize the MCP server connection.
|
|
4794
|
+
*/
|
|
4795
|
+
async connect() {
|
|
4796
|
+
if (this.initialized) return;
|
|
4797
|
+
if (this.config.transport === "stdio") {
|
|
4798
|
+
await this.connectStdio();
|
|
4799
|
+
} else {
|
|
4800
|
+
await this.connectSSE();
|
|
4801
|
+
}
|
|
4802
|
+
try {
|
|
4803
|
+
const response = await this.sendJsonRpc("initialize", {
|
|
4804
|
+
protocolVersion: "2024-11-05",
|
|
4805
|
+
capabilities: {},
|
|
4806
|
+
clientInfo: {
|
|
4807
|
+
name: "retrivora-sdk",
|
|
4808
|
+
version: "1.0.0"
|
|
4809
|
+
}
|
|
4810
|
+
});
|
|
4811
|
+
await this.sendNotification("notifications/initialized");
|
|
4812
|
+
this.initialized = true;
|
|
4813
|
+
console.log(`[MCPClient] Connected and initialized server "${this.config.name}" successfully.`);
|
|
4814
|
+
} catch (err) {
|
|
4815
|
+
this.disconnect();
|
|
4816
|
+
throw new Error(`[MCPClient] Failed to initialize server "${this.config.name}": ${err.message}`);
|
|
4817
|
+
}
|
|
4818
|
+
}
|
|
4819
|
+
async connectStdio() {
|
|
4820
|
+
var _a2;
|
|
4821
|
+
const cmd = this.config.command;
|
|
4822
|
+
if (!cmd) {
|
|
4823
|
+
throw new Error(`[MCPClient] Command option is required for stdio transport on "${this.config.name}"`);
|
|
4824
|
+
}
|
|
4825
|
+
const args = this.config.args || [];
|
|
4826
|
+
const env = __spreadValues(__spreadValues({}, process.env), this.config.env || {});
|
|
4827
|
+
this.childProcess = (0, import_child_process.spawn)(cmd, args, { env, shell: true });
|
|
4828
|
+
if (!this.childProcess || !this.childProcess.stdout || !this.childProcess.stdin) {
|
|
4829
|
+
throw new Error(`[MCPClient] Failed to spawn stdio child process for "${this.config.name}"`);
|
|
4830
|
+
}
|
|
4831
|
+
this.childProcess.stdout.on("data", (data) => {
|
|
4832
|
+
this.stdioBuffer += data.toString("utf-8");
|
|
4833
|
+
this.processStdioLines();
|
|
4834
|
+
});
|
|
4835
|
+
(_a2 = this.childProcess.stderr) == null ? void 0 : _a2.on("data", (data) => {
|
|
4836
|
+
console.warn(`[MCPClient] [stderr] [${this.config.name}]:`, data.toString("utf-8"));
|
|
4837
|
+
});
|
|
4838
|
+
this.childProcess.on("close", (code) => {
|
|
4839
|
+
console.log(`[MCPClient] Connection closed for "${this.config.name}" with exit code: ${code}`);
|
|
4840
|
+
this.disconnect();
|
|
4841
|
+
});
|
|
4842
|
+
await new Promise((resolve) => setTimeout(resolve, 100));
|
|
4843
|
+
}
|
|
4844
|
+
processStdioLines() {
|
|
4845
|
+
let newlineIndex;
|
|
4846
|
+
while ((newlineIndex = this.stdioBuffer.indexOf("\n")) !== -1) {
|
|
4847
|
+
const line = this.stdioBuffer.substring(0, newlineIndex).trim();
|
|
4848
|
+
this.stdioBuffer = this.stdioBuffer.substring(newlineIndex + 1);
|
|
4849
|
+
if (!line) continue;
|
|
4850
|
+
try {
|
|
4851
|
+
const payload = JSON.parse(line);
|
|
4852
|
+
if (payload.id !== void 0) {
|
|
4853
|
+
const req = this.pendingRequests.get(Number(payload.id));
|
|
4854
|
+
if (req) {
|
|
4855
|
+
this.pendingRequests.delete(Number(payload.id));
|
|
4856
|
+
if (payload.error) {
|
|
4857
|
+
req.reject(new Error(payload.error.message || JSON.stringify(payload.error)));
|
|
4858
|
+
} else {
|
|
4859
|
+
req.resolve(payload.result);
|
|
4860
|
+
}
|
|
4861
|
+
}
|
|
4862
|
+
}
|
|
4863
|
+
} catch (e) {
|
|
4864
|
+
console.warn(`[MCPClient] Error parsing stdio JSON-RPC line from "${this.config.name}":`, e, "Line content:", line);
|
|
4865
|
+
}
|
|
4866
|
+
}
|
|
4867
|
+
}
|
|
4868
|
+
async connectSSE() {
|
|
4869
|
+
if (!this.config.url) {
|
|
4870
|
+
throw new Error(`[MCPClient] URL is required for sse transport on "${this.config.name}"`);
|
|
4871
|
+
}
|
|
4872
|
+
this.sseUrl = this.config.url;
|
|
4873
|
+
}
|
|
4874
|
+
async sendJsonRpc(method, params) {
|
|
4875
|
+
const id = this.getNextMessageId();
|
|
4876
|
+
const request = {
|
|
4877
|
+
jsonrpc: "2.0",
|
|
4878
|
+
id,
|
|
4879
|
+
method,
|
|
4880
|
+
params
|
|
4881
|
+
};
|
|
4882
|
+
if (this.config.transport === "stdio") {
|
|
4883
|
+
if (!this.childProcess || !this.childProcess.stdin) {
|
|
4884
|
+
throw new Error(`[MCPClient] Server "${this.config.name}" is not connected (stdio process missing)`);
|
|
4885
|
+
}
|
|
4886
|
+
return new Promise((resolve, reject) => {
|
|
4887
|
+
this.pendingRequests.set(id, { resolve, reject });
|
|
4888
|
+
this.childProcess.stdin.write(JSON.stringify(request) + "\n", "utf-8");
|
|
4258
4889
|
});
|
|
4259
|
-
}
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
|
|
4264
|
-
|
|
4265
|
-
|
|
4890
|
+
} else {
|
|
4891
|
+
if (!this.sseUrl) {
|
|
4892
|
+
throw new Error(`[MCPClient] Server "${this.config.name}" SSE URL is not initialized`);
|
|
4893
|
+
}
|
|
4894
|
+
const response = await fetch(this.sseUrl, {
|
|
4895
|
+
method: "POST",
|
|
4896
|
+
headers: { "Content-Type": "application/json" },
|
|
4897
|
+
body: JSON.stringify(request)
|
|
4898
|
+
});
|
|
4899
|
+
if (!response.ok) {
|
|
4900
|
+
throw new Error(`SSE JSON-RPC POST failed with status ${response.status}`);
|
|
4901
|
+
}
|
|
4902
|
+
const payload = await response.json();
|
|
4903
|
+
if (payload.error) {
|
|
4904
|
+
throw new Error(payload.error.message || JSON.stringify(payload.error));
|
|
4905
|
+
}
|
|
4906
|
+
return payload.result;
|
|
4907
|
+
}
|
|
4908
|
+
}
|
|
4909
|
+
async sendNotification(method, params) {
|
|
4910
|
+
var _a2;
|
|
4911
|
+
const notification = {
|
|
4912
|
+
jsonrpc: "2.0",
|
|
4913
|
+
method,
|
|
4914
|
+
params
|
|
4915
|
+
};
|
|
4916
|
+
if (this.config.transport === "stdio") {
|
|
4917
|
+
if ((_a2 = this.childProcess) == null ? void 0 : _a2.stdin) {
|
|
4918
|
+
this.childProcess.stdin.write(JSON.stringify(notification) + "\n", "utf-8");
|
|
4919
|
+
}
|
|
4920
|
+
} else if (this.sseUrl) {
|
|
4921
|
+
await fetch(this.sseUrl, {
|
|
4922
|
+
method: "POST",
|
|
4923
|
+
headers: { "Content-Type": "application/json" },
|
|
4924
|
+
body: JSON.stringify(notification)
|
|
4925
|
+
}).catch((err) => console.warn("[MCPClient] Failed to send notification over SSE:", err));
|
|
4266
4926
|
}
|
|
4267
4927
|
}
|
|
4268
4928
|
/**
|
|
4269
|
-
*
|
|
4270
|
-
*
|
|
4271
|
-
* LangChain v1.x: invoke takes `{ messages: [...] }` instead of `{ input, chat_history }`.
|
|
4272
|
-
* The agent returns `{ messages: [...] }` — the last message is the final answer.
|
|
4929
|
+
* List all tools offered by the MCP server.
|
|
4273
4930
|
*/
|
|
4274
|
-
async
|
|
4275
|
-
|
|
4276
|
-
|
|
4277
|
-
|
|
4931
|
+
async listTools() {
|
|
4932
|
+
await this.connect();
|
|
4933
|
+
const result = await this.sendJsonRpc("tools/list", {});
|
|
4934
|
+
return (result == null ? void 0 : result.tools) || [];
|
|
4935
|
+
}
|
|
4936
|
+
/**
|
|
4937
|
+
* Execute a tool on the MCP server.
|
|
4938
|
+
*/
|
|
4939
|
+
async callTool(name, args = {}) {
|
|
4940
|
+
await this.connect();
|
|
4941
|
+
return await this.sendJsonRpc("tools/call", { name, arguments: args });
|
|
4942
|
+
}
|
|
4943
|
+
disconnect() {
|
|
4944
|
+
this.initialized = false;
|
|
4945
|
+
this.pendingRequests.forEach((req) => req.reject(new Error("MCPClient disconnected")));
|
|
4946
|
+
this.pendingRequests.clear();
|
|
4947
|
+
if (this.childProcess) {
|
|
4948
|
+
try {
|
|
4949
|
+
this.childProcess.kill();
|
|
4950
|
+
} catch (e) {
|
|
4951
|
+
}
|
|
4952
|
+
this.childProcess = void 0;
|
|
4278
4953
|
}
|
|
4279
|
-
|
|
4280
|
-
|
|
4281
|
-
|
|
4954
|
+
}
|
|
4955
|
+
};
|
|
4956
|
+
var MCPRegistry = class {
|
|
4957
|
+
constructor(servers = []) {
|
|
4958
|
+
this.clients = [];
|
|
4959
|
+
this.clients = servers.map((cfg) => new MCPClient(cfg));
|
|
4960
|
+
}
|
|
4961
|
+
async getAllTools() {
|
|
4962
|
+
const list = [];
|
|
4963
|
+
await Promise.all(
|
|
4964
|
+
this.clients.map(async (client) => {
|
|
4965
|
+
try {
|
|
4966
|
+
const tools = await client.listTools();
|
|
4967
|
+
tools.forEach((t) => list.push({ serverName: client["config"].name, tool: t }));
|
|
4968
|
+
} catch (e) {
|
|
4969
|
+
console.warn(`[MCPRegistry] Failed to fetch tools from server "${client["config"].name}":`, e);
|
|
4970
|
+
}
|
|
4971
|
+
})
|
|
4282
4972
|
);
|
|
4283
|
-
|
|
4284
|
-
|
|
4285
|
-
|
|
4286
|
-
|
|
4287
|
-
|
|
4288
|
-
|
|
4973
|
+
return list;
|
|
4974
|
+
}
|
|
4975
|
+
async callTool(toolName, args = {}) {
|
|
4976
|
+
for (const client of this.clients) {
|
|
4977
|
+
try {
|
|
4978
|
+
const tools = await client.listTools();
|
|
4979
|
+
if (tools.some((t) => t.name === toolName)) {
|
|
4980
|
+
return await client.callTool(toolName, args);
|
|
4981
|
+
}
|
|
4982
|
+
} catch (e) {
|
|
4983
|
+
}
|
|
4289
4984
|
}
|
|
4290
|
-
|
|
4291
|
-
|
|
4985
|
+
throw new Error(`[MCPRegistry] Tool "${toolName}" not found on any registered MCP server.`);
|
|
4986
|
+
}
|
|
4987
|
+
disconnectAll() {
|
|
4988
|
+
this.clients.forEach((c) => c.disconnect());
|
|
4989
|
+
}
|
|
4990
|
+
};
|
|
4991
|
+
|
|
4992
|
+
// src/core/MultiAgentCoordinator.ts
|
|
4993
|
+
var MultiAgentCoordinator = class {
|
|
4994
|
+
constructor(options) {
|
|
4995
|
+
var _a2;
|
|
4996
|
+
this.llmProvider = options.llmProvider;
|
|
4997
|
+
this.mcpRegistry = options.mcpRegistry;
|
|
4998
|
+
this.documentSearch = options.documentSearch;
|
|
4999
|
+
this.maxIterations = (_a2 = options.maxIterations) != null ? _a2 : 5;
|
|
5000
|
+
}
|
|
5001
|
+
/**
|
|
5002
|
+
* Run the multi-agent coordination loop synchronously and return the final response.
|
|
5003
|
+
*/
|
|
5004
|
+
async run(question, history = []) {
|
|
5005
|
+
const generator = this.runStream(question, history);
|
|
5006
|
+
let finalReply = "";
|
|
5007
|
+
const sources = [];
|
|
5008
|
+
try {
|
|
5009
|
+
for (var iter = __forAwait(generator), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
5010
|
+
const chunk = temp.value;
|
|
5011
|
+
if (typeof chunk === "string") {
|
|
5012
|
+
finalReply += chunk;
|
|
5013
|
+
} else if (chunk && typeof chunk === "object") {
|
|
5014
|
+
if ("reply" in chunk && chunk.reply) {
|
|
5015
|
+
finalReply += chunk.reply;
|
|
5016
|
+
}
|
|
5017
|
+
if ("sources" in chunk && chunk.sources) {
|
|
5018
|
+
sources.push(...chunk.sources);
|
|
5019
|
+
}
|
|
5020
|
+
}
|
|
5021
|
+
}
|
|
5022
|
+
} catch (temp) {
|
|
5023
|
+
error = [temp];
|
|
5024
|
+
} finally {
|
|
5025
|
+
try {
|
|
5026
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
5027
|
+
} finally {
|
|
5028
|
+
if (error)
|
|
5029
|
+
throw error[0];
|
|
5030
|
+
}
|
|
4292
5031
|
}
|
|
4293
|
-
return
|
|
5032
|
+
return {
|
|
5033
|
+
reply: finalReply,
|
|
5034
|
+
sources
|
|
5035
|
+
};
|
|
5036
|
+
}
|
|
5037
|
+
/**
|
|
5038
|
+
* Run the multi-agent coordination loop as an async stream, yielding intermediate thought blocks and tool execution events.
|
|
5039
|
+
*/
|
|
5040
|
+
runStream(_0) {
|
|
5041
|
+
return __asyncGenerator(this, arguments, function* (question, history = []) {
|
|
5042
|
+
const mcpTools = yield new __await(this.mcpRegistry.getAllTools());
|
|
5043
|
+
let systemPrompt = `You are a goal-driven supervisor agent coordinating a RAG search engine and external MCP servers to solve the user's task.
|
|
5044
|
+
You must think step-by-step before acting. Write your internal thinking process inside a \`<think>...</think>\` block first, then act or answer.
|
|
5045
|
+
|
|
5046
|
+
Available Tools:
|
|
5047
|
+
- document_search(query: string): Search the vector database and knowledge base for documents.
|
|
5048
|
+
|
|
5049
|
+
${mcpTools.length > 0 ? "MCP Server Tools:" : ""}
|
|
5050
|
+
${mcpTools.map((mt) => {
|
|
5051
|
+
var _a2;
|
|
5052
|
+
return `- ${mt.tool.name}(${JSON.stringify(((_a2 = mt.tool.inputSchema) == null ? void 0 : _a2.properties) || {})}): ${mt.tool.description || "No description provided."}`;
|
|
5053
|
+
}).join("\n")}
|
|
5054
|
+
|
|
5055
|
+
Tool Calling Protocol:
|
|
5056
|
+
If you need to call a tool, write:
|
|
5057
|
+
TOOL_CALL: <toolName>({ "argName": "value" })
|
|
5058
|
+
And then STOP generating immediately.
|
|
5059
|
+
|
|
5060
|
+
Once you have gathered enough information to fully satisfy the user's query, write your final response directly after the closing \`</think>\` block.
|
|
5061
|
+
`;
|
|
5062
|
+
const supervisorHistory = [
|
|
5063
|
+
{ role: "system", content: systemPrompt },
|
|
5064
|
+
...history,
|
|
5065
|
+
{ role: "user", content: question }
|
|
5066
|
+
];
|
|
5067
|
+
let iteration = 0;
|
|
5068
|
+
const allSources = [];
|
|
5069
|
+
while (iteration < this.maxIterations) {
|
|
5070
|
+
iteration++;
|
|
5071
|
+
const context = "";
|
|
5072
|
+
let fullModelResponse = "";
|
|
5073
|
+
let textBuffer = "";
|
|
5074
|
+
let inThinking = false;
|
|
5075
|
+
let toolCallDetected = null;
|
|
5076
|
+
if (!this.llmProvider.chatStream) {
|
|
5077
|
+
const reply = yield new __await(this.llmProvider.chat(supervisorHistory, context));
|
|
5078
|
+
fullModelResponse = reply;
|
|
5079
|
+
const thinkIndex = reply.indexOf("<think>");
|
|
5080
|
+
const endThinkIndex = reply.indexOf("</think>");
|
|
5081
|
+
let thinkingText = "";
|
|
5082
|
+
let answerText = reply;
|
|
5083
|
+
if (thinkIndex !== -1 && endThinkIndex !== -1) {
|
|
5084
|
+
thinkingText = reply.substring(thinkIndex + 7, endThinkIndex);
|
|
5085
|
+
answerText = reply.substring(endThinkIndex + 8);
|
|
5086
|
+
yield { type: "thinking", text: thinkingText };
|
|
5087
|
+
}
|
|
5088
|
+
const toolMatch = answerText.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
|
|
5089
|
+
if (toolMatch) {
|
|
5090
|
+
const toolName = toolMatch[1];
|
|
5091
|
+
const toolArgsStr = toolMatch[2];
|
|
5092
|
+
try {
|
|
5093
|
+
const toolArgs = JSON.parse(toolArgsStr.trim());
|
|
5094
|
+
toolCallDetected = { name: toolName, args: toolArgs };
|
|
5095
|
+
} catch (e) {
|
|
5096
|
+
console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
|
|
5097
|
+
}
|
|
5098
|
+
} else {
|
|
5099
|
+
yield answerText;
|
|
5100
|
+
}
|
|
5101
|
+
} else {
|
|
5102
|
+
const stream = this.llmProvider.chatStream(supervisorHistory, context);
|
|
5103
|
+
try {
|
|
5104
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
5105
|
+
const chunk = temp.value;
|
|
5106
|
+
fullModelResponse += chunk;
|
|
5107
|
+
textBuffer += chunk;
|
|
5108
|
+
if (!inThinking && textBuffer.includes("<think>")) {
|
|
5109
|
+
inThinking = true;
|
|
5110
|
+
const idx = textBuffer.indexOf("<think>");
|
|
5111
|
+
textBuffer = textBuffer.slice(idx + 7);
|
|
5112
|
+
}
|
|
5113
|
+
if (inThinking && textBuffer.includes("</think>")) {
|
|
5114
|
+
inThinking = false;
|
|
5115
|
+
const idx = textBuffer.indexOf("</think>");
|
|
5116
|
+
const thinkingDelta = textBuffer.slice(0, idx);
|
|
5117
|
+
yield { type: "thinking", text: thinkingDelta };
|
|
5118
|
+
textBuffer = textBuffer.slice(idx + 8);
|
|
5119
|
+
}
|
|
5120
|
+
if (inThinking && textBuffer.length > 0) {
|
|
5121
|
+
yield { type: "thinking", text: textBuffer };
|
|
5122
|
+
textBuffer = "";
|
|
5123
|
+
}
|
|
5124
|
+
if (!inThinking && textBuffer.includes("TOOL_CALL:")) {
|
|
5125
|
+
const idx = textBuffer.indexOf("TOOL_CALL:");
|
|
5126
|
+
const precedingText = textBuffer.slice(0, idx);
|
|
5127
|
+
if (precedingText.trim()) {
|
|
5128
|
+
yield precedingText;
|
|
5129
|
+
}
|
|
5130
|
+
textBuffer = textBuffer.slice(idx);
|
|
5131
|
+
}
|
|
5132
|
+
if (!inThinking && !textBuffer.includes("TOOL_CALL:") && textBuffer.length > 0) {
|
|
5133
|
+
yield textBuffer;
|
|
5134
|
+
textBuffer = "";
|
|
5135
|
+
}
|
|
5136
|
+
}
|
|
5137
|
+
} catch (temp) {
|
|
5138
|
+
error = [temp];
|
|
5139
|
+
} finally {
|
|
5140
|
+
try {
|
|
5141
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
5142
|
+
} finally {
|
|
5143
|
+
if (error)
|
|
5144
|
+
throw error[0];
|
|
5145
|
+
}
|
|
5146
|
+
}
|
|
5147
|
+
if (textBuffer.trim()) {
|
|
5148
|
+
const toolMatch = textBuffer.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
|
|
5149
|
+
if (toolMatch) {
|
|
5150
|
+
const toolName = toolMatch[1];
|
|
5151
|
+
const toolArgsStr = toolMatch[2];
|
|
5152
|
+
try {
|
|
5153
|
+
const toolArgs = JSON.parse(toolArgsStr.trim());
|
|
5154
|
+
toolCallDetected = { name: toolName, args: toolArgs };
|
|
5155
|
+
} catch (e) {
|
|
5156
|
+
console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
|
|
5157
|
+
}
|
|
5158
|
+
} else {
|
|
5159
|
+
yield textBuffer;
|
|
5160
|
+
}
|
|
5161
|
+
}
|
|
5162
|
+
}
|
|
5163
|
+
supervisorHistory.push({ role: "assistant", content: fullModelResponse });
|
|
5164
|
+
if (toolCallDetected) {
|
|
5165
|
+
const { name: toolName, args: toolArgs } = toolCallDetected;
|
|
5166
|
+
yield {
|
|
5167
|
+
type: "thinking",
|
|
5168
|
+
text: `
|
|
5169
|
+
[Agent Call] Executing tool "${toolName}" with parameters ${JSON.stringify(toolArgs)}...
|
|
5170
|
+
`
|
|
5171
|
+
};
|
|
5172
|
+
let toolResultText = "";
|
|
5173
|
+
try {
|
|
5174
|
+
if (toolName === "document_search") {
|
|
5175
|
+
const searchRes = yield new __await(this.documentSearch(toolArgs.query || ""));
|
|
5176
|
+
toolResultText = `document_search returned:
|
|
5177
|
+
${searchRes.reply}
|
|
5178
|
+
|
|
5179
|
+
Sources count: ${searchRes.sources.length}`;
|
|
5180
|
+
if (searchRes.sources && searchRes.sources.length > 0) {
|
|
5181
|
+
allSources.push(...searchRes.sources);
|
|
5182
|
+
yield { reply: "", sources: searchRes.sources };
|
|
5183
|
+
}
|
|
5184
|
+
} else {
|
|
5185
|
+
const mcpRes = yield new __await(this.mcpRegistry.callTool(toolName, toolArgs));
|
|
5186
|
+
toolResultText = `MCP Tool "${toolName}" returned:
|
|
5187
|
+
${JSON.stringify(mcpRes.content)}`;
|
|
5188
|
+
}
|
|
5189
|
+
} catch (err) {
|
|
5190
|
+
toolResultText = `Error calling tool "${toolName}": ${err.message}`;
|
|
5191
|
+
}
|
|
5192
|
+
supervisorHistory.push({
|
|
5193
|
+
role: "user",
|
|
5194
|
+
content: `TOOL_RESULT for ${toolName}:
|
|
5195
|
+
${toolResultText}`
|
|
5196
|
+
});
|
|
5197
|
+
yield {
|
|
5198
|
+
type: "thinking",
|
|
5199
|
+
text: `[Agent Output] Tool "${toolName}" executed. Continuing reasoning...
|
|
5200
|
+
`
|
|
5201
|
+
};
|
|
5202
|
+
} else {
|
|
5203
|
+
break;
|
|
5204
|
+
}
|
|
5205
|
+
}
|
|
5206
|
+
});
|
|
4294
5207
|
}
|
|
4295
5208
|
};
|
|
4296
5209
|
|
|
@@ -4620,7 +5533,7 @@ var QueryProcessor = class {
|
|
|
4620
5533
|
* @param validFields Optional list of known filterable fields to look for
|
|
4621
5534
|
*/
|
|
4622
5535
|
static extractQueryFieldHints(question, validFields = []) {
|
|
4623
|
-
var
|
|
5536
|
+
var _a2, _b, _c, _d;
|
|
4624
5537
|
if (!question.trim()) return [];
|
|
4625
5538
|
const hints = /* @__PURE__ */ new Map();
|
|
4626
5539
|
const addHint = (value, field) => {
|
|
@@ -4700,7 +5613,7 @@ var QueryProcessor = class {
|
|
|
4700
5613
|
];
|
|
4701
5614
|
for (const p of universalPatterns) {
|
|
4702
5615
|
for (const match of question.matchAll(p.regex)) {
|
|
4703
|
-
const val = p.group ? (
|
|
5616
|
+
const val = p.group ? (_a2 = match[p.group]) != null ? _a2 : match[0] : match[0];
|
|
4704
5617
|
if (!val) continue;
|
|
4705
5618
|
if (p.field) addHint(val, p.field);
|
|
4706
5619
|
else addHint(val);
|
|
@@ -4924,11 +5837,11 @@ var LLMRouter = class {
|
|
|
4924
5837
|
* When provided it is used directly as the 'default' role without re-constructing.
|
|
4925
5838
|
*/
|
|
4926
5839
|
async initialize(prebuiltDefault) {
|
|
4927
|
-
var
|
|
5840
|
+
var _a2;
|
|
4928
5841
|
const defaultModel = prebuiltDefault != null ? prebuiltDefault : LLMFactory.create(this.config.llm, this.config.embedding);
|
|
4929
5842
|
this.models.set("default", defaultModel);
|
|
4930
5843
|
const envFastModel = process.env.FAST_LLM_MODEL;
|
|
4931
|
-
const providerFastDefault = (
|
|
5844
|
+
const providerFastDefault = (_a2 = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a2 : "";
|
|
4932
5845
|
const fastModelName = envFastModel || providerFastDefault;
|
|
4933
5846
|
if (fastModelName && fastModelName !== this.config.llm.model) {
|
|
4934
5847
|
console.log(`[LLMRouter] Fast role \u2192 provider="${this.config.llm.provider}" model="${fastModelName}"`);
|
|
@@ -4947,8 +5860,8 @@ var LLMRouter = class {
|
|
|
4947
5860
|
* Falls back to 'default' if the requested role is not registered.
|
|
4948
5861
|
*/
|
|
4949
5862
|
get(role) {
|
|
4950
|
-
var
|
|
4951
|
-
const provider = (
|
|
5863
|
+
var _a2;
|
|
5864
|
+
const provider = (_a2 = this.models.get(role)) != null ? _a2 : this.models.get("default");
|
|
4952
5865
|
if (!provider) {
|
|
4953
5866
|
throw new Error(`[LLMRouter] No provider registered for role: "${role}". Did you call initialize()?`);
|
|
4954
5867
|
}
|
|
@@ -4966,7 +5879,7 @@ var UITransformer = class _UITransformer {
|
|
|
4966
5879
|
* Prefer `analyzeAndDecide()` in production.
|
|
4967
5880
|
*/
|
|
4968
5881
|
static transform(userQuery, retrievedData, config, trainedSchema, intent) {
|
|
4969
|
-
var
|
|
5882
|
+
var _a2, _b, _c;
|
|
4970
5883
|
if (!retrievedData || retrievedData.length === 0) {
|
|
4971
5884
|
return this.createTextResponse("No data available", "No relevant data found for your query.");
|
|
4972
5885
|
}
|
|
@@ -4986,7 +5899,7 @@ var UITransformer = class _UITransformer {
|
|
|
4986
5899
|
return this.transformToBarChart(filteredData, profile, userQuery, resolvedIntent.visualizationHint === "ranking");
|
|
4987
5900
|
}
|
|
4988
5901
|
if (resolvedIntent.visualizationHint === "distribution") {
|
|
4989
|
-
return (
|
|
5902
|
+
return (_a2 = this.transformToHistogram(profile, userQuery)) != null ? _a2 : this.transformToBarChart(filteredData, profile, userQuery);
|
|
4990
5903
|
}
|
|
4991
5904
|
if (resolvedIntent.visualizationHint === "correlation") {
|
|
4992
5905
|
return (_b = this.transformToScatterPlot(profile, userQuery)) != null ? _b : this.transformToBarChart(filteredData, profile, userQuery);
|
|
@@ -5311,11 +6224,11 @@ ${schemaProfileText}` : ""}`;
|
|
|
5311
6224
|
};
|
|
5312
6225
|
}
|
|
5313
6226
|
static transformToPieChart(data, profile, query = "") {
|
|
5314
|
-
var
|
|
6227
|
+
var _a2;
|
|
5315
6228
|
const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
|
|
5316
6229
|
const categories = dimension ? Array.from(new Set(profile.records.map((record) => {
|
|
5317
|
-
var
|
|
5318
|
-
return String((
|
|
6230
|
+
var _a3;
|
|
6231
|
+
return String((_a3 = record.fields[dimension.key]) != null ? _a3 : "");
|
|
5319
6232
|
}).filter(Boolean))) : this.detectCategories(data);
|
|
5320
6233
|
if (categories.length === 0) return null;
|
|
5321
6234
|
const categoryData = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key) : this.aggregateByCategory(data, categories);
|
|
@@ -5325,7 +6238,7 @@ ${schemaProfileText}` : ""}`;
|
|
|
5325
6238
|
});
|
|
5326
6239
|
return {
|
|
5327
6240
|
type: "pie_chart",
|
|
5328
|
-
title: `Distribution by ${(
|
|
6241
|
+
title: `Distribution by ${(_a2 = dimension == null ? void 0 : dimension.label) != null ? _a2 : "Category"}`,
|
|
5329
6242
|
description: `Showing breakdown across ${pieData.length} categories`,
|
|
5330
6243
|
data: pieData
|
|
5331
6244
|
};
|
|
@@ -5335,8 +6248,8 @@ ${schemaProfileText}` : ""}`;
|
|
|
5335
6248
|
const valueField = profile.numericFields[0];
|
|
5336
6249
|
const buckets = /* @__PURE__ */ new Map();
|
|
5337
6250
|
profile.records.forEach((record) => {
|
|
5338
|
-
var
|
|
5339
|
-
const timestamp = String((
|
|
6251
|
+
var _a2, _b, _c;
|
|
6252
|
+
const timestamp = String((_a2 = record.fields[dateField.key]) != null ? _a2 : "");
|
|
5340
6253
|
const value = (_b = this.toFiniteNumber(record.fields[valueField.key])) != null ? _b : 0;
|
|
5341
6254
|
buckets.set(timestamp, ((_c = buckets.get(timestamp)) != null ? _c : 0) + value);
|
|
5342
6255
|
});
|
|
@@ -5349,23 +6262,23 @@ ${schemaProfileText}` : ""}`;
|
|
|
5349
6262
|
};
|
|
5350
6263
|
}
|
|
5351
6264
|
static transformToBarChart(data, profile, query = "", horizontal = false) {
|
|
5352
|
-
var
|
|
6265
|
+
var _a2;
|
|
5353
6266
|
const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
|
|
5354
6267
|
const measure = profile ? this.selectNumericField(profile, query) : void 0;
|
|
5355
6268
|
const aggregate = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key, measure == null ? void 0 : measure.key) : this.aggregateByCategory(data, this.detectCategories(data));
|
|
5356
6269
|
const barData = Object.entries(aggregate).map(([category, value]) => ({ category, value: Number(value) })).sort((a, b) => horizontal ? b.value - a.value : 0).slice(0, 12);
|
|
5357
6270
|
const fallbackData = barData.length > 0 ? barData : data.slice(0, 12).map((item, index) => {
|
|
5358
|
-
var
|
|
6271
|
+
var _a3, _b, _c, _d, _e;
|
|
5359
6272
|
const meta = item.metadata || {};
|
|
5360
6273
|
const label = String(
|
|
5361
|
-
(_c = (_b = (
|
|
6274
|
+
(_c = (_b = (_a3 = this.getDynamicVal(meta, "name")) != null ? _a3 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
|
|
5362
6275
|
);
|
|
5363
6276
|
const value = (_e = (_d = this.extractNumericValue(meta)) != null ? _d : item.score) != null ? _e : 0;
|
|
5364
6277
|
return { category: label, value: Number(value) };
|
|
5365
6278
|
});
|
|
5366
6279
|
return {
|
|
5367
6280
|
type: horizontal ? "horizontal_bar" : "bar_chart",
|
|
5368
|
-
title: dimension ? `${(
|
|
6281
|
+
title: dimension ? `${(_a2 = measure == null ? void 0 : measure.label) != null ? _a2 : "Count"} by ${dimension.label}` : "Comparison",
|
|
5369
6282
|
description: `Showing ${fallbackData.length} comparable values`,
|
|
5370
6283
|
data: fallbackData
|
|
5371
6284
|
};
|
|
@@ -5400,11 +6313,11 @@ ${schemaProfileText}` : ""}`;
|
|
|
5400
6313
|
if (fields.length < 2) return null;
|
|
5401
6314
|
const [xField, yField] = fields;
|
|
5402
6315
|
const points = profile.records.map((record) => {
|
|
5403
|
-
var
|
|
6316
|
+
var _a2;
|
|
5404
6317
|
const x = this.toFiniteNumber(record.fields[xField.key]);
|
|
5405
6318
|
const y = this.toFiniteNumber(record.fields[yField.key]);
|
|
5406
6319
|
if (x === null || y === null) return null;
|
|
5407
|
-
return { x, y, label: String((
|
|
6320
|
+
return { x, y, label: String((_a2 = this.getRecordLabel(record)) != null ? _a2 : record.id) };
|
|
5408
6321
|
}).filter((point) => point !== null).slice(0, 100);
|
|
5409
6322
|
if (points.length === 0) return null;
|
|
5410
6323
|
return {
|
|
@@ -5434,9 +6347,9 @@ ${schemaProfileText}` : ""}`;
|
|
|
5434
6347
|
static transformToRadarChart(data) {
|
|
5435
6348
|
const attributeMap = {};
|
|
5436
6349
|
data.forEach((item) => {
|
|
5437
|
-
var
|
|
6350
|
+
var _a2, _b, _c;
|
|
5438
6351
|
const meta = item.metadata || {};
|
|
5439
|
-
const seriesName = String((_c = (_b = (
|
|
6352
|
+
const seriesName = String((_c = (_b = (_a2 = meta.name) != null ? _a2 : meta.product) != null ? _b : item.id) != null ? _c : "Item");
|
|
5440
6353
|
Object.entries(meta).forEach(([key, val]) => {
|
|
5441
6354
|
if (typeof val === "number" && !["price", "id"].includes(key.toLowerCase())) {
|
|
5442
6355
|
if (!attributeMap[key]) attributeMap[key] = {};
|
|
@@ -5518,22 +6431,22 @@ ${schemaProfileText}` : ""}`;
|
|
|
5518
6431
|
return null;
|
|
5519
6432
|
}
|
|
5520
6433
|
static normalizeTransformation(payload) {
|
|
5521
|
-
var
|
|
6434
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j;
|
|
5522
6435
|
if (!payload || typeof payload !== "object") return null;
|
|
5523
6436
|
const p = payload;
|
|
5524
6437
|
const type = this.normalizeVisualizationType(
|
|
5525
|
-
String((_c = (_b = (
|
|
6438
|
+
String((_c = (_b = (_a2 = p.type) != null ? _a2 : p.view) != null ? _b : p.chartType) != null ? _c : "")
|
|
5526
6439
|
);
|
|
5527
6440
|
if (!type) return null;
|
|
5528
6441
|
const title = String((_e = (_d = p.title) != null ? _d : p.heading) != null ? _e : "Visualization");
|
|
5529
6442
|
const description = p.description ? String(p.description) : void 0;
|
|
5530
|
-
const rawData = (_j = (_i = (_h = (
|
|
6443
|
+
const rawData = (_j = (_i = (_h = (_g2 = (_f = p.data) != null ? _f : p.table) != null ? _g2 : p.rows) != null ? _h : p.items) != null ? _i : p.content) != null ? _j : null;
|
|
5531
6444
|
const data = type === "text" && typeof rawData === "string" ? { content: rawData } : rawData;
|
|
5532
6445
|
const transformation = { type, title, description, data };
|
|
5533
6446
|
return this.validateTransformation(transformation) ? transformation : null;
|
|
5534
6447
|
}
|
|
5535
6448
|
static normalizeVisualizationType(type) {
|
|
5536
|
-
var
|
|
6449
|
+
var _a2;
|
|
5537
6450
|
const mapping = {
|
|
5538
6451
|
pie: "pie_chart",
|
|
5539
6452
|
pie_chart: "pie_chart",
|
|
@@ -5561,7 +6474,7 @@ ${schemaProfileText}` : ""}`;
|
|
|
5561
6474
|
product_carousel: "product_carousel",
|
|
5562
6475
|
carousel: "carousel"
|
|
5563
6476
|
};
|
|
5564
|
-
return (
|
|
6477
|
+
return (_a2 = mapping[type.toLowerCase()]) != null ? _a2 : null;
|
|
5565
6478
|
}
|
|
5566
6479
|
static validateTransformation(t) {
|
|
5567
6480
|
const { type, data } = t;
|
|
@@ -5763,16 +6676,16 @@ ${schemaProfileText}` : ""}`;
|
|
|
5763
6676
|
return null;
|
|
5764
6677
|
}
|
|
5765
6678
|
static selectDimensionField(profile, query) {
|
|
5766
|
-
var
|
|
6679
|
+
var _a2, _b;
|
|
5767
6680
|
const productCategory = profile.categoricalFields.find(
|
|
5768
6681
|
(field) => /category|department|collection|type|group|segment|region|country|state|city/i.test(field.key)
|
|
5769
6682
|
);
|
|
5770
6683
|
const ranked = this.rankFieldsByQuery(profile.categoricalFields, query);
|
|
5771
|
-
return (_b = (
|
|
6684
|
+
return (_b = (_a2 = ranked[0]) != null ? _a2 : productCategory) != null ? _b : profile.categoricalFields[0];
|
|
5772
6685
|
}
|
|
5773
6686
|
static selectNumericField(profile, query) {
|
|
5774
|
-
var
|
|
5775
|
-
return (
|
|
6687
|
+
var _a2;
|
|
6688
|
+
return (_a2 = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a2 : profile.numericFields[0];
|
|
5776
6689
|
}
|
|
5777
6690
|
static rankFieldsByQuery(fields, query) {
|
|
5778
6691
|
const q = query.toLowerCase();
|
|
@@ -5801,8 +6714,8 @@ ${schemaProfileText}` : ""}`;
|
|
|
5801
6714
|
static aggregateProfileByDimension(profile, dimensionKey, measureKey) {
|
|
5802
6715
|
const result = {};
|
|
5803
6716
|
profile.records.forEach((record) => {
|
|
5804
|
-
var
|
|
5805
|
-
const category = String((
|
|
6717
|
+
var _a2, _b, _c;
|
|
6718
|
+
const category = String((_a2 = record.fields[dimensionKey]) != null ? _a2 : "Other").trim() || "Other";
|
|
5806
6719
|
const value = measureKey ? (_b = this.toFiniteNumber(record.fields[measureKey])) != null ? _b : 0 : 1;
|
|
5807
6720
|
result[category] = ((_c = result[category]) != null ? _c : 0) + value;
|
|
5808
6721
|
});
|
|
@@ -5881,8 +6794,8 @@ ${schemaProfileText}` : ""}`;
|
|
|
5881
6794
|
static aggregateByCategory(data, categories) {
|
|
5882
6795
|
const result = Object.fromEntries(categories.map((c) => [c, 0]));
|
|
5883
6796
|
data.forEach((item) => {
|
|
5884
|
-
var
|
|
5885
|
-
const cat = (
|
|
6797
|
+
var _a2;
|
|
6798
|
+
const cat = (_a2 = this.getProductCategory(item)) != null ? _a2 : "Other";
|
|
5886
6799
|
if (Object.prototype.hasOwnProperty.call(result, cat)) result[cat]++;
|
|
5887
6800
|
else result["Other"] = (result["Other"] || 0) + 1;
|
|
5888
6801
|
});
|
|
@@ -5890,17 +6803,17 @@ ${schemaProfileText}` : ""}`;
|
|
|
5890
6803
|
}
|
|
5891
6804
|
static extractTimeSeriesData(data) {
|
|
5892
6805
|
return data.map((item) => {
|
|
5893
|
-
var
|
|
6806
|
+
var _a2, _b, _c, _d, _e;
|
|
5894
6807
|
const meta = item.metadata || {};
|
|
5895
6808
|
return {
|
|
5896
|
-
timestamp: (_b = (
|
|
6809
|
+
timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
|
|
5897
6810
|
value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
|
|
5898
6811
|
label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
|
|
5899
6812
|
};
|
|
5900
6813
|
});
|
|
5901
6814
|
}
|
|
5902
6815
|
static extractNumericValue(meta) {
|
|
5903
|
-
var
|
|
6816
|
+
var _a2;
|
|
5904
6817
|
const preferredKeys = [
|
|
5905
6818
|
"value",
|
|
5906
6819
|
"count",
|
|
@@ -5915,7 +6828,7 @@ ${schemaProfileText}` : ""}`;
|
|
|
5915
6828
|
"price"
|
|
5916
6829
|
];
|
|
5917
6830
|
for (const key of preferredKeys) {
|
|
5918
|
-
const raw = (
|
|
6831
|
+
const raw = (_a2 = resolveMetadataValue(meta, key)) != null ? _a2 : meta[key];
|
|
5919
6832
|
const value = typeof raw === "number" ? raw : Number(String(raw != null ? raw : "").replace(/[$,% ,]/g, ""));
|
|
5920
6833
|
if (Number.isFinite(value)) return value;
|
|
5921
6834
|
}
|
|
@@ -6061,8 +6974,8 @@ ${schemaProfileText}` : ""}`;
|
|
|
6061
6974
|
let inStock = 0;
|
|
6062
6975
|
let outOfStock = 0;
|
|
6063
6976
|
data.forEach((d) => {
|
|
6064
|
-
var
|
|
6065
|
-
const cat = (
|
|
6977
|
+
var _a2, _b;
|
|
6978
|
+
const cat = (_a2 = this.getProductCategory(d)) != null ? _a2 : "Other";
|
|
6066
6979
|
if (cat === category) {
|
|
6067
6980
|
const quantity = (_b = this.extractStockQuantity(d)) != null ? _b : 1;
|
|
6068
6981
|
if (this.determineStockStatus(d)) inStock += quantity;
|
|
@@ -6106,9 +7019,9 @@ ${schemaProfileText}` : ""}`;
|
|
|
6106
7019
|
}
|
|
6107
7020
|
// ─── Product Extraction ───────────────────────────────────────────────────
|
|
6108
7021
|
static getDynamicVal(meta, uiKey, config, trainedSchema) {
|
|
6109
|
-
var
|
|
7022
|
+
var _a2;
|
|
6110
7023
|
if (!meta) return void 0;
|
|
6111
|
-
const mapping = (
|
|
7024
|
+
const mapping = (_a2 = config == null ? void 0 : config.rag) == null ? void 0 : _a2.uiMapping;
|
|
6112
7025
|
if ((mapping == null ? void 0 : mapping[uiKey]) && meta[mapping[uiKey]] !== void 0) return meta[mapping[uiKey]];
|
|
6113
7026
|
if (trainedSchema && typeof trainedSchema === "object") {
|
|
6114
7027
|
const trainedKey = trainedSchema[uiKey];
|
|
@@ -6117,13 +7030,13 @@ ${schemaProfileText}` : ""}`;
|
|
|
6117
7030
|
return resolveMetadataValue(meta, uiKey);
|
|
6118
7031
|
}
|
|
6119
7032
|
static extractProductInfo(item, config, trainedSchema) {
|
|
6120
|
-
var
|
|
7033
|
+
var _a2;
|
|
6121
7034
|
const meta = item.metadata || {};
|
|
6122
7035
|
const name = this.getDynamicVal(meta, "name", config, trainedSchema);
|
|
6123
7036
|
const price = this.getDynamicVal(meta, "price", config, trainedSchema);
|
|
6124
7037
|
const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
|
|
6125
7038
|
const description = this.cleanProductDescription(
|
|
6126
|
-
(
|
|
7039
|
+
(_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
|
|
6127
7040
|
);
|
|
6128
7041
|
if (name || this.isProductData(item)) {
|
|
6129
7042
|
let finalName = name ? String(name) : void 0;
|
|
@@ -6231,10 +7144,10 @@ RULES:
|
|
|
6231
7144
|
}
|
|
6232
7145
|
static buildContextSummary(sources, maxChars = 6e3) {
|
|
6233
7146
|
const items = sources.map((s, i) => {
|
|
6234
|
-
var
|
|
7147
|
+
var _a2, _b, _c, _d;
|
|
6235
7148
|
return {
|
|
6236
7149
|
index: i + 1,
|
|
6237
|
-
content: (_b = (
|
|
7150
|
+
content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
|
|
6238
7151
|
metadata: (_c = s.metadata) != null ? _c : {},
|
|
6239
7152
|
score: (_d = s.score) != null ? _d : 0
|
|
6240
7153
|
};
|
|
@@ -6427,9 +7340,11 @@ var Pipeline = class {
|
|
|
6427
7340
|
/** LRU-bounded cache: avoids re-embedding identical queries within the same process. */
|
|
6428
7341
|
this.embeddingCache = new LRUEmbeddingCache(500);
|
|
6429
7342
|
this.initialised = false;
|
|
6430
|
-
|
|
7343
|
+
/** Namespace-specific static cold context cache for CAG */
|
|
7344
|
+
this.coldContexts = /* @__PURE__ */ new Map();
|
|
7345
|
+
var _a2, _b, _c, _d, _e;
|
|
6431
7346
|
this.chunker = new DocumentChunker(
|
|
6432
|
-
(_b = (
|
|
7347
|
+
(_b = (_a2 = config.rag) == null ? void 0 : _a2.chunkSize) != null ? _b : 1e3,
|
|
6433
7348
|
(_d = (_c = config.rag) == null ? void 0 : _c.chunkOverlap) != null ? _d : 200
|
|
6434
7349
|
);
|
|
6435
7350
|
if (((_e = config.rag) == null ? void 0 : _e.chunkingStrategy) === "llamaindex") {
|
|
@@ -6445,7 +7360,7 @@ var Pipeline = class {
|
|
|
6445
7360
|
return this.initialised ? this.llmProvider : void 0;
|
|
6446
7361
|
}
|
|
6447
7362
|
async initialize() {
|
|
6448
|
-
var
|
|
7363
|
+
var _a2, _b, _c;
|
|
6449
7364
|
if (this.initialised) return;
|
|
6450
7365
|
const chartInstruction = `You are a helpful assistant. Use the provided context to answer questions accurately.
|
|
6451
7366
|
|
|
@@ -6488,12 +7403,47 @@ var Pipeline = class {
|
|
|
6488
7403
|
this.entityExtractor = new EntityExtractor(this.llmProvider);
|
|
6489
7404
|
}
|
|
6490
7405
|
await this.vectorDB.initialize();
|
|
6491
|
-
if (((
|
|
7406
|
+
if (((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) {
|
|
7407
|
+
this.mcpRegistry = new MCPRegistry(this.config.mcpServers || []);
|
|
7408
|
+
this.multiAgentCoordinator = new MultiAgentCoordinator({
|
|
7409
|
+
llmProvider: this.llmProvider,
|
|
7410
|
+
mcpRegistry: this.mcpRegistry,
|
|
7411
|
+
documentSearch: async (query) => {
|
|
7412
|
+
return this.runNormalQuery(query);
|
|
7413
|
+
}
|
|
7414
|
+
});
|
|
6492
7415
|
this.agent = new LangChainAgent(this, this.config);
|
|
6493
7416
|
await this.agent.initialize(this.llmProvider);
|
|
6494
7417
|
}
|
|
7418
|
+
if ((_c = (_b = this.config.rag) == null ? void 0 : _b.cag) == null ? void 0 : _c.enabled) {
|
|
7419
|
+
await this.loadColdContext(this.config.projectId);
|
|
7420
|
+
}
|
|
6495
7421
|
this.initialised = true;
|
|
6496
7422
|
}
|
|
7423
|
+
async loadColdContext(ns) {
|
|
7424
|
+
var _a2, _b;
|
|
7425
|
+
const cagConfig = (_a2 = this.config.rag) == null ? void 0 : _a2.cag;
|
|
7426
|
+
if (!cagConfig || !cagConfig.enabled) return;
|
|
7427
|
+
try {
|
|
7428
|
+
const coldNs = cagConfig.coldNamespace || ns;
|
|
7429
|
+
const limit = (_b = cagConfig.coldLimit) != null ? _b : 20;
|
|
7430
|
+
const queryText = cagConfig.coldQuery || "documentation";
|
|
7431
|
+
const queryVector = await this.embeddingProvider.embed(queryText, { taskType: "query" });
|
|
7432
|
+
const coldMatches = await this.vectorDB.query(queryVector, limit, coldNs);
|
|
7433
|
+
if (coldMatches.length > 0) {
|
|
7434
|
+
const formatted = coldMatches.map((m, i) => `[Cold Source ${i + 1}]
|
|
7435
|
+
${m.content}`).join("\n\n---\n\n");
|
|
7436
|
+
this.coldContexts.set(ns, formatted);
|
|
7437
|
+
console.log(`[Pipeline] Cold RAG (CAG) loaded ${coldMatches.length} documents into cached context for namespace: ${ns}`);
|
|
7438
|
+
} else {
|
|
7439
|
+
this.coldContexts.set(ns, "No cold context found.");
|
|
7440
|
+
console.warn(`[Pipeline] Cold RAG (CAG) initialized but no documents were found in namespace: ${coldNs}`);
|
|
7441
|
+
}
|
|
7442
|
+
} catch (err) {
|
|
7443
|
+
console.error(`[Pipeline] Failed to load Cold RAG (CAG) context for namespace ${ns}:`, err);
|
|
7444
|
+
this.coldContexts.set(ns, "Failed to load cold context.");
|
|
7445
|
+
}
|
|
7446
|
+
}
|
|
6497
7447
|
/**
|
|
6498
7448
|
* Ingest documents with automatic chunking, embedding, and batch upsert.
|
|
6499
7449
|
*/
|
|
@@ -6525,12 +7475,12 @@ var Pipeline = class {
|
|
|
6525
7475
|
}
|
|
6526
7476
|
/** Step 1: Chunk the document content. */
|
|
6527
7477
|
async prepareChunks(doc) {
|
|
6528
|
-
var
|
|
7478
|
+
var _a2, _b;
|
|
6529
7479
|
if (this.llamaIngestor) {
|
|
6530
7480
|
return this.llamaIngestor.chunk(doc.content, {
|
|
6531
7481
|
docId: doc.docId,
|
|
6532
7482
|
metadata: doc.metadata,
|
|
6533
|
-
chunkSize: (
|
|
7483
|
+
chunkSize: (_a2 = this.config.rag) == null ? void 0 : _a2.chunkSize,
|
|
6534
7484
|
chunkOverlap: (_b = this.config.rag) == null ? void 0 : _b.chunkOverlap
|
|
6535
7485
|
});
|
|
6536
7486
|
}
|
|
@@ -6552,7 +7502,7 @@ var Pipeline = class {
|
|
|
6552
7502
|
embedBatchOptions
|
|
6553
7503
|
);
|
|
6554
7504
|
if (vectors.length !== chunks.length) {
|
|
6555
|
-
throw new
|
|
7505
|
+
throw new EmbeddingFailedException(
|
|
6556
7506
|
`[Pipeline] Embedding mismatch: got ${vectors.length} vectors for ${chunks.length} chunks. Check embedding provider logs for individual chunk failures.`
|
|
6557
7507
|
);
|
|
6558
7508
|
}
|
|
@@ -6601,12 +7551,37 @@ var Pipeline = class {
|
|
|
6601
7551
|
extractionOptions
|
|
6602
7552
|
);
|
|
6603
7553
|
}
|
|
7554
|
+
async runNormalQuery(question, history = [], namespace) {
|
|
7555
|
+
const stream = this.askStreamInternal(question, history, namespace);
|
|
7556
|
+
let reply = "";
|
|
7557
|
+
let sources = [];
|
|
7558
|
+
try {
|
|
7559
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
7560
|
+
const chunk = temp.value;
|
|
7561
|
+
if (typeof chunk === "string") {
|
|
7562
|
+
reply += chunk;
|
|
7563
|
+
} else if (typeof chunk === "object" && chunk !== null) {
|
|
7564
|
+
if ("reply" in chunk && chunk.reply) reply += chunk.reply;
|
|
7565
|
+
if ("sources" in chunk && chunk.sources) sources = chunk.sources;
|
|
7566
|
+
}
|
|
7567
|
+
}
|
|
7568
|
+
} catch (temp) {
|
|
7569
|
+
error = [temp];
|
|
7570
|
+
} finally {
|
|
7571
|
+
try {
|
|
7572
|
+
more && (temp = iter.return) && await temp.call(iter);
|
|
7573
|
+
} finally {
|
|
7574
|
+
if (error)
|
|
7575
|
+
throw error[0];
|
|
7576
|
+
}
|
|
7577
|
+
}
|
|
7578
|
+
return { reply, sources };
|
|
7579
|
+
}
|
|
6604
7580
|
async ask(question, history = [], namespace) {
|
|
6605
|
-
var
|
|
7581
|
+
var _a2;
|
|
6606
7582
|
await this.initialize();
|
|
6607
|
-
if (((
|
|
6608
|
-
|
|
6609
|
-
return { reply: agentReply, sources: [] };
|
|
7583
|
+
if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
|
|
7584
|
+
return await this.multiAgentCoordinator.run(question, history);
|
|
6610
7585
|
}
|
|
6611
7586
|
const stream = this.askStream(question, history, namespace);
|
|
6612
7587
|
let reply = "";
|
|
@@ -6638,6 +7613,47 @@ var Pipeline = class {
|
|
|
6638
7613
|
}
|
|
6639
7614
|
return { reply, sources, graphData, ui_transformation: uiTransformation, trace };
|
|
6640
7615
|
}
|
|
7616
|
+
askStream(_0) {
|
|
7617
|
+
return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
|
|
7618
|
+
var _a2;
|
|
7619
|
+
yield new __await(this.initialize());
|
|
7620
|
+
if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
|
|
7621
|
+
const stream2 = this.multiAgentCoordinator.runStream(question, history);
|
|
7622
|
+
try {
|
|
7623
|
+
for (var iter = __forAwait(stream2), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
7624
|
+
const chunk = temp.value;
|
|
7625
|
+
yield chunk;
|
|
7626
|
+
}
|
|
7627
|
+
} catch (temp) {
|
|
7628
|
+
error = [temp];
|
|
7629
|
+
} finally {
|
|
7630
|
+
try {
|
|
7631
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
7632
|
+
} finally {
|
|
7633
|
+
if (error)
|
|
7634
|
+
throw error[0];
|
|
7635
|
+
}
|
|
7636
|
+
}
|
|
7637
|
+
return;
|
|
7638
|
+
}
|
|
7639
|
+
const stream = this.askStreamInternal(question, history, namespace);
|
|
7640
|
+
try {
|
|
7641
|
+
for (var iter2 = __forAwait(stream), more2, temp2, error2; more2 = !(temp2 = yield new __await(iter2.next())).done; more2 = false) {
|
|
7642
|
+
const chunk = temp2.value;
|
|
7643
|
+
yield chunk;
|
|
7644
|
+
}
|
|
7645
|
+
} catch (temp2) {
|
|
7646
|
+
error2 = [temp2];
|
|
7647
|
+
} finally {
|
|
7648
|
+
try {
|
|
7649
|
+
more2 && (temp2 = iter2.return) && (yield new __await(temp2.call(iter2)));
|
|
7650
|
+
} finally {
|
|
7651
|
+
if (error2)
|
|
7652
|
+
throw error2[0];
|
|
7653
|
+
}
|
|
7654
|
+
}
|
|
7655
|
+
});
|
|
7656
|
+
}
|
|
6641
7657
|
/**
|
|
6642
7658
|
* High-performance streaming RAG flow.
|
|
6643
7659
|
* Yields text chunks first, then the retrieval metadata + observability trace at the end.
|
|
@@ -6648,12 +7664,12 @@ var Pipeline = class {
|
|
|
6648
7664
|
* - UITransformation is computed after text streaming and emitted with metadata
|
|
6649
7665
|
* - SchemaMapper.train runs while answer generation streams
|
|
6650
7666
|
*/
|
|
6651
|
-
|
|
7667
|
+
askStreamInternal(_0) {
|
|
6652
7668
|
return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
|
|
6653
|
-
var
|
|
7669
|
+
var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
|
|
6654
7670
|
yield new __await(this.initialize());
|
|
6655
7671
|
const ns = namespace != null ? namespace : this.config.projectId;
|
|
6656
|
-
const topK = (_b = (
|
|
7672
|
+
const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
|
|
6657
7673
|
const scoreThreshold = (_d = (_c = this.config.rag) == null ? void 0 : _c.scoreThreshold) != null ? _d : 0.3;
|
|
6658
7674
|
const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
|
|
6659
7675
|
const requestStart = performance.now();
|
|
@@ -6666,7 +7682,7 @@ var Pipeline = class {
|
|
|
6666
7682
|
}
|
|
6667
7683
|
const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
|
|
6668
7684
|
const filter = QueryProcessor.buildQueryFilter(question, hints);
|
|
6669
|
-
const numericPredicates = QueryProcessor.extractNumericPredicates(question, (
|
|
7685
|
+
const numericPredicates = QueryProcessor.extractNumericPredicates(question, (_g2 = this.config.rag) == null ? void 0 : _g2.filterableFields);
|
|
6670
7686
|
if (numericPredicates.length > 0) {
|
|
6671
7687
|
filter.__numericPredicates = numericPredicates;
|
|
6672
7688
|
}
|
|
@@ -6732,6 +7748,32 @@ ${graphContext}
|
|
|
6732
7748
|
VECTOR CONTEXT:
|
|
6733
7749
|
${context}`;
|
|
6734
7750
|
}
|
|
7751
|
+
if ((_n = (_m = this.config.rag) == null ? void 0 : _m.cag) == null ? void 0 : _n.enabled) {
|
|
7752
|
+
if (!this.coldContexts.has(ns)) {
|
|
7753
|
+
yield new __await(this.loadColdContext(ns));
|
|
7754
|
+
}
|
|
7755
|
+
const coldContext = this.coldContexts.get(ns);
|
|
7756
|
+
if (coldContext && coldContext !== "No cold context found." && coldContext !== "Failed to load cold context.") {
|
|
7757
|
+
context = `COLD CONTEXT (STATIC KNOWLEDGE):
|
|
7758
|
+
${coldContext}
|
|
7759
|
+
|
|
7760
|
+
RETRIEVED HOT CONTEXT (REAL-TIME KNOWLEDGE):
|
|
7761
|
+
${context}`;
|
|
7762
|
+
}
|
|
7763
|
+
}
|
|
7764
|
+
yield {
|
|
7765
|
+
reply: "",
|
|
7766
|
+
sources: sources.map((s) => {
|
|
7767
|
+
var _a3;
|
|
7768
|
+
return {
|
|
7769
|
+
id: s.id,
|
|
7770
|
+
score: s.score,
|
|
7771
|
+
content: s.content,
|
|
7772
|
+
metadata: (_a3 = s.metadata) != null ? _a3 : {},
|
|
7773
|
+
namespace: ns
|
|
7774
|
+
};
|
|
7775
|
+
})
|
|
7776
|
+
};
|
|
6735
7777
|
const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
|
|
6736
7778
|
const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
|
|
6737
7779
|
if (allMetadataKeys.length > 0 && !cachedSchema) {
|
|
@@ -6759,10 +7801,10 @@ ${context}`;
|
|
|
6759
7801
|
let hallucinationScoringPromise = Promise.resolve(void 0);
|
|
6760
7802
|
const restrictionSuffix = "\n\n(IMPORTANT: Format your response beautifully using rich Markdown! Use bolding for emphasis, headings (##) for structure, bullet points for lists, and proper line breaks between paragraphs to make it highly readable. However, NEVER generate Markdown tables, HTML figures, or text charts (the UI renders requested charts separately, so NEVER say you cannot create, display, draw, render, or provide a chart/visualization). If listing products, use simple markdown bullet points or comma-separated names. NEVER use plus signs (+) to separate product names, category names, or list items. For product description/detail questions, provide customer-facing prose only and do NOT list internal catalog fields such as Handle, Body (HTML), Vendor, Type, Tags, Published, Option, Variant, SKU, or raw metadata labels. You CAN use numbers for years/counts like 2006 or 5800, but NEVER put a dollar sign ($) before them.)";
|
|
6761
7803
|
const isClaude37 = this.config.llm.model.includes("claude-3-7-sonnet");
|
|
6762
|
-
const isNativeThinking = isClaude37 && (((
|
|
7804
|
+
const isNativeThinking = isClaude37 && (((_o = this.config.llm.options) == null ? void 0 : _o.thinking) === true || ((_p = this.config.llm.options) == null ? void 0 : _p.thinking) === "enabled" || ((_q = this.config.llm.options) == null ? void 0 : _q.thinking) !== false);
|
|
6763
7805
|
const modelNameLower = this.config.llm.model.toLowerCase();
|
|
6764
7806
|
const isReasoningModel = modelNameLower.includes("-r1") || modelNameLower.includes("deepseek-r1") || modelNameLower.includes("reasoning") || modelNameLower.includes("thinking");
|
|
6765
|
-
const isSimulatedThinking = !isNativeThinking && (((
|
|
7807
|
+
const isSimulatedThinking = !isNativeThinking && (((_r = this.config.llm.options) == null ? void 0 : _r.thinking) === true || ((_s = this.config.llm.options) == null ? void 0 : _s.thinking) === "enabled" || isReasoningModel && ((_t = this.config.llm.options) == null ? void 0 : _t.thinking) !== false);
|
|
6766
7808
|
let finalRestrictionSuffix = restrictionSuffix;
|
|
6767
7809
|
if (isSimulatedThinking) {
|
|
6768
7810
|
finalRestrictionSuffix += "\n\n(IMPORTANT: You must think step-by-step before answering. Write your thinking process inside a `<think>...</think>` block. Write the `<think>` block first, then follow it with your final response. Keep the thinking process thorough and detailed. Example: `<think>Thinking details here...</think>Final answer text here.`)";
|
|
@@ -6770,7 +7812,7 @@ ${context}`;
|
|
|
6770
7812
|
const hardenedHistory = [...history];
|
|
6771
7813
|
const userQuestion = { role: "user", content: question + finalRestrictionSuffix };
|
|
6772
7814
|
const messages = [...hardenedHistory, userQuestion];
|
|
6773
|
-
const systemPrompt = (
|
|
7815
|
+
const systemPrompt = (_u = this.config.llm.systemPrompt) != null ? _u : "";
|
|
6774
7816
|
const userPrompt = messages.map((m) => `${m.role}: ${m.content}`).join("\n");
|
|
6775
7817
|
let fullReply = "";
|
|
6776
7818
|
let thinkingText = "";
|
|
@@ -6881,7 +7923,7 @@ ${context}`;
|
|
|
6881
7923
|
}
|
|
6882
7924
|
yield fullReply;
|
|
6883
7925
|
}
|
|
6884
|
-
const runHallucination = ((
|
|
7926
|
+
const runHallucination = ((_v = this.config.llm.options) == null ? void 0 : _v.hallucinationScoring) === true || this.config.llm.provider !== "ollama" && ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) !== false;
|
|
6885
7927
|
if (runHallucination) {
|
|
6886
7928
|
hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
|
|
6887
7929
|
}
|
|
@@ -6890,7 +7932,7 @@ ${context}`;
|
|
|
6890
7932
|
const latency = {
|
|
6891
7933
|
embedMs: Math.round(embedMs),
|
|
6892
7934
|
retrieveMs: Math.round(retrieveMs),
|
|
6893
|
-
rerankMs: ((
|
|
7935
|
+
rerankMs: ((_x = this.config.rag) == null ? void 0 : _x.useReranking) ? Math.round(rerankMs) : void 0,
|
|
6894
7936
|
generateMs: Math.round(generateMs),
|
|
6895
7937
|
totalMs: Math.round(totalMs)
|
|
6896
7938
|
};
|
|
@@ -6903,33 +7945,63 @@ ${context}`;
|
|
|
6903
7945
|
totalTokens: promptTokens + completionTokens,
|
|
6904
7946
|
estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
|
|
6905
7947
|
};
|
|
7948
|
+
const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
|
|
6906
7949
|
const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
|
|
6907
7950
|
uiTransformationPromise,
|
|
6908
|
-
hallucinationScoringPromise
|
|
7951
|
+
awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
|
|
6909
7952
|
]));
|
|
6910
|
-
const
|
|
7953
|
+
const buildTrace = (hScore) => __spreadValues({
|
|
6911
7954
|
requestId,
|
|
6912
7955
|
query: question,
|
|
6913
7956
|
rewrittenQuery,
|
|
6914
7957
|
systemPrompt,
|
|
6915
7958
|
userPrompt: question + finalRestrictionSuffix,
|
|
6916
7959
|
chunks: sources.map((s) => {
|
|
6917
|
-
var
|
|
7960
|
+
var _a3;
|
|
6918
7961
|
return {
|
|
6919
7962
|
id: s.id,
|
|
6920
7963
|
score: s.score,
|
|
6921
7964
|
content: s.content,
|
|
6922
|
-
metadata: (
|
|
7965
|
+
metadata: (_a3 = s.metadata) != null ? _a3 : {},
|
|
6923
7966
|
namespace: ns
|
|
6924
7967
|
};
|
|
6925
7968
|
}),
|
|
6926
7969
|
latency,
|
|
6927
7970
|
tokens,
|
|
6928
7971
|
timestamp: (/* @__PURE__ */ new Date()).toISOString()
|
|
6929
|
-
},
|
|
6930
|
-
hallucinationScore:
|
|
6931
|
-
hallucinationReason:
|
|
7972
|
+
}, hScore ? {
|
|
7973
|
+
hallucinationScore: hScore.score,
|
|
7974
|
+
hallucinationReason: hScore.reason
|
|
6932
7975
|
} : {});
|
|
7976
|
+
const trace = buildTrace(hallucinationResult);
|
|
7977
|
+
if ((_z = this.config.telemetry) == null ? void 0 : _z.enabled) {
|
|
7978
|
+
const telemetryUrl = this.config.telemetry.url || "/api/telemetry";
|
|
7979
|
+
const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
|
|
7980
|
+
(async () => {
|
|
7981
|
+
try {
|
|
7982
|
+
let finalTrace = trace;
|
|
7983
|
+
if (!awaitHallucination && runHallucination) {
|
|
7984
|
+
const backgroundScoreResult = await hallucinationScoringPromise;
|
|
7985
|
+
if (backgroundScoreResult) {
|
|
7986
|
+
finalTrace = buildTrace(backgroundScoreResult);
|
|
7987
|
+
}
|
|
7988
|
+
}
|
|
7989
|
+
await fetch(absoluteUrl, {
|
|
7990
|
+
method: "POST",
|
|
7991
|
+
headers: {
|
|
7992
|
+
"Content-Type": "application/json"
|
|
7993
|
+
},
|
|
7994
|
+
body: JSON.stringify({
|
|
7995
|
+
trace: finalTrace,
|
|
7996
|
+
licenseKey: this.config.licenseKey,
|
|
7997
|
+
projectId: ns
|
|
7998
|
+
})
|
|
7999
|
+
});
|
|
8000
|
+
} catch (err) {
|
|
8001
|
+
console.warn(`[Pipeline Telemetry] Failed to send trace async to ${absoluteUrl}:`, err.message);
|
|
8002
|
+
}
|
|
8003
|
+
})();
|
|
8004
|
+
}
|
|
6933
8005
|
yield {
|
|
6934
8006
|
reply: "",
|
|
6935
8007
|
sources,
|
|
@@ -6949,7 +8021,7 @@ ${context}`;
|
|
|
6949
8021
|
* Uses an LRU-bounded embedding cache to avoid re-embedding the same query.
|
|
6950
8022
|
*/
|
|
6951
8023
|
async generateUiTransformation(question, sources, cachedSchema, forceDeterministic = false) {
|
|
6952
|
-
var
|
|
8024
|
+
var _a2;
|
|
6953
8025
|
if (!sources || sources.length === 0) {
|
|
6954
8026
|
return UITransformer.transform(question, sources, this.config, cachedSchema);
|
|
6955
8027
|
}
|
|
@@ -6963,7 +8035,7 @@ ${context}`;
|
|
|
6963
8035
|
);
|
|
6964
8036
|
}
|
|
6965
8037
|
const isLocalProvider = this.config.llm.provider === "ollama";
|
|
6966
|
-
const disableLlmUiTransform = ((
|
|
8038
|
+
const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
|
|
6967
8039
|
if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
|
|
6968
8040
|
return UITransformer.transform(question, sources, this.config, cachedSchema);
|
|
6969
8041
|
}
|
|
@@ -6981,9 +8053,9 @@ ${context}`;
|
|
|
6981
8053
|
const value = this.resolveNumericPredicateValue(source, predicate);
|
|
6982
8054
|
return value !== null && this.matchesNumericPredicate(value, predicate);
|
|
6983
8055
|
})).sort((a, b) => {
|
|
6984
|
-
var
|
|
8056
|
+
var _a2, _b;
|
|
6985
8057
|
const primary = predicates[0];
|
|
6986
|
-
const aValue = (
|
|
8058
|
+
const aValue = (_a2 = this.resolveNumericPredicateValue(a, primary)) != null ? _a2 : 0;
|
|
6987
8059
|
const bValue = (_b = this.resolveNumericPredicateValue(b, primary)) != null ? _b : 0;
|
|
6988
8060
|
return primary.operator === "lt" || primary.operator === "lte" ? aValue - bValue : bValue - aValue;
|
|
6989
8061
|
});
|
|
@@ -7055,8 +8127,8 @@ ${context}`;
|
|
|
7055
8127
|
return Number.isFinite(numeric) ? numeric : null;
|
|
7056
8128
|
}
|
|
7057
8129
|
async retrieve(query, options) {
|
|
7058
|
-
var
|
|
7059
|
-
const ns = (
|
|
8130
|
+
var _a2, _b, _c, _d, _e, _f, _g2;
|
|
8131
|
+
const ns = (_a2 = options.namespace) != null ? _a2 : this.config.projectId;
|
|
7060
8132
|
const topK = (_b = options.topK) != null ? _b : 5;
|
|
7061
8133
|
const cacheKey = `${ns}::${query}`;
|
|
7062
8134
|
let queryVector = this.embeddingCache.get(cacheKey);
|
|
@@ -7088,7 +8160,7 @@ ${context}`;
|
|
|
7088
8160
|
) : [];
|
|
7089
8161
|
const resolvedSources = [];
|
|
7090
8162
|
for (const source of sources) {
|
|
7091
|
-
const parentId = (
|
|
8163
|
+
const parentId = (_g2 = source.metadata) == null ? void 0 : _g2.parent_id;
|
|
7092
8164
|
if (parentId) {
|
|
7093
8165
|
console.log(`[Pipeline] Multi-Vector: Found child chunk. Parent ID: ${parentId}`);
|
|
7094
8166
|
resolvedSources.push(source);
|
|
@@ -7148,18 +8220,100 @@ Suggestions:`;
|
|
|
7148
8220
|
systemPrompt: "You are a helpful assistant that generates search suggestions based on the provided snippets. Focus on questions that can be answered by the context, keep each under 10 words, and return ONLY a JSON array of strings.",
|
|
7149
8221
|
temperature: 0
|
|
7150
8222
|
}
|
|
7151
|
-
);
|
|
7152
|
-
const match = response.match(/\[[\s\S]*\]/);
|
|
7153
|
-
if (match) {
|
|
7154
|
-
const suggestions = JSON.parse(match[0]);
|
|
7155
|
-
if (Array.isArray(suggestions)) {
|
|
7156
|
-
return suggestions.map((s) => String(s)).slice(0, 5);
|
|
8223
|
+
);
|
|
8224
|
+
const match = response.match(/\[[\s\S]*\]/);
|
|
8225
|
+
if (match) {
|
|
8226
|
+
const suggestions = JSON.parse(match[0]);
|
|
8227
|
+
if (Array.isArray(suggestions)) {
|
|
8228
|
+
return suggestions.map((s) => String(s)).slice(0, 5);
|
|
8229
|
+
}
|
|
8230
|
+
}
|
|
8231
|
+
} catch (error) {
|
|
8232
|
+
console.error("[Pipeline] Failed to generate suggestions:", error);
|
|
8233
|
+
}
|
|
8234
|
+
return [];
|
|
8235
|
+
}
|
|
8236
|
+
};
|
|
8237
|
+
|
|
8238
|
+
// src/core/Retrivora.ts
|
|
8239
|
+
var Retrivora = class {
|
|
8240
|
+
constructor(config) {
|
|
8241
|
+
this.config = ConfigResolver.resolveUniversal(config);
|
|
8242
|
+
this.pipeline = new Pipeline(this.config);
|
|
8243
|
+
}
|
|
8244
|
+
async initialize() {
|
|
8245
|
+
var _a2;
|
|
8246
|
+
try {
|
|
8247
|
+
await ConfigValidator.validateAndThrow(this.config);
|
|
8248
|
+
LicenseVerifier.verify(
|
|
8249
|
+
this.config.licenseKey,
|
|
8250
|
+
this.config.projectId,
|
|
8251
|
+
(_a2 = this.config.vectorDb) == null ? void 0 : _a2.provider
|
|
8252
|
+
);
|
|
8253
|
+
} catch (err) {
|
|
8254
|
+
throw wrapError(err, "CONFIGURATION_ERROR");
|
|
8255
|
+
}
|
|
8256
|
+
try {
|
|
8257
|
+
await this.pipeline.initialize();
|
|
8258
|
+
} catch (err) {
|
|
8259
|
+
throw wrapError(err, "AUTHENTICATION_ERROR");
|
|
8260
|
+
}
|
|
8261
|
+
}
|
|
8262
|
+
async ingest(documents, namespace) {
|
|
8263
|
+
try {
|
|
8264
|
+
return await this.pipeline.ingest(documents, namespace);
|
|
8265
|
+
} catch (err) {
|
|
8266
|
+
const msg = String(err);
|
|
8267
|
+
let defaultCode = "RETRIEVAL_FAILED";
|
|
8268
|
+
if (msg.includes("Embed") || msg.includes("embed")) {
|
|
8269
|
+
defaultCode = "EMBEDDING_FAILED";
|
|
8270
|
+
}
|
|
8271
|
+
throw wrapError(err, defaultCode);
|
|
8272
|
+
}
|
|
8273
|
+
}
|
|
8274
|
+
async ask(question, history = [], namespace) {
|
|
8275
|
+
try {
|
|
8276
|
+
return await this.pipeline.ask(question, history, namespace);
|
|
8277
|
+
} catch (err) {
|
|
8278
|
+
const msg = String(err);
|
|
8279
|
+
let defaultCode = "RETRIEVAL_FAILED";
|
|
8280
|
+
if (msg.includes("Embed") || msg.includes("embed")) {
|
|
8281
|
+
defaultCode = "EMBEDDING_FAILED";
|
|
8282
|
+
}
|
|
8283
|
+
throw wrapError(err, defaultCode);
|
|
8284
|
+
}
|
|
8285
|
+
}
|
|
8286
|
+
askStream(_0) {
|
|
8287
|
+
return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
|
|
8288
|
+
try {
|
|
8289
|
+
const stream = this.pipeline.askStream(question, history, namespace);
|
|
8290
|
+
try {
|
|
8291
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
8292
|
+
const chunk = temp.value;
|
|
8293
|
+
yield chunk;
|
|
8294
|
+
}
|
|
8295
|
+
} catch (temp) {
|
|
8296
|
+
error = [temp];
|
|
8297
|
+
} finally {
|
|
8298
|
+
try {
|
|
8299
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
8300
|
+
} finally {
|
|
8301
|
+
if (error)
|
|
8302
|
+
throw error[0];
|
|
8303
|
+
}
|
|
8304
|
+
}
|
|
8305
|
+
} catch (err) {
|
|
8306
|
+
const msg = String(err);
|
|
8307
|
+
let defaultCode = "RETRIEVAL_FAILED";
|
|
8308
|
+
if (msg.includes("Embed") || msg.includes("embed")) {
|
|
8309
|
+
defaultCode = "EMBEDDING_FAILED";
|
|
7157
8310
|
}
|
|
8311
|
+
throw wrapError(err, defaultCode);
|
|
7158
8312
|
}
|
|
7159
|
-
}
|
|
7160
|
-
|
|
7161
|
-
|
|
7162
|
-
return
|
|
8313
|
+
});
|
|
8314
|
+
}
|
|
8315
|
+
getPipeline() {
|
|
8316
|
+
return this.pipeline;
|
|
7163
8317
|
}
|
|
7164
8318
|
};
|
|
7165
8319
|
|
|
@@ -7269,9 +8423,20 @@ var ProviderHealthCheck = class {
|
|
|
7269
8423
|
// src/core/VectorPlugin.ts
|
|
7270
8424
|
var VectorPlugin = class {
|
|
7271
8425
|
constructor(hostConfig) {
|
|
7272
|
-
|
|
7273
|
-
this.
|
|
7274
|
-
this.
|
|
8426
|
+
const resolvedConfig = ConfigResolver.resolve(hostConfig);
|
|
8427
|
+
this.config = resolvedConfig;
|
|
8428
|
+
this.validationPromise = (async () => {
|
|
8429
|
+
var _a2;
|
|
8430
|
+
await ConfigValidator.validateAndThrow(resolvedConfig);
|
|
8431
|
+
LicenseVerifier.verify(
|
|
8432
|
+
resolvedConfig.licenseKey,
|
|
8433
|
+
resolvedConfig.projectId,
|
|
8434
|
+
(_a2 = resolvedConfig.vectorDb) == null ? void 0 : _a2.provider
|
|
8435
|
+
);
|
|
8436
|
+
})();
|
|
8437
|
+
this.validationPromise.catch(() => {
|
|
8438
|
+
});
|
|
8439
|
+
this.pipeline = new Pipeline(resolvedConfig);
|
|
7275
8440
|
}
|
|
7276
8441
|
/**
|
|
7277
8442
|
* Get the current resolved configuration.
|
|
@@ -7304,55 +8469,93 @@ var VectorPlugin = class {
|
|
|
7304
8469
|
* Run a chat query.
|
|
7305
8470
|
*/
|
|
7306
8471
|
async chat(message, history = [], namespace) {
|
|
7307
|
-
|
|
7308
|
-
|
|
8472
|
+
try {
|
|
8473
|
+
await this.validationPromise;
|
|
8474
|
+
} catch (err) {
|
|
8475
|
+
throw wrapError(err, "CONFIGURATION_ERROR");
|
|
8476
|
+
}
|
|
8477
|
+
try {
|
|
8478
|
+
return await this.pipeline.ask(message, history, namespace);
|
|
8479
|
+
} catch (err) {
|
|
8480
|
+
const msg = String(err);
|
|
8481
|
+
let defaultCode = "RETRIEVAL_FAILED";
|
|
8482
|
+
if (msg.includes("Embed") || msg.includes("embed")) {
|
|
8483
|
+
defaultCode = "EMBEDDING_FAILED";
|
|
8484
|
+
}
|
|
8485
|
+
throw wrapError(err, defaultCode);
|
|
8486
|
+
}
|
|
7309
8487
|
}
|
|
7310
8488
|
/**
|
|
7311
8489
|
* Run a streaming chat query.
|
|
7312
8490
|
*/
|
|
7313
8491
|
chatStream(_0) {
|
|
7314
8492
|
return __asyncGenerator(this, arguments, function* (message, history = [], namespace) {
|
|
7315
|
-
|
|
7316
|
-
|
|
8493
|
+
try {
|
|
8494
|
+
yield new __await(this.validationPromise);
|
|
8495
|
+
} catch (err) {
|
|
8496
|
+
throw wrapError(err, "CONFIGURATION_ERROR");
|
|
8497
|
+
}
|
|
8498
|
+
try {
|
|
8499
|
+
const stream = this.pipeline.askStream(message, history, namespace);
|
|
8500
|
+
try {
|
|
8501
|
+
for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
|
|
8502
|
+
const chunk = temp.value;
|
|
8503
|
+
yield chunk;
|
|
8504
|
+
}
|
|
8505
|
+
} catch (temp) {
|
|
8506
|
+
error = [temp];
|
|
8507
|
+
} finally {
|
|
8508
|
+
try {
|
|
8509
|
+
more && (temp = iter.return) && (yield new __await(temp.call(iter)));
|
|
8510
|
+
} finally {
|
|
8511
|
+
if (error)
|
|
8512
|
+
throw error[0];
|
|
8513
|
+
}
|
|
8514
|
+
}
|
|
8515
|
+
} catch (err) {
|
|
8516
|
+
const msg = String(err);
|
|
8517
|
+
let defaultCode = "RETRIEVAL_FAILED";
|
|
8518
|
+
if (msg.includes("Embed") || msg.includes("embed")) {
|
|
8519
|
+
defaultCode = "EMBEDDING_FAILED";
|
|
8520
|
+
}
|
|
8521
|
+
throw wrapError(err, defaultCode);
|
|
8522
|
+
}
|
|
7317
8523
|
});
|
|
7318
8524
|
}
|
|
7319
8525
|
/**
|
|
7320
8526
|
* Ingest documents into the vector database.
|
|
7321
8527
|
*/
|
|
7322
8528
|
async ingest(documents, namespace) {
|
|
7323
|
-
|
|
7324
|
-
|
|
8529
|
+
try {
|
|
8530
|
+
await this.validationPromise;
|
|
8531
|
+
} catch (err) {
|
|
8532
|
+
throw wrapError(err, "CONFIGURATION_ERROR");
|
|
8533
|
+
}
|
|
8534
|
+
try {
|
|
8535
|
+
return await this.pipeline.ingest(documents, namespace);
|
|
8536
|
+
} catch (err) {
|
|
8537
|
+
const msg = String(err);
|
|
8538
|
+
let defaultCode = "RETRIEVAL_FAILED";
|
|
8539
|
+
if (msg.includes("Embed") || msg.includes("embed")) {
|
|
8540
|
+
defaultCode = "EMBEDDING_FAILED";
|
|
8541
|
+
}
|
|
8542
|
+
throw wrapError(err, defaultCode);
|
|
8543
|
+
}
|
|
7325
8544
|
}
|
|
7326
8545
|
/**
|
|
7327
8546
|
* Get auto-suggestions based on a query prefix.
|
|
7328
8547
|
*/
|
|
7329
8548
|
async getSuggestions(query, namespace) {
|
|
7330
|
-
|
|
7331
|
-
|
|
7332
|
-
|
|
7333
|
-
|
|
7334
|
-
|
|
7335
|
-
|
|
7336
|
-
|
|
7337
|
-
|
|
7338
|
-
|
|
7339
|
-
|
|
7340
|
-
}
|
|
7341
|
-
async initialize() {
|
|
7342
|
-
await ConfigValidator.validateAndThrow(this.config);
|
|
7343
|
-
await this.pipeline.initialize();
|
|
7344
|
-
}
|
|
7345
|
-
async ingest(documents, namespace) {
|
|
7346
|
-
return this.pipeline.ingest(documents, namespace);
|
|
7347
|
-
}
|
|
7348
|
-
async ask(question, history = [], namespace) {
|
|
7349
|
-
return this.pipeline.ask(question, history, namespace);
|
|
7350
|
-
}
|
|
7351
|
-
askStream(question, history = [], namespace) {
|
|
7352
|
-
return this.pipeline.askStream(question, history, namespace);
|
|
7353
|
-
}
|
|
7354
|
-
getPipeline() {
|
|
7355
|
-
return this.pipeline;
|
|
8549
|
+
try {
|
|
8550
|
+
await this.validationPromise;
|
|
8551
|
+
} catch (err) {
|
|
8552
|
+
throw wrapError(err, "CONFIGURATION_ERROR");
|
|
8553
|
+
}
|
|
8554
|
+
try {
|
|
8555
|
+
return await this.pipeline.getSuggestions(query, namespace);
|
|
8556
|
+
} catch (err) {
|
|
8557
|
+
throw wrapError(err, "RETRIEVAL_FAILED");
|
|
8558
|
+
}
|
|
7356
8559
|
}
|
|
7357
8560
|
};
|
|
7358
8561
|
|
|
@@ -7369,13 +8572,13 @@ var ConfigBuilder = class {
|
|
|
7369
8572
|
* Configure the vector database provider
|
|
7370
8573
|
*/
|
|
7371
8574
|
vectorDb(provider, options) {
|
|
7372
|
-
var
|
|
8575
|
+
var _a2;
|
|
7373
8576
|
if (provider === "auto") {
|
|
7374
8577
|
this._vectorDb = this._autoDetectVectorDb();
|
|
7375
8578
|
} else {
|
|
7376
8579
|
this._vectorDb = {
|
|
7377
8580
|
provider,
|
|
7378
|
-
indexName: (
|
|
8581
|
+
indexName: (_a2 = options == null ? void 0 : options.indexName) != null ? _a2 : "default",
|
|
7379
8582
|
options: __spreadValues({}, options)
|
|
7380
8583
|
};
|
|
7381
8584
|
}
|
|
@@ -7385,7 +8588,7 @@ var ConfigBuilder = class {
|
|
|
7385
8588
|
* Configure the LLM provider for chat
|
|
7386
8589
|
*/
|
|
7387
8590
|
llm(provider, model, apiKey, options) {
|
|
7388
|
-
var
|
|
8591
|
+
var _a2, _b;
|
|
7389
8592
|
if (provider === "auto") {
|
|
7390
8593
|
this._llm = this._autoDetectLLM();
|
|
7391
8594
|
} else {
|
|
@@ -7394,7 +8597,7 @@ var ConfigBuilder = class {
|
|
|
7394
8597
|
model: model != null ? model : "default-model",
|
|
7395
8598
|
apiKey,
|
|
7396
8599
|
systemPrompt: options == null ? void 0 : options.systemPrompt,
|
|
7397
|
-
maxTokens: (
|
|
8600
|
+
maxTokens: (_a2 = options == null ? void 0 : options.maxTokens) != null ? _a2 : 1024,
|
|
7398
8601
|
temperature: (_b = options == null ? void 0 : options.temperature) != null ? _b : 0.7,
|
|
7399
8602
|
baseUrl: options == null ? void 0 : options.baseUrl,
|
|
7400
8603
|
options
|
|
@@ -7437,8 +8640,8 @@ var ConfigBuilder = class {
|
|
|
7437
8640
|
* Set RAG-specific pipeline parameters
|
|
7438
8641
|
*/
|
|
7439
8642
|
rag(options) {
|
|
7440
|
-
var
|
|
7441
|
-
this._rag = __spreadValues(__spreadValues({}, (
|
|
8643
|
+
var _a2;
|
|
8644
|
+
this._rag = __spreadValues(__spreadValues({}, (_a2 = this._rag) != null ? _a2 : {}), options);
|
|
7442
8645
|
return this;
|
|
7443
8646
|
}
|
|
7444
8647
|
/**
|
|
@@ -7454,7 +8657,7 @@ var ConfigBuilder = class {
|
|
|
7454
8657
|
* Throws if required fields (projectId, vectorDb, llm, embedding) are not set.
|
|
7455
8658
|
*/
|
|
7456
8659
|
build() {
|
|
7457
|
-
var
|
|
8660
|
+
var _a2;
|
|
7458
8661
|
const missing = [];
|
|
7459
8662
|
if (!this._projectId) missing.push('projectId (call .projectId("my-app"))');
|
|
7460
8663
|
if (!this._vectorDb) missing.push('vectorDb (call .vectorDb("pinecone", { ... }))');
|
|
@@ -7466,7 +8669,7 @@ var ConfigBuilder = class {
|
|
|
7466
8669
|
${missing.join("\n ")}`
|
|
7467
8670
|
);
|
|
7468
8671
|
}
|
|
7469
|
-
const ragConfig = (
|
|
8672
|
+
const ragConfig = (_a2 = this._rag) != null ? _a2 : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
|
|
7470
8673
|
if (process.env.RAG_USE_GRAPH_RETRIEVAL === "true") {
|
|
7471
8674
|
ragConfig.useGraphRetrieval = true;
|
|
7472
8675
|
}
|
|
@@ -7562,8 +8765,8 @@ var DocumentParser = class {
|
|
|
7562
8765
|
* Extract text from a File or Buffer based on its type.
|
|
7563
8766
|
*/
|
|
7564
8767
|
static async parse(file, fileName, mimeType) {
|
|
7565
|
-
var
|
|
7566
|
-
const extension = (
|
|
8768
|
+
var _a2;
|
|
8769
|
+
const extension = (_a2 = fileName.split(".").pop()) == null ? void 0 : _a2.toLowerCase();
|
|
7567
8770
|
if (extension === "txt" || extension === "md" || mimeType === "text/plain" || mimeType === "text/markdown") {
|
|
7568
8771
|
return this.readAsText(file);
|
|
7569
8772
|
}
|
|
@@ -7630,6 +8833,497 @@ init_UniversalVectorProvider();
|
|
|
7630
8833
|
|
|
7631
8834
|
// src/handlers/index.ts
|
|
7632
8835
|
var import_server = require("next/server");
|
|
8836
|
+
|
|
8837
|
+
// src/core/DatabaseStorage.ts
|
|
8838
|
+
var fs = __toESM(require("fs"));
|
|
8839
|
+
var path = __toESM(require("path"));
|
|
8840
|
+
var DatabaseStorage = class {
|
|
8841
|
+
constructor(config) {
|
|
8842
|
+
// Dynamic PG Pool
|
|
8843
|
+
this.pgPool = null;
|
|
8844
|
+
// Dynamic MongoDB Client
|
|
8845
|
+
this.mongoClient = null;
|
|
8846
|
+
this.mongoDbName = "";
|
|
8847
|
+
// Filesystem fallback configuration
|
|
8848
|
+
this.fallbackDir = path.join(process.cwd(), ".retrivora");
|
|
8849
|
+
this.historyFile = path.join(this.fallbackDir, "history.json");
|
|
8850
|
+
this.feedbackFile = path.join(this.fallbackDir, "feedback.json");
|
|
8851
|
+
var _a2, _b, _c, _d, _e;
|
|
8852
|
+
this.config = config;
|
|
8853
|
+
this.provider = ((_a2 = config.vectorDb) == null ? void 0 : _a2.provider) || "fs";
|
|
8854
|
+
const rawHistoryTable = ((_c = (_b = config.rag) == null ? void 0 : _b.history) == null ? void 0 : _c.tableName) || "retrivora_history";
|
|
8855
|
+
const rawFeedbackTable = ((_e = (_d = config.rag) == null ? void 0 : _d.feedback) == null ? void 0 : _e.tableName) || "retrivora_feedback";
|
|
8856
|
+
this.historyTableName = rawHistoryTable.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
8857
|
+
this.feedbackTableName = rawFeedbackTable.replace(/[^a-zA-Z0-9_]/g, "_");
|
|
8858
|
+
}
|
|
8859
|
+
/**
|
|
8860
|
+
* Asserts the user is running a valid Premium/Enterprise license in production.
|
|
8861
|
+
* In non-production (development / test) environments this is a complete no-op —
|
|
8862
|
+
* all History and Feedback features are freely accessible for local development.
|
|
8863
|
+
*/
|
|
8864
|
+
checkPremiumSubscription() {
|
|
8865
|
+
if (process.env.NODE_ENV !== "production") {
|
|
8866
|
+
return;
|
|
8867
|
+
}
|
|
8868
|
+
if (!this.config.licenseKey) {
|
|
8869
|
+
throw new Error(
|
|
8870
|
+
"[Retrivora SDK] Chat History and Feedback features require a Premium or Enterprise license key in production."
|
|
8871
|
+
);
|
|
8872
|
+
}
|
|
8873
|
+
try {
|
|
8874
|
+
const payload = LicenseVerifier.verify(this.config.licenseKey, this.config.projectId);
|
|
8875
|
+
const tier = (payload.tier || "").toLowerCase();
|
|
8876
|
+
if (tier !== "premium" && tier !== "enterprise" && tier !== "growth" && tier !== "pro" && tier !== "developer_pro") {
|
|
8877
|
+
throw new Error(
|
|
8878
|
+
`[Retrivora SDK] Chat History and Feedback features are not available on the "${tier}" tier. Please upgrade to a Developer Pro or Enterprise plan.`
|
|
8879
|
+
);
|
|
8880
|
+
}
|
|
8881
|
+
} catch (err) {
|
|
8882
|
+
throw new Error(
|
|
8883
|
+
`[Retrivora SDK] Subscription check failed: ${err instanceof Error ? err.message : String(err)}`
|
|
8884
|
+
);
|
|
8885
|
+
}
|
|
8886
|
+
}
|
|
8887
|
+
checkHistoryEnabled() {
|
|
8888
|
+
var _a2, _b;
|
|
8889
|
+
this.checkPremiumSubscription();
|
|
8890
|
+
if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.history) == null ? void 0 : _b.enabled) === false) {
|
|
8891
|
+
throw new Error("[Retrivora SDK] Chat History is disabled in RagConfig.");
|
|
8892
|
+
}
|
|
8893
|
+
}
|
|
8894
|
+
checkFeedbackEnabled() {
|
|
8895
|
+
var _a2, _b;
|
|
8896
|
+
this.checkPremiumSubscription();
|
|
8897
|
+
if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.feedback) == null ? void 0 : _b.enabled) === false) {
|
|
8898
|
+
throw new Error("[Retrivora SDK] User Feedback is disabled in RagConfig.");
|
|
8899
|
+
}
|
|
8900
|
+
}
|
|
8901
|
+
async getPGPool() {
|
|
8902
|
+
const globalKey = `__retrivora_pg_pool_${this.config.projectId}`;
|
|
8903
|
+
const _g2 = global;
|
|
8904
|
+
if (_g2[globalKey]) {
|
|
8905
|
+
this.pgPool = _g2[globalKey];
|
|
8906
|
+
return this.pgPool;
|
|
8907
|
+
}
|
|
8908
|
+
const opts = this.config.vectorDb.options;
|
|
8909
|
+
if (!opts.connectionString) {
|
|
8910
|
+
throw new Error("[DatabaseStorage] pg connectionString option is missing.");
|
|
8911
|
+
}
|
|
8912
|
+
const { Pool: Pool3 } = await import("pg");
|
|
8913
|
+
this.pgPool = new Pool3({ connectionString: opts.connectionString });
|
|
8914
|
+
_g2[globalKey] = this.pgPool;
|
|
8915
|
+
const client = await this.pgPool.connect();
|
|
8916
|
+
try {
|
|
8917
|
+
await client.query(`
|
|
8918
|
+
CREATE TABLE IF NOT EXISTS ${this.historyTableName} (
|
|
8919
|
+
id TEXT PRIMARY KEY,
|
|
8920
|
+
session_id TEXT NOT NULL,
|
|
8921
|
+
role TEXT NOT NULL,
|
|
8922
|
+
content TEXT NOT NULL,
|
|
8923
|
+
sources JSONB,
|
|
8924
|
+
ui_transformation JSONB,
|
|
8925
|
+
trace JSONB,
|
|
8926
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
8927
|
+
)
|
|
8928
|
+
`);
|
|
8929
|
+
await client.query(`
|
|
8930
|
+
CREATE TABLE IF NOT EXISTS ${this.feedbackTableName} (
|
|
8931
|
+
id TEXT PRIMARY KEY,
|
|
8932
|
+
message_id TEXT NOT NULL UNIQUE,
|
|
8933
|
+
session_id TEXT NOT NULL,
|
|
8934
|
+
rating TEXT NOT NULL,
|
|
8935
|
+
comment TEXT,
|
|
8936
|
+
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
|
|
8937
|
+
)
|
|
8938
|
+
`);
|
|
8939
|
+
} finally {
|
|
8940
|
+
client.release();
|
|
8941
|
+
}
|
|
8942
|
+
return this.pgPool;
|
|
8943
|
+
}
|
|
8944
|
+
async getMongoClient() {
|
|
8945
|
+
const globalKey = `__retrivora_mongo_client_${this.config.projectId}`;
|
|
8946
|
+
const _g2 = global;
|
|
8947
|
+
if (_g2[globalKey]) {
|
|
8948
|
+
this.mongoClient = _g2[globalKey];
|
|
8949
|
+
this.mongoDbName = this.config.vectorDb.options.database;
|
|
8950
|
+
return this.mongoClient;
|
|
8951
|
+
}
|
|
8952
|
+
const opts = this.config.vectorDb.options;
|
|
8953
|
+
if (!opts.uri || !opts.database) {
|
|
8954
|
+
throw new Error("[DatabaseStorage] mongo uri and database options are missing.");
|
|
8955
|
+
}
|
|
8956
|
+
const { MongoClient: MongoClient2 } = await import("mongodb");
|
|
8957
|
+
this.mongoClient = new MongoClient2(opts.uri);
|
|
8958
|
+
await this.mongoClient.connect();
|
|
8959
|
+
_g2[globalKey] = this.mongoClient;
|
|
8960
|
+
this.mongoDbName = opts.database;
|
|
8961
|
+
return this.mongoClient;
|
|
8962
|
+
}
|
|
8963
|
+
getMongoDb() {
|
|
8964
|
+
return this.mongoClient.db(this.mongoDbName);
|
|
8965
|
+
}
|
|
8966
|
+
// Helper for FS fallback reads
|
|
8967
|
+
readLocalFile(filePath) {
|
|
8968
|
+
if (!fs.existsSync(filePath)) return [];
|
|
8969
|
+
try {
|
|
8970
|
+
const raw = fs.readFileSync(filePath, "utf-8");
|
|
8971
|
+
return JSON.parse(raw) || [];
|
|
8972
|
+
} catch (e) {
|
|
8973
|
+
return [];
|
|
8974
|
+
}
|
|
8975
|
+
}
|
|
8976
|
+
// Helper for FS fallback writes
|
|
8977
|
+
writeLocalFile(filePath, data) {
|
|
8978
|
+
if (!fs.existsSync(this.fallbackDir)) {
|
|
8979
|
+
fs.mkdirSync(this.fallbackDir, { recursive: true });
|
|
8980
|
+
}
|
|
8981
|
+
fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
|
|
8982
|
+
}
|
|
8983
|
+
// ─── Message History Operations ──────────────────────────────────────────
|
|
8984
|
+
async saveMessage(sessionId, message) {
|
|
8985
|
+
this.checkHistoryEnabled();
|
|
8986
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
8987
|
+
const msgId = message.id || `msg_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
8988
|
+
if (this.provider === "postgresql" || this.provider === "pgvector") {
|
|
8989
|
+
const pool = await this.getPGPool();
|
|
8990
|
+
await pool.query(
|
|
8991
|
+
`INSERT INTO ${this.historyTableName} (id, session_id, role, content, sources, ui_transformation, trace, created_at)
|
|
8992
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
|
|
8993
|
+
ON CONFLICT (id) DO UPDATE
|
|
8994
|
+
SET content = EXCLUDED.content, sources = EXCLUDED.sources, ui_transformation = EXCLUDED.ui_transformation, trace = EXCLUDED.trace`,
|
|
8995
|
+
[
|
|
8996
|
+
msgId,
|
|
8997
|
+
sessionId,
|
|
8998
|
+
message.role,
|
|
8999
|
+
message.content,
|
|
9000
|
+
message.sources ? JSON.stringify(message.sources) : null,
|
|
9001
|
+
message.uiTransformation ? JSON.stringify(message.uiTransformation) : null,
|
|
9002
|
+
message.trace ? JSON.stringify(message.trace) : null,
|
|
9003
|
+
createdAt
|
|
9004
|
+
]
|
|
9005
|
+
);
|
|
9006
|
+
} else if (this.provider === "mongodb") {
|
|
9007
|
+
await this.getMongoClient();
|
|
9008
|
+
const db = this.getMongoDb();
|
|
9009
|
+
const col = db.collection(this.historyTableName);
|
|
9010
|
+
await col.updateOne(
|
|
9011
|
+
{ id: msgId },
|
|
9012
|
+
{
|
|
9013
|
+
$set: {
|
|
9014
|
+
id: msgId,
|
|
9015
|
+
session_id: sessionId,
|
|
9016
|
+
role: message.role,
|
|
9017
|
+
content: message.content,
|
|
9018
|
+
sources: message.sources || null,
|
|
9019
|
+
ui_transformation: message.uiTransformation || null,
|
|
9020
|
+
trace: message.trace || null,
|
|
9021
|
+
created_at: createdAt
|
|
9022
|
+
}
|
|
9023
|
+
},
|
|
9024
|
+
{ upsert: true }
|
|
9025
|
+
);
|
|
9026
|
+
} else {
|
|
9027
|
+
const history = this.readLocalFile(this.historyFile);
|
|
9028
|
+
const index = history.findIndex((h) => h.id === msgId);
|
|
9029
|
+
const item = {
|
|
9030
|
+
id: msgId,
|
|
9031
|
+
session_id: sessionId,
|
|
9032
|
+
role: message.role,
|
|
9033
|
+
content: message.content,
|
|
9034
|
+
sources: message.sources || null,
|
|
9035
|
+
ui_transformation: message.uiTransformation || null,
|
|
9036
|
+
trace: message.trace || null,
|
|
9037
|
+
created_at: createdAt
|
|
9038
|
+
};
|
|
9039
|
+
if (index !== -1) {
|
|
9040
|
+
history[index] = item;
|
|
9041
|
+
} else {
|
|
9042
|
+
history.push(item);
|
|
9043
|
+
}
|
|
9044
|
+
this.writeLocalFile(this.historyFile, history);
|
|
9045
|
+
}
|
|
9046
|
+
}
|
|
9047
|
+
async getHistory(sessionId) {
|
|
9048
|
+
this.checkHistoryEnabled();
|
|
9049
|
+
if (this.provider === "postgresql" || this.provider === "pgvector") {
|
|
9050
|
+
const pool = await this.getPGPool();
|
|
9051
|
+
const res = await pool.query(
|
|
9052
|
+
`SELECT id, role, content, sources, ui_transformation as "uiTransformation", trace, created_at as "createdAt"
|
|
9053
|
+
FROM ${this.historyTableName}
|
|
9054
|
+
WHERE session_id = $1
|
|
9055
|
+
ORDER BY created_at ASC`,
|
|
9056
|
+
[sessionId]
|
|
9057
|
+
);
|
|
9058
|
+
return res.rows;
|
|
9059
|
+
} else if (this.provider === "mongodb") {
|
|
9060
|
+
await this.getMongoClient();
|
|
9061
|
+
const db = this.getMongoDb();
|
|
9062
|
+
const col = db.collection(this.historyTableName);
|
|
9063
|
+
const items = await col.find({ session_id: sessionId }).sort({ created_at: 1 }).toArray();
|
|
9064
|
+
return items.map((item) => ({
|
|
9065
|
+
id: item.id,
|
|
9066
|
+
role: item.role,
|
|
9067
|
+
content: item.content,
|
|
9068
|
+
sources: item.sources,
|
|
9069
|
+
uiTransformation: item.ui_transformation,
|
|
9070
|
+
trace: item.trace,
|
|
9071
|
+
createdAt: item.created_at
|
|
9072
|
+
}));
|
|
9073
|
+
} else {
|
|
9074
|
+
const history = this.readLocalFile(this.historyFile);
|
|
9075
|
+
return history.filter((h) => h.session_id === sessionId).sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
|
|
9076
|
+
}
|
|
9077
|
+
}
|
|
9078
|
+
async clearHistory(sessionId) {
|
|
9079
|
+
this.checkHistoryEnabled();
|
|
9080
|
+
if (this.provider === "postgresql" || this.provider === "pgvector") {
|
|
9081
|
+
const pool = await this.getPGPool();
|
|
9082
|
+
await pool.query(`DELETE FROM ${this.historyTableName} WHERE session_id = $1`, [sessionId]);
|
|
9083
|
+
await pool.query(`DELETE FROM ${this.feedbackTableName} WHERE session_id = $1`, [sessionId]);
|
|
9084
|
+
} else if (this.provider === "mongodb") {
|
|
9085
|
+
await this.getMongoClient();
|
|
9086
|
+
const db = this.getMongoDb();
|
|
9087
|
+
await db.collection(this.historyTableName).deleteMany({ session_id: sessionId });
|
|
9088
|
+
await db.collection(this.feedbackTableName).deleteMany({ session_id: sessionId });
|
|
9089
|
+
} else {
|
|
9090
|
+
const history = this.readLocalFile(this.historyFile);
|
|
9091
|
+
const filteredHistory = history.filter((h) => h.session_id !== sessionId);
|
|
9092
|
+
this.writeLocalFile(this.historyFile, filteredHistory);
|
|
9093
|
+
const feedback = this.readLocalFile(this.feedbackFile);
|
|
9094
|
+
const filteredFeedback = feedback.filter((f) => f.session_id !== sessionId);
|
|
9095
|
+
this.writeLocalFile(this.feedbackFile, filteredFeedback);
|
|
9096
|
+
}
|
|
9097
|
+
}
|
|
9098
|
+
async listSessions() {
|
|
9099
|
+
this.checkHistoryEnabled();
|
|
9100
|
+
if (this.provider === "postgresql" || this.provider === "pgvector") {
|
|
9101
|
+
const pool = await this.getPGPool();
|
|
9102
|
+
const res = await pool.query(`SELECT DISTINCT session_id FROM ${this.historyTableName}`);
|
|
9103
|
+
return res.rows.map((r) => r.session_id);
|
|
9104
|
+
} else if (this.provider === "mongodb") {
|
|
9105
|
+
await this.getMongoClient();
|
|
9106
|
+
const db = this.getMongoDb();
|
|
9107
|
+
return db.collection(this.historyTableName).distinct("session_id");
|
|
9108
|
+
} else {
|
|
9109
|
+
const history = this.readLocalFile(this.historyFile);
|
|
9110
|
+
const sessions = new Set(history.map((h) => h.session_id));
|
|
9111
|
+
return Array.from(sessions);
|
|
9112
|
+
}
|
|
9113
|
+
}
|
|
9114
|
+
// ─── Feedback Operations ──────────────────────────────────────────────────
|
|
9115
|
+
async saveFeedback(feedback) {
|
|
9116
|
+
this.checkFeedbackEnabled();
|
|
9117
|
+
const id = `fb_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
9118
|
+
const createdAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
9119
|
+
if (this.provider === "postgresql" || this.provider === "pgvector") {
|
|
9120
|
+
const pool = await this.getPGPool();
|
|
9121
|
+
await pool.query(
|
|
9122
|
+
`INSERT INTO ${this.feedbackTableName} (id, message_id, session_id, rating, comment, created_at)
|
|
9123
|
+
VALUES ($1, $2, $3, $4, $5, $6)
|
|
9124
|
+
ON CONFLICT (message_id) DO UPDATE
|
|
9125
|
+
SET rating = EXCLUDED.rating, comment = EXCLUDED.comment`,
|
|
9126
|
+
[id, feedback.messageId, feedback.sessionId, feedback.rating, feedback.comment || null, createdAt]
|
|
9127
|
+
);
|
|
9128
|
+
} else if (this.provider === "mongodb") {
|
|
9129
|
+
await this.getMongoClient();
|
|
9130
|
+
const db = this.getMongoDb();
|
|
9131
|
+
const col = db.collection(this.feedbackTableName);
|
|
9132
|
+
await col.updateOne(
|
|
9133
|
+
{ message_id: feedback.messageId },
|
|
9134
|
+
{
|
|
9135
|
+
$set: {
|
|
9136
|
+
id,
|
|
9137
|
+
message_id: feedback.messageId,
|
|
9138
|
+
session_id: feedback.sessionId,
|
|
9139
|
+
rating: feedback.rating,
|
|
9140
|
+
comment: feedback.comment || null,
|
|
9141
|
+
created_at: createdAt
|
|
9142
|
+
}
|
|
9143
|
+
},
|
|
9144
|
+
{ upsert: true }
|
|
9145
|
+
);
|
|
9146
|
+
} else {
|
|
9147
|
+
const list = this.readLocalFile(this.feedbackFile);
|
|
9148
|
+
const index = list.findIndex((f) => f.message_id === feedback.messageId);
|
|
9149
|
+
const item = {
|
|
9150
|
+
id,
|
|
9151
|
+
message_id: feedback.messageId,
|
|
9152
|
+
session_id: feedback.sessionId,
|
|
9153
|
+
rating: feedback.rating,
|
|
9154
|
+
comment: feedback.comment || null,
|
|
9155
|
+
created_at: createdAt
|
|
9156
|
+
};
|
|
9157
|
+
if (index !== -1) {
|
|
9158
|
+
list[index] = item;
|
|
9159
|
+
} else {
|
|
9160
|
+
list.push(item);
|
|
9161
|
+
}
|
|
9162
|
+
this.writeLocalFile(this.feedbackFile, list);
|
|
9163
|
+
}
|
|
9164
|
+
}
|
|
9165
|
+
async getFeedback(messageId) {
|
|
9166
|
+
this.checkFeedbackEnabled();
|
|
9167
|
+
if (this.provider === "postgresql" || this.provider === "pgvector") {
|
|
9168
|
+
const pool = await this.getPGPool();
|
|
9169
|
+
const res = await pool.query(
|
|
9170
|
+
`SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
|
|
9171
|
+
FROM ${this.feedbackTableName}
|
|
9172
|
+
WHERE message_id = $1`,
|
|
9173
|
+
[messageId]
|
|
9174
|
+
);
|
|
9175
|
+
return res.rows[0] || null;
|
|
9176
|
+
} else if (this.provider === "mongodb") {
|
|
9177
|
+
await this.getMongoClient();
|
|
9178
|
+
const db = this.getMongoDb();
|
|
9179
|
+
const col = db.collection(this.feedbackTableName);
|
|
9180
|
+
const item = await col.findOne({ message_id: messageId });
|
|
9181
|
+
if (!item) return null;
|
|
9182
|
+
return {
|
|
9183
|
+
id: item.id,
|
|
9184
|
+
messageId: item.message_id,
|
|
9185
|
+
sessionId: item.session_id,
|
|
9186
|
+
rating: item.rating,
|
|
9187
|
+
comment: item.comment,
|
|
9188
|
+
createdAt: item.created_at
|
|
9189
|
+
};
|
|
9190
|
+
} else {
|
|
9191
|
+
const list = this.readLocalFile(this.feedbackFile);
|
|
9192
|
+
return list.find((f) => f.message_id === messageId) || null;
|
|
9193
|
+
}
|
|
9194
|
+
}
|
|
9195
|
+
async listFeedback() {
|
|
9196
|
+
this.checkFeedbackEnabled();
|
|
9197
|
+
if (this.provider === "postgresql" || this.provider === "pgvector") {
|
|
9198
|
+
const pool = await this.getPGPool();
|
|
9199
|
+
const res = await pool.query(
|
|
9200
|
+
`SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
|
|
9201
|
+
FROM ${this.feedbackTableName}
|
|
9202
|
+
ORDER BY created_at DESC`
|
|
9203
|
+
);
|
|
9204
|
+
return res.rows;
|
|
9205
|
+
} else if (this.provider === "mongodb") {
|
|
9206
|
+
await this.getMongoClient();
|
|
9207
|
+
const db = this.getMongoDb();
|
|
9208
|
+
const col = db.collection(this.feedbackTableName);
|
|
9209
|
+
const items = await col.find({}).sort({ created_at: -1 }).toArray();
|
|
9210
|
+
return items.map((item) => ({
|
|
9211
|
+
id: item.id,
|
|
9212
|
+
messageId: item.message_id,
|
|
9213
|
+
sessionId: item.session_id,
|
|
9214
|
+
rating: item.rating,
|
|
9215
|
+
comment: item.comment,
|
|
9216
|
+
createdAt: item.created_at
|
|
9217
|
+
}));
|
|
9218
|
+
} else {
|
|
9219
|
+
const list = this.readLocalFile(this.feedbackFile);
|
|
9220
|
+
return [...list].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
|
|
9221
|
+
}
|
|
9222
|
+
}
|
|
9223
|
+
async disconnect() {
|
|
9224
|
+
if (this.pgPool) {
|
|
9225
|
+
await this.pgPool.end();
|
|
9226
|
+
this.pgPool = null;
|
|
9227
|
+
}
|
|
9228
|
+
if (this.mongoClient) {
|
|
9229
|
+
await this.mongoClient.close();
|
|
9230
|
+
this.mongoClient = null;
|
|
9231
|
+
}
|
|
9232
|
+
}
|
|
9233
|
+
};
|
|
9234
|
+
|
|
9235
|
+
// src/handlers/index.ts
|
|
9236
|
+
async function checkAuth(req, onAuthorize) {
|
|
9237
|
+
if (!onAuthorize) return null;
|
|
9238
|
+
try {
|
|
9239
|
+
const res = await onAuthorize(req);
|
|
9240
|
+
if (res === false) {
|
|
9241
|
+
return import_server.NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
9242
|
+
}
|
|
9243
|
+
if (res instanceof Response) {
|
|
9244
|
+
return res;
|
|
9245
|
+
}
|
|
9246
|
+
return null;
|
|
9247
|
+
} catch (err) {
|
|
9248
|
+
const msg = err instanceof Error ? err.message : "Authorization check failed";
|
|
9249
|
+
return import_server.NextResponse.json({ error: msg }, { status: 401 });
|
|
9250
|
+
}
|
|
9251
|
+
}
|
|
9252
|
+
var RateLimiter = class {
|
|
9253
|
+
constructor(windowMs = 6e4, max = 30) {
|
|
9254
|
+
this.hits = /* @__PURE__ */ new Map();
|
|
9255
|
+
this.windowMs = windowMs;
|
|
9256
|
+
this.max = max;
|
|
9257
|
+
}
|
|
9258
|
+
/** Returns true if the request should be allowed, false if rate-limited. */
|
|
9259
|
+
allow(key) {
|
|
9260
|
+
const now = Date.now();
|
|
9261
|
+
const cutoff = now - this.windowMs;
|
|
9262
|
+
const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
|
|
9263
|
+
existing.push(now);
|
|
9264
|
+
this.hits.set(key, existing);
|
|
9265
|
+
if (this.hits.size > 5e3) {
|
|
9266
|
+
for (const [k, timestamps] of this.hits.entries()) {
|
|
9267
|
+
if (timestamps.every((t) => t <= cutoff)) this.hits.delete(k);
|
|
9268
|
+
}
|
|
9269
|
+
}
|
|
9270
|
+
return existing.length <= this.max;
|
|
9271
|
+
}
|
|
9272
|
+
retryAfterSec(key) {
|
|
9273
|
+
const now = Date.now();
|
|
9274
|
+
const cutoff = now - this.windowMs;
|
|
9275
|
+
const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
|
|
9276
|
+
if (existing.length === 0) return 0;
|
|
9277
|
+
return Math.ceil((existing[0] + this.windowMs - now) / 1e3);
|
|
9278
|
+
}
|
|
9279
|
+
};
|
|
9280
|
+
var _g = global;
|
|
9281
|
+
var _a;
|
|
9282
|
+
var rateLimiter = (_a = _g.__retrivoraRateLimiter) != null ? _a : _g.__retrivoraRateLimiter = new RateLimiter(6e4, 30);
|
|
9283
|
+
function getRateLimitKey(req) {
|
|
9284
|
+
var _a2, _b;
|
|
9285
|
+
const ip = ((_b = (_a2 = req.headers.get("x-forwarded-for")) == null ? void 0 : _a2.split(",")[0]) == null ? void 0 : _b.trim()) || req.headers.get("x-real-ip") || "127.0.0.1";
|
|
9286
|
+
return `ip:${ip}`;
|
|
9287
|
+
}
|
|
9288
|
+
function checkRateLimit(req) {
|
|
9289
|
+
const key = getRateLimitKey(req);
|
|
9290
|
+
if (!rateLimiter.allow(key)) {
|
|
9291
|
+
const retryAfter = rateLimiter.retryAfterSec(key);
|
|
9292
|
+
return new Response(
|
|
9293
|
+
JSON.stringify({ error: { code: "RATE_LIMITED", message: "Too many requests. Please slow down." } }),
|
|
9294
|
+
{
|
|
9295
|
+
status: 429,
|
|
9296
|
+
headers: {
|
|
9297
|
+
"Content-Type": "application/json",
|
|
9298
|
+
"Retry-After": String(retryAfter),
|
|
9299
|
+
"X-RateLimit-Limit": "30",
|
|
9300
|
+
"X-RateLimit-Window": "60"
|
|
9301
|
+
}
|
|
9302
|
+
}
|
|
9303
|
+
);
|
|
9304
|
+
}
|
|
9305
|
+
return null;
|
|
9306
|
+
}
|
|
9307
|
+
var MAX_MESSAGE_LENGTH = 8e3;
|
|
9308
|
+
function sanitizeInput(raw) {
|
|
9309
|
+
const stripped = raw.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, "");
|
|
9310
|
+
const trimmed = stripped.trim();
|
|
9311
|
+
if (!trimmed) {
|
|
9312
|
+
return { ok: false, error: "message must not be empty" };
|
|
9313
|
+
}
|
|
9314
|
+
if (trimmed.length > MAX_MESSAGE_LENGTH) {
|
|
9315
|
+
return { ok: false, error: `message must be \u2264 ${MAX_MESSAGE_LENGTH} characters` };
|
|
9316
|
+
}
|
|
9317
|
+
return { ok: true, value: trimmed };
|
|
9318
|
+
}
|
|
9319
|
+
function getOrCreatePlugin(configOrPlugin) {
|
|
9320
|
+
if (configOrPlugin instanceof VectorPlugin) return configOrPlugin;
|
|
9321
|
+
const cacheKey = "__retrivoraPlugin_" + JSON.stringify(configOrPlugin != null ? configOrPlugin : {}).slice(0, 64);
|
|
9322
|
+
if (!_g[cacheKey]) {
|
|
9323
|
+
_g[cacheKey] = new VectorPlugin(configOrPlugin);
|
|
9324
|
+
}
|
|
9325
|
+
return _g[cacheKey];
|
|
9326
|
+
}
|
|
7633
9327
|
function sseFrame(payload) {
|
|
7634
9328
|
return `data: ${JSON.stringify(payload)}
|
|
7635
9329
|
|
|
@@ -7667,47 +9361,88 @@ var SSE_HEADERS = {
|
|
|
7667
9361
|
"X-Accel-Buffering": "no"
|
|
7668
9362
|
// Disable Nginx buffering for streaming
|
|
7669
9363
|
};
|
|
7670
|
-
function createChatHandler(configOrPlugin) {
|
|
7671
|
-
const plugin =
|
|
9364
|
+
function createChatHandler(configOrPlugin, options) {
|
|
9365
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9366
|
+
const storage = new DatabaseStorage(plugin.getConfig());
|
|
9367
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
7672
9368
|
return async function POST(req) {
|
|
9369
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9370
|
+
if (authResult) return authResult;
|
|
9371
|
+
const rateLimited = checkRateLimit(req);
|
|
9372
|
+
if (rateLimited) return rateLimited;
|
|
7673
9373
|
try {
|
|
7674
9374
|
const body = await req.json();
|
|
7675
|
-
const { message, history = [], namespace } = body;
|
|
7676
|
-
|
|
7677
|
-
|
|
7678
|
-
|
|
9375
|
+
const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
|
|
9376
|
+
const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
|
|
9377
|
+
if (!sanitized.ok) {
|
|
9378
|
+
return import_server.NextResponse.json({ error: { code: "INVALID_INPUT", message: sanitized.error } }, { status: 400 });
|
|
9379
|
+
}
|
|
9380
|
+
const message = sanitized.value;
|
|
9381
|
+
const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
9382
|
+
await storage.saveMessage(sessionId, {
|
|
9383
|
+
id: userMsgId,
|
|
9384
|
+
role: "user",
|
|
9385
|
+
content: message
|
|
9386
|
+
}).catch((err) => console.warn("[createChatHandler] Failed to save user message:", err));
|
|
7679
9387
|
const result = await plugin.chat(message, history, namespace);
|
|
7680
|
-
|
|
9388
|
+
const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
9389
|
+
await storage.saveMessage(sessionId, {
|
|
9390
|
+
id: assistantMsgId,
|
|
9391
|
+
role: "assistant",
|
|
9392
|
+
content: result.reply,
|
|
9393
|
+
sources: result.sources,
|
|
9394
|
+
uiTransformation: result.ui_transformation,
|
|
9395
|
+
trace: result.trace
|
|
9396
|
+
}).catch((err) => console.warn("[createChatHandler] Failed to save assistant message:", err));
|
|
9397
|
+
return import_server.NextResponse.json(__spreadProps(__spreadValues({}, result), {
|
|
9398
|
+
messageId: assistantMsgId,
|
|
9399
|
+
userMessageId: userMsgId
|
|
9400
|
+
}));
|
|
7681
9401
|
} catch (err) {
|
|
7682
9402
|
const message = err instanceof Error ? err.message : "Internal server error";
|
|
7683
9403
|
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
7684
9404
|
}
|
|
7685
9405
|
};
|
|
7686
9406
|
}
|
|
7687
|
-
function createStreamHandler(configOrPlugin) {
|
|
7688
|
-
const plugin =
|
|
9407
|
+
function createStreamHandler(configOrPlugin, options) {
|
|
9408
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9409
|
+
const storage = new DatabaseStorage(plugin.getConfig());
|
|
9410
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
7689
9411
|
return async function POST(req) {
|
|
9412
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9413
|
+
if (authResult) return authResult;
|
|
9414
|
+
const rateLimited = checkRateLimit(req);
|
|
9415
|
+
if (rateLimited) return rateLimited;
|
|
7690
9416
|
let body;
|
|
7691
9417
|
try {
|
|
7692
9418
|
body = await req.json();
|
|
7693
9419
|
} catch (e) {
|
|
7694
|
-
return new Response(JSON.stringify({ error: "Invalid JSON body" }), {
|
|
9420
|
+
return new Response(JSON.stringify({ error: { code: "INVALID_JSON", message: "Invalid JSON body" } }), {
|
|
7695
9421
|
status: 400,
|
|
7696
9422
|
headers: { "Content-Type": "application/json" }
|
|
7697
9423
|
});
|
|
7698
9424
|
}
|
|
7699
|
-
const { message, history = [], namespace } = body;
|
|
7700
|
-
|
|
7701
|
-
|
|
7702
|
-
|
|
7703
|
-
|
|
7704
|
-
|
|
9425
|
+
const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
|
|
9426
|
+
const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
|
|
9427
|
+
if (!sanitized.ok) {
|
|
9428
|
+
return new Response(
|
|
9429
|
+
JSON.stringify({ error: { code: "INVALID_INPUT", message: sanitized.error } }),
|
|
9430
|
+
{ status: 400, headers: { "Content-Type": "application/json" } }
|
|
9431
|
+
);
|
|
7705
9432
|
}
|
|
9433
|
+
const message = sanitized.value;
|
|
9434
|
+
const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
9435
|
+
await storage.saveMessage(sessionId, {
|
|
9436
|
+
id: userMsgId,
|
|
9437
|
+
role: "user",
|
|
9438
|
+
content: message
|
|
9439
|
+
}).catch((err) => console.warn("[createStreamHandler] Failed to save user message:", err));
|
|
9440
|
+
const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
|
|
7706
9441
|
const encoder = new TextEncoder();
|
|
7707
9442
|
let isActive = true;
|
|
7708
9443
|
const stream = new ReadableStream({
|
|
7709
9444
|
async start(controller) {
|
|
7710
|
-
var
|
|
9445
|
+
var _a2;
|
|
7711
9446
|
const enqueue = (text) => {
|
|
7712
9447
|
if (!isActive) return;
|
|
7713
9448
|
try {
|
|
@@ -7718,11 +9453,13 @@ function createStreamHandler(configOrPlugin) {
|
|
|
7718
9453
|
};
|
|
7719
9454
|
try {
|
|
7720
9455
|
const pipelineStream = plugin.chatStream(message, history, namespace);
|
|
9456
|
+
let fullReply = "";
|
|
7721
9457
|
try {
|
|
7722
9458
|
for (var iter = __forAwait(pipelineStream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
|
|
7723
9459
|
const chunk = temp.value;
|
|
7724
9460
|
if (!isActive) break;
|
|
7725
9461
|
if (typeof chunk === "string") {
|
|
9462
|
+
fullReply += chunk;
|
|
7726
9463
|
enqueue(sseTextFrame(chunk));
|
|
7727
9464
|
} else if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "thinking") {
|
|
7728
9465
|
enqueue(`data: ${JSON.stringify(chunk)}
|
|
@@ -7735,9 +9472,10 @@ function createStreamHandler(configOrPlugin) {
|
|
|
7735
9472
|
if (responseChunk == null ? void 0 : responseChunk.trace) {
|
|
7736
9473
|
enqueue(sseObservabilityFrame(responseChunk.trace));
|
|
7737
9474
|
}
|
|
9475
|
+
let uiTransformation = responseChunk == null ? void 0 : responseChunk.ui_transformation;
|
|
7738
9476
|
if (sources.length > 0) {
|
|
7739
9477
|
try {
|
|
7740
|
-
|
|
9478
|
+
uiTransformation = (_a2 = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a2 : UITransformer.transform(message, sources, plugin.getConfig());
|
|
7741
9479
|
if (uiTransformation) {
|
|
7742
9480
|
enqueue(sseUIFrame(uiTransformation));
|
|
7743
9481
|
}
|
|
@@ -7745,11 +9483,22 @@ function createStreamHandler(configOrPlugin) {
|
|
|
7745
9483
|
console.warn("[createStreamHandler] UI transformation warning:", transformError);
|
|
7746
9484
|
try {
|
|
7747
9485
|
const fallback = UITransformer.transform(message, sources, plugin.getConfig());
|
|
7748
|
-
if (fallback)
|
|
9486
|
+
if (fallback) {
|
|
9487
|
+
uiTransformation = fallback;
|
|
9488
|
+
enqueue(sseUIFrame(fallback));
|
|
9489
|
+
}
|
|
7749
9490
|
} catch (e) {
|
|
7750
9491
|
}
|
|
7751
9492
|
}
|
|
7752
9493
|
}
|
|
9494
|
+
await storage.saveMessage(sessionId, {
|
|
9495
|
+
id: assistantMsgId,
|
|
9496
|
+
role: "assistant",
|
|
9497
|
+
content: fullReply,
|
|
9498
|
+
sources,
|
|
9499
|
+
uiTransformation,
|
|
9500
|
+
trace: responseChunk == null ? void 0 : responseChunk.trace
|
|
9501
|
+
}).catch((err) => console.warn("[createStreamHandler] Failed to save assistant message:", err));
|
|
7753
9502
|
}
|
|
7754
9503
|
}
|
|
7755
9504
|
} catch (temp) {
|
|
@@ -7786,12 +9535,15 @@ function createStreamHandler(configOrPlugin) {
|
|
|
7786
9535
|
console.log("[createStreamHandler] Stream connection closed by client:", reason);
|
|
7787
9536
|
}
|
|
7788
9537
|
});
|
|
7789
|
-
return new Response(stream, { headers: SSE_HEADERS });
|
|
9538
|
+
return new Response(stream, { headers: __spreadProps(__spreadValues({}, SSE_HEADERS), { "x-message-id": assistantMsgId, "x-user-message-id": userMsgId }) });
|
|
7790
9539
|
};
|
|
7791
9540
|
}
|
|
7792
|
-
function createIngestHandler(configOrPlugin) {
|
|
7793
|
-
const plugin =
|
|
9541
|
+
function createIngestHandler(configOrPlugin, options) {
|
|
9542
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9543
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
7794
9544
|
return async function POST(req) {
|
|
9545
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9546
|
+
if (authResult) return authResult;
|
|
7795
9547
|
try {
|
|
7796
9548
|
const body = await req.json();
|
|
7797
9549
|
const { documents, namespace } = body;
|
|
@@ -7806,9 +9558,14 @@ function createIngestHandler(configOrPlugin) {
|
|
|
7806
9558
|
}
|
|
7807
9559
|
};
|
|
7808
9560
|
}
|
|
7809
|
-
function createHealthHandler(configOrPlugin) {
|
|
7810
|
-
const plugin =
|
|
7811
|
-
|
|
9561
|
+
function createHealthHandler(configOrPlugin, options) {
|
|
9562
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9563
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
9564
|
+
return async function GET(req) {
|
|
9565
|
+
if (req) {
|
|
9566
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9567
|
+
if (authResult) return authResult;
|
|
9568
|
+
}
|
|
7812
9569
|
try {
|
|
7813
9570
|
const health = await plugin.checkHealth();
|
|
7814
9571
|
const status = health.allHealthy ? "ok" : "degraded";
|
|
@@ -7823,9 +9580,12 @@ function createHealthHandler(configOrPlugin) {
|
|
|
7823
9580
|
}
|
|
7824
9581
|
};
|
|
7825
9582
|
}
|
|
7826
|
-
function createUploadHandler(configOrPlugin) {
|
|
7827
|
-
const plugin =
|
|
9583
|
+
function createUploadHandler(configOrPlugin, options) {
|
|
9584
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9585
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
7828
9586
|
return async function POST(req) {
|
|
9587
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9588
|
+
if (authResult) return authResult;
|
|
7829
9589
|
try {
|
|
7830
9590
|
const formData = await req.formData();
|
|
7831
9591
|
const files = formData.getAll("files");
|
|
@@ -7899,6 +9659,190 @@ function createUploadHandler(configOrPlugin) {
|
|
|
7899
9659
|
}
|
|
7900
9660
|
};
|
|
7901
9661
|
}
|
|
9662
|
+
function createSuggestionsHandler(configOrPlugin, options) {
|
|
9663
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9664
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
9665
|
+
return async function POST(req) {
|
|
9666
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9667
|
+
if (authResult) return authResult;
|
|
9668
|
+
try {
|
|
9669
|
+
const body = await req.json();
|
|
9670
|
+
const { query, namespace } = body;
|
|
9671
|
+
if (typeof query !== "string") {
|
|
9672
|
+
return import_server.NextResponse.json({ error: "query is required" }, { status: 400 });
|
|
9673
|
+
}
|
|
9674
|
+
const suggestions = await plugin.getSuggestions(query, namespace);
|
|
9675
|
+
return import_server.NextResponse.json({ suggestions });
|
|
9676
|
+
} catch (err) {
|
|
9677
|
+
const message = err instanceof Error ? err.message : "Internal server error";
|
|
9678
|
+
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
9679
|
+
}
|
|
9680
|
+
};
|
|
9681
|
+
}
|
|
9682
|
+
function createHistoryHandler(configOrPlugin, options) {
|
|
9683
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9684
|
+
const storage = new DatabaseStorage(plugin.getConfig());
|
|
9685
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
9686
|
+
return async function handler(req) {
|
|
9687
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9688
|
+
if (authResult) return authResult;
|
|
9689
|
+
const url = new URL(req.url);
|
|
9690
|
+
const sessionId = url.searchParams.get("sessionId") || "default";
|
|
9691
|
+
if (req.method === "GET") {
|
|
9692
|
+
try {
|
|
9693
|
+
const history = await storage.getHistory(sessionId);
|
|
9694
|
+
return import_server.NextResponse.json({ history });
|
|
9695
|
+
} catch (err) {
|
|
9696
|
+
const message = err instanceof Error ? err.message : "Failed to fetch history";
|
|
9697
|
+
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
9698
|
+
}
|
|
9699
|
+
} else if (req.method === "POST") {
|
|
9700
|
+
try {
|
|
9701
|
+
const body = await req.json().catch(() => ({}));
|
|
9702
|
+
const sid = body.sessionId || sessionId;
|
|
9703
|
+
await storage.clearHistory(sid);
|
|
9704
|
+
return import_server.NextResponse.json({ success: true });
|
|
9705
|
+
} catch (err) {
|
|
9706
|
+
const message = err instanceof Error ? err.message : "Failed to clear history";
|
|
9707
|
+
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
9708
|
+
}
|
|
9709
|
+
}
|
|
9710
|
+
return import_server.NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
|
|
9711
|
+
};
|
|
9712
|
+
}
|
|
9713
|
+
function createFeedbackHandler(configOrPlugin, options) {
|
|
9714
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9715
|
+
const storage = new DatabaseStorage(plugin.getConfig());
|
|
9716
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
9717
|
+
return async function handler(req) {
|
|
9718
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9719
|
+
if (authResult) return authResult;
|
|
9720
|
+
if (req.method === "GET") {
|
|
9721
|
+
try {
|
|
9722
|
+
const url = new URL(req.url);
|
|
9723
|
+
const messageId = url.searchParams.get("messageId");
|
|
9724
|
+
if (!messageId) {
|
|
9725
|
+
const feedbackList = await storage.listFeedback();
|
|
9726
|
+
return import_server.NextResponse.json({ feedback: feedbackList });
|
|
9727
|
+
}
|
|
9728
|
+
const feedback = await storage.getFeedback(messageId);
|
|
9729
|
+
return import_server.NextResponse.json({ feedback });
|
|
9730
|
+
} catch (err) {
|
|
9731
|
+
const message = err instanceof Error ? err.message : "Failed to fetch feedback";
|
|
9732
|
+
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
9733
|
+
}
|
|
9734
|
+
} else if (req.method === "POST") {
|
|
9735
|
+
try {
|
|
9736
|
+
const body = await req.json();
|
|
9737
|
+
const { messageId, sessionId = "default", rating, comment } = body;
|
|
9738
|
+
if (!messageId) {
|
|
9739
|
+
return import_server.NextResponse.json({ error: "messageId is required" }, { status: 400 });
|
|
9740
|
+
}
|
|
9741
|
+
if (!rating) {
|
|
9742
|
+
return import_server.NextResponse.json({ error: "rating is required" }, { status: 400 });
|
|
9743
|
+
}
|
|
9744
|
+
await storage.saveFeedback({ messageId, sessionId, rating, comment });
|
|
9745
|
+
return import_server.NextResponse.json({ success: true });
|
|
9746
|
+
} catch (err) {
|
|
9747
|
+
const message = err instanceof Error ? err.message : "Failed to save feedback";
|
|
9748
|
+
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
9749
|
+
}
|
|
9750
|
+
}
|
|
9751
|
+
return import_server.NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
|
|
9752
|
+
};
|
|
9753
|
+
}
|
|
9754
|
+
function createSessionsHandler(configOrPlugin, options) {
|
|
9755
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9756
|
+
const storage = new DatabaseStorage(plugin.getConfig());
|
|
9757
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
9758
|
+
return async function GET(req) {
|
|
9759
|
+
if (req) {
|
|
9760
|
+
const authResult = await checkAuth(req, onAuthorize);
|
|
9761
|
+
if (authResult) return authResult;
|
|
9762
|
+
}
|
|
9763
|
+
void req;
|
|
9764
|
+
try {
|
|
9765
|
+
const sessions = await storage.listSessions();
|
|
9766
|
+
return import_server.NextResponse.json({ sessions });
|
|
9767
|
+
} catch (err) {
|
|
9768
|
+
const message = err instanceof Error ? err.message : "Failed to list sessions";
|
|
9769
|
+
return import_server.NextResponse.json({ error: message }, { status: 500 });
|
|
9770
|
+
}
|
|
9771
|
+
};
|
|
9772
|
+
}
|
|
9773
|
+
function createRagHandler(configOrPlugin, options) {
|
|
9774
|
+
const plugin = getOrCreatePlugin(configOrPlugin);
|
|
9775
|
+
const onAuthorize = options == null ? void 0 : options.onAuthorize;
|
|
9776
|
+
const chatHandler = createChatHandler(plugin, { onAuthorize });
|
|
9777
|
+
const streamHandler = createStreamHandler(plugin, { onAuthorize });
|
|
9778
|
+
const uploadHandler = createUploadHandler(plugin, { onAuthorize });
|
|
9779
|
+
const healthHandler = createHealthHandler(plugin, { onAuthorize });
|
|
9780
|
+
const suggestionsHandler = createSuggestionsHandler(plugin, { onAuthorize });
|
|
9781
|
+
const historyHandler = createHistoryHandler(plugin, { onAuthorize });
|
|
9782
|
+
const feedbackHandler = createFeedbackHandler(plugin, { onAuthorize });
|
|
9783
|
+
const sessionsHandler = createSessionsHandler(plugin, { onAuthorize });
|
|
9784
|
+
async function routePostRequest(req, segment) {
|
|
9785
|
+
switch (segment) {
|
|
9786
|
+
case "chat":
|
|
9787
|
+
return streamHandler(req);
|
|
9788
|
+
case "chat-sync":
|
|
9789
|
+
return chatHandler(req);
|
|
9790
|
+
case "upload":
|
|
9791
|
+
return uploadHandler(req);
|
|
9792
|
+
case "suggestions":
|
|
9793
|
+
return suggestionsHandler(req);
|
|
9794
|
+
case "health":
|
|
9795
|
+
return healthHandler(req);
|
|
9796
|
+
case "history":
|
|
9797
|
+
case "history/clear":
|
|
9798
|
+
return historyHandler(req);
|
|
9799
|
+
case "feedback":
|
|
9800
|
+
return feedbackHandler(req);
|
|
9801
|
+
default:
|
|
9802
|
+
return import_server.NextResponse.json({ error: `Not Found: POST segment "${segment}" not supported.` }, { status: 404 });
|
|
9803
|
+
}
|
|
9804
|
+
}
|
|
9805
|
+
async function routeGetRequest(req, segment) {
|
|
9806
|
+
switch (segment) {
|
|
9807
|
+
case "health":
|
|
9808
|
+
return healthHandler(req);
|
|
9809
|
+
case "history":
|
|
9810
|
+
return historyHandler(req);
|
|
9811
|
+
case "feedback":
|
|
9812
|
+
return feedbackHandler(req);
|
|
9813
|
+
case "sessions":
|
|
9814
|
+
return sessionsHandler(req);
|
|
9815
|
+
default:
|
|
9816
|
+
return import_server.NextResponse.json({ error: `Method Not Allowed: GET segment "${segment}" not supported.` }, { status: 405 });
|
|
9817
|
+
}
|
|
9818
|
+
}
|
|
9819
|
+
async function getSegment(context) {
|
|
9820
|
+
var _a2;
|
|
9821
|
+
const resolvedParams = typeof ((_a2 = context == null ? void 0 : context.params) == null ? void 0 : _a2.then) === "function" ? await context.params : context == null ? void 0 : context.params;
|
|
9822
|
+
const segments = (resolvedParams == null ? void 0 : resolvedParams.retrivora) || [];
|
|
9823
|
+
return segments.join("/") || "chat";
|
|
9824
|
+
}
|
|
9825
|
+
return {
|
|
9826
|
+
GET: async (req, context) => {
|
|
9827
|
+
try {
|
|
9828
|
+
const segment = await getSegment(context);
|
|
9829
|
+
return await routeGetRequest(req, segment);
|
|
9830
|
+
} catch (err) {
|
|
9831
|
+
const msg = err instanceof Error ? err.message : "GET Routing failed";
|
|
9832
|
+
return import_server.NextResponse.json({ error: msg }, { status: 500 });
|
|
9833
|
+
}
|
|
9834
|
+
},
|
|
9835
|
+
POST: async (req, context) => {
|
|
9836
|
+
try {
|
|
9837
|
+
const segment = await getSegment(context);
|
|
9838
|
+
return await routePostRequest(req, segment);
|
|
9839
|
+
} catch (err) {
|
|
9840
|
+
const msg = err instanceof Error ? err.message : "POST Routing failed";
|
|
9841
|
+
return import_server.NextResponse.json({ error: msg }, { status: 500 });
|
|
9842
|
+
}
|
|
9843
|
+
}
|
|
9844
|
+
};
|
|
9845
|
+
}
|
|
7902
9846
|
// Annotate the CommonJS export names for ESM import in node:
|
|
7903
9847
|
0 && (module.exports = {
|
|
7904
9848
|
AnthropicProvider,
|
|
@@ -7915,8 +9859,10 @@ function createUploadHandler(configOrPlugin) {
|
|
|
7915
9859
|
EmbeddingFailedException,
|
|
7916
9860
|
EmbeddingStrategy,
|
|
7917
9861
|
EmbeddingStrategyResolver,
|
|
9862
|
+
GroqProvider,
|
|
7918
9863
|
LLMFactory,
|
|
7919
9864
|
LLM_PROFILES,
|
|
9865
|
+
LicenseVerifier,
|
|
7920
9866
|
MilvusProvider,
|
|
7921
9867
|
MongoDBProvider,
|
|
7922
9868
|
MultiTablePostgresProvider,
|
|
@@ -7930,6 +9876,7 @@ function createUploadHandler(configOrPlugin) {
|
|
|
7930
9876
|
ProviderNotFoundException,
|
|
7931
9877
|
ProviderRegistry,
|
|
7932
9878
|
QdrantProvider,
|
|
9879
|
+
QwenProvider,
|
|
7933
9880
|
RateLimitException,
|
|
7934
9881
|
RedisProvider,
|
|
7935
9882
|
RetrievalException,
|
|
@@ -7941,14 +9888,19 @@ function createUploadHandler(configOrPlugin) {
|
|
|
7941
9888
|
VectorPlugin,
|
|
7942
9889
|
WeaviateProvider,
|
|
7943
9890
|
createChatHandler,
|
|
9891
|
+
createFeedbackHandler,
|
|
7944
9892
|
createFromPreset,
|
|
7945
9893
|
createHealthHandler,
|
|
9894
|
+
createHistoryHandler,
|
|
7946
9895
|
createIngestHandler,
|
|
9896
|
+
createRagHandler,
|
|
9897
|
+
createSessionsHandler,
|
|
7947
9898
|
createStreamHandler,
|
|
7948
9899
|
createUploadHandler,
|
|
7949
9900
|
getRagConfig,
|
|
7950
9901
|
sseErrorFrame,
|
|
7951
9902
|
sseFrame,
|
|
7952
9903
|
sseMetaFrame,
|
|
7953
|
-
sseTextFrame
|
|
9904
|
+
sseTextFrame,
|
|
9905
|
+
wrapError
|
|
7954
9906
|
});
|