@retrivora-ai/rag-engine 1.4.7 → 1.4.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -2257,22 +2257,25 @@ var Pipeline = class {
2257
2257
  this.reranker = new Reranker();
2258
2258
  }
2259
2259
  async initialize() {
2260
- var _a;
2260
+ var _a, _b;
2261
2261
  if (this.initialised) return;
2262
+ const CHART_MARKER = "<!-- VIZ_PROTOCOL_V1 -->";
2262
2263
  const chartInstruction = `
2263
2264
 
2264
- ### VISUALIZATION PROTOCOL:
2265
- When requested to show data visually (charts, graphs, or comparisons), you MUST use this format:
2266
- 1. Wrap the data in a fenced code block with the language 'chart'.
2267
- 2. Use ONLY valid JSON matching this schema:
2265
+ ${CHART_MARKER}
2266
+ ### MASTER DATA VISUALIZATION PROTOCOL:
2267
+ You are an expert data analyst. When asked to visualize or compare data retrieved from the context:
2268
+ 1. DECIDE the best chart type: 'pie' (for parts-of-a-whole), 'bar' (for category comparisons), or 'line' (for trends).
2269
+ 2. TRANSFORM arbitrary metadata from the context into a FLAT list of objects. Extract relevant keys dynamically.
2270
+ 3. OUTPUT a \`\`\`chart\`\`\` code block using this JSON format:
2268
2271
  {
2269
2272
  "type": "bar" | "line" | "pie",
2270
- "xAxisKey": "property_for_label",
2271
- "dataKeys": ["property_for_value"],
2272
- "data": [{ "property_for_label": "A", "property_for_value": 10 }]
2273
+ "xAxisKey": "key_for_labels",
2274
+ "dataKeys": ["key_for_values"],
2275
+ "data": [ { "key_for_labels": "Category A", "key_for_values": 100 }, ... ]
2273
2276
  }
2274
- 3. RULES: Data objects MUST be FLAT (no nesting). No math expressions in JSON. NEVER draw charts with text or markdown tables.`;
2275
- if (!this.config.llm.systemPrompt || !this.config.llm.systemPrompt.includes("chart")) {
2277
+ 4. RULES: Valid JSON only. No math. No text-based charts. No markdown tables for graphs. If showing a chart, DO NOT output a "products" JSON carousel.`;
2278
+ if (!((_a = this.config.llm.systemPrompt) == null ? void 0 : _a.includes(CHART_MARKER))) {
2276
2279
  this.config.llm.systemPrompt = (this.config.llm.systemPrompt || "") + chartInstruction;
2277
2280
  }
2278
2281
  console.log(`[Pipeline] Initializing with provider: ${this.config.vectorDb.provider}...`);
@@ -2289,7 +2292,7 @@ When requested to show data visually (charts, graphs, or comparisons), you MUST
2289
2292
  this.entityExtractor = new EntityExtractor(this.llmProvider);
2290
2293
  }
2291
2294
  await this.vectorDB.initialize();
2292
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic") {
2295
+ if (((_b = this.config.rag) == null ? void 0 : _b.architecture) === "agentic") {
2293
2296
  this.agent = new LangChainAgent(this, this.config);
2294
2297
  await this.agent.initialize(this.llmProvider);
2295
2298
  }
@@ -3820,22 +3820,25 @@ var Pipeline = class {
3820
3820
  this.reranker = new Reranker();
3821
3821
  }
3822
3822
  async initialize() {
3823
- var _a;
3823
+ var _a, _b;
3824
3824
  if (this.initialised) return;
3825
+ const CHART_MARKER = "<!-- VIZ_PROTOCOL_V1 -->";
3825
3826
  const chartInstruction = `
3826
3827
 
3827
- ### VISUALIZATION PROTOCOL:
3828
- When requested to show data visually (charts, graphs, or comparisons), you MUST use this format:
3829
- 1. Wrap the data in a fenced code block with the language 'chart'.
3830
- 2. Use ONLY valid JSON matching this schema:
3828
+ ${CHART_MARKER}
3829
+ ### MASTER DATA VISUALIZATION PROTOCOL:
3830
+ You are an expert data analyst. When asked to visualize or compare data retrieved from the context:
3831
+ 1. DECIDE the best chart type: 'pie' (for parts-of-a-whole), 'bar' (for category comparisons), or 'line' (for trends).
3832
+ 2. TRANSFORM arbitrary metadata from the context into a FLAT list of objects. Extract relevant keys dynamically.
3833
+ 3. OUTPUT a \`\`\`chart\`\`\` code block using this JSON format:
3831
3834
  {
3832
3835
  "type": "bar" | "line" | "pie",
3833
- "xAxisKey": "property_for_label",
3834
- "dataKeys": ["property_for_value"],
3835
- "data": [{ "property_for_label": "A", "property_for_value": 10 }]
3836
+ "xAxisKey": "key_for_labels",
3837
+ "dataKeys": ["key_for_values"],
3838
+ "data": [ { "key_for_labels": "Category A", "key_for_values": 100 }, ... ]
3836
3839
  }
3837
- 3. RULES: Data objects MUST be FLAT (no nesting). No math expressions in JSON. NEVER draw charts with text or markdown tables.`;
3838
- if (!this.config.llm.systemPrompt || !this.config.llm.systemPrompt.includes("chart")) {
3840
+ 4. RULES: Valid JSON only. No math. No text-based charts. No markdown tables for graphs. If showing a chart, DO NOT output a "products" JSON carousel.`;
3841
+ if (!((_a = this.config.llm.systemPrompt) == null ? void 0 : _a.includes(CHART_MARKER))) {
3839
3842
  this.config.llm.systemPrompt = (this.config.llm.systemPrompt || "") + chartInstruction;
3840
3843
  }
3841
3844
  console.log(`[Pipeline] Initializing with provider: ${this.config.vectorDb.provider}...`);
@@ -3852,7 +3855,7 @@ When requested to show data visually (charts, graphs, or comparisons), you MUST
3852
3855
  this.entityExtractor = new EntityExtractor(this.llmProvider);
3853
3856
  }
3854
3857
  await this.vectorDB.initialize();
3855
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic") {
3858
+ if (((_b = this.config.rag) == null ? void 0 : _b.architecture) === "agentic") {
3856
3859
  this.agent = new LangChainAgent(this, this.config);
3857
3860
  await this.agent.initialize(this.llmProvider);
3858
3861
  }
@@ -9,7 +9,7 @@ import {
9
9
  sseFrame,
10
10
  sseMetaFrame,
11
11
  sseTextFrame
12
- } from "../chunk-YCL23GST.mjs";
12
+ } from "../chunk-FHNGNXXS.mjs";
13
13
  import "../chunk-YLTMFW4M.mjs";
14
14
  import "../chunk-X4TOT24V.mjs";
15
15
  export {
package/dist/index.js CHANGED
@@ -235,13 +235,21 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
235
235
  Object.keys(subItem).forEach((sk) => {
236
236
  const subVal = subItem[sk];
237
237
  if (typeof subVal !== "object" || subVal === null) {
238
- newItem[sk] = subVal;
238
+ if (typeof subVal === "string" && !isNaN(Number(subVal)) && subVal.trim() !== "") {
239
+ newItem[sk] = Number(subVal);
240
+ } else {
241
+ newItem[sk] = subVal;
242
+ }
239
243
  }
240
244
  });
241
245
  }
242
246
  });
243
247
  } else if (typeof val !== "object" || val === null) {
244
- newItem[k] = val;
248
+ if (typeof val === "string" && !isNaN(Number(val)) && val.trim() !== "") {
249
+ newItem[k] = Number(val);
250
+ } else {
251
+ newItem[k] = val;
252
+ }
245
253
  }
246
254
  });
247
255
  return newItem;
@@ -250,7 +258,7 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
250
258
  if (!data || data.length === 0) {
251
259
  return /* @__PURE__ */ import_react4.default.createElement("div", { className: "p-4 text-sm text-slate-500" }, "No data available for chart.");
252
260
  }
253
- const firstItem = data[0];
261
+ const firstItem = sanitizedData[0];
254
262
  const allKeys = Object.keys(firstItem);
255
263
  const resolvedXKey = config.xAxisKey && firstItem[config.xAxisKey] !== void 0 ? config.xAxisKey : allKeys.find((k) => k.toLowerCase() === "name" || k.toLowerCase() === "label" || k.toLowerCase() === "category") || allKeys.find((k) => typeof firstItem[k] === "string") || allKeys[0];
256
264
  const resolvedDataKeys = config.dataKeys && config.dataKeys.every((k) => {
@@ -497,6 +505,10 @@ function MessageBubble({
497
505
  }, [sources, isUser]);
498
506
  const { productsFromContent, cleanContent } = import_react5.default.useMemo(() => {
499
507
  if (isUser) return { productsFromContent: [], cleanContent: message.content };
508
+ const isVisualization = message.content.includes("```chart") || message.content.toLowerCase().includes("pie chart") || message.content.toLowerCase().includes("bar chart") || message.content.toLowerCase().includes("distribution");
509
+ if (isVisualization) {
510
+ return { productsFromContent: [], cleanContent: message.content };
511
+ }
500
512
  const jsonRegex = /```json\s*([\s\S]*?)\s*```/g;
501
513
  const products = [];
502
514
  let content = message.content;
package/dist/index.mjs CHANGED
@@ -198,13 +198,21 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
198
198
  Object.keys(subItem).forEach((sk) => {
199
199
  const subVal = subItem[sk];
200
200
  if (typeof subVal !== "object" || subVal === null) {
201
- newItem[sk] = subVal;
201
+ if (typeof subVal === "string" && !isNaN(Number(subVal)) && subVal.trim() !== "") {
202
+ newItem[sk] = Number(subVal);
203
+ } else {
204
+ newItem[sk] = subVal;
205
+ }
202
206
  }
203
207
  });
204
208
  }
205
209
  });
