@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.mjs CHANGED
@@ -6,9 +6,6 @@ var __getOwnPropSymbols = Object.getOwnPropertySymbols;
6
6
  var __hasOwnProp = Object.prototype.hasOwnProperty;
7
7
  var __propIsEnum = Object.prototype.propertyIsEnumerable;
8
8
  var __knownSymbol = (name, symbol) => (symbol = Symbol[name]) ? symbol : /* @__PURE__ */ Symbol.for("Symbol." + name);
9
- var __typeError = (msg) => {
10
- throw TypeError(msg);
11
- };
12
9
  var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
13
10
  var __spreadValues = (a, b) => {
14
11
  for (var prop in b || (b = {}))
@@ -56,43 +53,15 @@ var __asyncGenerator = (__this, __arguments, generator) => {
56
53
  }, 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 = {};
57
54
  return generator = generator.apply(__this, __arguments), it[__knownSymbol("asyncIterator")] = () => it, method("next"), method("throw"), method("return"), it;
58
55
  };
59
- var __yieldStar = (value) => {
60
- var obj = value[__knownSymbol("asyncIterator")], isAwait = false, method, it = {};
61
- if (obj == null) {
62
- obj = value[__knownSymbol("iterator")]();
63
- method = (k) => it[k] = (x) => obj[k](x);
64
- } else {
65
- obj = obj.call(value);
66
- method = (k) => it[k] = (v) => {
67
- if (isAwait) {
68
- isAwait = false;
69
- if (k === "throw") throw v;
70
- return v;
71
- }
72
- isAwait = true;
73
- return {
74
- done: false,
75
- value: new __await(new Promise((resolve) => {
76
- var x = obj[k](v);
77
- if (!(x instanceof Object)) __typeError("Object expected");
78
- resolve(x);
79
- }), 1)
80
- };
81
- };
82
- }
83
- return it[__knownSymbol("iterator")] = () => it, method("next"), "throw" in obj ? method("throw") : it.throw = (x) => {
84
- throw x;
85
- }, "return" in obj && method("return"), it;
86
- };
87
56
  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);
88
57
 
89
58
  // src/utils/templateUtils.ts
90
59
  function isRecord(value) {
91
60
  return typeof value === "object" && value !== null;
92
61
  }
