@retrivora-ai/rag-engine 1.9.7 → 1.9.9

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 (60) hide show
  1. package/README.md +136 -136
  2. package/dist/{ILLMProvider-Bhk6zJOK.d.mts → ILLMProvider-DMxLyTdq.d.mts} +59 -4
  3. package/dist/{ILLMProvider-Bhk6zJOK.d.ts → ILLMProvider-DMxLyTdq.d.ts} +59 -4
  4. package/dist/handlers/index.d.mts +2 -2
  5. package/dist/handlers/index.d.ts +2 -2
  6. package/dist/handlers/index.js +2327 -474
  7. package/dist/handlers/index.mjs +2329 -473
  8. package/dist/{index-B9J_XEh0.d.ts → index-CfkqZd2Y.d.ts} +12 -2
  9. package/dist/{index-C3SVtPYg.d.mts → index-DXd29KMq.d.mts} +27 -52
  10. package/dist/{index-Bu7T6xgr.d.ts → index-D_bOdJML.d.ts} +27 -52
  11. package/dist/{index-BJ4cd-t5.d.mts → index-xygonxpW.d.mts} +12 -2
  12. package/dist/index.css +783 -550
  13. package/dist/index.d.mts +35 -7
  14. package/dist/index.d.ts +35 -7
  15. package/dist/index.js +419 -282
  16. package/dist/index.mjs +426 -292
  17. package/dist/server.d.mts +65 -6
  18. package/dist/server.d.ts +65 -6
  19. package/dist/server.js +2185 -317
  20. package/dist/server.mjs +2185 -317
  21. package/package.json +13 -8
  22. package/src/app/constants.tsx +37 -7
  23. package/src/app/page.tsx +2 -0
  24. package/src/components/ChatWidget.tsx +2 -1
  25. package/src/components/ChatWindow.tsx +4 -1
  26. package/src/components/CodeViewer.tsx +19 -14
  27. package/src/components/MarkdownComponents.tsx +44 -1
  28. package/src/components/MessageBubble.tsx +162 -50
  29. package/src/components/constants.tsx +228 -0
  30. package/src/config/RagConfig.ts +48 -2
  31. package/src/config/constants.ts +4 -0
  32. package/src/config/serverConfig.ts +15 -0
  33. package/src/core/ConfigResolver.ts +38 -6
  34. package/src/core/DatabaseStorage.ts +469 -0
  35. package/src/core/LicenseVerifier.ts +260 -0
  36. package/src/core/MultiAgentCoordinator.ts +239 -0
  37. package/src/core/Pipeline.ts +151 -18
  38. package/src/core/Retrivora.ts +7 -0
  39. package/src/core/VectorPlugin.ts +12 -3
  40. package/src/core/mcp.ts +261 -0
  41. package/src/handlers/index.ts +449 -63
  42. package/src/hooks/useRagChat.ts +96 -42
  43. package/src/hooks/useStoredMessages.ts +15 -4
  44. package/src/index.ts +3 -0
  45. package/src/llm/LLMFactory.ts +9 -1
  46. package/src/llm/providers/GroqProvider.ts +176 -0
  47. package/src/llm/providers/QwenProvider.ts +191 -0
  48. package/src/server.ts +7 -0
  49. package/src/types/chat.ts +14 -0
  50. package/src/types/props.ts +12 -0
  51. package/.env.example +0 -80
  52. package/LICENSE.txt +0 -21
  53. package/src/components/AmbientBackground.tsx +0 -29
  54. package/src/components/ArchitectureCard.tsx +0 -17
  55. package/src/components/ArchitectureCardsSection.tsx +0 -15
  56. package/src/components/DocViewer.tsx +0 -103
  57. package/src/components/Documentation.tsx +0 -121
  58. package/src/components/Hero.tsx +0 -59
  59. package/src/components/Lifecycle.tsx +0 -37
  60. package/src/components/Navbar.tsx +0 -55
package/dist/server.js CHANGED
@@ -80,9 +80,9 @@ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")])
80
80
  function isRecord(value) {
81
81
  return typeof value === "object" && value !== null;
82
82
  }
