@retrivora-ai/rag-engine 2.0.5 → 2.0.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/server.mjs CHANGED
@@ -3911,7 +3911,7 @@ var UniversalLLMAdapter = class {
3911
3911
  });
3912
3912
  }
3913
3913
  async chat(messages, context) {
3914
- var _a2, _b;
3914
+ var _a2, _b, _c, _d, _e, _f;
3915
3915
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3916
3916
  const formattedMessages = [
3917
3917
  { role: "system", content: `${this.systemPrompt}
@@ -3936,8 +3936,27 @@ ${context != null ? context : "None"}` },
3936
3936
  temperature: this.temperature
3937
3937
  };
3938
3938
  }
3939
+ const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
3940
+ if (isSelfHost || Boolean(process.env.VERCEL)) {
3941
+ const _g2 = globalThis;
3942
+ if (typeof _g2.__retrivoraDispatchChat === "function") {
3943
+ try {
3944
+ const res = await _g2.__retrivoraDispatchChat({
3945
+ model: this.model,
3946
+ messages: formattedMessages,
3947
+ max_tokens: this.maxTokens,
3948
+ temperature: this.temperature
3949
+ }, this.apiKey);
3950
+ if ((_e = (_d = (_c = (_b = res == null ? void 0 : res.response) == null ? void 0 : _b.choices) == null ? void 0 : _c[0]) == null ? void 0 : _d.message) == null ? void 0 : _e.content) {
3951
+ return res.response.choices[0].message.content;
3952
+ }
3953
+ } catch (dispatchErr) {
3954
+ throw dispatchErr;
3955
+ }
3956
+ }
3957
+ }
3939
3958
  const { data } = await this.http.post(path2, payload);
3940
- const extractPath = (_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content";
3959
+ const extractPath = (_f = this.opts.responseExtractPath) != null ? _f : "choices[0].message.content";
3941
3960
  const result = resolvePath(data, extractPath);
3942
3961
  if (result === void 0) {
3943
3962
  throw new Error(`[UniversalLLMAdapter] Could not extract text from path '${extractPath}' in response.`);
@@ -3951,7 +3970,7 @@ ${context != null ? context : "None"}` },
3951
3970
  */
3952
3971
  chatStream(messages, context) {
3953
3972
  return __asyncGenerator(this, null, function* () {
3954
- var _a2, _b, _c;
3973
+ var _a2, _b, _c, _d, _e, _f, _g2;
3955
3974
  const path2 = (_a2 = this.opts.chatPath) != null ? _a2 : "/chat/completions";
3956
3975
  const url = `${this.baseUrl.replace(/\/$/, "")}${path2}`;
3957
3976
  const extractPath = ((_b = this.opts.responseExtractPath) != null ? _b : "choices[0].message.content").replace("message.content", "delta.content");
@@ -3982,19 +4001,46 @@ ${context != null ? context : "None"}` },
3982
4001
  stream: true
3983
4002
  };
3984
4003
  }
3985
- const response = yield new __await(fetch(url, {
3986
- method: "POST",
3987
- headers: this.resolvedHeaders,
3988
- body: JSON.stringify(payload)
3989
- }));
3990
- if (!response.ok) {
3991
- const errorText = yield new __await(response.text().catch(() => response.statusText));
3992
- throw new Error(`[UniversalLLMAdapter] Streaming request failed (${response.status}): ${errorText}`);
4004
+ const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4005
+ let streamBody = null;
4006
+ if (isSelfHost || Boolean(process.env.VERCEL)) {
4007
+ const _g3 = globalThis;
4008
+ if (typeof _g3.__retrivoraDispatchChat === "function") {
4009
+ try {
4010
+ const res = yield new __await(_g3.__retrivoraDispatchChat({
4011
+ model: this.model,
4012
+ messages: formattedMessages,
4013
+ max_tokens: this.maxTokens,
4014
+ temperature: this.temperature,
4015
+ stream: true
4016
+ }, this.apiKey));
4017
+ if (res == null ? void 0 : res.stream) {
4018
+ streamBody = res.stream;
4019
+ } else if ((_f = (_e = (_d = (_c = res == null ? void 0 : res.response) == null ? void 0 : _c.choices) == null ? void 0 : _d[0]) == null ? void 0 : _e.message) == null ? void 0 : _f.content) {
4020
+ yield res.response.choices[0].message.content;
4021
+ return;
4022
+ }
4023
+ } catch (dispatchErr) {
4024
+ throw dispatchErr;
4025
+ }
4026
+ }
3993
4027
  }
3994
- if (!response.body) {
3995
- throw new Error("[UniversalLLMAdapter] Response body is null \u2014 server did not send a streaming response.");
4028
+ if (!streamBody) {
4029
+ const response = yield new __await(fetch(url, {
4030
+ method: "POST",
4031
+ headers: this.resolvedHeaders,
4032
+ body: JSON.stringify(payload)
4033
+ }));
4034
+ if (!response.ok) {
4035
+ const errorText = yield new __await(response.text().catch(() => response.statusText));
4036
+ throw new Error(`[UniversalLLMAdapter] Streaming request failed (${response.status}): ${errorText}`);
4037
+ }
4038
+ if (!response.body) {
4039
+ throw new Error("[UniversalLLMAdapter] Response body is null \u2014 server did not send a streaming response.");
4040
+ }
4041
+ streamBody = response.body;
3996
4042
  }
3997
- const reader = response.body.getReader();
4043
+ const reader = streamBody.getReader();
3998
4044
  const decoder = new TextDecoder("utf-8");
3999
4045
  let buffer = "";
4000
4046
  try {
@@ -4003,7 +4049,7 @@ ${context != null ? context : "None"}` },
4003
4049
  if (done) break;
4004
4050
  buffer += decoder.decode(value, { stream: true });
4005
4051
  const lines = buffer.split("\n");
4006
- buffer = (_c = lines.pop()) != null ? _c : "";
4052
+ buffer = (_g2 = lines.pop()) != null ? _g2 : "";
4007
4053
  for (const line of lines) {
4008
4054
  const trimmed = line.trim();
4009
4055
  if (!trimmed || trimmed === "data: [DONE]") continue;
@@ -4031,7 +4077,7 @@ ${context != null ? context : "None"}` },
4031
4077
  });
