@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.
Files changed (62) hide show
  1. package/README.md +130 -113
  2. package/dist/{ILLMProvider-DNhyOYoK.d.mts → ILLMProvider-B8ROITYK.d.mts} +59 -8
  3. package/dist/{ILLMProvider-DNhyOYoK.d.ts → ILLMProvider-B8ROITYK.d.ts} +59 -8
  4. package/dist/handlers/index.d.mts +2 -2
  5. package/dist/handlers/index.d.ts +2 -2
  6. package/dist/handlers/index.js +2376 -489
  7. package/dist/handlers/index.mjs +2372 -489
  8. package/dist/{index-CjQdL0cX.d.ts → index-B8PbEFSY.d.mts} +17 -3
  9. package/dist/{index-CHL1jdYm.d.mts → index-BCPKUAVL.d.ts} +33 -41
  10. package/dist/{index-Hgbwl9X4.d.ts → index-CrxCy36A.d.mts} +33 -41
  11. package/dist/{index-C9v7-tWd.d.mts → index-DNvoi-sV.d.ts} +17 -3
  12. package/dist/index.css +695 -203
  13. package/dist/index.d.mts +37 -7
  14. package/dist/index.d.ts +37 -7
  15. package/dist/index.js +1197 -286
  16. package/dist/index.mjs +1221 -297
  17. package/dist/server.d.mts +62 -6
  18. package/dist/server.d.ts +62 -6
  19. package/dist/server.js +2526 -574
  20. package/dist/server.mjs +2517 -573
  21. package/package.json +12 -10
  22. package/src/app/constants.tsx +207 -212
  23. package/src/app/layout.tsx +4 -28
  24. package/src/app/types.ts +17 -17
  25. package/src/components/AmbientBackground.tsx +10 -10
  26. package/src/components/ArchitectureCard.tsx +43 -7
  27. package/src/components/ArchitectureCardsSection.tsx +37 -4
  28. package/src/components/ChatWidget.tsx +4 -1
  29. package/src/components/ChatWindow.tsx +9 -2
  30. package/src/components/CodeViewer.tsx +19 -14
  31. package/src/components/DocViewer.tsx +75 -15
  32. package/src/components/Documentation.tsx +111 -28
  33. package/src/components/Hero.tsx +103 -20
  34. package/src/components/Lifecycle.tsx +65 -25
  35. package/src/components/MarkdownComponents.tsx +44 -1
  36. package/src/components/MessageBubble.tsx +162 -50
  37. package/src/components/constants.tsx +279 -0
  38. package/src/config/RagConfig.ts +56 -10
  39. package/src/config/constants.ts +5 -0
  40. package/src/config/serverConfig.ts +15 -0
  41. package/src/core/ConfigResolver.ts +30 -25
  42. package/src/core/DatabaseStorage.ts +469 -0
  43. package/src/core/LicenseVerifier.ts +154 -0
  44. package/src/core/MultiAgentCoordinator.ts +239 -0
  45. package/src/core/Pipeline.ts +148 -16
  46. package/src/core/ProviderRegistry.ts +5 -5
  47. package/src/core/Retrivora.ts +52 -6
  48. package/src/core/VectorPlugin.ts +74 -11
  49. package/src/core/mcp.ts +261 -0
  50. package/src/exceptions/index.ts +52 -0
  51. package/src/handlers/index.ts +504 -47
  52. package/src/hooks/useRagChat.ts +100 -43
  53. package/src/hooks/useStoredMessages.ts +15 -4
  54. package/src/index.ts +7 -0
  55. package/src/llm/LLMFactory.ts +15 -6
  56. package/src/llm/providers/GroqProvider.ts +176 -0
  57. package/src/llm/providers/QwenProvider.ts +191 -0
  58. package/src/server.ts +23 -13
  59. package/src/types/chat.ts +16 -0
  60. package/src/types/props.ts +50 -1
  61. package/.env.example +0 -80
  62. 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, path) {
115
- if (!path || !obj) return void 0;
116
- return path.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
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 _a, _b;
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 = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _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 _a, _b;
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 = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _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 _a;
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 }, (_a = doc.metadata) != null ? _a : {})
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 _a;
258
+ var _a2;
290
259
  return {
291
260
  id: String(d.id),
292
261
  values: d.vector,
293
- metadata: __spreadValues({ content: d.content }, (_a = d.metadata) != null ? _a : {})
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 _a;
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 ((_a = result.matches) != null ? _a : []).map((m) => {
308
- var _a2, _b;
276
+ return ((_a2 = result.matches) != null ? _a2 : []).map((m) => {
277
+ var _a3, _b;
309
278
  return {
310
279
  id: m.id,
311
- score: (_a2 = m.score) != null ? _a2 : 0,
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 _a;
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 = (_a = opts.dimensions) != null ? _a : 1536;
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 _a;
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((_a = doc.metadata) != null ? _a : {}), vectorLiteral]
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 _a;
429
+ var _a2;
461
430
  const offset = idx * 5;
462
- values.push(doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), `[${doc.vector.join(",")}]`);
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 _a;
546
- const synonyms = (_a = FIELD_SYNONYMS[uiKey]) != null ? _a : [];
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 _a, _b, _c;
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 = (_a = opts.dimensions) != null ? _a : 768;
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 _a;
667
+ var _a2;
699
668
  if (docs.length === 0) return;
700
669
  const docsByFile = {};
701
670
  for (const doc of docs) {
702
- const fileName = ((_a = doc.metadata) == null ? void 0 : _a.fileName) || this.uploadTable;
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 _a2, _b;
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(((_a2 = doc.metadata) == null ? void 0 : _a2[h]) || ""));
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 _a;
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 _a3;
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 = (_a3 = FIELD_SYNONYMS[key]) != null ? _a3 : [];
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 _a2 = row, { hybrid_score, id } = _a2, rest = __objRest(_a2, ["hybrid_score", "id"]);
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 = (_a = allResults[0].metadata) == null ? void 0 : _a.source_table;
900
+ const bestMatchTable = (_a2 = allResults[0].metadata) == null ? void 0 : _a2.source_table;
932
901
  const finalSorted = allResults.filter((res) => {
933
- var _a2;
934
- return ((_a2 = res.metadata) == null ? void 0 : _a2.source_table) === bestMatchTable;
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 _a;
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 = ((_a = data.result) == null ? void 0 : _a.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 _a;
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) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
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 _a;
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 = (_a = err.response) == null ? void 0 : _a.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 _a;
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: ((_a = this.config.options) == null ? void 0 : _a.efSearch) || Math.max(topK * 20, 128),
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 _a;
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) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
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 _a, _b;
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 = (_a = data.data) == null ? void 0 : _a.Get) == null ? void 0 : _b[this.indexName]) || [];
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 path = `path: [${JSON.stringify(key)}], operator: Equal`;
1863
- if (typeof value === "number") return `{ ${path}, valueNumber: ${value} }`;
1864
- if (typeof value === "boolean") return `{ ${path}, valueBoolean: ${value} }`;
1865
- return `{ ${path}, valueString: ${JSON.stringify(value)} }`;
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 _a;
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: (_a = this.opts.timeout) != null ? _a : 3e4
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 _a, _b, _c;
1906
- const endpoint = (_a = this.opts.upsertEndpoint) != null ? _a : "/upsert";
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 _a, _b;
1940
- const endpoint = (_a = this.opts.queryEndpoint) != null ? _a : "/query";
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 _a2, _b2, _c, _d, _e, _f, _g;
1935
+ var _a3, _b2, _c, _d, _e, _f, _g2;
1967
1936
  return {
1968
- id: item[(_a2 = this.opts.queryIdField) != null ? _a2 : "id"],
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: (_g = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g : {}
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 _a, _b;
1982
- const endpoint = (_a = this.opts.deleteEndpoint) != null ? _a : "/delete";
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 _a;
2001
- const endpoint = (_a = this.opts.deleteNamespaceEndpoint) != null ? _a : "/delete-namespace";
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 _a;
1980
+ var _a2;
2012
1981
  try {
2013
- const endpoint = (_a = this.opts.pingEndpoint) != null ? _a : "/health";
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 _a;
2204
- const value = (_a = env[name]) == null ? void 0 : _a.trim();
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 _a;
2218
- const value = (_a = readString(env, name)) != null ? _a : fallback;
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 _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, _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;
2229
- const projectId = (_c = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : base == null ? void 0 : base.projectId) != null ? _c : "__default__";
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 = (_g = (_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 ? _g : "";
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: (_ha = (_ga = readString(env, "VECTOR_DB_INDEX")) != null ? _ga : vectorDbOptions.indexName) != null ? _ha : "rag-index",
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: (_ja = (_ia = readString(env, "LLM_MODEL")) != null ? _ia : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _ja : "gpt-4o",
2308
- apiKey: (_ka = llmApiKeyByProvider[llmProvider]) != null ? _ka : "",
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: (_la = readString(env, "EMBEDDING_MODEL")) != null ? _la : "text-embedding-3-small",
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: (_na = (_ma = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _ma : readString(env, "UI_TITLE")) != null ? _na : "AI Assistant",
2333
- subtitle: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _oa : readString(env, "UI_SUBTITLE")) != null ? _pa : "Powered by RAG",
2334
- primaryColor: (_ra = (_qa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _qa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ra : "#10b981",
2335
- accentColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _sa : readString(env, "UI_ACCENT_COLOR")) != null ? _ta : "#3b82f6",
2336
- logoUrl: (_ua = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _ua : readString(env, "UI_LOGO_URL"),
2337
- placeholder: (_wa = (_va = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _va : readString(env, "UI_PLACEHOLDER")) != null ? _wa : "Ask me anything\u2026",
2338
- showSources: ((_ya = (_xa = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _xa : readString(env, "UI_SHOW_SOURCES")) != null ? _ya : "true") !== "false",
2339
- welcomeMessage: (_Aa = (_za = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _za : readString(env, "UI_WELCOME_MESSAGE")) != null ? _Aa : "Hello! I'm your AI assistant. Ask me anything about your documents.",
2340
- visualStyle: (_Ca = (_Ba = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Ba : readString(env, "UI_VISUAL_STYLE")) != null ? _Ca : "glass",
2341
- borderRadius: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Da : readString(env, "UI_BORDER_RADIUS")) != null ? _Ea : "xl",
2342
- allowUpload: ((_Ga = (_Fa = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Fa : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ga : "false") === "true"
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: (_Ha = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ha.split(",").map((f) => f.trim()),
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: (_Ia = readString(env, "RAG_ARCHITECTURE")) != null ? _Ia : "simple",
2355
- chunkingStrategy: (_Ja = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _Ja : "recursive",
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 _a;
2409
+ var _a2;
2451
2410
  if (!hostConfig) return this.resolve(void 0, env);
2452
2411
  const normalized = __spreadProps(__spreadValues({}, hostConfig), {
2453
- vectorDb: (_a = hostConfig.vectorDb) != null ? _a : hostConfig.vectorDatabase,
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 ConfigurationException("[ConfigResolver] projectId is required");
2422
+ throw new Error("[ConfigResolver] projectId is required");
2464
2423
  }
2465
2424
  if (!config.vectorDb.provider) {
2466
- throw new ConfigurationException("[ConfigResolver] vectorDb.provider is required");
2425
+ throw new Error("[ConfigResolver] vectorDb.provider is required");
2467
2426
  }
2468
2427
  if (!config.llm.provider) {
2469
- throw new ConfigurationException("[ConfigResolver] llm.provider is required");
2428
+ throw new Error("[ConfigResolver] llm.provider is required");
2470
2429
  }
2471
2430
  }
2472
2431
  static mergeRetrievalWorkflow(rag, retrieval, workflow) {
2473
- var _a, _b, _c, _d, _e;
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 = (_a = retrieval.topK) != null ? _a : 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 OpenAI2 = await import("openai");
2560
- const client = new OpenAI2.default({ apiKey });
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 _a, _b, _c, _d, _e, _f, _g, _h, _i;
2582
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
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 = (_g = completion.choices[0]) == null ? void 0 : _g.message) == null ? void 0 : _h.content) != null ? _i : "";
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 _a, _b, _c, _d, _e, _f, _g, _h;
2606
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
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 = (_g = chunk.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content) || "";
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 _a, _b, _c, _d, _e;
2653
- const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-3-small";
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 _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2731
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
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 = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
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 _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2770
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
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 = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
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 _a, _b;
2855
- const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
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 _a, _b, _c, _d, _e, _f;
2914
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
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 _a, _b, _c, _d, _e, _f, _g, _h;
2933
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
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 ((_g = json.message) == null ? void 0 : _g.content) {
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 _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2992
- const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "nomic-embed-text";
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 !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
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 _a, _b;
3052
+ var _a2, _b;
3094
3053
  const timestamp = Date.now();
3095
- const apiKey = (_b = (_a = config.apiKey) != null ? _a : process.env.GOOGLE_GENAI_API_KEY) != null ? _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 _a;
3126
- if (((_a = this.embeddingConfig) == null ? void 0 : _a.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
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 _a, _b;
3134
- return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
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 _a, _b, _c, _d, _e, _f;
3155
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
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 _a, _b, _c, _d, _e, _f;
3173
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
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 _a, _b;
3167
+ var _a2, _b;
3209
3168
  const content = applyPrefix(
3210
3169
  text,
3211
3170
  options == null ? void 0 : options.taskType,
3212
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
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 _a, _b;
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
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
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 _a;
3255
- return (_a = e.values) != null ? _a : [];
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/UniversalLLMAdapter.ts
3276
- var import_axios2 = __toESM(require("axios"));
3277
- init_templateUtils();
3278
-
3279
- // src/config/UniversalProfiles.ts
3280
- var OPENAI_BASE = {
3281
- chatPath: "/chat/completions",
3282
- embedPath: "/embeddings",
3283
- responseExtractPath: "choices[0].message.content",
3284
- embedExtractPath: "data[0].embedding",
3285
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
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
- var VECTOR_PROFILES = {
3316
- "pinecone-rest": {
3317
- queryPath: "/query",
3318
- upsertPath: "/vectors/upsert",
3319
- responseExtractPath: "matches",
3320
- idPath: "id",
3321
- scorePath: "score",
3322
- contentPath: "metadata.content",
3323
- metadataPath: "metadata",
3324
- queryPayloadTemplate: '{"vector":{{vector}},"topK":{{topK}},"includeMetadata":true,"namespace":"{{namespace}}"}'
3325
- },
3326
- "mongodb-atlas": {
3327
- queryPath: "/action/aggregate",
3328
- responseExtractPath: "documents",
3329
- idPath: "_id",
3330
- scorePath: "score",
3331
- contentPath: "content",
3332
- metadataPath: "metadata",
3333
- 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"}}}]}'
3334
- },
3335
- "chromadb": {
3336
- queryPath: "/api/v1/collections/{{index}}/query",
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
- // src/llm/providers/UniversalLLMAdapter.ts
3356
- var UniversalLLMAdapter = class {
3357
- constructor(config) {
3358
- var _a, _b, _c, _d, _e, _f, _g, _h;
3359
- this.model = config.model;
3360
- const llmConfig = config;
3361
- const options = (_a = llmConfig.options) != null ? _a : {};
3362
- let profile = {};
3363
- if (typeof options.profile === "string") {
3364
- profile = LLM_PROFILES[options.profile] || {};
3365
- } else if (typeof options.profile === "object" && options.profile !== null) {
3366
- profile = options.profile;
3367
- }
3368
- this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
3369
- this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
3370
- this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
3371
- this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
3372
- this.apiKey = config.apiKey;
3373
- this.baseUrl = (_g = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g : "";
3374
- if (!this.baseUrl) {
3375
- throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
3376
- }
3377
- this.resolvedHeaders = __spreadValues(__spreadValues({
3378
- "Content-Type": "application/json"
3379
- }, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {});
3380
- this.http = import_axios2.default.create({
3381
- baseURL: this.baseUrl,
3382
- headers: this.resolvedHeaders,
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 _a, _b;
3388
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
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
- { role: "system", content: `${this.systemPrompt}
3391
-
3392
- Context:
3393
- ${context != null ? context : "None"}` },
3394
- ...messages
3310
+ systemMessage,
3311
+ ...messages.map((m) => ({
3312
+ role: m.role,
3313
+ content: m.content
3314
+ }))
3395
3315
  ];
3396
- let payload;
3397
- if (this.opts.chatPayloadTemplate) {
3398
- payload = buildPayload(this.opts.chatPayloadTemplate, {
3399
- model: this.model,
3400
- messages: formattedMessages,
3401
- maxTokens: this.maxTokens,
3402
- temperature: this.temperature
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 _a, _b, _c;
3428
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
3429
- const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
3430
- const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
3431
- const formattedMessages = [
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 _a, _b;
3508
- const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
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(path, payload);
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 _a, _b;
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((_a = llmConfig.provider) != null ? _a : "").toLowerCase();
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
- "LLM",
3619
- String(llmConfig.provider),
3620
- `[LLMFactory] Unknown provider "${llmConfig.provider}". Built-in providers: ${_LLMFactory.listProviders().join(", ")}. Register a custom provider with LLMFactory.register().`
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 _a;
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 = ((_a = process.env.POSTGRES_MODE) != null ? _a : "multi").toLowerCase();
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 _a, _b;
4644
+ var _a2, _b;
4163
4645
  try {
4164
4646
  const { Document, SentenceSplitter, MetadataMode } = await import(`${"llamaindex"}`);
4165
4647
  const splitter = new SentenceSplitter({
4166
- chunkSize: (_a = options.chunkSize) != null ? _a : 1e3,
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
- } catch (error) {
4260
- const isMissing = error instanceof Error && error.message.includes("Cannot find module");
4261
- const hint = isMissing ? " Make sure 'langchain' and '@langchain/core' are installed:\n npm install langchain @langchain/core" : "";
4262
- throw new Error(
4263
- `[LangChainAgent] Failed to initialize.${hint}
4264
- ${error instanceof Error ? error.message : String(error)}`
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
- * Run the agentic flow.
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 run(input, chatHistory = []) {
4275
- var _a, _b, _c;
4276
- if (!this.agent) {
4277
- throw new Error("[LangChainAgent] Agent not initialized. Call initialize() first.");
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
- const { HumanMessage, AIMessage } = await import("@langchain/core/messages");
4280
- const historyMessages = chatHistory.map(
4281
- (m) => m.role === "user" ? new HumanMessage(m.content) : new AIMessage(m.content)
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
- const response = await this.agent.invoke({
4284
- messages: [...historyMessages, new HumanMessage(input)]
4285
- });
4286
- const lastMessage = (_a = response == null ? void 0 : response.messages) == null ? void 0 : _a.at(-1);
4287
- if (lastMessage && typeof lastMessage.content === "string") {
4288
- return lastMessage.content;
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
- if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
4291
- return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
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 String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
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 _a, _b, _c, _d;
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 ? (_a = match[p.group]) != null ? _a : match[0] : match[0];
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 _a;
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 = (_a = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a : "";
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 _a;
4951
- const provider = (_a = this.models.get(role)) != null ? _a : this.models.get("default");
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 _a, _b, _c;
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 (_a = this.transformToHistogram(profile, userQuery)) != null ? _a : this.transformToBarChart(filteredData, profile, userQuery);
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 _a;
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 _a2;
5318
- return String((_a2 = record.fields[dimension.key]) != null ? _a2 : "");
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 ${(_a = dimension == null ? void 0 : dimension.label) != null ? _a : "Category"}`,
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 _a, _b, _c;
5339
- const timestamp = String((_a = record.fields[dateField.key]) != null ? _a : "");
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 _a;
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 _a2, _b, _c, _d, _e;
6271
+ var _a3, _b, _c, _d, _e;
5359
6272
  const meta = item.metadata || {};
5360
6273
  const label = String(
5361
- (_c = (_b = (_a2 = this.getDynamicVal(meta, "name")) != null ? _a2 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
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 ? `${(_a = measure == null ? void 0 : measure.label) != null ? _a : "Count"} by ${dimension.label}` : "Comparison",
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 _a;
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((_a = this.getRecordLabel(record)) != null ? _a : record.id) };
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 _a, _b, _c;
6350
+ var _a2, _b, _c;
5438
6351
  const meta = item.metadata || {};
5439
- const seriesName = String((_c = (_b = (_a = meta.name) != null ? _a : meta.product) != null ? _b : item.id) != null ? _c : "Item");
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 _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
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 = (_a = p.type) != null ? _a : p.view) != null ? _b : p.chartType) != null ? _c : "")
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 = (_g = (_f = p.data) != null ? _f : p.table) != null ? _g : p.rows) != null ? _h : p.items) != null ? _i : p.content) != null ? _j : null;
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 _a;
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 (_a = mapping[type.toLowerCase()]) != null ? _a : null;
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 _a, _b;
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 = (_a = ranked[0]) != null ? _a : productCategory) != null ? _b : profile.categoricalFields[0];
6684
+ return (_b = (_a2 = ranked[0]) != null ? _a2 : productCategory) != null ? _b : profile.categoricalFields[0];
5772
6685
  }
5773
6686
  static selectNumericField(profile, query) {
5774
- var _a;
5775
- return (_a = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a : profile.numericFields[0];
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 _a, _b, _c;
5805
- const category = String((_a = record.fields[dimensionKey]) != null ? _a : "Other").trim() || "Other";
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 _a;
5885
- const cat = (_a = this.getProductCategory(item)) != null ? _a : "Other";
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 _a, _b, _c, _d, _e;
6806
+ var _a2, _b, _c, _d, _e;
5894
6807
  const meta = item.metadata || {};
5895
6808
  return {
5896
- timestamp: (_b = (_a = meta.timestamp) != null ? _a : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
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 _a;
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 = (_a = resolveMetadataValue(meta, key)) != null ? _a : meta[key];
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 _a, _b;
6065
- const cat = (_a = this.getProductCategory(d)) != null ? _a : "Other";
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 _a;
7022
+ var _a2;
6110
7023
  if (!meta) return void 0;
6111
- const mapping = (_a = config == null ? void 0 : config.rag) == null ? void 0 : _a.uiMapping;
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 _a;
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
- (_a = this.extractProductDescriptionFromContent(item.content)) != null ? _a : this.getProductDescriptionValue(meta, config, trainedSchema)
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 _a, _b, _c, _d;
7147
+ var _a2, _b, _c, _d;
6235
7148
  return {
6236
7149
  index: i + 1,
6237
- content: (_b = (_a = s.content) == null ? void 0 : _a.substring(0, 400)) != null ? _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
- var _a, _b, _c, _d, _e;
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 = (_a = config.rag) == null ? void 0 : _a.chunkSize) != null ? _b : 1e3,
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 _a;
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 (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic") {
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 _a, _b;
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: (_a = this.config.rag) == null ? void 0 : _a.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 Error(
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 _a;
7581
+ var _a2;
6606
7582
  await this.initialize();
6607
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic" && this.agent) {
6608
- const agentReply = await this.agent.run(question, history);
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
- askStream(_0) {
7667
+ askStreamInternal(_0) {
6652
7668
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
6653
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
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 = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
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, (_g = this.config.rag) == null ? void 0 : _g.filterableFields);
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 && (((_m = this.config.llm.options) == null ? void 0 : _m.thinking) === true || ((_n = this.config.llm.options) == null ? void 0 : _n.thinking) === "enabled" || ((_o = this.config.llm.options) == null ? void 0 : _o.thinking) !== false);
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 && (((_p = this.config.llm.options) == null ? void 0 : _p.thinking) === true || ((_q = this.config.llm.options) == null ? void 0 : _q.thinking) === "enabled" || isReasoningModel && ((_r = this.config.llm.options) == null ? void 0 : _r.thinking) !== false);
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 = (_s = this.config.llm.systemPrompt) != null ? _s : "";
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 = ((_t = this.config.llm.options) == null ? void 0 : _t.hallucinationScoring) === true || this.config.llm.provider !== "ollama" && ((_u = this.config.llm.options) == null ? void 0 : _u.hallucinationScoring) !== false;
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: ((_v = this.config.rag) == null ? void 0 : _v.useReranking) ? Math.round(rerankMs) : void 0,
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 trace = __spreadValues({
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 _a2;
7960
+ var _a3;
6918
7961
  return {
6919
7962
  id: s.id,
6920
7963
  score: s.score,
6921
7964
  content: s.content,
6922
- metadata: (_a2 = s.metadata) != null ? _a2 : {},
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
- }, hallucinationResult ? {
6930
- hallucinationScore: hallucinationResult.score,
6931
- hallucinationReason: hallucinationResult.reason
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 _a;
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 = ((_a = this.config.llm.options) == null ? void 0 : _a.disableLlmUiTransform) === true;
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 _a, _b;
8056
+ var _a2, _b;
6985
8057
  const primary = predicates[0];
6986
- const aValue = (_a = this.resolveNumericPredicateValue(a, primary)) != null ? _a : 0;
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 _a, _b, _c, _d, _e, _f, _g;
7059
- const ns = (_a = options.namespace) != null ? _a : this.config.projectId;
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 = (_g = source.metadata) == null ? void 0 : _g.parent_id;
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
- } catch (error) {
7160
- console.error("[Pipeline] Failed to generate suggestions:", error);
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
- this.config = ConfigResolver.resolve(hostConfig);
7273
- this.validationPromise = ConfigValidator.validateAndThrow(this.config);
7274
- this.pipeline = new Pipeline(this.config);
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
- await this.validationPromise;
7308
- return this.pipeline.ask(message, history, namespace);
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
- yield new __await(this.validationPromise);
7316
- yield* __yieldStar(this.pipeline.askStream(message, history, namespace));
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
- await this.validationPromise;
7324
- return this.pipeline.ingest(documents, namespace);
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
- await this.validationPromise;
7331
- return this.pipeline.getSuggestions(query, namespace);
7332
- }
7333
- };
7334
-
7335
- // src/core/Retrivora.ts
7336
- var Retrivora = class {
7337
- constructor(config) {
7338
- this.config = ConfigResolver.resolveUniversal(config);
7339
- this.pipeline = new Pipeline(this.config);
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 _a;
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: (_a = options == null ? void 0 : options.indexName) != null ? _a : "default",
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 _a, _b;
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: (_a = options == null ? void 0 : options.maxTokens) != null ? _a : 1024,
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 _a;
7441
- this._rag = __spreadValues(__spreadValues({}, (_a = this._rag) != null ? _a : {}), options);
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 _a;
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 = (_a = this._rag) != null ? _a : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
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 _a;
7566
- const extension = (_a = fileName.split(".").pop()) == null ? void 0 : _a.toLowerCase();
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 = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
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
- if (!(message == null ? void 0 : message.trim())) {
7677
- return import_server.NextResponse.json({ error: "message is required" }, { status: 400 });
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
- return import_server.NextResponse.json(result);
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 = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
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
- if (!(message == null ? void 0 : message.trim())) {
7701
- return new Response(JSON.stringify({ error: "message is required" }), {
7702
- status: 400,
7703
- headers: { "Content-Type": "application/json" }
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 _a;
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
- const uiTransformation = (_a = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a : UITransformer.transform(message, sources, plugin.getConfig());
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) enqueue(sseUIFrame(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 = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
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 = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
7811
- return async function GET() {
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 = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
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
  });