@retrivora-ai/rag-engine 1.9.7 → 1.9.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (58) hide show
  1. package/README.md +127 -135
  2. package/dist/{ILLMProvider-Bhk6zJOK.d.mts → ILLMProvider-B8ROITYK.d.mts} +57 -2
  3. package/dist/{ILLMProvider-Bhk6zJOK.d.ts → ILLMProvider-B8ROITYK.d.ts} +57 -2
  4. package/dist/handlers/index.d.mts +2 -2
  5. package/dist/handlers/index.d.ts +2 -2
  6. package/dist/handlers/index.js +2198 -457
  7. package/dist/handlers/index.mjs +2195 -457
  8. package/dist/{index-BJ4cd-t5.d.mts → index-B8PbEFSY.d.mts} +12 -2
  9. package/dist/{index-Bu7T6xgr.d.ts → index-BCPKUAVL.d.ts} +27 -52
  10. package/dist/{index-C3SVtPYg.d.mts → index-CrxCy36A.d.mts} +27 -52
  11. package/dist/{index-B9J_XEh0.d.ts → index-DNvoi-sV.d.ts} +12 -2
  12. package/dist/index.css +578 -273
  13. package/dist/index.d.mts +29 -7
  14. package/dist/index.d.ts +29 -7
  15. package/dist/index.js +1160 -282
  16. package/dist/index.mjs +1185 -292
  17. package/dist/server.d.mts +62 -6
  18. package/dist/server.d.ts +62 -6
  19. package/dist/server.js +2061 -306
  20. package/dist/server.mjs +2055 -306
  21. package/package.json +11 -7
  22. package/src/app/constants.tsx +37 -7
  23. package/src/components/AmbientBackground.tsx +10 -10
  24. package/src/components/ArchitectureCard.tsx +43 -7
  25. package/src/components/ArchitectureCardsSection.tsx +37 -4
  26. package/src/components/ChatWidget.tsx +2 -1
  27. package/src/components/ChatWindow.tsx +4 -1
  28. package/src/components/CodeViewer.tsx +19 -14
  29. package/src/components/DocViewer.tsx +43 -49
  30. package/src/components/Documentation.tsx +71 -51
  31. package/src/components/Hero.tsx +103 -20
  32. package/src/components/Lifecycle.tsx +65 -25
  33. package/src/components/MarkdownComponents.tsx +44 -1
  34. package/src/components/MessageBubble.tsx +162 -50
  35. package/src/components/constants.tsx +4 -0
  36. package/src/config/RagConfig.ts +46 -0
  37. package/src/config/constants.ts +4 -0
  38. package/src/config/serverConfig.ts +15 -0
  39. package/src/core/ConfigResolver.ts +6 -0
  40. package/src/core/DatabaseStorage.ts +469 -0
  41. package/src/core/LicenseVerifier.ts +154 -0
  42. package/src/core/MultiAgentCoordinator.ts +239 -0
  43. package/src/core/Pipeline.ts +146 -15
  44. package/src/core/Retrivora.ts +6 -0
  45. package/src/core/VectorPlugin.ts +12 -3
  46. package/src/core/mcp.ts +261 -0
  47. package/src/handlers/index.ts +449 -63
  48. package/src/hooks/useRagChat.ts +96 -42
  49. package/src/hooks/useStoredMessages.ts +15 -4
  50. package/src/index.ts +5 -0
  51. package/src/llm/LLMFactory.ts +9 -1
  52. package/src/llm/providers/GroqProvider.ts +176 -0
  53. package/src/llm/providers/QwenProvider.ts +191 -0
  54. package/src/server.ts +7 -0
  55. package/src/types/chat.ts +14 -0
  56. package/src/types/props.ts +12 -0
  57. package/.env.example +0 -80
  58. package/LICENSE.txt +0 -21
package/dist/server.mjs CHANGED
@@ -59,9 +59,9 @@ var __forAwait = (obj, it, method) => (it = obj[__knownSymbol("asyncIterator")])
59
59
  function isRecord(value) {
60
60
  return typeof value === "object" && value !== null;
61
61
  }