4032
4078
  }
4033
4079
  async embed(text) {
4034
- var _a2, _b;
4080
+ var _a2, _b, _c, _d;
4035
4081
  const path2 = (_a2 = this.opts.embedPath) != null ? _a2 : "/embeddings";
4036
4082
  let payload;
4037
4083
  if (this.opts.embedPayloadTemplate) {
@@ -4045,8 +4091,25 @@ ${context != null ? context : "None"}` },
4045
4091
  input: text
4046
4092
  };
4047
4093
  }
4094
+ const isSelfHost = this.baseUrl.includes("retrivora.com") || this.baseUrl.includes("localhost");
4095
+ if (isSelfHost || Boolean(process.env.VERCEL)) {
4096
+ const _g2 = globalThis;
4097
+ if (typeof _g2.__retrivoraDispatchEmbedding === "function") {
4098
+ try {
4099
+ const res = await _g2.__retrivoraDispatchEmbedding({
4100
+ model: this.model,
4101
+ input: text
4102
+ }, this.apiKey);
4103
+ if ((_c = (_b = res == null ? void 0 : res.data) == null ? void 0 : _b[0]) == null ? void 0 : _c.embedding) {
4104
+ return res.data[0].embedding;
4105
+ }
4106
+ } catch (dispatchErr) {
4107
+ throw dispatchErr;
4108
+ }
4109
+ }
4110
+ }
4048
4111
  const { data } = await this.http.post(path2, payload);
4049
- const extractPath = (_b = this.opts.embedExtractPath) != null ? _b : "data[0].embedding";
4112
+ const extractPath = (_d = this.opts.embedExtractPath) != null ? _d : "data[0].embedding";
4050
4113
  const vector = resolvePath(data, extractPath);
4051
4114
  if (!Array.isArray(vector)) {
4052
4115
  throw new Error(`[UniversalLLMAdapter] Expected a number array at '${extractPath}' for embeddings.`);
@@ -4635,7 +4698,8 @@ var Reranker = class {
4635
4698
  return matches.sort((a, b) => b.score - a.score).slice(0, limit);
4636
4699
  }
4637
4700
  const scoredMatches = matches.map((match) => {
4638
- const contentLower = match.content.toLowerCase();
4701
+ var _a2;
4702
+ const contentLower = ((_a2 = match == null ? void 0 : match.content) != null ? _a2 : "").toLowerCase();
4639
4703
  let keywordScore = 0;
4640
4704
  keywords.forEach((keyword) => {
4641
4705
  if (contentLower.includes(keyword)) {
@@ -4656,7 +4720,10 @@ var Reranker = class {
4656
4720
  [{ role: "user", content: `Query: "${query}"
4657
4721
 
4658
4722
  Documents:
4659
- ${topN.map((m, i) => `[${i}] ${m.content.replace(/\n/g, " ")}`).join("\n")}` }],
4723
+ ${topN.map((m, i) => {
4724
+ var _a2;
4725
+ return `[${i}] ${((_a2 = m == null ? void 0 : m.content) != null ? _a2 : "").replace(/\n/g, " ")}`;
4726
+ }).join("\n")}` }],
4660
4727
  "",