93
- function resolvePath(obj, path) {
94
- if (!path || !obj) return void 0;
95
- return path.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
62
+ function resolvePath(obj, path2) {
63
+ if (!path2 || !obj) return void 0;
64
+ return path2.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
96
65
  if (!isRecord(current) && !Array.isArray(current)) {
97
66
  return void 0;
98
67
  }
@@ -202,7 +171,7 @@ var init_PineconeProvider = __esm({
202
171
  static getHealthChecker() {
203
172
  return {
204
173
  async check(config) {
205
- var _a, _b;
174
+ var _a2, _b;
206
175
  const opts = config.options || {};
207
176
  const indexName = config.indexName;
208
177
  const timestamp = Date.now();
@@ -210,7 +179,7 @@ var init_PineconeProvider = __esm({
210
179
  const { Pinecone: Pinecone2 } = await import("@pinecone-database/pinecone");
211
180
  const client = new Pinecone2({ apiKey: opts.apiKey });
212
181
  const indexes = await client.listIndexes();
213
- const indexNames = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
182
+ const indexNames = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
214
183
  if (!indexNames.includes(indexName)) {
215
184
  return {
216
185
  healthy: false,
@@ -237,10 +206,10 @@ var init_PineconeProvider = __esm({
237
206
  };
238
207
  }
239
208
  async initialize() {
240
- var _a, _b;
209
+ var _a2, _b;
241
210
  this.client = new Pinecone({ apiKey: this.apiKey });
242
211
  const indexes = await this.client.listIndexes();
243
- const names = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
212
+ const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
244
213
  if (!names.includes(this.indexName)) {
245
214
  throw new Error(
246
215
  `[PineconeProvider] Index "${this.indexName}" not found. Available: ${names.join(", ")}`
@@ -252,12 +221,12 @@ var init_PineconeProvider = __esm({
252
221
  return namespace ? idx.namespace(namespace) : idx.namespace("");
253
222
  }
254
223
  async upsert(doc, namespace) {
255
- var _a;
224
+ var _a2;
256
225
  await this.index(namespace).upsert({
257
226
  records: [{
258
227
  id: String(doc.id),
259
228
  values: doc.vector,
260
- metadata: __spreadValues({ content: doc.content }, (_a = doc.metadata) != null ? _a : {})
229
+ metadata: __spreadValues({ content: doc.content }, (_a2 = doc.metadata) != null ? _a2 : {})
261
230
  }]
262
231
  });
263
232
  }
@@ -265,29 +234,29 @@ var init_PineconeProvider = __esm({
265
234
  const BATCH = 100;
266
235
  for (let i = 0; i < docs.length; i += BATCH) {
267
236
  const records = docs.slice(i, i + BATCH).map((d) => {
268
- var _a;
237
+ var _a2;
269
238
  return {
270
239
  id: String(d.id),
271
240
  values: d.vector,
272
- metadata: __spreadValues({ content: d.content }, (_a = d.metadata) != null ? _a : {})
241
+ metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
273
242
  };
274
243
  });
275
244
  await this.index(namespace).upsert({ records });
276
245
  }
277
246
  }
278
247
  async query(vector, topK, namespace, filter) {
279
- var _a;
248
+ var _a2;
280
249
  const pineconeFilter = this.sanitizeFilter(filter);
281
250
  const result = await this.index(namespace).query(__spreadValues({
282
251
  vector,
283
252
  topK,
284
253
  includeMetadata: true
285
254
  }, Object.keys(pineconeFilter).length > 0 ? { filter: pineconeFilter } : {}));
286
- return ((_a = result.matches) != null ? _a : []).map((m) => {
287
- var _a2, _b;
255
+ return ((_a2 = result.matches) != null ? _a2 : []).map((m) => {
256
+ var _a3, _b;
288
257
  return {
289
258
  id: m.id,
290
- score: (_a2 = m.score) != null ? _a2 : 0,
259
+ score: (_a3 = m.score) != null ? _a3 : 0,
291
260
  content: ((_b = m.metadata) == null ? void 0 : _b.content) || "",
292
261
  metadata: m.metadata
293
262
  };
@@ -326,13 +295,13 @@ var init_PostgreSQLProvider = __esm({
326
295
  init_BaseVectorProvider();
327
296
  PostgreSQLProvider = class extends BaseVectorProvider {
328
297
  constructor(config) {
329
- var _a;
298
+ var _a2;
330
299
  super(config);
331
300
  this.tableName = this.indexName.replace(/[^a-z0-9_]/gi, "_");
332
301
  const opts = config.options;
333
302
  if (!opts.connectionString) throw new Error("[PostgreSQLProvider] options.connectionString is required");
334
303
  this.connectionString = opts.connectionString;
335
- this.dimensions = (_a = opts.dimensions) != null ? _a : 1536;
304
+ this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 1536;
336
305
  }
337
306
  static getValidator() {
338
307
  return {
@@ -413,7 +382,7 @@ var init_PostgreSQLProvider = __esm({
413
382
  }
414
383
  }
415
384
  async upsert(doc, namespace = "") {
416
- var _a;
385
+ var _a2;
417
386
  const vectorLiteral = `[${doc.vector.join(",")}]`;
418
387
  await this.pool.query(
419
388
  `INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
@@ -423,7 +392,7 @@ var init_PostgreSQLProvider = __esm({
423
392
  content = EXCLUDED.content,
424
393
  metadata = EXCLUDED.metadata,
425
394
  embedding = EXCLUDED.embedding`,
426
- [doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), vectorLiteral]
395
+ [doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), vectorLiteral]
427
396
  );
428
397
  }
429
398
  async batchUpsert(docs, namespace = "") {
@@ -436,9 +405,9 @@ var init_PostgreSQLProvider = __esm({
436
405
  const batch = docs.slice(i, i + BATCH_SIZE);
437
406
  const values = [];
438
407
  const valuePlaceholders = batch.map((doc, idx) => {
439
- var _a;
408
+ var _a2;
440
409
  const offset = idx * 5;
441
- values.push(doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), `[${doc.vector.join(",")}]`);
410
+ values.push(doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), `[${doc.vector.join(",")}]`);
442
411
  return `($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}::vector)`;
443
412
  }).join(", ");
444
413
  const query = `
@@ -521,8 +490,8 @@ var init_PostgreSQLProvider = __esm({
521
490
 
522
491
  // src/utils/synonyms.ts
523
492
  function resolveMetadataValue(meta, uiKey) {
524
- var _a;
525
- const synonyms = (_a = FIELD_SYNONYMS[uiKey]) != null ? _a : [];
493
+ var _a2;
494
+ const synonyms = (_a2 = FIELD_SYNONYMS[uiKey]) != null ? _a2 : [];
526
495
  const keys = Object.keys(meta);
527
496
  const systemKeys = ["namespace", "filename", "filesize", "filetype", "docid", "uploadedat", "dimension", "chunkindex"];
528
497
  let match = keys.find((k) => k.toLowerCase() === uiKey.toLowerCase());
@@ -609,14 +578,14 @@ var init_MultiTablePostgresProvider = __esm({
609
578
  init_synonyms();
610
579
  MultiTablePostgresProvider = class extends BaseVectorProvider {
611
580
  constructor(config) {
612
- var _a, _b, _c;
581
+ var _a2, _b, _c;
613
582
  super(config);
614
583
  const opts = config.options || {};
615
584
  if (!opts.connectionString) {
616
585
  throw new Error("[MultiTablePostgresProvider] options.connectionString is required");
617
586
  }
618
587
  this.connectionString = opts.connectionString;
619
- this.dimensions = (_a = opts.dimensions) != null ? _a : 768;
588
+ this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 768;
620
589
  this.tables = [];
621
590
  const rawSearchFields = (_c = (_b = opts.searchFields) != null ? _b : process.env.VECTOR_DB_SEARCH_FIELDS) != null ? _c : ["name", "product_name", "productname", "title"];
622
591
  this.searchFields = typeof rawSearchFields === "string" ? rawSearchFields.split(",").map((f) => f.trim()).filter(Boolean) : rawSearchFields;
@@ -674,11 +643,11 @@ var init_MultiTablePostgresProvider = __esm({
674
643
  * Batch upsert documents by dynamically provisioning tables and columns based on CSV headers.
675
644
  */
676
645
  async batchUpsert(docs, namespace = "") {
677
- var _a;
646
+ var _a2;
678
647
  if (docs.length === 0) return;
679
648
  const docsByFile = {};
680
649
  for (const doc of docs) {
681
- const fileName = ((_a = doc.metadata) == null ? void 0 : _a.fileName) || this.uploadTable;
650
+ const fileName = ((_a2 = doc.metadata) == null ? void 0 : _a2.fileName) || this.uploadTable;
682
651
  if (!docsByFile[fileName]) docsByFile[fileName] = [];
683
652
  docsByFile[fileName].push(doc);
684
653
  }
@@ -731,11 +700,11 @@ var init_MultiTablePostgresProvider = __esm({
731
700
  const headerColumns = csvHeaders.map((h) => `"${h}"`).join(", ");
732
701
  const allColumns = `id, ${headerColumns ? headerColumns + ", " : ""}namespace, content, metadata, embedding`;
733
702
  const valuePlaceholders = batch.map((doc, idx) => {
734
- var _a2, _b;
703
+ var _a3, _b;
735
704
  const offset = idx * (5 + csvHeaders.length);
736
705
  values.push(doc.id);
737
706
  for (const h of csvHeaders) {
738
- values.push(String(((_a2 = doc.metadata) == null ? void 0 : _a2[h]) || ""));
707
+ values.push(String(((_a3 = doc.metadata) == null ? void 0 : _a3[h]) || ""));
739
708
  }
740
709
  values.push(namespace, doc.content, JSON.stringify((_b = doc.metadata) != null ? _b : {}), `[${doc.vector.join(",")}]`);
741
710
  const docPlaceholders = [];
@@ -774,7 +743,7 @@ var init_MultiTablePostgresProvider = __esm({
774
743
  * Query all configured tables and merge results, sorted by cosine similarity score.
775
744
  */
776
745
  async query(vector, topK, _namespace, _filter) {
777
- var _a;
746
+ var _a2;
778
747
  if (!this.pool) {
779
748
  throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
780
749
  }
@@ -805,11 +774,11 @@ var init_MultiTablePostgresProvider = __esm({
805
774
  const filterParams = [];
806
775
  if (metadataFilters && Object.keys(metadataFilters).length > 0) {
807
776
  const conditions = Object.entries(metadataFilters).map(([key, val]) => {
808
- var _a3;
777
+ var _a4;
809
778
  filterParams.push(String(val));
810
779
  const baseOffset = queryText && dynamicKeywordQuery ? 2 : 1;
811
780
  const paramIdx = baseOffset + filterParams.length;
812
- const synonyms = (_a3 = FIELD_SYNONYMS[key]) != null ? _a3 : [];
781
+ const synonyms = (_a4 = FIELD_SYNONYMS[key]) != null ? _a4 : [];
813
782
  const keysToCheck = [key, ...synonyms];
814
783
  const coalesceExprs = keysToCheck.flatMap((k) => [
815
784
  `metadata->>'${k}'`,
@@ -878,7 +847,7 @@ var init_MultiTablePostgresProvider = __esm({
878
847
  }
879
848
  const tableResults = [];
880
849
  for (const row of result.rows) {
881
- const _a2 = row, { hybrid_score, id } = _a2, rest = __objRest(_a2, ["hybrid_score", "id"]);
850
+ const _a3 = row, { hybrid_score, id } = _a3, rest = __objRest(_a3, ["hybrid_score", "id"]);
882
851
  delete rest.embedding;
883
852
  delete rest.vector_score;
884
853
  delete rest.keyword_score;
@@ -907,10 +876,10 @@ var init_MultiTablePostgresProvider = __esm({
907
876
  }
908
877
  allResults.sort((a, b) => b.score - a.score);
909
878
  if (allResults.length === 0) return [];
910
- const bestMatchTable = (_a = allResults[0].metadata) == null ? void 0 : _a.source_table;
879
+ const bestMatchTable = (_a2 = allResults[0].metadata) == null ? void 0 : _a2.source_table;
911
880
  const finalSorted = allResults.filter((res) => {
912
- var _a2;
913
- return ((_a2 = res.metadata) == null ? void 0 : _a2.source_table) === bestMatchTable;
881
+ var _a3;
882
+ return ((_a3 = res.metadata) == null ? void 0 : _a3.source_table) === bestMatchTable;
914
883
  });
915
884
  console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
916
885
  console.log(`[MultiTablePostgresProvider] Final top match from "${bestMatchTable}" with score ${finalSorted[0].score.toFixed(4)}`);
@@ -1315,14 +1284,14 @@ var init_QdrantProvider = __esm({
1315
1284
  * Samples points from the collection to discover available payload fields.
1316
1285
  */
1317
1286
  async discoverSchema() {
1318
- var _a;
1287
+ var _a2;
1319
1288
  try {
1320
1289
  const { data } = await this.http.post(`/collections/${this.indexName}/points/scroll`, {
1321
1290
  limit: 20,
1322
1291
  with_payload: true,
1323
1292
  with_vector: false
1324
1293
  });
1325
- const points = ((_a = data.result) == null ? void 0 : _a.points) || [];
1294
+ const points = ((_a2 = data.result) == null ? void 0 : _a2.points) || [];
1326
1295
  const keys = /* @__PURE__ */ new Set();
1327
1296
  for (const point of points) {
1328
1297
  const payload = point.payload || {};
@@ -1348,12 +1317,12 @@ var init_QdrantProvider = __esm({
1348
1317
  * Ensures the collection exists. Creates it if missing.
1349
1318
  */
1350
1319
  async ensureCollection() {
1351
- var _a;
1320
+ var _a2;
1352
1321
  try {
1353
1322
  await this.http.get(`/collections/${this.indexName}`);
1354
1323
  console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
1355
1324
  } catch (err) {
1356
- if (axios4.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
1325
+ if (axios4.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
1357
1326
  const opts = this.config.options;
1358
1327
  const dimensionsForCreate = opts.dimensions || 1536;
1359
1328
  console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
@@ -1373,7 +1342,7 @@ var init_QdrantProvider = __esm({
1373
1342
  * Ensures that a payload field has an index.
1374
1343
  */
1375
1344
  async ensureIndex(fieldName, schema = "keyword") {
1376
- var _a;
1345
+ var _a2;
1377
1346
  let fullPath = fieldName;
1378
1347
  if (!this.isFlatPayload && !fieldName.includes(".") && fieldName !== "namespace" && fieldName !== this.contentField) {
1379
1348
  fullPath = `${this.metadataField}.${fieldName}`;
@@ -1386,7 +1355,7 @@ var init_QdrantProvider = __esm({
1386
1355
  console.log(`[QdrantProvider] \u2705 Ensured ${schema} index for "${fullPath}"`);
1387
1356
  } catch (err) {
1388
1357
  let status;
1389
- if (axios4.isAxiosError(err)) status = (_a = err.response) == null ? void 0 : _a.status;
1358
+ if (axios4.isAxiosError(err)) status = (_a2 = err.response) == null ? void 0 : _a2.status;
1390
1359
  if (status === 409) return;
1391
1360
  console.warn(`[QdrantProvider] \u26A0\uFE0F Could not ensure index for "${fullPath}":`, err instanceof Error ? err.message : String(err));
1392
1361
  }
@@ -1415,7 +1384,7 @@ var init_QdrantProvider = __esm({
1415
1384
  await this.http.put(`/collections/${this.indexName}/points`, payload);
1416
1385
  }
1417
1386
  async query(vector, topK, namespace, _filter) {
1418
- var _a;
1387
+ var _a2;
1419
1388
  const must = [];
1420
1389
  if (namespace) {
1421
1390
  must.push({ key: "namespace", match: { value: namespace } });
@@ -1437,7 +1406,7 @@ var init_QdrantProvider = __esm({
1437
1406
  limit: topK,
1438
1407
  with_payload: true,
1439
1408
  params: {
1440
- hnsw_ef: ((_a = this.config.options) == null ? void 0 : _a.efSearch) || Math.max(topK * 20, 128),
1409
+ hnsw_ef: ((_a2 = this.config.options) == null ? void 0 : _a2.efSearch) || Math.max(topK * 20, 128),
1441
1410
  exact: false
1442
1411
  },
1443
1412
  filter: must.length > 0 ? { must } : void 0
@@ -1532,13 +1501,13 @@ var init_ChromaDBProvider = __esm({
1532
1501
  * Get or create the ChromaDB collection.
1533
1502
  */
1534
1503
  async initialize() {
1535
- var _a;
1504
+ var _a2;
1536
1505
  try {
1537
1506
  const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
1538
1507
  this.collectionId = data.id;
1539
1508
  console.log(`[ChromaDBProvider] \u2705 Collection "${this.indexName}" found (id: ${this.collectionId})`);
1540
1509
  } catch (err) {
1541
- if (axios5.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
1510
+ if (axios5.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
1542
1511
  console.log(`[ChromaDBProvider] \u23F3 Collection "${this.indexName}" not found. Creating...`);
1543
1512
  const { data } = await this.http.post("/api/v1/collections", {
1544
1513
  name: this.indexName
@@ -1759,7 +1728,7 @@ var init_WeaviateProvider = __esm({
1759
1728
  await this.http.post("/v1/batch/objects", payload);
1760
1729
  }
1761
1730
  async query(vector, topK, namespace, _filter) {
1762
- var _a, _b;
1731
+ var _a2, _b;
1763
1732
  const queryText = _filter == null ? void 0 : _filter.queryText;
1764
1733
  const sanitizedFilter = this.sanitizeFilter(_filter);
1765
1734
  const searchParams = queryText ? `hybrid: { query: ${JSON.stringify(queryText)}, alpha: 0.5 }` : `nearVector: { vector: ${JSON.stringify(vector)} }`;
@@ -1785,7 +1754,7 @@ var init_WeaviateProvider = __esm({
1785
1754
  `
1786
1755
  };
1787
1756
  const { data } = await this.http.post("/v1/graphql", graphqlQuery);
1788
- const results = ((_b = (_a = data.data) == null ? void 0 : _a.Get) == null ? void 0 : _b[this.indexName]) || [];
1757
+ const results = ((_b = (_a2 = data.data) == null ? void 0 : _a2.Get) == null ? void 0 : _b[this.indexName]) || [];
1789
1758
  return results.map((res) => ({
1790
1759
  id: res["_additional"].id,
1791
1760
  score: 1 - res["_additional"].distance,
@@ -1838,10 +1807,10 @@ var init_WeaviateProvider = __esm({
1838
1807
  return `{ operator: And, operands: [${operands.join(", ")}] }`;
1839
1808
  }
1840
1809
  weaviateOperand(key, value) {
1841
- const path = `path: [${JSON.stringify(key)}], operator: Equal`;
1842
- if (typeof value === "number") return `{ ${path}, valueNumber: ${value} }`;
1843
- if (typeof value === "boolean") return `{ ${path}, valueBoolean: ${value} }`;
1844
- return `{ ${path}, valueString: ${JSON.stringify(value)} }`;
1810
+ const path2 = `path: [${JSON.stringify(key)}], operator: Equal`;
1811
+ if (typeof value === "number") return `{ ${path2}, valueNumber: ${value} }`;
1812
+ if (typeof value === "boolean") return `{ ${path2}, valueBoolean: ${value} }`;
1813
+ return `{ ${path2}, valueString: ${JSON.stringify(value)} }`;
1845
1814
  }
1846
1815
  };
1847
1816
  }
@@ -1868,21 +1837,21 @@ var init_UniversalVectorProvider = __esm({
1868
1837
  }
1869
1838
  }
1870
1839
  async initialize() {
1871
- var _a;
1840
+ var _a2;
1872
1841
  this.http = axios8.create({
1873
1842
  baseURL: this.opts.baseUrl,
1874
1843
  headers: __spreadValues({
1875
1844
  "Content-Type": "application/json"
1876
1845
  }, this.opts.headers),
1877
- timeout: (_a = this.opts.timeout) != null ? _a : 3e4
1846
+ timeout: (_a2 = this.opts.timeout) != null ? _a2 : 3e4
1878
1847
  });
1879
1848
  if (!await this.ping()) {
1880
1849
  throw new Error(`[UniversalVectorProvider] Failed to connect to ${this.opts.baseUrl}`);
1881
1850
  }
1882
1851
  }
1883
1852
  async upsert(doc, namespace) {
1884
- var _a, _b, _c;
1885
- const endpoint = (_a = this.opts.upsertEndpoint) != null ? _a : "/upsert";
1853
+ var _a2, _b, _c;
1854
+ const endpoint = (_a2 = this.opts.upsertEndpoint) != null ? _a2 : "/upsert";
1886
1855
  const template = (_b = this.opts.upsertTemplate) != null ? _b : JSON.stringify({
1887
1856
  id: "{{id}}",
1888
1857
  vector: "{{vector}}",
@@ -1915,8 +1884,8 @@ var init_UniversalVectorProvider = __esm({
1915
1884
  }
1916
1885
  }
1917
1886
  async query(vector, topK, namespace, filter) {
1918
- var _a, _b;
1919
- const endpoint = (_a = this.opts.queryEndpoint) != null ? _a : "/query";
1887
+ var _a2, _b;
1888
+ const endpoint = (_a2 = this.opts.queryEndpoint) != null ? _a2 : "/query";
1920
1889
  const template = (_b = this.opts.queryTemplate) != null ? _b : JSON.stringify({
1921
1890
  vector: "{{vector}}",
1922
1891
  limit: "{{topK}}",
@@ -1942,12 +1911,12 @@ var init_UniversalVectorProvider = __esm({
1942
1911
  );
1943
1912
  }
1944
1913
  return results.map((item) => {
1945
- var _a2, _b2, _c, _d, _e, _f, _g;
1914
+ var _a3, _b2, _c, _d, _e, _f, _g2;
1946
1915
  return {
1947
- id: item[(_a2 = this.opts.queryIdField) != null ? _a2 : "id"],
1916
+ id: item[(_a3 = this.opts.queryIdField) != null ? _a3 : "id"],
1948
1917
  score: (_c = item[(_b2 = this.opts.queryScoreField) != null ? _b2 : "score"]) != null ? _c : 0,
1949
1918
  content: (_e = item[(_d = this.opts.queryContentField) != null ? _d : "content"]) != null ? _e : "",
1950
- metadata: (_g = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g : {}
1919
+ metadata: (_g2 = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g2 : {}
1951
1920
  };
1952
1921
  });
1953
1922
  } catch (error) {
@@ -1957,8 +1926,8 @@ var init_UniversalVectorProvider = __esm({
1957
1926
  }
1958
1927
  }
1959
1928
  async delete(id, namespace) {
1960
- var _a, _b;
1961
- const endpoint = (_a = this.opts.deleteEndpoint) != null ? _a : "/delete";
1929
+ var _a2, _b;
1930
+ const endpoint = (_a2 = this.opts.deleteEndpoint) != null ? _a2 : "/delete";
1962
1931
  const template = (_b = this.opts.deleteTemplate) != null ? _b : JSON.stringify({
1963
1932
  id: "{{id}}",
1964
1933
  namespace: "{{namespace}}"
@@ -1976,8 +1945,8 @@ var init_UniversalVectorProvider = __esm({
1976
1945
  }
1977
1946
  }
1978
1947
  async deleteNamespace(namespace) {
1979
- var _a;
1980
- const endpoint = (_a = this.opts.deleteNamespaceEndpoint) != null ? _a : "/delete-namespace";
1948
+ var _a2;
1949
+ const endpoint = (_a2 = this.opts.deleteNamespaceEndpoint) != null ? _a2 : "/delete-namespace";
1981
1950
  try {
1982
1951
  await this.http.post(endpoint, { namespace });
1983
1952
  } catch (error) {
@@ -1987,9 +1956,9 @@ var init_UniversalVectorProvider = __esm({
1987
1956
  }
1988
1957
  }
1989
1958
  async ping() {
1990
- var _a;
1959
+ var _a2;
1991
1960
  try {
1992
- const endpoint = (_a = this.opts.pingEndpoint) != null ? _a : "/health";
1961
+ const endpoint = (_a2 = this.opts.pingEndpoint) != null ? _a2 : "/health";
1993
1962
  const response = await this.http.get(endpoint, { timeout: 5e3 });
1994
1963
  return response.status >= 200 && response.status < 300;
1995
1964
  } catch (e) {
@@ -2100,6 +2069,8 @@ var LLM_PROVIDERS = [
2100
2069
  "anthropic",
2101
2070
  "ollama",
2102
2071
  "gemini",
2072
+ "groq",
2073
+ "qwen",
2103
2074
  "rest",
2104
2075
  "universal_rest",
2105
2076
  "custom"
@@ -2108,6 +2079,7 @@ var EMBEDDING_PROVIDERS = [
2108
2079
  "openai",
2109
2080
  "ollama",
2110
2081
  "gemini",
2082
+ "qwen",
2111
2083
  "rest",
2112
2084
  "universal_rest",
2113
2085
  "custom"
@@ -2116,6 +2088,7 @@ var PROVIDERS_WITH_EMBEDDINGS = [
2116
2088
  "openai",
2117
2089
  "ollama",
2118
2090
  "gemini",
2091
+ "qwen",
2119
2092
  "rest",
2120
2093
  "universal_rest"
2121
2094
  ];
@@ -2123,8 +2096,8 @@ var UI_BORDER_RADIUS_OPTIONS = ["none", "sm", "md", "lg", "xl", "full"];
2123
2096
 
2124
2097
  // src/config/serverConfig.ts
2125
2098
  function readString(env, name) {
2126
- var _a;
2127
- const value = (_a = env[name]) == null ? void 0 : _a.trim();
2099
+ var _a2;
2100
+ const value = (_a2 = env[name]) == null ? void 0 : _a2.trim();
2128
2101
  return value ? value : void 0;
2129
2102
  }
2130
2103
  function readNumber(env, name, fallback) {
@@ -2137,8 +2110,8 @@ function readNumber(env, name, fallback) {
2137
2110
  return parsed;
2138
2111
  }
2139
2112
  function readEnum(env, name, fallback, allowed) {
2140
- var _a;
2141
- const value = (_a = readString(env, name)) != null ? _a : fallback;
2113
+ var _a2;
2114
+ const value = (_a2 = readString(env, name)) != null ? _a2 : fallback;
2142
2115
  if (allowed.includes(value)) {
2143
2116
  return value;
2144
2117
  }
@@ -2148,15 +2121,15 @@ function getRagConfig(baseConfig, env = process.env) {
2148
2121
  return getEnvConfig(env, baseConfig);
2149
2122
  }
2150
2123
  function getEnvConfig(env = process.env, base) {
2151
- 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;
2152
- 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__";
2124
+ 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;
2125
+ 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__";
2153
2126
  const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
2154
2127
  const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
2155
2128
  const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
2156
2129
  const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
2157
2130
  const vectorDbOptions = {};
2158
2131
  if (vectorProvider === "pinecone") {
2159
- 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 : "";
2132
+ 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 : "";
2160
2133
  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;
2161
2134
  } else if (vectorProvider === "pgvector" || vectorProvider === "postgresql") {
2162
2135
  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 : "";
@@ -2218,17 +2191,18 @@ function getEnvConfig(env = process.env, base) {
2218
2191
  rest: "default",
2219
2192
  custom: "default"
2220
2193
  };
2221
- return __spreadValues({
2194
+ return __spreadProps(__spreadValues({
2222
2195
  projectId,
2196
+ licenseKey: (_ha = (_ga = readString(env, "RETRIVORA_LICENSE_KEY")) != null ? _ga : readString(env, "LICENSE_KEY")) != null ? _ha : base == null ? void 0 : base.licenseKey,
2223
2197
  vectorDb: {
2224
2198
  provider: vectorProvider,
2225
- indexName: (_ha = (_ga = readString(env, "VECTOR_DB_INDEX")) != null ? _ga : vectorDbOptions.indexName) != null ? _ha : "rag-index",
2199
+ indexName: (_ja = (_ia = readString(env, "VECTOR_DB_INDEX")) != null ? _ia : vectorDbOptions.indexName) != null ? _ja : "rag-index",
2226
2200
  options: vectorDbOptions
2227
2201
  },
2228
2202
  llm: {
2229
2203
  provider: llmProvider,
2230
- model: (_ja = (_ia = readString(env, "LLM_MODEL")) != null ? _ia : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _ja : "gpt-4o",
2231
- apiKey: (_ka = llmApiKeyByProvider[llmProvider]) != null ? _ka : "",
2204
+ model: (_la = (_ka = readString(env, "LLM_MODEL")) != null ? _ka : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _la : "gpt-4o",
2205
+ apiKey: (_ma = llmApiKeyByProvider[llmProvider]) != null ? _ma : "",
2232
2206
  baseUrl: readString(env, "LLM_BASE_URL"),
2233
2207
  systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
2234
2208
  maxTokens: readNumber(env, "LLM_MAX_TOKENS", 4096),
@@ -2241,7 +2215,7 @@ function getEnvConfig(env = process.env, base) {
2241
2215
  },
2242
2216
  embedding: {
2243
2217
  provider: embeddingProvider,
2244
- model: (_la = readString(env, "EMBEDDING_MODEL")) != null ? _la : "text-embedding-3-small",
2218
+ model: (_na = readString(env, "EMBEDDING_MODEL")) != null ? _na : "text-embedding-3-small",
2245
2219
  apiKey: embeddingApiKeyByProvider[embeddingProvider],
2246
2220
  baseUrl: readString(env, "EMBEDDING_BASE_URL"),
2247
2221
  dimensions: embeddingDimensions,
@@ -2252,30 +2226,30 @@ function getEnvConfig(env = process.env, base) {
2252
2226
  }
2253
2227
  },
2254
2228
  ui: {
2255
- title: (_na = (_ma = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _ma : readString(env, "UI_TITLE")) != null ? _na : "AI Assistant",
2256
- subtitle: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _oa : readString(env, "UI_SUBTITLE")) != null ? _pa : "Powered by RAG",
2257
- primaryColor: (_ra = (_qa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _qa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ra : "#10b981",
2258
- accentColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _sa : readString(env, "UI_ACCENT_COLOR")) != null ? _ta : "#3b82f6",
2259
- logoUrl: (_ua = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _ua : readString(env, "UI_LOGO_URL"),
2260
- placeholder: (_wa = (_va = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _va : readString(env, "UI_PLACEHOLDER")) != null ? _wa : "Ask me anything\u2026",
2261
- showSources: ((_ya = (_xa = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _xa : readString(env, "UI_SHOW_SOURCES")) != null ? _ya : "true") !== "false",
2262
- 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.",
2263
- visualStyle: (_Ca = (_Ba = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Ba : readString(env, "UI_VISUAL_STYLE")) != null ? _Ca : "glass",
2264
- borderRadius: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Da : readString(env, "UI_BORDER_RADIUS")) != null ? _Ea : "xl",
2265
- allowUpload: ((_Ga = (_Fa = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Fa : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ga : "false") === "true"
2229
+ title: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _oa : readString(env, "UI_TITLE")) != null ? _pa : "AI Assistant",
2230
+ subtitle: (_ra = (_qa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _qa : readString(env, "UI_SUBTITLE")) != null ? _ra : "Powered by RAG",
2231
+ primaryColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _sa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ta : "#10b981",
2232
+ accentColor: (_va = (_ua = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _ua : readString(env, "UI_ACCENT_COLOR")) != null ? _va : "#3b82f6",
2233
+ logoUrl: (_wa = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _wa : readString(env, "UI_LOGO_URL"),
2234
+ placeholder: (_ya = (_xa = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _xa : readString(env, "UI_PLACEHOLDER")) != null ? _ya : "Ask me anything\u2026",
2235
+ showSources: ((_Aa = (_za = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _za : readString(env, "UI_SHOW_SOURCES")) != null ? _Aa : "true") !== "false",
2236
+ 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.",
2237
+ visualStyle: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Da : readString(env, "UI_VISUAL_STYLE")) != null ? _Ea : "glass",
2238
+ borderRadius: (_Ga = (_Fa = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Fa : readString(env, "UI_BORDER_RADIUS")) != null ? _Ga : "xl",
2239
+ allowUpload: ((_Ia = (_Ha = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Ha : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ia : "false") === "true"
2266
2240
  },
2267
2241
  rag: {
2268
2242
  topK: readNumber(env, "RAG_TOP_K", 5),
2269
2243
  scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
2270
2244
  chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
2271
2245
  chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200),
2272
- filterableFields: (_Ha = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ha.split(",").map((f) => f.trim()),
2246
+ filterableFields: (_Ja = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ja.split(",").map((f) => f.trim()),
2273
2247
  // Query pipeline toggles — read from .env.local
2274
2248
  useQueryTransformation: readString(env, "RAG_USE_QUERY_TRANSFORMATION") === "true",
2275
2249
  useReranking: readString(env, "RAG_USE_RERANKING") === "true",
2276
2250
  useGraphRetrieval: readString(env, "RAG_USE_GRAPH_RETRIEVAL") === "true",
2277
- architecture: (_Ia = readString(env, "RAG_ARCHITECTURE")) != null ? _Ia : "simple",
2278
- chunkingStrategy: (_Ja = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _Ja : "recursive",
2251
+ architecture: (_Ka = readString(env, "RAG_ARCHITECTURE")) != null ? _Ka : "simple",
2252
+ chunkingStrategy: (_La = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _La : "recursive",
2279
2253
  uiMapping: (() => {
2280
2254
  const raw = readString(env, "RAG_UI_MAPPING");
2281
2255
  if (!raw) return void 0;
@@ -2285,6 +2259,10 @@ function getEnvConfig(env = process.env, base) {
2285
2259
  return void 0;
2286
2260
  }
2287
2261
  })()
2262
+ },
2263
+ telemetry: {
2264
+ 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,
2265
+ 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"
2288
2266
  }
2289
2267
  }, readString(env, "GRAPH_DB_PROVIDER") ? {
2290
2268
  graphDb: {
@@ -2295,49 +2273,21 @@ function getEnvConfig(env = process.env, base) {
2295
2273
  password: readString(env, "GRAPH_DB_PASSWORD")
2296
2274
  }
2297
2275
  }
2298
- } : {});
2276
+ } : {}), {
2277
+ mcpServers: (() => {
2278
+ var _a3;
2279
+ const raw = (_a3 = readString(env, "MCP_SERVERS")) != null ? _a3 : readString(env, "NEXT_PUBLIC_MCP_SERVERS");
2280
+ if (!raw) return void 0;
2281
+ try {
2282
+ return JSON.parse(raw);
2283
+ } catch (e) {
2284
+ console.warn("[serverConfig] Failed to parse MCP_SERVERS env:", e);
2285
+ return void 0;
2286
+ }
2287
+ })()
2288
+ });
2299
2289
  }
2300
2290
 
2301
- // src/exceptions/index.ts
2302
- var RetrivoraError = class extends Error {
2303
- constructor(message, code, details) {
2304
- super(message);
2305
- this.name = new.target.name;
2306
- this.code = code;
2307
- this.details = details;
2308
- }
2309
- };
2310
- var ProviderNotFoundException = class extends RetrivoraError {
2311
- constructor(providerType, provider, details) {
2312
- super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
2313
- }
2314
- };
2315
- var EmbeddingFailedException = class extends RetrivoraError {
2316
- constructor(message = "Embedding generation failed", details) {
2317
- super(message, "EMBEDDING_FAILED", details);
2318
- }
2319
- };
2320
- var RetrievalException = class extends RetrivoraError {
2321
- constructor(message = "Retrieval failed", details) {
2322
- super(message, "RETRIEVAL_FAILED", details);
2323
- }
2324
- };
2325
- var RateLimitException = class extends RetrivoraError {
2326
- constructor(message = "Provider rate limit exceeded", details) {
2327
- super(message, "RATE_LIMITED", details);
2328
- }
2329
- };
2330
- var ConfigurationException = class extends RetrivoraError {
2331
- constructor(message, details) {
2332
- super(message, "CONFIGURATION_ERROR", details);
2333
- }
2334
- };
2335
- var AuthenticationException = class extends RetrivoraError {
2336
- constructor(message = "Provider authentication failed", details) {
2337
- super(message, "AUTHENTICATION_ERROR", details);
2338
- }
2339
- };
2340
-
2341
2291
  // src/core/ConfigResolver.ts
2342
2292
  var ConfigResolver = class {
2343
2293
  /**
@@ -2361,7 +2311,8 @@ var ConfigResolver = class {
2361
2311
  options: __spreadValues(__spreadValues({}, envConfig.embedding.options || {}), hostConfig.embedding.options || {})
2362
2312
  }) : envConfig.embedding,
2363
2313
  ui: hostConfig.ui ? mergeDefined(envConfig.ui, hostConfig.ui) : envConfig.ui,
2364
- rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag
2314
+ rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag,
2315
+ telemetry: hostConfig.telemetry ? __spreadValues(__spreadValues({}, envConfig.telemetry), hostConfig.telemetry) : envConfig.telemetry
2365
2316
  });
2366
2317
  }
2367
2318
  /**
@@ -2370,10 +2321,10 @@ var ConfigResolver = class {
2370
2321
  * fallback behavior.
2371
2322
  */
2372
2323
  static resolveUniversal(hostConfig, env = process.env) {
2373
- var _a;
2324
+ var _a2;
2374
2325
  if (!hostConfig) return this.resolve(void 0, env);
2375
2326
  const normalized = __spreadProps(__spreadValues({}, hostConfig), {
2376
- vectorDb: (_a = hostConfig.vectorDb) != null ? _a : hostConfig.vectorDatabase,
2327
+ vectorDb: (_a2 = hostConfig.vectorDb) != null ? _a2 : hostConfig.vectorDatabase,
2377
2328
  rag: this.mergeRetrievalWorkflow(hostConfig.rag, hostConfig.retrieval, hostConfig.workflow)
2378
2329
  });
2379
2330
  return this.resolve(normalized, env);
@@ -2383,21 +2334,21 @@ var ConfigResolver = class {
2383
2334
  */
2384
2335
  static validate(config) {
2385
2336
  if (!config.projectId) {
2386
- throw new ConfigurationException("[ConfigResolver] projectId is required");
2337
+ throw new Error("[ConfigResolver] projectId is required");
2387
2338
  }
2388
2339
  if (!config.vectorDb.provider) {
2389
- throw new ConfigurationException("[ConfigResolver] vectorDb.provider is required");
2340
+ throw new Error("[ConfigResolver] vectorDb.provider is required");
2390
2341
  }
2391
2342
  if (!config.llm.provider) {
2392
- throw new ConfigurationException("[ConfigResolver] llm.provider is required");
2343
+ throw new Error("[ConfigResolver] llm.provider is required");
2393
2344
  }
2394
2345
  }
2395
2346
  static mergeRetrievalWorkflow(rag, retrieval, workflow) {
2396
- var _a, _b, _c, _d, _e;
2347
+ var _a2, _b, _c, _d, _e;
2397
2348
  if (!rag && !retrieval && !workflow) return void 0;
2398
2349
  const normalized = __spreadValues({}, rag != null ? rag : {});
2399
2350
  if (retrieval) {
2400
- normalized.topK = (_a = retrieval.topK) != null ? _a : normalized.topK;
2351
+ normalized.topK = (_a2 = retrieval.topK) != null ? _a2 : normalized.topK;
2401
2352
  normalized.scoreThreshold = (_b = retrieval.scoreThreshold) != null ? _b : normalized.scoreThreshold;
2402
2353
  normalized.useReranking = (_c = retrieval.useReranking) != null ? _c : normalized.useReranking;
2403
2354
  if (retrieval.strategy === "hybrid") normalized.architecture = (_d = normalized.architecture) != null ? _d : "hybrid";
@@ -2479,8 +2430,8 @@ var OpenAIProvider = class {
2479
2430
  const apiKey = config.apiKey;
2480
2431
  const modelName = config.model;
2481
2432
  try {
2482
- const OpenAI2 = await import("openai");
2483
- const client = new OpenAI2.default({ apiKey });
2433
+ const OpenAI4 = await import("openai");
2434
+ const client = new OpenAI4.default({ apiKey });
2484
2435
  const models = await client.models.list();
2485
2436
  const hasModel = models.data.some((m) => m.id === modelName);
2486
2437
  return {
@@ -2501,8 +2452,8 @@ var OpenAIProvider = class {
2501
2452
  };
2502
2453
  }
2503
2454
  async chat(messages, context, options) {
2504
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2505
- 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.";
2455
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
2456
+ 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.";
2506
2457
  const systemMessage = {
2507
2458
  role: "system",
2508
2459
  content: buildSystemContent(basePrompt, context)
@@ -2521,12 +2472,12 @@ var OpenAIProvider = class {
2521
2472
  temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
2522
2473
  stop: options == null ? void 0 : options.stop
2523
2474
  });
2524
- return (_i = (_h = (_g = completion.choices[0]) == null ? void 0 : _g.message) == null ? void 0 : _h.content) != null ? _i : "";
2475
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
2525
2476
  }
2526
2477
  chatStream(messages, context, options) {
2527
2478
  return __asyncGenerator(this, null, function* () {
2528
- var _a, _b, _c, _d, _e, _f, _g, _h;
2529
- 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.";
2479
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
2480
+ 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.";
2530
2481
  const systemMessage = {
2531
2482
  role: "system",
2532
2483
  content: buildSystemContent(basePrompt, context)
@@ -2552,7 +2503,7 @@ var OpenAIProvider = class {
2552
2503
  try {
2553
2504
  for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2554
2505
  const chunk = temp.value;
2555
- const content = ((_h = (_g = chunk.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content) || "";
2506
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
2556
2507
  if (content) yield content;
2557
2508
  }
2558
2509
  } catch (temp) {
@@ -2572,8 +2523,8 @@ var OpenAIProvider = class {
2572
2523
  return results[0];
2573
2524
  }
2574
2525
  async batchEmbed(texts, options) {
2575
- var _a, _b, _c, _d, _e;
2576
- 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";
2526
+ var _a2, _b, _c, _d, _e;
2527
+ 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";
2577
2528
  const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
2578
2529
  const client = apiKey !== this.llmConfig.apiKey ? new OpenAI({ apiKey }) : this.client;
2579
2530
  const response = await client.embeddings.create({ model, input: texts });
@@ -2650,8 +2601,8 @@ var AnthropicProvider = class {
2650
2601
  };
2651
2602
  }
2652
2603
  async chat(messages, context, options) {
2653
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2654
- 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.";
2604
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2605
+ 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.";
2655
2606
  const system = buildSystemContent(basePrompt, context);
2656
2607
  const anthropicMessages = messages.map((m) => ({
2657
2608
  role: m.role === "assistant" ? "assistant" : "user",
@@ -2662,7 +2613,7 @@ var AnthropicProvider = class {
2662
2613
  const extraParams = {};
2663
2614
  if (isThinkingEnabled && isClaude37) {
2664
2615
  extraParams.betas = ["interleaved-thinking-2025-05-14"];
2665
- const maxTokens = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
2616
+ const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
2666
2617
  const budget = Math.min(
2667
2618
  typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
2668
2619
  maxTokens - 1
@@ -2689,8 +2640,8 @@ var AnthropicProvider = class {
2689
2640
  }
2690
2641
  chatStream(messages, context, options) {
2691
2642
  return __asyncGenerator(this, null, function* () {
2692
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2693
- 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.";
2643
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2644
+ 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.";
2694
2645
  const system = buildSystemContent(basePrompt, context);
2695
2646
  const anthropicMessages = messages.map((m) => ({
2696
2647
  role: m.role === "assistant" ? "assistant" : "user",
@@ -2701,7 +2652,7 @@ var AnthropicProvider = class {
2701
2652
  const extraParams = {};
2702
2653
  if (isThinkingEnabled && isClaude37) {
2703
2654
  extraParams.betas = ["interleaved-thinking-2025-05-14"];
2704
- const maxTokens = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
2655
+ const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
2705
2656
  const budget = Math.min(
2706
2657
  typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
2707
2658
  maxTokens - 1
@@ -2774,8 +2725,8 @@ var AnthropicProvider = class {
2774
2725
  import axios from "axios";
2775
2726
  var OllamaProvider = class {
2776
2727
  constructor(llmConfig, embeddingConfig) {
2777
- var _a, _b;
2778
- const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
2728
+ var _a2, _b;
2729
+ const baseURL = (_a2 = llmConfig.baseUrl) != null ? _a2 : "http://localhost:11434";
2779
2730
  const timeout = Number((_b = llmConfig.options) == null ? void 0 : _b.timeout) || 3e5;
2780
2731
  this.http = axios.create({ baseURL, timeout });
2781
2732
  this.llmConfig = llmConfig;
@@ -2833,8 +2784,8 @@ var OllamaProvider = class {
2833
2784
  };
2834
2785
  }
2835
2786
  async chat(messages, context, options) {
2836
- var _a, _b, _c, _d, _e, _f;
2837
- 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.";
2787
+ var _a2, _b, _c, _d, _e, _f;
2788
+ 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.";
2838
2789
  const system = buildSystemContent(basePrompt, context);
2839
2790
  const { data } = await this.http.post("/api/chat", {
2840
2791
  model: this.llmConfig.model,
@@ -2852,8 +2803,8 @@ var OllamaProvider = class {
2852
2803
  }
2853
2804
  chatStream(messages, context, options) {
2854
2805
  return __asyncGenerator(this, null, function* () {
2855
- var _a, _b, _c, _d, _e, _f, _g, _h;
2856
- 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.";
2806
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
2807
+ 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.";
2857
2808
  const system = buildSystemContent(basePrompt, context);
2858
2809
  const response = yield new __await(this.http.post("/api/chat", {
2859
2810
  model: this.llmConfig.model,
@@ -2882,7 +2833,7 @@ var OllamaProvider = class {
2882
2833
  if (!line.trim()) continue;
2883
2834
  try {
2884
2835
  const json = JSON.parse(line);
2885
- if ((_g = json.message) == null ? void 0 : _g.content) {
2836
+ if ((_g2 = json.message) == null ? void 0 : _g2.content) {
2886
2837
  yield json.message.content;
2887
2838
  }
2888
2839
  if (json.done) return;
@@ -2911,10 +2862,10 @@ var OllamaProvider = class {
2911
2862
  });
2912
2863
  }
2913
2864
  async embed(text, options) {
2914
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2915
- 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";
2865
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2866
+ 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";
2916
2867
  const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
2917
- const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? axios.create({ baseURL, timeout: 6e4 }) : this.http;
2868
+ const client = baseURL !== ((_g2 = this.llmConfig.baseUrl) != null ? _g2 : "http://localhost:11434") ? axios.create({ baseURL, timeout: 6e4 }) : this.http;
2918
2869
  let prompt = text;
2919
2870
  const queryPrefix = (_i = (_h = this.embeddingConfig) == null ? void 0 : _h.queryPrefix) != null ? _i : model.includes("nomic") ? "search_query: " : "";
2920
2871
  const docPrefix = (_k = (_j = this.embeddingConfig) == null ? void 0 : _j.documentPrefix) != null ? _k : model.includes("nomic") ? "search_document: " : "";
@@ -3013,9 +2964,9 @@ var GeminiProvider = class {
3013
2964
  static getHealthChecker() {
3014
2965
  return {
3015
2966
  async check(config) {
3016
- var _a, _b;
2967
+ var _a2, _b;
3017
2968
  const timestamp = Date.now();
3018
- const apiKey = (_b = (_a = config.apiKey) != null ? _a : process.env.GOOGLE_GENAI_API_KEY) != null ? _b : "";
2969
+ const apiKey = (_b = (_a2 = config.apiKey) != null ? _a2 : process.env.GOOGLE_GENAI_API_KEY) != null ? _b : "";
3019
2970
  const modelName = sanitizeModel(config.model);
3020
2971
  try {
3021
2972
  const { GoogleGenerativeAI: GoogleGenerativeAI2 } = await import("@google/generative-ai");
@@ -3045,16 +2996,16 @@ var GeminiProvider = class {
3045
2996
  /** Resolve the embedding client — uses a separate client when the embedding
3046
2997
  * API key differs from the LLM API key. */
3047
2998
  get embeddingClient() {
3048
- var _a;
3049
- if (((_a = this.embeddingConfig) == null ? void 0 : _a.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
2999
+ var _a2;
3000
+ if (((_a2 = this.embeddingConfig) == null ? void 0 : _a2.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
3050
3001
  return buildClient(this.embeddingConfig.apiKey);
3051
3002
  }
3052
3003
  return this.client;
3053
3004
  }
3054
3005
  /** Resolve the embedding model to use, in order of specificity. */
3055
3006
  resolveEmbeddingModel(optionsModel) {
3056
- var _a, _b;
3057
- return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
3007
+ var _a2, _b;
3008
+ return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
3058
3009
  }
3059
3010
  /**
3060
3011
  * Convert ChatMessage[] to the Gemini contents format.
@@ -3074,8 +3025,8 @@ var GeminiProvider = class {
3074
3025
  // ILLMProvider — chat
3075
3026
  // -------------------------------------------------------------------------
3076
3027
  async chat(messages, context, options) {
3077
- var _a, _b, _c, _d, _e, _f;
3078
- 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.";
3028
+ var _a2, _b, _c, _d, _e, _f;
3029
+ 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.";
3079
3030
  const model = this.client.getGenerativeModel({
3080
3031
  model: this.llmConfig.model,
3081
3032
  systemInstruction: buildSystemContent(basePrompt, context)
@@ -3092,8 +3043,8 @@ var GeminiProvider = class {
3092
3043
  }
3093
3044
  chatStream(messages, context, options) {
3094
3045
  return __asyncGenerator(this, null, function* () {
3095
- var _a, _b, _c, _d, _e, _f;
3096
- 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.";
3046
+ var _a2, _b, _c, _d, _e, _f;
3047
+ 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.";
3097
3048
  const model = this.client.getGenerativeModel({
3098
3049
  model: this.llmConfig.model,
3099
3050
  systemInstruction: buildSystemContent(basePrompt, context)
@@ -3128,11 +3079,11 @@ var GeminiProvider = class {
3128
3079
  // ILLMProvider — embeddings
3129
3080
  // -------------------------------------------------------------------------
3130
3081
  async embed(text, options) {
3131
- var _a, _b;
3082
+ var _a2, _b;
3132
3083
  const content = applyPrefix(
3133
3084
  text,
3134
3085
  options == null ? void 0 : options.taskType,
3135
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
3086
+ (_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
3136
3087
  (_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
3137
3088
  );
3138
3089
  const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
@@ -3149,7 +3100,7 @@ var GeminiProvider = class {
3149
3100
  const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
3150
3101
  const model = this.embeddingClient.getGenerativeModel({ model: modelName });
3151
3102
  const requests = texts.map((text) => {
3152
- var _a, _b;
3103
+ var _a2, _b;
3153
3104
  return {
3154
3105
  content: {
3155
3106
  role: "user",
@@ -3157,7 +3108,7 @@ var GeminiProvider = class {
3157
3108
  text: applyPrefix(
3158
3109
  text,
3159
3110
  options == null ? void 0 : options.taskType,
3160
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
3111
+ (_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
3161
3112
  (_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
3162
3113
  )
3163
3114
  }]
@@ -3174,8 +3125,8 @@ var GeminiProvider = class {
3174
3125
  throw err;
3175
3126
  });
3176
3127
  return response.embeddings.map((e) => {
3177
- var _a;
3178
- return (_a = e.values) != null ? _a : [];
3128
+ var _a2;
3129
+ return (_a2 = e.values) != null ? _a2 : [];
3179
3130
  });
3180
3131
  }
3181
3132
  // -------------------------------------------------------------------------
@@ -3195,163 +3146,482 @@ var GeminiProvider = class {
3195
3146
  }
3196
3147
  };
3197
3148
 
3198
- // src/llm/providers/UniversalLLMAdapter.ts
3199
- init_templateUtils();
3200
- import axios2 from "axios";
3201
-
3202
- // src/config/UniversalProfiles.ts
3203
- var OPENAI_BASE = {
3204
- chatPath: "/chat/completions",
3205
- embedPath: "/embeddings",
3206
- responseExtractPath: "choices[0].message.content",
3207
- embedExtractPath: "data[0].embedding",
3208
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
3209
- };
3210
- var LLM_PROFILES = {
3211
- "openai-compatible": OPENAI_BASE,
3212
- "litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
3213
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
3214
- }),
3215
- "anthropic-claude": {
3216
- chatPath: "/v1/messages",
3217
- responseExtractPath: "content[0].text",
3218
- headers: { "anthropic-version": "2023-06-01" },
3219
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
3220
- },
3221
- "google-gemini": {
3222
- chatPath: "/v1beta/models/{{model}}:generateContent",
3223
- responseExtractPath: "candidates[0].content.parts[0].text",
3224
- chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
3225
- },
3226
- "github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
3227
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
3228
- }),
3229
- "ollama-standard": {
3230
- chatPath: "/api/chat",
3231
- embedPath: "/api/embeddings",
3232
- responseExtractPath: "message.content",
3233
- embedExtractPath: "embedding",
3234
- chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
3235
- embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
3149
+ // src/llm/providers/GroqProvider.ts
3150
+ import OpenAI2 from "openai";
3151
+ var GroqProvider = class {
3152
+ constructor(llmConfig, embeddingConfig) {
3153
+ void embeddingConfig;
3154
+ const apiKey = llmConfig.apiKey || process.env.GROQ_API_KEY;
3155
+ if (!apiKey) throw new Error("[GroqProvider] llmConfig.apiKey or GROQ_API_KEY environment variable is required");
3156
+ this.client = new OpenAI2({
3157
+ apiKey,
3158
+ baseURL: llmConfig.baseUrl || "https://api.groq.com/openai/v1"
3159
+ });
3160
+ this.llmConfig = llmConfig;
3236
3161
  }
3237
- };
3238
- var VECTOR_PROFILES = {
3239
- "pinecone-rest": {
3240
- queryPath: "/query",
3241
- upsertPath: "/vectors/upsert",
3242
- responseExtractPath: "matches",
3243
- idPath: "id",
3244
- scorePath: "score",
3245
- contentPath: "metadata.content",
3246
- metadataPath: "metadata",
3247
- queryPayloadTemplate: '{"vector":{{vector}},"topK":{{topK}},"includeMetadata":true,"namespace":"{{namespace}}"}'
3248
- },
3249
- "mongodb-atlas": {
3250
- queryPath: "/action/aggregate",
3251
- responseExtractPath: "documents",
3252
- idPath: "_id",
3253
- scorePath: "score",
3254
- contentPath: "content",
3255
- metadataPath: "metadata",
3256
- 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"}}}]}'
3257
- },
3258
- "chromadb": {
3259
- queryPath: "/api/v1/collections/{{index}}/query",
3260
- upsertPath: "/api/v1/collections/{{index}}/add",
3261
- responseExtractPath: "matches",
3262
- idPath: "id",
3263
- scorePath: "distance",
3264
- contentPath: "document",
3265
- metadataPath: "metadata"
3266
- },
3267
- "qdrant": {
3268
- queryPath: "/collections/{{index}}/points/search",
3269
- upsertPath: "/collections/{{index}}/points",
3270
- responseExtractPath: "result",
3271
- idPath: "id",
3272
- scorePath: "score",
3273
- contentPath: "payload.content",
3274
- metadataPath: "payload"
3162
+ static getValidator() {
3163
+ return {
3164
+ validate(config) {
3165
+ const errors = [];
3166
+ if (!config.apiKey && !process.env.GROQ_API_KEY) {
3167
+ errors.push({
3168
+ field: "llm.apiKey",
3169
+ message: "Groq API key is required",
3170
+ suggestion: "Set GROQ_API_KEY environment variable",
3171
+ severity: "error"
3172
+ });
3173
+ }
3174
+ if (!config.model) {
3175
+ errors.push({
3176
+ field: "llm.model",
3177
+ message: "Groq model name is required",
3178
+ suggestion: 'e.g., "llama-3.3-70b-versatile"',
3179
+ severity: "error"
3180
+ });
3181
+ }
3182
+ return errors;
3183
+ }
3184
+ };
3275
3185
  }
3276
- };
3277
-
3278
- // src/llm/providers/UniversalLLMAdapter.ts
3279
- var UniversalLLMAdapter = class {
3280
- constructor(config) {
3281
- var _a, _b, _c, _d, _e, _f, _g, _h;
3282
- this.model = config.model;
3283
- const llmConfig = config;
3284
- const options = (_a = llmConfig.options) != null ? _a : {};
3285
- let profile = {};
3286
- if (typeof options.profile === "string") {
3287
- profile = LLM_PROFILES[options.profile] || {};
3288
- } else if (typeof options.profile === "object" && options.profile !== null) {
3289
- profile = options.profile;
3290
- }
3291
- this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
3292
- this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
3293
- this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
3294
- this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
3295
- this.apiKey = config.apiKey;
3296
- this.baseUrl = (_g = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g : "";
3297
- if (!this.baseUrl) {
3298
- throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
3299
- }
3300
- this.resolvedHeaders = __spreadValues(__spreadValues({
3301
- "Content-Type": "application/json"
3302
- }, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {});
3303
- this.http = axios2.create({
3304
- baseURL: this.baseUrl,
3305
- headers: this.resolvedHeaders,
3306
- timeout: (_h = this.opts.timeout) != null ? _h : 6e4
3307
- });
3186
+ static getHealthChecker() {
3187
+ return {
3188
+ async check(config) {
3189
+ const timestamp = Date.now();
3190
+ const apiKey = config.apiKey || process.env.GROQ_API_KEY || "";
3191
+ const modelName = config.model;
3192
+ try {
3193
+ const OpenAI4 = await import("openai");
3194
+ const client = new OpenAI4.default({
3195
+ apiKey,
3196
+ baseURL: config.baseUrl || "https://api.groq.com/openai/v1"
3197
+ });
3198
+ const models = await client.models.list();
3199
+ const hasModel = models.data.some((m) => m.id === modelName);
3200
+ return {
3201
+ healthy: true,
3202
+ provider: "groq",
3203
+ capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
3204
+ timestamp
3205
+ };
3206
+ } catch (error) {
3207
+ return {
3208
+ healthy: false,
3209
+ provider: "groq",
3210
+ error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
3211
+ timestamp
3212
+ };
3213
+ }
3214
+ }
3215
+ };
3308
3216
  }
3309
- async chat(messages, context) {
3310
- var _a, _b;
3311
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
3217
+ async chat(messages, context, options) {
3218
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
3219
+ 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.";
3220
+ const systemMessage = {
3221
+ role: "system",
3222
+ content: buildSystemContent(basePrompt, context)
3223
+ };
3312
3224
  const formattedMessages = [
3313
- { role: "system", content: `${this.systemPrompt}
3314
-
3315
- Context:
3316
- ${context != null ? context : "None"}` },
3317
- ...messages
3225
+ systemMessage,
3226
+ ...messages.map((m) => ({
3227
+ role: m.role,
3228
+ content: m.content
3229
+ }))
3318
3230
  ];
3319
- let payload;
3320
- if (this.opts.chatPayloadTemplate) {
3321
- payload = buildPayload(this.opts.chatPayloadTemplate, {
3322
- model: this.model,
3323
- messages: formattedMessages,
3324
- maxTokens: this.maxTokens,
3325
- temperature: this.temperature
3326
- });
3327
- } else {
3328
- payload = {
3329
- model: this.model,
3330
- messages: formattedMessages,
3331
- max_tokens: this.maxTokens,
3332
- temperature: this.temperature
3333
- };
3334
- }
3335
- const { data } = await this.http.post(path, payload);
3336
- const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
3337
- const result = resolvePath(data, extractPath);
3338
- if (result === void 0) {
3339
- throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
3340
- }
3341
- return String(result);
3231
+ const completion = await this.client.chat.completions.create({
3232
+ model: this.llmConfig.model,
3233
+ messages: formattedMessages,
3234
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3235
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3236
+ stop: options == null ? void 0 : options.stop
3237
+ });
3238
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
3342
3239
  }
3343
- /**
3344
- * Streaming chat using native fetch + ReadableStream.
3345
- * Parses OpenAI-compatible SSE frames: `data: {...}\n\n`
3346
- * Works with vLLM, LMStudio, Together AI, Fireworks, and any OpenAI-compatible API.
3347
- */
3348
- chatStream(messages, context) {
3240
+ chatStream(messages, context, options) {
3349
3241
  return __asyncGenerator(this, null, function* () {
3350
- var _a, _b, _c;
3351
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
3352
- const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
3353
- const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
3354
- const formattedMessages = [
3242
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3243
+ 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.";
3244
+ const systemMessage = {
3245
+ role: "system",
3246
+ content: buildSystemContent(basePrompt, context)
3247
+ };
3248
+ const formattedMessages = [
3249
+ systemMessage,
3250
+ ...messages.map((m) => ({
3251
+ role: m.role,
3252
+ content: m.content
3253
+ }))
3254
+ ];
3255
+ const stream = yield new __await(this.client.chat.completions.create({
3256
+ model: this.llmConfig.model,
3257
+ messages: formattedMessages,
3258
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3259
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3260
+ stop: options == null ? void 0 : options.stop,
3261
+ stream: true
3262
+ }));
3263
+ if (!stream) {
3264
+ throw new Error("[GroqProvider] completions.create stream is undefined");
3265
+ }
3266
+ try {
3267
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
3268
+ const chunk = temp.value;
3269
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
3270
+ if (content) yield content;
3271
+ }
3272
+ } catch (temp) {
3273
+ error = [temp];
3274
+ } finally {
3275
+ try {
3276
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
3277
+ } finally {
3278
+ if (error)
3279
+ throw error[0];
3280
+ }
3281
+ }
3282
+ });
3283
+ }
3284
+ async embed(text, options) {
3285
+ void text;
3286
+ void options;
3287
+ throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
3288
+ }
3289
+ async batchEmbed(texts, options) {
3290
+ void texts;
3291
+ void options;
3292
+ throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
3293
+ }
3294
+ async ping() {
3295
+ try {
3296
+ await this.client.models.list();
3297
+ return true;
3298
+ } catch (err) {
3299
+ console.error("[GroqProvider] Ping failed:", err);
3300
+ return false;
3301
+ }
3302
+ }
3303
+ };
3304
+
3305
+ // src/llm/providers/QwenProvider.ts
3306
+ import OpenAI3 from "openai";
3307
+ var QwenProvider = class {
3308
+ constructor(llmConfig, embeddingConfig) {
3309
+ const apiKey = llmConfig.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY;
3310
+ if (!apiKey) throw new Error("[QwenProvider] llmConfig.apiKey, DASHSCOPE_API_KEY, or QWEN_API_KEY environment variable is required");
3311
+ this.client = new OpenAI3({
3312
+ apiKey,
3313
+ baseURL: llmConfig.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3314
+ });
3315
+ this.llmConfig = llmConfig;
3316
+ this.embeddingConfig = embeddingConfig;
3317
+ }
3318
+ static getValidator() {
3319
+ return {
3320
+ validate(config) {
3321
+ const errors = [];
3322
+ const isEmbedding = config.provider === "qwen" && "dimensions" in config;
3323
+ const prefix = isEmbedding ? "embedding" : "llm";
3324
+ if (!config.apiKey && !process.env.DASHSCOPE_API_KEY && !process.env.QWEN_API_KEY) {
3325
+ errors.push({
3326
+ field: `${prefix}.apiKey`,
3327
+ message: "Qwen API key is required",
3328
+ suggestion: "Set DASHSCOPE_API_KEY or QWEN_API_KEY environment variable",
3329
+ severity: "error"
3330
+ });
3331
+ }
3332
+ if (!config.model) {
3333
+ errors.push({
3334
+ field: `${prefix}.model`,
3335
+ message: "Qwen model name is required",
3336
+ suggestion: isEmbedding ? 'e.g., "text-embedding-v3"' : 'e.g., "qwen-plus" or "qwen-max"',
3337
+ severity: "error"
3338
+ });
3339
+ }
3340
+ return errors;
3341
+ }
3342
+ };
3343
+ }
3344
+ static getHealthChecker() {
3345
+ return {
3346
+ async check(config) {
3347
+ const timestamp = Date.now();
3348
+ const apiKey = config.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY || "";
3349
+ const modelName = config.model;
3350
+ try {
3351
+ const OpenAI4 = await import("openai");
3352
+ const client = new OpenAI4.default({
3353
+ apiKey,
3354
+ baseURL: config.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3355
+ });
3356
+ const models = await client.models.list();
3357
+ const hasModel = models.data.some((m) => m.id === modelName);
3358
+ return {
3359
+ healthy: true,
3360
+ provider: "qwen",
3361
+ capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
3362
+ timestamp
3363
+ };
3364
+ } catch (error) {
3365
+ return {
3366
+ healthy: false,
3367
+ provider: "qwen",
3368
+ error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
3369
+ timestamp
3370
+ };
3371
+ }
3372
+ }
3373
+ };
3374
+ }
3375
+ async chat(messages, context, options) {
3376
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
3377
+ 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.";
3378
+ const systemMessage = {
3379
+ role: "system",
3380
+ content: buildSystemContent(basePrompt, context)
3381
+ };
3382
+ const formattedMessages = [
3383
+ systemMessage,
3384
+ ...messages.map((m) => ({
3385
+ role: m.role,
3386
+ content: m.content
3387
+ }))
3388
+ ];
3389
+ const completion = await this.client.chat.completions.create({
3390
+ model: this.llmConfig.model,
3391
+ messages: formattedMessages,
3392
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3393
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3394
+ stop: options == null ? void 0 : options.stop
3395
+ });
3396
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
3397
+ }
3398
+ chatStream(messages, context, options) {
3399
+ return __asyncGenerator(this, null, function* () {
3400
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3401
+ 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.";
3402
+ const systemMessage = {
3403
+ role: "system",
3404
+ content: buildSystemContent(basePrompt, context)
3405
+ };
3406
+ const formattedMessages = [
3407
+ systemMessage,
3408
+ ...messages.map((m) => ({
3409
+ role: m.role,
3410
+ content: m.content
3411
+ }))
3412
+ ];
3413
+ const stream = yield new __await(this.client.chat.completions.create({
3414
+ model: this.llmConfig.model,
3415
+ messages: formattedMessages,
3416
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3417
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3418
+ stop: options == null ? void 0 : options.stop,
3419
+ stream: true
3420
+ }));
3421
+ if (!stream) {
3422
+ throw new Error("[QwenProvider] completions.create stream is undefined");
3423
+ }
3424
+ try {
3425
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
3426
+ const chunk = temp.value;
3427
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
3428
+ if (content) yield content;
3429
+ }
3430
+ } catch (temp) {
3431
+ error = [temp];
3432
+ } finally {
3433
+ try {
3434
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
3435
+ } finally {
3436
+ if (error)
3437
+ throw error[0];
3438
+ }
3439
+ }
3440
+ });
3441
+ }
3442
+ async embed(text, options) {
3443
+ const results = await this.batchEmbed([text], options);
3444
+ return results[0];
3445
+ }
3446
+ async batchEmbed(texts, options) {
3447
+ var _a2, _b, _c, _d, _e, _f;
3448
+ 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";
3449
+ const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
3450
+ const client = apiKey !== this.llmConfig.apiKey ? new OpenAI3({
3451
+ apiKey,
3452
+ baseURL: ((_f = this.embeddingConfig) == null ? void 0 : _f.baseUrl) || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3453
+ }) : this.client;
3454
+ const response = await client.embeddings.create({ model, input: texts });
3455
+ return response.data.map((d) => d.embedding);
3456
+ }
3457
+ async ping() {
3458
+ try {
3459
+ await this.client.models.list();
3460
+ return true;
3461
+ } catch (err) {
3462
+ console.error("[QwenProvider] Ping failed:", err);
3463
+ return false;
3464
+ }
3465
+ }
3466
+ };
3467
+
3468
+ // src/llm/providers/UniversalLLMAdapter.ts
3469
+ init_templateUtils();
3470
+ import axios2 from "axios";
3471
+
3472
+ // src/config/UniversalProfiles.ts
3473
+ var OPENAI_BASE = {
3474
+ chatPath: "/chat/completions",
3475
+ embedPath: "/embeddings",
3476
+ responseExtractPath: "choices[0].message.content",
3477
+ embedExtractPath: "data[0].embedding",
3478
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}}}'
3479
+ };
3480
+ var LLM_PROFILES = {
3481
+ "openai-compatible": OPENAI_BASE,
3482
+ "litellm": __spreadProps(__spreadValues({}, OPENAI_BASE), {
3483
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}},"temperature":{{temperature}},"stream":false}'
3484
+ }),
3485
+ "anthropic-claude": {
3486
+ chatPath: "/v1/messages",
3487
+ responseExtractPath: "content[0].text",
3488
+ headers: { "anthropic-version": "2023-06-01" },
3489
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"max_tokens":{{maxTokens}}}'
3490
+ },
3491
+ "google-gemini": {
3492
+ chatPath: "/v1beta/models/{{model}}:generateContent",
3493
+ responseExtractPath: "candidates[0].content.parts[0].text",
3494
+ chatPayloadTemplate: '{"contents":[{"parts":[{"text":"{{messages}}"}]}]}'
3495
+ },
3496
+ "github-copilot": __spreadProps(__spreadValues({}, OPENAI_BASE), {
3497
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"temperature":{{temperature}}}'
3498
+ }),
3499
+ "ollama-standard": {
3500
+ chatPath: "/api/chat",
3501
+ embedPath: "/api/embeddings",
3502
+ responseExtractPath: "message.content",
3503
+ embedExtractPath: "embedding",
3504
+ chatPayloadTemplate: '{"model":"{{model}}","messages":{{messages}},"stream":false}',
3505
+ embedPayloadTemplate: '{"model":"{{model}}","prompt":"{{input}}"}'
3506
+ }
3507
+ };
3508
+ var VECTOR_PROFILES = {
3509
+ "pinecone-rest": {
3510
+ queryPath: "/query",
3511
+ upsertPath: "/vectors/upsert",
3512
+ responseExtractPath: "matches",
3513
+ idPath: "id",
3514
+ scorePath: "score",
3515
+ contentPath: "metadata.content",
3516
+ metadataPath: "metadata",
3517
+ queryPayloadTemplate: '{"vector":{{vector}},"topK":{{topK}},"includeMetadata":true,"namespace":"{{namespace}}"}'
3518
+ },
3519
+ "mongodb-atlas": {
3520
+ queryPath: "/action/aggregate",
3521
+ responseExtractPath: "documents",
3522
+ idPath: "_id",
3523
+ scorePath: "score",
3524
+ contentPath: "content",
3525
+ metadataPath: "metadata",
3526
+ 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"}}}]}'
3527
+ },
3528
+ "chromadb": {
3529
+ queryPath: "/api/v1/collections/{{index}}/query",
3530
+ upsertPath: "/api/v1/collections/{{index}}/add",
3531
+ responseExtractPath: "matches",
3532
+ idPath: "id",
3533
+ scorePath: "distance",
3534
+ contentPath: "document",
3535
+ metadataPath: "metadata"
3536
+ },
3537
+ "qdrant": {
3538
+ queryPath: "/collections/{{index}}/points/search",
3539
+ upsertPath: "/collections/{{index}}/points",
3540
+ responseExtractPath: "result",
3541
+ idPath: "id",
3542
+ scorePath: "score",
3543
+ contentPath: "payload.content",
3544
+ metadataPath: "payload"
3545
+ }
3546
+ };
3547
+
3548
+ // src/llm/providers/UniversalLLMAdapter.ts
3549
+ var UniversalLLMAdapter = class {
3550
+ constructor(config) {
3551
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3552
+ this.model = config.model;
3553
+ const llmConfig = config;
3554
+ const options = (_a2 = llmConfig.options) != null ? _a2 : {};
3555
+ let profile = {};
3556
+ if (typeof options.profile === "string") {
3557
+ profile = LLM_PROFILES[options.profile] || {};
3558
+ } else if (typeof options.profile === "object" && options.profile !== null) {
3559
+ profile = options.profile;
3560
+ }
3561
+ this.opts = __spreadValues(__spreadValues({}, profile), (_b = llmConfig.options) != null ? _b : {});
3562
+ this.systemPrompt = (_c = llmConfig.systemPrompt) != null ? _c : "You are a helpful AI assistant. Use the provided context to answer the user.";
3563
+ this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
3564
+ this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
3565
+ this.apiKey = config.apiKey;
3566
+ this.baseUrl = (_g2 = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g2 : "";
3567
+ if (!this.baseUrl) {
3568
+ throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
3569
+ }
3570
+ this.resolvedHeaders = __spreadValues(__spreadValues({
3571
+ "Content-Type": "application/json"
3572
+ }, config.apiKey ? { Authorization: `Bearer ${config.apiKey}` } : {}), this.opts.headers || {});
3573
+ this.http = axios2.create({
3574
+ baseURL: this.baseUrl,
3575
+ headers: this.resolvedHeaders,
3576
+ timeout: (_h = this.opts.timeout) != null ? _h : 6e4
3577
+ });
3578
+ }
3579
+ async chat(messages, context) {
3580
+ var _a2, _b;
3581
+ const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3582
+ const formattedMessages = [
3583
+ { role: "system", content: `${this.systemPrompt}
3584
+
3585
+ Context:
3586
+ ${context != null ? context : "None"}` },
3587
+ ...messages
3588
+ ];
3589
+ let payload;
3590
+ if (this.opts.chatPayloadTemplate) {
3591
+ payload = buildPayload(this.opts.chatPayloadTemplate, {
3592
+ model: this.model,
3593
+ messages: formattedMessages,
3594
+ maxTokens: this.maxTokens,
3595
+ temperature: this.temperature
3596
+ });
3597
+ } else {
3598
+ payload = {
3599
+ model: this.model,
3600
+ messages: formattedMessages,
3601
+ max_tokens: this.maxTokens,
3602
+ temperature: this.temperature
3603
+ };
3604
+ }
3605
+ const { data } = await this.http.post(path2, payload);
3606
+ const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
3607
+ const result = resolvePath(data, extractPath);
3608
+ if (result === void 0) {
3609
+ throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
3610
+ }
3611
+ return String(result);
3612
+ }
3613
+ /**
3614
+ * Streaming chat using native fetch + ReadableStream.
3615
+ * Parses OpenAI-compatible SSE frames: `data: {...}\n\n`
3616
+ * Works with vLLM, LMStudio, Together AI, Fireworks, and any OpenAI-compatible API.
3617
+ */
3618
+ chatStream(messages, context) {
3619
+ return __asyncGenerator(this, null, function* () {
3620
+ var _a2, _b, _c;
3621
+ const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3622
+ const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3623
+ const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
3624
+ const formattedMessages = [
3355
3625
  { role: "system", content: `${this.systemPrompt}
3356
3626
 
3357
3627
  Context:
@@ -3427,8 +3697,8 @@ ${context != null ? context : "None"}` },
3427
3697
  });
3428
3698
  }
3429
3699
  async embed(text) {
3430
- var _a, _b;
3431
- const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
3700
+ var _a2, _b;
3701
+ const path2 = (_a2 = this.opts.embedPath) != null ? _a2 : "/embeddings";
3432
3702
  let payload;
3433
3703
  if (this.opts.embedPayloadTemplate) {
3434
3704
  payload = buildPayload(this.opts.embedPayloadTemplate, {
@@ -3441,7 +3711,7 @@ ${context != null ? context : "None"}` },
3441
3711
  input: text
3442
3712
  };
3443
3713
  }
3444
- const { data } = await this.http.post(path, payload);
3714
+ const { data } = await this.http.post(path2, payload);
3445
3715
  const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
3446
3716
  const vector = resolvePath(data, extractPath);
3447
3717
  if (!Array.isArray(vector)) {
@@ -3469,6 +3739,78 @@ ${context != null ? context : "None"}` },
3469
3739
  }
3470
3740
  };
3471
3741
 
3742
+ // src/exceptions/index.ts
3743
+ var RetrivoraError = class extends Error {
3744
+ constructor(message, code, details) {
3745
+ super(message);
3746
+ this.name = new.target.name;
3747
+ this.code = code;
3748
+ this.details = details;
3749
+ }
3750
+ };
3751
+ var ProviderNotFoundException = class extends RetrivoraError {
3752
+ constructor(providerType, provider, details) {
3753
+ super(`Unsupported ${providerType} provider: ${provider}`, "PROVIDER_NOT_FOUND", details);
3754
+ }
3755
+ };
3756
+ var EmbeddingFailedException = class extends RetrivoraError {
3757
+ constructor(message = "Embedding generation failed", details) {
3758
+ super(message, "EMBEDDING_FAILED", details);
3759
+ }
3760
+ };
3761
+ var RetrievalException = class extends RetrivoraError {
3762
+ constructor(message = "Retrieval failed", details) {
3763
+ super(message, "RETRIEVAL_FAILED", details);
3764
+ }
3765
+ };
3766
+ var RateLimitException = class extends RetrivoraError {
3767
+ constructor(message = "Provider rate limit exceeded", details) {
3768
+ super(message, "RATE_LIMITED", details);
3769
+ }
3770
+ };
3771
+ var ConfigurationException = class extends RetrivoraError {
3772
+ constructor(message, details) {
3773
+ super(message, "CONFIGURATION_ERROR", details);
3774
+ }
3775
+ };
3776
+ var AuthenticationException = class extends RetrivoraError {
3777
+ constructor(message = "Provider authentication failed", details) {
3778
+ super(message, "AUTHENTICATION_ERROR", details);
3779
+ }
3780
+ };
3781
+ function wrapError(err, defaultCode, defaultMessage) {
3782
+ var _a2;
3783
+ if (err instanceof RetrivoraError) {
3784
+ return err;
3785
+ }
3786
+ const error = err;
3787
+ const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
3788
+ 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);
3789
+ const code = error == null ? void 0 : error.code;
3790
+ if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
3791
+ return new RateLimitException(message, err);
3792
+ }
3793
+ if (status === 401 || status === 403 || /unauthorized|auth|api[- ]?key/i.test(message) || code === "INVALID_API_KEY") {
3794
+ return new AuthenticationException(message, err);
3795
+ }
3796
+ switch (defaultCode) {
3797
+ case "PROVIDER_NOT_FOUND":
3798
+ return new ProviderNotFoundException("provider", message, err);
3799
+ case "EMBEDDING_FAILED":
3800
+ return new EmbeddingFailedException(message, err);
3801
+ case "RETRIEVAL_FAILED":
3802
+ return new RetrievalException(message, err);
3803
+ case "RATE_LIMITED":
3804
+ return new RateLimitException(message, err);
3805
+ case "CONFIGURATION_ERROR":
3806
+ return new ConfigurationException(message, err);
3807
+ case "AUTHENTICATION_ERROR":
3808
+ return new AuthenticationException(message, err);
3809
+ default:
3810
+ return new RetrivoraError(message, defaultCode, err);
3811
+ }
3812
+ }
3813
+
3472
3814
  // src/llm/LLMFactory.ts
3473
3815
  var customProviders = /* @__PURE__ */ new Map();
3474
3816
  var LLMFactory = class _LLMFactory {
@@ -3507,6 +3849,8 @@ var LLMFactory = class _LLMFactory {
3507
3849
  "anthropic",
3508
3850
  "ollama",
3509
3851
  "gemini",
3852
+ "groq",
3853
+ "qwen",
3510
3854
  "rest",
3511
3855
  "universal_rest",
3512
3856
  "custom",
@@ -3514,7 +3858,7 @@ var LLMFactory = class _LLMFactory {
3514
3858
  ];
3515
3859
  }
3516
3860
  static create(llmConfig, embeddingConfig) {
3517
- var _a, _b;
3861
+ var _a2, _b, _c;
3518
3862
  switch (llmConfig.provider) {
3519
3863
  case "openai":
3520
3864
  return new OpenAIProvider(llmConfig, embeddingConfig);
@@ -3524,12 +3868,16 @@ var LLMFactory = class _LLMFactory {
3524
3868
  return new OllamaProvider(llmConfig, embeddingConfig);
3525
3869
  case "gemini":
3526
3870
  return new GeminiProvider(llmConfig, embeddingConfig);
3871
+ case "groq":
3872
+ return new GroqProvider(llmConfig, embeddingConfig);
3873
+ case "qwen":
3874
+ return new QwenProvider(llmConfig, embeddingConfig);
3527
3875
  case "rest":
3528
3876
  case "universal_rest":
3529
3877
  case "custom":
3530
3878
  return new UniversalLLMAdapter(llmConfig);
3531
3879
  default: {
3532
- const providerName = String((_a = llmConfig.provider) != null ? _a : "").toLowerCase();
3880
+ const providerName = String((_a2 = llmConfig.provider) != null ? _a2 : "").toLowerCase();
3533
3881
  const customFactory = customProviders.get(providerName);
3534
3882
  if (customFactory) {
3535
3883
  return customFactory(llmConfig);
@@ -3538,9 +3886,12 @@ var LLMFactory = class _LLMFactory {
3538
3886
  return new UniversalLLMAdapter(llmConfig);
3539
3887
  }
3540
3888
  throw new ProviderNotFoundException(
3541
- "LLM",
3542
- String(llmConfig.provider),
3543
- `[LLMFactory] Unknown provider "${llmConfig.provider}". Built-in providers: ${_LLMFactory.listProviders().join(", ")}. Register a custom provider with LLMFactory.register().`
3889
+ "llm",
3890
+ (_c = llmConfig.provider) != null ? _c : "undefined",
3891
+ {
3892
+ message: `Unknown provider "${llmConfig.provider}". Register a custom provider with LLMFactory.register().`,
3893
+ available: _LLMFactory.listProviders()
3894
+ }
3544
3895
  );
3545
3896
  }
3546
3897
  }
@@ -3563,6 +3914,10 @@ var LLMFactory = class _LLMFactory {
3563
3914
  return OllamaProvider;
3564
3915
  case "gemini":
3565
3916
  return GeminiProvider;
3917
+ case "groq":
3918
+ return GroqProvider;
3919
+ case "qwen":
3920
+ return QwenProvider;
3566
3921
  case "rest":
3567
3922
  case "universal_rest":
3568
3923
  case "custom":
@@ -3624,7 +3979,7 @@ var ProviderRegistry = class {
3624
3979
  return null;
3625
3980
  }
3626
3981
  static async loadVectorProviderClass(provider) {
3627
- var _a;
3982
+ var _a2;
3628
3983
  if (this.vectorProviders[provider]) return this.vectorProviders[provider];
3629
3984
  switch (provider) {
3630
3985
  case "pinecone": {
@@ -3633,7 +3988,7 @@ var ProviderRegistry = class {
3633
3988
  }
3634
3989
  case "pgvector":
3635
3990
  case "postgresql": {
3636
- const postgresMode = ((_a = process.env.POSTGRES_MODE) != null ? _a : "multi").toLowerCase();
3991
+ const postgresMode = ((_a2 = process.env.POSTGRES_MODE) != null ? _a2 : "multi").toLowerCase();
3637
3992
  if (postgresMode === "single") {
3638
3993
  const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
3639
3994
  return PostgreSQLProvider2;
@@ -3853,6 +4208,125 @@ var ConfigValidator = class {
3853
4208
  }
3854
4209
  };
3855
4210
 
4211
+ // src/core/LicenseVerifier.ts
4212
+ import * as crypto2 from "crypto";
4213
+ var LicenseVerifier = class {
4214
+ /**
4215
+ * Decodes, verifies signature, and checks metadata of a license key.
4216
+ *
4217
+ * @param licenseKey - Base64url signed JWT license key.
4218
+ * @param currentProjectId - Project namespace ID.
4219
+ * @param publicKeyOverride - Optional override for unit/integration tests.
4220
+ */
4221
+ static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
4222
+ const isProduction = process.env.NODE_ENV === "production";
4223
+ if (!licenseKey) {
4224
+ if (isProduction) {
4225
+ throw new ConfigurationException(
4226
+ "[Retrivora SDK] License key (licenseKey) is required in production environments."
4227
+ );
4228
+ }
4229
+ console.warn(
4230
+ `\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
4231
+ );
4232
+ return {
4233
+ projectId: currentProjectId,
4234
+ expiresAt: Math.floor(Date.now() / 1e3) + 86400,
4235
+ // Valid for 24h
4236
+ tier: "hobby"
4237
+ };
4238
+ }
4239
+ try {
4240
+ const parts = licenseKey.split(".");
4241
+ if (parts.length !== 3) {
4242
+ throw new Error("Malformed token structure (expected 3 parts).");
4243
+ }
4244
+ const [headerB64, payloadB64, signatureB64] = parts;
4245
+ const dataToVerify = `${headerB64}.${payloadB64}`;
4246
+ const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
4247
+ const signature = Buffer.from(signatureB64, "base64url");
4248
+ const data = Buffer.from(dataToVerify);
4249
+ const isValid = crypto2.verify(
4250
+ "sha256",
4251
+ data,
4252
+ publicKey,
4253
+ signature
4254
+ );
4255
+ if (!isValid) {
4256
+ throw new Error("Signature verification failed.");
4257
+ }
4258
+ const payload = JSON.parse(
4259
+ Buffer.from(payloadB64, "base64url").toString("utf8")
4260
+ );
4261
+ if (!payload.projectId) {
4262
+ throw new Error('License payload is missing "projectId".');
4263
+ }
4264
+ if (payload.projectId !== currentProjectId) {
4265
+ throw new Error(
4266
+ `Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
4267
+ );
4268
+ }
4269
+ if (!payload.expiresAt) {
4270
+ throw new Error('License payload is missing expiration ("expiresAt").');
4271
+ }
4272
+ const currentTimestampSec = Math.floor(Date.now() / 1e3);
4273
+ if (currentTimestampSec > payload.expiresAt) {
4274
+ throw new Error(
4275
+ `License key has expired. Expiration: ${new Date(
4276
+ payload.expiresAt * 1e3
4277
+ ).toDateString()}`
4278
+ );
4279
+ }
4280
+ if (isProduction && provider) {
4281
+ const tier = (payload.tier || "").toLowerCase();
4282
+ const normalizedProvider = provider.toLowerCase();
4283
+ if (tier === "hobby") {
4284
+ const allowedHobby = ["postgresql", "pgvector", "supabase"];
4285
+ if (!allowedHobby.includes(normalizedProvider)) {
4286
+ throw new Error(
4287
+ `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.`
4288
+ );
4289
+ }
4290
+ } else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth") {
4291
+ const allowedPro = [
4292
+ "postgresql",
4293
+ "pgvector",
4294
+ "supabase",
4295
+ "pinecone",
4296
+ "qdrant",
4297
+ "mongodb",
4298
+ "milvus",
4299
+ "chroma",
4300
+ "chromadb"
4301
+ ];
4302
+ if (!allowedPro.includes(normalizedProvider)) {
4303
+ throw new Error(
4304
+ `The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
4305
+ );
4306
+ }
4307
+ }
4308
+ }
4309
+ return payload;
4310
+ } catch (err) {
4311
+ const message = err instanceof Error ? err.message : String(err);
4312
+ throw new ConfigurationException(
4313
+ `[Retrivora SDK] License key validation failed: ${message}`
4314
+ );
4315
+ }
4316
+ }
4317
+ };
4318
+ // Retrivora's Public Key used to verify the license key signature.
4319
+ // In production, this matches the private key held by Retrivora SaaS.
4320
+ LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
4321
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
4322
+ XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
4323
+ xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
4324
+ NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
4325
+ iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
4326
+ +Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
4327
+ MwIDAQAB
4328
+ -----END PUBLIC KEY-----`;
4329
+
3856
4330
  // src/rag/DocumentChunker.ts
3857
4331
  var DocumentChunker = class {
3858
4332
  constructor(chunkSize = 1e3, chunkOverlap = 200, separators = ["\n# ", "\n## ", "\n### ", "\n#### ", "\n\n", "\n", " ", ""]) {
@@ -4082,11 +4556,11 @@ var LlamaIndexIngestor = class {
4082
4556
  * than standard character-count splitting.
4083
4557
  */
4084
4558
  async chunk(text, options = {}) {
4085
- var _a, _b;
4559
+ var _a2, _b;
4086
4560
  try {
4087
4561
  const { Document, SentenceSplitter, MetadataMode } = await import(`${"llamaindex"}`);
4088
4562
  const splitter = new SentenceSplitter({
4089
- chunkSize: (_a = options.chunkSize) != null ? _a : 1e3,
4563
+ chunkSize: (_a2 = options.chunkSize) != null ? _a2 : 1e3,
4090
4564
  chunkOverlap: (_b = options.chunkOverlap) != null ? _b : 200
4091
4565
  });
4092
4566
  const doc = new Document({ text, metadata: options.metadata || {} });
@@ -4173,47 +4647,478 @@ When presenting structured data, statistics, or comparisons, decide if it is bes
4173
4647
  if (!finalSystemPrompt.includes("chart")) {
4174
4648
  finalSystemPrompt += chartInstruction;
4175
4649
  }
4176
- this.agent = createAgent({
4177
- // eslint-disable-next-line @typescript-eslint/no-explicit-any
4178
- model: chatModel,
4179
- tools: [searchTool],
4180
- systemPrompt: finalSystemPrompt
4650
+ this.agent = createAgent({
4651
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
4652
+ model: chatModel,
4653
+ tools: [searchTool],
4654
+ systemPrompt: finalSystemPrompt
4655
+ });
4656
+ } catch (error) {
4657
+ const isMissing = error instanceof Error && error.message.includes("Cannot find module");
4658
+ const hint = isMissing ? " Make sure 'langchain' and '@langchain/core' are installed:\n npm install langchain @langchain/core" : "";
4659
+ throw new Error(
4660
+ `[LangChainAgent] Failed to initialize.${hint}
4661
+ ${error instanceof Error ? error.message : String(error)}`
4662
+ );
4663
+ }
4664
+ }
4665
+ /**
4666
+ * Run the agentic flow.
4667
+ *
4668
+ * LangChain v1.x: invoke takes `{ messages: [...] }` instead of `{ input, chat_history }`.
4669
+ * The agent returns `{ messages: [...] }` — the last message is the final answer.
4670
+ */
4671
+ async run(input, chatHistory = []) {
4672
+ var _a2, _b, _c;
4673
+ if (!this.agent) {
4674
+ throw new Error("[LangChainAgent] Agent not initialized. Call initialize() first.");
4675
+ }
4676
+ const { HumanMessage, AIMessage } = await import("@langchain/core/messages");
4677
+ const historyMessages = chatHistory.map(
4678
+ (m) => m.role === "user" ? new HumanMessage(m.content) : new AIMessage(m.content)
4679
+ );
4680
+ const response = await this.agent.invoke({
4681
+ messages: [...historyMessages, new HumanMessage(input)]
4682
+ });
4683
+ const lastMessage = (_a2 = response == null ? void 0 : response.messages) == null ? void 0 : _a2.at(-1);
4684
+ if (lastMessage && typeof lastMessage.content === "string") {
4685
+ return lastMessage.content;
4686
+ }
4687
+ if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
4688
+ return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
4689
+ }
4690
+ return String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
4691
+ }
4692
+ };
4693
+
4694
+ // src/core/mcp.ts
4695
+ import { spawn } from "child_process";
4696
+ var MCPClient = class {
4697
+ constructor(config) {
4698
+ this.config = config;
4699
+ this.messageIdCounter = 0;
4700
+ this.pendingRequests = /* @__PURE__ */ new Map();
4701
+ this.stdioBuffer = "";
4702
+ this.initialized = false;
4703
+ }
4704
+ getNextMessageId() {
4705
+ return ++this.messageIdCounter;
4706
+ }
4707
+ /**
4708
+ * Connect and initialize the MCP server connection.
4709
+ */
4710
+ async connect() {
4711
+ if (this.initialized) return;
4712
+ if (this.config.transport === "stdio") {
4713
+ await this.connectStdio();
4714
+ } else {
4715
+ await this.connectSSE();
4716
+ }
4717
+ try {
4718
+ const response = await this.sendJsonRpc("initialize", {
4719
+ protocolVersion: "2024-11-05",
4720
+ capabilities: {},
4721
+ clientInfo: {
4722
+ name: "retrivora-sdk",
4723
+ version: "1.0.0"
4724
+ }
4725
+ });
4726
+ await this.sendNotification("notifications/initialized");
4727
+ this.initialized = true;
4728
+ console.log(`[MCPClient] Connected and initialized server "${this.config.name}" successfully.`);
4729
+ } catch (err) {
4730
+ this.disconnect();
4731
+ throw new Error(`[MCPClient] Failed to initialize server "${this.config.name}": ${err.message}`);
4732
+ }
4733
+ }
4734
+ async connectStdio() {
4735
+ var _a2;
4736
+ const cmd = this.config.command;
4737
+ if (!cmd) {
4738
+ throw new Error(`[MCPClient] Command option is required for stdio transport on "${this.config.name}"`);
4739
+ }
4740
+ const args = this.config.args || [];
4741
+ const env = __spreadValues(__spreadValues({}, process.env), this.config.env || {});
4742
+ this.childProcess = spawn(cmd, args, { env, shell: true });
4743
+ if (!this.childProcess || !this.childProcess.stdout || !this.childProcess.stdin) {
4744
+ throw new Error(`[MCPClient] Failed to spawn stdio child process for "${this.config.name}"`);
4745
+ }
4746
+ this.childProcess.stdout.on("data", (data) => {
4747
+ this.stdioBuffer += data.toString("utf-8");
4748
+ this.processStdioLines();
4749
+ });
4750
+ (_a2 = this.childProcess.stderr) == null ? void 0 : _a2.on("data", (data) => {
4751
+ console.warn(`[MCPClient] [stderr] [${this.config.name}]:`, data.toString("utf-8"));
4752
+ });
4753
+ this.childProcess.on("close", (code) => {
4754
+ console.log(`[MCPClient] Connection closed for "${this.config.name}" with exit code: ${code}`);
4755
+ this.disconnect();
4756
+ });
4757
+ await new Promise((resolve) => setTimeout(resolve, 100));
4758
+ }
4759
+ processStdioLines() {
4760
+ let newlineIndex;
4761
+ while ((newlineIndex = this.stdioBuffer.indexOf("\n")) !== -1) {
4762
+ const line = this.stdioBuffer.substring(0, newlineIndex).trim();
4763
+ this.stdioBuffer = this.stdioBuffer.substring(newlineIndex + 1);
4764
+ if (!line) continue;
4765
+ try {
4766
+ const payload = JSON.parse(line);
4767
+ if (payload.id !== void 0) {
4768
+ const req = this.pendingRequests.get(Number(payload.id));
4769
+ if (req) {
4770
+ this.pendingRequests.delete(Number(payload.id));
4771
+ if (payload.error) {
4772
+ req.reject(new Error(payload.error.message || JSON.stringify(payload.error)));
4773
+ } else {
4774
+ req.resolve(payload.result);
4775
+ }
4776
+ }
4777
+ }
4778
+ } catch (e) {
4779
+ console.warn(`[MCPClient] Error parsing stdio JSON-RPC line from "${this.config.name}":`, e, "Line content:", line);
4780
+ }
4781
+ }
4782
+ }
4783
+ async connectSSE() {
4784
+ if (!this.config.url) {
4785
+ throw new Error(`[MCPClient] URL is required for sse transport on "${this.config.name}"`);
4786
+ }
4787
+ this.sseUrl = this.config.url;
4788
+ }
4789
+ async sendJsonRpc(method, params) {
4790
+ const id = this.getNextMessageId();
4791
+ const request = {
4792
+ jsonrpc: "2.0",
4793
+ id,
4794
+ method,
4795
+ params
4796
+ };
4797
+ if (this.config.transport === "stdio") {
4798
+ if (!this.childProcess || !this.childProcess.stdin) {
4799
+ throw new Error(`[MCPClient] Server "${this.config.name}" is not connected (stdio process missing)`);
4800
+ }
4801
+ return new Promise((resolve, reject) => {
4802
+ this.pendingRequests.set(id, { resolve, reject });
4803
+ this.childProcess.stdin.write(JSON.stringify(request) + "\n", "utf-8");
4181
4804
  });
4182
- } catch (error) {
4183
- const isMissing = error instanceof Error && error.message.includes("Cannot find module");
4184
- const hint = isMissing ? " Make sure 'langchain' and '@langchain/core' are installed:\n npm install langchain @langchain/core" : "";
4185
- throw new Error(
4186
- `[LangChainAgent] Failed to initialize.${hint}
4187
- ${error instanceof Error ? error.message : String(error)}`
4188
- );
4805
+ } else {
4806
+ if (!this.sseUrl) {
4807
+ throw new Error(`[MCPClient] Server "${this.config.name}" SSE URL is not initialized`);
4808
+ }
4809
+ const response = await fetch(this.sseUrl, {
4810
+ method: "POST",
4811
+ headers: { "Content-Type": "application/json" },
4812
+ body: JSON.stringify(request)
4813
+ });
4814
+ if (!response.ok) {
4815
+ throw new Error(`SSE JSON-RPC POST failed with status ${response.status}`);
4816
+ }
4817
+ const payload = await response.json();
4818
+ if (payload.error) {
4819
+ throw new Error(payload.error.message || JSON.stringify(payload.error));
4820
+ }
4821
+ return payload.result;
4822
+ }
4823
+ }
4824
+ async sendNotification(method, params) {
4825
+ var _a2;
4826
+ const notification = {
4827
+ jsonrpc: "2.0",
4828
+ method,
4829
+ params
4830
+ };
4831
+ if (this.config.transport === "stdio") {
4832
+ if ((_a2 = this.childProcess) == null ? void 0 : _a2.stdin) {
4833
+ this.childProcess.stdin.write(JSON.stringify(notification) + "\n", "utf-8");
4834
+ }
4835
+ } else if (this.sseUrl) {
4836
+ await fetch(this.sseUrl, {
4837
+ method: "POST",
4838
+ headers: { "Content-Type": "application/json" },
4839
+ body: JSON.stringify(notification)
4840
+ }).catch((err) => console.warn("[MCPClient] Failed to send notification over SSE:", err));
4189
4841
  }
4190
4842
  }
4191
4843
  /**
4192
- * Run the agentic flow.
4193
- *
4194
- * LangChain v1.x: invoke takes `{ messages: [...] }` instead of `{ input, chat_history }`.
4195
- * The agent returns `{ messages: [...] }` — the last message is the final answer.
4844
+ * List all tools offered by the MCP server.
4196
4845
  */
4197
- async run(input, chatHistory = []) {
4198
- var _a, _b, _c;
4199
- if (!this.agent) {
4200
- throw new Error("[LangChainAgent] Agent not initialized. Call initialize() first.");
4846
+ async listTools() {
4847
+ await this.connect();
4848
+ const result = await this.sendJsonRpc("tools/list", {});
4849
+ return (result == null ? void 0 : result.tools) || [];
4850
+ }
4851
+ /**
4852
+ * Execute a tool on the MCP server.
4853
+ */
4854
+ async callTool(name, args = {}) {
4855
+ await this.connect();
4856
+ return await this.sendJsonRpc("tools/call", { name, arguments: args });
4857
+ }
4858
+ disconnect() {
4859
+ this.initialized = false;
4860
+ this.pendingRequests.forEach((req) => req.reject(new Error("MCPClient disconnected")));
4861
+ this.pendingRequests.clear();
4862
+ if (this.childProcess) {
4863
+ try {
4864
+ this.childProcess.kill();
4865
+ } catch (e) {
4866
+ }
4867
+ this.childProcess = void 0;
4201
4868
  }
4202
- const { HumanMessage, AIMessage } = await import("@langchain/core/messages");
4203
- const historyMessages = chatHistory.map(
4204
- (m) => m.role === "user" ? new HumanMessage(m.content) : new AIMessage(m.content)
4869
+ }
4870
+ };
4871
+ var MCPRegistry = class {
4872
+ constructor(servers = []) {
4873
+ this.clients = [];
4874
+ this.clients = servers.map((cfg) => new MCPClient(cfg));
4875
+ }
4876
+ async getAllTools() {
4877
+ const list = [];
4878
+ await Promise.all(
4879
+ this.clients.map(async (client) => {
4880
+ try {
4881
+ const tools = await client.listTools();
4882
+ tools.forEach((t) => list.push({ serverName: client["config"].name, tool: t }));
4883
+ } catch (e) {
4884
+ console.warn(`[MCPRegistry] Failed to fetch tools from server "${client["config"].name}":`, e);
4885
+ }
4886
+ })
4205
4887
  );
4206
- const response = await this.agent.invoke({
4207
- messages: [...historyMessages, new HumanMessage(input)]
4208
- });
4209
- const lastMessage = (_a = response == null ? void 0 : response.messages) == null ? void 0 : _a.at(-1);
4210
- if (lastMessage && typeof lastMessage.content === "string") {
4211
- return lastMessage.content;
4888
+ return list;
4889
+ }
4890
+ async callTool(toolName, args = {}) {
4891
+ for (const client of this.clients) {
4892
+ try {
4893
+ const tools = await client.listTools();
4894
+ if (tools.some((t) => t.name === toolName)) {
4895
+ return await client.callTool(toolName, args);
4896
+ }
4897
+ } catch (e) {
4898
+ }
4212
4899
  }
4213
- if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
4214
- return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
4900
+ throw new Error(`[MCPRegistry] Tool "${toolName}" not found on any registered MCP server.`);
4901
+ }
4902
+ disconnectAll() {
4903
+ this.clients.forEach((c) => c.disconnect());
4904
+ }
4905
+ };
4906
+
4907
+ // src/core/MultiAgentCoordinator.ts
4908
+ var MultiAgentCoordinator = class {
4909
+ constructor(options) {
4910
+ var _a2;
4911
+ this.llmProvider = options.llmProvider;
4912
+ this.mcpRegistry = options.mcpRegistry;
4913
+ this.documentSearch = options.documentSearch;
4914
+ this.maxIterations = (_a2 = options.maxIterations) != null ? _a2 : 5;
4915
+ }
4916
+ /**
4917
+ * Run the multi-agent coordination loop synchronously and return the final response.
4918
+ */
4919
+ async run(question, history = []) {
4920
+ const generator = this.runStream(question, history);
4921
+ let finalReply = "";
4922
+ const sources = [];
4923
+ try {
4924
+ for (var iter = __forAwait(generator), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
4925
+ const chunk = temp.value;
4926
+ if (typeof chunk === "string") {
4927
+ finalReply += chunk;
4928
+ } else if (chunk && typeof chunk === "object") {
4929
+ if ("reply" in chunk && chunk.reply) {
4930
+ finalReply += chunk.reply;
4931
+ }
4932
+ if ("sources" in chunk && chunk.sources) {
4933
+ sources.push(...chunk.sources);
4934
+ }
4935
+ }
4936
+ }
4937
+ } catch (temp) {
4938
+ error = [temp];
4939
+ } finally {
4940
+ try {
4941
+ more && (temp = iter.return) && await temp.call(iter);
4942
+ } finally {
4943
+ if (error)
4944
+ throw error[0];
4945
+ }
4215
4946
  }
4216
- return String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
4947
+ return {
4948
+ reply: finalReply,
4949
+ sources
4950
+ };
4951
+ }
4952
+ /**
4953
+ * Run the multi-agent coordination loop as an async stream, yielding intermediate thought blocks and tool execution events.
4954
+ */
4955
+ runStream(_0) {
4956
+ return __asyncGenerator(this, arguments, function* (question, history = []) {
4957
+ const mcpTools = yield new __await(this.mcpRegistry.getAllTools());
4958
+ let systemPrompt = `You are a goal-driven supervisor agent coordinating a RAG search engine and external MCP servers to solve the user's task.
4959
+ You must think step-by-step before acting. Write your internal thinking process inside a \`<think>...</think>\` block first, then act or answer.
4960
+
4961
+ Available Tools:
4962
+ - document_search(query: string): Search the vector database and knowledge base for documents.
4963
+
4964
+ ${mcpTools.length > 0 ? "MCP Server Tools:" : ""}
4965
+ ${mcpTools.map((mt) => {
4966
+ var _a2;
4967
+ return `- ${mt.tool.name}(${JSON.stringify(((_a2 = mt.tool.inputSchema) == null ? void 0 : _a2.properties) || {})}): ${mt.tool.description || "No description provided."}`;
4968
+ }).join("\n")}
4969
+
4970
+ Tool Calling Protocol:
4971
+ If you need to call a tool, write:
4972
+ TOOL_CALL: <toolName>({ "argName": "value" })
4973
+ And then STOP generating immediately.
4974
+
4975
+ Once you have gathered enough information to fully satisfy the user's query, write your final response directly after the closing \`</think>\` block.
4976
+ `;
4977
+ const supervisorHistory = [
4978
+ { role: "system", content: systemPrompt },
4979
+ ...history,
4980
+ { role: "user", content: question }
4981
+ ];
4982
+ let iteration = 0;
4983
+ const allSources = [];
4984
+ while (iteration < this.maxIterations) {
4985
+ iteration++;
4986
+ const context = "";
4987
+ let fullModelResponse = "";
4988
+ let textBuffer = "";
4989
+ let inThinking = false;
4990
+ let toolCallDetected = null;
4991
+ if (!this.llmProvider.chatStream) {
4992
+ const reply = yield new __await(this.llmProvider.chat(supervisorHistory, context));
4993
+ fullModelResponse = reply;
4994
+ const thinkIndex = reply.indexOf("<think>");
4995
+ const endThinkIndex = reply.indexOf("</think>");
4996
+ let thinkingText = "";
4997
+ let answerText = reply;
4998
+ if (thinkIndex !== -1 && endThinkIndex !== -1) {
4999
+ thinkingText = reply.substring(thinkIndex + 7, endThinkIndex);
5000
+ answerText = reply.substring(endThinkIndex + 8);
5001
+ yield { type: "thinking", text: thinkingText };
5002
+ }
5003
+ const toolMatch = answerText.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
5004
+ if (toolMatch) {
5005
+ const toolName = toolMatch[1];
5006
+ const toolArgsStr = toolMatch[2];
5007
+ try {
5008
+ const toolArgs = JSON.parse(toolArgsStr.trim());
5009
+ toolCallDetected = { name: toolName, args: toolArgs };
5010
+ } catch (e) {
5011
+ console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
5012
+ }
5013
+ } else {
5014
+ yield answerText;
5015
+ }
5016
+ } else {
5017
+ const stream = this.llmProvider.chatStream(supervisorHistory, context);
5018
+ try {
5019
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
5020
+ const chunk = temp.value;
5021
+ fullModelResponse += chunk;
5022
+ textBuffer += chunk;
5023
+ if (!inThinking && textBuffer.includes("<think>")) {
5024
+ inThinking = true;
5025
+ const idx = textBuffer.indexOf("<think>");
5026
+ textBuffer = textBuffer.slice(idx + 7);
5027
+ }
5028
+ if (inThinking && textBuffer.includes("</think>")) {
5029
+ inThinking = false;
5030
+ const idx = textBuffer.indexOf("</think>");
5031
+ const thinkingDelta = textBuffer.slice(0, idx);
5032
+ yield { type: "thinking", text: thinkingDelta };
5033
+ textBuffer = textBuffer.slice(idx + 8);
5034
+ }
5035
+ if (inThinking && textBuffer.length > 0) {
5036
+ yield { type: "thinking", text: textBuffer };
5037
+ textBuffer = "";
5038
+ }
5039
+ if (!inThinking && textBuffer.includes("TOOL_CALL:")) {
5040
+ const idx = textBuffer.indexOf("TOOL_CALL:");
5041
+ const precedingText = textBuffer.slice(0, idx);
5042
+ if (precedingText.trim()) {
5043
+ yield precedingText;
5044
+ }
5045
+ textBuffer = textBuffer.slice(idx);
5046
+ }
5047
+ if (!inThinking && !textBuffer.includes("TOOL_CALL:") && textBuffer.length > 0) {
5048
+ yield textBuffer;
5049
+ textBuffer = "";
5050
+ }
5051
+ }
5052
+ } catch (temp) {
5053
+ error = [temp];
5054
+ } finally {
5055
+ try {
5056
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
5057
+ } finally {
5058
+ if (error)
5059
+ throw error[0];
5060
+ }
5061
+ }
5062
+ if (textBuffer.trim()) {
5063
+ const toolMatch = textBuffer.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
5064
+ if (toolMatch) {
5065
+ const toolName = toolMatch[1];
5066
+ const toolArgsStr = toolMatch[2];
5067
+ try {
5068
+ const toolArgs = JSON.parse(toolArgsStr.trim());
5069
+ toolCallDetected = { name: toolName, args: toolArgs };
5070
+ } catch (e) {
5071
+ console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
5072
+ }
5073
+ } else {
5074
+ yield textBuffer;
5075
+ }
5076
+ }
5077
+ }
5078
+ supervisorHistory.push({ role: "assistant", content: fullModelResponse });
5079
+ if (toolCallDetected) {
5080
+ const { name: toolName, args: toolArgs } = toolCallDetected;
5081
+ yield {
5082
+ type: "thinking",
5083
+ text: `
5084
+ [Agent Call] Executing tool "${toolName}" with parameters ${JSON.stringify(toolArgs)}...
5085
+ `
5086
+ };
5087
+ let toolResultText = "";
5088
+ try {
5089
+ if (toolName === "document_search") {
5090
+ const searchRes = yield new __await(this.documentSearch(toolArgs.query || ""));
5091
+ toolResultText = `document_search returned:
5092
+ ${searchRes.reply}
5093
+
5094
+ Sources count: ${searchRes.sources.length}`;
5095
+ if (searchRes.sources && searchRes.sources.length > 0) {
5096
+ allSources.push(...searchRes.sources);
5097
+ yield { reply: "", sources: searchRes.sources };
5098
+ }
5099
+ } else {
5100
+ const mcpRes = yield new __await(this.mcpRegistry.callTool(toolName, toolArgs));
5101
+ toolResultText = `MCP Tool "${toolName}" returned:
5102
+ ${JSON.stringify(mcpRes.content)}`;
5103
+ }
5104
+ } catch (err) {
5105
+ toolResultText = `Error calling tool "${toolName}": ${err.message}`;
5106
+ }
5107
+ supervisorHistory.push({
5108
+ role: "user",
5109
+ content: `TOOL_RESULT for ${toolName}:
5110
+ ${toolResultText}`
5111
+ });
5112
+ yield {
5113
+ type: "thinking",
5114
+ text: `[Agent Output] Tool "${toolName}" executed. Continuing reasoning...
5115
+ `
5116
+ };
5117
+ } else {
5118
+ break;
5119
+ }
5120
+ }
5121
+ });
4217
5122
  }
4218
5123
  };
4219
5124
 
@@ -4543,7 +5448,7 @@ var QueryProcessor = class {
4543
5448
  * @param validFields Optional list of known filterable fields to look for
4544
5449
  */
4545
5450
  static extractQueryFieldHints(question, validFields = []) {
4546
- var _a, _b, _c, _d;
5451
+ var _a2, _b, _c, _d;
4547
5452
  if (!question.trim()) return [];
4548
5453
  const hints = /* @__PURE__ */ new Map();
4549
5454
  const addHint = (value, field) => {
@@ -4623,7 +5528,7 @@ var QueryProcessor = class {
4623
5528
  ];
4624
5529
  for (const p of universalPatterns) {
4625
5530
  for (const match of question.matchAll(p.regex)) {
4626
- const val = p.group ? (_a = match[p.group]) != null ? _a : match[0] : match[0];
5531
+ const val = p.group ? (_a2 = match[p.group]) != null ? _a2 : match[0] : match[0];
4627
5532
  if (!val) continue;
4628
5533
  if (p.field) addHint(val, p.field);
4629
5534
  else addHint(val);
@@ -4847,11 +5752,11 @@ var LLMRouter = class {
4847
5752
  * When provided it is used directly as the 'default' role without re-constructing.
4848
5753
  */
4849
5754
  async initialize(prebuiltDefault) {
4850
- var _a;
5755
+ var _a2;
4851
5756
  const defaultModel = prebuiltDefault != null ? prebuiltDefault : LLMFactory.create(this.config.llm, this.config.embedding);
4852
5757
  this.models.set("default", defaultModel);
4853
5758
  const envFastModel = process.env.FAST_LLM_MODEL;
4854
- const providerFastDefault = (_a = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a : "";
5759
+ const providerFastDefault = (_a2 = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a2 : "";
4855
5760
  const fastModelName = envFastModel || providerFastDefault;
4856
5761
  if (fastModelName && fastModelName !== this.config.llm.model) {
4857
5762
  console.log(`[LLMRouter] Fast role \u2192 provider="${this.config.llm.provider}" model="${fastModelName}"`);
@@ -4870,8 +5775,8 @@ var LLMRouter = class {
4870
5775
  * Falls back to 'default' if the requested role is not registered.
4871
5776
  */
4872
5777
  get(role) {
4873
- var _a;
4874
- const provider = (_a = this.models.get(role)) != null ? _a : this.models.get("default");
5778
+ var _a2;
5779
+ const provider = (_a2 = this.models.get(role)) != null ? _a2 : this.models.get("default");
4875
5780
  if (!provider) {
4876
5781
  throw new Error(`[LLMRouter] No provider registered for role: "${role}". Did you call initialize()?`);
4877
5782
  }
@@ -4889,7 +5794,7 @@ var UITransformer = class _UITransformer {
4889
5794
  * Prefer `analyzeAndDecide()` in production.
4890
5795
  */
4891
5796
  static transform(userQuery, retrievedData, config, trainedSchema, intent) {
4892
- var _a, _b, _c;
5797
+ var _a2, _b, _c;
4893
5798
  if (!retrievedData || retrievedData.length === 0) {
4894
5799
  return this.createTextResponse("No data available", "No relevant data found for your query.");
4895
5800
  }
@@ -4909,7 +5814,7 @@ var UITransformer = class _UITransformer {
4909
5814
  return this.transformToBarChart(filteredData, profile, userQuery, resolvedIntent.visualizationHint === "ranking");
4910
5815
  }
4911
5816
  if (resolvedIntent.visualizationHint === "distribution") {
4912
- return (_a = this.transformToHistogram(profile, userQuery)) != null ? _a : this.transformToBarChart(filteredData, profile, userQuery);
5817
+ return (_a2 = this.transformToHistogram(profile, userQuery)) != null ? _a2 : this.transformToBarChart(filteredData, profile, userQuery);
4913
5818
  }
4914
5819
  if (resolvedIntent.visualizationHint === "correlation") {
4915
5820
  return (_b = this.transformToScatterPlot(profile, userQuery)) != null ? _b : this.transformToBarChart(filteredData, profile, userQuery);
@@ -5234,11 +6139,11 @@ ${schemaProfileText}` : ""}`;
5234
6139
  };
5235
6140
  }
5236
6141
  static transformToPieChart(data, profile, query = "") {
5237
- var _a;
6142
+ var _a2;
5238
6143
  const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
5239
6144
  const categories = dimension ? Array.from(new Set(profile.records.map((record) => {
5240
- var _a2;
5241
- return String((_a2 = record.fields[dimension.key]) != null ? _a2 : "");
6145
+ var _a3;
6146
+ return String((_a3 = record.fields[dimension.key]) != null ? _a3 : "");
5242
6147
  }).filter(Boolean))) : this.detectCategories(data);
5243
6148
  if (categories.length === 0) return null;
5244
6149
  const categoryData = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key) : this.aggregateByCategory(data, categories);
@@ -5248,7 +6153,7 @@ ${schemaProfileText}` : ""}`;
5248
6153
  });
5249
6154
  return {
5250
6155
  type: "pie_chart",
5251
- title: `Distribution by ${(_a = dimension == null ? void 0 : dimension.label) != null ? _a : "Category"}`,
6156
+ title: `Distribution by ${(_a2 = dimension == null ? void 0 : dimension.label) != null ? _a2 : "Category"}`,
5252
6157
  description: `Showing breakdown across ${pieData.length} categories`,
5253
6158
  data: pieData
5254
6159
  };
@@ -5258,8 +6163,8 @@ ${schemaProfileText}` : ""}`;
5258
6163
  const valueField = profile.numericFields[0];
5259
6164
  const buckets = /* @__PURE__ */ new Map();
5260
6165
  profile.records.forEach((record) => {
5261
- var _a, _b, _c;
5262
- const timestamp = String((_a = record.fields[dateField.key]) != null ? _a : "");
6166
+ var _a2, _b, _c;
6167
+ const timestamp = String((_a2 = record.fields[dateField.key]) != null ? _a2 : "");
5263
6168
  const value = (_b = this.toFiniteNumber(record.fields[valueField.key])) != null ? _b : 0;
5264
6169
  buckets.set(timestamp, ((_c = buckets.get(timestamp)) != null ? _c : 0) + value);
5265
6170
  });
@@ -5272,23 +6177,23 @@ ${schemaProfileText}` : ""}`;
5272
6177
  };
5273
6178
  }
5274
6179
  static transformToBarChart(data, profile, query = "", horizontal = false) {
5275
- var _a;
6180
+ var _a2;
5276
6181
  const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
5277
6182
  const measure = profile ? this.selectNumericField(profile, query) : void 0;
5278
6183
  const aggregate = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key, measure == null ? void 0 : measure.key) : this.aggregateByCategory(data, this.detectCategories(data));
5279
6184
  const barData = Object.entries(aggregate).map(([category, value]) => ({ category, value: Number(value) })).sort((a, b) => horizontal ? b.value - a.value : 0).slice(0, 12);
5280
6185
  const fallbackData = barData.length > 0 ? barData : data.slice(0, 12).map((item, index) => {
5281
- var _a2, _b, _c, _d, _e;
6186
+ var _a3, _b, _c, _d, _e;
5282
6187
  const meta = item.metadata || {};
5283
6188
  const label = String(
5284
- (_c = (_b = (_a2 = this.getDynamicVal(meta, "name")) != null ? _a2 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
6189
+ (_c = (_b = (_a3 = this.getDynamicVal(meta, "name")) != null ? _a3 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
5285
6190
  );
5286
6191
  const value = (_e = (_d = this.extractNumericValue(meta)) != null ? _d : item.score) != null ? _e : 0;
5287
6192
  return { category: label, value: Number(value) };
5288
6193
  });
5289
6194
  return {
5290
6195
  type: horizontal ? "horizontal_bar" : "bar_chart",
5291
- title: dimension ? `${(_a = measure == null ? void 0 : measure.label) != null ? _a : "Count"} by ${dimension.label}` : "Comparison",
6196
+ title: dimension ? `${(_a2 = measure == null ? void 0 : measure.label) != null ? _a2 : "Count"} by ${dimension.label}` : "Comparison",
5292
6197
  description: `Showing ${fallbackData.length} comparable values`,
5293
6198
  data: fallbackData
5294
6199
  };
@@ -5323,11 +6228,11 @@ ${schemaProfileText}` : ""}`;
5323
6228
  if (fields.length < 2) return null;
5324
6229
  const [xField, yField] = fields;
5325
6230
  const points = profile.records.map((record) => {
5326
- var _a;
6231
+ var _a2;
5327
6232
  const x = this.toFiniteNumber(record.fields[xField.key]);
5328
6233
  const y = this.toFiniteNumber(record.fields[yField.key]);
5329
6234
  if (x === null || y === null) return null;
5330
- return { x, y, label: String((_a = this.getRecordLabel(record)) != null ? _a : record.id) };
6235
+ return { x, y, label: String((_a2 = this.getRecordLabel(record)) != null ? _a2 : record.id) };
5331
6236
  }).filter((point) => point !== null).slice(0, 100);
5332
6237
  if (points.length === 0) return null;
5333
6238
  return {
@@ -5357,9 +6262,9 @@ ${schemaProfileText}` : ""}`;
5357
6262
  static transformToRadarChart(data) {
5358
6263
  const attributeMap = {};
5359
6264
  data.forEach((item) => {
5360
- var _a, _b, _c;
6265
+ var _a2, _b, _c;
5361
6266
  const meta = item.metadata || {};
5362
- const seriesName = String((_c = (_b = (_a = meta.name) != null ? _a : meta.product) != null ? _b : item.id) != null ? _c : "Item");
6267
+ const seriesName = String((_c = (_b = (_a2 = meta.name) != null ? _a2 : meta.product) != null ? _b : item.id) != null ? _c : "Item");
5363
6268
  Object.entries(meta).forEach(([key, val]) => {
5364
6269
  if (typeof val === "number" && !["price", "id"].includes(key.toLowerCase())) {
5365
6270
  if (!attributeMap[key]) attributeMap[key] = {};
@@ -5441,22 +6346,22 @@ ${schemaProfileText}` : ""}`;
5441
6346
  return null;
5442
6347
  }
5443
6348
  static normalizeTransformation(payload) {
5444
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
6349
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j;
5445
6350
  if (!payload || typeof payload !== "object") return null;
5446
6351
  const p = payload;
5447
6352
  const type = this.normalizeVisualizationType(
5448
- String((_c = (_b = (_a = p.type) != null ? _a : p.view) != null ? _b : p.chartType) != null ? _c : "")
6353
+ String((_c = (_b = (_a2 = p.type) != null ? _a2 : p.view) != null ? _b : p.chartType) != null ? _c : "")
5449
6354
  );
5450
6355
  if (!type) return null;
5451
6356
  const title = String((_e = (_d = p.title) != null ? _d : p.heading) != null ? _e : "Visualization");
5452
6357
  const description = p.description ? String(p.description) : void 0;
5453
- 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;
6358
+ 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;
5454
6359
  const data = type === "text" && typeof rawData === "string" ? { content: rawData } : rawData;
5455
6360
  const transformation = { type, title, description, data };
5456
6361
  return this.validateTransformation(transformation) ? transformation : null;
5457
6362
  }
5458
6363
  static normalizeVisualizationType(type) {
5459
- var _a;
6364
+ var _a2;
5460
6365
  const mapping = {
5461
6366
  pie: "pie_chart",
5462
6367
  pie_chart: "pie_chart",
@@ -5484,7 +6389,7 @@ ${schemaProfileText}` : ""}`;
5484
6389
  product_carousel: "product_carousel",
5485
6390
  carousel: "carousel"
5486
6391
  };
5487
- return (_a = mapping[type.toLowerCase()]) != null ? _a : null;
6392
+ return (_a2 = mapping[type.toLowerCase()]) != null ? _a2 : null;
5488
6393
  }
5489
6394
  static validateTransformation(t) {
5490
6395
  const { type, data } = t;
@@ -5686,16 +6591,16 @@ ${schemaProfileText}` : ""}`;
5686
6591
  return null;
5687
6592
  }
5688
6593
  static selectDimensionField(profile, query) {
5689
- var _a, _b;
6594
+ var _a2, _b;
5690
6595
  const productCategory = profile.categoricalFields.find(
5691
6596
  (field) => /category|department|collection|type|group|segment|region|country|state|city/i.test(field.key)
5692
6597
  );
5693
6598
  const ranked = this.rankFieldsByQuery(profile.categoricalFields, query);
5694
- return (_b = (_a = ranked[0]) != null ? _a : productCategory) != null ? _b : profile.categoricalFields[0];
6599
+ return (_b = (_a2 = ranked[0]) != null ? _a2 : productCategory) != null ? _b : profile.categoricalFields[0];
5695
6600
  }
5696
6601
  static selectNumericField(profile, query) {
5697
- var _a;
5698
- return (_a = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a : profile.numericFields[0];
6602
+ var _a2;
6603
+ return (_a2 = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a2 : profile.numericFields[0];
5699
6604
  }
5700
6605
  static rankFieldsByQuery(fields, query) {
5701
6606
  const q = query.toLowerCase();
@@ -5724,8 +6629,8 @@ ${schemaProfileText}` : ""}`;
5724
6629
  static aggregateProfileByDimension(profile, dimensionKey, measureKey) {
5725
6630
  const result = {};
5726
6631
  profile.records.forEach((record) => {
5727
- var _a, _b, _c;
5728
- const category = String((_a = record.fields[dimensionKey]) != null ? _a : "Other").trim() || "Other";
6632
+ var _a2, _b, _c;
6633
+ const category = String((_a2 = record.fields[dimensionKey]) != null ? _a2 : "Other").trim() || "Other";
5729
6634
  const value = measureKey ? (_b = this.toFiniteNumber(record.fields[measureKey])) != null ? _b : 0 : 1;
5730
6635
  result[category] = ((_c = result[category]) != null ? _c : 0) + value;
5731
6636
  });
@@ -5804,8 +6709,8 @@ ${schemaProfileText}` : ""}`;
5804
6709
  static aggregateByCategory(data, categories) {
5805
6710
  const result = Object.fromEntries(categories.map((c) => [c, 0]));
5806
6711
  data.forEach((item) => {
5807
- var _a;
5808
- const cat = (_a = this.getProductCategory(item)) != null ? _a : "Other";
6712
+ var _a2;
6713
+ const cat = (_a2 = this.getProductCategory(item)) != null ? _a2 : "Other";
5809
6714
  if (Object.prototype.hasOwnProperty.call(result, cat)) result[cat]++;
5810
6715
  else result["Other"] = (result["Other"] || 0) + 1;
5811
6716
  });
@@ -5813,17 +6718,17 @@ ${schemaProfileText}` : ""}`;
5813
6718
  }
5814
6719
  static extractTimeSeriesData(data) {
5815
6720
  return data.map((item) => {
5816
- var _a, _b, _c, _d, _e;
6721
+ var _a2, _b, _c, _d, _e;
5817
6722
  const meta = item.metadata || {};
5818
6723
  return {
5819
- timestamp: (_b = (_a = meta.timestamp) != null ? _a : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
6724
+ timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
5820
6725
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
5821
6726
  label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
5822
6727
  };
5823
6728
  });
5824
6729
  }
5825
6730
  static extractNumericValue(meta) {
5826
- var _a;
6731
+ var _a2;
5827
6732
  const preferredKeys = [
5828
6733
  "value",
5829
6734
  "count",
@@ -5838,7 +6743,7 @@ ${schemaProfileText}` : ""}`;
5838
6743
  "price"
5839
6744
  ];
5840
6745
  for (const key of preferredKeys) {
5841
- const raw = (_a = resolveMetadataValue(meta, key)) != null ? _a : meta[key];
6746
+ const raw = (_a2 = resolveMetadataValue(meta, key)) != null ? _a2 : meta[key];
5842
6747
  const value = typeof raw === "number" ? raw : Number(String(raw != null ? raw : "").replace(/[$,% ,]/g, ""));
5843
6748
  if (Number.isFinite(value)) return value;
5844
6749
  }
@@ -5984,8 +6889,8 @@ ${schemaProfileText}` : ""}`;
5984
6889
  let inStock = 0;
5985
6890
  let outOfStock = 0;
5986
6891
  data.forEach((d) => {
5987
- var _a, _b;
5988
- const cat = (_a = this.getProductCategory(d)) != null ? _a : "Other";
6892
+ var _a2, _b;
6893
+ const cat = (_a2 = this.getProductCategory(d)) != null ? _a2 : "Other";
5989
6894
  if (cat === category) {
5990
6895
  const quantity = (_b = this.extractStockQuantity(d)) != null ? _b : 1;
5991
6896
  if (this.determineStockStatus(d)) inStock += quantity;
@@ -6029,9 +6934,9 @@ ${schemaProfileText}` : ""}`;
6029
6934
  }
6030
6935
  // ─── Product Extraction ───────────────────────────────────────────────────
6031
6936
  static getDynamicVal(meta, uiKey, config, trainedSchema) {
6032
- var _a;
6937
+ var _a2;
6033
6938
  if (!meta) return void 0;
6034
- const mapping = (_a = config == null ? void 0 : config.rag) == null ? void 0 : _a.uiMapping;
6939
+ const mapping = (_a2 = config == null ? void 0 : config.rag) == null ? void 0 : _a2.uiMapping;
6035
6940
  if ((mapping == null ? void 0 : mapping[uiKey]) && meta[mapping[uiKey]] !== void 0) return meta[mapping[uiKey]];
6036
6941
  if (trainedSchema && typeof trainedSchema === "object") {
6037
6942
  const trainedKey = trainedSchema[uiKey];
@@ -6040,13 +6945,13 @@ ${schemaProfileText}` : ""}`;
6040
6945
  return resolveMetadataValue(meta, uiKey);
6041
6946
  }
6042
6947
  static extractProductInfo(item, config, trainedSchema) {
6043
- var _a;
6948
+ var _a2;
6044
6949
  const meta = item.metadata || {};
6045
6950
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
6046
6951
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
6047
6952
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
6048
6953
  const description = this.cleanProductDescription(
6049
- (_a = this.extractProductDescriptionFromContent(item.content)) != null ? _a : this.getProductDescriptionValue(meta, config, trainedSchema)
6954
+ (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
6050
6955
  );
6051
6956
  if (name || this.isProductData(item)) {
6052
6957
  let finalName = name ? String(name) : void 0;
@@ -6154,10 +7059,10 @@ RULES:
6154
7059
  }
6155
7060
  static buildContextSummary(sources, maxChars = 6e3) {
6156
7061
  const items = sources.map((s, i) => {
6157
- var _a, _b, _c, _d;
7062
+ var _a2, _b, _c, _d;
6158
7063
  return {
6159
7064
  index: i + 1,
6160
- content: (_b = (_a = s.content) == null ? void 0 : _a.substring(0, 400)) != null ? _b : "",
7065
+ content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
6161
7066
  metadata: (_c = s.metadata) != null ? _c : {},
6162
7067
  score: (_d = s.score) != null ? _d : 0
6163
7068
  };
@@ -6350,9 +7255,11 @@ var Pipeline = class {
6350
7255
  /** LRU-bounded cache: avoids re-embedding identical queries within the same process. */
6351
7256
  this.embeddingCache = new LRUEmbeddingCache(500);
6352
7257
  this.initialised = false;
6353
- var _a, _b, _c, _d, _e;
7258
+ /** Namespace-specific static cold context cache for CAG */
7259
+ this.coldContexts = /* @__PURE__ */ new Map();
7260
+ var _a2, _b, _c, _d, _e;
6354
7261
  this.chunker = new DocumentChunker(
6355
- (_b = (_a = config.rag) == null ? void 0 : _a.chunkSize) != null ? _b : 1e3,
7262
+ (_b = (_a2 = config.rag) == null ? void 0 : _a2.chunkSize) != null ? _b : 1e3,
6356
7263
  (_d = (_c = config.rag) == null ? void 0 : _c.chunkOverlap) != null ? _d : 200
6357
7264
  );
6358
7265
  if (((_e = config.rag) == null ? void 0 : _e.chunkingStrategy) === "llamaindex") {
@@ -6368,7 +7275,7 @@ var Pipeline = class {
6368
7275
  return this.initialised ? this.llmProvider : void 0;
6369
7276
  }
6370
7277
  async initialize() {
6371
- var _a;
7278
+ var _a2, _b, _c;
6372
7279
  if (this.initialised) return;
6373
7280
  const chartInstruction = `You are a helpful assistant. Use the provided context to answer questions accurately.
6374
7281
 
@@ -6411,12 +7318,47 @@ var Pipeline = class {
6411
7318
  this.entityExtractor = new EntityExtractor(this.llmProvider);
6412
7319
  }
6413
7320
  await this.vectorDB.initialize();
6414
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic") {
7321
+ if (((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) {
7322
+ this.mcpRegistry = new MCPRegistry(this.config.mcpServers || []);
7323
+ this.multiAgentCoordinator = new MultiAgentCoordinator({
7324
+ llmProvider: this.llmProvider,
7325
+ mcpRegistry: this.mcpRegistry,
7326
+ documentSearch: async (query) => {
7327
+ return this.runNormalQuery(query);
7328
+ }
7329
+ });
6415
7330
  this.agent = new LangChainAgent(this, this.config);
6416
7331
  await this.agent.initialize(this.llmProvider);
6417
7332
  }
7333
+ if ((_c = (_b = this.config.rag) == null ? void 0 : _b.cag) == null ? void 0 : _c.enabled) {
7334
+ await this.loadColdContext(this.config.projectId);
7335
+ }
6418
7336
  this.initialised = true;
6419
7337
  }
7338
+ async loadColdContext(ns) {
7339
+ var _a2, _b;
7340
+ const cagConfig = (_a2 = this.config.rag) == null ? void 0 : _a2.cag;
7341
+ if (!cagConfig || !cagConfig.enabled) return;
7342
+ try {
7343
+ const coldNs = cagConfig.coldNamespace || ns;
7344
+ const limit = (_b = cagConfig.coldLimit) != null ? _b : 20;
7345
+ const queryText = cagConfig.coldQuery || "documentation";
7346
+ const queryVector = await this.embeddingProvider.embed(queryText, { taskType: "query" });
7347
+ const coldMatches = await this.vectorDB.query(queryVector, limit, coldNs);
7348
+ if (coldMatches.length > 0) {
7349
+ const formatted = coldMatches.map((m, i) => `[Cold Source ${i + 1}]
7350
+ ${m.content}`).join("\n\n---\n\n");
7351
+ this.coldContexts.set(ns, formatted);
7352
+ console.log(`[Pipeline] Cold RAG (CAG) loaded ${coldMatches.length} documents into cached context for namespace: ${ns}`);
7353
+ } else {
7354
+ this.coldContexts.set(ns, "No cold context found.");
7355
+ console.warn(`[Pipeline] Cold RAG (CAG) initialized but no documents were found in namespace: ${coldNs}`);
7356
+ }
7357
+ } catch (err) {
7358
+ console.error(`[Pipeline] Failed to load Cold RAG (CAG) context for namespace ${ns}:`, err);
7359
+ this.coldContexts.set(ns, "Failed to load cold context.");
7360
+ }
7361
+ }
6420
7362
  /**
6421
7363
  * Ingest documents with automatic chunking, embedding, and batch upsert.
6422
7364
  */
@@ -6448,12 +7390,12 @@ var Pipeline = class {
6448
7390
  }
6449
7391
  /** Step 1: Chunk the document content. */
6450
7392
  async prepareChunks(doc) {
6451
- var _a, _b;
7393
+ var _a2, _b;
6452
7394
  if (this.llamaIngestor) {
6453
7395
  return this.llamaIngestor.chunk(doc.content, {
6454
7396
  docId: doc.docId,
6455
7397
  metadata: doc.metadata,
6456
- chunkSize: (_a = this.config.rag) == null ? void 0 : _a.chunkSize,
7398
+ chunkSize: (_a2 = this.config.rag) == null ? void 0 : _a2.chunkSize,
6457
7399
  chunkOverlap: (_b = this.config.rag) == null ? void 0 : _b.chunkOverlap
6458
7400
  });
6459
7401
  }
@@ -6475,7 +7417,7 @@ var Pipeline = class {
6475
7417
  embedBatchOptions
6476
7418
  );
6477
7419
  if (vectors.length !== chunks.length) {
6478
- throw new Error(
7420
+ throw new EmbeddingFailedException(
6479
7421
  `[Pipeline] Embedding mismatch: got ${vectors.length} vectors for ${chunks.length} chunks. Check embedding provider logs for individual chunk failures.`
6480
7422
  );
6481
7423
  }
@@ -6524,12 +7466,37 @@ var Pipeline = class {
6524
7466
  extractionOptions
6525
7467
  );
6526
7468
  }
7469
+ async runNormalQuery(question, history = [], namespace) {
7470
+ const stream = this.askStreamInternal(question, history, namespace);
7471
+ let reply = "";
7472
+ let sources = [];
7473
+ try {
7474
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
7475
+ const chunk = temp.value;
7476
+ if (typeof chunk === "string") {
7477
+ reply += chunk;
7478
+ } else if (typeof chunk === "object" && chunk !== null) {
7479
+ if ("reply" in chunk && chunk.reply) reply += chunk.reply;
7480
+ if ("sources" in chunk && chunk.sources) sources = chunk.sources;
7481
+ }
7482
+ }
7483
+ } catch (temp) {
7484
+ error = [temp];
7485
+ } finally {
7486
+ try {
7487
+ more && (temp = iter.return) && await temp.call(iter);
7488
+ } finally {
7489
+ if (error)
7490
+ throw error[0];
7491
+ }
7492
+ }
7493
+ return { reply, sources };
7494
+ }
6527
7495
  async ask(question, history = [], namespace) {
6528
- var _a;
7496
+ var _a2;
6529
7497
  await this.initialize();
6530
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic" && this.agent) {
6531
- const agentReply = await this.agent.run(question, history);
6532
- return { reply: agentReply, sources: [] };
7498
+ if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
7499
+ return await this.multiAgentCoordinator.run(question, history);
6533
7500
  }
6534
7501
  const stream = this.askStream(question, history, namespace);
6535
7502
  let reply = "";
@@ -6561,6 +7528,47 @@ var Pipeline = class {
6561
7528
  }
6562
7529
  return { reply, sources, graphData, ui_transformation: uiTransformation, trace };
6563
7530
  }
7531
+ askStream(_0) {
7532
+ return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
7533
+ var _a2;
7534
+ yield new __await(this.initialize());
7535
+ if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
7536
+ const stream2 = this.multiAgentCoordinator.runStream(question, history);
7537
+ try {
7538
+ for (var iter = __forAwait(stream2), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
7539
+ const chunk = temp.value;
7540
+ yield chunk;
7541
+ }
7542
+ } catch (temp) {
7543
+ error = [temp];
7544
+ } finally {
7545
+ try {
7546
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
7547
+ } finally {
7548
+ if (error)
7549
+ throw error[0];
7550
+ }
7551
+ }
7552
+ return;
7553
+ }
7554
+ const stream = this.askStreamInternal(question, history, namespace);
7555
+ try {
7556
+ for (var iter2 = __forAwait(stream), more2, temp2, error2; more2 = !(temp2 = yield new __await(iter2.next())).done; more2 = false) {
7557
+ const chunk = temp2.value;
7558
+ yield chunk;
7559
+ }
7560
+ } catch (temp2) {
7561
+ error2 = [temp2];
7562
+ } finally {
7563
+ try {
7564
+ more2 && (temp2 = iter2.return) && (yield new __await(temp2.call(iter2)));
7565
+ } finally {
7566
+ if (error2)
7567
+ throw error2[0];
7568
+ }
7569
+ }
7570
+ });
7571
+ }
6564
7572
  /**
6565
7573
  * High-performance streaming RAG flow.
6566
7574
  * Yields text chunks first, then the retrieval metadata + observability trace at the end.
@@ -6571,12 +7579,12 @@ var Pipeline = class {
6571
7579
  * - UITransformation is computed after text streaming and emitted with metadata
6572
7580
  * - SchemaMapper.train runs while answer generation streams
6573
7581
  */
6574
- askStream(_0) {
7582
+ askStreamInternal(_0) {
6575
7583
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
6576
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
7584
+ 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;
6577
7585
  yield new __await(this.initialize());
6578
7586
  const ns = namespace != null ? namespace : this.config.projectId;
6579
- const topK = (_b = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
7587
+ const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
6580
7588
  const scoreThreshold = (_d = (_c = this.config.rag) == null ? void 0 : _c.scoreThreshold) != null ? _d : 0.3;
6581
7589
  const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
6582
7590
  const requestStart = performance.now();
@@ -6589,7 +7597,7 @@ var Pipeline = class {
6589
7597
  }
6590
7598
  const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
6591
7599
  const filter = QueryProcessor.buildQueryFilter(question, hints);
6592
- const numericPredicates = QueryProcessor.extractNumericPredicates(question, (_g = this.config.rag) == null ? void 0 : _g.filterableFields);
7600
+ const numericPredicates = QueryProcessor.extractNumericPredicates(question, (_g2 = this.config.rag) == null ? void 0 : _g2.filterableFields);
6593
7601
  if (numericPredicates.length > 0) {
6594
7602
  filter.__numericPredicates = numericPredicates;
6595
7603
  }
@@ -6655,6 +7663,32 @@ ${graphContext}
6655
7663
  VECTOR CONTEXT:
6656
7664
  ${context}`;
6657
7665
  }
7666
+ if ((_n = (_m = this.config.rag) == null ? void 0 : _m.cag) == null ? void 0 : _n.enabled) {
7667
+ if (!this.coldContexts.has(ns)) {
7668
+ yield new __await(this.loadColdContext(ns));
7669
+ }
7670
+ const coldContext = this.coldContexts.get(ns);
7671
+ if (coldContext && coldContext !== "No cold context found." && coldContext !== "Failed to load cold context.") {
7672
+ context = `COLD CONTEXT (STATIC KNOWLEDGE):
7673
+ ${coldContext}
7674
+
7675
+ RETRIEVED HOT CONTEXT (REAL-TIME KNOWLEDGE):
7676
+ ${context}`;
7677
+ }
7678
+ }
7679
+ yield {
7680
+ reply: "",
7681
+ sources: sources.map((s) => {
7682
+ var _a3;
7683
+ return {
7684
+ id: s.id,
7685
+ score: s.score,
7686
+ content: s.content,
7687
+ metadata: (_a3 = s.metadata) != null ? _a3 : {},
7688
+ namespace: ns
7689
+ };
7690
+ })
7691
+ };
6658
7692
  const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
6659
7693
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
6660
7694
  if (allMetadataKeys.length > 0 && !cachedSchema) {
@@ -6682,10 +7716,10 @@ ${context}`;
6682
7716
  let hallucinationScoringPromise = Promise.resolve(void 0);
6683
7717
  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.)";
6684
7718
  const isClaude37 = this.config.llm.model.includes("claude-3-7-sonnet");
6685
- 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);
7719
+ 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);
6686
7720
  const modelNameLower = this.config.llm.model.toLowerCase();
6687
7721
  const isReasoningModel = modelNameLower.includes("-r1") || modelNameLower.includes("deepseek-r1") || modelNameLower.includes("reasoning") || modelNameLower.includes("thinking");
6688
- 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);
7722
+ 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);
6689
7723
  let finalRestrictionSuffix = restrictionSuffix;
6690
7724
  if (isSimulatedThinking) {
6691
7725
  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.`)";
@@ -6693,7 +7727,7 @@ ${context}`;
6693
7727
  const hardenedHistory = [...history];
6694
7728
  const userQuestion = { role: "user", content: question + finalRestrictionSuffix };
6695
7729
  const messages = [...hardenedHistory, userQuestion];
6696
- const systemPrompt = (_s = this.config.llm.systemPrompt) != null ? _s : "";
7730
+ const systemPrompt = (_u = this.config.llm.systemPrompt) != null ? _u : "";
6697
7731
  const userPrompt = messages.map((m) => `${m.role}: ${m.content}`).join("\n");
6698
7732
  let fullReply = "";
6699
7733
  let thinkingText = "";
@@ -6804,7 +7838,7 @@ ${context}`;
6804
7838
  }
6805
7839
  yield fullReply;
6806
7840
  }
6807
- 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;
7841
+ 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;
6808
7842
  if (runHallucination) {
6809
7843
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
6810
7844
  }
@@ -6813,7 +7847,7 @@ ${context}`;
6813
7847
  const latency = {
6814
7848
  embedMs: Math.round(embedMs),
6815
7849
  retrieveMs: Math.round(retrieveMs),
6816
- rerankMs: ((_v = this.config.rag) == null ? void 0 : _v.useReranking) ? Math.round(rerankMs) : void 0,
7850
+ rerankMs: ((_x = this.config.rag) == null ? void 0 : _x.useReranking) ? Math.round(rerankMs) : void 0,
6817
7851
  generateMs: Math.round(generateMs),
6818
7852
  totalMs: Math.round(totalMs)
6819
7853
  };
@@ -6826,33 +7860,63 @@ ${context}`;
6826
7860
  totalTokens: promptTokens + completionTokens,
6827
7861
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
6828
7862
  };
7863
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
6829
7864
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
6830
7865
  uiTransformationPromise,
6831
- hallucinationScoringPromise
7866
+ awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
6832
7867
  ]));
6833
- const trace = __spreadValues({
7868
+ const buildTrace = (hScore) => __spreadValues({
6834
7869
  requestId,
6835
7870
  query: question,
6836
7871
  rewrittenQuery,
6837
7872
  systemPrompt,
6838
7873
  userPrompt: question + finalRestrictionSuffix,
6839
7874
  chunks: sources.map((s) => {
6840
- var _a2;
7875
+ var _a3;
6841
7876
  return {
6842
7877
  id: s.id,
6843
7878
  score: s.score,
6844
7879
  content: s.content,
6845
- metadata: (_a2 = s.metadata) != null ? _a2 : {},
7880
+ metadata: (_a3 = s.metadata) != null ? _a3 : {},
6846
7881
  namespace: ns
6847
7882
  };
6848
7883
  }),
6849
7884
  latency,
6850
7885
  tokens,
6851
7886
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
6852
- }, hallucinationResult ? {
6853
- hallucinationScore: hallucinationResult.score,
6854
- hallucinationReason: hallucinationResult.reason
7887
+ }, hScore ? {
7888
+ hallucinationScore: hScore.score,
7889
+ hallucinationReason: hScore.reason
6855
7890
  } : {});
7891
+ const trace = buildTrace(hallucinationResult);
7892
+ if ((_z = this.config.telemetry) == null ? void 0 : _z.enabled) {
7893
+ const telemetryUrl = this.config.telemetry.url || "/api/telemetry";
7894
+ const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
7895
+ (async () => {
7896
+ try {
7897
+ let finalTrace = trace;
7898
+ if (!awaitHallucination && runHallucination) {
7899
+ const backgroundScoreResult = await hallucinationScoringPromise;
7900
+ if (backgroundScoreResult) {
7901
+ finalTrace = buildTrace(backgroundScoreResult);
7902
+ }
7903
+ }
7904
+ await fetch(absoluteUrl, {
7905
+ method: "POST",
7906
+ headers: {
7907
+ "Content-Type": "application/json"
7908
+ },
7909
+ body: JSON.stringify({
7910
+ trace: finalTrace,
7911
+ licenseKey: this.config.licenseKey,
7912
+ projectId: ns
7913
+ })
7914
+ });
7915
+ } catch (err) {
7916
+ console.warn(`[Pipeline Telemetry] Failed to send trace async to ${absoluteUrl}:`, err.message);
7917
+ }
7918
+ })();
7919
+ }
6856
7920
  yield {
6857
7921
  reply: "",
6858
7922
  sources,
@@ -6872,7 +7936,7 @@ ${context}`;
6872
7936
  * Uses an LRU-bounded embedding cache to avoid re-embedding the same query.
6873
7937
  */
6874
7938
  async generateUiTransformation(question, sources, cachedSchema, forceDeterministic = false) {
6875
- var _a;
7939
+ var _a2;
6876
7940
  if (!sources || sources.length === 0) {
6877
7941
  return UITransformer.transform(question, sources, this.config, cachedSchema);
6878
7942
  }
@@ -6886,7 +7950,7 @@ ${context}`;
6886
7950
  );
6887
7951
  }
6888
7952
  const isLocalProvider = this.config.llm.provider === "ollama";
6889
- const disableLlmUiTransform = ((_a = this.config.llm.options) == null ? void 0 : _a.disableLlmUiTransform) === true;
7953
+ const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
6890
7954
  if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
6891
7955
  return UITransformer.transform(question, sources, this.config, cachedSchema);
6892
7956
  }
@@ -6904,9 +7968,9 @@ ${context}`;
6904
7968
  const value = this.resolveNumericPredicateValue(source, predicate);
6905
7969
  return value !== null && this.matchesNumericPredicate(value, predicate);
6906
7970
  })).sort((a, b) => {
6907
- var _a, _b;
7971
+ var _a2, _b;
6908
7972
  const primary = predicates[0];
6909
- const aValue = (_a = this.resolveNumericPredicateValue(a, primary)) != null ? _a : 0;
7973
+ const aValue = (_a2 = this.resolveNumericPredicateValue(a, primary)) != null ? _a2 : 0;
6910
7974
  const bValue = (_b = this.resolveNumericPredicateValue(b, primary)) != null ? _b : 0;
6911
7975
  return primary.operator === "lt" || primary.operator === "lte" ? aValue - bValue : bValue - aValue;
6912
7976
  });
@@ -6978,8 +8042,8 @@ ${context}`;
6978
8042
  return Number.isFinite(numeric) ? numeric : null;
6979
8043
  }
6980
8044
  async retrieve(query, options) {
6981
- var _a, _b, _c, _d, _e, _f, _g;
6982
- const ns = (_a = options.namespace) != null ? _a : this.config.projectId;
8045
+ var _a2, _b, _c, _d, _e, _f, _g2;
8046
+ const ns = (_a2 = options.namespace) != null ? _a2 : this.config.projectId;
6983
8047
  const topK = (_b = options.topK) != null ? _b : 5;
6984
8048
  const cacheKey = `${ns}::${query}`;
6985
8049
  let queryVector = this.embeddingCache.get(cacheKey);
@@ -7011,7 +8075,7 @@ ${context}`;
7011
8075
  ) : [];
7012
8076
  const resolvedSources = [];
7013
8077
  for (const source of sources) {
7014
- const parentId = (_g = source.metadata) == null ? void 0 : _g.parent_id;
8078
+ const parentId = (_g2 = source.metadata) == null ? void 0 : _g2.parent_id;
7015
8079
  if (parentId) {
7016
8080
  console.log(`[Pipeline] Multi-Vector: Found child chunk. Parent ID: ${parentId}`);
7017
8081
  resolvedSources.push(source);
@@ -7071,18 +8135,100 @@ Suggestions:`;
7071
8135
  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.",
7072
8136
  temperature: 0
7073
8137
  }
7074
- );
7075
- const match = response.match(/\[[\s\S]*\]/);
7076
- if (match) {
7077
- const suggestions = JSON.parse(match[0]);
7078
- if (Array.isArray(suggestions)) {
7079
- return suggestions.map((s) => String(s)).slice(0, 5);
8138
+ );
8139
+ const match = response.match(/\[[\s\S]*\]/);
8140
+ if (match) {
8141
+ const suggestions = JSON.parse(match[0]);
8142
+ if (Array.isArray(suggestions)) {
8143
+ return suggestions.map((s) => String(s)).slice(0, 5);
8144
+ }
8145
+ }
8146
+ } catch (error) {
8147
+ console.error("[Pipeline] Failed to generate suggestions:", error);
8148
+ }
8149
+ return [];
8150
+ }
8151
+ };
8152
+
8153
+ // src/core/Retrivora.ts
8154
+ var Retrivora = class {
8155
+ constructor(config) {
8156
+ this.config = ConfigResolver.resolveUniversal(config);
8157
+ this.pipeline = new Pipeline(this.config);
8158
+ }
8159
+ async initialize() {
8160
+ var _a2;
8161
+ try {
8162
+ await ConfigValidator.validateAndThrow(this.config);
8163
+ LicenseVerifier.verify(
8164
+ this.config.licenseKey,
8165
+ this.config.projectId,
8166
+ (_a2 = this.config.vectorDb) == null ? void 0 : _a2.provider
8167
+ );
8168
+ } catch (err) {
8169
+ throw wrapError(err, "CONFIGURATION_ERROR");
8170
+ }
8171
+ try {
8172
+ await this.pipeline.initialize();
8173
+ } catch (err) {
8174
+ throw wrapError(err, "AUTHENTICATION_ERROR");
8175
+ }
8176
+ }
8177
+ async ingest(documents, namespace) {
8178
+ try {
8179
+ return await this.pipeline.ingest(documents, namespace);
8180
+ } catch (err) {
8181
+ const msg = String(err);
8182
+ let defaultCode = "RETRIEVAL_FAILED";
8183
+ if (msg.includes("Embed") || msg.includes("embed")) {
8184
+ defaultCode = "EMBEDDING_FAILED";
8185
+ }
8186
+ throw wrapError(err, defaultCode);
8187
+ }
8188
+ }
8189
+ async ask(question, history = [], namespace) {
8190
+ try {
8191
+ return await this.pipeline.ask(question, history, namespace);
8192
+ } catch (err) {
8193
+ const msg = String(err);
8194
+ let defaultCode = "RETRIEVAL_FAILED";
8195
+ if (msg.includes("Embed") || msg.includes("embed")) {
8196
+ defaultCode = "EMBEDDING_FAILED";
8197
+ }
8198
+ throw wrapError(err, defaultCode);
8199
+ }
8200
+ }
8201
+ askStream(_0) {
8202
+ return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
8203
+ try {
8204
+ const stream = this.pipeline.askStream(question, history, namespace);
8205
+ try {
8206
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
8207
+ const chunk = temp.value;
8208
+ yield chunk;
8209
+ }
8210
+ } catch (temp) {
8211
+ error = [temp];
8212
+ } finally {
8213
+ try {
8214
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
8215
+ } finally {
8216
+ if (error)
8217
+ throw error[0];
8218
+ }
8219
+ }
8220
+ } catch (err) {
8221
+ const msg = String(err);
8222
+ let defaultCode = "RETRIEVAL_FAILED";
8223
+ if (msg.includes("Embed") || msg.includes("embed")) {
8224
+ defaultCode = "EMBEDDING_FAILED";
7080
8225
  }
8226
+ throw wrapError(err, defaultCode);
7081
8227
  }
7082
- } catch (error) {
7083
- console.error("[Pipeline] Failed to generate suggestions:", error);
7084
- }
7085
- return [];
8228
+ });
8229
+ }
8230
+ getPipeline() {
8231
+ return this.pipeline;
7086
8232
  }
7087
8233
  };
7088
8234
 
@@ -7192,9 +8338,20 @@ var ProviderHealthCheck = class {
7192
8338
  // src/core/VectorPlugin.ts
7193
8339
  var VectorPlugin = class {
7194
8340
  constructor(hostConfig) {
7195
- this.config = ConfigResolver.resolve(hostConfig);
7196
- this.validationPromise = ConfigValidator.validateAndThrow(this.config);
7197
- this.pipeline = new Pipeline(this.config);
8341
+ const resolvedConfig = ConfigResolver.resolve(hostConfig);
8342
+ this.config = resolvedConfig;
8343
+ this.validationPromise = (async () => {
8344
+ var _a2;
8345
+ await ConfigValidator.validateAndThrow(resolvedConfig);
8346
+ LicenseVerifier.verify(
8347
+ resolvedConfig.licenseKey,
8348
+ resolvedConfig.projectId,
8349
+ (_a2 = resolvedConfig.vectorDb) == null ? void 0 : _a2.provider
8350
+ );
8351
+ })();
8352
+ this.validationPromise.catch(() => {
8353
+ });
8354
+ this.pipeline = new Pipeline(resolvedConfig);
7198
8355
  }
7199
8356
  /**
7200
8357
  * Get the current resolved configuration.
@@ -7227,55 +8384,93 @@ var VectorPlugin = class {
7227
8384
  * Run a chat query.
7228
8385
  */
7229
8386
  async chat(message, history = [], namespace) {
7230
- await this.validationPromise;
7231
- return this.pipeline.ask(message, history, namespace);
8387
+ try {
8388
+ await this.validationPromise;
8389
+ } catch (err) {
8390
+ throw wrapError(err, "CONFIGURATION_ERROR");
8391
+ }
8392
+ try {
8393
+ return await this.pipeline.ask(message, history, namespace);
8394
+ } catch (err) {
8395
+ const msg = String(err);
8396
+ let defaultCode = "RETRIEVAL_FAILED";
8397
+ if (msg.includes("Embed") || msg.includes("embed")) {
8398
+ defaultCode = "EMBEDDING_FAILED";
8399
+ }
8400
+ throw wrapError(err, defaultCode);
8401
+ }
7232
8402
  }
7233
8403
  /**
7234
8404
  * Run a streaming chat query.
7235
8405
  */
7236
8406
  chatStream(_0) {
7237
8407
  return __asyncGenerator(this, arguments, function* (message, history = [], namespace) {
7238
- yield new __await(this.validationPromise);
7239
- yield* __yieldStar(this.pipeline.askStream(message, history, namespace));
8408
+ try {
8409
+ yield new __await(this.validationPromise);
8410
+ } catch (err) {
8411
+ throw wrapError(err, "CONFIGURATION_ERROR");
8412
+ }
8413
+ try {
8414
+ const stream = this.pipeline.askStream(message, history, namespace);
8415
+ try {
8416
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
8417
+ const chunk = temp.value;
8418
+ yield chunk;
8419
+ }
8420
+ } catch (temp) {
8421
+ error = [temp];
8422
+ } finally {
8423
+ try {
8424
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
8425
+ } finally {
8426
+ if (error)
8427
+ throw error[0];
8428
+ }
8429
+ }
8430
+ } catch (err) {
8431
+ const msg = String(err);
8432
+ let defaultCode = "RETRIEVAL_FAILED";
8433
+ if (msg.includes("Embed") || msg.includes("embed")) {
8434
+ defaultCode = "EMBEDDING_FAILED";
8435
+ }
8436
+ throw wrapError(err, defaultCode);
8437
+ }
7240
8438
  });
7241
8439
  }
7242
8440
  /**
7243
8441
  * Ingest documents into the vector database.
7244
8442
  */
7245
8443
  async ingest(documents, namespace) {
7246
- await this.validationPromise;
7247
- return this.pipeline.ingest(documents, namespace);
8444
+ try {
8445
+ await this.validationPromise;
8446
+ } catch (err) {
8447
+ throw wrapError(err, "CONFIGURATION_ERROR");
8448
+ }
8449
+ try {
8450
+ return await this.pipeline.ingest(documents, namespace);
8451
+ } catch (err) {
8452
+ const msg = String(err);
8453
+ let defaultCode = "RETRIEVAL_FAILED";
8454
+ if (msg.includes("Embed") || msg.includes("embed")) {
8455
+ defaultCode = "EMBEDDING_FAILED";
8456
+ }
8457
+ throw wrapError(err, defaultCode);
8458
+ }
7248
8459
  }
7249
8460
  /**
7250
8461
  * Get auto-suggestions based on a query prefix.
7251
8462
  */
7252
8463
  async getSuggestions(query, namespace) {
7253
- await this.validationPromise;
7254
- return this.pipeline.getSuggestions(query, namespace);
7255
- }
7256
- };
7257
-
7258
- // src/core/Retrivora.ts
7259
- var Retrivora = class {
7260
- constructor(config) {
7261
- this.config = ConfigResolver.resolveUniversal(config);
7262
- this.pipeline = new Pipeline(this.config);
7263
- }
7264
- async initialize() {
7265
- await ConfigValidator.validateAndThrow(this.config);
7266
- await this.pipeline.initialize();
7267
- }
7268
- async ingest(documents, namespace) {
7269
- return this.pipeline.ingest(documents, namespace);
7270
- }
7271
- async ask(question, history = [], namespace) {
7272
- return this.pipeline.ask(question, history, namespace);
7273
- }
7274
- askStream(question, history = [], namespace) {
7275
- return this.pipeline.askStream(question, history, namespace);
7276
- }
7277
- getPipeline() {
7278
- return this.pipeline;
8464
+ try {
8465
+ await this.validationPromise;
8466
+ } catch (err) {
8467
+ throw wrapError(err, "CONFIGURATION_ERROR");
8468
+ }
8469
+ try {
8470
+ return await this.pipeline.getSuggestions(query, namespace);
8471
+ } catch (err) {
8472
+ throw wrapError(err, "RETRIEVAL_FAILED");
8473
+ }
7279
8474
  }
7280
8475
  };
7281
8476
 
@@ -7292,13 +8487,13 @@ var ConfigBuilder = class {
7292
8487
  * Configure the vector database provider
7293
8488
  */
7294
8489
  vectorDb(provider, options) {
7295
- var _a;
8490
+ var _a2;
7296
8491
  if (provider === "auto") {
7297
8492
  this._vectorDb = this._autoDetectVectorDb();
7298
8493
  } else {
7299
8494
  this._vectorDb = {
7300
8495
  provider,
7301
- indexName: (_a = options == null ? void 0 : options.indexName) != null ? _a : "default",
8496
+ indexName: (_a2 = options == null ? void 0 : options.indexName) != null ? _a2 : "default",
7302
8497
  options: __spreadValues({}, options)
7303
8498
  };
7304
8499
  }
@@ -7308,7 +8503,7 @@ var ConfigBuilder = class {
7308
8503
  * Configure the LLM provider for chat
7309
8504
  */
7310
8505
  llm(provider, model, apiKey, options) {
7311
- var _a, _b;
8506
+ var _a2, _b;
7312
8507
  if (provider === "auto") {
7313
8508
  this._llm = this._autoDetectLLM();
7314
8509
  } else {
@@ -7317,7 +8512,7 @@ var ConfigBuilder = class {
7317
8512
  model: model != null ? model : "default-model",
7318
8513
  apiKey,
7319
8514
  systemPrompt: options == null ? void 0 : options.systemPrompt,
7320
- maxTokens: (_a = options == null ? void 0 : options.maxTokens) != null ? _a : 1024,
8515
+ maxTokens: (_a2 = options == null ? void 0 : options.maxTokens) != null ? _a2 : 1024,
7321
8516
  temperature: (_b = options == null ? void 0 : options.temperature) != null ? _b : 0.7,
7322
8517
  baseUrl: options == null ? void 0 : options.baseUrl,
7323
8518
  options
@@ -7360,8 +8555,8 @@ var ConfigBuilder = class {
7360
8555
  * Set RAG-specific pipeline parameters
7361
8556
  */
7362
8557
  rag(options) {
7363
- var _a;
7364
- this._rag = __spreadValues(__spreadValues({}, (_a = this._rag) != null ? _a : {}), options);
8558
+ var _a2;
8559
+ this._rag = __spreadValues(__spreadValues({}, (_a2 = this._rag) != null ? _a2 : {}), options);
7365
8560
  return this;
7366
8561
  }
7367
8562
  /**
@@ -7377,7 +8572,7 @@ var ConfigBuilder = class {
7377
8572
  * Throws if required fields (projectId, vectorDb, llm, embedding) are not set.
7378
8573
  */
7379
8574
  build() {
7380
- var _a;
8575
+ var _a2;
7381
8576
  const missing = [];
7382
8577
  if (!this._projectId) missing.push('projectId (call .projectId("my-app"))');
7383
8578
  if (!this._vectorDb) missing.push('vectorDb (call .vectorDb("pinecone", { ... }))');
@@ -7389,7 +8584,7 @@ var ConfigBuilder = class {
7389
8584
  ${missing.join("\n ")}`
7390
8585
  );
7391
8586
  }
7392
- const ragConfig = (_a = this._rag) != null ? _a : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
8587
+ const ragConfig = (_a2 = this._rag) != null ? _a2 : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
7393
8588
  if (process.env.RAG_USE_GRAPH_RETRIEVAL === "true") {
7394
8589
  ragConfig.useGraphRetrieval = true;
7395
8590
  }
@@ -7485,8 +8680,8 @@ var DocumentParser = class {
7485
8680
  * Extract text from a File or Buffer based on its type.
7486
8681
  */
7487
8682
  static async parse(file, fileName, mimeType) {
7488
- var _a;
7489
- const extension = (_a = fileName.split(".").pop()) == null ? void 0 : _a.toLowerCase();
8683
+ var _a2;
8684
+ const extension = (_a2 = fileName.split(".").pop()) == null ? void 0 : _a2.toLowerCase();
7490
8685
  if (extension === "txt" || extension === "md" || mimeType === "text/plain" || mimeType === "text/markdown") {
7491
8686
  return this.readAsText(file);
7492
8687
  }
@@ -7553,6 +8748,497 @@ init_UniversalVectorProvider();
7553
8748
 
7554
8749
  // src/handlers/index.ts
7555
8750
  import { NextResponse } from "next/server";
8751
+
8752
+ // src/core/DatabaseStorage.ts
8753
+ import * as fs from "fs";
8754
+ import * as path from "path";
8755
+ var DatabaseStorage = class {
8756
+ constructor(config) {
8757
+ // Dynamic PG Pool
8758
+ this.pgPool = null;
8759
+ // Dynamic MongoDB Client
8760
+ this.mongoClient = null;
8761
+ this.mongoDbName = "";
8762
+ // Filesystem fallback configuration
8763
+ this.fallbackDir = path.join(process.cwd(), ".retrivora");
8764
+ this.historyFile = path.join(this.fallbackDir, "history.json");
8765
+ this.feedbackFile = path.join(this.fallbackDir, "feedback.json");
8766
+ var _a2, _b, _c, _d, _e;
8767
+ this.config = config;
8768
+ this.provider = ((_a2 = config.vectorDb) == null ? void 0 : _a2.provider) || "fs";
8769
+ const rawHistoryTable = ((_c = (_b = config.rag) == null ? void 0 : _b.history) == null ? void 0 : _c.tableName) || "retrivora_history";
8770
+ const rawFeedbackTable = ((_e = (_d = config.rag) == null ? void 0 : _d.feedback) == null ? void 0 : _e.tableName) || "retrivora_feedback";
8771
+ this.historyTableName = rawHistoryTable.replace(/[^a-zA-Z0-9_]/g, "_");
8772
+ this.feedbackTableName = rawFeedbackTable.replace(/[^a-zA-Z0-9_]/g, "_");
8773
+ }
8774
+ /**
8775
+ * Asserts the user is running a valid Premium/Enterprise license in production.
8776
+ * In non-production (development / test) environments this is a complete no-op —
8777
+ * all History and Feedback features are freely accessible for local development.
8778
+ */
8779
+ checkPremiumSubscription() {
8780
+ if (process.env.NODE_ENV !== "production") {
8781
+ return;
8782
+ }
8783
+ if (!this.config.licenseKey) {
8784
+ throw new Error(
8785
+ "[Retrivora SDK] Chat History and Feedback features require a Premium or Enterprise license key in production."
8786
+ );
8787
+ }
8788
+ try {
8789
+ const payload = LicenseVerifier.verify(this.config.licenseKey, this.config.projectId);
8790
+ const tier = (payload.tier || "").toLowerCase();
8791
+ if (tier !== "premium" && tier !== "enterprise" && tier !== "growth" && tier !== "pro" && tier !== "developer_pro") {
8792
+ throw new Error(
8793
+ `[Retrivora SDK] Chat History and Feedback features are not available on the "${tier}" tier. Please upgrade to a Developer Pro or Enterprise plan.`
8794
+ );
8795
+ }
8796
+ } catch (err) {
8797
+ throw new Error(
8798
+ `[Retrivora SDK] Subscription check failed: ${err instanceof Error ? err.message : String(err)}`
8799
+ );
8800
+ }
8801
+ }
8802
+ checkHistoryEnabled() {
8803
+ var _a2, _b;
8804
+ this.checkPremiumSubscription();
8805
+ if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.history) == null ? void 0 : _b.enabled) === false) {
8806
+ throw new Error("[Retrivora SDK] Chat History is disabled in RagConfig.");
8807
+ }
8808
+ }
8809
+ checkFeedbackEnabled() {
8810
+ var _a2, _b;
8811
+ this.checkPremiumSubscription();
8812
+ if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.feedback) == null ? void 0 : _b.enabled) === false) {
8813
+ throw new Error("[Retrivora SDK] User Feedback is disabled in RagConfig.");
8814
+ }
8815
+ }
8816
+ async getPGPool() {
8817
+ const globalKey = `__retrivora_pg_pool_${this.config.projectId}`;
8818
+ const _g2 = global;
8819
+ if (_g2[globalKey]) {
8820
+ this.pgPool = _g2[globalKey];
8821
+ return this.pgPool;
8822
+ }
8823
+ const opts = this.config.vectorDb.options;
8824
+ if (!opts.connectionString) {
8825
+ throw new Error("[DatabaseStorage] pg connectionString option is missing.");
8826
+ }
8827
+ const { Pool: Pool3 } = await import("pg");
8828
+ this.pgPool = new Pool3({ connectionString: opts.connectionString });
8829
+ _g2[globalKey] = this.pgPool;
8830
+ const client = await this.pgPool.connect();
8831
+ try {
8832
+ await client.query(`
8833
+ CREATE TABLE IF NOT EXISTS ${this.historyTableName} (
8834
+ id TEXT PRIMARY KEY,
8835
+ session_id TEXT NOT NULL,
8836
+ role TEXT NOT NULL,
8837
+ content TEXT NOT NULL,
8838
+ sources JSONB,
8839
+ ui_transformation JSONB,
8840
+ trace JSONB,
8841
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
8842
+ )
8843
+ `);
8844
+ await client.query(`
8845
+ CREATE TABLE IF NOT EXISTS ${this.feedbackTableName} (
8846
+ id TEXT PRIMARY KEY,
8847
+ message_id TEXT NOT NULL UNIQUE,
8848
+ session_id TEXT NOT NULL,
8849
+ rating TEXT NOT NULL,
8850
+ comment TEXT,
8851
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
8852
+ )
8853
+ `);
8854
+ } finally {
8855
+ client.release();
8856
+ }
8857
+ return this.pgPool;
8858
+ }
8859
+ async getMongoClient() {
8860
+ const globalKey = `__retrivora_mongo_client_${this.config.projectId}`;
8861
+ const _g2 = global;
8862
+ if (_g2[globalKey]) {
8863
+ this.mongoClient = _g2[globalKey];
8864
+ this.mongoDbName = this.config.vectorDb.options.database;
8865
+ return this.mongoClient;
8866
+ }
8867
+ const opts = this.config.vectorDb.options;
8868
+ if (!opts.uri || !opts.database) {
8869
+ throw new Error("[DatabaseStorage] mongo uri and database options are missing.");
8870
+ }
8871
+ const { MongoClient: MongoClient2 } = await import("mongodb");
8872
+ this.mongoClient = new MongoClient2(opts.uri);
8873
+ await this.mongoClient.connect();
8874
+ _g2[globalKey] = this.mongoClient;
8875
+ this.mongoDbName = opts.database;
8876
+ return this.mongoClient;
8877
+ }
8878
+ getMongoDb() {
8879
+ return this.mongoClient.db(this.mongoDbName);
8880
+ }
8881
+ // Helper for FS fallback reads
8882
+ readLocalFile(filePath) {
8883
+ if (!fs.existsSync(filePath)) return [];
8884
+ try {
8885
+ const raw = fs.readFileSync(filePath, "utf-8");
8886
+ return JSON.parse(raw) || [];
8887
+ } catch (e) {
8888
+ return [];
8889
+ }
8890
+ }
8891
+ // Helper for FS fallback writes
8892
+ writeLocalFile(filePath, data) {
8893
+ if (!fs.existsSync(this.fallbackDir)) {
8894
+ fs.mkdirSync(this.fallbackDir, { recursive: true });
8895
+ }
8896
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
8897
+ }
8898
+ // ─── Message History Operations ──────────────────────────────────────────
8899
+ async saveMessage(sessionId, message) {
8900
+ this.checkHistoryEnabled();
8901
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
8902
+ const msgId = message.id || `msg_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
8903
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
8904
+ const pool = await this.getPGPool();
8905
+ await pool.query(
8906
+ `INSERT INTO ${this.historyTableName} (id, session_id, role, content, sources, ui_transformation, trace, created_at)
8907
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
8908
+ ON CONFLICT (id) DO UPDATE
8909
+ SET content = EXCLUDED.content, sources = EXCLUDED.sources, ui_transformation = EXCLUDED.ui_transformation, trace = EXCLUDED.trace`,
8910
+ [
8911
+ msgId,
8912
+ sessionId,
8913
+ message.role,
8914
+ message.content,
8915
+ message.sources ? JSON.stringify(message.sources) : null,
8916
+ message.uiTransformation ? JSON.stringify(message.uiTransformation) : null,
8917
+ message.trace ? JSON.stringify(message.trace) : null,
8918
+ createdAt
8919
+ ]
8920
+ );
8921
+ } else if (this.provider === "mongodb") {
8922
+ await this.getMongoClient();
8923
+ const db = this.getMongoDb();
8924
+ const col = db.collection(this.historyTableName);
8925
+ await col.updateOne(
8926
+ { id: msgId },
8927
+ {
8928
+ $set: {
8929
+ id: msgId,
8930
+ session_id: sessionId,
8931
+ role: message.role,
8932
+ content: message.content,
8933
+ sources: message.sources || null,
8934
+ ui_transformation: message.uiTransformation || null,
8935
+ trace: message.trace || null,
8936
+ created_at: createdAt
8937
+ }
8938
+ },
8939
+ { upsert: true }
8940
+ );
8941
+ } else {
8942
+ const history = this.readLocalFile(this.historyFile);
8943
+ const index = history.findIndex((h) => h.id === msgId);
8944
+ const item = {
8945
+ id: msgId,
8946
+ session_id: sessionId,
8947
+ role: message.role,
8948
+ content: message.content,
8949
+ sources: message.sources || null,
8950
+ ui_transformation: message.uiTransformation || null,
8951
+ trace: message.trace || null,
8952
+ created_at: createdAt
8953
+ };
8954
+ if (index !== -1) {
8955
+ history[index] = item;
8956
+ } else {
8957
+ history.push(item);
8958
+ }
8959
+ this.writeLocalFile(this.historyFile, history);
8960
+ }
8961
+ }
8962
+ async getHistory(sessionId) {
8963
+ this.checkHistoryEnabled();
8964
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
8965
+ const pool = await this.getPGPool();
8966
+ const res = await pool.query(
8967
+ `SELECT id, role, content, sources, ui_transformation as "uiTransformation", trace, created_at as "createdAt"
8968
+ FROM ${this.historyTableName}
8969
+ WHERE session_id = $1
8970
+ ORDER BY created_at ASC`,
8971
+ [sessionId]
8972
+ );
8973
+ return res.rows;
8974
+ } else if (this.provider === "mongodb") {
8975
+ await this.getMongoClient();
8976
+ const db = this.getMongoDb();
8977
+ const col = db.collection(this.historyTableName);
8978
+ const items = await col.find({ session_id: sessionId }).sort({ created_at: 1 }).toArray();
8979
+ return items.map((item) => ({
8980
+ id: item.id,
8981
+ role: item.role,
8982
+ content: item.content,
8983
+ sources: item.sources,
8984
+ uiTransformation: item.ui_transformation,
8985
+ trace: item.trace,
8986
+ createdAt: item.created_at
8987
+ }));
8988
+ } else {
8989
+ const history = this.readLocalFile(this.historyFile);
8990
+ return history.filter((h) => h.session_id === sessionId).sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
8991
+ }
8992
+ }
8993
+ async clearHistory(sessionId) {
8994
+ this.checkHistoryEnabled();
8995
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
8996
+ const pool = await this.getPGPool();
8997
+ await pool.query(`DELETE FROM ${this.historyTableName} WHERE session_id = $1`, [sessionId]);
8998
+ await pool.query(`DELETE FROM ${this.feedbackTableName} WHERE session_id = $1`, [sessionId]);
8999
+ } else if (this.provider === "mongodb") {
9000
+ await this.getMongoClient();
9001
+ const db = this.getMongoDb();
9002
+ await db.collection(this.historyTableName).deleteMany({ session_id: sessionId });
9003
+ await db.collection(this.feedbackTableName).deleteMany({ session_id: sessionId });
9004
+ } else {
9005
+ const history = this.readLocalFile(this.historyFile);
9006
+ const filteredHistory = history.filter((h) => h.session_id !== sessionId);
9007
+ this.writeLocalFile(this.historyFile, filteredHistory);
9008
+ const feedback = this.readLocalFile(this.feedbackFile);
9009
+ const filteredFeedback = feedback.filter((f) => f.session_id !== sessionId);
9010
+ this.writeLocalFile(this.feedbackFile, filteredFeedback);
9011
+ }
9012
+ }
9013
+ async listSessions() {
9014
+ this.checkHistoryEnabled();
9015
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9016
+ const pool = await this.getPGPool();
9017
+ const res = await pool.query(`SELECT DISTINCT session_id FROM ${this.historyTableName}`);
9018
+ return res.rows.map((r) => r.session_id);
9019
+ } else if (this.provider === "mongodb") {
9020
+ await this.getMongoClient();
9021
+ const db = this.getMongoDb();
9022
+ return db.collection(this.historyTableName).distinct("session_id");
9023
+ } else {
9024
+ const history = this.readLocalFile(this.historyFile);
9025
+ const sessions = new Set(history.map((h) => h.session_id));
9026
+ return Array.from(sessions);
9027
+ }
9028
+ }
9029
+ // ─── Feedback Operations ──────────────────────────────────────────────────
9030
+ async saveFeedback(feedback) {
9031
+ this.checkFeedbackEnabled();
9032
+ const id = `fb_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9033
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
9034
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9035
+ const pool = await this.getPGPool();
9036
+ await pool.query(
9037
+ `INSERT INTO ${this.feedbackTableName} (id, message_id, session_id, rating, comment, created_at)
9038
+ VALUES ($1, $2, $3, $4, $5, $6)
9039
+ ON CONFLICT (message_id) DO UPDATE
9040
+ SET rating = EXCLUDED.rating, comment = EXCLUDED.comment`,
9041
+ [id, feedback.messageId, feedback.sessionId, feedback.rating, feedback.comment || null, createdAt]
9042
+ );
9043
+ } else if (this.provider === "mongodb") {
9044
+ await this.getMongoClient();
9045
+ const db = this.getMongoDb();
9046
+ const col = db.collection(this.feedbackTableName);
9047
+ await col.updateOne(
9048
+ { message_id: feedback.messageId },
9049
+ {
9050
+ $set: {
9051
+ id,
9052
+ message_id: feedback.messageId,
9053
+ session_id: feedback.sessionId,
9054
+ rating: feedback.rating,
9055
+ comment: feedback.comment || null,
9056
+ created_at: createdAt
9057
+ }
9058
+ },
9059
+ { upsert: true }
9060
+ );
9061
+ } else {
9062
+ const list = this.readLocalFile(this.feedbackFile);
9063
+ const index = list.findIndex((f) => f.message_id === feedback.messageId);
9064
+ const item = {
9065
+ id,
9066
+ message_id: feedback.messageId,
9067
+ session_id: feedback.sessionId,
9068
+ rating: feedback.rating,
9069
+ comment: feedback.comment || null,
9070
+ created_at: createdAt
9071
+ };
9072
+ if (index !== -1) {
9073
+ list[index] = item;
9074
+ } else {
9075
+ list.push(item);
9076
+ }
9077
+ this.writeLocalFile(this.feedbackFile, list);
9078
+ }
9079
+ }
9080
+ async getFeedback(messageId) {
9081
+ this.checkFeedbackEnabled();
9082
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9083
+ const pool = await this.getPGPool();
9084
+ const res = await pool.query(
9085
+ `SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
9086
+ FROM ${this.feedbackTableName}
9087
+ WHERE message_id = $1`,
9088
+ [messageId]
9089
+ );
9090
+ return res.rows[0] || null;
9091
+ } else if (this.provider === "mongodb") {
9092
+ await this.getMongoClient();
9093
+ const db = this.getMongoDb();
9094
+ const col = db.collection(this.feedbackTableName);
9095
+ const item = await col.findOne({ message_id: messageId });
9096
+ if (!item) return null;
9097
+ return {
9098
+ id: item.id,
9099
+ messageId: item.message_id,
9100
+ sessionId: item.session_id,
9101
+ rating: item.rating,
9102
+ comment: item.comment,
9103
+ createdAt: item.created_at
9104
+ };
9105
+ } else {
9106
+ const list = this.readLocalFile(this.feedbackFile);
9107
+ return list.find((f) => f.message_id === messageId) || null;
9108
+ }
9109
+ }
9110
+ async listFeedback() {
9111
+ this.checkFeedbackEnabled();
9112
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9113
+ const pool = await this.getPGPool();
9114
+ const res = await pool.query(
9115
+ `SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
9116
+ FROM ${this.feedbackTableName}
9117
+ ORDER BY created_at DESC`
9118
+ );
9119
+ return res.rows;
9120
+ } else if (this.provider === "mongodb") {
9121
+ await this.getMongoClient();
9122
+ const db = this.getMongoDb();
9123
+ const col = db.collection(this.feedbackTableName);
9124
+ const items = await col.find({}).sort({ created_at: -1 }).toArray();
9125
+ return items.map((item) => ({
9126
+ id: item.id,
9127
+ messageId: item.message_id,
9128
+ sessionId: item.session_id,
9129
+ rating: item.rating,
9130
+ comment: item.comment,
9131
+ createdAt: item.created_at
9132
+ }));
9133
+ } else {
9134
+ const list = this.readLocalFile(this.feedbackFile);
9135
+ return [...list].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
9136
+ }
9137
+ }
9138
+ async disconnect() {
9139
+ if (this.pgPool) {
9140
+ await this.pgPool.end();
9141
+ this.pgPool = null;
9142
+ }
9143
+ if (this.mongoClient) {
9144
+ await this.mongoClient.close();
9145
+ this.mongoClient = null;
9146
+ }
9147
+ }
9148
+ };
9149
+
9150
+ // src/handlers/index.ts
9151
+ async function checkAuth(req, onAuthorize) {
9152
+ if (!onAuthorize) return null;
9153
+ try {
9154
+ const res = await onAuthorize(req);
9155
+ if (res === false) {
9156
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
9157
+ }
9158
+ if (res instanceof Response) {
9159
+ return res;
9160
+ }
9161
+ return null;
9162
+ } catch (err) {
9163
+ const msg = err instanceof Error ? err.message : "Authorization check failed";
9164
+ return NextResponse.json({ error: msg }, { status: 401 });
9165
+ }
9166
+ }
9167
+ var RateLimiter = class {
9168
+ constructor(windowMs = 6e4, max = 30) {
9169
+ this.hits = /* @__PURE__ */ new Map();
9170
+ this.windowMs = windowMs;
9171
+ this.max = max;
9172
+ }
9173
+ /** Returns true if the request should be allowed, false if rate-limited. */
9174
+ allow(key) {
9175
+ const now = Date.now();
9176
+ const cutoff = now - this.windowMs;
9177
+ const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
9178
+ existing.push(now);
9179
+ this.hits.set(key, existing);
9180
+ if (this.hits.size > 5e3) {
9181
+ for (const [k, timestamps] of this.hits.entries()) {
9182
+ if (timestamps.every((t) => t <= cutoff)) this.hits.delete(k);
9183
+ }
9184
+ }
9185
+ return existing.length <= this.max;
9186
+ }
9187
+ retryAfterSec(key) {
9188
+ const now = Date.now();
9189
+ const cutoff = now - this.windowMs;
9190
+ const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
9191
+ if (existing.length === 0) return 0;
9192
+ return Math.ceil((existing[0] + this.windowMs - now) / 1e3);
9193
+ }
9194
+ };
9195
+ var _g = global;
9196
+ var _a;
9197
+ var rateLimiter = (_a = _g.__retrivoraRateLimiter) != null ? _a : _g.__retrivoraRateLimiter = new RateLimiter(6e4, 30);
9198
+ function getRateLimitKey(req) {
9199
+ var _a2, _b;
9200
+ 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";
9201
+ return `ip:${ip}`;
9202
+ }
9203
+ function checkRateLimit(req) {
9204
+ const key = getRateLimitKey(req);
9205
+ if (!rateLimiter.allow(key)) {
9206
+ const retryAfter = rateLimiter.retryAfterSec(key);
9207
+ return new Response(
9208
+ JSON.stringify({ error: { code: "RATE_LIMITED", message: "Too many requests. Please slow down." } }),
9209
+ {
9210
+ status: 429,
9211
+ headers: {
9212
+ "Content-Type": "application/json",
9213
+ "Retry-After": String(retryAfter),
9214
+ "X-RateLimit-Limit": "30",
9215
+ "X-RateLimit-Window": "60"
9216
+ }
9217
+ }
9218
+ );
9219
+ }
9220
+ return null;
9221
+ }
9222
+ var MAX_MESSAGE_LENGTH = 8e3;
9223
+ function sanitizeInput(raw) {
9224
+ const stripped = raw.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, "");
9225
+ const trimmed = stripped.trim();
9226
+ if (!trimmed) {
9227
+ return { ok: false, error: "message must not be empty" };
9228
+ }
9229
+ if (trimmed.length > MAX_MESSAGE_LENGTH) {
9230
+ return { ok: false, error: `message must be \u2264 ${MAX_MESSAGE_LENGTH} characters` };
9231
+ }
9232
+ return { ok: true, value: trimmed };
9233
+ }
9234
+ function getOrCreatePlugin(configOrPlugin) {
9235
+ if (configOrPlugin instanceof VectorPlugin) return configOrPlugin;
9236
+ const cacheKey = "__retrivoraPlugin_" + JSON.stringify(configOrPlugin != null ? configOrPlugin : {}).slice(0, 64);
9237
+ if (!_g[cacheKey]) {
9238
+ _g[cacheKey] = new VectorPlugin(configOrPlugin);
9239
+ }
9240
+ return _g[cacheKey];
9241
+ }
7556
9242
  function sseFrame(payload) {
7557
9243
  return `data: ${JSON.stringify(payload)}
7558
9244
 
@@ -7590,47 +9276,88 @@ var SSE_HEADERS = {
7590
9276
  "X-Accel-Buffering": "no"
7591
9277
  // Disable Nginx buffering for streaming
7592
9278
  };
7593
- function createChatHandler(configOrPlugin) {
7594
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9279
+ function createChatHandler(configOrPlugin, options) {
9280
+ const plugin = getOrCreatePlugin(configOrPlugin);
9281
+ const storage = new DatabaseStorage(plugin.getConfig());
9282
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7595
9283
  return async function POST(req) {
9284
+ const authResult = await checkAuth(req, onAuthorize);
9285
+ if (authResult) return authResult;
9286
+ const rateLimited = checkRateLimit(req);
9287
+ if (rateLimited) return rateLimited;
7596
9288
  try {
7597
9289
  const body = await req.json();
7598
- const { message, history = [], namespace } = body;
7599
- if (!(message == null ? void 0 : message.trim())) {
7600
- return NextResponse.json({ error: "message is required" }, { status: 400 });
7601
- }
9290
+ const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
9291
+ const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
9292
+ if (!sanitized.ok) {
9293
+ return NextResponse.json({ error: { code: "INVALID_INPUT", message: sanitized.error } }, { status: 400 });
9294
+ }
9295
+ const message = sanitized.value;
9296
+ const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9297
+ await storage.saveMessage(sessionId, {
9298
+ id: userMsgId,
9299
+ role: "user",
9300
+ content: message
9301
+ }).catch((err) => console.warn("[createChatHandler] Failed to save user message:", err));
7602
9302
  const result = await plugin.chat(message, history, namespace);
7603
- return NextResponse.json(result);
9303
+ const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9304
+ await storage.saveMessage(sessionId, {
9305
+ id: assistantMsgId,
9306
+ role: "assistant",
9307
+ content: result.reply,
9308
+ sources: result.sources,
9309
+ uiTransformation: result.ui_transformation,
9310
+ trace: result.trace
9311
+ }).catch((err) => console.warn("[createChatHandler] Failed to save assistant message:", err));
9312
+ return NextResponse.json(__spreadProps(__spreadValues({}, result), {
9313
+ messageId: assistantMsgId,
9314
+ userMessageId: userMsgId
9315
+ }));
7604
9316
  } catch (err) {
7605
9317
  const message = err instanceof Error ? err.message : "Internal server error";
7606
9318
  return NextResponse.json({ error: message }, { status: 500 });
7607
9319
  }
7608
9320
  };
7609
9321
  }
7610
- function createStreamHandler(configOrPlugin) {
7611
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9322
+ function createStreamHandler(configOrPlugin, options) {
9323
+ const plugin = getOrCreatePlugin(configOrPlugin);
9324
+ const storage = new DatabaseStorage(plugin.getConfig());
9325
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7612
9326
  return async function POST(req) {
9327
+ const authResult = await checkAuth(req, onAuthorize);
9328
+ if (authResult) return authResult;
9329
+ const rateLimited = checkRateLimit(req);
9330
+ if (rateLimited) return rateLimited;
7613
9331
  let body;
7614
9332
  try {
7615
9333
  body = await req.json();
7616
9334
  } catch (e) {
7617
- return new Response(JSON.stringify({ error: "Invalid JSON body" }), {
9335
+ return new Response(JSON.stringify({ error: { code: "INVALID_JSON", message: "Invalid JSON body" } }), {
7618
9336
  status: 400,
7619
9337
  headers: { "Content-Type": "application/json" }
7620
9338
  });
7621
9339
  }
7622
- const { message, history = [], namespace } = body;
7623
- if (!(message == null ? void 0 : message.trim())) {
7624
- return new Response(JSON.stringify({ error: "message is required" }), {
7625
- status: 400,
7626
- headers: { "Content-Type": "application/json" }
7627
- });
9340
+ const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
9341
+ const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
9342
+ if (!sanitized.ok) {
9343
+ return new Response(
9344
+ JSON.stringify({ error: { code: "INVALID_INPUT", message: sanitized.error } }),
9345
+ { status: 400, headers: { "Content-Type": "application/json" } }
9346
+ );
7628
9347
  }
9348
+ const message = sanitized.value;
9349
+ const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9350
+ await storage.saveMessage(sessionId, {
9351
+ id: userMsgId,
9352
+ role: "user",
9353
+ content: message
9354
+ }).catch((err) => console.warn("[createStreamHandler] Failed to save user message:", err));
9355
+ const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
7629
9356
  const encoder = new TextEncoder();
7630
9357
  let isActive = true;
7631
9358
  const stream = new ReadableStream({
7632
9359
  async start(controller) {
7633
- var _a;
9360
+ var _a2;
7634
9361
  const enqueue = (text) => {
7635
9362
  if (!isActive) return;
7636
9363
  try {
@@ -7641,11 +9368,13 @@ function createStreamHandler(configOrPlugin) {
7641
9368
  };
7642
9369
  try {
7643
9370
  const pipelineStream = plugin.chatStream(message, history, namespace);
9371
+ let fullReply = "";
7644
9372
  try {
7645
9373
  for (var iter = __forAwait(pipelineStream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
7646
9374
  const chunk = temp.value;
7647
9375
  if (!isActive) break;
7648
9376
  if (typeof chunk === "string") {
9377
+ fullReply += chunk;
7649
9378
  enqueue(sseTextFrame(chunk));
7650
9379
  } else if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "thinking") {
7651
9380
  enqueue(`data: ${JSON.stringify(chunk)}
@@ -7658,9 +9387,10 @@ function createStreamHandler(configOrPlugin) {
7658
9387
  if (responseChunk == null ? void 0 : responseChunk.trace) {
7659
9388
  enqueue(sseObservabilityFrame(responseChunk.trace));
7660
9389
  }
9390
+ let uiTransformation = responseChunk == null ? void 0 : responseChunk.ui_transformation;
7661
9391
  if (sources.length > 0) {
7662
9392
  try {
7663
- const uiTransformation = (_a = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a : UITransformer.transform(message, sources, plugin.getConfig());
9393
+ uiTransformation = (_a2 = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a2 : UITransformer.transform(message, sources, plugin.getConfig());
7664
9394
  if (uiTransformation) {
7665
9395
  enqueue(sseUIFrame(uiTransformation));
7666
9396
  }
@@ -7668,11 +9398,22 @@ function createStreamHandler(configOrPlugin) {
7668
9398
  console.warn("[createStreamHandler] UI transformation warning:", transformError);
7669
9399
  try {
7670
9400
  const fallback = UITransformer.transform(message, sources, plugin.getConfig());
7671
- if (fallback) enqueue(sseUIFrame(fallback));
9401
+ if (fallback) {
9402
+ uiTransformation = fallback;
9403
+ enqueue(sseUIFrame(fallback));
9404
+ }
7672
9405
  } catch (e) {
7673
9406
  }
7674
9407
  }
7675
9408
  }
9409
+ await storage.saveMessage(sessionId, {
9410
+ id: assistantMsgId,
9411
+ role: "assistant",
9412
+ content: fullReply,
9413
+ sources,
9414
+ uiTransformation,
9415
+ trace: responseChunk == null ? void 0 : responseChunk.trace
9416
+ }).catch((err) => console.warn("[createStreamHandler] Failed to save assistant message:", err));
7676
9417
  }
7677
9418
  }
7678
9419
  } catch (temp) {
@@ -7709,12 +9450,15 @@ function createStreamHandler(configOrPlugin) {
7709
9450
  console.log("[createStreamHandler] Stream connection closed by client:", reason);
7710
9451
  }
7711
9452
  });
7712
- return new Response(stream, { headers: SSE_HEADERS });
9453
+ return new Response(stream, { headers: __spreadProps(__spreadValues({}, SSE_HEADERS), { "x-message-id": assistantMsgId, "x-user-message-id": userMsgId }) });
7713
9454
  };
7714
9455
  }
7715
- function createIngestHandler(configOrPlugin) {
7716
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9456
+ function createIngestHandler(configOrPlugin, options) {
9457
+ const plugin = getOrCreatePlugin(configOrPlugin);
9458
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7717
9459
  return async function POST(req) {
9460
+ const authResult = await checkAuth(req, onAuthorize);
9461
+ if (authResult) return authResult;
7718
9462
  try {
7719
9463
  const body = await req.json();
7720
9464
  const { documents, namespace } = body;
@@ -7729,9 +9473,14 @@ function createIngestHandler(configOrPlugin) {
7729
9473
  }
7730
9474
  };
7731
9475
  }
7732
- function createHealthHandler(configOrPlugin) {
7733
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
7734
- return async function GET() {
9476
+ function createHealthHandler(configOrPlugin, options) {
9477
+ const plugin = getOrCreatePlugin(configOrPlugin);
9478
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9479
+ return async function GET(req) {
9480
+ if (req) {
9481
+ const authResult = await checkAuth(req, onAuthorize);
9482
+ if (authResult) return authResult;
9483
+ }
7735
9484
  try {
7736
9485
  const health = await plugin.checkHealth();
7737
9486
  const status = health.allHealthy ? "ok" : "degraded";
@@ -7746,9 +9495,12 @@ function createHealthHandler(configOrPlugin) {
7746
9495
  }
7747
9496
  };
7748
9497
  }
7749
- function createUploadHandler(configOrPlugin) {
7750
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9498
+ function createUploadHandler(configOrPlugin, options) {
9499
+ const plugin = getOrCreatePlugin(configOrPlugin);
9500
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7751
9501
  return async function POST(req) {
9502
+ const authResult = await checkAuth(req, onAuthorize);
9503
+ if (authResult) return authResult;
7752
9504
  try {
7753
9505
  const formData = await req.formData();
7754
9506
  const files = formData.getAll("files");
@@ -7822,6 +9574,190 @@ function createUploadHandler(configOrPlugin) {
7822
9574
  }
7823
9575
  };
7824
9576
  }
9577
+ function createSuggestionsHandler(configOrPlugin, options) {
9578
+ const plugin = getOrCreatePlugin(configOrPlugin);
9579
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9580
+ return async function POST(req) {
9581
+ const authResult = await checkAuth(req, onAuthorize);
9582
+ if (authResult) return authResult;
9583
+ try {
9584
+ const body = await req.json();
9585
+ const { query, namespace } = body;
9586
+ if (typeof query !== "string") {
9587
+ return NextResponse.json({ error: "query is required" }, { status: 400 });
9588
+ }
9589
+ const suggestions = await plugin.getSuggestions(query, namespace);
9590
+ return NextResponse.json({ suggestions });
9591
+ } catch (err) {
9592
+ const message = err instanceof Error ? err.message : "Internal server error";
9593
+ return NextResponse.json({ error: message }, { status: 500 });
9594
+ }
9595
+ };
9596
+ }
9597
+ function createHistoryHandler(configOrPlugin, options) {
9598
+ const plugin = getOrCreatePlugin(configOrPlugin);
9599
+ const storage = new DatabaseStorage(plugin.getConfig());
9600
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9601
+ return async function handler(req) {
9602
+ const authResult = await checkAuth(req, onAuthorize);
9603
+ if (authResult) return authResult;
9604
+ const url = new URL(req.url);
9605
+ const sessionId = url.searchParams.get("sessionId") || "default";
9606
+ if (req.method === "GET") {
9607
+ try {
9608
+ const history = await storage.getHistory(sessionId);
9609
+ return NextResponse.json({ history });
9610
+ } catch (err) {
9611
+ const message = err instanceof Error ? err.message : "Failed to fetch history";
9612
+ return NextResponse.json({ error: message }, { status: 500 });
9613
+ }
9614
+ } else if (req.method === "POST") {
9615
+ try {
9616
+ const body = await req.json().catch(() => ({}));
9617
+ const sid = body.sessionId || sessionId;
9618
+ await storage.clearHistory(sid);
9619
+ return NextResponse.json({ success: true });
9620
+ } catch (err) {
9621
+ const message = err instanceof Error ? err.message : "Failed to clear history";
9622
+ return NextResponse.json({ error: message }, { status: 500 });
9623
+ }
9624
+ }
9625
+ return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
9626
+ };
9627
+ }
9628
+ function createFeedbackHandler(configOrPlugin, options) {
9629
+ const plugin = getOrCreatePlugin(configOrPlugin);
9630
+ const storage = new DatabaseStorage(plugin.getConfig());
9631
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9632
+ return async function handler(req) {
9633
+ const authResult = await checkAuth(req, onAuthorize);
9634
+ if (authResult) return authResult;
9635
+ if (req.method === "GET") {
9636
+ try {
9637
+ const url = new URL(req.url);
9638
+ const messageId = url.searchParams.get("messageId");
9639
+ if (!messageId) {
9640
+ const feedbackList = await storage.listFeedback();
9641
+ return NextResponse.json({ feedback: feedbackList });
9642
+ }
9643
+ const feedback = await storage.getFeedback(messageId);
9644
+ return NextResponse.json({ feedback });
9645
+ } catch (err) {
9646
+ const message = err instanceof Error ? err.message : "Failed to fetch feedback";
9647
+ return NextResponse.json({ error: message }, { status: 500 });
9648
+ }
9649
+ } else if (req.method === "POST") {
9650
+ try {
9651
+ const body = await req.json();
9652
+ const { messageId, sessionId = "default", rating, comment } = body;
9653
+ if (!messageId) {
9654
+ return NextResponse.json({ error: "messageId is required" }, { status: 400 });
9655
+ }
9656
+ if (!rating) {
9657
+ return NextResponse.json({ error: "rating is required" }, { status: 400 });
9658
+ }
9659
+ await storage.saveFeedback({ messageId, sessionId, rating, comment });
9660
+ return NextResponse.json({ success: true });
9661
+ } catch (err) {
9662
+ const message = err instanceof Error ? err.message : "Failed to save feedback";
9663
+ return NextResponse.json({ error: message }, { status: 500 });
9664
+ }
9665
+ }
9666
+ return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
9667
+ };
9668
+ }
9669
+ function createSessionsHandler(configOrPlugin, options) {
9670
+ const plugin = getOrCreatePlugin(configOrPlugin);
9671
+ const storage = new DatabaseStorage(plugin.getConfig());
9672
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9673
+ return async function GET(req) {
9674
+ if (req) {
9675
+ const authResult = await checkAuth(req, onAuthorize);
9676
+ if (authResult) return authResult;
9677
+ }
9678
+ void req;
9679
+ try {
9680
+ const sessions = await storage.listSessions();
9681
+ return NextResponse.json({ sessions });
9682
+ } catch (err) {
9683
+ const message = err instanceof Error ? err.message : "Failed to list sessions";
9684
+ return NextResponse.json({ error: message }, { status: 500 });
9685
+ }
9686
+ };
9687
+ }
9688
+ function createRagHandler(configOrPlugin, options) {
9689
+ const plugin = getOrCreatePlugin(configOrPlugin);
9690
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9691
+ const chatHandler = createChatHandler(plugin, { onAuthorize });
9692
+ const streamHandler = createStreamHandler(plugin, { onAuthorize });
9693
+ const uploadHandler = createUploadHandler(plugin, { onAuthorize });
9694
+ const healthHandler = createHealthHandler(plugin, { onAuthorize });
9695
+ const suggestionsHandler = createSuggestionsHandler(plugin, { onAuthorize });
9696
+ const historyHandler = createHistoryHandler(plugin, { onAuthorize });
9697
+ const feedbackHandler = createFeedbackHandler(plugin, { onAuthorize });
9698
+ const sessionsHandler = createSessionsHandler(plugin, { onAuthorize });
9699
+ async function routePostRequest(req, segment) {
9700
+ switch (segment) {
9701
+ case "chat":
9702
+ return streamHandler(req);
9703
+ case "chat-sync":
9704
+ return chatHandler(req);
9705
+ case "upload":
9706
+ return uploadHandler(req);
9707
+ case "suggestions":
9708
+ return suggestionsHandler(req);
9709
+ case "health":
9710
+ return healthHandler(req);
9711
+ case "history":
9712
+ case "history/clear":
9713
+ return historyHandler(req);
9714
+ case "feedback":
9715
+ return feedbackHandler(req);
9716
+ default:
9717
+ return NextResponse.json({ error: `Not Found: POST segment "${segment}" not supported.` }, { status: 404 });
9718
+ }
9719
+ }
9720
+ async function routeGetRequest(req, segment) {
9721
+ switch (segment) {
9722
+ case "health":
9723
+ return healthHandler(req);
9724
+ case "history":
9725
+ return historyHandler(req);
9726
+ case "feedback":
9727
+ return feedbackHandler(req);
9728
+ case "sessions":
9729
+ return sessionsHandler(req);
9730
+ default:
9731
+ return NextResponse.json({ error: `Method Not Allowed: GET segment "${segment}" not supported.` }, { status: 405 });
9732
+ }
9733
+ }
9734
+ async function getSegment(context) {
9735
+ var _a2;
9736
+ 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;
9737
+ const segments = (resolvedParams == null ? void 0 : resolvedParams.retrivora) || [];
9738
+ return segments.join("/") || "chat";
9739
+ }
9740
+ return {
9741
+ GET: async (req, context) => {
9742
+ try {
9743
+ const segment = await getSegment(context);
9744
+ return await routeGetRequest(req, segment);
9745
+ } catch (err) {
9746
+ const msg = err instanceof Error ? err.message : "GET Routing failed";
9747
+ return NextResponse.json({ error: msg }, { status: 500 });
9748
+ }
9749
+ },
9750
+ POST: async (req, context) => {
9751
+ try {
9752
+ const segment = await getSegment(context);
9753
+ return await routePostRequest(req, segment);
9754
+ } catch (err) {
9755
+ const msg = err instanceof Error ? err.message : "POST Routing failed";
9756
+ return NextResponse.json({ error: msg }, { status: 500 });
9757
+ }
9758
+ }
9759
+ };
9760
+ }
7825
9761
  export {
7826
9762
  AnthropicProvider,
7827
9763
  AuthenticationException,
@@ -7837,8 +9773,10 @@ export {
7837
9773
  EmbeddingFailedException,
7838
9774
  EmbeddingStrategy,
7839
9775
  EmbeddingStrategyResolver,
9776
+ GroqProvider,
7840
9777
  LLMFactory,
7841
9778
  LLM_PROFILES,
9779
+ LicenseVerifier,
7842
9780
  MilvusProvider,
7843
9781
  MongoDBProvider,
7844
9782
  MultiTablePostgresProvider,
@@ -7852,6 +9790,7 @@ export {
7852
9790
  ProviderNotFoundException,
7853
9791
  ProviderRegistry,
7854
9792
  QdrantProvider,
9793
+ QwenProvider,
7855
9794
  RateLimitException,
7856
9795
  RedisProvider,
7857
9796
  RetrievalException,
@@ -7863,14 +9802,19 @@ export {
7863
9802
  VectorPlugin,
7864
9803
  WeaviateProvider,
7865
9804
  createChatHandler,
9805
+ createFeedbackHandler,
7866
9806
  createFromPreset,
7867
9807
  createHealthHandler,
9808
+ createHistoryHandler,
7868
9809
  createIngestHandler,
9810
+ createRagHandler,
9811
+ createSessionsHandler,
7869
9812
  createStreamHandler,
7870
9813
  createUploadHandler,
7871
9814
  getRagConfig,
7872
9815
  sseErrorFrame,
7873
9816
  sseFrame,
7874
9817
  sseMetaFrame,
7875
- sseTextFrame
9818
+ sseTextFrame,
9819
+ wrapError
7876
9820
  };