83
- function resolvePath(obj, path) {
84
- if (!path || !obj) return void 0;
85
- return path.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
83
+ function resolvePath(obj, path2) {
84
+ if (!path2 || !obj) return void 0;
85
+ return path2.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
86
86
  if (!isRecord(current) && !Array.isArray(current)) {
87
87
  return void 0;
88
88
  }
@@ -192,7 +192,7 @@ var init_PineconeProvider = __esm({
192
192
  static getHealthChecker() {
193
193
  return {
194
194
  async check(config) {
195
- var _a, _b;
195
+ var _a2, _b;
196
196
  const opts = config.options || {};
197
197
  const indexName = config.indexName;
198
198
  const timestamp = Date.now();
@@ -200,7 +200,7 @@ var init_PineconeProvider = __esm({
200
200
  const { Pinecone: Pinecone2 } = await import("@pinecone-database/pinecone");
201
201
  const client = new Pinecone2({ apiKey: opts.apiKey });
202
202
  const indexes = await client.listIndexes();
203
- const indexNames = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
203
+ const indexNames = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
204
204
  if (!indexNames.includes(indexName)) {
205
205
  return {
206
206
  healthy: false,
@@ -227,10 +227,10 @@ var init_PineconeProvider = __esm({
227
227
  };
228
228
  }
229
229
  async initialize() {
230
- var _a, _b;
230
+ var _a2, _b;
231
231
  this.client = new import_pinecone.Pinecone({ apiKey: this.apiKey });
232
232
  const indexes = await this.client.listIndexes();
233
- const names = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
233
+ const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
234
234
  if (!names.includes(this.indexName)) {
235
235
  throw new Error(
236
236
  `[PineconeProvider] Index "${this.indexName}" not found. Available: ${names.join(", ")}`
@@ -242,12 +242,12 @@ var init_PineconeProvider = __esm({
242
242
  return namespace ? idx.namespace(namespace) : idx.namespace("");
243
243
  }
244
244
  async upsert(doc, namespace) {
245
- var _a;
245
+ var _a2;
246
246
  await this.index(namespace).upsert({
247
247
  records: [{
248
248
  id: String(doc.id),
249
249
  values: doc.vector,
250
- metadata: __spreadValues({ content: doc.content }, (_a = doc.metadata) != null ? _a : {})
250
+ metadata: __spreadValues({ content: doc.content }, (_a2 = doc.metadata) != null ? _a2 : {})
251
251
  }]
252
252
  });
253
253
  }
@@ -255,29 +255,29 @@ var init_PineconeProvider = __esm({
255
255
  const BATCH = 100;
256
256
  for (let i = 0; i < docs.length; i += BATCH) {
257
257
  const records = docs.slice(i, i + BATCH).map((d) => {
258
- var _a;
258
+ var _a2;
259
259
  return {
260
260
  id: String(d.id),
261
261
  values: d.vector,
262
- metadata: __spreadValues({ content: d.content }, (_a = d.metadata) != null ? _a : {})
262
+ metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
263
263
  };
264
264
  });
265
265
  await this.index(namespace).upsert({ records });
266
266
  }
267
267
  }
268
268
  async query(vector, topK, namespace, filter) {
269
- var _a;
269
+ var _a2;
270
270
  const pineconeFilter = this.sanitizeFilter(filter);
271
271
  const result = await this.index(namespace).query(__spreadValues({
272
272
  vector,
273
273
  topK,
274
274
  includeMetadata: true
275
275
  }, Object.keys(pineconeFilter).length > 0 ? { filter: pineconeFilter } : {}));
276
- return ((_a = result.matches) != null ? _a : []).map((m) => {
277
- var _a2, _b;
276
+ return ((_a2 = result.matches) != null ? _a2 : []).map((m) => {
277
+ var _a3, _b;
278
278
  return {
279
279
  id: m.id,
280
- score: (_a2 = m.score) != null ? _a2 : 0,
280
+ score: (_a3 = m.score) != null ? _a3 : 0,
281
281
  content: ((_b = m.metadata) == null ? void 0 : _b.content) || "",
282
282
  metadata: m.metadata
283
283
  };
@@ -316,13 +316,13 @@ var init_PostgreSQLProvider = __esm({
316
316
  init_BaseVectorProvider();
317
317
  PostgreSQLProvider = class extends BaseVectorProvider {
318
318
  constructor(config) {
319
- var _a;
319
+ var _a2;
320
320
  super(config);
321
321
  this.tableName = this.indexName.replace(/[^a-z0-9_]/gi, "_");
322
322
  const opts = config.options;
323
323
  if (!opts.connectionString) throw new Error("[PostgreSQLProvider] options.connectionString is required");
324
324
  this.connectionString = opts.connectionString;
325
- this.dimensions = (_a = opts.dimensions) != null ? _a : 1536;
325
+ this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 1536;
326
326
  }
327
327
  static getValidator() {
328
328
  return {
@@ -403,7 +403,7 @@ var init_PostgreSQLProvider = __esm({
403
403
  }
404
404
  }
405
405
  async upsert(doc, namespace = "") {
406
- var _a;
406
+ var _a2;
407
407
  const vectorLiteral = `[${doc.vector.join(",")}]`;
408
408
  await this.pool.query(
409
409
  `INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
@@ -413,7 +413,7 @@ var init_PostgreSQLProvider = __esm({
413
413
  content = EXCLUDED.content,
414
414
  metadata = EXCLUDED.metadata,
415
415
  embedding = EXCLUDED.embedding`,
416
- [doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), vectorLiteral]
416
+ [doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), vectorLiteral]
417
417
  );
418
418
  }
419
419
  async batchUpsert(docs, namespace = "") {
@@ -426,9 +426,9 @@ var init_PostgreSQLProvider = __esm({
426
426
  const batch = docs.slice(i, i + BATCH_SIZE);
427
427
  const values = [];
428
428
  const valuePlaceholders = batch.map((doc, idx) => {
429
- var _a;
429
+ var _a2;
430
430
  const offset = idx * 5;
431
- values.push(doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), `[${doc.vector.join(",")}]`);
431
+ values.push(doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), `[${doc.vector.join(",")}]`);
432
432
  return `($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}::vector)`;
433
433
  }).join(", ");
434
434
  const query = `
@@ -511,8 +511,8 @@ var init_PostgreSQLProvider = __esm({
511
511
 
512
512
  // src/utils/synonyms.ts
513
513
  function resolveMetadataValue(meta, uiKey) {
514
- var _a;
515
- const synonyms = (_a = FIELD_SYNONYMS[uiKey]) != null ? _a : [];
514
+ var _a2;
515
+ const synonyms = (_a2 = FIELD_SYNONYMS[uiKey]) != null ? _a2 : [];
516
516
  const keys = Object.keys(meta);
517
517
  const systemKeys = ["namespace", "filename", "filesize", "filetype", "docid", "uploadedat", "dimension", "chunkindex"];
518
518
  let match = keys.find((k) => k.toLowerCase() === uiKey.toLowerCase());
@@ -599,14 +599,14 @@ var init_MultiTablePostgresProvider = __esm({
599
599
  init_synonyms();
600
600
  MultiTablePostgresProvider = class extends BaseVectorProvider {
601
601
  constructor(config) {
602
- var _a, _b, _c;
602
+ var _a2, _b, _c;
603
603
  super(config);
604
604
  const opts = config.options || {};
605
605
  if (!opts.connectionString) {
606
606
  throw new Error("[MultiTablePostgresProvider] options.connectionString is required");
607
607
  }
608
608
  this.connectionString = opts.connectionString;
609
- this.dimensions = (_a = opts.dimensions) != null ? _a : 768;
609
+ this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 768;
610
610
  this.tables = [];
611
611
  const rawSearchFields = (_c = (_b = opts.searchFields) != null ? _b : process.env.VECTOR_DB_SEARCH_FIELDS) != null ? _c : ["name", "product_name", "productname", "title"];
612
612
  this.searchFields = typeof rawSearchFields === "string" ? rawSearchFields.split(",").map((f) => f.trim()).filter(Boolean) : rawSearchFields;
@@ -664,11 +664,11 @@ var init_MultiTablePostgresProvider = __esm({
664
664
  * Batch upsert documents by dynamically provisioning tables and columns based on CSV headers.
665
665
  */
666
666
  async batchUpsert(docs, namespace = "") {
667
- var _a;
667
+ var _a2;
668
668
  if (docs.length === 0) return;
669
669
  const docsByFile = {};
670
670
  for (const doc of docs) {
671
- const fileName = ((_a = doc.metadata) == null ? void 0 : _a.fileName) || this.uploadTable;
671
+ const fileName = ((_a2 = doc.metadata) == null ? void 0 : _a2.fileName) || this.uploadTable;
672
672
  if (!docsByFile[fileName]) docsByFile[fileName] = [];
673
673
  docsByFile[fileName].push(doc);
674
674
  }
@@ -721,11 +721,11 @@ var init_MultiTablePostgresProvider = __esm({
721
721
  const headerColumns = csvHeaders.map((h) => `"${h}"`).join(", ");
722
722
  const allColumns = `id, ${headerColumns ? headerColumns + ", " : ""}namespace, content, metadata, embedding`;
723
723
  const valuePlaceholders = batch.map((doc, idx) => {
724
- var _a2, _b;
724
+ var _a3, _b;
725
725
  const offset = idx * (5 + csvHeaders.length);
726
726
  values.push(doc.id);
727
727
  for (const h of csvHeaders) {
728
- values.push(String(((_a2 = doc.metadata) == null ? void 0 : _a2[h]) || ""));
728
+ values.push(String(((_a3 = doc.metadata) == null ? void 0 : _a3[h]) || ""));
729
729
  }
730
730
  values.push(namespace, doc.content, JSON.stringify((_b = doc.metadata) != null ? _b : {}), `[${doc.vector.join(",")}]`);
731
731
  const docPlaceholders = [];
@@ -764,7 +764,7 @@ var init_MultiTablePostgresProvider = __esm({
764
764
  * Query all configured tables and merge results, sorted by cosine similarity score.
765
765
  */
766
766
  async query(vector, topK, _namespace, _filter) {
767
- var _a;
767
+ var _a2;
768
768
  if (!this.pool) {
769
769
  throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
770
770
  }
@@ -795,11 +795,11 @@ var init_MultiTablePostgresProvider = __esm({
795
795
  const filterParams = [];
796
796
  if (metadataFilters && Object.keys(metadataFilters).length > 0) {
797
797
  const conditions = Object.entries(metadataFilters).map(([key, val]) => {
798
- var _a3;
798
+ var _a4;
799
799
  filterParams.push(String(val));
800
800
  const baseOffset = queryText && dynamicKeywordQuery ? 2 : 1;
801
801
  const paramIdx = baseOffset + filterParams.length;
802
- const synonyms = (_a3 = FIELD_SYNONYMS[key]) != null ? _a3 : [];
802
+ const synonyms = (_a4 = FIELD_SYNONYMS[key]) != null ? _a4 : [];
803
803
  const keysToCheck = [key, ...synonyms];
804
804
  const coalesceExprs = keysToCheck.flatMap((k) => [
805
805
  `metadata->>'${k}'`,
@@ -868,7 +868,7 @@ var init_MultiTablePostgresProvider = __esm({
868
868
  }
869
869
  const tableResults = [];
870
870
  for (const row of result.rows) {
871
- const _a2 = row, { hybrid_score, id } = _a2, rest = __objRest(_a2, ["hybrid_score", "id"]);
871
+ const _a3 = row, { hybrid_score, id } = _a3, rest = __objRest(_a3, ["hybrid_score", "id"]);
872
872
  delete rest.embedding;
873
873
  delete rest.vector_score;
874
874
  delete rest.keyword_score;
@@ -897,10 +897,10 @@ var init_MultiTablePostgresProvider = __esm({
897
897
  }
898
898
  allResults.sort((a, b) => b.score - a.score);
899
899
  if (allResults.length === 0) return [];
900
- const bestMatchTable = (_a = allResults[0].metadata) == null ? void 0 : _a.source_table;
900
+ const bestMatchTable = (_a2 = allResults[0].metadata) == null ? void 0 : _a2.source_table;
901
901
  const finalSorted = allResults.filter((res) => {
902
- var _a2;
903
- return ((_a2 = res.metadata) == null ? void 0 : _a2.source_table) === bestMatchTable;
902
+ var _a3;
903
+ return ((_a3 = res.metadata) == null ? void 0 : _a3.source_table) === bestMatchTable;
904
904
  });
905
905
  console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
906
906
  console.log(`[MultiTablePostgresProvider] Final top match from "${bestMatchTable}" with score ${finalSorted[0].score.toFixed(4)}`);
@@ -1305,14 +1305,14 @@ var init_QdrantProvider = __esm({
1305
1305
  * Samples points from the collection to discover available payload fields.
1306
1306
  */
1307
1307
  async discoverSchema() {
1308
- var _a;
1308
+ var _a2;
1309
1309
  try {
1310
1310
  const { data } = await this.http.post(`/collections/${this.indexName}/points/scroll`, {
1311
1311
  limit: 20,
1312
1312
  with_payload: true,
1313
1313
  with_vector: false
1314
1314
  });
1315
- const points = ((_a = data.result) == null ? void 0 : _a.points) || [];
1315
+ const points = ((_a2 = data.result) == null ? void 0 : _a2.points) || [];
1316
1316
  const keys = /* @__PURE__ */ new Set();
1317
1317
  for (const point of points) {
1318
1318
  const payload = point.payload || {};
@@ -1338,12 +1338,12 @@ var init_QdrantProvider = __esm({
1338
1338
  * Ensures the collection exists. Creates it if missing.
1339
1339
  */
1340
1340
  async ensureCollection() {
1341
- var _a;
1341
+ var _a2;
1342
1342
  try {
1343
1343
  await this.http.get(`/collections/${this.indexName}`);
1344
1344
  console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
1345
1345
  } catch (err) {
1346
- if (import_axios4.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
1346
+ if (import_axios4.default.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
1347
1347
  const opts = this.config.options;
1348
1348
  const dimensionsForCreate = opts.dimensions || 1536;
1349
1349
  console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
@@ -1363,7 +1363,7 @@ var init_QdrantProvider = __esm({
1363
1363
  * Ensures that a payload field has an index.
1364
1364
  */
1365
1365
  async ensureIndex(fieldName, schema = "keyword") {
1366
- var _a;
1366
+ var _a2;
1367
1367
  let fullPath = fieldName;
1368
1368
  if (!this.isFlatPayload && !fieldName.includes(".") && fieldName !== "namespace" && fieldName !== this.contentField) {
1369
1369
  fullPath = `${this.metadataField}.${fieldName}`;
@@ -1376,7 +1376,7 @@ var init_QdrantProvider = __esm({
1376
1376
  console.log(`[QdrantProvider] \u2705 Ensured ${schema} index for "${fullPath}"`);
1377
1377
  } catch (err) {
1378
1378
  let status;
1379
- if (import_axios4.default.isAxiosError(err)) status = (_a = err.response) == null ? void 0 : _a.status;
1379
+ if (import_axios4.default.isAxiosError(err)) status = (_a2 = err.response) == null ? void 0 : _a2.status;
1380
1380
  if (status === 409) return;
1381
1381
  console.warn(`[QdrantProvider] \u26A0\uFE0F Could not ensure index for "${fullPath}":`, err instanceof Error ? err.message : String(err));
1382
1382
  }
@@ -1405,7 +1405,7 @@ var init_QdrantProvider = __esm({
1405
1405
  await this.http.put(`/collections/${this.indexName}/points`, payload);
1406
1406
  }
1407
1407
  async query(vector, topK, namespace, _filter) {
1408
- var _a;
1408
+ var _a2;
1409
1409
  const must = [];
1410
1410
  if (namespace) {
1411
1411
  must.push({ key: "namespace", match: { value: namespace } });
@@ -1427,7 +1427,7 @@ var init_QdrantProvider = __esm({
1427
1427
  limit: topK,
1428
1428
  with_payload: true,
1429
1429
  params: {
1430
- hnsw_ef: ((_a = this.config.options) == null ? void 0 : _a.efSearch) || Math.max(topK * 20, 128),
1430
+ hnsw_ef: ((_a2 = this.config.options) == null ? void 0 : _a2.efSearch) || Math.max(topK * 20, 128),
1431
1431
  exact: false
1432
1432
  },
1433
1433
  filter: must.length > 0 ? { must } : void 0
@@ -1522,13 +1522,13 @@ var init_ChromaDBProvider = __esm({
1522
1522
  * Get or create the ChromaDB collection.
1523
1523
  */
1524
1524
  async initialize() {
1525
- var _a;
1525
+ var _a2;
1526
1526
  try {
1527
1527
  const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
1528
1528
  this.collectionId = data.id;
1529
1529
  console.log(`[ChromaDBProvider] \u2705 Collection "${this.indexName}" found (id: ${this.collectionId})`);
1530
1530
  } catch (err) {
1531
- if (import_axios5.default.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
1531
+ if (import_axios5.default.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
1532
1532
  console.log(`[ChromaDBProvider] \u23F3 Collection "${this.indexName}" not found. Creating...`);
1533
1533
  const { data } = await this.http.post("/api/v1/collections", {
1534
1534
  name: this.indexName
@@ -1749,7 +1749,7 @@ var init_WeaviateProvider = __esm({
1749
1749
  await this.http.post("/v1/batch/objects", payload);
1750
1750
  }
1751
1751
  async query(vector, topK, namespace, _filter) {
1752
- var _a, _b;
1752
+ var _a2, _b;
1753
1753
  const queryText = _filter == null ? void 0 : _filter.queryText;
1754
1754
  const sanitizedFilter = this.sanitizeFilter(_filter);
1755
1755
  const searchParams = queryText ? `hybrid: { query: ${JSON.stringify(queryText)}, alpha: 0.5 }` : `nearVector: { vector: ${JSON.stringify(vector)} }`;
@@ -1775,7 +1775,7 @@ var init_WeaviateProvider = __esm({
1775
1775
  `
1776
1776
  };
1777
1777
  const { data } = await this.http.post("/v1/graphql", graphqlQuery);
1778
- const results = ((_b = (_a = data.data) == null ? void 0 : _a.Get) == null ? void 0 : _b[this.indexName]) || [];
1778
+ const results = ((_b = (_a2 = data.data) == null ? void 0 : _a2.Get) == null ? void 0 : _b[this.indexName]) || [];
1779
1779
  return results.map((res) => ({
1780
1780
  id: res["_additional"].id,
1781
1781
  score: 1 - res["_additional"].distance,
@@ -1828,10 +1828,10 @@ var init_WeaviateProvider = __esm({
1828
1828
  return `{ operator: And, operands: [${operands.join(", ")}] }`;
1829
1829
  }
1830
1830
  weaviateOperand(key, value) {
1831
- const path = `path: [${JSON.stringify(key)}], operator: Equal`;
1832
- if (typeof value === "number") return `{ ${path}, valueNumber: ${value} }`;
1833
- if (typeof value === "boolean") return `{ ${path}, valueBoolean: ${value} }`;
1834
- return `{ ${path}, valueString: ${JSON.stringify(value)} }`;
1831
+ const path2 = `path: [${JSON.stringify(key)}], operator: Equal`;
1832
+ if (typeof value === "number") return `{ ${path2}, valueNumber: ${value} }`;
1833
+ if (typeof value === "boolean") return `{ ${path2}, valueBoolean: ${value} }`;
1834
+ return `{ ${path2}, valueString: ${JSON.stringify(value)} }`;
1835
1835
  }
1836
1836
  };
1837
1837
  }
@@ -1858,21 +1858,21 @@ var init_UniversalVectorProvider = __esm({
1858
1858
  }
1859
1859
  }
1860
1860
  async initialize() {
1861
- var _a;
1861
+ var _a2;
1862
1862
  this.http = import_axios8.default.create({
1863
1863
  baseURL: this.opts.baseUrl,
1864
1864
  headers: __spreadValues({
1865
1865
  "Content-Type": "application/json"
1866
1866
  }, this.opts.headers),
1867
- timeout: (_a = this.opts.timeout) != null ? _a : 3e4
1867
+ timeout: (_a2 = this.opts.timeout) != null ? _a2 : 3e4
1868
1868
  });
1869
1869
  if (!await this.ping()) {
1870
1870
  throw new Error(`[UniversalVectorProvider] Failed to connect to ${this.opts.baseUrl}`);
1871
1871
  }
1872
1872
  }
1873
1873
  async upsert(doc, namespace) {
1874
- var _a, _b, _c;
1875
- const endpoint = (_a = this.opts.upsertEndpoint) != null ? _a : "/upsert";
1874
+ var _a2, _b, _c;
1875
+ const endpoint = (_a2 = this.opts.upsertEndpoint) != null ? _a2 : "/upsert";
1876
1876
  const template = (_b = this.opts.upsertTemplate) != null ? _b : JSON.stringify({
1877
1877
  id: "{{id}}",
1878
1878
  vector: "{{vector}}",
@@ -1905,8 +1905,8 @@ var init_UniversalVectorProvider = __esm({
1905
1905
  }
1906
1906
  }
1907
1907
  async query(vector, topK, namespace, filter) {
1908
- var _a, _b;
1909
- const endpoint = (_a = this.opts.queryEndpoint) != null ? _a : "/query";
1908
+ var _a2, _b;
1909
+ const endpoint = (_a2 = this.opts.queryEndpoint) != null ? _a2 : "/query";
1910
1910
  const template = (_b = this.opts.queryTemplate) != null ? _b : JSON.stringify({
1911
1911
  vector: "{{vector}}",
1912
1912
  limit: "{{topK}}",
@@ -1932,12 +1932,12 @@ var init_UniversalVectorProvider = __esm({
1932
1932
  );
1933
1933
  }
1934
1934
  return results.map((item) => {
1935
- var _a2, _b2, _c, _d, _e, _f, _g;
1935
+ var _a3, _b2, _c, _d, _e, _f, _g2;
1936
1936
  return {
1937
- id: item[(_a2 = this.opts.queryIdField) != null ? _a2 : "id"],
1937
+ id: item[(_a3 = this.opts.queryIdField) != null ? _a3 : "id"],
1938
1938
  score: (_c = item[(_b2 = this.opts.queryScoreField) != null ? _b2 : "score"]) != null ? _c : 0,
1939
1939
  content: (_e = item[(_d = this.opts.queryContentField) != null ? _d : "content"]) != null ? _e : "",
1940
- metadata: (_g = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g : {}
1940
+ metadata: (_g2 = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g2 : {}
1941
1941
  };
1942
1942
  });
1943
1943
  } catch (error) {
@@ -1947,8 +1947,8 @@ var init_UniversalVectorProvider = __esm({
1947
1947
  }
1948
1948
  }
1949
1949
  async delete(id, namespace) {
1950
- var _a, _b;
1951
- const endpoint = (_a = this.opts.deleteEndpoint) != null ? _a : "/delete";
1950
+ var _a2, _b;
1951
+ const endpoint = (_a2 = this.opts.deleteEndpoint) != null ? _a2 : "/delete";
1952
1952
  const template = (_b = this.opts.deleteTemplate) != null ? _b : JSON.stringify({
1953
1953
  id: "{{id}}",
1954
1954
  namespace: "{{namespace}}"
@@ -1966,8 +1966,8 @@ var init_UniversalVectorProvider = __esm({
1966
1966
  }
1967
1967
  }
1968
1968
  async deleteNamespace(namespace) {
1969
- var _a;
1970
- const endpoint = (_a = this.opts.deleteNamespaceEndpoint) != null ? _a : "/delete-namespace";
1969
+ var _a2;
1970
+ const endpoint = (_a2 = this.opts.deleteNamespaceEndpoint) != null ? _a2 : "/delete-namespace";
1971
1971
  try {
1972
1972
  await this.http.post(endpoint, { namespace });
1973
1973
  } catch (error) {
@@ -1977,9 +1977,9 @@ var init_UniversalVectorProvider = __esm({
1977
1977
  }
1978
1978
  }
1979
1979
  async ping() {
1980
- var _a;
1980
+ var _a2;
1981
1981
  try {
1982
- const endpoint = (_a = this.opts.pingEndpoint) != null ? _a : "/health";
1982
+ const endpoint = (_a2 = this.opts.pingEndpoint) != null ? _a2 : "/health";
1983
1983
  const response = await this.http.get(endpoint, { timeout: 5e3 });
1984
1984
  return response.status >= 200 && response.status < 300;
1985
1985
  } catch (e) {
@@ -2084,8 +2084,10 @@ __export(server_exports, {
2084
2084
  EmbeddingFailedException: () => EmbeddingFailedException,
2085
2085
  EmbeddingStrategy: () => EmbeddingStrategy,
2086
2086
  EmbeddingStrategyResolver: () => EmbeddingStrategyResolver,
2087
+ GroqProvider: () => GroqProvider,
2087
2088
  LLMFactory: () => LLMFactory,
2088
2089
  LLM_PROFILES: () => LLM_PROFILES,
2090
+ LicenseVerifier: () => LicenseVerifier,
2089
2091
  MilvusProvider: () => MilvusProvider,
2090
2092
  MongoDBProvider: () => MongoDBProvider,
2091
2093
  MultiTablePostgresProvider: () => MultiTablePostgresProvider,
@@ -2099,6 +2101,7 @@ __export(server_exports, {
2099
2101
  ProviderNotFoundException: () => ProviderNotFoundException,
2100
2102
  ProviderRegistry: () => ProviderRegistry,
2101
2103
  QdrantProvider: () => QdrantProvider,
2104
+ QwenProvider: () => QwenProvider,
2102
2105
  RateLimitException: () => RateLimitException,
2103
2106
  RedisProvider: () => RedisProvider,
2104
2107
  RetrievalException: () => RetrievalException,
@@ -2110,10 +2113,13 @@ __export(server_exports, {
2110
2113
  VectorPlugin: () => VectorPlugin,
2111
2114
  WeaviateProvider: () => WeaviateProvider,
2112
2115
  createChatHandler: () => createChatHandler,
2116
+ createFeedbackHandler: () => createFeedbackHandler,
2113
2117
  createFromPreset: () => createFromPreset,
2114
2118
  createHealthHandler: () => createHealthHandler,
2119
+ createHistoryHandler: () => createHistoryHandler,
2115
2120
  createIngestHandler: () => createIngestHandler,
2116
2121
  createRagHandler: () => createRagHandler,
2122
+ createSessionsHandler: () => createSessionsHandler,
2117
2123
  createStreamHandler: () => createStreamHandler,
2118
2124
  createUploadHandler: () => createUploadHandler,
2119
2125
  getRagConfig: () => getRagConfig,
@@ -2148,6 +2154,8 @@ var LLM_PROVIDERS = [
2148
2154
  "anthropic",
2149
2155
  "ollama",
2150
2156
  "gemini",
2157
+ "groq",
2158
+ "qwen",
2151
2159
  "rest",
2152
2160
  "universal_rest",
2153
2161
  "custom"
@@ -2156,6 +2164,7 @@ var EMBEDDING_PROVIDERS = [
2156
2164
  "openai",
2157
2165
  "ollama",
2158
2166
  "gemini",
2167
+ "qwen",
2159
2168
  "rest",
2160
2169
  "universal_rest",
2161
2170
  "custom"
@@ -2164,6 +2173,7 @@ var PROVIDERS_WITH_EMBEDDINGS = [
2164
2173
  "openai",
2165
2174
  "ollama",
2166
2175
  "gemini",
2176
+ "qwen",
2167
2177
  "rest",
2168
2178
  "universal_rest"
2169
2179
  ];
@@ -2171,8 +2181,8 @@ var UI_BORDER_RADIUS_OPTIONS = ["none", "sm", "md", "lg", "xl", "full"];
2171
2181
 
2172
2182
  // src/config/serverConfig.ts
2173
2183
  function readString(env, name) {
2174
- var _a;
2175
- const value = (_a = env[name]) == null ? void 0 : _a.trim();
2184
+ var _a2;
2185
+ const value = (_a2 = env[name]) == null ? void 0 : _a2.trim();
2176
2186
  return value ? value : void 0;
2177
2187
  }
2178
2188
  function readNumber(env, name, fallback) {
@@ -2185,8 +2195,8 @@ function readNumber(env, name, fallback) {
2185
2195
  return parsed;
2186
2196
  }
2187
2197
  function readEnum(env, name, fallback, allowed) {
2188
- var _a;
2189
- const value = (_a = readString(env, name)) != null ? _a : fallback;
2198
+ var _a2;
2199
+ const value = (_a2 = readString(env, name)) != null ? _a2 : fallback;
2190
2200
  if (allowed.includes(value)) {
2191
2201
  return value;
2192
2202
  }
@@ -2196,15 +2206,15 @@ function getRagConfig(baseConfig, env = process.env) {
2196
2206
  return getEnvConfig(env, baseConfig);
2197
2207
  }
2198
2208
  function getEnvConfig(env = process.env, base) {
2199
- 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;
2200
- const projectId = (_c = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : base == null ? void 0 : base.projectId) != null ? _c : "__default__";
2209
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa;
2210
+ const projectId = (_c = (_b = (_a2 = readString(env, "RAG_PROJECT_ID")) != null ? _a2 : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : base == null ? void 0 : base.projectId) != null ? _c : "__default__";
2201
2211
  const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
2202
2212
  const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
2203
2213
  const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
2204
2214
  const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
2205
2215
  const vectorDbOptions = {};
2206
2216
  if (vectorProvider === "pinecone") {
2207
- vectorDbOptions.apiKey = (_g = (_f = readString(env, "PINECONE_API_KEY")) != null ? _f : (_e = (_d = base == null ? void 0 : base.vectorDb) == null ? void 0 : _d.options) == null ? void 0 : _e.apiKey) != null ? _g : "";
2217
+ vectorDbOptions.apiKey = (_g2 = (_f = readString(env, "PINECONE_API_KEY")) != null ? _f : (_e = (_d = base == null ? void 0 : base.vectorDb) == null ? void 0 : _d.options) == null ? void 0 : _e.apiKey) != null ? _g2 : "";
2208
2218
  vectorDbOptions.indexName = (_l = (_i = readString(env, "PINECONE_INDEX")) != null ? _i : (_h = base == null ? void 0 : base.vectorDb) == null ? void 0 : _h.indexName) != null ? _l : (_k = (_j = base == null ? void 0 : base.vectorDb) == null ? void 0 : _j.options) == null ? void 0 : _k.indexName;
2209
2219
  } else if (vectorProvider === "pgvector" || vectorProvider === "postgresql") {
2210
2220
  vectorDbOptions.connectionString = (_q = (_p = (_m = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _m : readString(env, "POSTGRES_URL")) != null ? _p : (_o = (_n = base == null ? void 0 : base.vectorDb) == null ? void 0 : _n.options) == null ? void 0 : _o.connectionString) != null ? _q : "";
@@ -2266,17 +2276,18 @@ function getEnvConfig(env = process.env, base) {
2266
2276
  rest: "default",
2267
2277
  custom: "default"
2268
2278
  };
2269
- return __spreadValues({
2279
+ return __spreadProps(__spreadValues({
2270
2280
  projectId,
2281
+ licenseKey: (_ha = (_ga = readString(env, "RETRIVORA_LICENSE_KEY")) != null ? _ga : readString(env, "LICENSE_KEY")) != null ? _ha : base == null ? void 0 : base.licenseKey,
2271
2282
  vectorDb: {
2272
2283
  provider: vectorProvider,
2273
- indexName: (_ha = (_ga = readString(env, "VECTOR_DB_INDEX")) != null ? _ga : vectorDbOptions.indexName) != null ? _ha : "rag-index",
2284
+ indexName: (_ja = (_ia = readString(env, "VECTOR_DB_INDEX")) != null ? _ia : vectorDbOptions.indexName) != null ? _ja : "rag-index",
2274
2285
  options: vectorDbOptions
2275
2286
  },
2276
2287
  llm: {
2277
2288
  provider: llmProvider,
2278
- model: (_ja = (_ia = readString(env, "LLM_MODEL")) != null ? _ia : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _ja : "gpt-4o",
2279
- apiKey: (_ka = llmApiKeyByProvider[llmProvider]) != null ? _ka : "",
2289
+ model: (_la = (_ka = readString(env, "LLM_MODEL")) != null ? _ka : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _la : "gpt-4o",
2290
+ apiKey: (_ma = llmApiKeyByProvider[llmProvider]) != null ? _ma : "",
2280
2291
  baseUrl: readString(env, "LLM_BASE_URL"),
2281
2292
  systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
2282
2293
  maxTokens: readNumber(env, "LLM_MAX_TOKENS", 4096),
@@ -2289,7 +2300,7 @@ function getEnvConfig(env = process.env, base) {
2289
2300
  },
2290
2301
  embedding: {
2291
2302
  provider: embeddingProvider,
2292
- model: (_la = readString(env, "EMBEDDING_MODEL")) != null ? _la : "text-embedding-3-small",
2303
+ model: (_na = readString(env, "EMBEDDING_MODEL")) != null ? _na : "text-embedding-3-small",
2293
2304
  apiKey: embeddingApiKeyByProvider[embeddingProvider],
2294
2305
  baseUrl: readString(env, "EMBEDDING_BASE_URL"),
2295
2306
  dimensions: embeddingDimensions,
@@ -2300,30 +2311,30 @@ function getEnvConfig(env = process.env, base) {
2300
2311
  }
2301
2312
  },
2302
2313
  ui: {
2303
- title: (_na = (_ma = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _ma : readString(env, "UI_TITLE")) != null ? _na : "AI Assistant",
2304
- subtitle: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _oa : readString(env, "UI_SUBTITLE")) != null ? _pa : "Powered by RAG",
2305
- primaryColor: (_ra = (_qa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _qa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ra : "#10b981",
2306
- accentColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _sa : readString(env, "UI_ACCENT_COLOR")) != null ? _ta : "#3b82f6",
2307
- logoUrl: (_ua = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _ua : readString(env, "UI_LOGO_URL"),
2308
- placeholder: (_wa = (_va = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _va : readString(env, "UI_PLACEHOLDER")) != null ? _wa : "Ask me anything\u2026",
2309
- showSources: ((_ya = (_xa = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _xa : readString(env, "UI_SHOW_SOURCES")) != null ? _ya : "true") !== "false",
2310
- 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.",
2311
- visualStyle: (_Ca = (_Ba = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Ba : readString(env, "UI_VISUAL_STYLE")) != null ? _Ca : "glass",
2312
- borderRadius: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Da : readString(env, "UI_BORDER_RADIUS")) != null ? _Ea : "xl",
2313
- allowUpload: ((_Ga = (_Fa = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Fa : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ga : "false") === "true"
2314
+ title: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _oa : readString(env, "UI_TITLE")) != null ? _pa : "AI Assistant",
2315
+ subtitle: (_ra = (_qa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _qa : readString(env, "UI_SUBTITLE")) != null ? _ra : "Powered by RAG",
2316
+ primaryColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _sa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ta : "#10b981",
2317
+ accentColor: (_va = (_ua = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _ua : readString(env, "UI_ACCENT_COLOR")) != null ? _va : "#3b82f6",
2318
+ logoUrl: (_wa = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _wa : readString(env, "UI_LOGO_URL"),
2319
+ placeholder: (_ya = (_xa = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _xa : readString(env, "UI_PLACEHOLDER")) != null ? _ya : "Ask me anything\u2026",
2320
+ showSources: ((_Aa = (_za = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _za : readString(env, "UI_SHOW_SOURCES")) != null ? _Aa : "true") !== "false",
2321
+ welcomeMessage: (_Ca = (_Ba = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _Ba : readString(env, "UI_WELCOME_MESSAGE")) != null ? _Ca : "Hello! I'm your AI assistant. Ask me anything about your documents.",
2322
+ visualStyle: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Da : readString(env, "UI_VISUAL_STYLE")) != null ? _Ea : "glass",
2323
+ borderRadius: (_Ga = (_Fa = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Fa : readString(env, "UI_BORDER_RADIUS")) != null ? _Ga : "xl",
2324
+ allowUpload: ((_Ia = (_Ha = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Ha : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ia : "false") === "true"
2314
2325
  },
2315
2326
  rag: {
2316
2327
  topK: readNumber(env, "RAG_TOP_K", 5),
2317
2328
  scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
2318
2329
  chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
2319
2330
  chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200),
2320
- filterableFields: (_Ha = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ha.split(",").map((f) => f.trim()),
2331
+ filterableFields: (_Ja = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ja.split(",").map((f) => f.trim()),
2321
2332
  // Query pipeline toggles — read from .env.local
2322
2333
  useQueryTransformation: readString(env, "RAG_USE_QUERY_TRANSFORMATION") === "true",
2323
2334
  useReranking: readString(env, "RAG_USE_RERANKING") === "true",
2324
2335
  useGraphRetrieval: readString(env, "RAG_USE_GRAPH_RETRIEVAL") === "true",
2325
- architecture: (_Ia = readString(env, "RAG_ARCHITECTURE")) != null ? _Ia : "simple",
2326
- chunkingStrategy: (_Ja = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _Ja : "recursive",
2336
+ architecture: (_Ka = readString(env, "RAG_ARCHITECTURE")) != null ? _Ka : "simple",
2337
+ chunkingStrategy: (_La = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _La : "recursive",
2327
2338
  uiMapping: (() => {
2328
2339
  const raw = readString(env, "RAG_UI_MAPPING");
2329
2340
  if (!raw) return void 0;
@@ -2333,6 +2344,10 @@ function getEnvConfig(env = process.env, base) {
2333
2344
  return void 0;
2334
2345
  }
2335
2346
  })()
2347
+ },
2348
+ telemetry: {
2349
+ enabled: readString(env, "TELEMETRY_ENABLED") === "true" || readString(env, "NEXT_PUBLIC_TELEMETRY_ENABLED") === "true" || ((_Ma = base == null ? void 0 : base.telemetry) == null ? void 0 : _Ma.enabled) || false,
2350
+ url: (_Qa = (_Pa = (_Na = readString(env, "TELEMETRY_URL")) != null ? _Na : readString(env, "NEXT_PUBLIC_TELEMETRY_URL")) != null ? _Pa : (_Oa = base == null ? void 0 : base.telemetry) == null ? void 0 : _Oa.url) != null ? _Qa : "/api/telemetry"
2336
2351
  }
2337
2352
  }, readString(env, "GRAPH_DB_PROVIDER") ? {
2338
2353
  graphDb: {
@@ -2343,7 +2358,19 @@ function getEnvConfig(env = process.env, base) {
2343
2358
  password: readString(env, "GRAPH_DB_PASSWORD")
2344
2359
  }
2345
2360
  }
2346
- } : {});
2361
+ } : {}), {
2362
+ mcpServers: (() => {
2363
+ var _a3;
2364
+ const raw = (_a3 = readString(env, "MCP_SERVERS")) != null ? _a3 : readString(env, "NEXT_PUBLIC_MCP_SERVERS");
2365
+ if (!raw) return void 0;
2366
+ try {
2367
+ return JSON.parse(raw);
2368
+ } catch (e) {
2369
+ console.warn("[serverConfig] Failed to parse MCP_SERVERS env:", e);
2370
+ return void 0;
2371
+ }
2372
+ })()
2373
+ });
2347
2374
  }
2348
2375
 
2349
2376
  // src/core/ConfigResolver.ts
@@ -2369,7 +2396,8 @@ var ConfigResolver = class {
2369
2396
  options: __spreadValues(__spreadValues({}, envConfig.embedding.options || {}), hostConfig.embedding.options || {})
2370
2397
  }) : envConfig.embedding,
2371
2398
  ui: hostConfig.ui ? mergeDefined(envConfig.ui, hostConfig.ui) : envConfig.ui,
2372
- rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag
2399
+ rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag,
2400
+ telemetry: hostConfig.telemetry ? __spreadValues(__spreadValues({}, envConfig.telemetry), hostConfig.telemetry) : envConfig.telemetry
2373
2401
  });
2374
2402
  }
2375
2403
  /**
@@ -2378,10 +2406,10 @@ var ConfigResolver = class {
2378
2406
  * fallback behavior.
2379
2407
  */
2380
2408
  static resolveUniversal(hostConfig, env = process.env) {
2381
- var _a;
2409
+ var _a2;
2382
2410
  if (!hostConfig) return this.resolve(void 0, env);
2383
2411
  const normalized = __spreadProps(__spreadValues({}, hostConfig), {
2384
- vectorDb: (_a = hostConfig.vectorDb) != null ? _a : hostConfig.vectorDatabase,
2412
+ vectorDb: (_a2 = hostConfig.vectorDb) != null ? _a2 : hostConfig.vectorDatabase,
2385
2413
  rag: this.mergeRetrievalWorkflow(hostConfig.rag, hostConfig.retrieval, hostConfig.workflow)
2386
2414
  });
2387
2415
  return this.resolve(normalized, env);
@@ -2401,28 +2429,52 @@ var ConfigResolver = class {
2401
2429
  }
2402
2430
  }
2403
2431
  static mergeRetrievalWorkflow(rag, retrieval, workflow) {
2404
- var _a, _b, _c, _d, _e;
2432
+ var _a2, _b, _c, _d, _e, _f;
2405
2433
  if (!rag && !retrieval && !workflow) return void 0;
2406
2434
  const normalized = __spreadValues({}, rag != null ? rag : {});
2407
2435
  if (retrieval) {
2408
- normalized.topK = (_a = retrieval.topK) != null ? _a : normalized.topK;
2436
+ normalized.topK = (_a2 = retrieval.topK) != null ? _a2 : normalized.topK;
2409
2437
  normalized.scoreThreshold = (_b = retrieval.scoreThreshold) != null ? _b : normalized.scoreThreshold;
2410
2438
  normalized.useReranking = (_c = retrieval.useReranking) != null ? _c : normalized.useReranking;
2411
2439
  if (retrieval.strategy === "hybrid") normalized.architecture = (_d = normalized.architecture) != null ? _d : "hybrid";
2412
- if (retrieval.strategy === "agentic") normalized.architecture = "agentic";
2413
- if (retrieval.strategy === "contextual-compression") normalized.useReranking = true;
2440
+ if (retrieval.strategy === "agentic") normalized.architecture = "multi-agent";
2441
+ if (retrieval.strategy === "contextual-compression") {
2442
+ normalized.useReranking = true;
2443
+ normalized.architecture = (_e = normalized.architecture) != null ? _e : "retrieve-and-rerank";
2444
+ }
2414
2445
  }
2415
2446
  if (workflow == null ? void 0 : workflow.type) {
2416
2447
  const type = workflow.type;
2417
- if (type === "agentic" || type === "agentic-rag") normalized.architecture = "agentic";
2418
- else if (type === "hybrid-rag") normalized.architecture = "hybrid";
2419
- else if (type === "graph-rag") {
2448
+ if (type === "naive-rag") {
2449
+ normalized.architecture = "naive";
2450
+ normalized.useReranking = false;
2451
+ normalized.useGraphRetrieval = false;
2452
+ } else if (type === "retrieve-and-rerank") {
2453
+ normalized.architecture = "retrieve-and-rerank";
2454
+ normalized.useReranking = true;
2455
+ } else if (type === "multimodal-rag") {
2456
+ normalized.architecture = "multimodal";
2457
+ } else if (type === "graph-rag") {
2420
2458
  normalized.architecture = "graph";
2421
2459
  normalized.useGraphRetrieval = true;
2460
+ } else if (type === "hybrid-rag") {
2461
+ normalized.architecture = "hybrid";
2462
+ } else if (type === "agentic-router") {
2463
+ normalized.architecture = "agentic-router";
2464
+ } else if (type === "multi-agent-rag" || type === "multi-agent" || type === "agentic" || type === "agentic-rag") {
2465
+ normalized.architecture = "multi-agent";
2422
2466
  } else if (type === "simple-rag" || type === "rag") {
2423
- normalized.architecture = (_e = normalized.architecture) != null ? _e : "simple";
2467
+ normalized.architecture = (_f = normalized.architecture) != null ? _f : "naive";
2424
2468
  }
2425
2469
  }
2470
+ if (normalized.architecture === "retrieve-and-rerank") {
2471
+ normalized.useReranking = true;
2472
+ } else if (normalized.architecture === "graph") {
2473
+ normalized.useGraphRetrieval = true;
2474
+ } else if (normalized.architecture === "naive") {
2475
+ normalized.useReranking = false;
2476
+ normalized.useGraphRetrieval = false;
2477
+ }
2426
2478
  return normalized;
2427
2479
  }
2428
2480
  };
@@ -2487,8 +2539,8 @@ var OpenAIProvider = class {
2487
2539
  const apiKey = config.apiKey;
2488
2540
  const modelName = config.model;
2489
2541
  try {
2490
- const OpenAI2 = await import("openai");
2491
- const client = new OpenAI2.default({ apiKey });
2542
+ const OpenAI4 = await import("openai");
2543
+ const client = new OpenAI4.default({ apiKey });
2492
2544
  const models = await client.models.list();
2493
2545
  const hasModel = models.data.some((m) => m.id === modelName);
2494
2546
  return {
@@ -2509,8 +2561,8 @@ var OpenAIProvider = class {
2509
2561
  };
2510
2562
  }
2511
2563
  async chat(messages, context, options) {
2512
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2513
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
2564
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
2565
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
2514
2566
  const systemMessage = {
2515
2567
  role: "system",
2516
2568
  content: buildSystemContent(basePrompt, context)
@@ -2529,12 +2581,12 @@ var OpenAIProvider = class {
2529
2581
  temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
2530
2582
  stop: options == null ? void 0 : options.stop
2531
2583
  });
2532
- return (_i = (_h = (_g = completion.choices[0]) == null ? void 0 : _g.message) == null ? void 0 : _h.content) != null ? _i : "";
2584
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
2533
2585
  }
2534
2586
  chatStream(messages, context, options) {
2535
2587
  return __asyncGenerator(this, null, function* () {
2536
- var _a, _b, _c, _d, _e, _f, _g, _h;
2537
- 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.";
2588
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
2589
+ 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.";
2538
2590
  const systemMessage = {
2539
2591
  role: "system",
2540
2592
  content: buildSystemContent(basePrompt, context)
@@ -2560,7 +2612,7 @@ var OpenAIProvider = class {
2560
2612
  try {
2561
2613
  for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2562
2614
  const chunk = temp.value;
2563
- const content = ((_h = (_g = chunk.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content) || "";
2615
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
2564
2616
  if (content) yield content;
2565
2617
  }
2566
2618
  } catch (temp) {
@@ -2580,8 +2632,8 @@ var OpenAIProvider = class {
2580
2632
  return results[0];
2581
2633
  }
2582
2634
  async batchEmbed(texts, options) {
2583
- var _a, _b, _c, _d, _e;
2584
- 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";
2635
+ var _a2, _b, _c, _d, _e;
2636
+ 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";
2585
2637
  const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
2586
2638
  const client = apiKey !== this.llmConfig.apiKey ? new import_openai.default({ apiKey }) : this.client;
2587
2639
  const response = await client.embeddings.create({ model, input: texts });
@@ -2658,8 +2710,8 @@ var AnthropicProvider = class {
2658
2710
  };
2659
2711
  }
2660
2712
  async chat(messages, context, options) {
2661
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2662
- 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.";
2713
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2714
+ 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.";
2663
2715
  const system = buildSystemContent(basePrompt, context);
2664
2716
  const anthropicMessages = messages.map((m) => ({
2665
2717
  role: m.role === "assistant" ? "assistant" : "user",
@@ -2670,7 +2722,7 @@ var AnthropicProvider = class {
2670
2722
  const extraParams = {};
2671
2723
  if (isThinkingEnabled && isClaude37) {
2672
2724
  extraParams.betas = ["interleaved-thinking-2025-05-14"];
2673
- const maxTokens = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
2725
+ const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
2674
2726
  const budget = Math.min(
2675
2727
  typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
2676
2728
  maxTokens - 1
@@ -2697,8 +2749,8 @@ var AnthropicProvider = class {
2697
2749
  }
2698
2750
  chatStream(messages, context, options) {
2699
2751
  return __asyncGenerator(this, null, function* () {
2700
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2701
- 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.";
2752
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2753
+ 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.";
2702
2754
  const system = buildSystemContent(basePrompt, context);
2703
2755
  const anthropicMessages = messages.map((m) => ({
2704
2756
  role: m.role === "assistant" ? "assistant" : "user",
@@ -2709,7 +2761,7 @@ var AnthropicProvider = class {
2709
2761
  const extraParams = {};
2710
2762
  if (isThinkingEnabled && isClaude37) {
2711
2763
  extraParams.betas = ["interleaved-thinking-2025-05-14"];
2712
- const maxTokens = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
2764
+ const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
2713
2765
  const budget = Math.min(
2714
2766
  typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
2715
2767
  maxTokens - 1
@@ -2782,8 +2834,8 @@ var AnthropicProvider = class {
2782
2834
  var import_axios = __toESM(require("axios"));
2783
2835
  var OllamaProvider = class {
2784
2836
  constructor(llmConfig, embeddingConfig) {
2785
- var _a, _b;
2786
- const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
2837
+ var _a2, _b;
2838
+ const baseURL = (_a2 = llmConfig.baseUrl) != null ? _a2 : "http://localhost:11434";
2787
2839
  const timeout = Number((_b = llmConfig.options) == null ? void 0 : _b.timeout) || 3e5;
2788
2840
  this.http = import_axios.default.create({ baseURL, timeout });
2789
2841
  this.llmConfig = llmConfig;
@@ -2841,8 +2893,8 @@ var OllamaProvider = class {
2841
2893
  };
2842
2894
  }
2843
2895
  async chat(messages, context, options) {
2844
- var _a, _b, _c, _d, _e, _f;
2845
- 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.";
2896
+ var _a2, _b, _c, _d, _e, _f;
2897
+ 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.";
2846
2898
  const system = buildSystemContent(basePrompt, context);
2847
2899
  const { data } = await this.http.post("/api/chat", {
2848
2900
  model: this.llmConfig.model,
@@ -2860,8 +2912,8 @@ var OllamaProvider = class {
2860
2912
  }
2861
2913
  chatStream(messages, context, options) {
2862
2914
  return __asyncGenerator(this, null, function* () {
2863
- var _a, _b, _c, _d, _e, _f, _g, _h;
2864
- 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.";
2915
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
2916
+ 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.";
2865
2917
  const system = buildSystemContent(basePrompt, context);
2866
2918
  const response = yield new __await(this.http.post("/api/chat", {
2867
2919
  model: this.llmConfig.model,
@@ -2890,7 +2942,7 @@ var OllamaProvider = class {
2890
2942
  if (!line.trim()) continue;
2891
2943
  try {
2892
2944
  const json = JSON.parse(line);
2893
- if ((_g = json.message) == null ? void 0 : _g.content) {
2945
+ if ((_g2 = json.message) == null ? void 0 : _g2.content) {
2894
2946
  yield json.message.content;
2895
2947
  }
2896
2948
  if (json.done) return;
@@ -2919,10 +2971,10 @@ var OllamaProvider = class {
2919
2971
  });
2920
2972
  }
2921
2973
  async embed(text, options) {
2922
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2923
- 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";
2974
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2975
+ 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";
2924
2976
  const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
2925
- const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
2977
+ const client = baseURL !== ((_g2 = this.llmConfig.baseUrl) != null ? _g2 : "http://localhost:11434") ? import_axios.default.create({ baseURL, timeout: 6e4 }) : this.http;
2926
2978
  let prompt = text;
2927
2979
  const queryPrefix = (_i = (_h = this.embeddingConfig) == null ? void 0 : _h.queryPrefix) != null ? _i : model.includes("nomic") ? "search_query: " : "";
2928
2980
  const docPrefix = (_k = (_j = this.embeddingConfig) == null ? void 0 : _j.documentPrefix) != null ? _k : model.includes("nomic") ? "search_document: " : "";
@@ -3021,9 +3073,9 @@ var GeminiProvider = class {
3021
3073
  static getHealthChecker() {
3022
3074
  return {
3023
3075
  async check(config) {
3024
- var _a, _b;
3076
+ var _a2, _b;
3025
3077
  const timestamp = Date.now();
3026
- const apiKey = (_b = (_a = config.apiKey) != null ? _a : process.env.GOOGLE_GENAI_API_KEY) != null ? _b : "";
3078
+ const apiKey = (_b = (_a2 = config.apiKey) != null ? _a2 : process.env.GOOGLE_GENAI_API_KEY) != null ? _b : "";
3027
3079
  const modelName = sanitizeModel(config.model);
3028
3080
  try {
3029
3081
  const { GoogleGenerativeAI: GoogleGenerativeAI2 } = await import("@google/generative-ai");
@@ -3053,16 +3105,16 @@ var GeminiProvider = class {
3053
3105
  /** Resolve the embedding client — uses a separate client when the embedding
3054
3106
  * API key differs from the LLM API key. */
3055
3107
  get embeddingClient() {
3056
- var _a;
3057
- if (((_a = this.embeddingConfig) == null ? void 0 : _a.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
3108
+ var _a2;
3109
+ if (((_a2 = this.embeddingConfig) == null ? void 0 : _a2.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
3058
3110
  return buildClient(this.embeddingConfig.apiKey);
3059
3111
  }
3060
3112
  return this.client;
3061
3113
  }
3062
3114
  /** Resolve the embedding model to use, in order of specificity. */
3063
3115
  resolveEmbeddingModel(optionsModel) {
3064
- var _a, _b;
3065
- return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
3116
+ var _a2, _b;
3117
+ return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
3066
3118
  }
3067
3119
  /**
3068
3120
  * Convert ChatMessage[] to the Gemini contents format.
@@ -3082,8 +3134,8 @@ var GeminiProvider = class {
3082
3134
  // ILLMProvider — chat
3083
3135
  // -------------------------------------------------------------------------
3084
3136
  async chat(messages, context, options) {
3085
- var _a, _b, _c, _d, _e, _f;
3086
- 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.";
3137
+ var _a2, _b, _c, _d, _e, _f;
3138
+ 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.";
3087
3139
  const model = this.client.getGenerativeModel({
3088
3140
  model: this.llmConfig.model,
3089
3141
  systemInstruction: buildSystemContent(basePrompt, context)
@@ -3100,8 +3152,8 @@ var GeminiProvider = class {
3100
3152
  }
3101
3153
  chatStream(messages, context, options) {
3102
3154
  return __asyncGenerator(this, null, function* () {
3103
- var _a, _b, _c, _d, _e, _f;
3104
- 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.";
3155
+ var _a2, _b, _c, _d, _e, _f;
3156
+ 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.";
3105
3157
  const model = this.client.getGenerativeModel({
3106
3158
  model: this.llmConfig.model,
3107
3159
  systemInstruction: buildSystemContent(basePrompt, context)
@@ -3136,11 +3188,11 @@ var GeminiProvider = class {
3136
3188
  // ILLMProvider — embeddings
3137
3189
  // -------------------------------------------------------------------------
3138
3190
  async embed(text, options) {
3139
- var _a, _b;
3191
+ var _a2, _b;
3140
3192
  const content = applyPrefix(
3141
3193
  text,
3142
3194
  options == null ? void 0 : options.taskType,
3143
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
3195
+ (_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
3144
3196
  (_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
3145
3197
  );
3146
3198
  const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
@@ -3157,7 +3209,7 @@ var GeminiProvider = class {
3157
3209
  const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
3158
3210
  const model = this.embeddingClient.getGenerativeModel({ model: modelName });
3159
3211
  const requests = texts.map((text) => {
3160
- var _a, _b;
3212
+ var _a2, _b;
3161
3213
  return {
3162
3214
  content: {
3163
3215
  role: "user",
@@ -3165,7 +3217,7 @@ var GeminiProvider = class {
3165
3217
  text: applyPrefix(
3166
3218
  text,
3167
3219
  options == null ? void 0 : options.taskType,
3168
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
3220
+ (_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
3169
3221
  (_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
3170
3222
  )
3171
3223
  }]
@@ -3182,8 +3234,8 @@ var GeminiProvider = class {
3182
3234
  throw err;
3183
3235
  });
3184
3236
  return response.embeddings.map((e) => {
3185
- var _a;
3186
- return (_a = e.values) != null ? _a : [];
3237
+ var _a2;
3238
+ return (_a2 = e.values) != null ? _a2 : [];
3187
3239
  });
3188
3240
  }
3189
3241
  // -------------------------------------------------------------------------
@@ -3203,6 +3255,325 @@ var GeminiProvider = class {
3203
3255
  }
3204
3256
  };
3205
3257
 
3258
+ // src/llm/providers/GroqProvider.ts
3259
+ var import_openai2 = __toESM(require("openai"));
3260
+ var GroqProvider = class {
3261
+ constructor(llmConfig, embeddingConfig) {
3262
+ void embeddingConfig;
3263
+ const apiKey = llmConfig.apiKey || process.env.GROQ_API_KEY;
3264
+ if (!apiKey) throw new Error("[GroqProvider] llmConfig.apiKey or GROQ_API_KEY environment variable is required");
3265
+ this.client = new import_openai2.default({
3266
+ apiKey,
3267
+ baseURL: llmConfig.baseUrl || "https://api.groq.com/openai/v1"
3268
+ });
3269
+ this.llmConfig = llmConfig;
3270
+ }
3271
+ static getValidator() {
3272
+ return {
3273
+ validate(config) {
3274
+ const errors = [];
3275
+ if (!config.apiKey && !process.env.GROQ_API_KEY) {
3276
+ errors.push({
3277
+ field: "llm.apiKey",
3278
+ message: "Groq API key is required",
3279
+ suggestion: "Set GROQ_API_KEY environment variable",
3280
+ severity: "error"
3281
+ });
3282
+ }
3283
+ if (!config.model) {
3284
+ errors.push({
3285
+ field: "llm.model",
3286
+ message: "Groq model name is required",
3287
+ suggestion: 'e.g., "llama-3.3-70b-versatile"',
3288
+ severity: "error"
3289
+ });
3290
+ }
3291
+ return errors;
3292
+ }
3293
+ };
3294
+ }
3295
+ static getHealthChecker() {
3296
+ return {
3297
+ async check(config) {
3298
+ const timestamp = Date.now();
3299
+ const apiKey = config.apiKey || process.env.GROQ_API_KEY || "";
3300
+ const modelName = config.model;
3301
+ try {
3302
+ const OpenAI4 = await import("openai");
3303
+ const client = new OpenAI4.default({
3304
+ apiKey,
3305
+ baseURL: config.baseUrl || "https://api.groq.com/openai/v1"
3306
+ });
3307
+ const models = await client.models.list();
3308
+ const hasModel = models.data.some((m) => m.id === modelName);
3309
+ return {
3310
+ healthy: true,
3311
+ provider: "groq",
3312
+ capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
3313
+ timestamp
3314
+ };
3315
+ } catch (error) {
3316
+ return {
3317
+ healthy: false,
3318
+ provider: "groq",
3319
+ error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
3320
+ timestamp
3321
+ };
3322
+ }
3323
+ }
3324
+ };
3325
+ }
3326
+ async chat(messages, context, options) {
3327
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
3328
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3329
+ const systemMessage = {
3330
+ role: "system",
3331
+ content: buildSystemContent(basePrompt, context)
3332
+ };
3333
+ const formattedMessages = [
3334
+ systemMessage,
3335
+ ...messages.map((m) => ({
3336
+ role: m.role,
3337
+ content: m.content
3338
+ }))
3339
+ ];
3340
+ const completion = await this.client.chat.completions.create({
3341
+ model: this.llmConfig.model,
3342
+ messages: formattedMessages,
3343
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3344
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3345
+ stop: options == null ? void 0 : options.stop
3346
+ });
3347
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
3348
+ }
3349
+ chatStream(messages, context, options) {
3350
+ return __asyncGenerator(this, null, function* () {
3351
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3352
+ 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.";
3353
+ const systemMessage = {
3354
+ role: "system",
3355
+ content: buildSystemContent(basePrompt, context)
3356
+ };
3357
+ const formattedMessages = [
3358
+ systemMessage,
3359
+ ...messages.map((m) => ({
3360
+ role: m.role,
3361
+ content: m.content
3362
+ }))
3363
+ ];
3364
+ const stream = yield new __await(this.client.chat.completions.create({
3365
+ model: this.llmConfig.model,
3366
+ messages: formattedMessages,
3367
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3368
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3369
+ stop: options == null ? void 0 : options.stop,
3370
+ stream: true
3371
+ }));
3372
+ if (!stream) {
3373
+ throw new Error("[GroqProvider] completions.create stream is undefined");
3374
+ }
3375
+ try {
3376
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
3377
+ const chunk = temp.value;
3378
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
3379
+ if (content) yield content;
3380
+ }
3381
+ } catch (temp) {
3382
+ error = [temp];
3383
+ } finally {
3384
+ try {
3385
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
3386
+ } finally {
3387
+ if (error)
3388
+ throw error[0];
3389
+ }
3390
+ }
3391
+ });
3392
+ }
3393
+ async embed(text, options) {
3394
+ void text;
3395
+ void options;
3396
+ throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
3397
+ }
3398
+ async batchEmbed(texts, options) {
3399
+ void texts;
3400
+ void options;
3401
+ throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
3402
+ }
3403
+ async ping() {
3404
+ try {
3405
+ await this.client.models.list();
3406
+ return true;
3407
+ } catch (err) {
3408
+ console.error("[GroqProvider] Ping failed:", err);
3409
+ return false;
3410
+ }
3411
+ }
3412
+ };
3413
+
3414
+ // src/llm/providers/QwenProvider.ts
3415
+ var import_openai3 = __toESM(require("openai"));
3416
+ var QwenProvider = class {
3417
+ constructor(llmConfig, embeddingConfig) {
3418
+ const apiKey = llmConfig.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY;
3419
+ if (!apiKey) throw new Error("[QwenProvider] llmConfig.apiKey, DASHSCOPE_API_KEY, or QWEN_API_KEY environment variable is required");
3420
+ this.client = new import_openai3.default({
3421
+ apiKey,
3422
+ baseURL: llmConfig.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3423
+ });
3424
+ this.llmConfig = llmConfig;
3425
+ this.embeddingConfig = embeddingConfig;
3426
+ }
3427
+ static getValidator() {
3428
+ return {
3429
+ validate(config) {
3430
+ const errors = [];
3431
+ const isEmbedding = config.provider === "qwen" && "dimensions" in config;
3432
+ const prefix = isEmbedding ? "embedding" : "llm";
3433
+ if (!config.apiKey && !process.env.DASHSCOPE_API_KEY && !process.env.QWEN_API_KEY) {
3434
+ errors.push({
3435
+ field: `${prefix}.apiKey`,
3436
+ message: "Qwen API key is required",
3437
+ suggestion: "Set DASHSCOPE_API_KEY or QWEN_API_KEY environment variable",
3438
+ severity: "error"
3439
+ });
3440
+ }
3441
+ if (!config.model) {
3442
+ errors.push({
3443
+ field: `${prefix}.model`,
3444
+ message: "Qwen model name is required",
3445
+ suggestion: isEmbedding ? 'e.g., "text-embedding-v3"' : 'e.g., "qwen-plus" or "qwen-max"',
3446
+ severity: "error"
3447
+ });
3448
+ }
3449
+ return errors;
3450
+ }
3451
+ };
3452
+ }
3453
+ static getHealthChecker() {
3454
+ return {
3455
+ async check(config) {
3456
+ const timestamp = Date.now();
3457
+ const apiKey = config.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY || "";
3458
+ const modelName = config.model;
3459
+ try {
3460
+ const OpenAI4 = await import("openai");
3461
+ const client = new OpenAI4.default({
3462
+ apiKey,
3463
+ baseURL: config.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3464
+ });
3465
+ const models = await client.models.list();
3466
+ const hasModel = models.data.some((m) => m.id === modelName);
3467
+ return {
3468
+ healthy: true,
3469
+ provider: "qwen",
3470
+ capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
3471
+ timestamp
3472
+ };
3473
+ } catch (error) {
3474
+ return {
3475
+ healthy: false,
3476
+ provider: "qwen",
3477
+ error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
3478
+ timestamp
3479
+ };
3480
+ }
3481
+ }
3482
+ };
3483
+ }
3484
+ async chat(messages, context, options) {
3485
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
3486
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3487
+ const systemMessage = {
3488
+ role: "system",
3489
+ content: buildSystemContent(basePrompt, context)
3490
+ };
3491
+ const formattedMessages = [
3492
+ systemMessage,
3493
+ ...messages.map((m) => ({
3494
+ role: m.role,
3495
+ content: m.content
3496
+ }))
3497
+ ];
3498
+ const completion = await this.client.chat.completions.create({
3499
+ model: this.llmConfig.model,
3500
+ messages: formattedMessages,
3501
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3502
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3503
+ stop: options == null ? void 0 : options.stop
3504
+ });
3505
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
3506
+ }
3507
+ chatStream(messages, context, options) {
3508
+ return __asyncGenerator(this, null, function* () {
3509
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3510
+ 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.";
3511
+ const systemMessage = {
3512
+ role: "system",
3513
+ content: buildSystemContent(basePrompt, context)
3514
+ };
3515
+ const formattedMessages = [
3516
+ systemMessage,
3517
+ ...messages.map((m) => ({
3518
+ role: m.role,
3519
+ content: m.content
3520
+ }))
3521
+ ];
3522
+ const stream = yield new __await(this.client.chat.completions.create({
3523
+ model: this.llmConfig.model,
3524
+ messages: formattedMessages,
3525
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3526
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3527
+ stop: options == null ? void 0 : options.stop,
3528
+ stream: true
3529
+ }));
3530
+ if (!stream) {
3531
+ throw new Error("[QwenProvider] completions.create stream is undefined");
3532
+ }
3533
+ try {
3534
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
3535
+ const chunk = temp.value;
3536
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
3537
+ if (content) yield content;
3538
+ }
3539
+ } catch (temp) {
3540
+ error = [temp];
3541
+ } finally {
3542
+ try {
3543
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
3544
+ } finally {
3545
+ if (error)
3546
+ throw error[0];
3547
+ }
3548
+ }
3549
+ });
3550
+ }
3551
+ async embed(text, options) {
3552
+ const results = await this.batchEmbed([text], options);
3553
+ return results[0];
3554
+ }
3555
+ async batchEmbed(texts, options) {
3556
+ var _a2, _b, _c, _d, _e, _f;
3557
+ 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";
3558
+ const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
3559
+ const client = apiKey !== this.llmConfig.apiKey ? new import_openai3.default({
3560
+ apiKey,
3561
+ baseURL: ((_f = this.embeddingConfig) == null ? void 0 : _f.baseUrl) || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3562
+ }) : this.client;
3563
+ const response = await client.embeddings.create({ model, input: texts });
3564
+ return response.data.map((d) => d.embedding);
3565
+ }
3566
+ async ping() {
3567
+ try {
3568
+ await this.client.models.list();
3569
+ return true;
3570
+ } catch (err) {
3571
+ console.error("[QwenProvider] Ping failed:", err);
3572
+ return false;
3573
+ }
3574
+ }
3575
+ };
3576
+
3206
3577
  // src/llm/providers/UniversalLLMAdapter.ts
3207
3578
  var import_axios2 = __toESM(require("axios"));
3208
3579
  init_templateUtils();
@@ -3286,10 +3657,10 @@ var VECTOR_PROFILES = {
3286
3657
  // src/llm/providers/UniversalLLMAdapter.ts
3287
3658
  var UniversalLLMAdapter = class {
3288
3659
  constructor(config) {
3289
- var _a, _b, _c, _d, _e, _f, _g, _h;
3660
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3290
3661
  this.model = config.model;
3291
3662
  const llmConfig = config;
3292
- const options = (_a = llmConfig.options) != null ? _a : {};
3663
+ const options = (_a2 = llmConfig.options) != null ? _a2 : {};
3293
3664
  let profile = {};
3294
3665
  if (typeof options.profile === "string") {
3295
3666
  profile = LLM_PROFILES[options.profile] || {};
@@ -3301,7 +3672,7 @@ var UniversalLLMAdapter = class {
3301
3672
  this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
3302
3673
  this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
3303
3674
  this.apiKey = config.apiKey;
3304
- this.baseUrl = (_g = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g : "";
3675
+ this.baseUrl = (_g2 = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g2 : "";
3305
3676
  if (!this.baseUrl) {
3306
3677
  throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
3307
3678
  }
@@ -3315,8 +3686,8 @@ var UniversalLLMAdapter = class {
3315
3686
  });
3316
3687
  }
3317
3688
  async chat(messages, context) {
3318
- var _a, _b;
3319
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
3689
+ var _a2, _b;
3690
+ const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3320
3691
  const formattedMessages = [
3321
3692
  { role: "system", content: `${this.systemPrompt}
3322
3693
 
@@ -3340,7 +3711,7 @@ ${context != null ? context : "None"}` },
3340
3711
  temperature: this.temperature
3341
3712
  };
3342
3713
  }
3343
- const { data } = await this.http.post(path, payload);
3714
+ const { data } = await this.http.post(path2, payload);
3344
3715
  const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
3345
3716
  const result = resolvePath(data, extractPath);
3346
3717
  if (result === void 0) {
@@ -3355,9 +3726,9 @@ ${context != null ? context : "None"}` },
3355
3726
  */
3356
3727
  chatStream(messages, context) {
3357
3728
  return __asyncGenerator(this, null, function* () {
3358
- var _a, _b, _c;
3359
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
3360
- const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
3729
+ var _a2, _b, _c;
3730
+ const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3731
+ const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3361
3732
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
3362
3733
  const formattedMessages = [
3363
3734
  { role: "system", content: `${this.systemPrompt}
@@ -3435,8 +3806,8 @@ ${context != null ? context : "None"}` },
3435
3806
  });
3436
3807
  }
3437
3808
  async embed(text) {
3438
- var _a, _b;
3439
- const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
3809
+ var _a2, _b;
3810
+ const path2 = (_a2 = this.opts.embedPath) != null ? _a2 : "/embeddings";
3440
3811
  let payload;
3441
3812
  if (this.opts.embedPayloadTemplate) {
3442
3813
  payload = buildPayload(this.opts.embedPayloadTemplate, {
@@ -3449,7 +3820,7 @@ ${context != null ? context : "None"}` },
3449
3820
  input: text
3450
3821
  };
3451
3822
  }
3452
- const { data } = await this.http.post(path, payload);
3823
+ const { data } = await this.http.post(path2, payload);
3453
3824
  const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
3454
3825
  const vector = resolvePath(data, extractPath);
3455
3826
  if (!Array.isArray(vector)) {
@@ -3517,13 +3888,13 @@ var AuthenticationException = class extends RetrivoraError {
3517
3888
  }
3518
3889
  };
3519
3890
  function wrapError(err, defaultCode, defaultMessage) {
3520
- var _a;
3891
+ var _a2;
3521
3892
  if (err instanceof RetrivoraError) {
3522
3893
  return err;
3523
3894
  }
3524
3895
  const error = err;
3525
3896
  const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
3526
- const status = (error == null ? void 0 : error.status) || (error == null ? void 0 : error.statusCode) || ((_a = error == null ? void 0 : error.response) == null ? void 0 : _a.status);
3897
+ 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);
3527
3898
  const code = error == null ? void 0 : error.code;
3528
3899
  if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
3529
3900
  return new RateLimitException(message, err);
@@ -3587,6 +3958,8 @@ var LLMFactory = class _LLMFactory {
3587
3958
  "anthropic",
3588
3959
  "ollama",
3589
3960
  "gemini",
3961
+ "groq",
3962
+ "qwen",
3590
3963
  "rest",
3591
3964
  "universal_rest",
3592
3965
  "custom",
@@ -3594,7 +3967,7 @@ var LLMFactory = class _LLMFactory {
3594
3967
  ];
3595
3968
  }
3596
3969
  static create(llmConfig, embeddingConfig) {
3597
- var _a, _b, _c;
3970
+ var _a2, _b, _c;
3598
3971
  switch (llmConfig.provider) {
3599
3972
  case "openai":
3600
3973
  return new OpenAIProvider(llmConfig, embeddingConfig);
@@ -3604,12 +3977,16 @@ var LLMFactory = class _LLMFactory {
3604
3977
  return new OllamaProvider(llmConfig, embeddingConfig);
3605
3978
  case "gemini":
3606
3979
  return new GeminiProvider(llmConfig, embeddingConfig);
3980
+ case "groq":
3981
+ return new GroqProvider(llmConfig, embeddingConfig);
3982
+ case "qwen":
3983
+ return new QwenProvider(llmConfig, embeddingConfig);
3607
3984
  case "rest":
3608
3985
  case "universal_rest":
3609
3986
  case "custom":
3610
3987
  return new UniversalLLMAdapter(llmConfig);
3611
3988
  default: {
3612
- const providerName = String((_a = llmConfig.provider) != null ? _a : "").toLowerCase();
3989
+ const providerName = String((_a2 = llmConfig.provider) != null ? _a2 : "").toLowerCase();
3613
3990
  const customFactory = customProviders.get(providerName);
3614
3991
  if (customFactory) {
3615
3992
  return customFactory(llmConfig);
@@ -3646,6 +4023,10 @@ var LLMFactory = class _LLMFactory {
3646
4023
  return OllamaProvider;
3647
4024
  case "gemini":
3648
4025
  return GeminiProvider;
4026
+ case "groq":
4027
+ return GroqProvider;
4028
+ case "qwen":
4029
+ return QwenProvider;
3649
4030
  case "rest":
3650
4031
  case "universal_rest":
3651
4032
  case "custom":
@@ -3707,7 +4088,7 @@ var ProviderRegistry = class {
3707
4088
  return null;
3708
4089
  }
3709
4090
  static async loadVectorProviderClass(provider) {
3710
- var _a;
4091
+ var _a2;
3711
4092
  if (this.vectorProviders[provider]) return this.vectorProviders[provider];
3712
4093
  switch (provider) {
3713
4094
  case "pinecone": {
@@ -3716,7 +4097,7 @@ var ProviderRegistry = class {
3716
4097
  }
3717
4098
  case "pgvector":
3718
4099
  case "postgresql": {
3719
- const postgresMode = ((_a = process.env.POSTGRES_MODE) != null ? _a : "multi").toLowerCase();
4100
+ const postgresMode = ((_a2 = process.env.POSTGRES_MODE) != null ? _a2 : "multi").toLowerCase();
3720
4101
  if (postgresMode === "single") {
3721
4102
  const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
3722
4103
  return PostgreSQLProvider2;
@@ -3936,6 +4317,211 @@ var ConfigValidator = class {
3936
4317
  }
3937
4318
  };
3938
4319
 
4320
+ // src/core/LicenseVerifier.ts
4321
+ var crypto2 = __toESM(require("crypto"));
4322
+ var LicenseVerifier = class {
4323
+ /**
4324
+ * Decodes, verifies signature, and checks metadata of a license key.
4325
+ *
4326
+ * @param licenseKey - Base64url signed JWT license key.
4327
+ * @param currentProjectId - Project namespace ID.
4328
+ * @param publicKeyOverride - Optional override for unit/integration tests.
4329
+ */
4330
+ static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
4331
+ const isProduction = process.env.NODE_ENV === "production";
4332
+ const now = Date.now();
4333
+ if (licenseKey) {
4334
+ const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
4335
+ const cached = this.cache.get(cacheKey);
4336
+ if (cached && now - cached.cachedAt < this.CACHE_TTL_MS) {
4337
+ const currentTimestampSec = Math.floor(now / 1e3);
4338
+ if (cached.payload.expiresAt && currentTimestampSec > cached.payload.expiresAt) {
4339
+ this.cache.delete(cacheKey);
4340
+ } else {
4341
+ return cached.payload;
4342
+ }
4343
+ }
4344
+ }
4345
+ if (!licenseKey) {
4346
+ if (isProduction) {
4347
+ throw new ConfigurationException(
4348
+ "[Retrivora SDK] License key (licenseKey) is required in production environments."
4349
+ );
4350
+ }
4351
+ console.warn(
4352
+ `\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
4353
+ );
4354
+ return {
4355
+ projectId: currentProjectId,
4356
+ expiresAt: Math.floor(Date.now() / 1e3) + 86400,
4357
+ // Valid for 24h
4358
+ tier: "hobby"
4359
+ };
4360
+ }
4361
+ try {
4362
+ const parts = licenseKey.split(".");
4363
+ if (parts.length !== 3) {
4364
+ throw new Error("Malformed token structure (expected 3 parts).");
4365
+ }
4366
+ const [headerB64, payloadB64, signatureB64] = parts;
4367
+ const dataToVerify = `${headerB64}.${payloadB64}`;
4368
+ const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
4369
+ const signature = Buffer.from(signatureB64, "base64url");
4370
+ const data = Buffer.from(dataToVerify);
4371
+ const isValid = crypto2.verify(
4372
+ "sha256",
4373
+ data,
4374
+ publicKey,
4375
+ signature
4376
+ );
4377
+ if (!isValid) {
4378
+ throw new Error("Signature verification failed.");
4379
+ }
4380
+ const payload = JSON.parse(
4381
+ Buffer.from(payloadB64, "base64url").toString("utf8")
4382
+ );
4383
+ if (!payload.projectId) {
4384
+ throw new Error('License payload is missing "projectId".');
4385
+ }
4386
+ if (payload.projectId !== currentProjectId) {
4387
+ throw new Error(
4388
+ `Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
4389
+ );
4390
+ }
4391
+ if (!payload.expiresAt) {
4392
+ throw new Error('License payload is missing expiration ("expiresAt").');
4393
+ }
4394
+ const currentTimestampSec = Math.floor(Date.now() / 1e3);
4395
+ if (currentTimestampSec > payload.expiresAt) {
4396
+ throw new Error(
4397
+ `License key has expired. Expiration: ${new Date(
4398
+ payload.expiresAt * 1e3
4399
+ ).toDateString()}`
4400
+ );
4401
+ }
4402
+ if (isProduction && provider) {
4403
+ const tier = (payload.tier || "").toLowerCase();
4404
+ const normalizedProvider = provider.toLowerCase();
4405
+ if (tier === "hobby") {
4406
+ const allowedHobby = ["postgresql", "pgvector", "supabase"];
4407
+ if (!allowedHobby.includes(normalizedProvider)) {
4408
+ throw new Error(
4409
+ `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.`
4410
+ );
4411
+ }
4412
+ } else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth") {
4413
+ const allowedPro = [
4414
+ "postgresql",
4415
+ "pgvector",
4416
+ "supabase",
4417
+ "pinecone",
4418
+ "qdrant",
4419
+ "mongodb",
4420
+ "milvus",
4421
+ "chroma",
4422
+ "chromadb"
4423
+ ];
4424
+ if (!allowedPro.includes(normalizedProvider)) {
4425
+ throw new Error(
4426
+ `The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
4427
+ );
4428
+ }
4429
+ }
4430
+ }
4431
+ if (licenseKey) {
4432
+ const cacheKey = `${licenseKey}:${currentProjectId}:${provider || ""}:${publicKeyOverride || ""}`;
4433
+ this.cache.set(cacheKey, { payload, cachedAt: now });
4434
+ }
4435
+ return payload;
4436
+ } catch (err) {
4437
+ const message = err instanceof Error ? err.message : String(err);
4438
+ throw new ConfigurationException(
4439
+ `[Retrivora SDK] License key validation failed: ${message}`
4440
+ );
4441
+ }
4442
+ }
4443
+ static async verifyIP(licenseKey) {
4444
+ if (!licenseKey) return;
4445
+ try {
4446
+ const parts = licenseKey.split(".");
4447
+ if (parts.length !== 3) return;
4448
+ const [, payloadB64] = parts;
4449
+ const payload = JSON.parse(
4450
+ Buffer.from(payloadB64, "base64url").toString("utf8")
4451
+ );
4452
+ const tier = (payload.tier || "").toLowerCase();
4453
+ if (tier === "enterprise" || tier === "custom") {
4454
+ return;
4455
+ }
4456
+ if (payload.ipv4 || payload.ipv6) {
4457
+ let currentIpv4 = "";
4458
+ let currentIpv6 = "";
4459
+ try {
4460
+ const res = await fetch("https://api4.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
4461
+ const data = await res.json();
4462
+ currentIpv4 = data.ip;
4463
+ } catch (e) {
4464
+ }
4465
+ try {
4466
+ const res = await fetch("https://api6.ipify.org?format=json", { signal: AbortSignal.timeout(3e3) });
4467
+ const data = await res.json();
4468
+ currentIpv6 = data.ip;
4469
+ } catch (e) {
4470
+ }
4471
+ const localIps = [];
4472
+ try {
4473
+ const osModule = require("os");
4474
+ const interfaces = osModule.networkInterfaces();
4475
+ for (const name of Object.keys(interfaces)) {
4476
+ for (const iface of interfaces[name] || []) {
4477
+ if (!iface.internal) {
4478
+ localIps.push(iface.address);
4479
+ }
4480
+ }
4481
+ }
4482
+ } catch (e) {
4483
+ }
4484
+ const isIpv4Match = payload.ipv4 && (currentIpv4 === payload.ipv4 || localIps.includes(payload.ipv4));
4485
+ const isIpv6Match = payload.ipv6 && (currentIpv6 === payload.ipv6 || localIps.includes(payload.ipv6));
4486
+ if (payload.ipv4 && payload.ipv6) {
4487
+ if (!isIpv4Match && !isIpv6Match) {
4488
+ throw new Error(
4489
+ `License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}, IPv6: ${payload.ipv6}) and cannot be used on this machine.`
4490
+ );
4491
+ }
4492
+ } else if (payload.ipv4 && !isIpv4Match) {
4493
+ throw new Error(
4494
+ `License key access restricted. This license key was created for a different system (authorized IPv4: ${payload.ipv4}) and cannot be used on this machine.`
4495
+ );
4496
+ } else if (payload.ipv6 && !isIpv6Match) {
4497
+ throw new Error(
4498
+ `License key access restricted. This license key was created for a different system (authorized IPv6: ${payload.ipv6}) and cannot be used on this machine.`
4499
+ );
4500
+ }
4501
+ }
4502
+ } catch (err) {
4503
+ if (err.message.includes("License key access restricted")) {
4504
+ throw new ConfigurationException(`[Retrivora SDK] ${err.message}`);
4505
+ }
4506
+ }
4507
+ }
4508
+ };
4509
+ // A simple in-memory cache to save CPU overhead of cryptographic signature checks.
4510
+ LicenseVerifier.cache = /* @__PURE__ */ new Map();
4511
+ LicenseVerifier.CACHE_TTL_MS = 60 * 1e3;
4512
+ // Cache verified license for 60 seconds
4513
+ // Retrivora's Public Key used to verify the license key signature.
4514
+ // In production, this matches the private key held by Retrivora SaaS.
4515
+ LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
4516
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
4517
+ XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
4518
+ xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
4519
+ NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
4520
+ iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
4521
+ +Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
4522
+ MwIDAQAB
4523
+ -----END PUBLIC KEY-----`;
4524
+
3939
4525
  // src/rag/DocumentChunker.ts
3940
4526
  var DocumentChunker = class {
3941
4527
  constructor(chunkSize = 1e3, chunkOverlap = 200, separators = ["\n# ", "\n## ", "\n### ", "\n#### ", "\n\n", "\n", " ", ""]) {
@@ -4165,11 +4751,11 @@ var LlamaIndexIngestor = class {
4165
4751
  * than standard character-count splitting.
4166
4752
  */
4167
4753
  async chunk(text, options = {}) {
4168
- var _a, _b;
4754
+ var _a2, _b;
4169
4755
  try {
4170
4756
  const { Document, SentenceSplitter, MetadataMode } = await import(`${"llamaindex"}`);
4171
4757
  const splitter = new SentenceSplitter({
4172
- chunkSize: (_a = options.chunkSize) != null ? _a : 1e3,
4758
+ chunkSize: (_a2 = options.chunkSize) != null ? _a2 : 1e3,
4173
4759
  chunkOverlap: (_b = options.chunkOverlap) != null ? _b : 200
4174
4760
  });
4175
4761
  const doc = new Document({ text, metadata: options.metadata || {} });
@@ -4278,7 +4864,7 @@ ${error instanceof Error ? error.message : String(error)}`
4278
4864
  * The agent returns `{ messages: [...] }` — the last message is the final answer.
4279
4865
  */
4280
4866
  async run(input, chatHistory = []) {
4281
- var _a, _b, _c;
4867
+ var _a2, _b, _c;
4282
4868
  if (!this.agent) {
4283
4869
  throw new Error("[LangChainAgent] Agent not initialized. Call initialize() first.");
4284
4870
  }
@@ -4289,14 +4875,445 @@ ${error instanceof Error ? error.message : String(error)}`
4289
4875
  const response = await this.agent.invoke({
4290
4876
  messages: [...historyMessages, new HumanMessage(input)]
4291
4877
  });
4292
- const lastMessage = (_a = response == null ? void 0 : response.messages) == null ? void 0 : _a.at(-1);
4293
- if (lastMessage && typeof lastMessage.content === "string") {
4294
- return lastMessage.content;
4295
- }
4296
- if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
4297
- return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
4298
- }
4299
- return String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
4878
+ const lastMessage = (_a2 = response == null ? void 0 : response.messages) == null ? void 0 : _a2.at(-1);
4879
+ if (lastMessage && typeof lastMessage.content === "string") {
4880
+ return lastMessage.content;
4881
+ }
4882
+ if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
4883
+ return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
4884
+ }
4885
+ return String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
4886
+ }
4887
+ };
4888
+
4889
+ // src/core/mcp.ts
4890
+ var import_child_process = require("child_process");
4891
+ var MCPClient = class {
4892
+ constructor(config) {
4893
+ this.config = config;
4894
+ this.messageIdCounter = 0;
4895
+ this.pendingRequests = /* @__PURE__ */ new Map();
4896
+ this.stdioBuffer = "";
4897
+ this.initialized = false;
4898
+ }
4899
+ getNextMessageId() {
4900
+ return ++this.messageIdCounter;
4901
+ }
4902
+ /**
4903
+ * Connect and initialize the MCP server connection.
4904
+ */
4905
+ async connect() {
4906
+ if (this.initialized) return;
4907
+ if (this.config.transport === "stdio") {
4908
+ await this.connectStdio();
4909
+ } else {
4910
+ await this.connectSSE();
4911
+ }
4912
+ try {
4913
+ const response = await this.sendJsonRpc("initialize", {
4914
+ protocolVersion: "2024-11-05",
4915
+ capabilities: {},
4916
+ clientInfo: {
4917
+ name: "retrivora-sdk",
4918
+ version: "1.0.0"
4919
+ }
4920
+ });
4921
+ await this.sendNotification("notifications/initialized");
4922
+ this.initialized = true;
4923
+ console.log(`[MCPClient] Connected and initialized server "${this.config.name}" successfully.`);
4924
+ } catch (err) {
4925
+ this.disconnect();
4926
+ throw new Error(`[MCPClient] Failed to initialize server "${this.config.name}": ${err.message}`);
4927
+ }
4928
+ }
4929
+ async connectStdio() {
4930
+ var _a2;
4931
+ const cmd = this.config.command;
4932
+ if (!cmd) {
4933
+ throw new Error(`[MCPClient] Command option is required for stdio transport on "${this.config.name}"`);
4934
+ }
4935
+ const args = this.config.args || [];
4936
+ const env = __spreadValues(__spreadValues({}, process.env), this.config.env || {});
4937
+ this.childProcess = (0, import_child_process.spawn)(cmd, args, { env, shell: true });
4938
+ if (!this.childProcess || !this.childProcess.stdout || !this.childProcess.stdin) {
4939
+ throw new Error(`[MCPClient] Failed to spawn stdio child process for "${this.config.name}"`);
4940
+ }
4941
+ this.childProcess.stdout.on("data", (data) => {
4942
+ this.stdioBuffer += data.toString("utf-8");
4943
+ this.processStdioLines();
4944
+ });
4945
+ (_a2 = this.childProcess.stderr) == null ? void 0 : _a2.on("data", (data) => {
4946
+ console.warn(`[MCPClient] [stderr] [${this.config.name}]:`, data.toString("utf-8"));
4947
+ });
4948
+ this.childProcess.on("close", (code) => {
4949
+ console.log(`[MCPClient] Connection closed for "${this.config.name}" with exit code: ${code}`);
4950
+ this.disconnect();
4951
+ });
4952
+ await new Promise((resolve) => setTimeout(resolve, 100));
4953
+ }
4954
+ processStdioLines() {
4955
+ let newlineIndex;
4956
+ while ((newlineIndex = this.stdioBuffer.indexOf("\n")) !== -1) {
4957
+ const line = this.stdioBuffer.substring(0, newlineIndex).trim();
4958
+ this.stdioBuffer = this.stdioBuffer.substring(newlineIndex + 1);
4959
+ if (!line) continue;
4960
+ try {
4961
+ const payload = JSON.parse(line);
4962
+ if (payload.id !== void 0) {
4963
+ const req = this.pendingRequests.get(Number(payload.id));
4964
+ if (req) {
4965
+ this.pendingRequests.delete(Number(payload.id));
4966
+ if (payload.error) {
4967
+ req.reject(new Error(payload.error.message || JSON.stringify(payload.error)));
4968
+ } else {
4969
+ req.resolve(payload.result);
4970
+ }
4971
+ }
4972
+ }
4973
+ } catch (e) {
4974
+ console.warn(`[MCPClient] Error parsing stdio JSON-RPC line from "${this.config.name}":`, e, "Line content:", line);
4975
+ }
4976
+ }
4977
+ }
4978
+ async connectSSE() {
4979
+ if (!this.config.url) {
4980
+ throw new Error(`[MCPClient] URL is required for sse transport on "${this.config.name}"`);
4981
+ }
4982
+ this.sseUrl = this.config.url;
4983
+ }
4984
+ async sendJsonRpc(method, params) {
4985
+ const id = this.getNextMessageId();
4986
+ const request = {
4987
+ jsonrpc: "2.0",
4988
+ id,
4989
+ method,
4990
+ params
4991
+ };
4992
+ if (this.config.transport === "stdio") {
4993
+ if (!this.childProcess || !this.childProcess.stdin) {
4994
+ throw new Error(`[MCPClient] Server "${this.config.name}" is not connected (stdio process missing)`);
4995
+ }
4996
+ return new Promise((resolve, reject) => {
4997
+ this.pendingRequests.set(id, { resolve, reject });
4998
+ this.childProcess.stdin.write(JSON.stringify(request) + "\n", "utf-8");
4999
+ });
5000
+ } else {
5001
+ if (!this.sseUrl) {
5002
+ throw new Error(`[MCPClient] Server "${this.config.name}" SSE URL is not initialized`);
5003
+ }
5004
+ const response = await fetch(this.sseUrl, {
5005
+ method: "POST",
5006
+ headers: { "Content-Type": "application/json" },
5007
+ body: JSON.stringify(request)
5008
+ });
5009
+ if (!response.ok) {
5010
+ throw new Error(`SSE JSON-RPC POST failed with status ${response.status}`);
5011
+ }
5012
+ const payload = await response.json();
5013
+ if (payload.error) {
5014
+ throw new Error(payload.error.message || JSON.stringify(payload.error));
5015
+ }
5016
+ return payload.result;
5017
+ }
5018
+ }
5019
+ async sendNotification(method, params) {
5020
+ var _a2;
5021
+ const notification = {
5022
+ jsonrpc: "2.0",
5023
+ method,
5024
+ params
5025
+ };
5026
+ if (this.config.transport === "stdio") {
5027
+ if ((_a2 = this.childProcess) == null ? void 0 : _a2.stdin) {
5028
+ this.childProcess.stdin.write(JSON.stringify(notification) + "\n", "utf-8");
5029
+ }
5030
+ } else if (this.sseUrl) {
5031
+ await fetch(this.sseUrl, {
5032
+ method: "POST",
5033
+ headers: { "Content-Type": "application/json" },
5034
+ body: JSON.stringify(notification)
5035
+ }).catch((err) => console.warn("[MCPClient] Failed to send notification over SSE:", err));
5036
+ }
5037
+ }
5038
+ /**
5039
+ * List all tools offered by the MCP server.
5040
+ */
5041
+ async listTools() {
5042
+ await this.connect();
5043
+ const result = await this.sendJsonRpc("tools/list", {});
5044
+ return (result == null ? void 0 : result.tools) || [];
5045
+ }
5046
+ /**
5047
+ * Execute a tool on the MCP server.
5048
+ */
5049
+ async callTool(name, args = {}) {
5050
+ await this.connect();
5051
+ return await this.sendJsonRpc("tools/call", { name, arguments: args });
5052
+ }
5053
+ disconnect() {
5054
+ this.initialized = false;
5055
+ this.pendingRequests.forEach((req) => req.reject(new Error("MCPClient disconnected")));
5056
+ this.pendingRequests.clear();
5057
+ if (this.childProcess) {
5058
+ try {
5059
+ this.childProcess.kill();
5060
+ } catch (e) {
5061
+ }
5062
+ this.childProcess = void 0;
5063
+ }
5064
+ }
5065
+ };
5066
+ var MCPRegistry = class {
5067
+ constructor(servers = []) {
5068
+ this.clients = [];
5069
+ this.clients = servers.map((cfg) => new MCPClient(cfg));
5070
+ }
5071
+ async getAllTools() {
5072
+ const list = [];
5073
+ await Promise.all(
5074
+ this.clients.map(async (client) => {
5075
+ try {
5076
+ const tools = await client.listTools();
5077
+ tools.forEach((t) => list.push({ serverName: client["config"].name, tool: t }));
5078
+ } catch (e) {
5079
+ console.warn(`[MCPRegistry] Failed to fetch tools from server "${client["config"].name}":`, e);
5080
+ }
5081
+ })
5082
+ );
5083
+ return list;
5084
+ }
5085
+ async callTool(toolName, args = {}) {
5086
+ for (const client of this.clients) {
5087
+ try {
5088
+ const tools = await client.listTools();
5089
+ if (tools.some((t) => t.name === toolName)) {
5090
+ return await client.callTool(toolName, args);
5091
+ }
5092
+ } catch (e) {
5093
+ }
5094
+ }
5095
+ throw new Error(`[MCPRegistry] Tool "${toolName}" not found on any registered MCP server.`);
5096
+ }
5097
+ disconnectAll() {
5098
+ this.clients.forEach((c) => c.disconnect());
5099
+ }
5100
+ };
5101
+
5102
+ // src/core/MultiAgentCoordinator.ts
5103
+ var MultiAgentCoordinator = class {
5104
+ constructor(options) {
5105
+ var _a2;
5106
+ this.llmProvider = options.llmProvider;
5107
+ this.mcpRegistry = options.mcpRegistry;
5108
+ this.documentSearch = options.documentSearch;
5109
+ this.maxIterations = (_a2 = options.maxIterations) != null ? _a2 : 5;
5110
+ }
5111
+ /**
5112
+ * Run the multi-agent coordination loop synchronously and return the final response.
5113
+ */
5114
+ async run(question, history = []) {
5115
+ const generator = this.runStream(question, history);
5116
+ let finalReply = "";
5117
+ const sources = [];
5118
+ try {
5119
+ for (var iter = __forAwait(generator), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
5120
+ const chunk = temp.value;
5121
+ if (typeof chunk === "string") {
5122
+ finalReply += chunk;
5123
+ } else if (chunk && typeof chunk === "object") {
5124
+ if ("reply" in chunk && chunk.reply) {
5125
+ finalReply += chunk.reply;
5126
+ }
5127
+ if ("sources" in chunk && chunk.sources) {
5128
+ sources.push(...chunk.sources);
5129
+ }
5130
+ }
5131
+ }
5132
+ } catch (temp) {
5133
+ error = [temp];
5134
+ } finally {
5135
+ try {
5136
+ more && (temp = iter.return) && await temp.call(iter);
5137
+ } finally {
5138
+ if (error)
5139
+ throw error[0];
5140
+ }
5141
+ }
5142
+ return {
5143
+ reply: finalReply,
5144
+ sources
5145
+ };
5146
+ }
5147
+ /**
5148
+ * Run the multi-agent coordination loop as an async stream, yielding intermediate thought blocks and tool execution events.
5149
+ */
5150
+ runStream(_0) {
5151
+ return __asyncGenerator(this, arguments, function* (question, history = []) {
5152
+ const mcpTools = yield new __await(this.mcpRegistry.getAllTools());
5153
+ let systemPrompt = `You are a goal-driven supervisor agent coordinating a RAG search engine and external MCP servers to solve the user's task.
5154
+ You must think step-by-step before acting. Write your internal thinking process inside a \`<think>...</think>\` block first, then act or answer.
5155
+
5156
+ Available Tools:
5157
+ - document_search(query: string): Search the vector database and knowledge base for documents.
5158
+
5159
+ ${mcpTools.length > 0 ? "MCP Server Tools:" : ""}
5160
+ ${mcpTools.map((mt) => {
5161
+ var _a2;
5162
+ return `- ${mt.tool.name}(${JSON.stringify(((_a2 = mt.tool.inputSchema) == null ? void 0 : _a2.properties) || {})}): ${mt.tool.description || "No description provided."}`;
5163
+ }).join("\n")}
5164
+
5165
+ Tool Calling Protocol:
5166
+ If you need to call a tool, write:
5167
+ TOOL_CALL: <toolName>({ "argName": "value" })
5168
+ And then STOP generating immediately.
5169
+
5170
+ Once you have gathered enough information to fully satisfy the user's query, write your final response directly after the closing \`</think>\` block.
5171
+ `;
5172
+ const supervisorHistory = [
5173
+ { role: "system", content: systemPrompt },
5174
+ ...history,
5175
+ { role: "user", content: question }
5176
+ ];
5177
+ let iteration = 0;
5178
+ const allSources = [];
5179
+ while (iteration < this.maxIterations) {
5180
+ iteration++;
5181
+ const context = "";
5182
+ let fullModelResponse = "";
5183
+ let textBuffer = "";
5184
+ let inThinking = false;
5185
+ let toolCallDetected = null;
5186
+ if (!this.llmProvider.chatStream) {
5187
+ const reply = yield new __await(this.llmProvider.chat(supervisorHistory, context));
5188
+ fullModelResponse = reply;
5189
+ const thinkIndex = reply.indexOf("<think>");
5190
+ const endThinkIndex = reply.indexOf("</think>");
5191
+ let thinkingText = "";
5192
+ let answerText = reply;
5193
+ if (thinkIndex !== -1 && endThinkIndex !== -1) {
5194
+ thinkingText = reply.substring(thinkIndex + 7, endThinkIndex);
5195
+ answerText = reply.substring(endThinkIndex + 8);
5196
+ yield { type: "thinking", text: thinkingText };
5197
+ }
5198
+ const toolMatch = answerText.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
5199
+ if (toolMatch) {
5200
+ const toolName = toolMatch[1];
5201
+ const toolArgsStr = toolMatch[2];
5202
+ try {
5203
+ const toolArgs = JSON.parse(toolArgsStr.trim());
5204
+ toolCallDetected = { name: toolName, args: toolArgs };
5205
+ } catch (e) {
5206
+ console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
5207
+ }
5208
+ } else {
5209
+ yield answerText;
5210
+ }
5211
+ } else {
5212
+ const stream = this.llmProvider.chatStream(supervisorHistory, context);
5213
+ try {
5214
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
5215
+ const chunk = temp.value;
5216
+ fullModelResponse += chunk;
5217
+ textBuffer += chunk;
5218
+ if (!inThinking && textBuffer.includes("<think>")) {
5219
+ inThinking = true;
5220
+ const idx = textBuffer.indexOf("<think>");
5221
+ textBuffer = textBuffer.slice(idx + 7);
5222
+ }
5223
+ if (inThinking && textBuffer.includes("</think>")) {
5224
+ inThinking = false;
5225
+ const idx = textBuffer.indexOf("</think>");
5226
+ const thinkingDelta = textBuffer.slice(0, idx);
5227
+ yield { type: "thinking", text: thinkingDelta };
5228
+ textBuffer = textBuffer.slice(idx + 8);
5229
+ }
5230
+ if (inThinking && textBuffer.length > 0) {
5231
+ yield { type: "thinking", text: textBuffer };
5232
+ textBuffer = "";
5233
+ }
5234
+ if (!inThinking && textBuffer.includes("TOOL_CALL:")) {
5235
+ const idx = textBuffer.indexOf("TOOL_CALL:");
5236
+ const precedingText = textBuffer.slice(0, idx);
5237
+ if (precedingText.trim()) {
5238
+ yield precedingText;
5239
+ }
5240
+ textBuffer = textBuffer.slice(idx);
5241
+ }
5242
+ if (!inThinking && !textBuffer.includes("TOOL_CALL:") && textBuffer.length > 0) {
5243
+ yield textBuffer;
5244
+ textBuffer = "";
5245
+ }
5246
+ }
5247
+ } catch (temp) {
5248
+ error = [temp];
5249
+ } finally {
5250
+ try {
5251
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
5252
+ } finally {
5253
+ if (error)
5254
+ throw error[0];
5255
+ }
5256
+ }
5257
+ if (textBuffer.trim()) {
5258
+ const toolMatch = textBuffer.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
5259
+ if (toolMatch) {
5260
+ const toolName = toolMatch[1];
5261
+ const toolArgsStr = toolMatch[2];
5262
+ try {
5263
+ const toolArgs = JSON.parse(toolArgsStr.trim());
5264
+ toolCallDetected = { name: toolName, args: toolArgs };
5265
+ } catch (e) {
5266
+ console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
5267
+ }
5268
+ } else {
5269
+ yield textBuffer;
5270
+ }
5271
+ }
5272
+ }
5273
+ supervisorHistory.push({ role: "assistant", content: fullModelResponse });
5274
+ if (toolCallDetected) {
5275
+ const { name: toolName, args: toolArgs } = toolCallDetected;
5276
+ yield {
5277
+ type: "thinking",
5278
+ text: `
5279
+ [Agent Call] Executing tool "${toolName}" with parameters ${JSON.stringify(toolArgs)}...
5280
+ `
5281
+ };
5282
+ let toolResultText = "";
5283
+ try {
5284
+ if (toolName === "document_search") {
5285
+ const searchRes = yield new __await(this.documentSearch(toolArgs.query || ""));
5286
+ toolResultText = `document_search returned:
5287
+ ${searchRes.reply}
5288
+
5289
+ Sources count: ${searchRes.sources.length}`;
5290
+ if (searchRes.sources && searchRes.sources.length > 0) {
5291
+ allSources.push(...searchRes.sources);
5292
+ yield { reply: "", sources: searchRes.sources };
5293
+ }
5294
+ } else {
5295
+ const mcpRes = yield new __await(this.mcpRegistry.callTool(toolName, toolArgs));
5296
+ toolResultText = `MCP Tool "${toolName}" returned:
5297
+ ${JSON.stringify(mcpRes.content)}`;
5298
+ }
5299
+ } catch (err) {
5300
+ toolResultText = `Error calling tool "${toolName}": ${err.message}`;
5301
+ }
5302
+ supervisorHistory.push({
5303
+ role: "user",
5304
+ content: `TOOL_RESULT for ${toolName}:
5305
+ ${toolResultText}`
5306
+ });
5307
+ yield {
5308
+ type: "thinking",
5309
+ text: `[Agent Output] Tool "${toolName}" executed. Continuing reasoning...
5310
+ `
5311
+ };
5312
+ } else {
5313
+ break;
5314
+ }
5315
+ }
5316
+ });
4300
5317
  }
4301
5318
  };
4302
5319
 
@@ -4626,7 +5643,7 @@ var QueryProcessor = class {
4626
5643
  * @param validFields Optional list of known filterable fields to look for
4627
5644
  */
4628
5645
  static extractQueryFieldHints(question, validFields = []) {
4629
- var _a, _b, _c, _d;
5646
+ var _a2, _b, _c, _d;
4630
5647
  if (!question.trim()) return [];
4631
5648
  const hints = /* @__PURE__ */ new Map();
4632
5649
  const addHint = (value, field) => {
@@ -4706,7 +5723,7 @@ var QueryProcessor = class {
4706
5723
  ];
4707
5724
  for (const p of universalPatterns) {
4708
5725
  for (const match of question.matchAll(p.regex)) {
4709
- const val = p.group ? (_a = match[p.group]) != null ? _a : match[0] : match[0];
5726
+ const val = p.group ? (_a2 = match[p.group]) != null ? _a2 : match[0] : match[0];
4710
5727
  if (!val) continue;
4711
5728
  if (p.field) addHint(val, p.field);
4712
5729
  else addHint(val);
@@ -4930,11 +5947,11 @@ var LLMRouter = class {
4930
5947
  * When provided it is used directly as the 'default' role without re-constructing.
4931
5948
  */
4932
5949
  async initialize(prebuiltDefault) {
4933
- var _a;
5950
+ var _a2;
4934
5951
  const defaultModel = prebuiltDefault != null ? prebuiltDefault : LLMFactory.create(this.config.llm, this.config.embedding);
4935
5952
  this.models.set("default", defaultModel);
4936
5953
  const envFastModel = process.env.FAST_LLM_MODEL;
4937
- const providerFastDefault = (_a = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a : "";
5954
+ const providerFastDefault = (_a2 = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a2 : "";
4938
5955
  const fastModelName = envFastModel || providerFastDefault;
4939
5956
  if (fastModelName && fastModelName !== this.config.llm.model) {
4940
5957
  console.log(`[LLMRouter] Fast role \u2192 provider="${this.config.llm.provider}" model="${fastModelName}"`);
@@ -4953,8 +5970,8 @@ var LLMRouter = class {
4953
5970
  * Falls back to 'default' if the requested role is not registered.
4954
5971
  */
4955
5972
  get(role) {
4956
- var _a;
4957
- const provider = (_a = this.models.get(role)) != null ? _a : this.models.get("default");
5973
+ var _a2;
5974
+ const provider = (_a2 = this.models.get(role)) != null ? _a2 : this.models.get("default");
4958
5975
  if (!provider) {
4959
5976
  throw new Error(`[LLMRouter] No provider registered for role: "${role}". Did you call initialize()?`);
4960
5977
  }
@@ -4972,7 +5989,7 @@ var UITransformer = class _UITransformer {
4972
5989
  * Prefer `analyzeAndDecide()` in production.
4973
5990
  */
4974
5991
  static transform(userQuery, retrievedData, config, trainedSchema, intent) {
4975
- var _a, _b, _c;
5992
+ var _a2, _b, _c;
4976
5993
  if (!retrievedData || retrievedData.length === 0) {
4977
5994
  return this.createTextResponse("No data available", "No relevant data found for your query.");
4978
5995
  }
@@ -4992,7 +6009,7 @@ var UITransformer = class _UITransformer {
4992
6009
  return this.transformToBarChart(filteredData, profile, userQuery, resolvedIntent.visualizationHint === "ranking");
4993
6010
  }
4994
6011
  if (resolvedIntent.visualizationHint === "distribution") {
4995
- return (_a = this.transformToHistogram(profile, userQuery)) != null ? _a : this.transformToBarChart(filteredData, profile, userQuery);
6012
+ return (_a2 = this.transformToHistogram(profile, userQuery)) != null ? _a2 : this.transformToBarChart(filteredData, profile, userQuery);
4996
6013
  }
4997
6014
  if (resolvedIntent.visualizationHint === "correlation") {
4998
6015
  return (_b = this.transformToScatterPlot(profile, userQuery)) != null ? _b : this.transformToBarChart(filteredData, profile, userQuery);
@@ -5317,11 +6334,11 @@ ${schemaProfileText}` : ""}`;
5317
6334
  };
5318
6335
  }
5319
6336
  static transformToPieChart(data, profile, query = "") {
5320
- var _a;
6337
+ var _a2;
5321
6338
  const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
5322
6339
  const categories = dimension ? Array.from(new Set(profile.records.map((record) => {
5323
- var _a2;
5324
- return String((_a2 = record.fields[dimension.key]) != null ? _a2 : "");
6340
+ var _a3;
6341
+ return String((_a3 = record.fields[dimension.key]) != null ? _a3 : "");
5325
6342
  }).filter(Boolean))) : this.detectCategories(data);
5326
6343
  if (categories.length === 0) return null;
5327
6344
  const categoryData = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key) : this.aggregateByCategory(data, categories);
@@ -5331,7 +6348,7 @@ ${schemaProfileText}` : ""}`;
5331
6348
  });
5332
6349
  return {
5333
6350
  type: "pie_chart",
5334
- title: `Distribution by ${(_a = dimension == null ? void 0 : dimension.label) != null ? _a : "Category"}`,
6351
+ title: `Distribution by ${(_a2 = dimension == null ? void 0 : dimension.label) != null ? _a2 : "Category"}`,
5335
6352
  description: `Showing breakdown across ${pieData.length} categories`,
5336
6353
  data: pieData
5337
6354
  };
@@ -5341,8 +6358,8 @@ ${schemaProfileText}` : ""}`;
5341
6358
  const valueField = profile.numericFields[0];
5342
6359
  const buckets = /* @__PURE__ */ new Map();
5343
6360
  profile.records.forEach((record) => {
5344
- var _a, _b, _c;
5345
- const timestamp = String((_a = record.fields[dateField.key]) != null ? _a : "");
6361
+ var _a2, _b, _c;
6362
+ const timestamp = String((_a2 = record.fields[dateField.key]) != null ? _a2 : "");
5346
6363
  const value = (_b = this.toFiniteNumber(record.fields[valueField.key])) != null ? _b : 0;
5347
6364
  buckets.set(timestamp, ((_c = buckets.get(timestamp)) != null ? _c : 0) + value);
5348
6365
  });
@@ -5355,23 +6372,23 @@ ${schemaProfileText}` : ""}`;
5355
6372
  };
5356
6373
  }
5357
6374
  static transformToBarChart(data, profile, query = "", horizontal = false) {
5358
- var _a;
6375
+ var _a2;
5359
6376
  const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
5360
6377
  const measure = profile ? this.selectNumericField(profile, query) : void 0;
5361
6378
  const aggregate = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key, measure == null ? void 0 : measure.key) : this.aggregateByCategory(data, this.detectCategories(data));
5362
6379
  const barData = Object.entries(aggregate).map(([category, value]) => ({ category, value: Number(value) })).sort((a, b) => horizontal ? b.value - a.value : 0).slice(0, 12);
5363
6380
  const fallbackData = barData.length > 0 ? barData : data.slice(0, 12).map((item, index) => {
5364
- var _a2, _b, _c, _d, _e;
6381
+ var _a3, _b, _c, _d, _e;
5365
6382
  const meta = item.metadata || {};
5366
6383
  const label = String(
5367
- (_c = (_b = (_a2 = this.getDynamicVal(meta, "name")) != null ? _a2 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
6384
+ (_c = (_b = (_a3 = this.getDynamicVal(meta, "name")) != null ? _a3 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
5368
6385
  );
5369
6386
  const value = (_e = (_d = this.extractNumericValue(meta)) != null ? _d : item.score) != null ? _e : 0;
5370
6387
  return { category: label, value: Number(value) };
5371
6388
  });
5372
6389
  return {
5373
6390
  type: horizontal ? "horizontal_bar" : "bar_chart",
5374
- title: dimension ? `${(_a = measure == null ? void 0 : measure.label) != null ? _a : "Count"} by ${dimension.label}` : "Comparison",
6391
+ title: dimension ? `${(_a2 = measure == null ? void 0 : measure.label) != null ? _a2 : "Count"} by ${dimension.label}` : "Comparison",
5375
6392
  description: `Showing ${fallbackData.length} comparable values`,
5376
6393
  data: fallbackData
5377
6394
  };
@@ -5406,11 +6423,11 @@ ${schemaProfileText}` : ""}`;
5406
6423
  if (fields.length < 2) return null;
5407
6424
  const [xField, yField] = fields;
5408
6425
  const points = profile.records.map((record) => {
5409
- var _a;
6426
+ var _a2;
5410
6427
  const x = this.toFiniteNumber(record.fields[xField.key]);
5411
6428
  const y = this.toFiniteNumber(record.fields[yField.key]);
5412
6429
  if (x === null || y === null) return null;
5413
- return { x, y, label: String((_a = this.getRecordLabel(record)) != null ? _a : record.id) };
6430
+ return { x, y, label: String((_a2 = this.getRecordLabel(record)) != null ? _a2 : record.id) };
5414
6431
  }).filter((point) => point !== null).slice(0, 100);
5415
6432
  if (points.length === 0) return null;
5416
6433
  return {
@@ -5440,9 +6457,9 @@ ${schemaProfileText}` : ""}`;
5440
6457
  static transformToRadarChart(data) {
5441
6458
  const attributeMap = {};
5442
6459
  data.forEach((item) => {
5443
- var _a, _b, _c;
6460
+ var _a2, _b, _c;
5444
6461
  const meta = item.metadata || {};
5445
- const seriesName = String((_c = (_b = (_a = meta.name) != null ? _a : meta.product) != null ? _b : item.id) != null ? _c : "Item");
6462
+ const seriesName = String((_c = (_b = (_a2 = meta.name) != null ? _a2 : meta.product) != null ? _b : item.id) != null ? _c : "Item");
5446
6463
  Object.entries(meta).forEach(([key, val]) => {
5447
6464
  if (typeof val === "number" && !["price", "id"].includes(key.toLowerCase())) {
5448
6465
  if (!attributeMap[key]) attributeMap[key] = {};
@@ -5524,22 +6541,22 @@ ${schemaProfileText}` : ""}`;
5524
6541
  return null;
5525
6542
  }
5526
6543
  static normalizeTransformation(payload) {
5527
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
6544
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j;
5528
6545
  if (!payload || typeof payload !== "object") return null;
5529
6546
  const p = payload;
5530
6547
  const type = this.normalizeVisualizationType(
5531
- String((_c = (_b = (_a = p.type) != null ? _a : p.view) != null ? _b : p.chartType) != null ? _c : "")
6548
+ String((_c = (_b = (_a2 = p.type) != null ? _a2 : p.view) != null ? _b : p.chartType) != null ? _c : "")
5532
6549
  );
5533
6550
  if (!type) return null;
5534
6551
  const title = String((_e = (_d = p.title) != null ? _d : p.heading) != null ? _e : "Visualization");
5535
6552
  const description = p.description ? String(p.description) : void 0;
5536
- 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;
6553
+ 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;
5537
6554
  const data = type === "text" && typeof rawData === "string" ? { content: rawData } : rawData;
5538
6555
  const transformation = { type, title, description, data };
5539
6556
  return this.validateTransformation(transformation) ? transformation : null;
5540
6557
  }
5541
6558
  static normalizeVisualizationType(type) {
5542
- var _a;
6559
+ var _a2;
5543
6560
  const mapping = {
5544
6561
  pie: "pie_chart",
5545
6562
  pie_chart: "pie_chart",
@@ -5567,7 +6584,7 @@ ${schemaProfileText}` : ""}`;
5567
6584
  product_carousel: "product_carousel",
5568
6585
  carousel: "carousel"
5569
6586
  };
5570
- return (_a = mapping[type.toLowerCase()]) != null ? _a : null;
6587
+ return (_a2 = mapping[type.toLowerCase()]) != null ? _a2 : null;
5571
6588
  }
5572
6589
  static validateTransformation(t) {
5573
6590
  const { type, data } = t;
@@ -5769,16 +6786,16 @@ ${schemaProfileText}` : ""}`;
5769
6786
  return null;
5770
6787
  }
5771
6788
  static selectDimensionField(profile, query) {
5772
- var _a, _b;
6789
+ var _a2, _b;
5773
6790
  const productCategory = profile.categoricalFields.find(
5774
6791
  (field) => /category|department|collection|type|group|segment|region|country|state|city/i.test(field.key)
5775
6792
  );
5776
6793
  const ranked = this.rankFieldsByQuery(profile.categoricalFields, query);
5777
- return (_b = (_a = ranked[0]) != null ? _a : productCategory) != null ? _b : profile.categoricalFields[0];
6794
+ return (_b = (_a2 = ranked[0]) != null ? _a2 : productCategory) != null ? _b : profile.categoricalFields[0];
5778
6795
  }
5779
6796
  static selectNumericField(profile, query) {
5780
- var _a;
5781
- return (_a = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a : profile.numericFields[0];
6797
+ var _a2;
6798
+ return (_a2 = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a2 : profile.numericFields[0];
5782
6799
  }
5783
6800
  static rankFieldsByQuery(fields, query) {
5784
6801
  const q = query.toLowerCase();
@@ -5807,8 +6824,8 @@ ${schemaProfileText}` : ""}`;
5807
6824
  static aggregateProfileByDimension(profile, dimensionKey, measureKey) {
5808
6825
  const result = {};
5809
6826
  profile.records.forEach((record) => {
5810
- var _a, _b, _c;
5811
- const category = String((_a = record.fields[dimensionKey]) != null ? _a : "Other").trim() || "Other";
6827
+ var _a2, _b, _c;
6828
+ const category = String((_a2 = record.fields[dimensionKey]) != null ? _a2 : "Other").trim() || "Other";
5812
6829
  const value = measureKey ? (_b = this.toFiniteNumber(record.fields[measureKey])) != null ? _b : 0 : 1;
5813
6830
  result[category] = ((_c = result[category]) != null ? _c : 0) + value;
5814
6831
  });
@@ -5887,8 +6904,8 @@ ${schemaProfileText}` : ""}`;
5887
6904
  static aggregateByCategory(data, categories) {
5888
6905
  const result = Object.fromEntries(categories.map((c) => [c, 0]));
5889
6906
  data.forEach((item) => {
5890
- var _a;
5891
- const cat = (_a = this.getProductCategory(item)) != null ? _a : "Other";
6907
+ var _a2;
6908
+ const cat = (_a2 = this.getProductCategory(item)) != null ? _a2 : "Other";
5892
6909
  if (Object.prototype.hasOwnProperty.call(result, cat)) result[cat]++;
5893
6910
  else result["Other"] = (result["Other"] || 0) + 1;
5894
6911
  });
@@ -5896,17 +6913,17 @@ ${schemaProfileText}` : ""}`;
5896
6913
  }
5897
6914
  static extractTimeSeriesData(data) {
5898
6915
  return data.map((item) => {
5899
- var _a, _b, _c, _d, _e;
6916
+ var _a2, _b, _c, _d, _e;
5900
6917
  const meta = item.metadata || {};
5901
6918
  return {
5902
- timestamp: (_b = (_a = meta.timestamp) != null ? _a : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
6919
+ timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
5903
6920
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
5904
6921
  label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
5905
6922
  };
5906
6923
  });
5907
6924
  }
5908
6925
  static extractNumericValue(meta) {
5909
- var _a;
6926
+ var _a2;
5910
6927
  const preferredKeys = [
5911
6928
  "value",
5912
6929
  "count",
@@ -5921,7 +6938,7 @@ ${schemaProfileText}` : ""}`;
5921
6938
  "price"
5922
6939
  ];
5923
6940
  for (const key of preferredKeys) {
5924
- const raw = (_a = resolveMetadataValue(meta, key)) != null ? _a : meta[key];
6941
+ const raw = (_a2 = resolveMetadataValue(meta, key)) != null ? _a2 : meta[key];
5925
6942
  const value = typeof raw === "number" ? raw : Number(String(raw != null ? raw : "").replace(/[$,% ,]/g, ""));
5926
6943
  if (Number.isFinite(value)) return value;
5927
6944
  }
@@ -6067,8 +7084,8 @@ ${schemaProfileText}` : ""}`;
6067
7084
  let inStock = 0;
6068
7085
  let outOfStock = 0;
6069
7086
  data.forEach((d) => {
6070
- var _a, _b;
6071
- const cat = (_a = this.getProductCategory(d)) != null ? _a : "Other";
7087
+ var _a2, _b;
7088
+ const cat = (_a2 = this.getProductCategory(d)) != null ? _a2 : "Other";
6072
7089
  if (cat === category) {
6073
7090
  const quantity = (_b = this.extractStockQuantity(d)) != null ? _b : 1;
6074
7091
  if (this.determineStockStatus(d)) inStock += quantity;
@@ -6112,9 +7129,9 @@ ${schemaProfileText}` : ""}`;
6112
7129
  }
6113
7130
  // ─── Product Extraction ───────────────────────────────────────────────────
6114
7131
  static getDynamicVal(meta, uiKey, config, trainedSchema) {
6115
- var _a;
7132
+ var _a2;
6116
7133
  if (!meta) return void 0;
6117
- const mapping = (_a = config == null ? void 0 : config.rag) == null ? void 0 : _a.uiMapping;
7134
+ const mapping = (_a2 = config == null ? void 0 : config.rag) == null ? void 0 : _a2.uiMapping;
6118
7135
  if ((mapping == null ? void 0 : mapping[uiKey]) && meta[mapping[uiKey]] !== void 0) return meta[mapping[uiKey]];
6119
7136
  if (trainedSchema && typeof trainedSchema === "object") {
6120
7137
  const trainedKey = trainedSchema[uiKey];
@@ -6123,13 +7140,13 @@ ${schemaProfileText}` : ""}`;
6123
7140
  return resolveMetadataValue(meta, uiKey);
6124
7141
  }
6125
7142
  static extractProductInfo(item, config, trainedSchema) {
6126
- var _a;
7143
+ var _a2;
6127
7144
  const meta = item.metadata || {};
6128
7145
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
6129
7146
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
6130
7147
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
6131
7148
  const description = this.cleanProductDescription(
6132
- (_a = this.extractProductDescriptionFromContent(item.content)) != null ? _a : this.getProductDescriptionValue(meta, config, trainedSchema)
7149
+ (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
6133
7150
  );
6134
7151
  if (name || this.isProductData(item)) {
6135
7152
  let finalName = name ? String(name) : void 0;
@@ -6237,10 +7254,10 @@ RULES:
6237
7254
  }
6238
7255
  static buildContextSummary(sources, maxChars = 6e3) {
6239
7256
  const items = sources.map((s, i) => {
6240
- var _a, _b, _c, _d;
7257
+ var _a2, _b, _c, _d;
6241
7258
  return {
6242
7259
  index: i + 1,
6243
- content: (_b = (_a = s.content) == null ? void 0 : _a.substring(0, 400)) != null ? _b : "",
7260
+ content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
6244
7261
  metadata: (_c = s.metadata) != null ? _c : {},
6245
7262
  score: (_d = s.score) != null ? _d : 0
6246
7263
  };
@@ -6433,9 +7450,11 @@ var Pipeline = class {
6433
7450
  /** LRU-bounded cache: avoids re-embedding identical queries within the same process. */
6434
7451
  this.embeddingCache = new LRUEmbeddingCache(500);
6435
7452
  this.initialised = false;
6436
- var _a, _b, _c, _d, _e;
7453
+ /** Namespace-specific static cold context cache for CAG */
7454
+ this.coldContexts = /* @__PURE__ */ new Map();
7455
+ var _a2, _b, _c, _d, _e;
6437
7456
  this.chunker = new DocumentChunker(
6438
- (_b = (_a = config.rag) == null ? void 0 : _a.chunkSize) != null ? _b : 1e3,
7457
+ (_b = (_a2 = config.rag) == null ? void 0 : _a2.chunkSize) != null ? _b : 1e3,
6439
7458
  (_d = (_c = config.rag) == null ? void 0 : _c.chunkOverlap) != null ? _d : 200
6440
7459
  );
6441
7460
  if (((_e = config.rag) == null ? void 0 : _e.chunkingStrategy) === "llamaindex") {
@@ -6451,7 +7470,7 @@ var Pipeline = class {
6451
7470
  return this.initialised ? this.llmProvider : void 0;
6452
7471
  }
6453
7472
  async initialize() {
6454
- var _a;
7473
+ var _a2, _b, _c, _d;
6455
7474
  if (this.initialised) return;
6456
7475
  const chartInstruction = `You are a helpful assistant. Use the provided context to answer questions accurately.
6457
7476
 
@@ -6494,12 +7513,47 @@ var Pipeline = class {
6494
7513
  this.entityExtractor = new EntityExtractor(this.llmProvider);
6495
7514
  }
6496
7515
  await this.vectorDB.initialize();
6497
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic") {
7516
+ if (((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || ((_b = this.config.rag) == null ? void 0 : _b.architecture) === "multi-agent" || this.config.mcpServers && this.config.mcpServers.length > 0) {
7517
+ this.mcpRegistry = new MCPRegistry(this.config.mcpServers || []);
7518
+ this.multiAgentCoordinator = new MultiAgentCoordinator({
7519
+ llmProvider: this.llmProvider,
7520
+ mcpRegistry: this.mcpRegistry,
7521
+ documentSearch: async (query) => {
7522
+ return this.runNormalQuery(query);
7523
+ }
7524
+ });
6498
7525
  this.agent = new LangChainAgent(this, this.config);
6499
7526
  await this.agent.initialize(this.llmProvider);
6500
7527
  }
7528
+ if ((_d = (_c = this.config.rag) == null ? void 0 : _c.cag) == null ? void 0 : _d.enabled) {
7529
+ await this.loadColdContext(this.config.projectId);
7530
+ }
6501
7531
  this.initialised = true;
6502
7532
  }
7533
+ async loadColdContext(ns) {
7534
+ var _a2, _b;
7535
+ const cagConfig = (_a2 = this.config.rag) == null ? void 0 : _a2.cag;
7536
+ if (!cagConfig || !cagConfig.enabled) return;
7537
+ try {
7538
+ const coldNs = cagConfig.coldNamespace || ns;
7539
+ const limit = (_b = cagConfig.coldLimit) != null ? _b : 20;
7540
+ const queryText = cagConfig.coldQuery || "documentation";
7541
+ const queryVector = await this.embeddingProvider.embed(queryText, { taskType: "query" });
7542
+ const coldMatches = await this.vectorDB.query(queryVector, limit, coldNs);
7543
+ if (coldMatches.length > 0) {
7544
+ const formatted = coldMatches.map((m, i) => `[Cold Source ${i + 1}]
7545
+ ${m.content}`).join("\n\n---\n\n");
7546
+ this.coldContexts.set(ns, formatted);
7547
+ console.log(`[Pipeline] Cold RAG (CAG) loaded ${coldMatches.length} documents into cached context for namespace: ${ns}`);
7548
+ } else {
7549
+ this.coldContexts.set(ns, "No cold context found.");
7550
+ console.warn(`[Pipeline] Cold RAG (CAG) initialized but no documents were found in namespace: ${coldNs}`);
7551
+ }
7552
+ } catch (err) {
7553
+ console.error(`[Pipeline] Failed to load Cold RAG (CAG) context for namespace ${ns}:`, err);
7554
+ this.coldContexts.set(ns, "Failed to load cold context.");
7555
+ }
7556
+ }
6503
7557
  /**
6504
7558
  * Ingest documents with automatic chunking, embedding, and batch upsert.
6505
7559
  */
@@ -6531,12 +7585,12 @@ var Pipeline = class {
6531
7585
  }
6532
7586
  /** Step 1: Chunk the document content. */
6533
7587
  async prepareChunks(doc) {
6534
- var _a, _b;
7588
+ var _a2, _b;
6535
7589
  if (this.llamaIngestor) {
6536
7590
  return this.llamaIngestor.chunk(doc.content, {
6537
7591
  docId: doc.docId,
6538
7592
  metadata: doc.metadata,
6539
- chunkSize: (_a = this.config.rag) == null ? void 0 : _a.chunkSize,
7593
+ chunkSize: (_a2 = this.config.rag) == null ? void 0 : _a2.chunkSize,
6540
7594
  chunkOverlap: (_b = this.config.rag) == null ? void 0 : _b.chunkOverlap
6541
7595
  });
6542
7596
  }
@@ -6607,12 +7661,37 @@ var Pipeline = class {
6607
7661
  extractionOptions
6608
7662
  );
6609
7663
  }
7664
+ async runNormalQuery(question, history = [], namespace) {
7665
+ const stream = this.askStreamInternal(question, history, namespace);
7666
+ let reply = "";
7667
+ let sources = [];
7668
+ try {
7669
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
7670
+ const chunk = temp.value;
7671
+ if (typeof chunk === "string") {
7672
+ reply += chunk;
7673
+ } else if (typeof chunk === "object" && chunk !== null) {
7674
+ if ("reply" in chunk && chunk.reply) reply += chunk.reply;
7675
+ if ("sources" in chunk && chunk.sources) sources = chunk.sources;
7676
+ }
7677
+ }
7678
+ } catch (temp) {
7679
+ error = [temp];
7680
+ } finally {
7681
+ try {
7682
+ more && (temp = iter.return) && await temp.call(iter);
7683
+ } finally {
7684
+ if (error)
7685
+ throw error[0];
7686
+ }
7687
+ }
7688
+ return { reply, sources };
7689
+ }
6610
7690
  async ask(question, history = [], namespace) {
6611
- var _a;
7691
+ var _a2, _b;
6612
7692
  await this.initialize();
6613
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic" && this.agent) {
6614
- const agentReply = await this.agent.run(question, history);
6615
- return { reply: agentReply, sources: [] };
7693
+ if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || ((_b = this.config.rag) == null ? void 0 : _b.architecture) === "multi-agent" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
7694
+ return await this.multiAgentCoordinator.run(question, history);
6616
7695
  }
6617
7696
  const stream = this.askStream(question, history, namespace);
6618
7697
  let reply = "";
@@ -6644,6 +7723,47 @@ var Pipeline = class {
6644
7723
  }
6645
7724
  return { reply, sources, graphData, ui_transformation: uiTransformation, trace };
6646
7725
  }
7726
+ askStream(_0) {
7727
+ return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
7728
+ var _a2, _b;
7729
+ yield new __await(this.initialize());
7730
+ if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || ((_b = this.config.rag) == null ? void 0 : _b.architecture) === "multi-agent" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
7731
+ const stream2 = this.multiAgentCoordinator.runStream(question, history);
7732
+ try {
7733
+ for (var iter = __forAwait(stream2), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
7734
+ const chunk = temp.value;
7735
+ yield chunk;
7736
+ }
7737
+ } catch (temp) {
7738
+ error = [temp];
7739
+ } finally {
7740
+ try {
7741
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
7742
+ } finally {
7743
+ if (error)
7744
+ throw error[0];
7745
+ }
7746
+ }
7747
+ return;
7748
+ }
7749
+ const stream = this.askStreamInternal(question, history, namespace);
7750
+ try {
7751
+ for (var iter2 = __forAwait(stream), more2, temp2, error2; more2 = !(temp2 = yield new __await(iter2.next())).done; more2 = false) {
7752
+ const chunk = temp2.value;
7753
+ yield chunk;
7754
+ }
7755
+ } catch (temp2) {
7756
+ error2 = [temp2];
7757
+ } finally {
7758
+ try {
7759
+ more2 && (temp2 = iter2.return) && (yield new __await(temp2.call(iter2)));
7760
+ } finally {
7761
+ if (error2)
7762
+ throw error2[0];
7763
+ }
7764
+ }
7765
+ });
7766
+ }
6647
7767
  /**
6648
7768
  * High-performance streaming RAG flow.
6649
7769
  * Yields text chunks first, then the retrieval metadata + observability trace at the end.
@@ -6654,12 +7774,12 @@ var Pipeline = class {
6654
7774
  * - UITransformation is computed after text streaming and emitted with metadata
6655
7775
  * - SchemaMapper.train runs while answer generation streams
6656
7776
  */
6657
- askStream(_0) {
7777
+ askStreamInternal(_0) {
6658
7778
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
6659
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
7779
+ 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;
6660
7780
  yield new __await(this.initialize());
6661
7781
  const ns = namespace != null ? namespace : this.config.projectId;
6662
- const topK = (_b = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
7782
+ const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
6663
7783
  const scoreThreshold = (_d = (_c = this.config.rag) == null ? void 0 : _c.scoreThreshold) != null ? _d : 0.3;
6664
7784
  const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
6665
7785
  const requestStart = performance.now();
@@ -6672,20 +7792,21 @@ var Pipeline = class {
6672
7792
  }
6673
7793
  const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
6674
7794
  const filter = QueryProcessor.buildQueryFilter(question, hints);
6675
- const numericPredicates = QueryProcessor.extractNumericPredicates(question, (_g = this.config.rag) == null ? void 0 : _g.filterableFields);
7795
+ const numericPredicates = QueryProcessor.extractNumericPredicates(question, (_g2 = this.config.rag) == null ? void 0 : _g2.filterableFields);
6676
7796
  if (numericPredicates.length > 0) {
6677
7797
  filter.__numericPredicates = numericPredicates;
6678
7798
  }
6679
7799
  const embedStart = performance.now();
6680
7800
  const cacheKey = `${ns}::${searchQuery}`;
6681
7801
  const cachedVector = this.embeddingCache.get(cacheKey);
6682
- const useGraph = this.graphDB && ((_h = this.config.rag) == null ? void 0 : _h.useGraphRetrieval);
7802
+ const arch = (_h = this.config.rag) == null ? void 0 : _h.architecture;
7803
+ const useGraph = arch !== "naive" && arch !== "retrieve-and-rerank" && this.graphDB && ((_i = this.config.rag) == null ? void 0 : _i.useGraphRetrieval);
6683
7804
  const [strategyResult, embeddedVector] = yield new __await(Promise.all([
6684
7805
  QueryProcessor.determineRetrievalStrategy(
6685
7806
  searchQuery,
6686
7807
  useGraph ? this.llmRouter.get("fast") : void 0,
6687
- (_i = this.config.rag) == null ? void 0 : _i.graphKeywords,
6688
- (_j = this.config.rag) == null ? void 0 : _j.vectorKeywords
7808
+ (_j = this.config.rag) == null ? void 0 : _j.graphKeywords,
7809
+ (_k = this.config.rag) == null ? void 0 : _k.vectorKeywords
6689
7810
  ),
6690
7811
  // Embed immediately regardless of strategy — costs nothing if cached.
6691
7812
  // If strategy turns out to be 'graph'-only we just won't use the vector.
@@ -6695,7 +7816,7 @@ var Pipeline = class {
6695
7816
  if (!cachedVector && queryVector.length > 0) {
6696
7817
  this.embeddingCache.set(cacheKey, queryVector);
6697
7818
  }
6698
- const graphData = (strategyResult === "graph" || strategyResult === "both") && this.graphDB && ((_k = this.config.rag) == null ? void 0 : _k.useGraphRetrieval) ? yield new __await(this.graphDB.query(searchQuery)) : void 0;
7819
+ const graphData = (strategyResult === "graph" || strategyResult === "both") && this.graphDB && ((_l = this.config.rag) == null ? void 0 : _l.useGraphRetrieval) ? yield new __await(this.graphDB.query(searchQuery)) : void 0;
6699
7820
  const hasMetadataFilter = filter.metadata && Object.keys(filter.metadata).length > 0;
6700
7821
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
6701
7822
  const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
@@ -6708,7 +7829,8 @@ var Pipeline = class {
6708
7829
  const structuredSources = this.applyStructuredFilters(rawSources, filter);
6709
7830
  let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => m.score >= scoreThreshold);
6710
7831
  const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
6711
- if (!hasNumericPredicates && ((_l = this.config.rag) == null ? void 0 : _l.useReranking)) {
7832
+ const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
7833
+ if (!hasNumericPredicates && useReranking) {
6712
7834
  fullSources = yield new __await(this.reranker.rerank(fullSources, question, rerankLimit));
6713
7835
  } else if (!wantsExhaustiveList) {
6714
7836
  fullSources = fullSources.slice(0, topK);
@@ -6738,6 +7860,32 @@ ${graphContext}
6738
7860
  VECTOR CONTEXT:
6739
7861
  ${context}`;
6740
7862
  }
7863
+ if ((_o = (_n = this.config.rag) == null ? void 0 : _n.cag) == null ? void 0 : _o.enabled) {
7864
+ if (!this.coldContexts.has(ns)) {
7865
+ yield new __await(this.loadColdContext(ns));
7866
+ }
7867
+ const coldContext = this.coldContexts.get(ns);
7868
+ if (coldContext && coldContext !== "No cold context found." && coldContext !== "Failed to load cold context.") {
7869
+ context = `COLD CONTEXT (STATIC KNOWLEDGE):
7870
+ ${coldContext}
7871
+
7872
+ RETRIEVED HOT CONTEXT (REAL-TIME KNOWLEDGE):
7873
+ ${context}`;
7874
+ }
7875
+ }
7876
+ yield {
7877
+ reply: "",
7878
+ sources: sources.map((s) => {
7879
+ var _a3;
7880
+ return {
7881
+ id: s.id,
7882
+ score: s.score,
7883
+ content: s.content,
7884
+ metadata: (_a3 = s.metadata) != null ? _a3 : {},
7885
+ namespace: ns
7886
+ };
7887
+ })
7888
+ };
6741
7889
  const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
6742
7890
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
6743
7891
  if (allMetadataKeys.length > 0 && !cachedSchema) {
@@ -6765,10 +7913,10 @@ ${context}`;
6765
7913
  let hallucinationScoringPromise = Promise.resolve(void 0);
6766
7914
  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.)";
6767
7915
  const isClaude37 = this.config.llm.model.includes("claude-3-7-sonnet");
6768
- 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);
7916
+ const isNativeThinking = isClaude37 && (((_p = this.config.llm.options) == null ? void 0 : _p.thinking) === true || ((_q = this.config.llm.options) == null ? void 0 : _q.thinking) === "enabled" || ((_r = this.config.llm.options) == null ? void 0 : _r.thinking) !== false);
6769
7917
  const modelNameLower = this.config.llm.model.toLowerCase();
6770
7918
  const isReasoningModel = modelNameLower.includes("-r1") || modelNameLower.includes("deepseek-r1") || modelNameLower.includes("reasoning") || modelNameLower.includes("thinking");
6771
- 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);
7919
+ const isSimulatedThinking = !isNativeThinking && (((_s = this.config.llm.options) == null ? void 0 : _s.thinking) === true || ((_t = this.config.llm.options) == null ? void 0 : _t.thinking) === "enabled" || isReasoningModel && ((_u = this.config.llm.options) == null ? void 0 : _u.thinking) !== false);
6772
7920
  let finalRestrictionSuffix = restrictionSuffix;
6773
7921
  if (isSimulatedThinking) {
6774
7922
  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.`)";
@@ -6776,7 +7924,7 @@ ${context}`;
6776
7924
  const hardenedHistory = [...history];
6777
7925
  const userQuestion = { role: "user", content: question + finalRestrictionSuffix };
6778
7926
  const messages = [...hardenedHistory, userQuestion];
6779
- const systemPrompt = (_s = this.config.llm.systemPrompt) != null ? _s : "";
7927
+ const systemPrompt = (_v = this.config.llm.systemPrompt) != null ? _v : "";
6780
7928
  const userPrompt = messages.map((m) => `${m.role}: ${m.content}`).join("\n");
6781
7929
  let fullReply = "";
6782
7930
  let thinkingText = "";
@@ -6887,7 +8035,7 @@ ${context}`;
6887
8035
  }
6888
8036
  yield fullReply;
6889
8037
  }
6890
- 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;
8038
+ const runHallucination = ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) === true || this.config.llm.provider !== "ollama" && ((_x = this.config.llm.options) == null ? void 0 : _x.hallucinationScoring) !== false;
6891
8039
  if (runHallucination) {
6892
8040
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
6893
8041
  }
@@ -6896,7 +8044,7 @@ ${context}`;
6896
8044
  const latency = {
6897
8045
  embedMs: Math.round(embedMs),
6898
8046
  retrieveMs: Math.round(retrieveMs),
6899
- rerankMs: ((_v = this.config.rag) == null ? void 0 : _v.useReranking) ? Math.round(rerankMs) : void 0,
8047
+ rerankMs: arch !== "naive" && (arch === "retrieve-and-rerank" || ((_y = this.config.rag) == null ? void 0 : _y.useReranking)) ? Math.round(rerankMs) : void 0,
6900
8048
  generateMs: Math.round(generateMs),
6901
8049
  totalMs: Math.round(totalMs)
6902
8050
  };
@@ -6909,33 +8057,63 @@ ${context}`;
6909
8057
  totalTokens: promptTokens + completionTokens,
6910
8058
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
6911
8059
  };
8060
+ const awaitHallucination = ((_z = this.config.llm.options) == null ? void 0 : _z.awaitHallucination) === true;
6912
8061
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
6913
8062
  uiTransformationPromise,
6914
- hallucinationScoringPromise
8063
+ awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
6915
8064
  ]));
6916
- const trace = __spreadValues({
8065
+ const buildTrace = (hScore) => __spreadValues({
6917
8066
  requestId,
6918
8067
  query: question,
6919
8068
  rewrittenQuery,
6920
8069
  systemPrompt,
6921
8070
  userPrompt: question + finalRestrictionSuffix,
6922
8071
  chunks: sources.map((s) => {
6923
- var _a2;
8072
+ var _a3;
6924
8073
  return {
6925
8074
  id: s.id,
6926
8075
  score: s.score,
6927
8076
  content: s.content,
6928
- metadata: (_a2 = s.metadata) != null ? _a2 : {},
8077
+ metadata: (_a3 = s.metadata) != null ? _a3 : {},
6929
8078
  namespace: ns
6930
8079
  };
6931
8080
  }),
6932
8081
  latency,
6933
8082
  tokens,
6934
8083
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
6935
- }, hallucinationResult ? {
6936
- hallucinationScore: hallucinationResult.score,
6937
- hallucinationReason: hallucinationResult.reason
8084
+ }, hScore ? {
8085
+ hallucinationScore: hScore.score,
8086
+ hallucinationReason: hScore.reason
6938
8087
  } : {});
8088
+ const trace = buildTrace(hallucinationResult);
8089
+ if ((_A = this.config.telemetry) == null ? void 0 : _A.enabled) {
8090
+ const telemetryUrl = this.config.telemetry.url || "/api/telemetry";
8091
+ const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
8092
+ (async () => {
8093
+ try {
8094
+ let finalTrace = trace;
8095
+ if (!awaitHallucination && runHallucination) {
8096
+ const backgroundScoreResult = await hallucinationScoringPromise;
8097
+ if (backgroundScoreResult) {
8098
+ finalTrace = buildTrace(backgroundScoreResult);
8099
+ }
8100
+ }
8101
+ await fetch(absoluteUrl, {
8102
+ method: "POST",
8103
+ headers: {
8104
+ "Content-Type": "application/json"
8105
+ },
8106
+ body: JSON.stringify({
8107
+ trace: finalTrace,
8108
+ licenseKey: this.config.licenseKey,
8109
+ projectId: ns
8110
+ })
8111
+ });
8112
+ } catch (err) {
8113
+ console.warn(`[Pipeline Telemetry] Failed to send trace async to ${absoluteUrl}:`, err.message);
8114
+ }
8115
+ })();
8116
+ }
6939
8117
  yield {
6940
8118
  reply: "",
6941
8119
  sources,
@@ -6955,7 +8133,7 @@ ${context}`;
6955
8133
  * Uses an LRU-bounded embedding cache to avoid re-embedding the same query.
6956
8134
  */
6957
8135
  async generateUiTransformation(question, sources, cachedSchema, forceDeterministic = false) {
6958
- var _a;
8136
+ var _a2;
6959
8137
  if (!sources || sources.length === 0) {
6960
8138
  return UITransformer.transform(question, sources, this.config, cachedSchema);
6961
8139
  }
@@ -6969,7 +8147,7 @@ ${context}`;
6969
8147
  );
6970
8148
  }
6971
8149
  const isLocalProvider = this.config.llm.provider === "ollama";
6972
- const disableLlmUiTransform = ((_a = this.config.llm.options) == null ? void 0 : _a.disableLlmUiTransform) === true;
8150
+ const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
6973
8151
  if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
6974
8152
  return UITransformer.transform(question, sources, this.config, cachedSchema);
6975
8153
  }
@@ -6987,9 +8165,9 @@ ${context}`;
6987
8165
  const value = this.resolveNumericPredicateValue(source, predicate);
6988
8166
  return value !== null && this.matchesNumericPredicate(value, predicate);
6989
8167
  })).sort((a, b) => {
6990
- var _a, _b;
8168
+ var _a2, _b;
6991
8169
  const primary = predicates[0];
6992
- const aValue = (_a = this.resolveNumericPredicateValue(a, primary)) != null ? _a : 0;
8170
+ const aValue = (_a2 = this.resolveNumericPredicateValue(a, primary)) != null ? _a2 : 0;
6993
8171
  const bValue = (_b = this.resolveNumericPredicateValue(b, primary)) != null ? _b : 0;
6994
8172
  return primary.operator === "lt" || primary.operator === "lte" ? aValue - bValue : bValue - aValue;
6995
8173
  });
@@ -7061,8 +8239,8 @@ ${context}`;
7061
8239
  return Number.isFinite(numeric) ? numeric : null;
7062
8240
  }
7063
8241
  async retrieve(query, options) {
7064
- var _a, _b, _c, _d, _e, _f, _g;
7065
- const ns = (_a = options.namespace) != null ? _a : this.config.projectId;
8242
+ var _a2, _b, _c, _d, _e, _f, _g2;
8243
+ const ns = (_a2 = options.namespace) != null ? _a2 : this.config.projectId;
7066
8244
  const topK = (_b = options.topK) != null ? _b : 5;
7067
8245
  const cacheKey = `${ns}::${query}`;
7068
8246
  let queryVector = this.embeddingCache.get(cacheKey);
@@ -7094,7 +8272,7 @@ ${context}`;
7094
8272
  ) : [];
7095
8273
  const resolvedSources = [];
7096
8274
  for (const source of sources) {
7097
- const parentId = (_g = source.metadata) == null ? void 0 : _g.parent_id;
8275
+ const parentId = (_g2 = source.metadata) == null ? void 0 : _g2.parent_id;
7098
8276
  if (parentId) {
7099
8277
  console.log(`[Pipeline] Multi-Vector: Found child chunk. Parent ID: ${parentId}`);
7100
8278
  resolvedSources.push(source);
@@ -7176,8 +8354,15 @@ var Retrivora = class {
7176
8354
  this.pipeline = new Pipeline(this.config);
7177
8355
  }
7178
8356
  async initialize() {
8357
+ var _a2;
7179
8358
  try {
7180
8359
  await ConfigValidator.validateAndThrow(this.config);
8360
+ LicenseVerifier.verify(
8361
+ this.config.licenseKey,
8362
+ this.config.projectId,
8363
+ (_a2 = this.config.vectorDb) == null ? void 0 : _a2.provider
8364
+ );
8365
+ await LicenseVerifier.verifyIP(this.config.licenseKey);
7181
8366
  } catch (err) {
7182
8367
  throw wrapError(err, "CONFIGURATION_ERROR");
7183
8368
  }
@@ -7351,11 +8536,20 @@ var ProviderHealthCheck = class {
7351
8536
  // src/core/VectorPlugin.ts
7352
8537
  var VectorPlugin = class {
7353
8538
  constructor(hostConfig) {
7354
- this.config = ConfigResolver.resolve(hostConfig);
7355
- this.validationPromise = ConfigValidator.validateAndThrow(this.config);
8539
+ const resolvedConfig = ConfigResolver.resolve(hostConfig);
8540
+ this.config = resolvedConfig;
8541
+ this.validationPromise = (async () => {
8542
+ var _a2;
8543
+ await ConfigValidator.validateAndThrow(resolvedConfig);
8544
+ LicenseVerifier.verify(
8545
+ resolvedConfig.licenseKey,
8546
+ resolvedConfig.projectId,
8547
+ (_a2 = resolvedConfig.vectorDb) == null ? void 0 : _a2.provider
8548
+ );
8549
+ })();
7356
8550
  this.validationPromise.catch(() => {
7357
8551
  });
7358
- this.pipeline = new Pipeline(this.config);
8552
+ this.pipeline = new Pipeline(resolvedConfig);
7359
8553
  }
7360
8554
  /**
7361
8555
  * Get the current resolved configuration.
@@ -7491,13 +8685,13 @@ var ConfigBuilder = class {
7491
8685
  * Configure the vector database provider
7492
8686
  */
7493
8687
  vectorDb(provider, options) {
7494
- var _a;
8688
+ var _a2;
7495
8689
  if (provider === "auto") {
7496
8690
  this._vectorDb = this._autoDetectVectorDb();
7497
8691
  } else {
7498
8692
  this._vectorDb = {
7499
8693
  provider,
7500
- indexName: (_a = options == null ? void 0 : options.indexName) != null ? _a : "default",
8694
+ indexName: (_a2 = options == null ? void 0 : options.indexName) != null ? _a2 : "default",
7501
8695
  options: __spreadValues({}, options)
7502
8696
  };
7503
8697
  }
@@ -7507,7 +8701,7 @@ var ConfigBuilder = class {
7507
8701
  * Configure the LLM provider for chat
7508
8702
  */
7509
8703
  llm(provider, model, apiKey, options) {
7510
- var _a, _b;
8704
+ var _a2, _b;
7511
8705
  if (provider === "auto") {
7512
8706
  this._llm = this._autoDetectLLM();
7513
8707
  } else {
@@ -7516,7 +8710,7 @@ var ConfigBuilder = class {
7516
8710
  model: model != null ? model : "default-model",
7517
8711
  apiKey,
7518
8712
  systemPrompt: options == null ? void 0 : options.systemPrompt,
7519
- maxTokens: (_a = options == null ? void 0 : options.maxTokens) != null ? _a : 1024,
8713
+ maxTokens: (_a2 = options == null ? void 0 : options.maxTokens) != null ? _a2 : 1024,
7520
8714
  temperature: (_b = options == null ? void 0 : options.temperature) != null ? _b : 0.7,
7521
8715
  baseUrl: options == null ? void 0 : options.baseUrl,
7522
8716
  options
@@ -7559,8 +8753,8 @@ var ConfigBuilder = class {
7559
8753
  * Set RAG-specific pipeline parameters
7560
8754
  */
7561
8755
  rag(options) {
7562
- var _a;
7563
- this._rag = __spreadValues(__spreadValues({}, (_a = this._rag) != null ? _a : {}), options);
8756
+ var _a2;
8757
+ this._rag = __spreadValues(__spreadValues({}, (_a2 = this._rag) != null ? _a2 : {}), options);
7564
8758
  return this;
7565
8759
  }
7566
8760
  /**
@@ -7576,7 +8770,7 @@ var ConfigBuilder = class {
7576
8770
  * Throws if required fields (projectId, vectorDb, llm, embedding) are not set.
7577
8771
  */
7578
8772
  build() {
7579
- var _a;
8773
+ var _a2;
7580
8774
  const missing = [];
7581
8775
  if (!this._projectId) missing.push('projectId (call .projectId("my-app"))');
7582
8776
  if (!this._vectorDb) missing.push('vectorDb (call .vectorDb("pinecone", { ... }))');
@@ -7588,7 +8782,7 @@ var ConfigBuilder = class {
7588
8782
  ${missing.join("\n ")}`
7589
8783
  );
7590
8784
  }
7591
- const ragConfig = (_a = this._rag) != null ? _a : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
8785
+ const ragConfig = (_a2 = this._rag) != null ? _a2 : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
7592
8786
  if (process.env.RAG_USE_GRAPH_RETRIEVAL === "true") {
7593
8787
  ragConfig.useGraphRetrieval = true;
7594
8788
  }
@@ -7684,8 +8878,8 @@ var DocumentParser = class {
7684
8878
  * Extract text from a File or Buffer based on its type.
7685
8879
  */
7686
8880
  static async parse(file, fileName, mimeType) {
7687
- var _a;
7688
- const extension = (_a = fileName.split(".").pop()) == null ? void 0 : _a.toLowerCase();
8881
+ var _a2;
8882
+ const extension = (_a2 = fileName.split(".").pop()) == null ? void 0 : _a2.toLowerCase();
7689
8883
  if (extension === "txt" || extension === "md" || mimeType === "text/plain" || mimeType === "text/markdown") {
7690
8884
  return this.readAsText(file);
7691
8885
  }
@@ -7752,6 +8946,497 @@ init_UniversalVectorProvider();
7752
8946
 
7753
8947
  // src/handlers/index.ts
7754
8948
  var import_server = require("next/server");
8949
+
8950
+ // src/core/DatabaseStorage.ts
8951
+ var fs = __toESM(require("fs"));
8952
+ var path = __toESM(require("path"));
8953
+ var DatabaseStorage = class {
8954
+ constructor(config) {
8955
+ // Dynamic PG Pool
8956
+ this.pgPool = null;
8957
+ // Dynamic MongoDB Client
8958
+ this.mongoClient = null;
8959
+ this.mongoDbName = "";
8960
+ // Filesystem fallback configuration
8961
+ this.fallbackDir = path.join(process.cwd(), ".retrivora");
8962
+ this.historyFile = path.join(this.fallbackDir, "history.json");
8963
+ this.feedbackFile = path.join(this.fallbackDir, "feedback.json");
8964
+ var _a2, _b, _c, _d, _e;
8965
+ this.config = config;
8966
+ this.provider = ((_a2 = config.vectorDb) == null ? void 0 : _a2.provider) || "fs";
8967
+ const rawHistoryTable = ((_c = (_b = config.rag) == null ? void 0 : _b.history) == null ? void 0 : _c.tableName) || "retrivora_history";
8968
+ const rawFeedbackTable = ((_e = (_d = config.rag) == null ? void 0 : _d.feedback) == null ? void 0 : _e.tableName) || "retrivora_feedback";
8969
+ this.historyTableName = rawHistoryTable.replace(/[^a-zA-Z0-9_]/g, "_");
8970
+ this.feedbackTableName = rawFeedbackTable.replace(/[^a-zA-Z0-9_]/g, "_");
8971
+ }
8972
+ /**
8973
+ * Asserts the user is running a valid Premium/Enterprise license in production.
8974
+ * In non-production (development / test) environments this is a complete no-op —
8975
+ * all History and Feedback features are freely accessible for local development.
8976
+ */
8977
+ checkPremiumSubscription() {
8978
+ if (process.env.NODE_ENV !== "production") {
8979
+ return;
8980
+ }
8981
+ if (!this.config.licenseKey) {
8982
+ throw new Error(
8983
+ "[Retrivora SDK] Chat History and Feedback features require a Premium or Enterprise license key in production."
8984
+ );
8985
+ }
8986
+ try {
8987
+ const payload = LicenseVerifier.verify(this.config.licenseKey, this.config.projectId);
8988
+ const tier = (payload.tier || "").toLowerCase();
8989
+ if (tier !== "premium" && tier !== "enterprise" && tier !== "growth" && tier !== "pro" && tier !== "developer_pro") {
8990
+ throw new Error(
8991
+ `[Retrivora SDK] Chat History and Feedback features are not available on the "${tier}" tier. Please upgrade to a Developer Pro or Enterprise plan.`
8992
+ );
8993
+ }
8994
+ } catch (err) {
8995
+ throw new Error(
8996
+ `[Retrivora SDK] Subscription check failed: ${err instanceof Error ? err.message : String(err)}`
8997
+ );
8998
+ }
8999
+ }
9000
+ checkHistoryEnabled() {
9001
+ var _a2, _b;
9002
+ this.checkPremiumSubscription();
9003
+ if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.history) == null ? void 0 : _b.enabled) === false) {
9004
+ throw new Error("[Retrivora SDK] Chat History is disabled in RagConfig.");
9005
+ }
9006
+ }
9007
+ checkFeedbackEnabled() {
9008
+ var _a2, _b;
9009
+ this.checkPremiumSubscription();
9010
+ if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.feedback) == null ? void 0 : _b.enabled) === false) {
9011
+ throw new Error("[Retrivora SDK] User Feedback is disabled in RagConfig.");
9012
+ }
9013
+ }
9014
+ async getPGPool() {
9015
+ const globalKey = `__retrivora_pg_pool_${this.config.projectId}`;
9016
+ const _g2 = global;
9017
+ if (_g2[globalKey]) {
9018
+ this.pgPool = _g2[globalKey];
9019
+ return this.pgPool;
9020
+ }
9021
+ const opts = this.config.vectorDb.options;
9022
+ if (!opts.connectionString) {
9023
+ throw new Error("[DatabaseStorage] pg connectionString option is missing.");
9024
+ }
9025
+ const { Pool: Pool3 } = await import("pg");
9026
+ this.pgPool = new Pool3({ connectionString: opts.connectionString });
9027
+ _g2[globalKey] = this.pgPool;
9028
+ const client = await this.pgPool.connect();
9029
+ try {
9030
+ await client.query(`
9031
+ CREATE TABLE IF NOT EXISTS ${this.historyTableName} (
9032
+ id TEXT PRIMARY KEY,
9033
+ session_id TEXT NOT NULL,
9034
+ role TEXT NOT NULL,
9035
+ content TEXT NOT NULL,
9036
+ sources JSONB,
9037
+ ui_transformation JSONB,
9038
+ trace JSONB,
9039
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
9040
+ )
9041
+ `);
9042
+ await client.query(`
9043
+ CREATE TABLE IF NOT EXISTS ${this.feedbackTableName} (
9044
+ id TEXT PRIMARY KEY,
9045
+ message_id TEXT NOT NULL UNIQUE,
9046
+ session_id TEXT NOT NULL,
9047
+ rating TEXT NOT NULL,
9048
+ comment TEXT,
9049
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
9050
+ )
9051
+ `);
9052
+ } finally {
9053
+ client.release();
9054
+ }
9055
+ return this.pgPool;
9056
+ }
9057
+ async getMongoClient() {
9058
+ const globalKey = `__retrivora_mongo_client_${this.config.projectId}`;
9059
+ const _g2 = global;
9060
+ if (_g2[globalKey]) {
9061
+ this.mongoClient = _g2[globalKey];
9062
+ this.mongoDbName = this.config.vectorDb.options.database;
9063
+ return this.mongoClient;
9064
+ }
9065
+ const opts = this.config.vectorDb.options;
9066
+ if (!opts.uri || !opts.database) {
9067
+ throw new Error("[DatabaseStorage] mongo uri and database options are missing.");
9068
+ }
9069
+ const { MongoClient: MongoClient2 } = await import("mongodb");
9070
+ this.mongoClient = new MongoClient2(opts.uri);
9071
+ await this.mongoClient.connect();
9072
+ _g2[globalKey] = this.mongoClient;
9073
+ this.mongoDbName = opts.database;
9074
+ return this.mongoClient;
9075
+ }
9076
+ getMongoDb() {
9077
+ return this.mongoClient.db(this.mongoDbName);
9078
+ }
9079
+ // Helper for FS fallback reads
9080
+ readLocalFile(filePath) {
9081
+ if (!fs.existsSync(filePath)) return [];
9082
+ try {
9083
+ const raw = fs.readFileSync(filePath, "utf-8");
9084
+ return JSON.parse(raw) || [];
9085
+ } catch (e) {
9086
+ return [];
9087
+ }
9088
+ }
9089
+ // Helper for FS fallback writes
9090
+ writeLocalFile(filePath, data) {
9091
+ if (!fs.existsSync(this.fallbackDir)) {
9092
+ fs.mkdirSync(this.fallbackDir, { recursive: true });
9093
+ }
9094
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
9095
+ }
9096
+ // ─── Message History Operations ──────────────────────────────────────────
9097
+ async saveMessage(sessionId, message) {
9098
+ this.checkHistoryEnabled();
9099
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
9100
+ const msgId = message.id || `msg_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9101
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9102
+ const pool = await this.getPGPool();
9103
+ await pool.query(
9104
+ `INSERT INTO ${this.historyTableName} (id, session_id, role, content, sources, ui_transformation, trace, created_at)
9105
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
9106
+ ON CONFLICT (id) DO UPDATE
9107
+ SET content = EXCLUDED.content, sources = EXCLUDED.sources, ui_transformation = EXCLUDED.ui_transformation, trace = EXCLUDED.trace`,
9108
+ [
9109
+ msgId,
9110
+ sessionId,
9111
+ message.role,
9112
+ message.content,
9113
+ message.sources ? JSON.stringify(message.sources) : null,
9114
+ message.uiTransformation ? JSON.stringify(message.uiTransformation) : null,
9115
+ message.trace ? JSON.stringify(message.trace) : null,
9116
+ createdAt
9117
+ ]
9118
+ );
9119
+ } else if (this.provider === "mongodb") {
9120
+ await this.getMongoClient();
9121
+ const db = this.getMongoDb();
9122
+ const col = db.collection(this.historyTableName);
9123
+ await col.updateOne(
9124
+ { id: msgId },
9125
+ {
9126
+ $set: {
9127
+ id: msgId,
9128
+ session_id: sessionId,
9129
+ role: message.role,
9130
+ content: message.content,
9131
+ sources: message.sources || null,
9132
+ ui_transformation: message.uiTransformation || null,
9133
+ trace: message.trace || null,
9134
+ created_at: createdAt
9135
+ }
9136
+ },
9137
+ { upsert: true }
9138
+ );
9139
+ } else {
9140
+ const history = this.readLocalFile(this.historyFile);
9141
+ const index = history.findIndex((h) => h.id === msgId);
9142
+ const item = {
9143
+ id: msgId,
9144
+ session_id: sessionId,
9145
+ role: message.role,
9146
+ content: message.content,
9147
+ sources: message.sources || null,
9148
+ ui_transformation: message.uiTransformation || null,
9149
+ trace: message.trace || null,
9150
+ created_at: createdAt
9151
+ };
9152
+ if (index !== -1) {
9153
+ history[index] = item;
9154
+ } else {
9155
+ history.push(item);
9156
+ }
9157
+ this.writeLocalFile(this.historyFile, history);
9158
+ }
9159
+ }
9160
+ async getHistory(sessionId) {
9161
+ this.checkHistoryEnabled();
9162
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9163
+ const pool = await this.getPGPool();
9164
+ const res = await pool.query(
9165
+ `SELECT id, role, content, sources, ui_transformation as "uiTransformation", trace, created_at as "createdAt"
9166
+ FROM ${this.historyTableName}
9167
+ WHERE session_id = $1
9168
+ ORDER BY created_at ASC`,
9169
+ [sessionId]
9170
+ );
9171
+ return res.rows;
9172
+ } else if (this.provider === "mongodb") {
9173
+ await this.getMongoClient();
9174
+ const db = this.getMongoDb();
9175
+ const col = db.collection(this.historyTableName);
9176
+ const items = await col.find({ session_id: sessionId }).sort({ created_at: 1 }).toArray();
9177
+ return items.map((item) => ({
9178
+ id: item.id,
9179
+ role: item.role,
9180
+ content: item.content,
9181
+ sources: item.sources,
9182
+ uiTransformation: item.ui_transformation,
9183
+ trace: item.trace,
9184
+ createdAt: item.created_at
9185
+ }));
9186
+ } else {
9187
+ const history = this.readLocalFile(this.historyFile);
9188
+ return history.filter((h) => h.session_id === sessionId).sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
9189
+ }
9190
+ }
9191
+ async clearHistory(sessionId) {
9192
+ this.checkHistoryEnabled();
9193
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9194
+ const pool = await this.getPGPool();
9195
+ await pool.query(`DELETE FROM ${this.historyTableName} WHERE session_id = $1`, [sessionId]);
9196
+ await pool.query(`DELETE FROM ${this.feedbackTableName} WHERE session_id = $1`, [sessionId]);
9197
+ } else if (this.provider === "mongodb") {
9198
+ await this.getMongoClient();
9199
+ const db = this.getMongoDb();
9200
+ await db.collection(this.historyTableName).deleteMany({ session_id: sessionId });
9201
+ await db.collection(this.feedbackTableName).deleteMany({ session_id: sessionId });
9202
+ } else {
9203
+ const history = this.readLocalFile(this.historyFile);
9204
+ const filteredHistory = history.filter((h) => h.session_id !== sessionId);
9205
+ this.writeLocalFile(this.historyFile, filteredHistory);
9206
+ const feedback = this.readLocalFile(this.feedbackFile);
9207
+ const filteredFeedback = feedback.filter((f) => f.session_id !== sessionId);
9208
+ this.writeLocalFile(this.feedbackFile, filteredFeedback);
9209
+ }
9210
+ }
9211
+ async listSessions() {
9212
+ this.checkHistoryEnabled();
9213
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9214
+ const pool = await this.getPGPool();
9215
+ const res = await pool.query(`SELECT DISTINCT session_id FROM ${this.historyTableName}`);
9216
+ return res.rows.map((r) => r.session_id);
9217
+ } else if (this.provider === "mongodb") {
9218
+ await this.getMongoClient();
9219
+ const db = this.getMongoDb();
9220
+ return db.collection(this.historyTableName).distinct("session_id");
9221
+ } else {
9222
+ const history = this.readLocalFile(this.historyFile);
9223
+ const sessions = new Set(history.map((h) => h.session_id));
9224
+ return Array.from(sessions);
9225
+ }
9226
+ }
9227
+ // ─── Feedback Operations ──────────────────────────────────────────────────
9228
+ async saveFeedback(feedback) {
9229
+ this.checkFeedbackEnabled();
9230
+ const id = `fb_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9231
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
9232
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9233
+ const pool = await this.getPGPool();
9234
+ await pool.query(
9235
+ `INSERT INTO ${this.feedbackTableName} (id, message_id, session_id, rating, comment, created_at)
9236
+ VALUES ($1, $2, $3, $4, $5, $6)
9237
+ ON CONFLICT (message_id) DO UPDATE
9238
+ SET rating = EXCLUDED.rating, comment = EXCLUDED.comment`,
9239
+ [id, feedback.messageId, feedback.sessionId, feedback.rating, feedback.comment || null, createdAt]
9240
+ );
9241
+ } else if (this.provider === "mongodb") {
9242
+ await this.getMongoClient();
9243
+ const db = this.getMongoDb();
9244
+ const col = db.collection(this.feedbackTableName);
9245
+ await col.updateOne(
9246
+ { message_id: feedback.messageId },
9247
+ {
9248
+ $set: {
9249
+ id,
9250
+ message_id: feedback.messageId,
9251
+ session_id: feedback.sessionId,
9252
+ rating: feedback.rating,
9253
+ comment: feedback.comment || null,
9254
+ created_at: createdAt
9255
+ }
9256
+ },
9257
+ { upsert: true }
9258
+ );
9259
+ } else {
9260
+ const list = this.readLocalFile(this.feedbackFile);
9261
+ const index = list.findIndex((f) => f.message_id === feedback.messageId);
9262
+ const item = {
9263
+ id,
9264
+ message_id: feedback.messageId,
9265
+ session_id: feedback.sessionId,
9266
+ rating: feedback.rating,
9267
+ comment: feedback.comment || null,
9268
+ created_at: createdAt
9269
+ };
9270
+ if (index !== -1) {
9271
+ list[index] = item;
9272
+ } else {
9273
+ list.push(item);
9274
+ }
9275
+ this.writeLocalFile(this.feedbackFile, list);
9276
+ }
9277
+ }
9278
+ async getFeedback(messageId) {
9279
+ this.checkFeedbackEnabled();
9280
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9281
+ const pool = await this.getPGPool();
9282
+ const res = await pool.query(
9283
+ `SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
9284
+ FROM ${this.feedbackTableName}
9285
+ WHERE message_id = $1`,
9286
+ [messageId]
9287
+ );
9288
+ return res.rows[0] || null;
9289
+ } else if (this.provider === "mongodb") {
9290
+ await this.getMongoClient();
9291
+ const db = this.getMongoDb();
9292
+ const col = db.collection(this.feedbackTableName);
9293
+ const item = await col.findOne({ message_id: messageId });
9294
+ if (!item) return null;
9295
+ return {
9296
+ id: item.id,
9297
+ messageId: item.message_id,
9298
+ sessionId: item.session_id,
9299
+ rating: item.rating,
9300
+ comment: item.comment,
9301
+ createdAt: item.created_at
9302
+ };
9303
+ } else {
9304
+ const list = this.readLocalFile(this.feedbackFile);
9305
+ return list.find((f) => f.message_id === messageId) || null;
9306
+ }
9307
+ }
9308
+ async listFeedback() {
9309
+ this.checkFeedbackEnabled();
9310
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9311
+ const pool = await this.getPGPool();
9312
+ const res = await pool.query(
9313
+ `SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
9314
+ FROM ${this.feedbackTableName}
9315
+ ORDER BY created_at DESC`
9316
+ );
9317
+ return res.rows;
9318
+ } else if (this.provider === "mongodb") {
9319
+ await this.getMongoClient();
9320
+ const db = this.getMongoDb();
9321
+ const col = db.collection(this.feedbackTableName);
9322
+ const items = await col.find({}).sort({ created_at: -1 }).toArray();
9323
+ return items.map((item) => ({
9324
+ id: item.id,
9325
+ messageId: item.message_id,
9326
+ sessionId: item.session_id,
9327
+ rating: item.rating,
9328
+ comment: item.comment,
9329
+ createdAt: item.created_at
9330
+ }));
9331
+ } else {
9332
+ const list = this.readLocalFile(this.feedbackFile);
9333
+ return [...list].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
9334
+ }
9335
+ }
9336
+ async disconnect() {
9337
+ if (this.pgPool) {
9338
+ await this.pgPool.end();
9339
+ this.pgPool = null;
9340
+ }
9341
+ if (this.mongoClient) {
9342
+ await this.mongoClient.close();
9343
+ this.mongoClient = null;
9344
+ }
9345
+ }
9346
+ };
9347
+
9348
+ // src/handlers/index.ts
9349
+ async function checkAuth(req, onAuthorize) {
9350
+ if (!onAuthorize) return null;
9351
+ try {
9352
+ const res = await onAuthorize(req);
9353
+ if (res === false) {
9354
+ return import_server.NextResponse.json({ error: "Unauthorized" }, { status: 401 });
9355
+ }
9356
+ if (res instanceof Response) {
9357
+ return res;
9358
+ }
9359
+ return null;
9360
+ } catch (err) {
9361
+ const msg = err instanceof Error ? err.message : "Authorization check failed";
9362
+ return import_server.NextResponse.json({ error: msg }, { status: 401 });
9363
+ }
9364
+ }
9365
+ var RateLimiter = class {
9366
+ constructor(windowMs = 6e4, max = 30) {
9367
+ this.hits = /* @__PURE__ */ new Map();
9368
+ this.windowMs = windowMs;
9369
+ this.max = max;
9370
+ }
9371
+ /** Returns true if the request should be allowed, false if rate-limited. */
9372
+ allow(key) {
9373
+ const now = Date.now();
9374
+ const cutoff = now - this.windowMs;
9375
+ const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
9376
+ existing.push(now);
9377
+ this.hits.set(key, existing);
9378
+ if (this.hits.size > 5e3) {
9379
+ for (const [k, timestamps] of this.hits.entries()) {
9380
+ if (timestamps.every((t) => t <= cutoff)) this.hits.delete(k);
9381
+ }
9382
+ }
9383
+ return existing.length <= this.max;
9384
+ }
9385
+ retryAfterSec(key) {
9386
+ const now = Date.now();
9387
+ const cutoff = now - this.windowMs;
9388
+ const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
9389
+ if (existing.length === 0) return 0;
9390
+ return Math.ceil((existing[0] + this.windowMs - now) / 1e3);
9391
+ }
9392
+ };
9393
+ var _g = global;
9394
+ var _a;
9395
+ var rateLimiter = (_a = _g.__retrivoraRateLimiter) != null ? _a : _g.__retrivoraRateLimiter = new RateLimiter(6e4, 30);
9396
+ function getRateLimitKey(req) {
9397
+ var _a2, _b;
9398
+ 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";
9399
+ return `ip:${ip}`;
9400
+ }
9401
+ function checkRateLimit(req) {
9402
+ const key = getRateLimitKey(req);
9403
+ if (!rateLimiter.allow(key)) {
9404
+ const retryAfter = rateLimiter.retryAfterSec(key);
9405
+ return new Response(
9406
+ JSON.stringify({ error: { code: "RATE_LIMITED", message: "Too many requests. Please slow down." } }),
9407
+ {
9408
+ status: 429,
9409
+ headers: {
9410
+ "Content-Type": "application/json",
9411
+ "Retry-After": String(retryAfter),
9412
+ "X-RateLimit-Limit": "30",
9413
+ "X-RateLimit-Window": "60"
9414
+ }
9415
+ }
9416
+ );
9417
+ }
9418
+ return null;
9419
+ }
9420
+ var MAX_MESSAGE_LENGTH = 8e3;
9421
+ function sanitizeInput(raw) {
9422
+ const stripped = raw.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, "");
9423
+ const trimmed = stripped.trim();
9424
+ if (!trimmed) {
9425
+ return { ok: false, error: "message must not be empty" };
9426
+ }
9427
+ if (trimmed.length > MAX_MESSAGE_LENGTH) {
9428
+ return { ok: false, error: `message must be \u2264 ${MAX_MESSAGE_LENGTH} characters` };
9429
+ }
9430
+ return { ok: true, value: trimmed };
9431
+ }
9432
+ function getOrCreatePlugin(configOrPlugin) {
9433
+ if (configOrPlugin instanceof VectorPlugin) return configOrPlugin;
9434
+ const cacheKey = "__retrivoraPlugin_" + JSON.stringify(configOrPlugin != null ? configOrPlugin : {}).slice(0, 64);
9435
+ if (!_g[cacheKey]) {
9436
+ _g[cacheKey] = new VectorPlugin(configOrPlugin);
9437
+ }
9438
+ return _g[cacheKey];
9439
+ }
7755
9440
  function sseFrame(payload) {
7756
9441
  return `data: ${JSON.stringify(payload)}
7757
9442
 
@@ -7789,47 +9474,88 @@ var SSE_HEADERS = {
7789
9474
  "X-Accel-Buffering": "no"
7790
9475
  // Disable Nginx buffering for streaming
7791
9476
  };
7792
- function createChatHandler(configOrPlugin) {
7793
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9477
+ function createChatHandler(configOrPlugin, options) {
9478
+ const plugin = getOrCreatePlugin(configOrPlugin);
9479
+ const storage = new DatabaseStorage(plugin.getConfig());
9480
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7794
9481
  return async function POST(req) {
9482
+ const authResult = await checkAuth(req, onAuthorize);
9483
+ if (authResult) return authResult;
9484
+ const rateLimited = checkRateLimit(req);
9485
+ if (rateLimited) return rateLimited;
7795
9486
  try {
7796
9487
  const body = await req.json();
7797
- const { message, history = [], namespace } = body;
7798
- if (!(message == null ? void 0 : message.trim())) {
7799
- return import_server.NextResponse.json({ error: "message is required" }, { status: 400 });
7800
- }
9488
+ const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
9489
+ const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
9490
+ if (!sanitized.ok) {
9491
+ return import_server.NextResponse.json({ error: { code: "INVALID_INPUT", message: sanitized.error } }, { status: 400 });
9492
+ }
9493
+ const message = sanitized.value;
9494
+ const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9495
+ await storage.saveMessage(sessionId, {
9496
+ id: userMsgId,
9497
+ role: "user",
9498
+ content: message
9499
+ }).catch((err) => console.warn("[createChatHandler] Failed to save user message:", err));
7801
9500
  const result = await plugin.chat(message, history, namespace);
7802
- return import_server.NextResponse.json(result);
9501
+ const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9502
+ await storage.saveMessage(sessionId, {
9503
+ id: assistantMsgId,
9504
+ role: "assistant",
9505
+ content: result.reply,
9506
+ sources: result.sources,
9507
+ uiTransformation: result.ui_transformation,
9508
+ trace: result.trace
9509
+ }).catch((err) => console.warn("[createChatHandler] Failed to save assistant message:", err));
9510
+ return import_server.NextResponse.json(__spreadProps(__spreadValues({}, result), {
9511
+ messageId: assistantMsgId,
9512
+ userMessageId: userMsgId
9513
+ }));
7803
9514
  } catch (err) {
7804
9515
  const message = err instanceof Error ? err.message : "Internal server error";
7805
9516
  return import_server.NextResponse.json({ error: message }, { status: 500 });
7806
9517
  }
7807
9518
  };
7808
9519
  }
7809
- function createStreamHandler(configOrPlugin) {
7810
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9520
+ function createStreamHandler(configOrPlugin, options) {
9521
+ const plugin = getOrCreatePlugin(configOrPlugin);
9522
+ const storage = new DatabaseStorage(plugin.getConfig());
9523
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7811
9524
  return async function POST(req) {
9525
+ const authResult = await checkAuth(req, onAuthorize);
9526
+ if (authResult) return authResult;
9527
+ const rateLimited = checkRateLimit(req);
9528
+ if (rateLimited) return rateLimited;
7812
9529
  let body;
7813
9530
  try {
7814
9531
  body = await req.json();
7815
9532
  } catch (e) {
7816
- return new Response(JSON.stringify({ error: "Invalid JSON body" }), {
9533
+ return new Response(JSON.stringify({ error: { code: "INVALID_JSON", message: "Invalid JSON body" } }), {
7817
9534
  status: 400,
7818
9535
  headers: { "Content-Type": "application/json" }
7819
9536
  });
7820
9537
  }
7821
- const { message, history = [], namespace } = body;
7822
- if (!(message == null ? void 0 : message.trim())) {
7823
- return new Response(JSON.stringify({ error: "message is required" }), {
7824
- status: 400,
7825
- headers: { "Content-Type": "application/json" }
7826
- });
9538
+ const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
9539
+ const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
9540
+ if (!sanitized.ok) {
9541
+ return new Response(
9542
+ JSON.stringify({ error: { code: "INVALID_INPUT", message: sanitized.error } }),
9543
+ { status: 400, headers: { "Content-Type": "application/json" } }
9544
+ );
7827
9545
  }
9546
+ const message = sanitized.value;
9547
+ const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9548
+ await storage.saveMessage(sessionId, {
9549
+ id: userMsgId,
9550
+ role: "user",
9551
+ content: message
9552
+ }).catch((err) => console.warn("[createStreamHandler] Failed to save user message:", err));
9553
+ const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
7828
9554
  const encoder = new TextEncoder();
7829
9555
  let isActive = true;
7830
9556
  const stream = new ReadableStream({
7831
9557
  async start(controller) {
7832
- var _a;
9558
+ var _a2;
7833
9559
  const enqueue = (text) => {
7834
9560
  if (!isActive) return;
7835
9561
  try {
@@ -7840,11 +9566,13 @@ function createStreamHandler(configOrPlugin) {
7840
9566
  };
7841
9567
  try {
7842
9568
  const pipelineStream = plugin.chatStream(message, history, namespace);
9569
+ let fullReply = "";
7843
9570
  try {
7844
9571
  for (var iter = __forAwait(pipelineStream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
7845
9572
  const chunk = temp.value;
7846
9573
  if (!isActive) break;
7847
9574
  if (typeof chunk === "string") {
9575
+ fullReply += chunk;
7848
9576
  enqueue(sseTextFrame(chunk));
7849
9577
  } else if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "thinking") {
7850
9578
  enqueue(`data: ${JSON.stringify(chunk)}
@@ -7857,9 +9585,10 @@ function createStreamHandler(configOrPlugin) {
7857
9585
  if (responseChunk == null ? void 0 : responseChunk.trace) {
7858
9586
  enqueue(sseObservabilityFrame(responseChunk.trace));
7859
9587
  }
9588
+ let uiTransformation = responseChunk == null ? void 0 : responseChunk.ui_transformation;
7860
9589
  if (sources.length > 0) {
7861
9590
  try {
7862
- const uiTransformation = (_a = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a : UITransformer.transform(message, sources, plugin.getConfig());
9591
+ uiTransformation = (_a2 = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a2 : UITransformer.transform(message, sources, plugin.getConfig());
7863
9592
  if (uiTransformation) {
7864
9593
  enqueue(sseUIFrame(uiTransformation));
7865
9594
  }
@@ -7867,11 +9596,22 @@ function createStreamHandler(configOrPlugin) {
7867
9596
  console.warn("[createStreamHandler] UI transformation warning:", transformError);
7868
9597
  try {
7869
9598
  const fallback = UITransformer.transform(message, sources, plugin.getConfig());
7870
- if (fallback) enqueue(sseUIFrame(fallback));
9599
+ if (fallback) {
9600
+ uiTransformation = fallback;
9601
+ enqueue(sseUIFrame(fallback));
9602
+ }
7871
9603
  } catch (e) {
7872
9604
  }
7873
9605
  }
7874
9606
  }
9607
+ await storage.saveMessage(sessionId, {
9608
+ id: assistantMsgId,
9609
+ role: "assistant",
9610
+ content: fullReply,
9611
+ sources,
9612
+ uiTransformation,
9613
+ trace: responseChunk == null ? void 0 : responseChunk.trace
9614
+ }).catch((err) => console.warn("[createStreamHandler] Failed to save assistant message:", err));
7875
9615
  }
7876
9616
  }
7877
9617
  } catch (temp) {
@@ -7908,12 +9648,15 @@ function createStreamHandler(configOrPlugin) {
7908
9648
  console.log("[createStreamHandler] Stream connection closed by client:", reason);
7909
9649
  }
7910
9650
  });
7911
- return new Response(stream, { headers: SSE_HEADERS });
9651
+ return new Response(stream, { headers: __spreadProps(__spreadValues({}, SSE_HEADERS), { "x-message-id": assistantMsgId, "x-user-message-id": userMsgId }) });
7912
9652
  };
7913
9653
  }
7914
- function createIngestHandler(configOrPlugin) {
7915
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9654
+ function createIngestHandler(configOrPlugin, options) {
9655
+ const plugin = getOrCreatePlugin(configOrPlugin);
9656
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7916
9657
  return async function POST(req) {
9658
+ const authResult = await checkAuth(req, onAuthorize);
9659
+ if (authResult) return authResult;
7917
9660
  try {
7918
9661
  const body = await req.json();
7919
9662
  const { documents, namespace } = body;
@@ -7928,9 +9671,14 @@ function createIngestHandler(configOrPlugin) {
7928
9671
  }
7929
9672
  };
7930
9673
  }
7931
- function createHealthHandler(configOrPlugin) {
7932
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
7933
- return async function GET() {
9674
+ function createHealthHandler(configOrPlugin, options) {
9675
+ const plugin = getOrCreatePlugin(configOrPlugin);
9676
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9677
+ return async function GET(req) {
9678
+ if (req) {
9679
+ const authResult = await checkAuth(req, onAuthorize);
9680
+ if (authResult) return authResult;
9681
+ }
7934
9682
  try {
7935
9683
  const health = await plugin.checkHealth();
7936
9684
  const status = health.allHealthy ? "ok" : "degraded";
@@ -7945,9 +9693,12 @@ function createHealthHandler(configOrPlugin) {
7945
9693
  }
7946
9694
  };
7947
9695
  }
7948
- function createUploadHandler(configOrPlugin) {
7949
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9696
+ function createUploadHandler(configOrPlugin, options) {
9697
+ const plugin = getOrCreatePlugin(configOrPlugin);
9698
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7950
9699
  return async function POST(req) {
9700
+ const authResult = await checkAuth(req, onAuthorize);
9701
+ if (authResult) return authResult;
7951
9702
  try {
7952
9703
  const formData = await req.formData();
7953
9704
  const files = formData.getAll("files");
@@ -8021,9 +9772,12 @@ function createUploadHandler(configOrPlugin) {
8021
9772
  }
8022
9773
  };
8023
9774
  }
8024
- function createSuggestionsHandler(configOrPlugin) {
8025
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9775
+ function createSuggestionsHandler(configOrPlugin, options) {
9776
+ const plugin = getOrCreatePlugin(configOrPlugin);
9777
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
8026
9778
  return async function POST(req) {
9779
+ const authResult = await checkAuth(req, onAuthorize);
9780
+ if (authResult) return authResult;
8027
9781
  try {
8028
9782
  const body = await req.json();
8029
9783
  const { query, namespace } = body;
@@ -8038,13 +9792,108 @@ function createSuggestionsHandler(configOrPlugin) {
8038
9792
  }
8039
9793
  };
8040
9794
  }
8041
- function createRagHandler(configOrPlugin) {
8042
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
8043
- const chatHandler = createChatHandler(plugin);
8044
- const streamHandler = createStreamHandler(plugin);
8045
- const uploadHandler = createUploadHandler(plugin);
8046
- const healthHandler = createHealthHandler(plugin);
8047
- const suggestionsHandler = createSuggestionsHandler(plugin);
9795
+ function createHistoryHandler(configOrPlugin, options) {
9796
+ const plugin = getOrCreatePlugin(configOrPlugin);
9797
+ const storage = new DatabaseStorage(plugin.getConfig());
9798
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9799
+ return async function handler(req) {
9800
+ const authResult = await checkAuth(req, onAuthorize);
9801
+ if (authResult) return authResult;
9802
+ const url = new URL(req.url);
9803
+ const sessionId = url.searchParams.get("sessionId") || "default";
9804
+ if (req.method === "GET") {
9805
+ try {
9806
+ const history = await storage.getHistory(sessionId);
9807
+ return import_server.NextResponse.json({ history });
9808
+ } catch (err) {
9809
+ const message = err instanceof Error ? err.message : "Failed to fetch history";
9810
+ return import_server.NextResponse.json({ error: message }, { status: 500 });
9811
+ }
9812
+ } else if (req.method === "POST") {
9813
+ try {
9814
+ const body = await req.json().catch(() => ({}));
9815
+ const sid = body.sessionId || sessionId;
9816
+ await storage.clearHistory(sid);
9817
+ return import_server.NextResponse.json({ success: true });
9818
+ } catch (err) {
9819
+ const message = err instanceof Error ? err.message : "Failed to clear history";
9820
+ return import_server.NextResponse.json({ error: message }, { status: 500 });
9821
+ }
9822
+ }
9823
+ return import_server.NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
9824
+ };
9825
+ }
9826
+ function createFeedbackHandler(configOrPlugin, options) {
9827
+ const plugin = getOrCreatePlugin(configOrPlugin);
9828
+ const storage = new DatabaseStorage(plugin.getConfig());
9829
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9830
+ return async function handler(req) {
9831
+ const authResult = await checkAuth(req, onAuthorize);
9832
+ if (authResult) return authResult;
9833
+ if (req.method === "GET") {
9834
+ try {
9835
+ const url = new URL(req.url);
9836
+ const messageId = url.searchParams.get("messageId");
9837
+ if (!messageId) {
9838
+ const feedbackList = await storage.listFeedback();
9839
+ return import_server.NextResponse.json({ feedback: feedbackList });
9840
+ }
9841
+ const feedback = await storage.getFeedback(messageId);
9842
+ return import_server.NextResponse.json({ feedback });
9843
+ } catch (err) {
9844
+ const message = err instanceof Error ? err.message : "Failed to fetch feedback";
9845
+ return import_server.NextResponse.json({ error: message }, { status: 500 });
9846
+ }
9847
+ } else if (req.method === "POST") {
9848
+ try {
9849
+ const body = await req.json();
9850
+ const { messageId, sessionId = "default", rating, comment } = body;
9851
+ if (!messageId) {
9852
+ return import_server.NextResponse.json({ error: "messageId is required" }, { status: 400 });
9853
+ }
9854
+ if (!rating) {
9855
+ return import_server.NextResponse.json({ error: "rating is required" }, { status: 400 });
9856
+ }
9857
+ await storage.saveFeedback({ messageId, sessionId, rating, comment });
9858
+ return import_server.NextResponse.json({ success: true });
9859
+ } catch (err) {
9860
+ const message = err instanceof Error ? err.message : "Failed to save feedback";
9861
+ return import_server.NextResponse.json({ error: message }, { status: 500 });
9862
+ }
9863
+ }
9864
+ return import_server.NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
9865
+ };
9866
+ }
9867
+ function createSessionsHandler(configOrPlugin, options) {
9868
+ const plugin = getOrCreatePlugin(configOrPlugin);
9869
+ const storage = new DatabaseStorage(plugin.getConfig());
9870
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9871
+ return async function GET(req) {
9872
+ if (req) {
9873
+ const authResult = await checkAuth(req, onAuthorize);
9874
+ if (authResult) return authResult;
9875
+ }
9876
+ void req;
9877
+ try {
9878
+ const sessions = await storage.listSessions();
9879
+ return import_server.NextResponse.json({ sessions });
9880
+ } catch (err) {
9881
+ const message = err instanceof Error ? err.message : "Failed to list sessions";
9882
+ return import_server.NextResponse.json({ error: message }, { status: 500 });
9883
+ }
9884
+ };
9885
+ }
9886
+ function createRagHandler(configOrPlugin, options) {
9887
+ const plugin = getOrCreatePlugin(configOrPlugin);
9888
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9889
+ const chatHandler = createChatHandler(plugin, { onAuthorize });
9890
+ const streamHandler = createStreamHandler(plugin, { onAuthorize });
9891
+ const uploadHandler = createUploadHandler(plugin, { onAuthorize });
9892
+ const healthHandler = createHealthHandler(plugin, { onAuthorize });
9893
+ const suggestionsHandler = createSuggestionsHandler(plugin, { onAuthorize });
9894
+ const historyHandler = createHistoryHandler(plugin, { onAuthorize });
9895
+ const feedbackHandler = createFeedbackHandler(plugin, { onAuthorize });
9896
+ const sessionsHandler = createSessionsHandler(plugin, { onAuthorize });
8048
9897
  async function routePostRequest(req, segment) {
8049
9898
  switch (segment) {
8050
9899
  case "chat":
@@ -8056,22 +9905,35 @@ function createRagHandler(configOrPlugin) {
8056
9905
  case "suggestions":
8057
9906
  return suggestionsHandler(req);
8058
9907
  case "health":
8059
- return healthHandler();
9908
+ return healthHandler(req);
9909
+ case "history":
9910
+ case "history/clear":
9911
+ return historyHandler(req);
9912
+ case "feedback":
9913
+ return feedbackHandler(req);
8060
9914
  default:
8061
9915
  return import_server.NextResponse.json({ error: `Not Found: POST segment "${segment}" not supported.` }, { status: 404 });
8062
9916
  }
8063
9917
  }
8064
9918
  async function routeGetRequest(req, segment) {
8065
- if (segment === "health") {
8066
- return healthHandler();
9919
+ switch (segment) {
9920
+ case "health":
9921
+ return healthHandler(req);
9922
+ case "history":
9923
+ return historyHandler(req);
9924
+ case "feedback":
9925
+ return feedbackHandler(req);
9926
+ case "sessions":
9927
+ return sessionsHandler(req);
9928
+ default:
9929
+ return import_server.NextResponse.json({ error: `Method Not Allowed: GET segment "${segment}" not supported.` }, { status: 405 });
8067
9930
  }
8068
- return import_server.NextResponse.json({ error: `Method Not Allowed: GET is only supported for "health" segment.` }, { status: 405 });
8069
9931
  }
8070
9932
  async function getSegment(context) {
8071
- var _a;
8072
- const resolvedParams = typeof ((_a = context == null ? void 0 : context.params) == null ? void 0 : _a.then) === "function" ? await context.params : context == null ? void 0 : context.params;
9933
+ var _a2;
9934
+ 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;
8073
9935
  const segments = (resolvedParams == null ? void 0 : resolvedParams.retrivora) || [];
8074
- return segments[0] || "chat";
9936
+ return segments.join("/") || "chat";
8075
9937
  }
8076
9938
  return {
8077
9939
  GET: async (req, context) => {
@@ -8110,8 +9972,10 @@ function createRagHandler(configOrPlugin) {
8110
9972
  EmbeddingFailedException,
8111
9973
  EmbeddingStrategy,
8112
9974
  EmbeddingStrategyResolver,
9975
+ GroqProvider,
8113
9976
  LLMFactory,
8114
9977
  LLM_PROFILES,
9978
+ LicenseVerifier,
8115
9979
  MilvusProvider,
8116
9980
  MongoDBProvider,
8117
9981
  MultiTablePostgresProvider,
@@ -8125,6 +9989,7 @@ function createRagHandler(configOrPlugin) {
8125
9989
  ProviderNotFoundException,
8126
9990
  ProviderRegistry,
8127
9991
  QdrantProvider,
9992
+ QwenProvider,
8128
9993
  RateLimitException,
8129
9994
  RedisProvider,
8130
9995
  RetrievalException,
@@ -8136,10 +10001,13 @@ function createRagHandler(configOrPlugin) {
8136
10001
  VectorPlugin,
8137
10002
  WeaviateProvider,
8138
10003
  createChatHandler,
10004
+ createFeedbackHandler,
8139
10005
  createFromPreset,
8140
10006
  createHealthHandler,
10007
+ createHistoryHandler,
8141
10008
  createIngestHandler,
8142
10009
  createRagHandler,
10010
+ createSessionsHandler,
8143
10011
  createStreamHandler,
8144
10012
  createUploadHandler,
8145
10013
  getRagConfig,