4661
4728
  {
4662
4729
  systemPrompt: 'You are a relevance ranking expert. Given the user query and a list of retrieved document chunks, rank the chunks by relevance to the query. Return the result as a comma-separated list of document indices in order of relevance, from most relevant to least relevant. Use the indices provided in brackets like [0], [1], etc. Only return the indices (e.g., "2,0,1"), nothing else. Do not include brackets in the output.',
@@ -5827,10 +5894,10 @@ Return ONLY 'vector', 'graph', or 'both'. No explanation.`;
5827
5894
  "",
5828
5895
  { temperature: 0, maxTokens: 10 }
5829
5896
  );
5830
- const cleanResponse = response.trim().toLowerCase();
5831
- if (cleanResponse.includes("vector")) return "vector";
5832
- if (cleanResponse.includes("graph")) return "graph";
5897
+ const cleanResponse = (response != null ? response : "").trim().toLowerCase();
5833
5898
  if (cleanResponse.includes("both")) return "both";
5899
+ if (cleanResponse.includes("graph")) return "graph";
5900
+ if (cleanResponse.includes("vector")) return "vector";
5834
5901
  } catch (error) {
5835
5902
  console.warn("[QueryProcessor] LLM strategy classification failed, falling back to keywords:", error);
5836
5903
  }
@@ -6004,7 +6071,10 @@ var IntentClassifier = class {
6004
6071
  hasCategoricalFields = catKeys.size > 0;
6005
6072
  numericFieldCount = numericKeys.size;
6006
6073
  categoricalFieldCount = catKeys.size;
6007
- if (productKeyMatches >= 2 || docs.some((d) => d.content.toLowerCase().includes("price") || d.content.toLowerCase().includes("brand"))) {
6074
+ if (productKeyMatches >= 2 || docs.some((d) => {
6075
+ var _a2, _b;
6076
+ return ((_a2 = d == null ? void 0 : d.content) != null ? _a2 : "").toLowerCase().includes("price") || ((_b = d == null ? void 0 : d.content) != null ? _b : "").toLowerCase().includes("brand");
6077
+ })) {
6008
6078
  isProductLike = true;
6009
6079
  }
6010
6080
  }
@@ -6284,7 +6354,10 @@ var TextRendererStrategy = class {
6284
6354
  return { type: "text", title, data: { content: data } };
6285
6355
  }
6286
6356
  const docs = Array.isArray(data) ? data : [];
6287
- const text = docs.map((d) => d.content).join("\n\n");
6357
+ const text = docs.map((d) => {
6358
+ var _a2;
6359
+ return (_a2 = d == null ? void 0 : d.content) != null ? _a2 : "";
6360
+ }).join("\n\n");
6288
6361
  return { type: "text", title, data: { content: text || "No detailed content available." } };
6289
6362
  }
6290
6363
  };
@@ -6541,6 +6614,19 @@ var UITransformer = class _UITransformer {
6541
6614
  if (!retrievedData || retrievedData.length === 0) {
6542
6615
  return this.createTextResponse("No data available", "No relevant data found for your query.");
6543
6616
  }
6617
+ console.log("[UITransformer.transform] Processing retrievedData:", {
6618
+ userQuery,
6619
+ retrievedCount: retrievedData.length,
6620
+ sample: retrievedData.slice(0, 2).map((item) => {
6621
+ var _a3;
6622
+ return {
6623
+ id: item == null ? void 0 : item.id,
6624
+ contentType: typeof (item == null ? void 0 : item.content),
6625
+ contentSnippet: String((_a3 = item == null ? void 0 : item.content) != null ? _a3 : "").substring(0, 150),
6626
+ metadataKeys: Object.keys((item == null ? void 0 : item.metadata) || {})
6627
+ };
6628
+ })
6629
+ });
6544
6630
  const resolvedIntent = intent != null ? intent : this.detectIntentHeuristic(userQuery);
6545
6631
  const filteredData = resolvedIntent.filterInStockOnly ? retrievedData.filter((item) => this.determineStockStatus(item)) : retrievedData;
6546
6632
  const profile = this.profileData(filteredData);
@@ -7030,7 +7116,10 @@ ${schemaProfileText}` : ""}`;
7030
7116
  type: "radar_chart",
7031
7117
  title: "Product Comparison",
7032
7118
  description: `Comparing ${data.length} items across ${radarData.length} attributes`,
7033
- data: radarData.length > 0 ? radarData : data.map((d) => ({ attribute: d.content.substring(0, 40) }))
7119
+ data: radarData.length > 0 ? radarData : data.map((d) => {
7120
+ var _a2;
7121
+ return { attribute: ((_a2 = d == null ? void 0 : d.content) != null ? _a2 : "").substring(0, 40) };
7122
+ })
7034
7123
  };
7035
7124
  }
7036
7125
  static transformToTable(data, query = "") {
@@ -7047,7 +7136,10 @@ ${schemaProfileText}` : ""}`;
7047
7136
  static transformToText(data) {
7048
7137
  return this.createTextResponse(
7049
7138
  "Retrieved Context",
7050
- data.map((item) => item.content).join("\n\n"),
7139
+ data.map((item) => {
7140
+ var _a2;
7141
+ return (_a2 = item == null ? void 0 : item.content) != null ? _a2 : "";
7142
+ }).join("\n\n"),
7051
7143
  `Found ${data.length} relevant results`
7052
7144
  );
7053
7145
  }
@@ -7208,6 +7300,7 @@ ${schemaProfileText}` : ""}`;
7208
7300
  return productTerms && productAction && !nonProductEntityTerms;
7209
7301
  }
7210
7302
  static isProductData(item) {
7303
+ if (!item) return false;
7211
7304
  const content = (item.content || "").toLowerCase();
7212
7305
  const productKeywords = [
7213
7306
  "product",
@@ -7466,12 +7559,12 @@ ${schemaProfileText}` : ""}`;
7466
7559
  }
7467
7560
  static extractTimeSeriesData(data) {
7468
7561
  return data.map((item) => {
7469
- var _a2, _b, _c, _d, _e;
7562
+ var _a2, _b, _c, _d, _e, _f;
7470
7563
  const meta = item.metadata || {};
7471
7564
  return {
7472
7565
  timestamp: (_b = (_a2 = meta.timestamp) != null ? _a2 : meta.date) != null ? _b : (/* @__PURE__ */ new Date()).toISOString(),
7473
7566
  value: (_d = (_c = meta.value) != null ? _c : item.score) != null ? _d : 0,
7474
- label: (_e = meta.label) != null ? _e : item.content.substring(0, 50)
7567
+ label: (_f = meta.label) != null ? _f : ((_e = item == null ? void 0 : item.content) != null ? _e : "").substring(0, 50)
7475
7568
  };
7476
7569
  });
7477
7570
  }
@@ -7585,7 +7678,8 @@ ${schemaProfileText}` : ""}`;
7585
7678
  }, query.includes(normalizedField) ? 3 : 0);
7586
7679
  }
7587
7680
  static resolveTableCellValue(item, column) {
7588
- if (column === "Content") return item.content.substring(0, 100);
7681
+ var _a2, _b, _c;
7682
+ if (column === "Content") return ((_a2 = item == null ? void 0 : item.content) != null ? _a2 : "").substring(0, 100);
7589
7683
  const meta = item.metadata || {};
7590
7684
  const normalizedColumn = this.normalizeComparableField(column);
7591
7685
  const exactMetadata = Object.entries(meta).find(
@@ -7596,9 +7690,9 @@ ${schemaProfileText}` : ""}`;
7596
7690
  }
7597
7691
  const aliasValue = this.resolveAliasedTableCell(meta, column);
7598
7692
  if (aliasValue !== void 0) return this.toDisplayValue(aliasValue);
7599
- const contentValue = this.extractContentFieldValue(item.content, column);
7693
+ const contentValue = this.extractContentFieldValue((_b = item == null ? void 0 : item.content) != null ? _b : "", column);
7600
7694
  if (contentValue !== null) return contentValue;
7601
- const aliasContentValue = this.extractAliasedContentFieldValue(item.content, column);
7695
+ const aliasContentValue = this.extractAliasedContentFieldValue((_c = item == null ? void 0 : item.content) != null ? _c : "", column);
7602
7696
  return aliasContentValue != null ? aliasContentValue : "";
7603
7697
  }
7604
7698
  static resolveAliasedTableCell(meta, column) {
@@ -7648,6 +7742,7 @@ ${schemaProfileText}` : ""}`;
7648
7742
  return { inStockCount: inStock, outOfStockCount: outOfStock };
7649
7743
  }
7650
7744
  static determineStockStatus(item) {
7745
+ if (!item) return true;
7651
7746
  const meta = item.metadata || {};
7652
7747
  const stockValue = resolveMetadataValue(meta, "stock");
7653
7748
  if (stockValue !== void 0) {
@@ -7693,35 +7788,64 @@ ${schemaProfileText}` : ""}`;
7693
7788
  return resolveMetadataValue(meta, uiKey);
7694
7789
  }
7695
7790
  static extractProductInfo(item, config, trainedSchema) {
7696
- var _a2;
7791
+ var _a2, _b;
7792
+ if (!item) return null;
7697
7793
  const meta = item.metadata || {};
7794
+ const content = item.content || "";
7698
7795
  const name = this.getDynamicVal(meta, "name", config, trainedSchema);
7699
7796
  const price = this.getDynamicVal(meta, "price", config, trainedSchema);
7700
7797
  const brand = this.getDynamicVal(meta, "brand", config, trainedSchema);
7701
7798
  const description = this.cleanProductDescription(
7702
- (_a2 = this.extractProductDescriptionFromContent(item.content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
7799
+ (_a2 = this.extractProductDescriptionFromContent(content)) != null ? _a2 : this.getProductDescriptionValue(meta, config, trainedSchema)
7703
7800
  );
7704
7801
  if (name || this.isProductData(item)) {
7705
7802
  let finalName = name ? String(name) : void 0;
7803
+ if (!finalName && content) {
7804
+ const nameMatch = content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
7805
+ finalName = nameMatch ? nameMatch[1].trim() : (_b = content.split("\n")[0]) == null ? void 0 : _b.substring(0, 60);
7806
+ }
7706
7807
  if (!finalName) {
7707
- const nameMatch = item.content.match(/(?:Product|Item|Name):\s*([^\n]+)/i);
7708
- finalName = nameMatch ? nameMatch[1].trim() : item.content.split("\n")[0].substring(0, 60);
7808
+ console.warn(
7809
+ `[UITransformer] Unable to read product name from metadata or content for item ${item.id}. Defaulting to 'Unnamed Product'.`,
7810
+ { metadataKeys: Object.keys(meta), contentLength: content.length }
7811
+ );
7709
7812
  }
7710
7813
  let finalPrice = typeof price === "number" || typeof price === "string" ? price : void 0;
7711
- if (!finalPrice) {
7712
- const priceMatch = item.content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || item.content.match(/\$\s*([\d,.]+)/);
7814
+ if (!finalPrice && content) {
7815
+ const priceMatch = content.match(/(?:Price|Cost):\s*\$?([\d,.]+)/i) || content.match(/\$\s*([\d,.]+)/);
7713
7816
  if (priceMatch) finalPrice = priceMatch[1].replace(/,/g, "");
7714
7817
  }
7818
+ if (finalPrice === void 0) {
7819
+ console.warn(
7820
+ `[UITransformer] Unable to read product price from metadata or content for item ${item.id}.`,
7821
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
7822
+ );
7823
+ }
7715
7824
  const imageValue = this.getDynamicVal(meta, "image", config, trainedSchema);
7825
+ if (!imageValue) {
7826
+ console.debug(
7827
+ `[UITransformer] Unable to read product image URL from metadata for item ${item.id}.`
7828
+ );
7829
+ }
7830
+ if (!description) {
7831
+ console.debug(
7832
+ `[UITransformer] Unable to read product description from metadata or content for item ${item.id}.`
7833
+ );
7834
+ }
7716
7835
  return {
7717
7836
  id: item.id,
7718
- name: finalName,
7837
+ name: finalName || "Unnamed Product",
7719
7838
  price: finalPrice,
7720
7839
  image: typeof imageValue === "string" ? imageValue : void 0,
7721
7840
  brand: brand ? String(brand) : void 0,
7722
7841
  description,
7723
7842
  inStock: this.determineStockStatus(item)
7724
7843
  };
7844
+ } else {
7845
+ console.warn(
7846
+ `[UITransformer] Item ${item.id} skipped: unable to read name or identify as product data from metadata/content.`,
7847
+ { metadataKeys: Object.keys(meta), contentSnippet: content.substring(0, 100) }
7848
+ );
7725
7849
  }
7726
7850
  return null;
7727
7851
  }
@@ -7806,13 +7930,13 @@ RULES:
7806
7930
  5. If no relevant data is found, return text: "I cannot answer this question based on the available information."`;