62
- function resolvePath(obj, path) {
63
- if (!path || !obj) return void 0;
64
- return path.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
62
+ function resolvePath(obj, path2) {
63
+ if (!path2 || !obj) return void 0;
64
+ return path2.replace(/\[(\w+)\]/g, ".$1").replace(/^\./, "").split(".").reduce((current, segment) => {
65
65
  if (!isRecord(current) && !Array.isArray(current)) {
66
66
  return void 0;
67
67
  }
@@ -171,7 +171,7 @@ var init_PineconeProvider = __esm({
171
171
  static getHealthChecker() {
172
172
  return {
173
173
  async check(config) {
174
- var _a, _b;
174
+ var _a2, _b;
175
175
  const opts = config.options || {};
176
176
  const indexName = config.indexName;
177
177
  const timestamp = Date.now();
@@ -179,7 +179,7 @@ var init_PineconeProvider = __esm({
179
179
  const { Pinecone: Pinecone2 } = await import("@pinecone-database/pinecone");
180
180
  const client = new Pinecone2({ apiKey: opts.apiKey });
181
181
  const indexes = await client.listIndexes();
182
- const indexNames = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
182
+ const indexNames = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
183
183
  if (!indexNames.includes(indexName)) {
184
184
  return {
185
185
  healthy: false,
@@ -206,10 +206,10 @@ var init_PineconeProvider = __esm({
206
206
  };
207
207
  }
208
208
  async initialize() {
209
- var _a, _b;
209
+ var _a2, _b;
210
210
  this.client = new Pinecone({ apiKey: this.apiKey });
211
211
  const indexes = await this.client.listIndexes();
212
- const names = (_b = (_a = indexes.indexes) == null ? void 0 : _a.map((i) => i.name)) != null ? _b : [];
212
+ const names = (_b = (_a2 = indexes.indexes) == null ? void 0 : _a2.map((i) => i.name)) != null ? _b : [];
213
213
  if (!names.includes(this.indexName)) {
214
214
  throw new Error(
215
215
  `[PineconeProvider] Index "${this.indexName}" not found. Available: ${names.join(", ")}`
@@ -221,12 +221,12 @@ var init_PineconeProvider = __esm({
221
221
  return namespace ? idx.namespace(namespace) : idx.namespace("");
222
222
  }
223
223
  async upsert(doc, namespace) {
224
- var _a;
224
+ var _a2;
225
225
  await this.index(namespace).upsert({
226
226
  records: [{
227
227
  id: String(doc.id),
228
228
  values: doc.vector,
229
- metadata: __spreadValues({ content: doc.content }, (_a = doc.metadata) != null ? _a : {})
229
+ metadata: __spreadValues({ content: doc.content }, (_a2 = doc.metadata) != null ? _a2 : {})
230
230
  }]
231
231
  });
232
232
  }
@@ -234,29 +234,29 @@ var init_PineconeProvider = __esm({
234
234
  const BATCH = 100;
235
235
  for (let i = 0; i < docs.length; i += BATCH) {
236
236
  const records = docs.slice(i, i + BATCH).map((d) => {
237
- var _a;
237
+ var _a2;
238
238
  return {
239
239
  id: String(d.id),
240
240
  values: d.vector,
241
- metadata: __spreadValues({ content: d.content }, (_a = d.metadata) != null ? _a : {})
241
+ metadata: __spreadValues({ content: d.content }, (_a2 = d.metadata) != null ? _a2 : {})
242
242
  };
243
243
  });
244
244
  await this.index(namespace).upsert({ records });
245
245
  }
246
246
  }
247
247
  async query(vector, topK, namespace, filter) {
248
- var _a;
248
+ var _a2;
249
249
  const pineconeFilter = this.sanitizeFilter(filter);
250
250
  const result = await this.index(namespace).query(__spreadValues({
251
251
  vector,
252
252
  topK,
253
253
  includeMetadata: true
254
254
  }, Object.keys(pineconeFilter).length > 0 ? { filter: pineconeFilter } : {}));
255
- return ((_a = result.matches) != null ? _a : []).map((m) => {
256
- var _a2, _b;
255
+ return ((_a2 = result.matches) != null ? _a2 : []).map((m) => {
256
+ var _a3, _b;
257
257
  return {
258
258
  id: m.id,
259
- score: (_a2 = m.score) != null ? _a2 : 0,
259
+ score: (_a3 = m.score) != null ? _a3 : 0,
260
260
  content: ((_b = m.metadata) == null ? void 0 : _b.content) || "",
261
261
  metadata: m.metadata
262
262
  };
@@ -295,13 +295,13 @@ var init_PostgreSQLProvider = __esm({
295
295
  init_BaseVectorProvider();
296
296
  PostgreSQLProvider = class extends BaseVectorProvider {
297
297
  constructor(config) {
298
- var _a;
298
+ var _a2;
299
299
  super(config);
300
300
  this.tableName = this.indexName.replace(/[^a-z0-9_]/gi, "_");
301
301
  const opts = config.options;
302
302
  if (!opts.connectionString) throw new Error("[PostgreSQLProvider] options.connectionString is required");
303
303
  this.connectionString = opts.connectionString;
304
- this.dimensions = (_a = opts.dimensions) != null ? _a : 1536;
304
+ this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 1536;
305
305
  }
306
306
  static getValidator() {
307
307
  return {
@@ -382,7 +382,7 @@ var init_PostgreSQLProvider = __esm({
382
382
  }
383
383
  }
384
384
  async upsert(doc, namespace = "") {
385
- var _a;
385
+ var _a2;
386
386
  const vectorLiteral = `[${doc.vector.join(",")}]`;
387
387
  await this.pool.query(
388
388
  `INSERT INTO ${this.tableName} (id, namespace, content, metadata, embedding)
@@ -392,7 +392,7 @@ var init_PostgreSQLProvider = __esm({
392
392
  content = EXCLUDED.content,
393
393
  metadata = EXCLUDED.metadata,
394
394
  embedding = EXCLUDED.embedding`,
395
- [doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), vectorLiteral]
395
+ [doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), vectorLiteral]
396
396
  );
397
397
  }
398
398
  async batchUpsert(docs, namespace = "") {
@@ -405,9 +405,9 @@ var init_PostgreSQLProvider = __esm({
405
405
  const batch = docs.slice(i, i + BATCH_SIZE);
406
406
  const values = [];
407
407
  const valuePlaceholders = batch.map((doc, idx) => {
408
- var _a;
408
+ var _a2;
409
409
  const offset = idx * 5;
410
- values.push(doc.id, namespace, doc.content, JSON.stringify((_a = doc.metadata) != null ? _a : {}), `[${doc.vector.join(",")}]`);
410
+ values.push(doc.id, namespace, doc.content, JSON.stringify((_a2 = doc.metadata) != null ? _a2 : {}), `[${doc.vector.join(",")}]`);
411
411
  return `($${offset + 1}, $${offset + 2}, $${offset + 3}, $${offset + 4}, $${offset + 5}::vector)`;
412
412
  }).join(", ");
413
413
  const query = `
@@ -490,8 +490,8 @@ var init_PostgreSQLProvider = __esm({
490
490
 
491
491
  // src/utils/synonyms.ts
492
492
  function resolveMetadataValue(meta, uiKey) {
493
- var _a;
494
- const synonyms = (_a = FIELD_SYNONYMS[uiKey]) != null ? _a : [];
493
+ var _a2;
494
+ const synonyms = (_a2 = FIELD_SYNONYMS[uiKey]) != null ? _a2 : [];
495
495
  const keys = Object.keys(meta);
496
496
  const systemKeys = ["namespace", "filename", "filesize", "filetype", "docid", "uploadedat", "dimension", "chunkindex"];
497
497
  let match = keys.find((k) => k.toLowerCase() === uiKey.toLowerCase());
@@ -578,14 +578,14 @@ var init_MultiTablePostgresProvider = __esm({
578
578
  init_synonyms();
579
579
  MultiTablePostgresProvider = class extends BaseVectorProvider {
580
580
  constructor(config) {
581
- var _a, _b, _c;
581
+ var _a2, _b, _c;
582
582
  super(config);
583
583
  const opts = config.options || {};
584
584
  if (!opts.connectionString) {
585
585
  throw new Error("[MultiTablePostgresProvider] options.connectionString is required");
586
586
  }
587
587
  this.connectionString = opts.connectionString;
588
- this.dimensions = (_a = opts.dimensions) != null ? _a : 768;
588
+ this.dimensions = (_a2 = opts.dimensions) != null ? _a2 : 768;
589
589
  this.tables = [];
590
590
  const rawSearchFields = (_c = (_b = opts.searchFields) != null ? _b : process.env.VECTOR_DB_SEARCH_FIELDS) != null ? _c : ["name", "product_name", "productname", "title"];
591
591
  this.searchFields = typeof rawSearchFields === "string" ? rawSearchFields.split(",").map((f) => f.trim()).filter(Boolean) : rawSearchFields;
@@ -643,11 +643,11 @@ var init_MultiTablePostgresProvider = __esm({
643
643
  * Batch upsert documents by dynamically provisioning tables and columns based on CSV headers.
644
644
  */
645
645
  async batchUpsert(docs, namespace = "") {
646
- var _a;
646
+ var _a2;
647
647
  if (docs.length === 0) return;
648
648
  const docsByFile = {};
649
649
  for (const doc of docs) {
650
- const fileName = ((_a = doc.metadata) == null ? void 0 : _a.fileName) || this.uploadTable;
650
+ const fileName = ((_a2 = doc.metadata) == null ? void 0 : _a2.fileName) || this.uploadTable;
651
651
  if (!docsByFile[fileName]) docsByFile[fileName] = [];
652
652
  docsByFile[fileName].push(doc);
653
653
  }
@@ -700,11 +700,11 @@ var init_MultiTablePostgresProvider = __esm({
700
700
  const headerColumns = csvHeaders.map((h) => `"${h}"`).join(", ");
701
701
  const allColumns = `id, ${headerColumns ? headerColumns + ", " : ""}namespace, content, metadata, embedding`;
702
702
  const valuePlaceholders = batch.map((doc, idx) => {
703
- var _a2, _b;
703
+ var _a3, _b;
704
704
  const offset = idx * (5 + csvHeaders.length);
705
705
  values.push(doc.id);
706
706
  for (const h of csvHeaders) {
707
- values.push(String(((_a2 = doc.metadata) == null ? void 0 : _a2[h]) || ""));
707
+ values.push(String(((_a3 = doc.metadata) == null ? void 0 : _a3[h]) || ""));
708
708
  }
709
709
  values.push(namespace, doc.content, JSON.stringify((_b = doc.metadata) != null ? _b : {}), `[${doc.vector.join(",")}]`);
710
710
  const docPlaceholders = [];
@@ -743,7 +743,7 @@ var init_MultiTablePostgresProvider = __esm({
743
743
  * Query all configured tables and merge results, sorted by cosine similarity score.
744
744
  */
745
745
  async query(vector, topK, _namespace, _filter) {
746
- var _a;
746
+ var _a2;
747
747
  if (!this.pool) {
748
748
  throw new Error("[MultiTablePostgresProvider] Provider not initialized. Call initialize() first.");
749
749
  }
@@ -774,11 +774,11 @@ var init_MultiTablePostgresProvider = __esm({
774
774
  const filterParams = [];
775
775
  if (metadataFilters && Object.keys(metadataFilters).length > 0) {
776
776
  const conditions = Object.entries(metadataFilters).map(([key, val]) => {
777
- var _a3;
777
+ var _a4;
778
778
  filterParams.push(String(val));
779
779
  const baseOffset = queryText && dynamicKeywordQuery ? 2 : 1;
780
780
  const paramIdx = baseOffset + filterParams.length;
781
- const synonyms = (_a3 = FIELD_SYNONYMS[key]) != null ? _a3 : [];
781
+ const synonyms = (_a4 = FIELD_SYNONYMS[key]) != null ? _a4 : [];
782
782
  const keysToCheck = [key, ...synonyms];
783
783
  const coalesceExprs = keysToCheck.flatMap((k) => [
784
784
  `metadata->>'${k}'`,
@@ -847,7 +847,7 @@ var init_MultiTablePostgresProvider = __esm({
847
847
  }
848
848
  const tableResults = [];
849
849
  for (const row of result.rows) {
850
- const _a2 = row, { hybrid_score, id } = _a2, rest = __objRest(_a2, ["hybrid_score", "id"]);
850
+ const _a3 = row, { hybrid_score, id } = _a3, rest = __objRest(_a3, ["hybrid_score", "id"]);
851
851
  delete rest.embedding;
852
852
  delete rest.vector_score;
853
853
  delete rest.keyword_score;
@@ -876,10 +876,10 @@ var init_MultiTablePostgresProvider = __esm({
876
876
  }
877
877
  allResults.sort((a, b) => b.score - a.score);
878
878
  if (allResults.length === 0) return [];
879
- const bestMatchTable = (_a = allResults[0].metadata) == null ? void 0 : _a.source_table;
879
+ const bestMatchTable = (_a2 = allResults[0].metadata) == null ? void 0 : _a2.source_table;
880
880
  const finalSorted = allResults.filter((res) => {
881
- var _a2;
882
- return ((_a2 = res.metadata) == null ? void 0 : _a2.source_table) === bestMatchTable;
881
+ var _a3;
882
+ return ((_a3 = res.metadata) == null ? void 0 : _a3.source_table) === bestMatchTable;
883
883
  });
884
884
  console.log(`[MultiTablePostgresProvider] --- Search Complete ---`);
885
885
  console.log(`[MultiTablePostgresProvider] Final top match from "${bestMatchTable}" with score ${finalSorted[0].score.toFixed(4)}`);
@@ -1284,14 +1284,14 @@ var init_QdrantProvider = __esm({
1284
1284
  * Samples points from the collection to discover available payload fields.
1285
1285
  */
1286
1286
  async discoverSchema() {
1287
- var _a;
1287
+ var _a2;
1288
1288
  try {
1289
1289
  const { data } = await this.http.post(`/collections/${this.indexName}/points/scroll`, {
1290
1290
  limit: 20,
1291
1291
  with_payload: true,
1292
1292
  with_vector: false
1293
1293
  });
1294
- const points = ((_a = data.result) == null ? void 0 : _a.points) || [];
1294
+ const points = ((_a2 = data.result) == null ? void 0 : _a2.points) || [];
1295
1295
  const keys = /* @__PURE__ */ new Set();
1296
1296
  for (const point of points) {
1297
1297
  const payload = point.payload || {};
@@ -1317,12 +1317,12 @@ var init_QdrantProvider = __esm({
1317
1317
  * Ensures the collection exists. Creates it if missing.
1318
1318
  */
1319
1319
  async ensureCollection() {
1320
- var _a;
1320
+ var _a2;
1321
1321
  try {
1322
1322
  await this.http.get(`/collections/${this.indexName}`);
1323
1323
  console.log(`[QdrantProvider] \u2705 Collection "${this.indexName}" already exists.`);
1324
1324
  } catch (err) {
1325
- if (axios4.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
1325
+ if (axios4.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
1326
1326
  const opts = this.config.options;
1327
1327
  const dimensionsForCreate = opts.dimensions || 1536;
1328
1328
  console.log(`[QdrantProvider] \u23F3 Creating collection "${this.indexName}" (dimensions: ${dimensionsForCreate})...`);
@@ -1342,7 +1342,7 @@ var init_QdrantProvider = __esm({
1342
1342
  * Ensures that a payload field has an index.
1343
1343
  */
1344
1344
  async ensureIndex(fieldName, schema = "keyword") {
1345
- var _a;
1345
+ var _a2;
1346
1346
  let fullPath = fieldName;
1347
1347
  if (!this.isFlatPayload && !fieldName.includes(".") && fieldName !== "namespace" && fieldName !== this.contentField) {
1348
1348
  fullPath = `${this.metadataField}.${fieldName}`;
@@ -1355,7 +1355,7 @@ var init_QdrantProvider = __esm({
1355
1355
  console.log(`[QdrantProvider] \u2705 Ensured ${schema} index for "${fullPath}"`);
1356
1356
  } catch (err) {
1357
1357
  let status;
1358
- if (axios4.isAxiosError(err)) status = (_a = err.response) == null ? void 0 : _a.status;
1358
+ if (axios4.isAxiosError(err)) status = (_a2 = err.response) == null ? void 0 : _a2.status;
1359
1359
  if (status === 409) return;
1360
1360
  console.warn(`[QdrantProvider] \u26A0\uFE0F Could not ensure index for "${fullPath}":`, err instanceof Error ? err.message : String(err));
1361
1361
  }
@@ -1384,7 +1384,7 @@ var init_QdrantProvider = __esm({
1384
1384
  await this.http.put(`/collections/${this.indexName}/points`, payload);
1385
1385
  }
1386
1386
  async query(vector, topK, namespace, _filter) {
1387
- var _a;
1387
+ var _a2;
1388
1388
  const must = [];
1389
1389
  if (namespace) {
1390
1390
  must.push({ key: "namespace", match: { value: namespace } });
@@ -1406,7 +1406,7 @@ var init_QdrantProvider = __esm({
1406
1406
  limit: topK,
1407
1407
  with_payload: true,
1408
1408
  params: {
1409
- hnsw_ef: ((_a = this.config.options) == null ? void 0 : _a.efSearch) || Math.max(topK * 20, 128),
1409
+ hnsw_ef: ((_a2 = this.config.options) == null ? void 0 : _a2.efSearch) || Math.max(topK * 20, 128),
1410
1410
  exact: false
1411
1411
  },
1412
1412
  filter: must.length > 0 ? { must } : void 0
@@ -1501,13 +1501,13 @@ var init_ChromaDBProvider = __esm({
1501
1501
  * Get or create the ChromaDB collection.
1502
1502
  */
1503
1503
  async initialize() {
1504
- var _a;
1504
+ var _a2;
1505
1505
  try {
1506
1506
  const { data } = await this.http.get(`/api/v1/collections/${this.indexName}`);
1507
1507
  this.collectionId = data.id;
1508
1508
  console.log(`[ChromaDBProvider] \u2705 Collection "${this.indexName}" found (id: ${this.collectionId})`);
1509
1509
  } catch (err) {
1510
- if (axios5.isAxiosError(err) && ((_a = err.response) == null ? void 0 : _a.status) === 404) {
1510
+ if (axios5.isAxiosError(err) && ((_a2 = err.response) == null ? void 0 : _a2.status) === 404) {
1511
1511
  console.log(`[ChromaDBProvider] \u23F3 Collection "${this.indexName}" not found. Creating...`);
1512
1512
  const { data } = await this.http.post("/api/v1/collections", {
1513
1513
  name: this.indexName
@@ -1728,7 +1728,7 @@ var init_WeaviateProvider = __esm({
1728
1728
  await this.http.post("/v1/batch/objects", payload);
1729
1729
  }
1730
1730
  async query(vector, topK, namespace, _filter) {
1731
- var _a, _b;
1731
+ var _a2, _b;
1732
1732
  const queryText = _filter == null ? void 0 : _filter.queryText;
1733
1733
  const sanitizedFilter = this.sanitizeFilter(_filter);
1734
1734
  const searchParams = queryText ? `hybrid: { query: ${JSON.stringify(queryText)}, alpha: 0.5 }` : `nearVector: { vector: ${JSON.stringify(vector)} }`;
@@ -1754,7 +1754,7 @@ var init_WeaviateProvider = __esm({
1754
1754
  `
1755
1755
  };
1756
1756
  const { data } = await this.http.post("/v1/graphql", graphqlQuery);
1757
- const results = ((_b = (_a = data.data) == null ? void 0 : _a.Get) == null ? void 0 : _b[this.indexName]) || [];
1757
+ const results = ((_b = (_a2 = data.data) == null ? void 0 : _a2.Get) == null ? void 0 : _b[this.indexName]) || [];
1758
1758
  return results.map((res) => ({
1759
1759
  id: res["_additional"].id,
1760
1760
  score: 1 - res["_additional"].distance,
@@ -1807,10 +1807,10 @@ var init_WeaviateProvider = __esm({
1807
1807
  return `{ operator: And, operands: [${operands.join(", ")}] }`;
1808
1808
  }
1809
1809
  weaviateOperand(key, value) {
1810
- const path = `path: [${JSON.stringify(key)}], operator: Equal`;
1811
- if (typeof value === "number") return `{ ${path}, valueNumber: ${value} }`;
1812
- if (typeof value === "boolean") return `{ ${path}, valueBoolean: ${value} }`;
1813
- return `{ ${path}, valueString: ${JSON.stringify(value)} }`;
1810
+ const path2 = `path: [${JSON.stringify(key)}], operator: Equal`;
1811
+ if (typeof value === "number") return `{ ${path2}, valueNumber: ${value} }`;
1812
+ if (typeof value === "boolean") return `{ ${path2}, valueBoolean: ${value} }`;
1813
+ return `{ ${path2}, valueString: ${JSON.stringify(value)} }`;
1814
1814
  }
1815
1815
  };
1816
1816
  }
@@ -1837,21 +1837,21 @@ var init_UniversalVectorProvider = __esm({
1837
1837
  }
1838
1838
  }
1839
1839
  async initialize() {
1840
- var _a;
1840
+ var _a2;
1841
1841
  this.http = axios8.create({
1842
1842
  baseURL: this.opts.baseUrl,
1843
1843
  headers: __spreadValues({
1844
1844
  "Content-Type": "application/json"
1845
1845
  }, this.opts.headers),
1846
- timeout: (_a = this.opts.timeout) != null ? _a : 3e4
1846
+ timeout: (_a2 = this.opts.timeout) != null ? _a2 : 3e4
1847
1847
  });
1848
1848
  if (!await this.ping()) {
1849
1849
  throw new Error(`[UniversalVectorProvider] Failed to connect to ${this.opts.baseUrl}`);
1850
1850
  }
1851
1851
  }
1852
1852
  async upsert(doc, namespace) {
1853
- var _a, _b, _c;
1854
- const endpoint = (_a = this.opts.upsertEndpoint) != null ? _a : "/upsert";
1853
+ var _a2, _b, _c;
1854
+ const endpoint = (_a2 = this.opts.upsertEndpoint) != null ? _a2 : "/upsert";
1855
1855
  const template = (_b = this.opts.upsertTemplate) != null ? _b : JSON.stringify({
1856
1856
  id: "{{id}}",
1857
1857
  vector: "{{vector}}",
@@ -1884,8 +1884,8 @@ var init_UniversalVectorProvider = __esm({
1884
1884
  }
1885
1885
  }
1886
1886
  async query(vector, topK, namespace, filter) {
1887
- var _a, _b;
1888
- const endpoint = (_a = this.opts.queryEndpoint) != null ? _a : "/query";
1887
+ var _a2, _b;
1888
+ const endpoint = (_a2 = this.opts.queryEndpoint) != null ? _a2 : "/query";
1889
1889
  const template = (_b = this.opts.queryTemplate) != null ? _b : JSON.stringify({
1890
1890
  vector: "{{vector}}",
1891
1891
  limit: "{{topK}}",
@@ -1911,12 +1911,12 @@ var init_UniversalVectorProvider = __esm({
1911
1911
  );
1912
1912
  }
1913
1913
  return results.map((item) => {
1914
- var _a2, _b2, _c, _d, _e, _f, _g;
1914
+ var _a3, _b2, _c, _d, _e, _f, _g2;
1915
1915
  return {
1916
- id: item[(_a2 = this.opts.queryIdField) != null ? _a2 : "id"],
1916
+ id: item[(_a3 = this.opts.queryIdField) != null ? _a3 : "id"],
1917
1917
  score: (_c = item[(_b2 = this.opts.queryScoreField) != null ? _b2 : "score"]) != null ? _c : 0,
1918
1918
  content: (_e = item[(_d = this.opts.queryContentField) != null ? _d : "content"]) != null ? _e : "",
1919
- metadata: (_g = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g : {}
1919
+ metadata: (_g2 = item[(_f = this.opts.queryMetadataField) != null ? _f : "metadata"]) != null ? _g2 : {}
1920
1920
  };
1921
1921
  });
1922
1922
  } catch (error) {
@@ -1926,8 +1926,8 @@ var init_UniversalVectorProvider = __esm({
1926
1926
  }
1927
1927
  }
1928
1928
  async delete(id, namespace) {
1929
- var _a, _b;
1930
- const endpoint = (_a = this.opts.deleteEndpoint) != null ? _a : "/delete";
1929
+ var _a2, _b;
1930
+ const endpoint = (_a2 = this.opts.deleteEndpoint) != null ? _a2 : "/delete";
1931
1931
  const template = (_b = this.opts.deleteTemplate) != null ? _b : JSON.stringify({
1932
1932
  id: "{{id}}",
1933
1933
  namespace: "{{namespace}}"
@@ -1945,8 +1945,8 @@ var init_UniversalVectorProvider = __esm({
1945
1945
  }
1946
1946
  }
1947
1947
  async deleteNamespace(namespace) {
1948
- var _a;
1949
- const endpoint = (_a = this.opts.deleteNamespaceEndpoint) != null ? _a : "/delete-namespace";
1948
+ var _a2;
1949
+ const endpoint = (_a2 = this.opts.deleteNamespaceEndpoint) != null ? _a2 : "/delete-namespace";
1950
1950
  try {
1951
1951
  await this.http.post(endpoint, { namespace });
1952
1952
  } catch (error) {
@@ -1956,9 +1956,9 @@ var init_UniversalVectorProvider = __esm({
1956
1956
  }
1957
1957
  }
1958
1958
  async ping() {
1959
- var _a;
1959
+ var _a2;
1960
1960
  try {
1961
- const endpoint = (_a = this.opts.pingEndpoint) != null ? _a : "/health";
1961
+ const endpoint = (_a2 = this.opts.pingEndpoint) != null ? _a2 : "/health";
1962
1962
  const response = await this.http.get(endpoint, { timeout: 5e3 });
1963
1963
  return response.status >= 200 && response.status < 300;
1964
1964
  } catch (e) {
@@ -2069,6 +2069,8 @@ var LLM_PROVIDERS = [
2069
2069
  "anthropic",
2070
2070
  "ollama",
2071
2071
  "gemini",
2072
+ "groq",
2073
+ "qwen",
2072
2074
  "rest",
2073
2075
  "universal_rest",
2074
2076
  "custom"
@@ -2077,6 +2079,7 @@ var EMBEDDING_PROVIDERS = [
2077
2079
  "openai",
2078
2080
  "ollama",
2079
2081
  "gemini",
2082
+ "qwen",
2080
2083
  "rest",
2081
2084
  "universal_rest",
2082
2085
  "custom"
@@ -2085,6 +2088,7 @@ var PROVIDERS_WITH_EMBEDDINGS = [
2085
2088
  "openai",
2086
2089
  "ollama",
2087
2090
  "gemini",
2091
+ "qwen",
2088
2092
  "rest",
2089
2093
  "universal_rest"
2090
2094
  ];
@@ -2092,8 +2096,8 @@ var UI_BORDER_RADIUS_OPTIONS = ["none", "sm", "md", "lg", "xl", "full"];
2092
2096
 
2093
2097
  // src/config/serverConfig.ts
2094
2098
  function readString(env, name) {
2095
- var _a;
2096
- const value = (_a = env[name]) == null ? void 0 : _a.trim();
2099
+ var _a2;
2100
+ const value = (_a2 = env[name]) == null ? void 0 : _a2.trim();
2097
2101
  return value ? value : void 0;
2098
2102
  }
2099
2103
  function readNumber(env, name, fallback) {
@@ -2106,8 +2110,8 @@ function readNumber(env, name, fallback) {
2106
2110
  return parsed;
2107
2111
  }
2108
2112
  function readEnum(env, name, fallback, allowed) {
2109
- var _a;
2110
- const value = (_a = readString(env, name)) != null ? _a : fallback;
2113
+ var _a2;
2114
+ const value = (_a2 = readString(env, name)) != null ? _a2 : fallback;
2111
2115
  if (allowed.includes(value)) {
2112
2116
  return value;
2113
2117
  }
@@ -2117,15 +2121,15 @@ function getRagConfig(baseConfig, env = process.env) {
2117
2121
  return getEnvConfig(env, baseConfig);
2118
2122
  }
2119
2123
  function getEnvConfig(env = process.env, base) {
2120
- 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;
2121
- const projectId = (_c = (_b = (_a = readString(env, "RAG_PROJECT_ID")) != null ? _a : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : base == null ? void 0 : base.projectId) != null ? _c : "__default__";
2124
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z, _A, _B, _C, _D, _E, _F, _G, _H, _I, _J, _K, _L, _M, _N, _O, _P, _Q, _R, _S, _T, _U, _V, _W, _X, _Y, _Z, __, _$, _aa, _ba, _ca, _da, _ea, _fa, _ga, _ha, _ia, _ja, _ka, _la, _ma, _na, _oa, _pa, _qa, _ra, _sa, _ta, _ua, _va, _wa, _xa, _ya, _za, _Aa, _Ba, _Ca, _Da, _Ea, _Fa, _Ga, _Ha, _Ia, _Ja, _Ka, _La, _Ma, _Na, _Oa, _Pa, _Qa;
2125
+ const projectId = (_c = (_b = (_a2 = readString(env, "RAG_PROJECT_ID")) != null ? _a2 : readString(env, "NEXT_PUBLIC_PROJECT_ID")) != null ? _b : base == null ? void 0 : base.projectId) != null ? _c : "__default__";
2122
2126
  const vectorProvider = readEnum(env, "VECTOR_DB_PROVIDER", "pinecone", VECTOR_DB_PROVIDERS);
2123
2127
  const llmProvider = readEnum(env, "LLM_PROVIDER", "openai", LLM_PROVIDERS);
2124
2128
  const embeddingProvider = readEnum(env, "EMBEDDING_PROVIDER", "openai", EMBEDDING_PROVIDERS);
2125
2129
  const embeddingDimensions = readNumber(env, "EMBEDDING_DIMENSIONS", 1536);
2126
2130
  const vectorDbOptions = {};
2127
2131
  if (vectorProvider === "pinecone") {
2128
- vectorDbOptions.apiKey = (_g = (_f = readString(env, "PINECONE_API_KEY")) != null ? _f : (_e = (_d = base == null ? void 0 : base.vectorDb) == null ? void 0 : _d.options) == null ? void 0 : _e.apiKey) != null ? _g : "";
2132
+ vectorDbOptions.apiKey = (_g2 = (_f = readString(env, "PINECONE_API_KEY")) != null ? _f : (_e = (_d = base == null ? void 0 : base.vectorDb) == null ? void 0 : _d.options) == null ? void 0 : _e.apiKey) != null ? _g2 : "";
2129
2133
  vectorDbOptions.indexName = (_l = (_i = readString(env, "PINECONE_INDEX")) != null ? _i : (_h = base == null ? void 0 : base.vectorDb) == null ? void 0 : _h.indexName) != null ? _l : (_k = (_j = base == null ? void 0 : base.vectorDb) == null ? void 0 : _j.options) == null ? void 0 : _k.indexName;
2130
2134
  } else if (vectorProvider === "pgvector" || vectorProvider === "postgresql") {
2131
2135
  vectorDbOptions.connectionString = (_q = (_p = (_m = readString(env, "PGVECTOR_CONNECTION_STRING")) != null ? _m : readString(env, "POSTGRES_URL")) != null ? _p : (_o = (_n = base == null ? void 0 : base.vectorDb) == null ? void 0 : _n.options) == null ? void 0 : _o.connectionString) != null ? _q : "";
@@ -2187,17 +2191,18 @@ function getEnvConfig(env = process.env, base) {
2187
2191
  rest: "default",
2188
2192
  custom: "default"
2189
2193
  };
2190
- return __spreadValues({
2194
+ return __spreadProps(__spreadValues({
2191
2195
  projectId,
2196
+ licenseKey: (_ha = (_ga = readString(env, "RETRIVORA_LICENSE_KEY")) != null ? _ga : readString(env, "LICENSE_KEY")) != null ? _ha : base == null ? void 0 : base.licenseKey,
2192
2197
  vectorDb: {
2193
2198
  provider: vectorProvider,
2194
- indexName: (_ha = (_ga = readString(env, "VECTOR_DB_INDEX")) != null ? _ga : vectorDbOptions.indexName) != null ? _ha : "rag-index",
2199
+ indexName: (_ja = (_ia = readString(env, "VECTOR_DB_INDEX")) != null ? _ia : vectorDbOptions.indexName) != null ? _ja : "rag-index",
2195
2200
  options: vectorDbOptions
2196
2201
  },
2197
2202
  llm: {
2198
2203
  provider: llmProvider,
2199
- model: (_ja = (_ia = readString(env, "LLM_MODEL")) != null ? _ia : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _ja : "gpt-4o",
2200
- apiKey: (_ka = llmApiKeyByProvider[llmProvider]) != null ? _ka : "",
2204
+ model: (_la = (_ka = readString(env, "LLM_MODEL")) != null ? _ka : DEFAULT_MODEL_BY_PROVIDER[llmProvider]) != null ? _la : "gpt-4o",
2205
+ apiKey: (_ma = llmApiKeyByProvider[llmProvider]) != null ? _ma : "",
2201
2206
  baseUrl: readString(env, "LLM_BASE_URL"),
2202
2207
  systemPrompt: readString(env, "LLM_SYSTEM_PROMPT"),
2203
2208
  maxTokens: readNumber(env, "LLM_MAX_TOKENS", 4096),
@@ -2210,7 +2215,7 @@ function getEnvConfig(env = process.env, base) {
2210
2215
  },
2211
2216
  embedding: {
2212
2217
  provider: embeddingProvider,
2213
- model: (_la = readString(env, "EMBEDDING_MODEL")) != null ? _la : "text-embedding-3-small",
2218
+ model: (_na = readString(env, "EMBEDDING_MODEL")) != null ? _na : "text-embedding-3-small",
2214
2219
  apiKey: embeddingApiKeyByProvider[embeddingProvider],
2215
2220
  baseUrl: readString(env, "EMBEDDING_BASE_URL"),
2216
2221
  dimensions: embeddingDimensions,
@@ -2221,30 +2226,30 @@ function getEnvConfig(env = process.env, base) {
2221
2226
  }
2222
2227
  },
2223
2228
  ui: {
2224
- title: (_na = (_ma = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _ma : readString(env, "UI_TITLE")) != null ? _na : "AI Assistant",
2225
- subtitle: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _oa : readString(env, "UI_SUBTITLE")) != null ? _pa : "Powered by RAG",
2226
- primaryColor: (_ra = (_qa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _qa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ra : "#10b981",
2227
- accentColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _sa : readString(env, "UI_ACCENT_COLOR")) != null ? _ta : "#3b82f6",
2228
- logoUrl: (_ua = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _ua : readString(env, "UI_LOGO_URL"),
2229
- placeholder: (_wa = (_va = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _va : readString(env, "UI_PLACEHOLDER")) != null ? _wa : "Ask me anything\u2026",
2230
- showSources: ((_ya = (_xa = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _xa : readString(env, "UI_SHOW_SOURCES")) != null ? _ya : "true") !== "false",
2231
- 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.",
2232
- visualStyle: (_Ca = (_Ba = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Ba : readString(env, "UI_VISUAL_STYLE")) != null ? _Ca : "glass",
2233
- borderRadius: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Da : readString(env, "UI_BORDER_RADIUS")) != null ? _Ea : "xl",
2234
- allowUpload: ((_Ga = (_Fa = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Fa : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ga : "false") === "true"
2229
+ title: (_pa = (_oa = readString(env, "NEXT_PUBLIC_UI_TITLE")) != null ? _oa : readString(env, "UI_TITLE")) != null ? _pa : "AI Assistant",
2230
+ subtitle: (_ra = (_qa = readString(env, "NEXT_PUBLIC_UI_SUBTITLE")) != null ? _qa : readString(env, "UI_SUBTITLE")) != null ? _ra : "Powered by RAG",
2231
+ primaryColor: (_ta = (_sa = readString(env, "NEXT_PUBLIC_PRIMARY_COLOR")) != null ? _sa : readString(env, "UI_PRIMARY_COLOR")) != null ? _ta : "#10b981",
2232
+ accentColor: (_va = (_ua = readString(env, "NEXT_PUBLIC_ACCENT_COLOR")) != null ? _ua : readString(env, "UI_ACCENT_COLOR")) != null ? _va : "#3b82f6",
2233
+ logoUrl: (_wa = readString(env, "NEXT_PUBLIC_LOGO_URL")) != null ? _wa : readString(env, "UI_LOGO_URL"),
2234
+ placeholder: (_ya = (_xa = readString(env, "NEXT_PUBLIC_PLACEHOLDER")) != null ? _xa : readString(env, "UI_PLACEHOLDER")) != null ? _ya : "Ask me anything\u2026",
2235
+ showSources: ((_Aa = (_za = readString(env, "NEXT_PUBLIC_SHOW_SOURCES")) != null ? _za : readString(env, "UI_SHOW_SOURCES")) != null ? _Aa : "true") !== "false",
2236
+ welcomeMessage: (_Ca = (_Ba = readString(env, "NEXT_PUBLIC_WELCOME_MESSAGE")) != null ? _Ba : readString(env, "UI_WELCOME_MESSAGE")) != null ? _Ca : "Hello! I'm your AI assistant. Ask me anything about your documents.",
2237
+ visualStyle: (_Ea = (_Da = readString(env, "NEXT_PUBLIC_UI_VISUAL_STYLE")) != null ? _Da : readString(env, "UI_VISUAL_STYLE")) != null ? _Ea : "glass",
2238
+ borderRadius: (_Ga = (_Fa = readString(env, "NEXT_PUBLIC_UI_BORDER_RADIUS")) != null ? _Fa : readString(env, "UI_BORDER_RADIUS")) != null ? _Ga : "xl",
2239
+ allowUpload: ((_Ia = (_Ha = readString(env, "NEXT_PUBLIC_ALLOW_UPLOAD")) != null ? _Ha : readString(env, "UI_ALLOW_UPLOAD")) != null ? _Ia : "false") === "true"
2235
2240
  },
2236
2241
  rag: {
2237
2242
  topK: readNumber(env, "RAG_TOP_K", 5),
2238
2243
  scoreThreshold: readNumber(env, "RAG_SCORE_THRESHOLD", 0),
2239
2244
  chunkSize: readNumber(env, "RAG_CHUNK_SIZE", 1e3),
2240
2245
  chunkOverlap: readNumber(env, "RAG_CHUNK_OVERLAP", 200),
2241
- filterableFields: (_Ha = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ha.split(",").map((f) => f.trim()),
2246
+ filterableFields: (_Ja = readString(env, "RAG_FILTERABLE_FIELDS")) == null ? void 0 : _Ja.split(",").map((f) => f.trim()),
2242
2247
  // Query pipeline toggles — read from .env.local
2243
2248
  useQueryTransformation: readString(env, "RAG_USE_QUERY_TRANSFORMATION") === "true",
2244
2249
  useReranking: readString(env, "RAG_USE_RERANKING") === "true",
2245
2250
  useGraphRetrieval: readString(env, "RAG_USE_GRAPH_RETRIEVAL") === "true",
2246
- architecture: (_Ia = readString(env, "RAG_ARCHITECTURE")) != null ? _Ia : "simple",
2247
- chunkingStrategy: (_Ja = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _Ja : "recursive",
2251
+ architecture: (_Ka = readString(env, "RAG_ARCHITECTURE")) != null ? _Ka : "simple",
2252
+ chunkingStrategy: (_La = readString(env, "RAG_CHUNKING_STRATEGY")) != null ? _La : "recursive",
2248
2253
  uiMapping: (() => {
2249
2254
  const raw = readString(env, "RAG_UI_MAPPING");
2250
2255
  if (!raw) return void 0;
@@ -2254,6 +2259,10 @@ function getEnvConfig(env = process.env, base) {
2254
2259
  return void 0;
2255
2260
  }
2256
2261
  })()
2262
+ },
2263
+ telemetry: {
2264
+ enabled: readString(env, "TELEMETRY_ENABLED") === "true" || readString(env, "NEXT_PUBLIC_TELEMETRY_ENABLED") === "true" || ((_Ma = base == null ? void 0 : base.telemetry) == null ? void 0 : _Ma.enabled) || false,
2265
+ url: (_Qa = (_Pa = (_Na = readString(env, "TELEMETRY_URL")) != null ? _Na : readString(env, "NEXT_PUBLIC_TELEMETRY_URL")) != null ? _Pa : (_Oa = base == null ? void 0 : base.telemetry) == null ? void 0 : _Oa.url) != null ? _Qa : "/api/telemetry"
2257
2266
  }
2258
2267
  }, readString(env, "GRAPH_DB_PROVIDER") ? {
2259
2268
  graphDb: {
@@ -2264,7 +2273,19 @@ function getEnvConfig(env = process.env, base) {
2264
2273
  password: readString(env, "GRAPH_DB_PASSWORD")
2265
2274
  }
2266
2275
  }
2267
- } : {});
2276
+ } : {}), {
2277
+ mcpServers: (() => {
2278
+ var _a3;
2279
+ const raw = (_a3 = readString(env, "MCP_SERVERS")) != null ? _a3 : readString(env, "NEXT_PUBLIC_MCP_SERVERS");
2280
+ if (!raw) return void 0;
2281
+ try {
2282
+ return JSON.parse(raw);
2283
+ } catch (e) {
2284
+ console.warn("[serverConfig] Failed to parse MCP_SERVERS env:", e);
2285
+ return void 0;
2286
+ }
2287
+ })()
2288
+ });
2268
2289
  }
2269
2290
 
2270
2291
  // src/core/ConfigResolver.ts
@@ -2290,7 +2311,8 @@ var ConfigResolver = class {
2290
2311
  options: __spreadValues(__spreadValues({}, envConfig.embedding.options || {}), hostConfig.embedding.options || {})
2291
2312
  }) : envConfig.embedding,
2292
2313
  ui: hostConfig.ui ? mergeDefined(envConfig.ui, hostConfig.ui) : envConfig.ui,
2293
- rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag
2314
+ rag: hostConfig.rag ? __spreadValues(__spreadValues({}, envConfig.rag), hostConfig.rag) : envConfig.rag,
2315
+ telemetry: hostConfig.telemetry ? __spreadValues(__spreadValues({}, envConfig.telemetry), hostConfig.telemetry) : envConfig.telemetry
2294
2316
  });
2295
2317
  }
2296
2318
  /**
@@ -2299,10 +2321,10 @@ var ConfigResolver = class {
2299
2321
  * fallback behavior.
2300
2322
  */
2301
2323
  static resolveUniversal(hostConfig, env = process.env) {
2302
- var _a;
2324
+ var _a2;
2303
2325
  if (!hostConfig) return this.resolve(void 0, env);
2304
2326
  const normalized = __spreadProps(__spreadValues({}, hostConfig), {
2305
- vectorDb: (_a = hostConfig.vectorDb) != null ? _a : hostConfig.vectorDatabase,
2327
+ vectorDb: (_a2 = hostConfig.vectorDb) != null ? _a2 : hostConfig.vectorDatabase,
2306
2328
  rag: this.mergeRetrievalWorkflow(hostConfig.rag, hostConfig.retrieval, hostConfig.workflow)
2307
2329
  });
2308
2330
  return this.resolve(normalized, env);
@@ -2322,11 +2344,11 @@ var ConfigResolver = class {
2322
2344
  }
2323
2345
  }
2324
2346
  static mergeRetrievalWorkflow(rag, retrieval, workflow) {
2325
- var _a, _b, _c, _d, _e;
2347
+ var _a2, _b, _c, _d, _e;
2326
2348
  if (!rag && !retrieval && !workflow) return void 0;
2327
2349
  const normalized = __spreadValues({}, rag != null ? rag : {});
2328
2350
  if (retrieval) {
2329
- normalized.topK = (_a = retrieval.topK) != null ? _a : normalized.topK;
2351
+ normalized.topK = (_a2 = retrieval.topK) != null ? _a2 : normalized.topK;
2330
2352
  normalized.scoreThreshold = (_b = retrieval.scoreThreshold) != null ? _b : normalized.scoreThreshold;
2331
2353
  normalized.useReranking = (_c = retrieval.useReranking) != null ? _c : normalized.useReranking;
2332
2354
  if (retrieval.strategy === "hybrid") normalized.architecture = (_d = normalized.architecture) != null ? _d : "hybrid";
@@ -2408,8 +2430,8 @@ var OpenAIProvider = class {
2408
2430
  const apiKey = config.apiKey;
2409
2431
  const modelName = config.model;
2410
2432
  try {
2411
- const OpenAI2 = await import("openai");
2412
- const client = new OpenAI2.default({ apiKey });
2433
+ const OpenAI4 = await import("openai");
2434
+ const client = new OpenAI4.default({ apiKey });
2413
2435
  const models = await client.models.list();
2414
2436
  const hasModel = models.data.some((m) => m.id === modelName);
2415
2437
  return {
@@ -2430,8 +2452,8 @@ var OpenAIProvider = class {
2430
2452
  };
2431
2453
  }
2432
2454
  async chat(messages, context, options) {
2433
- var _a, _b, _c, _d, _e, _f, _g, _h, _i;
2434
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
2455
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
2456
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
2435
2457
  const systemMessage = {
2436
2458
  role: "system",
2437
2459
  content: buildSystemContent(basePrompt, context)
@@ -2450,12 +2472,12 @@ var OpenAIProvider = class {
2450
2472
  temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
2451
2473
  stop: options == null ? void 0 : options.stop
2452
2474
  });
2453
- return (_i = (_h = (_g = completion.choices[0]) == null ? void 0 : _g.message) == null ? void 0 : _h.content) != null ? _i : "";
2475
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
2454
2476
  }
2455
2477
  chatStream(messages, context, options) {
2456
2478
  return __asyncGenerator(this, null, function* () {
2457
- var _a, _b, _c, _d, _e, _f, _g, _h;
2458
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
2479
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
2480
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
2459
2481
  const systemMessage = {
2460
2482
  role: "system",
2461
2483
  content: buildSystemContent(basePrompt, context)
@@ -2481,7 +2503,7 @@ var OpenAIProvider = class {
2481
2503
  try {
2482
2504
  for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
2483
2505
  const chunk = temp.value;
2484
- const content = ((_h = (_g = chunk.choices[0]) == null ? void 0 : _g.delta) == null ? void 0 : _h.content) || "";
2506
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
2485
2507
  if (content) yield content;
2486
2508
  }
2487
2509
  } catch (temp) {
@@ -2501,8 +2523,8 @@ var OpenAIProvider = class {
2501
2523
  return results[0];
2502
2524
  }
2503
2525
  async batchEmbed(texts, options) {
2504
- var _a, _b, _c, _d, _e;
2505
- const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "text-embedding-3-small";
2526
+ var _a2, _b, _c, _d, _e;
2527
+ const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _c : "text-embedding-3-small";
2506
2528
  const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
2507
2529
  const client = apiKey !== this.llmConfig.apiKey ? new OpenAI({ apiKey }) : this.client;
2508
2530
  const response = await client.embeddings.create({ model, input: texts });
@@ -2579,8 +2601,8 @@ var AnthropicProvider = class {
2579
2601
  };
2580
2602
  }
2581
2603
  async chat(messages, context, options) {
2582
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2583
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
2604
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2605
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
2584
2606
  const system = buildSystemContent(basePrompt, context);
2585
2607
  const anthropicMessages = messages.map((m) => ({
2586
2608
  role: m.role === "assistant" ? "assistant" : "user",
@@ -2591,7 +2613,7 @@ var AnthropicProvider = class {
2591
2613
  const extraParams = {};
2592
2614
  if (isThinkingEnabled && isClaude37) {
2593
2615
  extraParams.betas = ["interleaved-thinking-2025-05-14"];
2594
- const maxTokens = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
2616
+ const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
2595
2617
  const budget = Math.min(
2596
2618
  typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
2597
2619
  maxTokens - 1
@@ -2618,8 +2640,8 @@ var AnthropicProvider = class {
2618
2640
  }
2619
2641
  chatStream(messages, context, options) {
2620
2642
  return __asyncGenerator(this, null, function* () {
2621
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2622
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
2643
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2644
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the context below to answer the user's question accurately.";
2623
2645
  const system = buildSystemContent(basePrompt, context);
2624
2646
  const anthropicMessages = messages.map((m) => ({
2625
2647
  role: m.role === "assistant" ? "assistant" : "user",
@@ -2630,7 +2652,7 @@ var AnthropicProvider = class {
2630
2652
  const extraParams = {};
2631
2653
  if (isThinkingEnabled && isClaude37) {
2632
2654
  extraParams.betas = ["interleaved-thinking-2025-05-14"];
2633
- const maxTokens = (_g = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g : 4096;
2655
+ const maxTokens = (_g2 = (_f = options == null ? void 0 : options.maxTokens) != null ? _f : this.llmConfig.maxTokens) != null ? _g2 : 4096;
2634
2656
  const budget = Math.min(
2635
2657
  typeof ((_h = this.llmConfig.options) == null ? void 0 : _h.thinkingBudget) === "number" ? (_i = this.llmConfig.options) == null ? void 0 : _i.thinkingBudget : 2048,
2636
2658
  maxTokens - 1
@@ -2703,8 +2725,8 @@ var AnthropicProvider = class {
2703
2725
  import axios from "axios";
2704
2726
  var OllamaProvider = class {
2705
2727
  constructor(llmConfig, embeddingConfig) {
2706
- var _a, _b;
2707
- const baseURL = (_a = llmConfig.baseUrl) != null ? _a : "http://localhost:11434";
2728
+ var _a2, _b;
2729
+ const baseURL = (_a2 = llmConfig.baseUrl) != null ? _a2 : "http://localhost:11434";
2708
2730
  const timeout = Number((_b = llmConfig.options) == null ? void 0 : _b.timeout) || 3e5;
2709
2731
  this.http = axios.create({ baseURL, timeout });
2710
2732
  this.llmConfig = llmConfig;
@@ -2762,8 +2784,8 @@ var OllamaProvider = class {
2762
2784
  };
2763
2785
  }
2764
2786
  async chat(messages, context, options) {
2765
- var _a, _b, _c, _d, _e, _f;
2766
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
2787
+ var _a2, _b, _c, _d, _e, _f;
2788
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
2767
2789
  const system = buildSystemContent(basePrompt, context);
2768
2790
  const { data } = await this.http.post("/api/chat", {
2769
2791
  model: this.llmConfig.model,
@@ -2781,8 +2803,8 @@ var OllamaProvider = class {
2781
2803
  }
2782
2804
  chatStream(messages, context, options) {
2783
2805
  return __asyncGenerator(this, null, function* () {
2784
- var _a, _b, _c, _d, _e, _f, _g, _h;
2785
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
2806
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
2807
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Use the provided context to answer the user's question.";
2786
2808
  const system = buildSystemContent(basePrompt, context);
2787
2809
  const response = yield new __await(this.http.post("/api/chat", {
2788
2810
  model: this.llmConfig.model,
@@ -2811,7 +2833,7 @@ var OllamaProvider = class {
2811
2833
  if (!line.trim()) continue;
2812
2834
  try {
2813
2835
  const json = JSON.parse(line);
2814
- if ((_g = json.message) == null ? void 0 : _g.content) {
2836
+ if ((_g2 = json.message) == null ? void 0 : _g2.content) {
2815
2837
  yield json.message.content;
2816
2838
  }
2817
2839
  if (json.done) return;
@@ -2840,10 +2862,10 @@ var OllamaProvider = class {
2840
2862
  });
2841
2863
  }
2842
2864
  async embed(text, options) {
2843
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k;
2844
- const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _c : "nomic-embed-text";
2865
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k;
2866
+ const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _c : "nomic-embed-text";
2845
2867
  const baseURL = (_f = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.baseUrl) != null ? _e : this.llmConfig.baseUrl) != null ? _f : "http://localhost:11434";
2846
- const client = baseURL !== ((_g = this.llmConfig.baseUrl) != null ? _g : "http://localhost:11434") ? axios.create({ baseURL, timeout: 6e4 }) : this.http;
2868
+ const client = baseURL !== ((_g2 = this.llmConfig.baseUrl) != null ? _g2 : "http://localhost:11434") ? axios.create({ baseURL, timeout: 6e4 }) : this.http;
2847
2869
  let prompt = text;
2848
2870
  const queryPrefix = (_i = (_h = this.embeddingConfig) == null ? void 0 : _h.queryPrefix) != null ? _i : model.includes("nomic") ? "search_query: " : "";
2849
2871
  const docPrefix = (_k = (_j = this.embeddingConfig) == null ? void 0 : _j.documentPrefix) != null ? _k : model.includes("nomic") ? "search_document: " : "";
@@ -2942,9 +2964,9 @@ var GeminiProvider = class {
2942
2964
  static getHealthChecker() {
2943
2965
  return {
2944
2966
  async check(config) {
2945
- var _a, _b;
2967
+ var _a2, _b;
2946
2968
  const timestamp = Date.now();
2947
- const apiKey = (_b = (_a = config.apiKey) != null ? _a : process.env.GOOGLE_GENAI_API_KEY) != null ? _b : "";
2969
+ const apiKey = (_b = (_a2 = config.apiKey) != null ? _a2 : process.env.GOOGLE_GENAI_API_KEY) != null ? _b : "";
2948
2970
  const modelName = sanitizeModel(config.model);
2949
2971
  try {
2950
2972
  const { GoogleGenerativeAI: GoogleGenerativeAI2 } = await import("@google/generative-ai");
@@ -2974,16 +2996,16 @@ var GeminiProvider = class {
2974
2996
  /** Resolve the embedding client — uses a separate client when the embedding
2975
2997
  * API key differs from the LLM API key. */
2976
2998
  get embeddingClient() {
2977
- var _a;
2978
- if (((_a = this.embeddingConfig) == null ? void 0 : _a.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
2999
+ var _a2;
3000
+ if (((_a2 = this.embeddingConfig) == null ? void 0 : _a2.apiKey) && this.embeddingConfig.apiKey !== this.llmConfig.apiKey) {
2979
3001
  return buildClient(this.embeddingConfig.apiKey);
2980
3002
  }
2981
3003
  return this.client;
2982
3004
  }
2983
3005
  /** Resolve the embedding model to use, in order of specificity. */
2984
3006
  resolveEmbeddingModel(optionsModel) {
2985
- var _a, _b;
2986
- return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a = this.embeddingConfig) == null ? void 0 : _a.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
3007
+ var _a2, _b;
3008
+ return sanitizeModel((_b = optionsModel != null ? optionsModel : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _b : DEFAULT_EMBEDDING_MODEL);
2987
3009
  }
2988
3010
  /**
2989
3011
  * Convert ChatMessage[] to the Gemini contents format.
@@ -3003,8 +3025,8 @@ var GeminiProvider = class {
3003
3025
  // ILLMProvider — chat
3004
3026
  // -------------------------------------------------------------------------
3005
3027
  async chat(messages, context, options) {
3006
- var _a, _b, _c, _d, _e, _f;
3007
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3028
+ var _a2, _b, _c, _d, _e, _f;
3029
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3008
3030
  const model = this.client.getGenerativeModel({
3009
3031
  model: this.llmConfig.model,
3010
3032
  systemInstruction: buildSystemContent(basePrompt, context)
@@ -3021,8 +3043,8 @@ var GeminiProvider = class {
3021
3043
  }
3022
3044
  chatStream(messages, context, options) {
3023
3045
  return __asyncGenerator(this, null, function* () {
3024
- var _a, _b, _c, _d, _e, _f;
3025
- const basePrompt = (_b = (_a = options == null ? void 0 : options.systemPrompt) != null ? _a : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3046
+ var _a2, _b, _c, _d, _e, _f;
3047
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3026
3048
  const model = this.client.getGenerativeModel({
3027
3049
  model: this.llmConfig.model,
3028
3050
  systemInstruction: buildSystemContent(basePrompt, context)
@@ -3057,11 +3079,11 @@ var GeminiProvider = class {
3057
3079
  // ILLMProvider — embeddings
3058
3080
  // -------------------------------------------------------------------------
3059
3081
  async embed(text, options) {
3060
- var _a, _b;
3082
+ var _a2, _b;
3061
3083
  const content = applyPrefix(
3062
3084
  text,
3063
3085
  options == null ? void 0 : options.taskType,
3064
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
3086
+ (_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
3065
3087
  (_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
3066
3088
  );
3067
3089
  const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
@@ -3078,7 +3100,7 @@ var GeminiProvider = class {
3078
3100
  const modelName = this.resolveEmbeddingModel(options == null ? void 0 : options.model);
3079
3101
  const model = this.embeddingClient.getGenerativeModel({ model: modelName });
3080
3102
  const requests = texts.map((text) => {
3081
- var _a, _b;
3103
+ var _a2, _b;
3082
3104
  return {
3083
3105
  content: {
3084
3106
  role: "user",
@@ -3086,7 +3108,7 @@ var GeminiProvider = class {
3086
3108
  text: applyPrefix(
3087
3109
  text,
3088
3110
  options == null ? void 0 : options.taskType,
3089
- (_a = this.embeddingConfig) == null ? void 0 : _a.queryPrefix,
3111
+ (_a2 = this.embeddingConfig) == null ? void 0 : _a2.queryPrefix,
3090
3112
  (_b = this.embeddingConfig) == null ? void 0 : _b.documentPrefix
3091
3113
  )
3092
3114
  }]
@@ -3103,8 +3125,8 @@ var GeminiProvider = class {
3103
3125
  throw err;
3104
3126
  });
3105
3127
  return response.embeddings.map((e) => {
3106
- var _a;
3107
- return (_a = e.values) != null ? _a : [];
3128
+ var _a2;
3129
+ return (_a2 = e.values) != null ? _a2 : [];
3108
3130
  });
3109
3131
  }
3110
3132
  // -------------------------------------------------------------------------
@@ -3124,6 +3146,325 @@ var GeminiProvider = class {
3124
3146
  }
3125
3147
  };
3126
3148
 
3149
+ // src/llm/providers/GroqProvider.ts
3150
+ import OpenAI2 from "openai";
3151
+ var GroqProvider = class {
3152
+ constructor(llmConfig, embeddingConfig) {
3153
+ void embeddingConfig;
3154
+ const apiKey = llmConfig.apiKey || process.env.GROQ_API_KEY;
3155
+ if (!apiKey) throw new Error("[GroqProvider] llmConfig.apiKey or GROQ_API_KEY environment variable is required");
3156
+ this.client = new OpenAI2({
3157
+ apiKey,
3158
+ baseURL: llmConfig.baseUrl || "https://api.groq.com/openai/v1"
3159
+ });
3160
+ this.llmConfig = llmConfig;
3161
+ }
3162
+ static getValidator() {
3163
+ return {
3164
+ validate(config) {
3165
+ const errors = [];
3166
+ if (!config.apiKey && !process.env.GROQ_API_KEY) {
3167
+ errors.push({
3168
+ field: "llm.apiKey",
3169
+ message: "Groq API key is required",
3170
+ suggestion: "Set GROQ_API_KEY environment variable",
3171
+ severity: "error"
3172
+ });
3173
+ }
3174
+ if (!config.model) {
3175
+ errors.push({
3176
+ field: "llm.model",
3177
+ message: "Groq model name is required",
3178
+ suggestion: 'e.g., "llama-3.3-70b-versatile"',
3179
+ severity: "error"
3180
+ });
3181
+ }
3182
+ return errors;
3183
+ }
3184
+ };
3185
+ }
3186
+ static getHealthChecker() {
3187
+ return {
3188
+ async check(config) {
3189
+ const timestamp = Date.now();
3190
+ const apiKey = config.apiKey || process.env.GROQ_API_KEY || "";
3191
+ const modelName = config.model;
3192
+ try {
3193
+ const OpenAI4 = await import("openai");
3194
+ const client = new OpenAI4.default({
3195
+ apiKey,
3196
+ baseURL: config.baseUrl || "https://api.groq.com/openai/v1"
3197
+ });
3198
+ const models = await client.models.list();
3199
+ const hasModel = models.data.some((m) => m.id === modelName);
3200
+ return {
3201
+ healthy: true,
3202
+ provider: "groq",
3203
+ capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
3204
+ timestamp
3205
+ };
3206
+ } catch (error) {
3207
+ return {
3208
+ healthy: false,
3209
+ provider: "groq",
3210
+ error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
3211
+ timestamp
3212
+ };
3213
+ }
3214
+ }
3215
+ };
3216
+ }
3217
+ async chat(messages, context, options) {
3218
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
3219
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3220
+ const systemMessage = {
3221
+ role: "system",
3222
+ content: buildSystemContent(basePrompt, context)
3223
+ };
3224
+ const formattedMessages = [
3225
+ systemMessage,
3226
+ ...messages.map((m) => ({
3227
+ role: m.role,
3228
+ content: m.content
3229
+ }))
3230
+ ];
3231
+ const completion = await this.client.chat.completions.create({
3232
+ model: this.llmConfig.model,
3233
+ messages: formattedMessages,
3234
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3235
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3236
+ stop: options == null ? void 0 : options.stop
3237
+ });
3238
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
3239
+ }
3240
+ chatStream(messages, context, options) {
3241
+ return __asyncGenerator(this, null, function* () {
3242
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3243
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3244
+ const systemMessage = {
3245
+ role: "system",
3246
+ content: buildSystemContent(basePrompt, context)
3247
+ };
3248
+ const formattedMessages = [
3249
+ systemMessage,
3250
+ ...messages.map((m) => ({
3251
+ role: m.role,
3252
+ content: m.content
3253
+ }))
3254
+ ];
3255
+ const stream = yield new __await(this.client.chat.completions.create({
3256
+ model: this.llmConfig.model,
3257
+ messages: formattedMessages,
3258
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3259
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3260
+ stop: options == null ? void 0 : options.stop,
3261
+ stream: true
3262
+ }));
3263
+ if (!stream) {
3264
+ throw new Error("[GroqProvider] completions.create stream is undefined");
3265
+ }
3266
+ try {
3267
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
3268
+ const chunk = temp.value;
3269
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
3270
+ if (content) yield content;
3271
+ }
3272
+ } catch (temp) {
3273
+ error = [temp];
3274
+ } finally {
3275
+ try {
3276
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
3277
+ } finally {
3278
+ if (error)
3279
+ throw error[0];
3280
+ }
3281
+ }
3282
+ });
3283
+ }
3284
+ async embed(text, options) {
3285
+ void text;
3286
+ void options;
3287
+ throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
3288
+ }
3289
+ async batchEmbed(texts, options) {
3290
+ void texts;
3291
+ void options;
3292
+ throw new Error('[GroqProvider] Groq does not provide a native embedding API. Please configure "openai" or "gemini" for embeddings in RagConfig.');
3293
+ }
3294
+ async ping() {
3295
+ try {
3296
+ await this.client.models.list();
3297
+ return true;
3298
+ } catch (err) {
3299
+ console.error("[GroqProvider] Ping failed:", err);
3300
+ return false;
3301
+ }
3302
+ }
3303
+ };
3304
+
3305
+ // src/llm/providers/QwenProvider.ts
3306
+ import OpenAI3 from "openai";
3307
+ var QwenProvider = class {
3308
+ constructor(llmConfig, embeddingConfig) {
3309
+ const apiKey = llmConfig.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY;
3310
+ if (!apiKey) throw new Error("[QwenProvider] llmConfig.apiKey, DASHSCOPE_API_KEY, or QWEN_API_KEY environment variable is required");
3311
+ this.client = new OpenAI3({
3312
+ apiKey,
3313
+ baseURL: llmConfig.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3314
+ });
3315
+ this.llmConfig = llmConfig;
3316
+ this.embeddingConfig = embeddingConfig;
3317
+ }
3318
+ static getValidator() {
3319
+ return {
3320
+ validate(config) {
3321
+ const errors = [];
3322
+ const isEmbedding = config.provider === "qwen" && "dimensions" in config;
3323
+ const prefix = isEmbedding ? "embedding" : "llm";
3324
+ if (!config.apiKey && !process.env.DASHSCOPE_API_KEY && !process.env.QWEN_API_KEY) {
3325
+ errors.push({
3326
+ field: `${prefix}.apiKey`,
3327
+ message: "Qwen API key is required",
3328
+ suggestion: "Set DASHSCOPE_API_KEY or QWEN_API_KEY environment variable",
3329
+ severity: "error"
3330
+ });
3331
+ }
3332
+ if (!config.model) {
3333
+ errors.push({
3334
+ field: `${prefix}.model`,
3335
+ message: "Qwen model name is required",
3336
+ suggestion: isEmbedding ? 'e.g., "text-embedding-v3"' : 'e.g., "qwen-plus" or "qwen-max"',
3337
+ severity: "error"
3338
+ });
3339
+ }
3340
+ return errors;
3341
+ }
3342
+ };
3343
+ }
3344
+ static getHealthChecker() {
3345
+ return {
3346
+ async check(config) {
3347
+ const timestamp = Date.now();
3348
+ const apiKey = config.apiKey || process.env.DASHSCOPE_API_KEY || process.env.QWEN_API_KEY || "";
3349
+ const modelName = config.model;
3350
+ try {
3351
+ const OpenAI4 = await import("openai");
3352
+ const client = new OpenAI4.default({
3353
+ apiKey,
3354
+ baseURL: config.baseUrl || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3355
+ });
3356
+ const models = await client.models.list();
3357
+ const hasModel = models.data.some((m) => m.id === modelName);
3358
+ return {
3359
+ healthy: true,
3360
+ provider: "qwen",
3361
+ capabilities: { model: modelName, available: hasModel, totalModels: models.data.length },
3362
+ timestamp
3363
+ };
3364
+ } catch (error) {
3365
+ return {
3366
+ healthy: false,
3367
+ provider: "qwen",
3368
+ error: `Connection failed: ${error instanceof Error ? error.message : String(error)}`,
3369
+ timestamp
3370
+ };
3371
+ }
3372
+ }
3373
+ };
3374
+ }
3375
+ async chat(messages, context, options) {
3376
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i;
3377
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3378
+ const systemMessage = {
3379
+ role: "system",
3380
+ content: buildSystemContent(basePrompt, context)
3381
+ };
3382
+ const formattedMessages = [
3383
+ systemMessage,
3384
+ ...messages.map((m) => ({
3385
+ role: m.role,
3386
+ content: m.content
3387
+ }))
3388
+ ];
3389
+ const completion = await this.client.chat.completions.create({
3390
+ model: this.llmConfig.model,
3391
+ messages: formattedMessages,
3392
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3393
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3394
+ stop: options == null ? void 0 : options.stop
3395
+ });
3396
+ return (_i = (_h = (_g2 = completion.choices[0]) == null ? void 0 : _g2.message) == null ? void 0 : _h.content) != null ? _i : "";
3397
+ }
3398
+ chatStream(messages, context, options) {
3399
+ return __asyncGenerator(this, null, function* () {
3400
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3401
+ const basePrompt = (_b = (_a2 = options == null ? void 0 : options.systemPrompt) != null ? _a2 : this.llmConfig.systemPrompt) != null ? _b : "You are a helpful assistant. Answer questions based on the provided context.";
3402
+ const systemMessage = {
3403
+ role: "system",
3404
+ content: buildSystemContent(basePrompt, context)
3405
+ };
3406
+ const formattedMessages = [
3407
+ systemMessage,
3408
+ ...messages.map((m) => ({
3409
+ role: m.role,
3410
+ content: m.content
3411
+ }))
3412
+ ];
3413
+ const stream = yield new __await(this.client.chat.completions.create({
3414
+ model: this.llmConfig.model,
3415
+ messages: formattedMessages,
3416
+ max_tokens: (_d = (_c = options == null ? void 0 : options.maxTokens) != null ? _c : this.llmConfig.maxTokens) != null ? _d : 1024,
3417
+ temperature: (_f = (_e = options == null ? void 0 : options.temperature) != null ? _e : this.llmConfig.temperature) != null ? _f : 0.7,
3418
+ stop: options == null ? void 0 : options.stop,
3419
+ stream: true
3420
+ }));
3421
+ if (!stream) {
3422
+ throw new Error("[QwenProvider] completions.create stream is undefined");
3423
+ }
3424
+ try {
3425
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
3426
+ const chunk = temp.value;
3427
+ const content = ((_h = (_g2 = chunk.choices[0]) == null ? void 0 : _g2.delta) == null ? void 0 : _h.content) || "";
3428
+ if (content) yield content;
3429
+ }
3430
+ } catch (temp) {
3431
+ error = [temp];
3432
+ } finally {
3433
+ try {
3434
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
3435
+ } finally {
3436
+ if (error)
3437
+ throw error[0];
3438
+ }
3439
+ }
3440
+ });
3441
+ }
3442
+ async embed(text, options) {
3443
+ const results = await this.batchEmbed([text], options);
3444
+ return results[0];
3445
+ }
3446
+ async batchEmbed(texts, options) {
3447
+ var _a2, _b, _c, _d, _e, _f;
3448
+ const model = (_c = (_b = options == null ? void 0 : options.model) != null ? _b : (_a2 = this.embeddingConfig) == null ? void 0 : _a2.model) != null ? _c : "text-embedding-v1";
3449
+ const apiKey = (_e = (_d = this.embeddingConfig) == null ? void 0 : _d.apiKey) != null ? _e : this.llmConfig.apiKey;
3450
+ const client = apiKey !== this.llmConfig.apiKey ? new OpenAI3({
3451
+ apiKey,
3452
+ baseURL: ((_f = this.embeddingConfig) == null ? void 0 : _f.baseUrl) || "https://dashscope.aliyuncs.com/compatible-mode/v1"
3453
+ }) : this.client;
3454
+ const response = await client.embeddings.create({ model, input: texts });
3455
+ return response.data.map((d) => d.embedding);
3456
+ }
3457
+ async ping() {
3458
+ try {
3459
+ await this.client.models.list();
3460
+ return true;
3461
+ } catch (err) {
3462
+ console.error("[QwenProvider] Ping failed:", err);
3463
+ return false;
3464
+ }
3465
+ }
3466
+ };
3467
+
3127
3468
  // src/llm/providers/UniversalLLMAdapter.ts
3128
3469
  init_templateUtils();
3129
3470
  import axios2 from "axios";
@@ -3207,10 +3548,10 @@ var VECTOR_PROFILES = {
3207
3548
  // src/llm/providers/UniversalLLMAdapter.ts
3208
3549
  var UniversalLLMAdapter = class {
3209
3550
  constructor(config) {
3210
- var _a, _b, _c, _d, _e, _f, _g, _h;
3551
+ var _a2, _b, _c, _d, _e, _f, _g2, _h;
3211
3552
  this.model = config.model;
3212
3553
  const llmConfig = config;
3213
- const options = (_a = llmConfig.options) != null ? _a : {};
3554
+ const options = (_a2 = llmConfig.options) != null ? _a2 : {};
3214
3555
  let profile = {};
3215
3556
  if (typeof options.profile === "string") {
3216
3557
  profile = LLM_PROFILES[options.profile] || {};
@@ -3222,7 +3563,7 @@ var UniversalLLMAdapter = class {
3222
3563
  this.maxTokens = (_d = llmConfig.maxTokens) != null ? _d : 1024;
3223
3564
  this.temperature = (_e = llmConfig.temperature) != null ? _e : 0;
3224
3565
  this.apiKey = config.apiKey;
3225
- this.baseUrl = (_g = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g : "";
3566
+ this.baseUrl = (_g2 = (_f = llmConfig.baseUrl) != null ? _f : this.opts.baseUrl) != null ? _g2 : "";
3226
3567
  if (!this.baseUrl) {
3227
3568
  throw new Error("[UniversalLLMAdapter] baseUrl is required in config or config.options");
3228
3569
  }
@@ -3236,8 +3577,8 @@ var UniversalLLMAdapter = class {
3236
3577
  });
3237
3578
  }
3238
3579
  async chat(messages, context) {
3239
- var _a, _b;
3240
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
3580
+ var _a2, _b;
3581
+ const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3241
3582
  const formattedMessages = [
3242
3583
  { role: "system", content: `${this.systemPrompt}
3243
3584
 
@@ -3261,7 +3602,7 @@ ${context != null ? context : "None"}` },
3261
3602
  temperature: this.temperature
3262
3603
  };
3263
3604
  }
3264
- const { data } = await this.http.post(path, payload);
3605
+ const { data } = await this.http.post(path2, payload);
3265
3606
  const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
3266
3607
  const result = resolvePath(data, extractPath);
3267
3608
  if (result === void 0) {
@@ -3276,9 +3617,9 @@ ${context != null ? context : "None"}` },
3276
3617
  */
3277
3618
  chatStream(messages, context) {
3278
3619
  return __asyncGenerator(this, null, function* () {
3279
- var _a, _b, _c;
3280
- const path = (_a = this.opts.chatPath) != null ? _a : "/chat/completions";
3281
- const url = `${this.baseUrl.replace(/\/$/, "")}${path}`;
3620
+ var _a2, _b, _c;
3621
+ const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3622
+ const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3282
3623
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
3283
3624
  const formattedMessages = [
3284
3625
  { role: "system", content: `${this.systemPrompt}
@@ -3356,8 +3697,8 @@ ${context != null ? context : "None"}` },
3356
3697
  });
3357
3698
  }
3358
3699
  async embed(text) {
3359
- var _a, _b;
3360
- const path = (_a = this.opts.embedPath) != null ? _a : "/embeddings";
3700
+ var _a2, _b;
3701
+ const path2 = (_a2 = this.opts.embedPath) != null ? _a2 : "/embeddings";
3361
3702
  let payload;
3362
3703
  if (this.opts.embedPayloadTemplate) {
3363
3704
  payload = buildPayload(this.opts.embedPayloadTemplate, {
@@ -3370,7 +3711,7 @@ ${context != null ? context : "None"}` },
3370
3711
  input: text
3371
3712
  };
3372
3713
  }
3373
- const { data } = await this.http.post(path, payload);
3714
+ const { data } = await this.http.post(path2, payload);
3374
3715
  const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
3375
3716
  const vector = resolvePath(data, extractPath);
3376
3717
  if (!Array.isArray(vector)) {
@@ -3438,13 +3779,13 @@ var AuthenticationException = class extends RetrivoraError {
3438
3779
  }
3439
3780
  };
3440
3781
  function wrapError(err, defaultCode, defaultMessage) {
3441
- var _a;
3782
+ var _a2;
3442
3783
  if (err instanceof RetrivoraError) {
3443
3784
  return err;
3444
3785
  }
3445
3786
  const error = err;
3446
3787
  const message = (error == null ? void 0 : error.message) || defaultMessage || String(err);
3447
- 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);
3788
+ const status = (error == null ? void 0 : error.status) || (error == null ? void 0 : error.statusCode) || ((_a2 = error == null ? void 0 : error.response) == null ? void 0 : _a2.status);
3448
3789
  const code = error == null ? void 0 : error.code;
3449
3790
  if (status === 429 || /rate[- ]?limit/i.test(message) || code === "RATE_LIMIT_EXCEEDED") {
3450
3791
  return new RateLimitException(message, err);
@@ -3508,6 +3849,8 @@ var LLMFactory = class _LLMFactory {
3508
3849
  "anthropic",
3509
3850
  "ollama",
3510
3851
  "gemini",
3852
+ "groq",
3853
+ "qwen",
3511
3854
  "rest",
3512
3855
  "universal_rest",
3513
3856
  "custom",
@@ -3515,7 +3858,7 @@ var LLMFactory = class _LLMFactory {
3515
3858
  ];
3516
3859
  }
3517
3860
  static create(llmConfig, embeddingConfig) {
3518
- var _a, _b, _c;
3861
+ var _a2, _b, _c;
3519
3862
  switch (llmConfig.provider) {
3520
3863
  case "openai":
3521
3864
  return new OpenAIProvider(llmConfig, embeddingConfig);
@@ -3525,12 +3868,16 @@ var LLMFactory = class _LLMFactory {
3525
3868
  return new OllamaProvider(llmConfig, embeddingConfig);
3526
3869
  case "gemini":
3527
3870
  return new GeminiProvider(llmConfig, embeddingConfig);
3871
+ case "groq":
3872
+ return new GroqProvider(llmConfig, embeddingConfig);
3873
+ case "qwen":
3874
+ return new QwenProvider(llmConfig, embeddingConfig);
3528
3875
  case "rest":
3529
3876
  case "universal_rest":
3530
3877
  case "custom":
3531
3878
  return new UniversalLLMAdapter(llmConfig);
3532
3879
  default: {
3533
- const providerName = String((_a = llmConfig.provider) != null ? _a : "").toLowerCase();
3880
+ const providerName = String((_a2 = llmConfig.provider) != null ? _a2 : "").toLowerCase();
3534
3881
  const customFactory = customProviders.get(providerName);
3535
3882
  if (customFactory) {
3536
3883
  return customFactory(llmConfig);
@@ -3567,6 +3914,10 @@ var LLMFactory = class _LLMFactory {
3567
3914
  return OllamaProvider;
3568
3915
  case "gemini":
3569
3916
  return GeminiProvider;
3917
+ case "groq":
3918
+ return GroqProvider;
3919
+ case "qwen":
3920
+ return QwenProvider;
3570
3921
  case "rest":
3571
3922
  case "universal_rest":
3572
3923
  case "custom":
@@ -3628,7 +3979,7 @@ var ProviderRegistry = class {
3628
3979
  return null;
3629
3980
  }
3630
3981
  static async loadVectorProviderClass(provider) {
3631
- var _a;
3982
+ var _a2;
3632
3983
  if (this.vectorProviders[provider]) return this.vectorProviders[provider];
3633
3984
  switch (provider) {
3634
3985
  case "pinecone": {
@@ -3637,7 +3988,7 @@ var ProviderRegistry = class {
3637
3988
  }
3638
3989
  case "pgvector":
3639
3990
  case "postgresql": {
3640
- const postgresMode = ((_a = process.env.POSTGRES_MODE) != null ? _a : "multi").toLowerCase();
3991
+ const postgresMode = ((_a2 = process.env.POSTGRES_MODE) != null ? _a2 : "multi").toLowerCase();
3641
3992
  if (postgresMode === "single") {
3642
3993
  const { PostgreSQLProvider: PostgreSQLProvider2 } = await Promise.resolve().then(() => (init_PostgreSQLProvider(), PostgreSQLProvider_exports));
3643
3994
  return PostgreSQLProvider2;
@@ -3857,6 +4208,125 @@ var ConfigValidator = class {
3857
4208
  }
3858
4209
  };
3859
4210
 
4211
+ // src/core/LicenseVerifier.ts
4212
+ import * as crypto2 from "crypto";
4213
+ var LicenseVerifier = class {
4214
+ /**
4215
+ * Decodes, verifies signature, and checks metadata of a license key.
4216
+ *
4217
+ * @param licenseKey - Base64url signed JWT license key.
4218
+ * @param currentProjectId - Project namespace ID.
4219
+ * @param publicKeyOverride - Optional override for unit/integration tests.
4220
+ */
4221
+ static verify(licenseKey, currentProjectId, provider, publicKeyOverride) {
4222
+ const isProduction = process.env.NODE_ENV === "production";
4223
+ if (!licenseKey) {
4224
+ if (isProduction) {
4225
+ throw new ConfigurationException(
4226
+ "[Retrivora SDK] License key (licenseKey) is required in production environments."
4227
+ );
4228
+ }
4229
+ console.warn(
4230
+ `\x1B[33m[Retrivora SDK] WARNING: Running without a license key. This namespace (${currentProjectId}) is permitted for local development only.\x1B[0m`
4231
+ );
4232
+ return {
4233
+ projectId: currentProjectId,
4234
+ expiresAt: Math.floor(Date.now() / 1e3) + 86400,
4235
+ // Valid for 24h
4236
+ tier: "hobby"
4237
+ };
4238
+ }
4239
+ try {
4240
+ const parts = licenseKey.split(".");
4241
+ if (parts.length !== 3) {
4242
+ throw new Error("Malformed token structure (expected 3 parts).");
4243
+ }
4244
+ const [headerB64, payloadB64, signatureB64] = parts;
4245
+ const dataToVerify = `${headerB64}.${payloadB64}`;
4246
+ const publicKey = publicKeyOverride != null ? publicKeyOverride : this.PUBLIC_KEY;
4247
+ const signature = Buffer.from(signatureB64, "base64url");
4248
+ const data = Buffer.from(dataToVerify);
4249
+ const isValid = crypto2.verify(
4250
+ "sha256",
4251
+ data,
4252
+ publicKey,
4253
+ signature
4254
+ );
4255
+ if (!isValid) {
4256
+ throw new Error("Signature verification failed.");
4257
+ }
4258
+ const payload = JSON.parse(
4259
+ Buffer.from(payloadB64, "base64url").toString("utf8")
4260
+ );
4261
+ if (!payload.projectId) {
4262
+ throw new Error('License payload is missing "projectId".');
4263
+ }
4264
+ if (payload.projectId !== currentProjectId) {
4265
+ throw new Error(
4266
+ `Project ID mismatch. License is bound to project namespace "${payload.projectId}" but configuration has "${currentProjectId}".`
4267
+ );
4268
+ }
4269
+ if (!payload.expiresAt) {
4270
+ throw new Error('License payload is missing expiration ("expiresAt").');
4271
+ }
4272
+ const currentTimestampSec = Math.floor(Date.now() / 1e3);
4273
+ if (currentTimestampSec > payload.expiresAt) {
4274
+ throw new Error(
4275
+ `License key has expired. Expiration: ${new Date(
4276
+ payload.expiresAt * 1e3
4277
+ ).toDateString()}`
4278
+ );
4279
+ }
4280
+ if (isProduction && provider) {
4281
+ const tier = (payload.tier || "").toLowerCase();
4282
+ const normalizedProvider = provider.toLowerCase();
4283
+ if (tier === "hobby") {
4284
+ const allowedHobby = ["postgresql", "pgvector", "supabase"];
4285
+ if (!allowedHobby.includes(normalizedProvider)) {
4286
+ throw new Error(
4287
+ `The database provider "${provider}" is not allowed on the Hobby tier. Hobby tier is restricted to PostgreSQL and Supabase. Please upgrade to a Developer Pro or Enterprise plan.`
4288
+ );
4289
+ }
4290
+ } else if (tier === "pro" || tier === "developer_pro" || tier === "premium" || tier === "growth") {
4291
+ const allowedPro = [
4292
+ "postgresql",
4293
+ "pgvector",
4294
+ "supabase",
4295
+ "pinecone",
4296
+ "qdrant",
4297
+ "mongodb",
4298
+ "milvus",
4299
+ "chroma",
4300
+ "chromadb"
4301
+ ];
4302
+ if (!allowedPro.includes(normalizedProvider)) {
4303
+ throw new Error(
4304
+ `The database provider "${provider}" is not allowed on the Developer Pro tier. Please upgrade to an Enterprise plan.`
4305
+ );
4306
+ }
4307
+ }
4308
+ }
4309
+ return payload;
4310
+ } catch (err) {
4311
+ const message = err instanceof Error ? err.message : String(err);
4312
+ throw new ConfigurationException(
4313
+ `[Retrivora SDK] License key validation failed: ${message}`
4314
+ );
4315
+ }
4316
+ }
4317
+ };
4318
+ // Retrivora's Public Key used to verify the license key signature.
4319
+ // In production, this matches the private key held by Retrivora SaaS.
4320
+ LicenseVerifier.PUBLIC_KEY = `-----BEGIN PUBLIC KEY-----
4321
+ MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEArMieCkCBtTfByRNOserm
4322
+ XM4T0Am29JyNzB4XQPe+WJJ56CN73H1HLXx9n1ByFcxkEJ9po+SURj5DnvUXwEy+
4323
+ xstx33wDPpVmcMQe33j5CRYS0S4gICiNqIRN7XkTlJtrcXqrmh1/hdOAwfRbjO1T
4324
+ NVtORHwUwWfI/lBLyxUPGtKPed+0fQ7NtcW4o00JXxs3EjCB5BV9CbnXoTjQb/4h
4325
+ iwZof4l8rb7oaNzOsVg0RSyxsETX7Ex5sI0CjBz1p2mYp4oVhw/A/h8Ls7H0XzjC
4326
+ +Eb6BLtsytt5JHoSp0jExLlCpDmpys2L+kETcBVx+IqiXtdN1n6KbkksvEDUVzLI
4327
+ MwIDAQAB
4328
+ -----END PUBLIC KEY-----`;
4329
+
3860
4330
  // src/rag/DocumentChunker.ts
3861
4331
  var DocumentChunker = class {
3862
4332
  constructor(chunkSize = 1e3, chunkOverlap = 200, separators = ["\n# ", "\n## ", "\n### ", "\n#### ", "\n\n", "\n", " ", ""]) {
@@ -4086,11 +4556,11 @@ var LlamaIndexIngestor = class {
4086
4556
  * than standard character-count splitting.
4087
4557
  */
4088
4558
  async chunk(text, options = {}) {
4089
- var _a, _b;
4559
+ var _a2, _b;
4090
4560
  try {
4091
4561
  const { Document, SentenceSplitter, MetadataMode } = await import(`${"llamaindex"}`);
4092
4562
  const splitter = new SentenceSplitter({
4093
- chunkSize: (_a = options.chunkSize) != null ? _a : 1e3,
4563
+ chunkSize: (_a2 = options.chunkSize) != null ? _a2 : 1e3,
4094
4564
  chunkOverlap: (_b = options.chunkOverlap) != null ? _b : 200
4095
4565
  });
4096
4566
  const doc = new Document({ text, metadata: options.metadata || {} });
@@ -4199,7 +4669,7 @@ ${error instanceof Error ? error.message : String(error)}`
4199
4669
  * The agent returns `{ messages: [...] }` — the last message is the final answer.
4200
4670
  */
4201
4671
  async run(input, chatHistory = []) {
4202
- var _a, _b, _c;
4672
+ var _a2, _b, _c;
4203
4673
  if (!this.agent) {
4204
4674
  throw new Error("[LangChainAgent] Agent not initialized. Call initialize() first.");
4205
4675
  }
@@ -4210,14 +4680,445 @@ ${error instanceof Error ? error.message : String(error)}`
4210
4680
  const response = await this.agent.invoke({
4211
4681
  messages: [...historyMessages, new HumanMessage(input)]
4212
4682
  });
4213
- const lastMessage = (_a = response == null ? void 0 : response.messages) == null ? void 0 : _a.at(-1);
4214
- if (lastMessage && typeof lastMessage.content === "string") {
4215
- return lastMessage.content;
4216
- }
4217
- if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
4218
- return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
4219
- }
4220
- return String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
4683
+ const lastMessage = (_a2 = response == null ? void 0 : response.messages) == null ? void 0 : _a2.at(-1);
4684
+ if (lastMessage && typeof lastMessage.content === "string") {
4685
+ return lastMessage.content;
4686
+ }
4687
+ if (Array.isArray(lastMessage == null ? void 0 : lastMessage.content)) {
4688
+ return lastMessage.content.filter((c) => c.type === "text").map((c) => c.text).join("");
4689
+ }
4690
+ return String((_c = (_b = response == null ? void 0 : response.output) != null ? _b : response) != null ? _c : "");
4691
+ }
4692
+ };
4693
+
4694
+ // src/core/mcp.ts
4695
+ import { spawn } from "child_process";
4696
+ var MCPClient = class {
4697
+ constructor(config) {
4698
+ this.config = config;
4699
+ this.messageIdCounter = 0;
4700
+ this.pendingRequests = /* @__PURE__ */ new Map();
4701
+ this.stdioBuffer = "";
4702
+ this.initialized = false;
4703
+ }
4704
+ getNextMessageId() {
4705
+ return ++this.messageIdCounter;
4706
+ }
4707
+ /**
4708
+ * Connect and initialize the MCP server connection.
4709
+ */
4710
+ async connect() {
4711
+ if (this.initialized) return;
4712
+ if (this.config.transport === "stdio") {
4713
+ await this.connectStdio();
4714
+ } else {
4715
+ await this.connectSSE();
4716
+ }
4717
+ try {
4718
+ const response = await this.sendJsonRpc("initialize", {
4719
+ protocolVersion: "2024-11-05",
4720
+ capabilities: {},
4721
+ clientInfo: {
4722
+ name: "retrivora-sdk",
4723
+ version: "1.0.0"
4724
+ }
4725
+ });
4726
+ await this.sendNotification("notifications/initialized");
4727
+ this.initialized = true;
4728
+ console.log(`[MCPClient] Connected and initialized server "${this.config.name}" successfully.`);
4729
+ } catch (err) {
4730
+ this.disconnect();
4731
+ throw new Error(`[MCPClient] Failed to initialize server "${this.config.name}": ${err.message}`);
4732
+ }
4733
+ }
4734
+ async connectStdio() {
4735
+ var _a2;
4736
+ const cmd = this.config.command;
4737
+ if (!cmd) {
4738
+ throw new Error(`[MCPClient] Command option is required for stdio transport on "${this.config.name}"`);
4739
+ }
4740
+ const args = this.config.args || [];
4741
+ const env = __spreadValues(__spreadValues({}, process.env), this.config.env || {});
4742
+ this.childProcess = spawn(cmd, args, { env, shell: true });
4743
+ if (!this.childProcess || !this.childProcess.stdout || !this.childProcess.stdin) {
4744
+ throw new Error(`[MCPClient] Failed to spawn stdio child process for "${this.config.name}"`);
4745
+ }
4746
+ this.childProcess.stdout.on("data", (data) => {
4747
+ this.stdioBuffer += data.toString("utf-8");
4748
+ this.processStdioLines();
4749
+ });
4750
+ (_a2 = this.childProcess.stderr) == null ? void 0 : _a2.on("data", (data) => {
4751
+ console.warn(`[MCPClient] [stderr] [${this.config.name}]:`, data.toString("utf-8"));
4752
+ });
4753
+ this.childProcess.on("close", (code) => {
4754
+ console.log(`[MCPClient] Connection closed for "${this.config.name}" with exit code: ${code}`);
4755
+ this.disconnect();
4756
+ });
4757
+ await new Promise((resolve) => setTimeout(resolve, 100));
4758
+ }
4759
+ processStdioLines() {
4760
+ let newlineIndex;
4761
+ while ((newlineIndex = this.stdioBuffer.indexOf("\n")) !== -1) {
4762
+ const line = this.stdioBuffer.substring(0, newlineIndex).trim();
4763
+ this.stdioBuffer = this.stdioBuffer.substring(newlineIndex + 1);
4764
+ if (!line) continue;
4765
+ try {
4766
+ const payload = JSON.parse(line);
4767
+ if (payload.id !== void 0) {
4768
+ const req = this.pendingRequests.get(Number(payload.id));
4769
+ if (req) {
4770
+ this.pendingRequests.delete(Number(payload.id));
4771
+ if (payload.error) {
4772
+ req.reject(new Error(payload.error.message || JSON.stringify(payload.error)));
4773
+ } else {
4774
+ req.resolve(payload.result);
4775
+ }
4776
+ }
4777
+ }
4778
+ } catch (e) {
4779
+ console.warn(`[MCPClient] Error parsing stdio JSON-RPC line from "${this.config.name}":`, e, "Line content:", line);
4780
+ }
4781
+ }
4782
+ }
4783
+ async connectSSE() {
4784
+ if (!this.config.url) {
4785
+ throw new Error(`[MCPClient] URL is required for sse transport on "${this.config.name}"`);
4786
+ }
4787
+ this.sseUrl = this.config.url;
4788
+ }
4789
+ async sendJsonRpc(method, params) {
4790
+ const id = this.getNextMessageId();
4791
+ const request = {
4792
+ jsonrpc: "2.0",
4793
+ id,
4794
+ method,
4795
+ params
4796
+ };
4797
+ if (this.config.transport === "stdio") {
4798
+ if (!this.childProcess || !this.childProcess.stdin) {
4799
+ throw new Error(`[MCPClient] Server "${this.config.name}" is not connected (stdio process missing)`);
4800
+ }
4801
+ return new Promise((resolve, reject) => {
4802
+ this.pendingRequests.set(id, { resolve, reject });
4803
+ this.childProcess.stdin.write(JSON.stringify(request) + "\n", "utf-8");
4804
+ });
4805
+ } else {
4806
+ if (!this.sseUrl) {
4807
+ throw new Error(`[MCPClient] Server "${this.config.name}" SSE URL is not initialized`);
4808
+ }
4809
+ const response = await fetch(this.sseUrl, {
4810
+ method: "POST",
4811
+ headers: { "Content-Type": "application/json" },
4812
+ body: JSON.stringify(request)
4813
+ });
4814
+ if (!response.ok) {
4815
+ throw new Error(`SSE JSON-RPC POST failed with status ${response.status}`);
4816
+ }
4817
+ const payload = await response.json();
4818
+ if (payload.error) {
4819
+ throw new Error(payload.error.message || JSON.stringify(payload.error));
4820
+ }
4821
+ return payload.result;
4822
+ }
4823
+ }
4824
+ async sendNotification(method, params) {
4825
+ var _a2;
4826
+ const notification = {
4827
+ jsonrpc: "2.0",
4828
+ method,
4829
+ params
4830
+ };
4831
+ if (this.config.transport === "stdio") {
4832
+ if ((_a2 = this.childProcess) == null ? void 0 : _a2.stdin) {
4833
+ this.childProcess.stdin.write(JSON.stringify(notification) + "\n", "utf-8");
4834
+ }
4835
+ } else if (this.sseUrl) {
4836
+ await fetch(this.sseUrl, {
4837
+ method: "POST",
4838
+ headers: { "Content-Type": "application/json" },
4839
+ body: JSON.stringify(notification)
4840
+ }).catch((err) => console.warn("[MCPClient] Failed to send notification over SSE:", err));
4841
+ }
4842
+ }
4843
+ /**
4844
+ * List all tools offered by the MCP server.
4845
+ */
4846
+ async listTools() {
4847
+ await this.connect();
4848
+ const result = await this.sendJsonRpc("tools/list", {});
4849
+ return (result == null ? void 0 : result.tools) || [];
4850
+ }
4851
+ /**
4852
+ * Execute a tool on the MCP server.
4853
+ */
4854
+ async callTool(name, args = {}) {
4855
+ await this.connect();
4856
+ return await this.sendJsonRpc("tools/call", { name, arguments: args });
4857
+ }
4858
+ disconnect() {
4859
+ this.initialized = false;
4860
+ this.pendingRequests.forEach((req) => req.reject(new Error("MCPClient disconnected")));
4861
+ this.pendingRequests.clear();
4862
+ if (this.childProcess) {
4863
+ try {
4864
+ this.childProcess.kill();
4865
+ } catch (e) {
4866
+ }
4867
+ this.childProcess = void 0;
4868
+ }
4869
+ }
4870
+ };
4871
+ var MCPRegistry = class {
4872
+ constructor(servers = []) {
4873
+ this.clients = [];
4874
+ this.clients = servers.map((cfg) => new MCPClient(cfg));
4875
+ }
4876
+ async getAllTools() {
4877
+ const list = [];
4878
+ await Promise.all(
4879
+ this.clients.map(async (client) => {
4880
+ try {
4881
+ const tools = await client.listTools();
4882
+ tools.forEach((t) => list.push({ serverName: client["config"].name, tool: t }));
4883
+ } catch (e) {
4884
+ console.warn(`[MCPRegistry] Failed to fetch tools from server "${client["config"].name}":`, e);
4885
+ }
4886
+ })
4887
+ );
4888
+ return list;
4889
+ }
4890
+ async callTool(toolName, args = {}) {
4891
+ for (const client of this.clients) {
4892
+ try {
4893
+ const tools = await client.listTools();
4894
+ if (tools.some((t) => t.name === toolName)) {
4895
+ return await client.callTool(toolName, args);
4896
+ }
4897
+ } catch (e) {
4898
+ }
4899
+ }
4900
+ throw new Error(`[MCPRegistry] Tool "${toolName}" not found on any registered MCP server.`);
4901
+ }
4902
+ disconnectAll() {
4903
+ this.clients.forEach((c) => c.disconnect());
4904
+ }
4905
+ };
4906
+
4907
+ // src/core/MultiAgentCoordinator.ts
4908
+ var MultiAgentCoordinator = class {
4909
+ constructor(options) {
4910
+ var _a2;
4911
+ this.llmProvider = options.llmProvider;
4912
+ this.mcpRegistry = options.mcpRegistry;
4913
+ this.documentSearch = options.documentSearch;
4914
+ this.maxIterations = (_a2 = options.maxIterations) != null ? _a2 : 5;
4915
+ }
4916
+ /**
4917
+ * Run the multi-agent coordination loop synchronously and return the final response.
4918
+ */
4919
+ async run(question, history = []) {
4920
+ const generator = this.runStream(question, history);
4921
+ let finalReply = "";
4922
+ const sources = [];
4923
+ try {
4924
+ for (var iter = __forAwait(generator), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
4925
+ const chunk = temp.value;
4926
+ if (typeof chunk === "string") {
4927
+ finalReply += chunk;
4928
+ } else if (chunk && typeof chunk === "object") {
4929
+ if ("reply" in chunk && chunk.reply) {
4930
+ finalReply += chunk.reply;
4931
+ }
4932
+ if ("sources" in chunk && chunk.sources) {
4933
+ sources.push(...chunk.sources);
4934
+ }
4935
+ }
4936
+ }
4937
+ } catch (temp) {
4938
+ error = [temp];
4939
+ } finally {
4940
+ try {
4941
+ more && (temp = iter.return) && await temp.call(iter);
4942
+ } finally {
4943
+ if (error)
4944
+ throw error[0];
4945
+ }
4946
+ }
4947
+ return {
4948
+ reply: finalReply,
4949
+ sources
4950
+ };
4951
+ }
4952
+ /**
4953
+ * Run the multi-agent coordination loop as an async stream, yielding intermediate thought blocks and tool execution events.
4954
+ */
4955
+ runStream(_0) {
4956
+ return __asyncGenerator(this, arguments, function* (question, history = []) {
4957
+ const mcpTools = yield new __await(this.mcpRegistry.getAllTools());
4958
+ let systemPrompt = `You are a goal-driven supervisor agent coordinating a RAG search engine and external MCP servers to solve the user's task.
4959
+ You must think step-by-step before acting. Write your internal thinking process inside a \`<think>...</think>\` block first, then act or answer.
4960
+
4961
+ Available Tools:
4962
+ - document_search(query: string): Search the vector database and knowledge base for documents.
4963
+
4964
+ ${mcpTools.length > 0 ? "MCP Server Tools:" : ""}
4965
+ ${mcpTools.map((mt) => {
4966
+ var _a2;
4967
+ return `- ${mt.tool.name}(${JSON.stringify(((_a2 = mt.tool.inputSchema) == null ? void 0 : _a2.properties) || {})}): ${mt.tool.description || "No description provided."}`;
4968
+ }).join("\n")}
4969
+
4970
+ Tool Calling Protocol:
4971
+ If you need to call a tool, write:
4972
+ TOOL_CALL: <toolName>({ "argName": "value" })
4973
+ And then STOP generating immediately.
4974
+
4975
+ Once you have gathered enough information to fully satisfy the user's query, write your final response directly after the closing \`</think>\` block.
4976
+ `;
4977
+ const supervisorHistory = [
4978
+ { role: "system", content: systemPrompt },
4979
+ ...history,
4980
+ { role: "user", content: question }
4981
+ ];
4982
+ let iteration = 0;
4983
+ const allSources = [];
4984
+ while (iteration < this.maxIterations) {
4985
+ iteration++;
4986
+ const context = "";
4987
+ let fullModelResponse = "";
4988
+ let textBuffer = "";
4989
+ let inThinking = false;
4990
+ let toolCallDetected = null;
4991
+ if (!this.llmProvider.chatStream) {
4992
+ const reply = yield new __await(this.llmProvider.chat(supervisorHistory, context));
4993
+ fullModelResponse = reply;
4994
+ const thinkIndex = reply.indexOf("<think>");
4995
+ const endThinkIndex = reply.indexOf("</think>");
4996
+ let thinkingText = "";
4997
+ let answerText = reply;
4998
+ if (thinkIndex !== -1 && endThinkIndex !== -1) {
4999
+ thinkingText = reply.substring(thinkIndex + 7, endThinkIndex);
5000
+ answerText = reply.substring(endThinkIndex + 8);
5001
+ yield { type: "thinking", text: thinkingText };
5002
+ }
5003
+ const toolMatch = answerText.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
5004
+ if (toolMatch) {
5005
+ const toolName = toolMatch[1];
5006
+ const toolArgsStr = toolMatch[2];
5007
+ try {
5008
+ const toolArgs = JSON.parse(toolArgsStr.trim());
5009
+ toolCallDetected = { name: toolName, args: toolArgs };
5010
+ } catch (e) {
5011
+ console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
5012
+ }
5013
+ } else {
5014
+ yield answerText;
5015
+ }
5016
+ } else {
5017
+ const stream = this.llmProvider.chatStream(supervisorHistory, context);
5018
+ try {
5019
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
5020
+ const chunk = temp.value;
5021
+ fullModelResponse += chunk;
5022
+ textBuffer += chunk;
5023
+ if (!inThinking && textBuffer.includes("<think>")) {
5024
+ inThinking = true;
5025
+ const idx = textBuffer.indexOf("<think>");
5026
+ textBuffer = textBuffer.slice(idx + 7);
5027
+ }
5028
+ if (inThinking && textBuffer.includes("</think>")) {
5029
+ inThinking = false;
5030
+ const idx = textBuffer.indexOf("</think>");
5031
+ const thinkingDelta = textBuffer.slice(0, idx);
5032
+ yield { type: "thinking", text: thinkingDelta };
5033
+ textBuffer = textBuffer.slice(idx + 8);
5034
+ }
5035
+ if (inThinking && textBuffer.length > 0) {
5036
+ yield { type: "thinking", text: textBuffer };
5037
+ textBuffer = "";
5038
+ }
5039
+ if (!inThinking && textBuffer.includes("TOOL_CALL:")) {
5040
+ const idx = textBuffer.indexOf("TOOL_CALL:");
5041
+ const precedingText = textBuffer.slice(0, idx);
5042
+ if (precedingText.trim()) {
5043
+ yield precedingText;
5044
+ }
5045
+ textBuffer = textBuffer.slice(idx);
5046
+ }
5047
+ if (!inThinking && !textBuffer.includes("TOOL_CALL:") && textBuffer.length > 0) {
5048
+ yield textBuffer;
5049
+ textBuffer = "";
5050
+ }
5051
+ }
5052
+ } catch (temp) {
5053
+ error = [temp];
5054
+ } finally {
5055
+ try {
5056
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
5057
+ } finally {
5058
+ if (error)
5059
+ throw error[0];
5060
+ }
5061
+ }
5062
+ if (textBuffer.trim()) {
5063
+ const toolMatch = textBuffer.match(/TOOL_CALL:\s*(\w+)\s*\(([\s\S]*)\)/);
5064
+ if (toolMatch) {
5065
+ const toolName = toolMatch[1];
5066
+ const toolArgsStr = toolMatch[2];
5067
+ try {
5068
+ const toolArgs = JSON.parse(toolArgsStr.trim());
5069
+ toolCallDetected = { name: toolName, args: toolArgs };
5070
+ } catch (e) {
5071
+ console.error("[MultiAgentCoordinator] Failed to parse tool args:", toolArgsStr, e);
5072
+ }
5073
+ } else {
5074
+ yield textBuffer;
5075
+ }
5076
+ }
5077
+ }
5078
+ supervisorHistory.push({ role: "assistant", content: fullModelResponse });
5079
+ if (toolCallDetected) {
5080
+ const { name: toolName, args: toolArgs } = toolCallDetected;
5081
+ yield {
5082
+ type: "thinking",
5083
+ text: `
5084
+ [Agent Call] Executing tool "${toolName}" with parameters ${JSON.stringify(toolArgs)}...
5085
+ `
5086
+ };
5087
+ let toolResultText = "";
5088
+ try {
5089
+ if (toolName === "document_search") {
5090
+ const searchRes = yield new __await(this.documentSearch(toolArgs.query || ""));
5091
+ toolResultText = `document_search returned:
5092
+ ${searchRes.reply}
5093
+
5094
+ Sources count: ${searchRes.sources.length}`;
5095
+ if (searchRes.sources && searchRes.sources.length > 0) {
5096
+ allSources.push(...searchRes.sources);
5097
+ yield { reply: "", sources: searchRes.sources };
5098
+ }
5099
+ } else {
5100
+ const mcpRes = yield new __await(this.mcpRegistry.callTool(toolName, toolArgs));
5101
+ toolResultText = `MCP Tool "${toolName}" returned:
5102
+ ${JSON.stringify(mcpRes.content)}`;
5103
+ }
5104
+ } catch (err) {
5105
+ toolResultText = `Error calling tool "${toolName}": ${err.message}`;
5106
+ }
5107
+ supervisorHistory.push({
5108
+ role: "user",
5109
+ content: `TOOL_RESULT for ${toolName}:
5110
+ ${toolResultText}`
5111
+ });
5112
+ yield {
5113
+ type: "thinking",
5114
+ text: `[Agent Output] Tool "${toolName}" executed. Continuing reasoning...
5115
+ `
5116
+ };
5117
+ } else {
5118
+ break;
5119
+ }
5120
+ }
5121
+ });
4221
5122
  }
4222
5123
  };
4223
5124
 
@@ -4547,7 +5448,7 @@ var QueryProcessor = class {
4547
5448
  * @param validFields Optional list of known filterable fields to look for
4548
5449
  */
4549
5450
  static extractQueryFieldHints(question, validFields = []) {
4550
- var _a, _b, _c, _d;
5451
+ var _a2, _b, _c, _d;
4551
5452
  if (!question.trim()) return [];
4552
5453
  const hints = /* @__PURE__ */ new Map();
4553
5454
  const addHint = (value, field) => {
@@ -4627,7 +5528,7 @@ var QueryProcessor = class {
4627
5528
  ];
4628
5529
  for (const p of universalPatterns) {
4629
5530
  for (const match of question.matchAll(p.regex)) {
4630
- const val = p.group ? (_a = match[p.group]) != null ? _a : match[0] : match[0];
5531
+ const val = p.group ? (_a2 = match[p.group]) != null ? _a2 : match[0] : match[0];
4631
5532
  if (!val) continue;
4632
5533
  if (p.field) addHint(val, p.field);
4633
5534
  else addHint(val);
@@ -4851,11 +5752,11 @@ var LLMRouter = class {
4851
5752
  * When provided it is used directly as the 'default' role without re-constructing.
4852
5753
  */
4853
5754
  async initialize(prebuiltDefault) {
4854
- var _a;
5755
+ var _a2;
4855
5756
  const defaultModel = prebuiltDefault != null ? prebuiltDefault : LLMFactory.create(this.config.llm, this.config.embedding);
4856
5757
  this.models.set("default", defaultModel);
4857
5758
  const envFastModel = process.env.FAST_LLM_MODEL;
4858
- const providerFastDefault = (_a = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a : "";
5759
+ const providerFastDefault = (_a2 = FAST_MODEL_DEFAULTS[this.config.llm.provider]) != null ? _a2 : "";
4859
5760
  const fastModelName = envFastModel || providerFastDefault;
4860
5761
  if (fastModelName && fastModelName !== this.config.llm.model) {
4861
5762
  console.log(`[LLMRouter] Fast role \u2192 provider="${this.config.llm.provider}" model="${fastModelName}"`);
@@ -4874,8 +5775,8 @@ var LLMRouter = class {
4874
5775
  * Falls back to 'default' if the requested role is not registered.
4875
5776
  */
4876
5777
  get(role) {
4877
- var _a;
4878
- const provider = (_a = this.models.get(role)) != null ? _a : this.models.get("default");
5778
+ var _a2;
5779
+ const provider = (_a2 = this.models.get(role)) != null ? _a2 : this.models.get("default");
4879
5780
  if (!provider) {
4880
5781
  throw new Error(`[LLMRouter] No provider registered for role: "${role}". Did you call initialize()?`);
4881
5782
  }
@@ -4893,7 +5794,7 @@ var UITransformer = class _UITransformer {
4893
5794
  * Prefer `analyzeAndDecide()` in production.
4894
5795
  */
4895
5796
  static transform(userQuery, retrievedData, config, trainedSchema, intent) {
4896
- var _a, _b, _c;
5797
+ var _a2, _b, _c;
4897
5798
  if (!retrievedData || retrievedData.length === 0) {
4898
5799
  return this.createTextResponse("No data available", "No relevant data found for your query.");
4899
5800
  }
@@ -4913,7 +5814,7 @@ var UITransformer = class _UITransformer {
4913
5814
  return this.transformToBarChart(filteredData, profile, userQuery, resolvedIntent.visualizationHint === "ranking");
4914
5815
  }
4915
5816
  if (resolvedIntent.visualizationHint === "distribution") {
4916
- return (_a = this.transformToHistogram(profile, userQuery)) != null ? _a : this.transformToBarChart(filteredData, profile, userQuery);
5817
+ return (_a2 = this.transformToHistogram(profile, userQuery)) != null ? _a2 : this.transformToBarChart(filteredData, profile, userQuery);
4917
5818
  }
4918
5819
  if (resolvedIntent.visualizationHint === "correlation") {
4919
5820
  return (_b = this.transformToScatterPlot(profile, userQuery)) != null ? _b : this.transformToBarChart(filteredData, profile, userQuery);
@@ -5238,11 +6139,11 @@ ${schemaProfileText}` : ""}`;
5238
6139
  };
5239
6140
  }
5240
6141
  static transformToPieChart(data, profile, query = "") {
5241
- var _a;
6142
+ var _a2;
5242
6143
  const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
5243
6144
  const categories = dimension ? Array.from(new Set(profile.records.map((record) => {
5244
- var _a2;
5245
- return String((_a2 = record.fields[dimension.key]) != null ? _a2 : "");
6145
+ var _a3;
6146
+ return String((_a3 = record.fields[dimension.key]) != null ? _a3 : "");
5246
6147
  }).filter(Boolean))) : this.detectCategories(data);
5247
6148
  if (categories.length === 0) return null;
5248
6149
  const categoryData = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key) : this.aggregateByCategory(data, categories);
@@ -5252,7 +6153,7 @@ ${schemaProfileText}` : ""}`;
5252
6153
  });
5253
6154
  return {
5254
6155
  type: "pie_chart",
5255
- title: `Distribution by ${(_a = dimension == null ? void 0 : dimension.label) != null ? _a : "Category"}`,
6156
+ title: `Distribution by ${(_a2 = dimension == null ? void 0 : dimension.label) != null ? _a2 : "Category"}`,
5256
6157
  description: `Showing breakdown across ${pieData.length} categories`,
5257
6158
  data: pieData
5258
6159
  };
@@ -5262,8 +6163,8 @@ ${schemaProfileText}` : ""}`;
5262
6163
  const valueField = profile.numericFields[0];
5263
6164
  const buckets = /* @__PURE__ */ new Map();
5264
6165
  profile.records.forEach((record) => {
5265
- var _a, _b, _c;
5266
- const timestamp = String((_a = record.fields[dateField.key]) != null ? _a : "");
6166
+ var _a2, _b, _c;
6167
+ const timestamp = String((_a2 = record.fields[dateField.key]) != null ? _a2 : "");
5267
6168
  const value = (_b = this.toFiniteNumber(record.fields[valueField.key])) != null ? _b : 0;
5268
6169
  buckets.set(timestamp, ((_c = buckets.get(timestamp)) != null ? _c : 0) + value);
5269
6170
  });
@@ -5276,23 +6177,23 @@ ${schemaProfileText}` : ""}`;
5276
6177
  };
5277
6178
  }
5278
6179
  static transformToBarChart(data, profile, query = "", horizontal = false) {
5279
- var _a;
6180
+ var _a2;
5280
6181
  const dimension = profile ? this.selectDimensionField(profile, query) : void 0;
5281
6182
  const measure = profile ? this.selectNumericField(profile, query) : void 0;
5282
6183
  const aggregate = dimension && profile ? this.aggregateProfileByDimension(profile, dimension.key, measure == null ? void 0 : measure.key) : this.aggregateByCategory(data, this.detectCategories(data));
5283
6184
  const barData = Object.entries(aggregate).map(([category, value]) => ({ category, value: Number(value) })).sort((a, b) => horizontal ? b.value - a.value : 0).slice(0, 12);
5284
6185
  const fallbackData = barData.length > 0 ? barData : data.slice(0, 12).map((item, index) => {
5285
- var _a2, _b, _c, _d, _e;
6186
+ var _a3, _b, _c, _d, _e;
5286
6187
  const meta = item.metadata || {};
5287
6188
  const label = String(
5288
- (_c = (_b = (_a2 = this.getDynamicVal(meta, "name")) != null ? _a2 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
6189
+ (_c = (_b = (_a3 = this.getDynamicVal(meta, "name")) != null ? _a3 : meta.label) != null ? _b : meta.title) != null ? _c : `Result ${index + 1}`
5289
6190
  );
5290
6191
  const value = (_e = (_d = this.extractNumericValue(meta)) != null ? _d : item.score) != null ? _e : 0;
5291
6192
  return { category: label, value: Number(value) };
5292
6193
  });
5293
6194
  return {
5294
6195
  type: horizontal ? "horizontal_bar" : "bar_chart",
5295
- title: dimension ? `${(_a = measure == null ? void 0 : measure.label) != null ? _a : "Count"} by ${dimension.label}` : "Comparison",
6196
+ title: dimension ? `${(_a2 = measure == null ? void 0 : measure.label) != null ? _a2 : "Count"} by ${dimension.label}` : "Comparison",
5296
6197
  description: `Showing ${fallbackData.length} comparable values`,
5297
6198
  data: fallbackData
5298
6199
  };
@@ -5327,11 +6228,11 @@ ${schemaProfileText}` : ""}`;
5327
6228
  if (fields.length < 2) return null;
5328
6229
  const [xField, yField] = fields;
5329
6230
  const points = profile.records.map((record) => {
5330
- var _a;
6231
+ var _a2;
5331
6232
  const x = this.toFiniteNumber(record.fields[xField.key]);
5332
6233
  const y = this.toFiniteNumber(record.fields[yField.key]);
5333
6234
  if (x === null || y === null) return null;
5334
- return { x, y, label: String((_a = this.getRecordLabel(record)) != null ? _a : record.id) };
6235
+ return { x, y, label: String((_a2 = this.getRecordLabel(record)) != null ? _a2 : record.id) };
5335
6236
  }).filter((point) => point !== null).slice(0, 100);
5336
6237
  if (points.length === 0) return null;
5337
6238
  return {
@@ -5361,9 +6262,9 @@ ${schemaProfileText}` : ""}`;
5361
6262
  static transformToRadarChart(data) {
5362
6263
  const attributeMap = {};
5363
6264
  data.forEach((item) => {
5364
- var _a, _b, _c;
6265
+ var _a2, _b, _c;
5365
6266
  const meta = item.metadata || {};
5366
- const seriesName = String((_c = (_b = (_a = meta.name) != null ? _a : meta.product) != null ? _b : item.id) != null ? _c : "Item");
6267
+ const seriesName = String((_c = (_b = (_a2 = meta.name) != null ? _a2 : meta.product) != null ? _b : item.id) != null ? _c : "Item");
5367
6268
  Object.entries(meta).forEach(([key, val]) => {
5368
6269
  if (typeof val === "number" && !["price", "id"].includes(key.toLowerCase())) {
5369
6270
  if (!attributeMap[key]) attributeMap[key] = {};
@@ -5445,22 +6346,22 @@ ${schemaProfileText}` : ""}`;
5445
6346
  return null;
5446
6347
  }
5447
6348
  static normalizeTransformation(payload) {
5448
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j;
6349
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j;
5449
6350
  if (!payload || typeof payload !== "object") return null;
5450
6351
  const p = payload;
5451
6352
  const type = this.normalizeVisualizationType(
5452
- String((_c = (_b = (_a = p.type) != null ? _a : p.view) != null ? _b : p.chartType) != null ? _c : "")
6353
+ String((_c = (_b = (_a2 = p.type) != null ? _a2 : p.view) != null ? _b : p.chartType) != null ? _c : "")
5453
6354
  );
5454
6355
  if (!type) return null;
5455
6356
  const title = String((_e = (_d = p.title) != null ? _d : p.heading) != null ? _e : "Visualization");
5456
6357
  const description = p.description ? String(p.description) : void 0;
5457
- const rawData = (_j = (_i = (_h = (_g = (_f = p.data) != null ? _f : p.table) != null ? _g : p.rows) != null ? _h : p.items) != null ? _i : p.content) != null ? _j : null;
6358
+ const rawData = (_j = (_i = (_h = (_g2 = (_f = p.data) != null ? _f : p.table) != null ? _g2 : p.rows) != null ? _h : p.items) != null ? _i : p.content) != null ? _j : null;
5458
6359
  const data = type === "text" && typeof rawData === "string" ? { content: rawData } : rawData;
5459
6360
  const transformation = { type, title, description, data };
5460
6361
  return this.validateTransformation(transformation) ? transformation : null;
5461
6362
  }
5462
6363
  static normalizeVisualizationType(type) {
5463
- var _a;
6364
+ var _a2;
5464
6365
  const mapping = {
5465
6366
  pie: "pie_chart",
5466
6367
  pie_chart: "pie_chart",
@@ -5488,7 +6389,7 @@ ${schemaProfileText}` : ""}`;
5488
6389
  product_carousel: "product_carousel",
5489
6390
  carousel: "carousel"
5490
6391
  };
5491
- return (_a = mapping[type.toLowerCase()]) != null ? _a : null;
6392
+ return (_a2 = mapping[type.toLowerCase()]) != null ? _a2 : null;
5492
6393
  }
5493
6394
  static validateTransformation(t) {
5494
6395
  const { type, data } = t;
@@ -5690,16 +6591,16 @@ ${schemaProfileText}` : ""}`;
5690
6591
  return null;
5691
6592
  }
5692
6593
  static selectDimensionField(profile, query) {
5693
- var _a, _b;
6594
+ var _a2, _b;
5694
6595
  const productCategory = profile.categoricalFields.find(
5695
6596
  (field) => /category|department|collection|type|group|segment|region|country|state|city/i.test(field.key)
5696
6597
  );
5697
6598
  const ranked = this.rankFieldsByQuery(profile.categoricalFields, query);
5698
- return (_b = (_a = ranked[0]) != null ? _a : productCategory) != null ? _b : profile.categoricalFields[0];
6599
+ return (_b = (_a2 = ranked[0]) != null ? _a2 : productCategory) != null ? _b : profile.categoricalFields[0];
5699
6600
  }
5700
6601
  static selectNumericField(profile, query) {
5701
- var _a;
5702
- return (_a = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a : profile.numericFields[0];
6602
+ var _a2;
6603
+ return (_a2 = this.rankFieldsByQuery(profile.numericFields, query)[0]) != null ? _a2 : profile.numericFields[0];
5703
6604
  }
5704
6605
  static rankFieldsByQuery(fields, query) {
5705
6606
  const q = query.toLowerCase();
@@ -5728,8 +6629,8 @@ ${schemaProfileText}` : ""}`;
5728
6629
  static aggregateProfileByDimension(profile, dimensionKey, measureKey) {
5729
6630
  const result = {};
5730
6631
  profile.records.forEach((record) => {
5731
- var _a, _b, _c;
5732
- const category = String((_a = record.fields[dimensionKey]) != null ? _a : "Other").trim() || "Other";
6632
+ var _a2, _b, _c;
6633
+ const category = String((_a2 = record.fields[dimensionKey]) != null ? _a2 : "Other").trim() || "Other";
5733
6634
  const value = measureKey ? (_b = this.toFiniteNumber(record.fields[measureKey])) != null ? _b : 0 : 1;
5734
6635
  result[category] = ((_c = result[category]) != null ? _c : 0) + value;
5735
6636
  });
@@ -5808,8 +6709,8 @@ ${schemaProfileText}` : ""}`;
5808
6709
  static aggregateByCategory(data, categories) {
5809
6710
  const result = Object.fromEntries(categories.map((c) => [c, 0]));
5810
6711
  data.forEach((item) => {
5811
- var _a;
5812
- const cat = (_a = this.getProductCategory(item)) != null ? _a : "Other";
6712
+ var _a2;
6713
+ const cat = (_a2 = this.getProductCategory(item)) != null ? _a2 : "Other";
5813
6714
  if (Object.prototype.hasOwnProperty.call(result, cat)) result[cat]++;
5814
6715
  else result["Other"] = (result["Other"] || 0) + 1;
5815
6716
  });
@@ -5817,17 +6718,17 @@ ${schemaProfileText}` : ""}`;
5817
6718
  }
5818
6719
  static extractTimeSeriesData(data) {
5819
6720
  return data.map((item) => {
5820
- var _a, _b, _c, _d, _e;
6721
+ var _a2, _b, _c, _d, _e;
5821
6722
  const meta = item.metadata || {};
5822
6723
  return {
5823
- timestamp: (_b = (_a = meta.timestamp) != null ? _a : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
6724
+ timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
5824
6725
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
5825
6726
  label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
5826
6727
  };
5827
6728
  });
5828
6729
  }
5829
6730
  static extractNumericValue(meta) {
5830
- var _a;
6731
+ var _a2;
5831
6732
  const preferredKeys = [
5832
6733
  "value",
5833
6734
  "count",
@@ -5842,7 +6743,7 @@ ${schemaProfileText}` : ""}`;
5842
6743
  "price"
5843
6744
  ];
5844
6745
  for (const key of preferredKeys) {
5845
- const raw = (_a = resolveMetadataValue(meta, key)) != null ? _a : meta[key];
6746
+ const raw = (_a2 = resolveMetadataValue(meta, key)) != null ? _a2 : meta[key];
5846
6747
  const value = typeof raw === "number" ? raw : Number(String(raw != null ? raw : "").replace(/[$,% ,]/g, ""));
5847
6748
  if (Number.isFinite(value)) return value;
5848
6749
  }
@@ -5988,8 +6889,8 @@ ${schemaProfileText}` : ""}`;
5988
6889
  let inStock = 0;
5989
6890
  let outOfStock = 0;
5990
6891
  data.forEach((d) => {
5991
- var _a, _b;
5992
- const cat = (_a = this.getProductCategory(d)) != null ? _a : "Other";
6892
+ var _a2, _b;
6893
+ const cat = (_a2 = this.getProductCategory(d)) != null ? _a2 : "Other";
5993
6894
  if (cat === category) {
5994
6895
  const quantity = (_b = this.extractStockQuantity(d)) != null ? _b : 1;
5995
6896
  if (this.determineStockStatus(d)) inStock += quantity;
@@ -6033,9 +6934,9 @@ ${schemaProfileText}` : ""}`;
6033
6934
  }
6034
6935
  // ─── Product Extraction ───────────────────────────────────────────────────
6035
6936
  static getDynamicVal(meta, uiKey, config, trainedSchema) {
6036
- var _a;
6937
+ var _a2;
6037
6938
  if (!meta) return void 0;
6038
- const mapping = (_a = config == null ? void 0 : config.rag) == null ? void 0 : _a.uiMapping;
6939
+ const mapping = (_a2 = config == null ? void 0 : config.rag) == null ? void 0 : _a2.uiMapping;
6039
6940
  if ((mapping == null ? void 0 : mapping[uiKey]) && meta[mapping[uiKey]] !== void 0) return meta[mapping[uiKey]];
6040
6941
  if (trainedSchema && typeof trainedSchema === "object") {
6041
6942
  const trainedKey = trainedSchema[uiKey];
@@ -6044,13 +6945,13 @@ ${schemaProfileText}` : ""}`;
6044
6945
  return resolveMetadataValue(meta, uiKey);
6045
6946
  }
6046
6947
  static extractProductInfo(item, config, trainedSchema) {
6047
- var _a;
6948
+ var _a2;
6048
6949
  const meta = item.metadata || {};
6049
6950
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
6050
6951
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
6051
6952
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
6052
6953
  const description = this.cleanProductDescription(
6053
- (_a = this.extractProductDescriptionFromContent(item.content)) != null ? _a : this.getProductDescriptionValue(meta, config, trainedSchema)
6954
+ (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
6054
6955
  );
6055
6956
  if (name || this.isProductData(item)) {
6056
6957
  let finalName = name ? String(name) : void 0;
@@ -6158,10 +7059,10 @@ RULES:
6158
7059
  }
6159
7060
  static buildContextSummary(sources, maxChars = 6e3) {
6160
7061
  const items = sources.map((s, i) => {
6161
- var _a, _b, _c, _d;
7062
+ var _a2, _b, _c, _d;
6162
7063
  return {
6163
7064
  index: i + 1,
6164
- content: (_b = (_a = s.content) == null ? void 0 : _a.substring(0, 400)) != null ? _b : "",
7065
+ content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
6165
7066
  metadata: (_c = s.metadata) != null ? _c : {},
6166
7067
  score: (_d = s.score) != null ? _d : 0
6167
7068
  };
@@ -6354,9 +7255,11 @@ var Pipeline = class {
6354
7255
  /** LRU-bounded cache: avoids re-embedding identical queries within the same process. */
6355
7256
  this.embeddingCache = new LRUEmbeddingCache(500);
6356
7257
  this.initialised = false;
6357
- var _a, _b, _c, _d, _e;
7258
+ /** Namespace-specific static cold context cache for CAG */
7259
+ this.coldContexts = /* @__PURE__ */ new Map();
7260
+ var _a2, _b, _c, _d, _e;
6358
7261
  this.chunker = new DocumentChunker(
6359
- (_b = (_a = config.rag) == null ? void 0 : _a.chunkSize) != null ? _b : 1e3,
7262
+ (_b = (_a2 = config.rag) == null ? void 0 : _a2.chunkSize) != null ? _b : 1e3,
6360
7263
  (_d = (_c = config.rag) == null ? void 0 : _c.chunkOverlap) != null ? _d : 200
6361
7264
  );
6362
7265
  if (((_e = config.rag) == null ? void 0 : _e.chunkingStrategy) === "llamaindex") {
@@ -6372,7 +7275,7 @@ var Pipeline = class {
6372
7275
  return this.initialised ? this.llmProvider : void 0;
6373
7276
  }
6374
7277
  async initialize() {
6375
- var _a;
7278
+ var _a2, _b, _c;
6376
7279
  if (this.initialised) return;
6377
7280
  const chartInstruction = `You are a helpful assistant. Use the provided context to answer questions accurately.
6378
7281
 
@@ -6415,12 +7318,47 @@ var Pipeline = class {
6415
7318
  this.entityExtractor = new EntityExtractor(this.llmProvider);
6416
7319
  }
6417
7320
  await this.vectorDB.initialize();
6418
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic") {
7321
+ if (((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) {
7322
+ this.mcpRegistry = new MCPRegistry(this.config.mcpServers || []);
7323
+ this.multiAgentCoordinator = new MultiAgentCoordinator({
7324
+ llmProvider: this.llmProvider,
7325
+ mcpRegistry: this.mcpRegistry,
7326
+ documentSearch: async (query) => {
7327
+ return this.runNormalQuery(query);
7328
+ }
7329
+ });
6419
7330
  this.agent = new LangChainAgent(this, this.config);
6420
7331
  await this.agent.initialize(this.llmProvider);
6421
7332
  }
7333
+ if ((_c = (_b = this.config.rag) == null ? void 0 : _b.cag) == null ? void 0 : _c.enabled) {
7334
+ await this.loadColdContext(this.config.projectId);
7335
+ }
6422
7336
  this.initialised = true;
6423
7337
  }
7338
+ async loadColdContext(ns) {
7339
+ var _a2, _b;
7340
+ const cagConfig = (_a2 = this.config.rag) == null ? void 0 : _a2.cag;
7341
+ if (!cagConfig || !cagConfig.enabled) return;
7342
+ try {
7343
+ const coldNs = cagConfig.coldNamespace || ns;
7344
+ const limit = (_b = cagConfig.coldLimit) != null ? _b : 20;
7345
+ const queryText = cagConfig.coldQuery || "documentation";
7346
+ const queryVector = await this.embeddingProvider.embed(queryText, { taskType: "query" });
7347
+ const coldMatches = await this.vectorDB.query(queryVector, limit, coldNs);
7348
+ if (coldMatches.length > 0) {
7349
+ const formatted = coldMatches.map((m, i) => `[Cold Source ${i + 1}]
7350
+ ${m.content}`).join("\n\n---\n\n");
7351
+ this.coldContexts.set(ns, formatted);
7352
+ console.log(`[Pipeline] Cold RAG (CAG) loaded ${coldMatches.length} documents into cached context for namespace: ${ns}`);
7353
+ } else {
7354
+ this.coldContexts.set(ns, "No cold context found.");
7355
+ console.warn(`[Pipeline] Cold RAG (CAG) initialized but no documents were found in namespace: ${coldNs}`);
7356
+ }
7357
+ } catch (err) {
7358
+ console.error(`[Pipeline] Failed to load Cold RAG (CAG) context for namespace ${ns}:`, err);
7359
+ this.coldContexts.set(ns, "Failed to load cold context.");
7360
+ }
7361
+ }
6424
7362
  /**
6425
7363
  * Ingest documents with automatic chunking, embedding, and batch upsert.
6426
7364
  */
@@ -6452,12 +7390,12 @@ var Pipeline = class {
6452
7390
  }
6453
7391
  /** Step 1: Chunk the document content. */
6454
7392
  async prepareChunks(doc) {
6455
- var _a, _b;
7393
+ var _a2, _b;
6456
7394
  if (this.llamaIngestor) {
6457
7395
  return this.llamaIngestor.chunk(doc.content, {
6458
7396
  docId: doc.docId,
6459
7397
  metadata: doc.metadata,
6460
- chunkSize: (_a = this.config.rag) == null ? void 0 : _a.chunkSize,
7398
+ chunkSize: (_a2 = this.config.rag) == null ? void 0 : _a2.chunkSize,
6461
7399
  chunkOverlap: (_b = this.config.rag) == null ? void 0 : _b.chunkOverlap
6462
7400
  });
6463
7401
  }
@@ -6528,12 +7466,37 @@ var Pipeline = class {
6528
7466
  extractionOptions
6529
7467
  );
6530
7468
  }
7469
+ async runNormalQuery(question, history = [], namespace) {
7470
+ const stream = this.askStreamInternal(question, history, namespace);
7471
+ let reply = "";
7472
+ let sources = [];
7473
+ try {
7474
+ for (var iter = __forAwait(stream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
7475
+ const chunk = temp.value;
7476
+ if (typeof chunk === "string") {
7477
+ reply += chunk;
7478
+ } else if (typeof chunk === "object" && chunk !== null) {
7479
+ if ("reply" in chunk && chunk.reply) reply += chunk.reply;
7480
+ if ("sources" in chunk && chunk.sources) sources = chunk.sources;
7481
+ }
7482
+ }
7483
+ } catch (temp) {
7484
+ error = [temp];
7485
+ } finally {
7486
+ try {
7487
+ more && (temp = iter.return) && await temp.call(iter);
7488
+ } finally {
7489
+ if (error)
7490
+ throw error[0];
7491
+ }
7492
+ }
7493
+ return { reply, sources };
7494
+ }
6531
7495
  async ask(question, history = [], namespace) {
6532
- var _a;
7496
+ var _a2;
6533
7497
  await this.initialize();
6534
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic" && this.agent) {
6535
- const agentReply = await this.agent.run(question, history);
6536
- return { reply: agentReply, sources: [] };
7498
+ if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
7499
+ return await this.multiAgentCoordinator.run(question, history);
6537
7500
  }
6538
7501
  const stream = this.askStream(question, history, namespace);
6539
7502
  let reply = "";
@@ -6565,6 +7528,47 @@ var Pipeline = class {
6565
7528
  }
6566
7529
  return { reply, sources, graphData, ui_transformation: uiTransformation, trace };
6567
7530
  }
7531
+ askStream(_0) {
7532
+ return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
7533
+ var _a2;
7534
+ yield new __await(this.initialize());
7535
+ if ((((_a2 = this.config.rag) == null ? void 0 : _a2.architecture) === "agentic" || this.config.mcpServers && this.config.mcpServers.length > 0) && this.multiAgentCoordinator) {
7536
+ const stream2 = this.multiAgentCoordinator.runStream(question, history);
7537
+ try {
7538
+ for (var iter = __forAwait(stream2), more, temp, error; more = !(temp = yield new __await(iter.next())).done; more = false) {
7539
+ const chunk = temp.value;
7540
+ yield chunk;
7541
+ }
7542
+ } catch (temp) {
7543
+ error = [temp];
7544
+ } finally {
7545
+ try {
7546
+ more && (temp = iter.return) && (yield new __await(temp.call(iter)));
7547
+ } finally {
7548
+ if (error)
7549
+ throw error[0];
7550
+ }
7551
+ }
7552
+ return;
7553
+ }
7554
+ const stream = this.askStreamInternal(question, history, namespace);
7555
+ try {
7556
+ for (var iter2 = __forAwait(stream), more2, temp2, error2; more2 = !(temp2 = yield new __await(iter2.next())).done; more2 = false) {
7557
+ const chunk = temp2.value;
7558
+ yield chunk;
7559
+ }
7560
+ } catch (temp2) {
7561
+ error2 = [temp2];
7562
+ } finally {
7563
+ try {
7564
+ more2 && (temp2 = iter2.return) && (yield new __await(temp2.call(iter2)));
7565
+ } finally {
7566
+ if (error2)
7567
+ throw error2[0];
7568
+ }
7569
+ }
7570
+ });
7571
+ }
6568
7572
  /**
6569
7573
  * High-performance streaming RAG flow.
6570
7574
  * Yields text chunks first, then the retrieval metadata + observability trace at the end.
@@ -6575,12 +7579,12 @@ var Pipeline = class {
6575
7579
  * - UITransformation is computed after text streaming and emitted with metadata
6576
7580
  * - SchemaMapper.train runs while answer generation streams
6577
7581
  */
6578
- askStream(_0) {
7582
+ askStreamInternal(_0) {
6579
7583
  return __asyncGenerator(this, arguments, function* (question, history = [], namespace) {
6580
- var _a, _b, _c, _d, _e, _f, _g, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v;
7584
+ var _a2, _b, _c, _d, _e, _f, _g2, _h, _i, _j, _k, _l, _m, _n, _o, _p, _q, _r, _s, _t, _u, _v, _w, _x, _y, _z;
6581
7585
  yield new __await(this.initialize());
6582
7586
  const ns = namespace != null ? namespace : this.config.projectId;
6583
- const topK = (_b = (_a = this.config.rag) == null ? void 0 : _a.topK) != null ? _b : 5;
7587
+ const topK = (_b = (_a2 = this.config.rag) == null ? void 0 : _a2.topK) != null ? _b : 5;
6584
7588
  const scoreThreshold = (_d = (_c = this.config.rag) == null ? void 0 : _c.scoreThreshold) != null ? _d : 0.3;
6585
7589
  const requestId = `req_${Date.now()}_${Math.random().toString(36).slice(2, 8)}`;
6586
7590
  const requestStart = performance.now();
@@ -6593,7 +7597,7 @@ var Pipeline = class {
6593
7597
  }
6594
7598
  const hints = QueryProcessor.extractQueryFieldHints(question, (_f = this.config.rag) == null ? void 0 : _f.filterableFields);
6595
7599
  const filter = QueryProcessor.buildQueryFilter(question, hints);
6596
- const numericPredicates = QueryProcessor.extractNumericPredicates(question, (_g = this.config.rag) == null ? void 0 : _g.filterableFields);
7600
+ const numericPredicates = QueryProcessor.extractNumericPredicates(question, (_g2 = this.config.rag) == null ? void 0 : _g2.filterableFields);
6597
7601
  if (numericPredicates.length > 0) {
6598
7602
  filter.__numericPredicates = numericPredicates;
6599
7603
  }
@@ -6659,6 +7663,32 @@ ${graphContext}
6659
7663
  VECTOR CONTEXT:
6660
7664
  ${context}`;
6661
7665
  }
7666
+ if ((_n = (_m = this.config.rag) == null ? void 0 : _m.cag) == null ? void 0 : _n.enabled) {
7667
+ if (!this.coldContexts.has(ns)) {
7668
+ yield new __await(this.loadColdContext(ns));
7669
+ }
7670
+ const coldContext = this.coldContexts.get(ns);
7671
+ if (coldContext && coldContext !== "No cold context found." && coldContext !== "Failed to load cold context.") {
7672
+ context = `COLD CONTEXT (STATIC KNOWLEDGE):
7673
+ ${coldContext}
7674
+
7675
+ RETRIEVED HOT CONTEXT (REAL-TIME KNOWLEDGE):
7676
+ ${context}`;
7677
+ }
7678
+ }
7679
+ yield {
7680
+ reply: "",
7681
+ sources: sources.map((s) => {
7682
+ var _a3;
7683
+ return {
7684
+ id: s.id,
7685
+ score: s.score,
7686
+ content: s.content,
7687
+ metadata: (_a3 = s.metadata) != null ? _a3 : {},
7688
+ namespace: ns
7689
+ };
7690
+ })
7691
+ };
6662
7692
  const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
6663
7693
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
6664
7694
  if (allMetadataKeys.length > 0 && !cachedSchema) {
@@ -6686,10 +7716,10 @@ ${context}`;
6686
7716
  let hallucinationScoringPromise = Promise.resolve(void 0);
6687
7717
  const restrictionSuffix = "\n\n(IMPORTANT: Format your response beautifully using rich Markdown! Use bolding for emphasis, headings (##) for structure, bullet points for lists, and proper line breaks between paragraphs to make it highly readable. However, NEVER generate Markdown tables, HTML figures, or text charts (the UI renders requested charts separately, so NEVER say you cannot create, display, draw, render, or provide a chart/visualization). If listing products, use simple markdown bullet points or comma-separated names. NEVER use plus signs (+) to separate product names, category names, or list items. For product description/detail questions, provide customer-facing prose only and do NOT list internal catalog fields such as Handle, Body (HTML), Vendor, Type, Tags, Published, Option, Variant, SKU, or raw metadata labels. You CAN use numbers for years/counts like 2006 or 5800, but NEVER put a dollar sign ($) before them.)";
6688
7718
  const isClaude37 = this.config.llm.model.includes("claude-3-7-sonnet");
6689
- const isNativeThinking = isClaude37 && (((_m = this.config.llm.options) == null ? void 0 : _m.thinking) === true || ((_n = this.config.llm.options) == null ? void 0 : _n.thinking) === "enabled" || ((_o = this.config.llm.options) == null ? void 0 : _o.thinking) !== false);
7719
+ const isNativeThinking = isClaude37 && (((_o = this.config.llm.options) == null ? void 0 : _o.thinking) === true || ((_p = this.config.llm.options) == null ? void 0 : _p.thinking) === "enabled" || ((_q = this.config.llm.options) == null ? void 0 : _q.thinking) !== false);
6690
7720
  const modelNameLower = this.config.llm.model.toLowerCase();
6691
7721
  const isReasoningModel = modelNameLower.includes("-r1") || modelNameLower.includes("deepseek-r1") || modelNameLower.includes("reasoning") || modelNameLower.includes("thinking");
6692
- const isSimulatedThinking = !isNativeThinking && (((_p = this.config.llm.options) == null ? void 0 : _p.thinking) === true || ((_q = this.config.llm.options) == null ? void 0 : _q.thinking) === "enabled" || isReasoningModel && ((_r = this.config.llm.options) == null ? void 0 : _r.thinking) !== false);
7722
+ const isSimulatedThinking = !isNativeThinking && (((_r = this.config.llm.options) == null ? void 0 : _r.thinking) === true || ((_s = this.config.llm.options) == null ? void 0 : _s.thinking) === "enabled" || isReasoningModel && ((_t = this.config.llm.options) == null ? void 0 : _t.thinking) !== false);
6693
7723
  let finalRestrictionSuffix = restrictionSuffix;
6694
7724
  if (isSimulatedThinking) {
6695
7725
  finalRestrictionSuffix += "\n\n(IMPORTANT: You must think step-by-step before answering. Write your thinking process inside a `<think>...</think>` block. Write the `<think>` block first, then follow it with your final response. Keep the thinking process thorough and detailed. Example: `<think>Thinking details here...</think>Final answer text here.`)";
@@ -6697,7 +7727,7 @@ ${context}`;
6697
7727
  const hardenedHistory = [...history];
6698
7728
  const userQuestion = { role: "user", content: question + finalRestrictionSuffix };
6699
7729
  const messages = [...hardenedHistory, userQuestion];
6700
- const systemPrompt = (_s = this.config.llm.systemPrompt) != null ? _s : "";
7730
+ const systemPrompt = (_u = this.config.llm.systemPrompt) != null ? _u : "";
6701
7731
  const userPrompt = messages.map((m) => `${m.role}: ${m.content}`).join("\n");
6702
7732
  let fullReply = "";
6703
7733
  let thinkingText = "";
@@ -6808,7 +7838,7 @@ ${context}`;
6808
7838
  }
6809
7839
  yield fullReply;
6810
7840
  }
6811
- const runHallucination = ((_t = this.config.llm.options) == null ? void 0 : _t.hallucinationScoring) === true || this.config.llm.provider !== "ollama" && ((_u = this.config.llm.options) == null ? void 0 : _u.hallucinationScoring) !== false;
7841
+ const runHallucination = ((_v = this.config.llm.options) == null ? void 0 : _v.hallucinationScoring) === true || this.config.llm.provider !== "ollama" && ((_w = this.config.llm.options) == null ? void 0 : _w.hallucinationScoring) !== false;
6812
7842
  if (runHallucination) {
6813
7843
  hallucinationScoringPromise = scoreHallucination(this.llmProvider, fullReply, context).catch(() => void 0);
6814
7844
  }
@@ -6817,7 +7847,7 @@ ${context}`;
6817
7847
  const latency = {
6818
7848
  embedMs: Math.round(embedMs),
6819
7849
  retrieveMs: Math.round(retrieveMs),
6820
- rerankMs: ((_v = this.config.rag) == null ? void 0 : _v.useReranking) ? Math.round(rerankMs) : void 0,
7850
+ rerankMs: ((_x = this.config.rag) == null ? void 0 : _x.useReranking) ? Math.round(rerankMs) : void 0,
6821
7851
  generateMs: Math.round(generateMs),
6822
7852
  totalMs: Math.round(totalMs)
6823
7853
  };
@@ -6830,33 +7860,63 @@ ${context}`;
6830
7860
  totalTokens: promptTokens + completionTokens,
6831
7861
  estimatedCostUsd: estimateCostUsd(promptTokens, completionTokens, this.config.llm.model)
6832
7862
  };
7863
+ const awaitHallucination = ((_y = this.config.llm.options) == null ? void 0 : _y.awaitHallucination) === true;
6833
7864
  const [uiTransformation, hallucinationResult] = yield new __await(Promise.all([
6834
7865
  uiTransformationPromise,
6835
- hallucinationScoringPromise
7866
+ awaitHallucination ? hallucinationScoringPromise : Promise.resolve(void 0)
6836
7867
  ]));
6837
- const trace = __spreadValues({
7868
+ const buildTrace = (hScore) => __spreadValues({
6838
7869
  requestId,
6839
7870
  query: question,
6840
7871
  rewrittenQuery,
6841
7872
  systemPrompt,
6842
7873
  userPrompt: question + finalRestrictionSuffix,
6843
7874
  chunks: sources.map((s) => {
6844
- var _a2;
7875
+ var _a3;
6845
7876
  return {
6846
7877
  id: s.id,
6847
7878
  score: s.score,
6848
7879
  content: s.content,
6849
- metadata: (_a2 = s.metadata) != null ? _a2 : {},
7880
+ metadata: (_a3 = s.metadata) != null ? _a3 : {},
6850
7881
  namespace: ns
6851
7882
  };
6852
7883
  }),
6853
7884
  latency,
6854
7885
  tokens,
6855
7886
  timestamp: (/* @__PURE__ */ new Date()).toISOString()
6856
- }, hallucinationResult ? {
6857
- hallucinationScore: hallucinationResult.score,
6858
- hallucinationReason: hallucinationResult.reason
7887
+ }, hScore ? {
7888
+ hallucinationScore: hScore.score,
7889
+ hallucinationReason: hScore.reason
6859
7890
  } : {});
7891
+ const trace = buildTrace(hallucinationResult);
7892
+ if ((_z = this.config.telemetry) == null ? void 0 : _z.enabled) {
7893
+ const telemetryUrl = this.config.telemetry.url || "/api/telemetry";
7894
+ const absoluteUrl = telemetryUrl.startsWith("http") ? telemetryUrl : (process.env.NEXT_PUBLIC_APP_URL || `http://localhost:${process.env.PORT || 3e3}`) + telemetryUrl;
7895
+ (async () => {
7896
+ try {
7897
+ let finalTrace = trace;
7898
+ if (!awaitHallucination && runHallucination) {
7899
+ const backgroundScoreResult = await hallucinationScoringPromise;
7900
+ if (backgroundScoreResult) {
7901
+ finalTrace = buildTrace(backgroundScoreResult);
7902
+ }
7903
+ }
7904
+ await fetch(absoluteUrl, {
7905
+ method: "POST",
7906
+ headers: {
7907
+ "Content-Type": "application/json"
7908
+ },
7909
+ body: JSON.stringify({
7910
+ trace: finalTrace,
7911
+ licenseKey: this.config.licenseKey,
7912
+ projectId: ns
7913
+ })
7914
+ });
7915
+ } catch (err) {
7916
+ console.warn(`[Pipeline Telemetry] Failed to send trace async to ${absoluteUrl}:`, err.message);
7917
+ }
7918
+ })();
7919
+ }
6860
7920
  yield {
6861
7921
  reply: "",
6862
7922
  sources,
@@ -6876,7 +7936,7 @@ ${context}`;
6876
7936
  * Uses an LRU-bounded embedding cache to avoid re-embedding the same query.
6877
7937
  */
6878
7938
  async generateUiTransformation(question, sources, cachedSchema, forceDeterministic = false) {
6879
- var _a;
7939
+ var _a2;
6880
7940
  if (!sources || sources.length === 0) {
6881
7941
  return UITransformer.transform(question, sources, this.config, cachedSchema);
6882
7942
  }
@@ -6890,7 +7950,7 @@ ${context}`;
6890
7950
  );
6891
7951
  }
6892
7952
  const isLocalProvider = this.config.llm.provider === "ollama";
6893
- const disableLlmUiTransform = ((_a = this.config.llm.options) == null ? void 0 : _a.disableLlmUiTransform) === true;
7953
+ const disableLlmUiTransform = ((_a2 = this.config.llm.options) == null ? void 0 : _a2.disableLlmUiTransform) === true;
6894
7954
  if (forceDeterministic || isLocalProvider || disableLlmUiTransform) {
6895
7955
  return UITransformer.transform(question, sources, this.config, cachedSchema);
6896
7956
  }
@@ -6908,9 +7968,9 @@ ${context}`;
6908
7968
  const value = this.resolveNumericPredicateValue(source, predicate);
6909
7969
  return value !== null && this.matchesNumericPredicate(value, predicate);
6910
7970
  })).sort((a, b) => {
6911
- var _a, _b;
7971
+ var _a2, _b;
6912
7972
  const primary = predicates[0];
6913
- const aValue = (_a = this.resolveNumericPredicateValue(a, primary)) != null ? _a : 0;
7973
+ const aValue = (_a2 = this.resolveNumericPredicateValue(a, primary)) != null ? _a2 : 0;
6914
7974
  const bValue = (_b = this.resolveNumericPredicateValue(b, primary)) != null ? _b : 0;
6915
7975
  return primary.operator === "lt" || primary.operator === "lte" ? aValue - bValue : bValue - aValue;
6916
7976
  });
@@ -6982,8 +8042,8 @@ ${context}`;
6982
8042
  return Number.isFinite(numeric) ? numeric : null;
6983
8043
  }
6984
8044
  async retrieve(query, options) {
6985
- var _a, _b, _c, _d, _e, _f, _g;
6986
- const ns = (_a = options.namespace) != null ? _a : this.config.projectId;
8045
+ var _a2, _b, _c, _d, _e, _f, _g2;
8046
+ const ns = (_a2 = options.namespace) != null ? _a2 : this.config.projectId;
6987
8047
  const topK = (_b = options.topK) != null ? _b : 5;
6988
8048
  const cacheKey = `${ns}::${query}`;
6989
8049
  let queryVector = this.embeddingCache.get(cacheKey);
@@ -7015,7 +8075,7 @@ ${context}`;
7015
8075
  ) : [];
7016
8076
  const resolvedSources = [];
7017
8077
  for (const source of sources) {
7018
- const parentId = (_g = source.metadata) == null ? void 0 : _g.parent_id;
8078
+ const parentId = (_g2 = source.metadata) == null ? void 0 : _g2.parent_id;
7019
8079
  if (parentId) {
7020
8080
  console.log(`[Pipeline] Multi-Vector: Found child chunk. Parent ID: ${parentId}`);
7021
8081
  resolvedSources.push(source);
@@ -7097,8 +8157,14 @@ var Retrivora = class {
7097
8157
  this.pipeline = new Pipeline(this.config);
7098
8158
  }
7099
8159
  async initialize() {
8160
+ var _a2;
7100
8161
  try {
7101
8162
  await ConfigValidator.validateAndThrow(this.config);
8163
+ LicenseVerifier.verify(
8164
+ this.config.licenseKey,
8165
+ this.config.projectId,
8166
+ (_a2 = this.config.vectorDb) == null ? void 0 : _a2.provider
8167
+ );
7102
8168
  } catch (err) {
7103
8169
  throw wrapError(err, "CONFIGURATION_ERROR");
7104
8170
  }
@@ -7272,11 +8338,20 @@ var ProviderHealthCheck = class {
7272
8338
  // src/core/VectorPlugin.ts
7273
8339
  var VectorPlugin = class {
7274
8340
  constructor(hostConfig) {
7275
- this.config = ConfigResolver.resolve(hostConfig);
7276
- this.validationPromise = ConfigValidator.validateAndThrow(this.config);
8341
+ const resolvedConfig = ConfigResolver.resolve(hostConfig);
8342
+ this.config = resolvedConfig;
8343
+ this.validationPromise = (async () => {
8344
+ var _a2;
8345
+ await ConfigValidator.validateAndThrow(resolvedConfig);
8346
+ LicenseVerifier.verify(
8347
+ resolvedConfig.licenseKey,
8348
+ resolvedConfig.projectId,
8349
+ (_a2 = resolvedConfig.vectorDb) == null ? void 0 : _a2.provider
8350
+ );
8351
+ })();
7277
8352
  this.validationPromise.catch(() => {
7278
8353
  });
7279
- this.pipeline = new Pipeline(this.config);
8354
+ this.pipeline = new Pipeline(resolvedConfig);
7280
8355
  }
7281
8356
  /**
7282
8357
  * Get the current resolved configuration.
@@ -7412,13 +8487,13 @@ var ConfigBuilder = class {
7412
8487
  * Configure the vector database provider
7413
8488
  */
7414
8489
  vectorDb(provider, options) {
7415
- var _a;
8490
+ var _a2;
7416
8491
  if (provider === "auto") {
7417
8492
  this._vectorDb = this._autoDetectVectorDb();
7418
8493
  } else {
7419
8494
  this._vectorDb = {
7420
8495
  provider,
7421
- indexName: (_a = options == null ? void 0 : options.indexName) != null ? _a : "default",
8496
+ indexName: (_a2 = options == null ? void 0 : options.indexName) != null ? _a2 : "default",
7422
8497
  options: __spreadValues({}, options)
7423
8498
  };
7424
8499
  }
@@ -7428,7 +8503,7 @@ var ConfigBuilder = class {
7428
8503
  * Configure the LLM provider for chat
7429
8504
  */
7430
8505
  llm(provider, model, apiKey, options) {
7431
- var _a, _b;
8506
+ var _a2, _b;
7432
8507
  if (provider === "auto") {
7433
8508
  this._llm = this._autoDetectLLM();
7434
8509
  } else {
@@ -7437,7 +8512,7 @@ var ConfigBuilder = class {
7437
8512
  model: model != null ? model : "default-model",
7438
8513
  apiKey,
7439
8514
  systemPrompt: options == null ? void 0 : options.systemPrompt,
7440
- maxTokens: (_a = options == null ? void 0 : options.maxTokens) != null ? _a : 1024,
8515
+ maxTokens: (_a2 = options == null ? void 0 : options.maxTokens) != null ? _a2 : 1024,
7441
8516
  temperature: (_b = options == null ? void 0 : options.temperature) != null ? _b : 0.7,
7442
8517
  baseUrl: options == null ? void 0 : options.baseUrl,
7443
8518
  options
@@ -7480,8 +8555,8 @@ var ConfigBuilder = class {
7480
8555
  * Set RAG-specific pipeline parameters
7481
8556
  */
7482
8557
  rag(options) {
7483
- var _a;
7484
- this._rag = __spreadValues(__spreadValues({}, (_a = this._rag) != null ? _a : {}), options);
8558
+ var _a2;
8559
+ this._rag = __spreadValues(__spreadValues({}, (_a2 = this._rag) != null ? _a2 : {}), options);
7485
8560
  return this;
7486
8561
  }
7487
8562
  /**
@@ -7497,7 +8572,7 @@ var ConfigBuilder = class {
7497
8572
  * Throws if required fields (projectId, vectorDb, llm, embedding) are not set.
7498
8573
  */
7499
8574
  build() {
7500
- var _a;
8575
+ var _a2;
7501
8576
  const missing = [];
7502
8577
  if (!this._projectId) missing.push('projectId (call .projectId("my-app"))');
7503
8578
  if (!this._vectorDb) missing.push('vectorDb (call .vectorDb("pinecone", { ... }))');
@@ -7509,7 +8584,7 @@ var ConfigBuilder = class {
7509
8584
  ${missing.join("\n ")}`
7510
8585
  );
7511
8586
  }
7512
- const ragConfig = (_a = this._rag) != null ? _a : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
8587
+ const ragConfig = (_a2 = this._rag) != null ? _a2 : { chunkSize: 1e3, chunkOverlap: 200, topK: 5 };
7513
8588
  if (process.env.RAG_USE_GRAPH_RETRIEVAL === "true") {
7514
8589
  ragConfig.useGraphRetrieval = true;
7515
8590
  }
@@ -7605,8 +8680,8 @@ var DocumentParser = class {
7605
8680
  * Extract text from a File or Buffer based on its type.
7606
8681
  */
7607
8682
  static async parse(file, fileName, mimeType) {
7608
- var _a;
7609
- const extension = (_a = fileName.split(".").pop()) == null ? void 0 : _a.toLowerCase();
8683
+ var _a2;
8684
+ const extension = (_a2 = fileName.split(".").pop()) == null ? void 0 : _a2.toLowerCase();
7610
8685
  if (extension === "txt" || extension === "md" || mimeType === "text/plain" || mimeType === "text/markdown") {
7611
8686
  return this.readAsText(file);
7612
8687
  }
@@ -7673,6 +8748,497 @@ init_UniversalVectorProvider();
7673
8748
 
7674
8749
  // src/handlers/index.ts
7675
8750
  import { NextResponse } from "next/server";
8751
+
8752
+ // src/core/DatabaseStorage.ts
8753
+ import * as fs from "fs";
8754
+ import * as path from "path";
8755
+ var DatabaseStorage = class {
8756
+ constructor(config) {
8757
+ // Dynamic PG Pool
8758
+ this.pgPool = null;
8759
+ // Dynamic MongoDB Client
8760
+ this.mongoClient = null;
8761
+ this.mongoDbName = "";
8762
+ // Filesystem fallback configuration
8763
+ this.fallbackDir = path.join(process.cwd(), ".retrivora");
8764
+ this.historyFile = path.join(this.fallbackDir, "history.json");
8765
+ this.feedbackFile = path.join(this.fallbackDir, "feedback.json");
8766
+ var _a2, _b, _c, _d, _e;
8767
+ this.config = config;
8768
+ this.provider = ((_a2 = config.vectorDb) == null ? void 0 : _a2.provider) || "fs";
8769
+ const rawHistoryTable = ((_c = (_b = config.rag) == null ? void 0 : _b.history) == null ? void 0 : _c.tableName) || "retrivora_history";
8770
+ const rawFeedbackTable = ((_e = (_d = config.rag) == null ? void 0 : _d.feedback) == null ? void 0 : _e.tableName) || "retrivora_feedback";
8771
+ this.historyTableName = rawHistoryTable.replace(/[^a-zA-Z0-9_]/g, "_");
8772
+ this.feedbackTableName = rawFeedbackTable.replace(/[^a-zA-Z0-9_]/g, "_");
8773
+ }
8774
+ /**
8775
+ * Asserts the user is running a valid Premium/Enterprise license in production.
8776
+ * In non-production (development / test) environments this is a complete no-op —
8777
+ * all History and Feedback features are freely accessible for local development.
8778
+ */
8779
+ checkPremiumSubscription() {
8780
+ if (process.env.NODE_ENV !== "production") {
8781
+ return;
8782
+ }
8783
+ if (!this.config.licenseKey) {
8784
+ throw new Error(
8785
+ "[Retrivora SDK] Chat History and Feedback features require a Premium or Enterprise license key in production."
8786
+ );
8787
+ }
8788
+ try {
8789
+ const payload = LicenseVerifier.verify(this.config.licenseKey, this.config.projectId);
8790
+ const tier = (payload.tier || "").toLowerCase();
8791
+ if (tier !== "premium" && tier !== "enterprise" && tier !== "growth" && tier !== "pro" && tier !== "developer_pro") {
8792
+ throw new Error(
8793
+ `[Retrivora SDK] Chat History and Feedback features are not available on the "${tier}" tier. Please upgrade to a Developer Pro or Enterprise plan.`
8794
+ );
8795
+ }
8796
+ } catch (err) {
8797
+ throw new Error(
8798
+ `[Retrivora SDK] Subscription check failed: ${err instanceof Error ? err.message : String(err)}`
8799
+ );
8800
+ }
8801
+ }
8802
+ checkHistoryEnabled() {
8803
+ var _a2, _b;
8804
+ this.checkPremiumSubscription();
8805
+ if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.history) == null ? void 0 : _b.enabled) === false) {
8806
+ throw new Error("[Retrivora SDK] Chat History is disabled in RagConfig.");
8807
+ }
8808
+ }
8809
+ checkFeedbackEnabled() {
8810
+ var _a2, _b;
8811
+ this.checkPremiumSubscription();
8812
+ if (((_b = (_a2 = this.config.rag) == null ? void 0 : _a2.feedback) == null ? void 0 : _b.enabled) === false) {
8813
+ throw new Error("[Retrivora SDK] User Feedback is disabled in RagConfig.");
8814
+ }
8815
+ }
8816
+ async getPGPool() {
8817
+ const globalKey = `__retrivora_pg_pool_${this.config.projectId}`;
8818
+ const _g2 = global;
8819
+ if (_g2[globalKey]) {
8820
+ this.pgPool = _g2[globalKey];
8821
+ return this.pgPool;
8822
+ }
8823
+ const opts = this.config.vectorDb.options;
8824
+ if (!opts.connectionString) {
8825
+ throw new Error("[DatabaseStorage] pg connectionString option is missing.");
8826
+ }
8827
+ const { Pool: Pool3 } = await import("pg");
8828
+ this.pgPool = new Pool3({ connectionString: opts.connectionString });
8829
+ _g2[globalKey] = this.pgPool;
8830
+ const client = await this.pgPool.connect();
8831
+ try {
8832
+ await client.query(`
8833
+ CREATE TABLE IF NOT EXISTS ${this.historyTableName} (
8834
+ id TEXT PRIMARY KEY,
8835
+ session_id TEXT NOT NULL,
8836
+ role TEXT NOT NULL,
8837
+ content TEXT NOT NULL,
8838
+ sources JSONB,
8839
+ ui_transformation JSONB,
8840
+ trace JSONB,
8841
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
8842
+ )
8843
+ `);
8844
+ await client.query(`
8845
+ CREATE TABLE IF NOT EXISTS ${this.feedbackTableName} (
8846
+ id TEXT PRIMARY KEY,
8847
+ message_id TEXT NOT NULL UNIQUE,
8848
+ session_id TEXT NOT NULL,
8849
+ rating TEXT NOT NULL,
8850
+ comment TEXT,
8851
+ created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP
8852
+ )
8853
+ `);
8854
+ } finally {
8855
+ client.release();
8856
+ }
8857
+ return this.pgPool;
8858
+ }
8859
+ async getMongoClient() {
8860
+ const globalKey = `__retrivora_mongo_client_${this.config.projectId}`;
8861
+ const _g2 = global;
8862
+ if (_g2[globalKey]) {
8863
+ this.mongoClient = _g2[globalKey];
8864
+ this.mongoDbName = this.config.vectorDb.options.database;
8865
+ return this.mongoClient;
8866
+ }
8867
+ const opts = this.config.vectorDb.options;
8868
+ if (!opts.uri || !opts.database) {
8869
+ throw new Error("[DatabaseStorage] mongo uri and database options are missing.");
8870
+ }
8871
+ const { MongoClient: MongoClient2 } = await import("mongodb");
8872
+ this.mongoClient = new MongoClient2(opts.uri);
8873
+ await this.mongoClient.connect();
8874
+ _g2[globalKey] = this.mongoClient;
8875
+ this.mongoDbName = opts.database;
8876
+ return this.mongoClient;
8877
+ }
8878
+ getMongoDb() {
8879
+ return this.mongoClient.db(this.mongoDbName);
8880
+ }
8881
+ // Helper for FS fallback reads
8882
+ readLocalFile(filePath) {
8883
+ if (!fs.existsSync(filePath)) return [];
8884
+ try {
8885
+ const raw = fs.readFileSync(filePath, "utf-8");
8886
+ return JSON.parse(raw) || [];
8887
+ } catch (e) {
8888
+ return [];
8889
+ }
8890
+ }
8891
+ // Helper for FS fallback writes
8892
+ writeLocalFile(filePath, data) {
8893
+ if (!fs.existsSync(this.fallbackDir)) {
8894
+ fs.mkdirSync(this.fallbackDir, { recursive: true });
8895
+ }
8896
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
8897
+ }
8898
+ // ─── Message History Operations ──────────────────────────────────────────
8899
+ async saveMessage(sessionId, message) {
8900
+ this.checkHistoryEnabled();
8901
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
8902
+ const msgId = message.id || `msg_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
8903
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
8904
+ const pool = await this.getPGPool();
8905
+ await pool.query(
8906
+ `INSERT INTO ${this.historyTableName} (id, session_id, role, content, sources, ui_transformation, trace, created_at)
8907
+ VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
8908
+ ON CONFLICT (id) DO UPDATE
8909
+ SET content = EXCLUDED.content, sources = EXCLUDED.sources, ui_transformation = EXCLUDED.ui_transformation, trace = EXCLUDED.trace`,
8910
+ [
8911
+ msgId,
8912
+ sessionId,
8913
+ message.role,
8914
+ message.content,
8915
+ message.sources ? JSON.stringify(message.sources) : null,
8916
+ message.uiTransformation ? JSON.stringify(message.uiTransformation) : null,
8917
+ message.trace ? JSON.stringify(message.trace) : null,
8918
+ createdAt
8919
+ ]
8920
+ );
8921
+ } else if (this.provider === "mongodb") {
8922
+ await this.getMongoClient();
8923
+ const db = this.getMongoDb();
8924
+ const col = db.collection(this.historyTableName);
8925
+ await col.updateOne(
8926
+ { id: msgId },
8927
+ {
8928
+ $set: {
8929
+ id: msgId,
8930
+ session_id: sessionId,
8931
+ role: message.role,
8932
+ content: message.content,
8933
+ sources: message.sources || null,
8934
+ ui_transformation: message.uiTransformation || null,
8935
+ trace: message.trace || null,
8936
+ created_at: createdAt
8937
+ }
8938
+ },
8939
+ { upsert: true }
8940
+ );
8941
+ } else {
8942
+ const history = this.readLocalFile(this.historyFile);
8943
+ const index = history.findIndex((h) => h.id === msgId);
8944
+ const item = {
8945
+ id: msgId,
8946
+ session_id: sessionId,
8947
+ role: message.role,
8948
+ content: message.content,
8949
+ sources: message.sources || null,
8950
+ ui_transformation: message.uiTransformation || null,
8951
+ trace: message.trace || null,
8952
+ created_at: createdAt
8953
+ };
8954
+ if (index !== -1) {
8955
+ history[index] = item;
8956
+ } else {
8957
+ history.push(item);
8958
+ }
8959
+ this.writeLocalFile(this.historyFile, history);
8960
+ }
8961
+ }
8962
+ async getHistory(sessionId) {
8963
+ this.checkHistoryEnabled();
8964
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
8965
+ const pool = await this.getPGPool();
8966
+ const res = await pool.query(
8967
+ `SELECT id, role, content, sources, ui_transformation as "uiTransformation", trace, created_at as "createdAt"
8968
+ FROM ${this.historyTableName}
8969
+ WHERE session_id = $1
8970
+ ORDER BY created_at ASC`,
8971
+ [sessionId]
8972
+ );
8973
+ return res.rows;
8974
+ } else if (this.provider === "mongodb") {
8975
+ await this.getMongoClient();
8976
+ const db = this.getMongoDb();
8977
+ const col = db.collection(this.historyTableName);
8978
+ const items = await col.find({ session_id: sessionId }).sort({ created_at: 1 }).toArray();
8979
+ return items.map((item) => ({
8980
+ id: item.id,
8981
+ role: item.role,
8982
+ content: item.content,
8983
+ sources: item.sources,
8984
+ uiTransformation: item.ui_transformation,
8985
+ trace: item.trace,
8986
+ createdAt: item.created_at
8987
+ }));
8988
+ } else {
8989
+ const history = this.readLocalFile(this.historyFile);
8990
+ return history.filter((h) => h.session_id === sessionId).sort((a, b) => new Date(a.created_at).getTime() - new Date(b.created_at).getTime());
8991
+ }
8992
+ }
8993
+ async clearHistory(sessionId) {
8994
+ this.checkHistoryEnabled();
8995
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
8996
+ const pool = await this.getPGPool();
8997
+ await pool.query(`DELETE FROM ${this.historyTableName} WHERE session_id = $1`, [sessionId]);
8998
+ await pool.query(`DELETE FROM ${this.feedbackTableName} WHERE session_id = $1`, [sessionId]);
8999
+ } else if (this.provider === "mongodb") {
9000
+ await this.getMongoClient();
9001
+ const db = this.getMongoDb();
9002
+ await db.collection(this.historyTableName).deleteMany({ session_id: sessionId });
9003
+ await db.collection(this.feedbackTableName).deleteMany({ session_id: sessionId });
9004
+ } else {
9005
+ const history = this.readLocalFile(this.historyFile);
9006
+ const filteredHistory = history.filter((h) => h.session_id !== sessionId);
9007
+ this.writeLocalFile(this.historyFile, filteredHistory);
9008
+ const feedback = this.readLocalFile(this.feedbackFile);
9009
+ const filteredFeedback = feedback.filter((f) => f.session_id !== sessionId);
9010
+ this.writeLocalFile(this.feedbackFile, filteredFeedback);
9011
+ }
9012
+ }
9013
+ async listSessions() {
9014
+ this.checkHistoryEnabled();
9015
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9016
+ const pool = await this.getPGPool();
9017
+ const res = await pool.query(`SELECT DISTINCT session_id FROM ${this.historyTableName}`);
9018
+ return res.rows.map((r) => r.session_id);
9019
+ } else if (this.provider === "mongodb") {
9020
+ await this.getMongoClient();
9021
+ const db = this.getMongoDb();
9022
+ return db.collection(this.historyTableName).distinct("session_id");
9023
+ } else {
9024
+ const history = this.readLocalFile(this.historyFile);
9025
+ const sessions = new Set(history.map((h) => h.session_id));
9026
+ return Array.from(sessions);
9027
+ }
9028
+ }
9029
+ // ─── Feedback Operations ──────────────────────────────────────────────────
9030
+ async saveFeedback(feedback) {
9031
+ this.checkFeedbackEnabled();
9032
+ const id = `fb_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9033
+ const createdAt = (/* @__PURE__ */ new Date()).toISOString();
9034
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9035
+ const pool = await this.getPGPool();
9036
+ await pool.query(
9037
+ `INSERT INTO ${this.feedbackTableName} (id, message_id, session_id, rating, comment, created_at)
9038
+ VALUES ($1, $2, $3, $4, $5, $6)
9039
+ ON CONFLICT (message_id) DO UPDATE
9040
+ SET rating = EXCLUDED.rating, comment = EXCLUDED.comment`,
9041
+ [id, feedback.messageId, feedback.sessionId, feedback.rating, feedback.comment || null, createdAt]
9042
+ );
9043
+ } else if (this.provider === "mongodb") {
9044
+ await this.getMongoClient();
9045
+ const db = this.getMongoDb();
9046
+ const col = db.collection(this.feedbackTableName);
9047
+ await col.updateOne(
9048
+ { message_id: feedback.messageId },
9049
+ {
9050
+ $set: {
9051
+ id,
9052
+ message_id: feedback.messageId,
9053
+ session_id: feedback.sessionId,
9054
+ rating: feedback.rating,
9055
+ comment: feedback.comment || null,
9056
+ created_at: createdAt
9057
+ }
9058
+ },
9059
+ { upsert: true }
9060
+ );
9061
+ } else {
9062
+ const list = this.readLocalFile(this.feedbackFile);
9063
+ const index = list.findIndex((f) => f.message_id === feedback.messageId);
9064
+ const item = {
9065
+ id,
9066
+ message_id: feedback.messageId,
9067
+ session_id: feedback.sessionId,
9068
+ rating: feedback.rating,
9069
+ comment: feedback.comment || null,
9070
+ created_at: createdAt
9071
+ };
9072
+ if (index !== -1) {
9073
+ list[index] = item;
9074
+ } else {
9075
+ list.push(item);
9076
+ }
9077
+ this.writeLocalFile(this.feedbackFile, list);
9078
+ }
9079
+ }
9080
+ async getFeedback(messageId) {
9081
+ this.checkFeedbackEnabled();
9082
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9083
+ const pool = await this.getPGPool();
9084
+ const res = await pool.query(
9085
+ `SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
9086
+ FROM ${this.feedbackTableName}
9087
+ WHERE message_id = $1`,
9088
+ [messageId]
9089
+ );
9090
+ return res.rows[0] || null;
9091
+ } else if (this.provider === "mongodb") {
9092
+ await this.getMongoClient();
9093
+ const db = this.getMongoDb();
9094
+ const col = db.collection(this.feedbackTableName);
9095
+ const item = await col.findOne({ message_id: messageId });
9096
+ if (!item) return null;
9097
+ return {
9098
+ id: item.id,
9099
+ messageId: item.message_id,
9100
+ sessionId: item.session_id,
9101
+ rating: item.rating,
9102
+ comment: item.comment,
9103
+ createdAt: item.created_at
9104
+ };
9105
+ } else {
9106
+ const list = this.readLocalFile(this.feedbackFile);
9107
+ return list.find((f) => f.message_id === messageId) || null;
9108
+ }
9109
+ }
9110
+ async listFeedback() {
9111
+ this.checkFeedbackEnabled();
9112
+ if (this.provider === "postgresql" || this.provider === "pgvector") {
9113
+ const pool = await this.getPGPool();
9114
+ const res = await pool.query(
9115
+ `SELECT id, message_id as "messageId", session_id as "sessionId", rating, comment, created_at as "createdAt"
9116
+ FROM ${this.feedbackTableName}
9117
+ ORDER BY created_at DESC`
9118
+ );
9119
+ return res.rows;
9120
+ } else if (this.provider === "mongodb") {
9121
+ await this.getMongoClient();
9122
+ const db = this.getMongoDb();
9123
+ const col = db.collection(this.feedbackTableName);
9124
+ const items = await col.find({}).sort({ created_at: -1 }).toArray();
9125
+ return items.map((item) => ({
9126
+ id: item.id,
9127
+ messageId: item.message_id,
9128
+ sessionId: item.session_id,
9129
+ rating: item.rating,
9130
+ comment: item.comment,
9131
+ createdAt: item.created_at
9132
+ }));
9133
+ } else {
9134
+ const list = this.readLocalFile(this.feedbackFile);
9135
+ return [...list].sort((a, b) => new Date(b.created_at).getTime() - new Date(a.created_at).getTime());
9136
+ }
9137
+ }
9138
+ async disconnect() {
9139
+ if (this.pgPool) {
9140
+ await this.pgPool.end();
9141
+ this.pgPool = null;
9142
+ }
9143
+ if (this.mongoClient) {
9144
+ await this.mongoClient.close();
9145
+ this.mongoClient = null;
9146
+ }
9147
+ }
9148
+ };
9149
+
9150
+ // src/handlers/index.ts
9151
+ async function checkAuth(req, onAuthorize) {
9152
+ if (!onAuthorize) return null;
9153
+ try {
9154
+ const res = await onAuthorize(req);
9155
+ if (res === false) {
9156
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
9157
+ }
9158
+ if (res instanceof Response) {
9159
+ return res;
9160
+ }
9161
+ return null;
9162
+ } catch (err) {
9163
+ const msg = err instanceof Error ? err.message : "Authorization check failed";
9164
+ return NextResponse.json({ error: msg }, { status: 401 });
9165
+ }
9166
+ }
9167
+ var RateLimiter = class {
9168
+ constructor(windowMs = 6e4, max = 30) {
9169
+ this.hits = /* @__PURE__ */ new Map();
9170
+ this.windowMs = windowMs;
9171
+ this.max = max;
9172
+ }
9173
+ /** Returns true if the request should be allowed, false if rate-limited. */
9174
+ allow(key) {
9175
+ const now = Date.now();
9176
+ const cutoff = now - this.windowMs;
9177
+ const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
9178
+ existing.push(now);
9179
+ this.hits.set(key, existing);
9180
+ if (this.hits.size > 5e3) {
9181
+ for (const [k, timestamps] of this.hits.entries()) {
9182
+ if (timestamps.every((t) => t <= cutoff)) this.hits.delete(k);
9183
+ }
9184
+ }
9185
+ return existing.length <= this.max;
9186
+ }
9187
+ retryAfterSec(key) {
9188
+ const now = Date.now();
9189
+ const cutoff = now - this.windowMs;
9190
+ const existing = (this.hits.get(key) || []).filter((t) => t > cutoff);
9191
+ if (existing.length === 0) return 0;
9192
+ return Math.ceil((existing[0] + this.windowMs - now) / 1e3);
9193
+ }
9194
+ };
9195
+ var _g = global;
9196
+ var _a;
9197
+ var rateLimiter = (_a = _g.__retrivoraRateLimiter) != null ? _a : _g.__retrivoraRateLimiter = new RateLimiter(6e4, 30);
9198
+ function getRateLimitKey(req) {
9199
+ var _a2, _b;
9200
+ const ip = ((_b = (_a2 = req.headers.get("x-forwarded-for")) == null ? void 0 : _a2.split(",")[0]) == null ? void 0 : _b.trim()) || req.headers.get("x-real-ip") || "127.0.0.1";
9201
+ return `ip:${ip}`;
9202
+ }
9203
+ function checkRateLimit(req) {
9204
+ const key = getRateLimitKey(req);
9205
+ if (!rateLimiter.allow(key)) {
9206
+ const retryAfter = rateLimiter.retryAfterSec(key);
9207
+ return new Response(
9208
+ JSON.stringify({ error: { code: "RATE_LIMITED", message: "Too many requests. Please slow down." } }),
9209
+ {
9210
+ status: 429,
9211
+ headers: {
9212
+ "Content-Type": "application/json",
9213
+ "Retry-After": String(retryAfter),
9214
+ "X-RateLimit-Limit": "30",
9215
+ "X-RateLimit-Window": "60"
9216
+ }
9217
+ }
9218
+ );
9219
+ }
9220
+ return null;
9221
+ }
9222
+ var MAX_MESSAGE_LENGTH = 8e3;
9223
+ function sanitizeInput(raw) {
9224
+ const stripped = raw.replace(/[\u0000-\u0008\u000B\u000C\u000E-\u001F\u007F-\u009F]/g, "");
9225
+ const trimmed = stripped.trim();
9226
+ if (!trimmed) {
9227
+ return { ok: false, error: "message must not be empty" };
9228
+ }
9229
+ if (trimmed.length > MAX_MESSAGE_LENGTH) {
9230
+ return { ok: false, error: `message must be \u2264 ${MAX_MESSAGE_LENGTH} characters` };
9231
+ }
9232
+ return { ok: true, value: trimmed };
9233
+ }
9234
+ function getOrCreatePlugin(configOrPlugin) {
9235
+ if (configOrPlugin instanceof VectorPlugin) return configOrPlugin;
9236
+ const cacheKey = "__retrivoraPlugin_" + JSON.stringify(configOrPlugin != null ? configOrPlugin : {}).slice(0, 64);
9237
+ if (!_g[cacheKey]) {
9238
+ _g[cacheKey] = new VectorPlugin(configOrPlugin);
9239
+ }
9240
+ return _g[cacheKey];
9241
+ }
7676
9242
  function sseFrame(payload) {
7677
9243
  return `data: ${JSON.stringify(payload)}
7678
9244
 
@@ -7710,47 +9276,88 @@ var SSE_HEADERS = {
7710
9276
  "X-Accel-Buffering": "no"
7711
9277
  // Disable Nginx buffering for streaming
7712
9278
  };
7713
- function createChatHandler(configOrPlugin) {
7714
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9279
+ function createChatHandler(configOrPlugin, options) {
9280
+ const plugin = getOrCreatePlugin(configOrPlugin);
9281
+ const storage = new DatabaseStorage(plugin.getConfig());
9282
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7715
9283
  return async function POST(req) {
9284
+ const authResult = await checkAuth(req, onAuthorize);
9285
+ if (authResult) return authResult;
9286
+ const rateLimited = checkRateLimit(req);
9287
+ if (rateLimited) return rateLimited;
7716
9288
  try {
7717
9289
  const body = await req.json();
7718
- const { message, history = [], namespace } = body;
7719
- if (!(message == null ? void 0 : message.trim())) {
7720
- return NextResponse.json({ error: "message is required" }, { status: 400 });
7721
- }
9290
+ const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
9291
+ const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
9292
+ if (!sanitized.ok) {
9293
+ return NextResponse.json({ error: { code: "INVALID_INPUT", message: sanitized.error } }, { status: 400 });
9294
+ }
9295
+ const message = sanitized.value;
9296
+ const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9297
+ await storage.saveMessage(sessionId, {
9298
+ id: userMsgId,
9299
+ role: "user",
9300
+ content: message
9301
+ }).catch((err) => console.warn("[createChatHandler] Failed to save user message:", err));
7722
9302
  const result = await plugin.chat(message, history, namespace);
7723
- return NextResponse.json(result);
9303
+ const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9304
+ await storage.saveMessage(sessionId, {
9305
+ id: assistantMsgId,
9306
+ role: "assistant",
9307
+ content: result.reply,
9308
+ sources: result.sources,
9309
+ uiTransformation: result.ui_transformation,
9310
+ trace: result.trace
9311
+ }).catch((err) => console.warn("[createChatHandler] Failed to save assistant message:", err));
9312
+ return NextResponse.json(__spreadProps(__spreadValues({}, result), {
9313
+ messageId: assistantMsgId,
9314
+ userMessageId: userMsgId
9315
+ }));
7724
9316
  } catch (err) {
7725
9317
  const message = err instanceof Error ? err.message : "Internal server error";
7726
9318
  return NextResponse.json({ error: message }, { status: 500 });
7727
9319
  }
7728
9320
  };
7729
9321
  }
7730
- function createStreamHandler(configOrPlugin) {
7731
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9322
+ function createStreamHandler(configOrPlugin, options) {
9323
+ const plugin = getOrCreatePlugin(configOrPlugin);
9324
+ const storage = new DatabaseStorage(plugin.getConfig());
9325
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7732
9326
  return async function POST(req) {
9327
+ const authResult = await checkAuth(req, onAuthorize);
9328
+ if (authResult) return authResult;
9329
+ const rateLimited = checkRateLimit(req);
9330
+ if (rateLimited) return rateLimited;
7733
9331
  let body;
7734
9332
  try {
7735
9333
  body = await req.json();
7736
9334
  } catch (e) {
7737
- return new Response(JSON.stringify({ error: "Invalid JSON body" }), {
9335
+ return new Response(JSON.stringify({ error: { code: "INVALID_JSON", message: "Invalid JSON body" } }), {
7738
9336
  status: 400,
7739
9337
  headers: { "Content-Type": "application/json" }
7740
9338
  });
7741
9339
  }
7742
- const { message, history = [], namespace } = body;
7743
- if (!(message == null ? void 0 : message.trim())) {
7744
- return new Response(JSON.stringify({ error: "message is required" }), {
7745
- status: 400,
7746
- headers: { "Content-Type": "application/json" }
7747
- });
9340
+ const { message: rawMessage, history = [], namespace, sessionId = "default", messageId, userMessageId } = body;
9341
+ const sanitized = sanitizeInput(rawMessage != null ? rawMessage : "");
9342
+ if (!sanitized.ok) {
9343
+ return new Response(
9344
+ JSON.stringify({ error: { code: "INVALID_INPUT", message: sanitized.error } }),
9345
+ { status: 400, headers: { "Content-Type": "application/json" } }
9346
+ );
7748
9347
  }
9348
+ const message = sanitized.value;
9349
+ const userMsgId = userMessageId || `user_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
9350
+ await storage.saveMessage(sessionId, {
9351
+ id: userMsgId,
9352
+ role: "user",
9353
+ content: message
9354
+ }).catch((err) => console.warn("[createStreamHandler] Failed to save user message:", err));
9355
+ const assistantMsgId = messageId || `assistant_${Date.now()}_${Math.random().toString(36).slice(2, 6)}`;
7749
9356
  const encoder = new TextEncoder();
7750
9357
  let isActive = true;
7751
9358
  const stream = new ReadableStream({
7752
9359
  async start(controller) {
7753
- var _a;
9360
+ var _a2;
7754
9361
  const enqueue = (text) => {
7755
9362
  if (!isActive) return;
7756
9363
  try {
@@ -7761,11 +9368,13 @@ function createStreamHandler(configOrPlugin) {
7761
9368
  };
7762
9369
  try {
7763
9370
  const pipelineStream = plugin.chatStream(message, history, namespace);
9371
+ let fullReply = "";
7764
9372
  try {
7765
9373
  for (var iter = __forAwait(pipelineStream), more, temp, error; more = !(temp = await iter.next()).done; more = false) {
7766
9374
  const chunk = temp.value;
7767
9375
  if (!isActive) break;
7768
9376
  if (typeof chunk === "string") {
9377
+ fullReply += chunk;
7769
9378
  enqueue(sseTextFrame(chunk));
7770
9379
  } else if (chunk && typeof chunk === "object" && "type" in chunk && chunk.type === "thinking") {
7771
9380
  enqueue(`data: ${JSON.stringify(chunk)}
@@ -7778,9 +9387,10 @@ function createStreamHandler(configOrPlugin) {
7778
9387
  if (responseChunk == null ? void 0 : responseChunk.trace) {
7779
9388
  enqueue(sseObservabilityFrame(responseChunk.trace));
7780
9389
  }
9390
+ let uiTransformation = responseChunk == null ? void 0 : responseChunk.ui_transformation;
7781
9391
  if (sources.length > 0) {
7782
9392
  try {
7783
- const uiTransformation = (_a = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a : UITransformer.transform(message, sources, plugin.getConfig());
9393
+ uiTransformation = (_a2 = responseChunk == null ? void 0 : responseChunk.ui_transformation) != null ? _a2 : UITransformer.transform(message, sources, plugin.getConfig());
7784
9394
  if (uiTransformation) {
7785
9395
  enqueue(sseUIFrame(uiTransformation));
7786
9396
  }
@@ -7788,11 +9398,22 @@ function createStreamHandler(configOrPlugin) {
7788
9398
  console.warn("[createStreamHandler] UI transformation warning:", transformError);
7789
9399
  try {
7790
9400
  const fallback = UITransformer.transform(message, sources, plugin.getConfig());
7791
- if (fallback) enqueue(sseUIFrame(fallback));
9401
+ if (fallback) {
9402
+ uiTransformation = fallback;
9403
+ enqueue(sseUIFrame(fallback));
9404
+ }
7792
9405
  } catch (e) {
7793
9406
  }
7794
9407
  }
7795
9408
  }
9409
+ await storage.saveMessage(sessionId, {
9410
+ id: assistantMsgId,
9411
+ role: "assistant",
9412
+ content: fullReply,
9413
+ sources,
9414
+ uiTransformation,
9415
+ trace: responseChunk == null ? void 0 : responseChunk.trace
9416
+ }).catch((err) => console.warn("[createStreamHandler] Failed to save assistant message:", err));
7796
9417
  }
7797
9418
  }
7798
9419
  } catch (temp) {
@@ -7829,12 +9450,15 @@ function createStreamHandler(configOrPlugin) {
7829
9450
  console.log("[createStreamHandler] Stream connection closed by client:", reason);
7830
9451
  }
7831
9452
  });
7832
- return new Response(stream, { headers: SSE_HEADERS });
9453
+ return new Response(stream, { headers: __spreadProps(__spreadValues({}, SSE_HEADERS), { "x-message-id": assistantMsgId, "x-user-message-id": userMsgId }) });
7833
9454
  };
7834
9455
  }
7835
- function createIngestHandler(configOrPlugin) {
7836
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9456
+ function createIngestHandler(configOrPlugin, options) {
9457
+ const plugin = getOrCreatePlugin(configOrPlugin);
9458
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7837
9459
  return async function POST(req) {
9460
+ const authResult = await checkAuth(req, onAuthorize);
9461
+ if (authResult) return authResult;
7838
9462
  try {
7839
9463
  const body = await req.json();
7840
9464
  const { documents, namespace } = body;
@@ -7849,9 +9473,14 @@ function createIngestHandler(configOrPlugin) {
7849
9473
  }
7850
9474
  };
7851
9475
  }
7852
- function createHealthHandler(configOrPlugin) {
7853
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
7854
- return async function GET() {
9476
+ function createHealthHandler(configOrPlugin, options) {
9477
+ const plugin = getOrCreatePlugin(configOrPlugin);
9478
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9479
+ return async function GET(req) {
9480
+ if (req) {
9481
+ const authResult = await checkAuth(req, onAuthorize);
9482
+ if (authResult) return authResult;
9483
+ }
7855
9484
  try {
7856
9485
  const health = await plugin.checkHealth();
7857
9486
  const status = health.allHealthy ? "ok" : "degraded";
@@ -7866,9 +9495,12 @@ function createHealthHandler(configOrPlugin) {
7866
9495
  }
7867
9496
  };
7868
9497
  }
7869
- function createUploadHandler(configOrPlugin) {
7870
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9498
+ function createUploadHandler(configOrPlugin, options) {
9499
+ const plugin = getOrCreatePlugin(configOrPlugin);
9500
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7871
9501
  return async function POST(req) {
9502
+ const authResult = await checkAuth(req, onAuthorize);
9503
+ if (authResult) return authResult;
7872
9504
  try {
7873
9505
  const formData = await req.formData();
7874
9506
  const files = formData.getAll("files");
@@ -7942,9 +9574,12 @@ function createUploadHandler(configOrPlugin) {
7942
9574
  }
7943
9575
  };
7944
9576
  }
7945
- function createSuggestionsHandler(configOrPlugin) {
7946
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
9577
+ function createSuggestionsHandler(configOrPlugin, options) {
9578
+ const plugin = getOrCreatePlugin(configOrPlugin);
9579
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
7947
9580
  return async function POST(req) {
9581
+ const authResult = await checkAuth(req, onAuthorize);
9582
+ if (authResult) return authResult;
7948
9583
  try {
7949
9584
  const body = await req.json();
7950
9585
  const { query, namespace } = body;
@@ -7959,13 +9594,108 @@ function createSuggestionsHandler(configOrPlugin) {
7959
9594
  }
7960
9595
  };
7961
9596
  }
7962
- function createRagHandler(configOrPlugin) {
7963
- const plugin = configOrPlugin instanceof VectorPlugin ? configOrPlugin : new VectorPlugin(configOrPlugin);
7964
- const chatHandler = createChatHandler(plugin);
7965
- const streamHandler = createStreamHandler(plugin);
7966
- const uploadHandler = createUploadHandler(plugin);
7967
- const healthHandler = createHealthHandler(plugin);
7968
- const suggestionsHandler = createSuggestionsHandler(plugin);
9597
+ function createHistoryHandler(configOrPlugin, options) {
9598
+ const plugin = getOrCreatePlugin(configOrPlugin);
9599
+ const storage = new DatabaseStorage(plugin.getConfig());
9600
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9601
+ return async function handler(req) {
9602
+ const authResult = await checkAuth(req, onAuthorize);
9603
+ if (authResult) return authResult;
9604
+ const url = new URL(req.url);
9605
+ const sessionId = url.searchParams.get("sessionId") || "default";
9606
+ if (req.method === "GET") {
9607
+ try {
9608
+ const history = await storage.getHistory(sessionId);
9609
+ return NextResponse.json({ history });
9610
+ } catch (err) {
9611
+ const message = err instanceof Error ? err.message : "Failed to fetch history";
9612
+ return NextResponse.json({ error: message }, { status: 500 });
9613
+ }
9614
+ } else if (req.method === "POST") {
9615
+ try {
9616
+ const body = await req.json().catch(() => ({}));
9617
+ const sid = body.sessionId || sessionId;
9618
+ await storage.clearHistory(sid);
9619
+ return NextResponse.json({ success: true });
9620
+ } catch (err) {
9621
+ const message = err instanceof Error ? err.message : "Failed to clear history";
9622
+ return NextResponse.json({ error: message }, { status: 500 });
9623
+ }
9624
+ }
9625
+ return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
9626
+ };
9627
+ }
9628
+ function createFeedbackHandler(configOrPlugin, options) {
9629
+ const plugin = getOrCreatePlugin(configOrPlugin);
9630
+ const storage = new DatabaseStorage(plugin.getConfig());
9631
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9632
+ return async function handler(req) {
9633
+ const authResult = await checkAuth(req, onAuthorize);
9634
+ if (authResult) return authResult;
9635
+ if (req.method === "GET") {
9636
+ try {
9637
+ const url = new URL(req.url);
9638
+ const messageId = url.searchParams.get("messageId");
9639
+ if (!messageId) {
9640
+ const feedbackList = await storage.listFeedback();
9641
+ return NextResponse.json({ feedback: feedbackList });
9642
+ }
9643
+ const feedback = await storage.getFeedback(messageId);
9644
+ return NextResponse.json({ feedback });
9645
+ } catch (err) {
9646
+ const message = err instanceof Error ? err.message : "Failed to fetch feedback";
9647
+ return NextResponse.json({ error: message }, { status: 500 });
9648
+ }
9649
+ } else if (req.method === "POST") {
9650
+ try {
9651
+ const body = await req.json();
9652
+ const { messageId, sessionId = "default", rating, comment } = body;
9653
+ if (!messageId) {
9654
+ return NextResponse.json({ error: "messageId is required" }, { status: 400 });
9655
+ }
9656
+ if (!rating) {
9657
+ return NextResponse.json({ error: "rating is required" }, { status: 400 });
9658
+ }
9659
+ await storage.saveFeedback({ messageId, sessionId, rating, comment });
9660
+ return NextResponse.json({ success: true });
9661
+ } catch (err) {
9662
+ const message = err instanceof Error ? err.message : "Failed to save feedback";
9663
+ return NextResponse.json({ error: message }, { status: 500 });
9664
+ }
9665
+ }
9666
+ return NextResponse.json({ error: "Method Not Allowed" }, { status: 405 });
9667
+ };
9668
+ }
9669
+ function createSessionsHandler(configOrPlugin, options) {
9670
+ const plugin = getOrCreatePlugin(configOrPlugin);
9671
+ const storage = new DatabaseStorage(plugin.getConfig());
9672
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9673
+ return async function GET(req) {
9674
+ if (req) {
9675
+ const authResult = await checkAuth(req, onAuthorize);
9676
+ if (authResult) return authResult;
9677
+ }
9678
+ void req;
9679
+ try {
9680
+ const sessions = await storage.listSessions();
9681
+ return NextResponse.json({ sessions });
9682
+ } catch (err) {
9683
+ const message = err instanceof Error ? err.message : "Failed to list sessions";
9684
+ return NextResponse.json({ error: message }, { status: 500 });
9685
+ }
9686
+ };
9687
+ }
9688
+ function createRagHandler(configOrPlugin, options) {
9689
+ const plugin = getOrCreatePlugin(configOrPlugin);
9690
+ const onAuthorize = options == null ? void 0 : options.onAuthorize;
9691
+ const chatHandler = createChatHandler(plugin, { onAuthorize });
9692
+ const streamHandler = createStreamHandler(plugin, { onAuthorize });
9693
+ const uploadHandler = createUploadHandler(plugin, { onAuthorize });
9694
+ const healthHandler = createHealthHandler(plugin, { onAuthorize });
9695
+ const suggestionsHandler = createSuggestionsHandler(plugin, { onAuthorize });
9696
+ const historyHandler = createHistoryHandler(plugin, { onAuthorize });
9697
+ const feedbackHandler = createFeedbackHandler(plugin, { onAuthorize });
9698
+ const sessionsHandler = createSessionsHandler(plugin, { onAuthorize });
7969
9699
  async function routePostRequest(req, segment) {
7970
9700
  switch (segment) {
7971
9701
  case "chat":
@@ -7977,22 +9707,35 @@ function createRagHandler(configOrPlugin) {
7977
9707
  case "suggestions":
7978
9708
  return suggestionsHandler(req);
7979
9709
  case "health":
7980
- return healthHandler();
9710
+ return healthHandler(req);
9711
+ case "history":
9712
+ case "history/clear":
9713
+ return historyHandler(req);
9714
+ case "feedback":
9715
+ return feedbackHandler(req);
7981
9716
  default:
7982
9717
  return NextResponse.json({ error: `Not Found: POST segment "${segment}" not supported.` }, { status: 404 });
7983
9718
  }
7984
9719
  }
7985
9720
  async function routeGetRequest(req, segment) {
7986
- if (segment === "health") {
7987
- return healthHandler();
9721
+ switch (segment) {
9722
+ case "health":
9723
+ return healthHandler(req);
9724
+ case "history":
9725
+ return historyHandler(req);
9726
+ case "feedback":
9727
+ return feedbackHandler(req);
9728
+ case "sessions":
9729
+ return sessionsHandler(req);
9730
+ default:
9731
+ return NextResponse.json({ error: `Method Not Allowed: GET segment "${segment}" not supported.` }, { status: 405 });
7988
9732
  }
7989
- return NextResponse.json({ error: `Method Not Allowed: GET is only supported for "health" segment.` }, { status: 405 });
7990
9733
  }
7991
9734
  async function getSegment(context) {
7992
- var _a;
7993
- 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;
9735
+ var _a2;
9736
+ const resolvedParams = typeof ((_a2 = context == null ? void 0 : context.params) == null ? void 0 : _a2.then) === "function" ? await context.params : context == null ? void 0 : context.params;
7994
9737
  const segments = (resolvedParams == null ? void 0 : resolvedParams.retrivora) || [];
7995
- return segments[0] || "chat";
9738
+ return segments.join("/") || "chat";
7996
9739
  }
7997
9740
  return {
7998
9741
  GET: async (req, context) => {
@@ -8030,8 +9773,10 @@ export {
8030
9773
  EmbeddingFailedException,
8031
9774
  EmbeddingStrategy,
8032
9775
  EmbeddingStrategyResolver,
9776
+ GroqProvider,
8033
9777
  LLMFactory,
8034
9778
  LLM_PROFILES,
9779
+ LicenseVerifier,
8035
9780
  MilvusProvider,
8036
9781
  MongoDBProvider,
8037
9782
  MultiTablePostgresProvider,
@@ -8045,6 +9790,7 @@ export {
8045
9790
  ProviderNotFoundException,
8046
9791
  ProviderRegistry,
8047
9792
  QdrantProvider,
9793
+ QwenProvider,
8048
9794
  RateLimitException,
8049
9795
  RedisProvider,
8050
9796
  RetrievalException,
@@ -8056,10 +9802,13 @@ export {
8056
9802
  VectorPlugin,
8057
9803
  WeaviateProvider,
8058
9804
  createChatHandler,
9805
+ createFeedbackHandler,
8059
9806
  createFromPreset,
8060
9807
  createHealthHandler,
9808
+ createHistoryHandler,
8061
9809
  createIngestHandler,
8062
9810
  createRagHandler,
9811
+ createSessionsHandler,
8063
9812
  createStreamHandler,
8064
9813
  createUploadHandler,
8065
9814
  getRagConfig,