206
210
  } else if (typeof val !== "object" || val === null) {
207
- newItem[k] = val;
211
+ if (typeof val === "string" && !isNaN(Number(val)) && val.trim() !== "") {
212
+ newItem[k] = Number(val);
213
+ } else {
214
+ newItem[k] = val;
215
+ }
208
216
  }
209
217
  });
210
218
  return newItem;
@@ -213,7 +221,7 @@ function DynamicChart({ config, primaryColor = "#6366f1", accentColor = "#8b5cf6
213
221
  if (!data || data.length === 0) {
214
222
  return /* @__PURE__ */ React4.createElement("div", { className: "p-4 text-sm text-slate-500" }, "No data available for chart.");
215
223
  }
216
- const firstItem = data[0];
224
+ const firstItem = sanitizedData[0];
217
225
  const allKeys = Object.keys(firstItem);
218
226
  const resolvedXKey = config.xAxisKey && firstItem[config.xAxisKey] !== void 0 ? config.xAxisKey : allKeys.find((k) => k.toLowerCase() === "name" || k.toLowerCase() === "label" || k.toLowerCase() === "category") || allKeys.find((k) => typeof firstItem[k] === "string") || allKeys[0];
219
227
  const resolvedDataKeys = config.dataKeys && config.dataKeys.every((k) => {
@@ -460,6 +468,10 @@ function MessageBubble({
460
468
  }, [sources, isUser]);
461
469
  const { productsFromContent, cleanContent } = React5.useMemo(() => {
462
470
  if (isUser) return { productsFromContent: [], cleanContent: message.content };
471
+ const isVisualization = message.content.includes("```chart") || message.content.toLowerCase().includes("pie chart") || message.content.toLowerCase().includes("bar chart") || message.content.toLowerCase().includes("distribution");
472
+ if (isVisualization) {
473
+ return { productsFromContent: [], cleanContent: message.content };
474
+ }
463
475
  const jsonRegex = /```json\s*([\s\S]*?)\s*```/g;
464
476
  const products = [];
465
477
  let content = message.content;
package/dist/server.js CHANGED
@@ -3911,22 +3911,25 @@ var Pipeline = class {
3911
3911
  this.reranker = new Reranker();
3912
3912
  }
3913
3913
  async initialize() {
3914
- var _a;
3914
+ var _a, _b;
3915
3915
  if (this.initialised) return;
3916
+ const CHART_MARKER = "<!-- VIZ_PROTOCOL_V1 -->";
3916
3917
  const chartInstruction = `
3917
3918
 
3918
- ### VISUALIZATION PROTOCOL:
3919
- When requested to show data visually (charts, graphs, or comparisons), you MUST use this format:
3920
- 1. Wrap the data in a fenced code block with the language 'chart'.
3921
- 2. Use ONLY valid JSON matching this schema:
3919
+ ${CHART_MARKER}
3920
+ ### MASTER DATA VISUALIZATION PROTOCOL:
3921
+ You are an expert data analyst. When asked to visualize or compare data retrieved from the context:
3922
+ 1. DECIDE the best chart type: 'pie' (for parts-of-a-whole), 'bar' (for category comparisons), or 'line' (for trends).
3923
+ 2. TRANSFORM arbitrary metadata from the context into a FLAT list of objects. Extract relevant keys dynamically.
3924
+ 3. OUTPUT a \`\`\`chart\`\`\` code block using this JSON format:
3922
3925
  {
3923
3926
  "type": "bar" | "line" | "pie",
3924
- "xAxisKey": "property_for_label",
3925
- "dataKeys": ["property_for_value"],
3926
- "data": [{ "property_for_label": "A", "property_for_value": 10 }]
3927
+ "xAxisKey": "key_for_labels",
3928
+ "dataKeys": ["key_for_values"],
3929
+ "data": [ { "key_for_labels": "Category A", "key_for_values": 100 }, ... ]
3927
3930
  }
3928
- 3. RULES: Data objects MUST be FLAT (no nesting). No math expressions in JSON. NEVER draw charts with text or markdown tables.`;
3929
- if (!this.config.llm.systemPrompt || !this.config.llm.systemPrompt.includes("chart")) {
3931
+ 4. RULES: Valid JSON only. No math. No text-based charts. No markdown tables for graphs. If showing a chart, DO NOT output a "products" JSON carousel.`;
3932
+ if (!((_a = this.config.llm.systemPrompt) == null ? void 0 : _a.includes(CHART_MARKER))) {
3930
3933
  this.config.llm.systemPrompt = (this.config.llm.systemPrompt || "") + chartInstruction;
3931
3934
  }
3932
3935
  console.log(`[Pipeline] Initializing with provider: ${this.config.vectorDb.provider}...`);
@@ -3943,7 +3946,7 @@ When requested to show data visually (charts, graphs, or comparisons), you MUST
3943
3946
  this.entityExtractor = new EntityExtractor(this.llmProvider);
3944
3947
  }
3945
3948
  await this.vectorDB.initialize();
3946
- if (((_a = this.config.rag) == null ? void 0 : _a.architecture) === "agentic") {
3949
+ if (((_b = this.config.rag) == null ? void 0 : _b.architecture) === "agentic") {
3947
3950
  this.agent = new LangChainAgent(this, this.config);
3948
3951
  await this.agent.initialize(this.llmProvider);
3949
3952
  }
package/dist/server.mjs CHANGED
@@ -39,7 +39,7 @@ import {
39
39
  sseFrame,
40
40
  sseMetaFrame,
41
41
  sseTextFrame
42
- } from "./chunk-YCL23GST.mjs";
42
+ } from "./chunk-FHNGNXXS.mjs";
43
43
  import "./chunk-YLTMFW4M.mjs";
44
44
  import {
45
45
  PineconeProvider
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@retrivora-ai/rag-engine",
3
- "version": "1.4.7",
3
+ "version": "1.4.9",
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": "MIT",
@@ -29,6 +29,8 @@ export function DynamicChart({ config, primaryColor = '#6366f1', accentColor = '
29
29
  // CRITICAL: Sanitize the data array to remove any non-primitive values (objects/arrays)
30
30
  // This prevents the "Objects are not valid as a React child" error in Tooltips/Legends
31
31
  // This hook MUST be called before any early returns to satisfy React rules
32
+ // CRITICAL: Sanitize the data array to remove any non-primitive values (objects/arrays)
33
+ // Also ensures numeric strings are converted to actual numbers for Recharts.
32
34
  const sanitizedData = React.useMemo(() => {
33
35
  if (!data) return [];
34
36
  return data.map(item => {
@@ -36,19 +38,28 @@ export function DynamicChart({ config, primaryColor = '#6366f1', accentColor = '
36
38
  Object.keys(item).forEach(k => {
37
39
  const val = item[k];
38
40
  if (Array.isArray(val)) {
39
- // If the LLM output nested arrays, attempt to flatten them
40
41
  val.forEach(subItem => {
41
42
  if (typeof subItem === 'object' && subItem !== null) {
42
43
  Object.keys(subItem).forEach(sk => {
43
44
  const subVal = (subItem as Record<string, unknown>)[sk];
44
45
  if (typeof subVal !== 'object' || subVal === null) {
45
- newItem[sk] = subVal as string | number | null;
46
+ // Auto-convert numeric strings
47
+ if (typeof subVal === 'string' && !isNaN(Number(subVal)) && subVal.trim() !== '') {
48
+ newItem[sk] = Number(subVal);
49
+ } else {
50
+ newItem[sk] = subVal as string | number | null;
51
+ }
46
52
  }
47
53
  });
48
54
  }
49
55
  });
50
56
  } else if (typeof val !== 'object' || val === null) {
51
- newItem[k] = val as string | number | null;
57
+ // Auto-convert numeric strings
58
+ if (typeof val === 'string' && !isNaN(Number(val)) && val.trim() !== '') {
59
+ newItem[k] = Number(val);
60
+ } else {
61
+ newItem[k] = val as string | number | null;
62
+ }
52
63
  }
53
64
  });
54
65
  return newItem;
@@ -60,7 +71,7 @@ export function DynamicChart({ config, primaryColor = '#6366f1', accentColor = '
60
71
  }
61
72
 
62
73
  // Smart key resolution: if the provided keys don't exist in the data, try to guess them
63
- const firstItem = data[0];
74
+ const firstItem = sanitizedData[0];
64
75
  const allKeys = Object.keys(firstItem);
65
76
 
66
77
  // Resolve xAxisKey: use provided, fallback to 'name', 'label', 'category', or the first string key
@@ -71,7 +82,6 @@ export function DynamicChart({ config, primaryColor = '#6366f1', accentColor = '
71
82
  || allKeys[0];
72
83
 
73
84
  // Resolve dataKeys: use provided, fallback to 'value', 'count', 'amount', or all numeric keys
74
- // CRITICAL: Filter out any keys that point to objects/arrays to prevent React render errors
75
85
  const resolvedDataKeys = config.dataKeys && config.dataKeys.every(k => {
76
86
  const val = firstItem[k];
77
87
  return val !== undefined && typeof val !== 'object';
@@ -313,6 +313,17 @@ export function MessageBubble({
313
313
  const { productsFromContent, cleanContent } = React.useMemo(() => {
314
314
  if (isUser) return { productsFromContent: [] as Product[], cleanContent: message.content };
315
315
 
316
+ // If the message contains a chart or refers to visualization, suppress the product carousel
317
+ const isVisualization =
318
+ message.content.includes('```chart') ||
319
+ message.content.toLowerCase().includes('pie chart') ||
320
+ message.content.toLowerCase().includes('bar chart') ||
321
+ message.content.toLowerCase().includes('distribution');
322
+
323
+ if (isVisualization) {
324
+ return { productsFromContent: [] as Product[], cleanContent: message.content };
325
+ }
326
+
316
327
  const jsonRegex = /```json\s*([\s\S]*?)\s*```/g;
317
328
  const products: Product[] = [];
318
329
  let content = message.content;
@@ -100,20 +100,23 @@ export class Pipeline {
100
100
  if (this.initialised) return;
101
101
 
102
102
  // Augment system prompt with a Universal Visualization Protocol
103
- const chartInstruction = `\n\n### VISUALIZATION PROTOCOL:
104
- When requested to show data visually (charts, graphs, or comparisons), you MUST use this format:
105
- 1. Wrap the data in a fenced code block with the language 'chart'.
106
- 2. Use ONLY valid JSON matching this schema:
103
+ // We use a unique marker to ensure this is only injected once but is ALWAYS present.
104
+ const CHART_MARKER = '<!-- VIZ_PROTOCOL_V1 -->';
105
+ const chartInstruction = `\n\n${CHART_MARKER}
106
+ ### MASTER DATA VISUALIZATION PROTOCOL:
107
+ You are an expert data analyst. When asked to visualize or compare data retrieved from the context:
108
+ 1. DECIDE the best chart type: 'pie' (for parts-of-a-whole), 'bar' (for category comparisons), or 'line' (for trends).
109
+ 2. TRANSFORM arbitrary metadata from the context into a FLAT list of objects. Extract relevant keys dynamically.
110
+ 3. OUTPUT a \`\`\`chart\`\`\` code block using this JSON format:
107
111
  {
108
112
  "type": "bar" | "line" | "pie",
109
- "xAxisKey": "property_for_label",
110
- "dataKeys": ["property_for_value"],
111
- "data": [{ "property_for_label": "A", "property_for_value": 10 }]
113
+ "xAxisKey": "key_for_labels",
114
+ "dataKeys": ["key_for_values"],
115
+ "data": [ { "key_for_labels": "Category A", "key_for_values": 100 }, ... ]
112
116
  }
113
- 3. RULES: Data objects MUST be FLAT (no nesting). No math expressions in JSON. NEVER draw charts with text or markdown tables.`;
117
+ 4. RULES: Valid JSON only. No math. No text-based charts. No markdown tables for graphs. If showing a chart, DO NOT output a "products" JSON carousel.`;
114
118
 
115
- // Inject chart instructions if not already present (including when systemPrompt is undefined)
116
- if (!this.config.llm.systemPrompt || !this.config.llm.systemPrompt.includes('chart')) {
119
+ if (!this.config.llm.systemPrompt?.includes(CHART_MARKER)) {
117
120
  this.config.llm.systemPrompt = (this.config.llm.systemPrompt || '') + chartInstruction;
118
121
  }
119
122