7807
7931
  }
7808
7932
  static buildContextSummary(sources, maxChars = 6e3) {
7809
- const items = sources.map((s, i) => {
7933
+ const items = (sources || []).filter(Boolean).map((s, i) => {
7810
7934
  var _a2, _b, _c, _d;
7811
7935
  return {
7812
7936
  index: i + 1,
7813
- content: (_b = (_a2 = s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
7814
- metadata: (_c = s.metadata) != null ? _c : {},
7815
- score: (_d = s.score) != null ? _d : 0
7937
+ content: (_b = (_a2 = s == null ? void 0 : s.content) == null ? void 0 : _a2.substring(0, 400)) != null ? _b : "",
7938
+ metadata: (_c = s == null ? void 0 : s.metadata) != null ? _c : {},
7939
+ score: (_d = s == null ? void 0 : s.score) != null ? _d : 0
7816
7940
  };
7817
7941
  });
7818
7942
  const full = JSON.stringify(items, null, 2);
@@ -8381,35 +8505,74 @@ ${m.content}`).join("\n\n---\n\n");
8381
8505
  const hasNumericPredicates = Array.isArray(filter.__numericPredicates) && filter.__numericPredicates.length > 0;
8382
8506
  const wantsExhaustiveList = hasNumericPredicates || hasMetadataFilter || /\b(list|all|show|provide|give|get|browse|find|search|display)\b/i.test(question);
8383
8507
  const retrievalLimit = wantsExhaustiveList ? Math.max(topK * 20, 100) : topK * 2;
8384
- const rawSources = (strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : [];
8508
+ const rawSources = ((strategyResult === "vector" || strategyResult === "both") && queryVector && queryVector.length > 0 ? yield new __await(this.vectorDB.query(queryVector, retrievalLimit, ns, filter)) : []).filter((s) => Boolean(s && typeof s === "object"));
8509
+ console.log("[Pipeline] Raw vectorDB.query response:", {
8510
+ rawCount: rawSources.length,
8511
+ sample: rawSources.slice(0, 2).map((s) => {
8512
+ var _a3;
8513
+ return {
8514
+ id: s == null ? void 0 : s.id,
8515
+ score: s == null ? void 0 : s.score,
8516
+ contentType: typeof (s == null ? void 0 : s.content),
8517
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
8518
+ metadataKeys: Object.keys((s == null ? void 0 : s.metadata) || {})
8519
+ };
8520
+ })
8521
+ });
8385
8522
  const retrieveEnd = performance.now();
8386
8523
  const embedMs = retrieveEnd - embedStart;
8387
8524
  const retrieveMs = retrieveEnd - embedStart;
8388
8525
  const rerankStart = performance.now();
8389
- const structuredSources = this.applyStructuredFilters(rawSources, filter);
8390
- let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => m.score >= scoreThreshold);
8526
+ const structuredSources = this.applyStructuredFilters(rawSources, filter).filter((s) => Boolean(s && typeof s === "object"));
8527
+ let fullSources = hasNumericPredicates ? structuredSources : structuredSources.filter((m) => {
8528
+ var _a3;
8529
+ return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= scoreThreshold;
8530
+ });
8391
8531
  const rerankLimit = wantsExhaustiveList ? retrievalLimit : topK;
8392
8532
  const useReranking = arch !== "naive" && (arch === "retrieve-and-rerank" || ((_m = this.config.rag) == null ? void 0 : _m.useReranking));
8393
8533
  if (!hasNumericPredicates && useReranking) {
8394
- fullSources = yield new __await(this.reranker.rerank(fullSources, question, rerankLimit));
8534
+ fullSources = (yield new __await(this.reranker.rerank(fullSources, question, rerankLimit))).filter((s) => Boolean(s && typeof s === "object"));
8395
8535
  } else if (!wantsExhaustiveList) {
8396
8536
  fullSources = fullSources.slice(0, topK);
8397
8537
  }
8398
8538
  const rerankMs = performance.now() - rerankStart;
8399
- let context = fullSources.length ? fullSources.map((m, i) => `[Source ${i + 1}]
8400
- ${m.content}`).join("\n\n---\n\n") : "No relevant context found.";
8539
+ let context = fullSources.length ? fullSources.map((m, i) => {
8540
+ var _a3;
8541
+ return `[Source ${i + 1}]
8542
+ ${(_a3 = m == null ? void 0 : m.content) != null ? _a3 : ""}`;
8543
+ }).join("\n\n---\n\n") : "No relevant context found.";
8401
8544
  let displayCount = 15;
8402
8545
  if (hasMetadataFilter) {
8403
8546
  displayCount = fullSources.length;
8404
8547
  } else {
8405
8548
  const baseThreshold = Math.max(scoreThreshold, 0.4);
8406
- const highlyRelevant = fullSources.filter((m) => m.score >= baseThreshold);
8549
+ const highlyRelevant = fullSources.filter((m) => {
8550
+ var _a3;
8551
+ return ((_a3 = m == null ? void 0 : m.score) != null ? _a3 : 0) >= baseThreshold;
8552
+ });
8407
8553
  displayCount = Math.max(highlyRelevant.length, topK);
8408
8554
  if (displayCount > 15) {
8409
8555
  displayCount = 15;
8410
8556
  }
8411
8557
  }
8412
- const sources = [...fullSources].sort((a, b) => b.score - a.score).slice(0, displayCount);
8558
+ const sources = [...fullSources].filter((s) => Boolean(s && typeof s === "object")).sort((a, b) => {
8559
+ var _a3, _b2;
8560
+ return ((_a3 = b == null ? void 0 : b.score) != null ? _a3 : 0) - ((_b2 = a == null ? void 0 : a.score) != null ? _b2 : 0);
8561
+ }).slice(0, displayCount);
8562
+ console.log("[Pipeline] Final sources for prompt & UI:", {
8563
+ count: sources.length,
8564
+ sources: sources.map((s, idx) => {
8565
+ var _a3;
8566
+ return {
8567
+ rank: idx + 1,
8568
+ id: s == null ? void 0 : s.id,
8569
+ score: s == null ? void 0 : s.score,
8570
+ contentType: typeof (s == null ? void 0 : s.content),
8571
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
8572
+ metadata: s == null ? void 0 : s.metadata
8573
+ };
8574
+ })
8575
+ });
8413
8576
  if (graphData && graphData.nodes.length > 0) {
8414
8577
  const graphContext = graphData.nodes.map(
8415
8578
  (n) => `Entity: ${n.label} (${n.id})${n.properties ? " - " + JSON.stringify(n.properties) : ""}`
@@ -8435,18 +8598,18 @@ ${context}`;
8435
8598
  }
8436
8599
  yield {
8437
8600
  reply: "",
8438
- sources: sources.map((s) => {
8439
- var _a3;
8601
+ sources: (sources || []).filter((s) => Boolean(s && typeof s === "object")).map((s) => {
8602
+ var _a3, _b2, _c2;
8440
8603
  return {
8441
8604
  id: s.id,
8442
- score: s.score,
8443
- content: s.content,
8444
- metadata: (_a3 = s.metadata) != null ? _a3 : {},
8605
+ score: (_a3 = s.score) != null ? _a3 : 0,
8606
+ content: (_b2 = s == null ? void 0 : s.content) != null ? _b2 : "",
8607
+ metadata: (_c2 = s == null ? void 0 : s.metadata) != null ? _c2 : {},
8445
8608
  namespace: ns
8446
8609
  };
8447
8610
  })
8448
8611
  };
8449
- const allMetadataKeys = Array.from(new Set(sources.flatMap((s) => Object.keys(s.metadata || {}))));
8612
+ const allMetadataKeys = Array.from(new Set(sources.filter(Boolean).flatMap((s) => Object.keys((s == null ? void 0 : s.metadata) || {}))));
8450
8613
  const cachedSchema = allMetadataKeys.length > 0 ? SchemaMapper.getCached(ns, allMetadataKeys) : void 0;
8451
8614
  if (allMetadataKeys.length > 0 && !cachedSchema) {
8452
8615
  SchemaMapper.train(this.llmProvider, ns, allMetadataKeys).catch(() => {
@@ -8481,7 +8644,10 @@ ${context}`;
8481
8644
  if (isSimulatedThinking) {
8482
8645
  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.`)";
8483
8646
  }
8484
- const hardenedHistory = [...history];
8647
+ const hardenedHistory = (Array.isArray(history) ? history : []).filter((m) => Boolean(m && typeof m === "object")).map((m) => ({
8648
+ role: m.role || "user",
8649
+ content: typeof m.content === "string" ? m.content : m.content != null ? String(m.content) : ""
8650
+ }));
8485
8651
  const userQuestion = { role: "user", content: question + finalRestrictionSuffix };
8486
8652
  const messages = [...hardenedHistory, userQuestion];
8487
8653
  const systemPrompt = (_v = this.config.llm.systemPrompt) != null ? _v : "";
@@ -8628,13 +8794,13 @@ ${context}`;
8628
8794
  rewrittenQuery,
8629
8795
  systemPrompt,
8630
8796
  userPrompt: question + finalRestrictionSuffix,
8631
- chunks: sources.map((s) => {
8632
- var _a3;
8797
+ chunks: (sources || []).filter(Boolean).map((s) => {
8798
+ var _a3, _b2;
8633
8799
  return {
8634
8800
  id: s.id,
8635
8801
  score: s.score,
8636
- content: s.content,
8637
- metadata: (_a3 = s.metadata) != null ? _a3 : {},
8802
+ content: (_a3 = s == null ? void 0 : s.content) != null ? _a3 : "",
8803
+ metadata: (_b2 = s == null ? void 0 : s.metadata) != null ? _b2 : {},
8638
8804
  namespace: ns
8639
8805
  };
8640
8806
  }),
@@ -8735,6 +8901,8 @@ ${context}`;
8735
8901
  });
8736
8902
  }
8737
8903
  resolveNumericPredicateValue(source, predicate) {
8904
+ var _a2;
8905
+ if (!source) return null;
8738
8906
  const meta = source.metadata || {};
8739
8907
  const field = predicate.field;
8740
8908
  const entries = Object.entries(meta).filter(([, value]) => value !== null && value !== void 0 && typeof value !== "object");
@@ -8746,7 +8914,7 @@ ${context}`;
8746
8914
  const value = this.toFiniteNumber(Array.isArray(fuzzy) ? fuzzy[1] : fuzzy.value);
8747
8915
  if (value !== null) return value;
8748
8916
  }
8749
- const contentValue = this.extractNumericValueFromContent(source.content, field);
8917
+ const contentValue = this.extractNumericValueFromContent((_a2 = source.content) != null ? _a2 : "", field);
8750
8918
  if (contentValue !== null) return contentValue;
8751
8919
  }
8752
8920
  for (const [key, value] of entries) {
@@ -8757,6 +8925,7 @@ ${context}`;
8757
8925
  return null;
8758
8926
  }
8759
8927
  extractNumericValueFromContent(content, field) {
8928
+ if (!content || typeof content !== "string") return null;
8760
8929
  const escapedWords = field.split(/\s+|_+|-+/).filter(Boolean).map((word) => word.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"));
8761
8930
  if (escapedWords.length === 0) return null;
8762
8931
  const pattern = new RegExp(`(?:${escapedWords.join("[\\\\s_:-]*")})\\s*[:\\-\u2013]?\\s*([\\d,]+(?:\\.\\d+)?)`, "i");
@@ -8842,6 +9011,20 @@ ${context}`;
8842
9011
  resolvedSources.push(source);
8843
9012
  }
8844
9013
  }
9014
+ console.log("[Pipeline] retrieve() response:", {
9015
+ query,
9016
+ namespace: ns,
9017
+ count: resolvedSources.length,
9018
+ sample: resolvedSources.slice(0, 2).map((s) => {
9019
+ var _a3;
9020
+ return {
9021
+ id: s == null ? void 0 : s.id,
9022
+ score: s == null ? void 0 : s.score,
9023
+ contentSnippet: String((_a3 = s == null ? void 0 : s.content) != null ? _a3 : "").substring(0, 150),
9024
+ metadata: s == null ? void 0 : s.metadata
9025
+ };
9026
+ })
9027
+ });
8845
9028
  return { sources: resolvedSources, graphData };
8846
9029
  }
8847
9030
  /** Rewrite the user query for better retrieval performance. */
@@ -9535,6 +9718,7 @@ import { NextResponse } from "next/server";
9535
9718
  // src/core/DatabaseStorage.ts
9536
9719
  import * as fs from "fs";
9537
9720
  import * as path from "path";
9721
+ import * as os from "os";
9538
9722
  var DatabaseStorage = class {
9539
9723
  constructor(config) {
9540
9724
  // Dynamic PG Pool
@@ -9543,7 +9727,8 @@ var DatabaseStorage = class {
9543
9727
  this.mongoClient = null;
9544
9728
  this.mongoDbName = "";
9545
9729
  // Filesystem fallback configuration
9546
- this.fallbackDir = path.join(process.cwd(), ".retrivora");
9730
+ this.isServerless = Boolean(process.env.VERCEL || process.env.AWS_LAMBDA_FUNCTION_NAME || process.env.LAMBDA_TASK_ROOT);
9731
+ this.fallbackDir = this.isServerless ? path.join(os.tmpdir(), ".retrivora") : path.join(process.cwd(), ".retrivora");
9547
9732
  this.historyFile = path.join(this.fallbackDir, "history.json");
9548
9733
  this.feedbackFile = path.join(this.fallbackDir, "feedback.json");
9549
9734
  var _a2, _b, _c, _d, _e;
@@ -9673,10 +9858,27 @@ var DatabaseStorage = class {
9673
9858
  }
9674
9859
  // Helper for FS fallback writes
9675
9860
  writeLocalFile(filePath, data) {
9676
- if (!fs.existsSync(this.fallbackDir)) {
9677
- fs.mkdirSync(this.fallbackDir, { recursive: true });
9861
+ try {
9862
+ const dir = path.dirname(filePath);
9863
+ if (!fs.existsSync(dir)) {
9864
+ fs.mkdirSync(dir, { recursive: true });
9865
+ }
9866
+ fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
9867
+ } catch (err) {
9868
+ if (err.code === "EROFS") {
9869
+ try {
9870
+ const tmpDir = path.join(os.tmpdir(), ".retrivora");
9871
+ if (!fs.existsSync(tmpDir)) {
9872
+ fs.mkdirSync(tmpDir, { recursive: true });
9873
+ }
9874
+ const tmpFilePath = path.join(tmpDir, path.basename(filePath));
9875
+ fs.writeFileSync(tmpFilePath, JSON.stringify(data, null, 2), "utf-8");
9876
+ } catch (e) {
9877
+ }
9878
+ } else {
9879
+ console.warn(`[DatabaseStorage] Failed to write local fallback file: ${err.message}`);
9880
+ }
9678
9881
  }
9679
- fs.writeFileSync(filePath, JSON.stringify(data, null, 2), "utf-8");
9680
9882
  }
9681
9883
  // ─── Message History Operations ──────────────────────────────────────────
9682
9884
  async saveMessage(sessionId, message) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retrivora-ai/rag-engine",
3
- "version": "2.0.5",
3
+ "version": "2.0.7",
4
4
  "description": "Retrivora AI is a plug-and-play AI engine for RAG chat experiences — generic vector DB + LLM provider, embeddable or standalone.",
5
5
  "author": "Abhinav Alkuchi",
6
6
  "license": "UNLICENSED",