@juspay/neurolink 8.31.2 → 8.31.3
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/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
## [8.31.3](https://github.com/juspay/neurolink/compare/v8.31.2...v8.31.3) (2026-01-05)
|
|
2
|
+
|
|
3
|
+
### Bug Fixes
|
|
4
|
+
|
|
5
|
+
- **(csv):** standardize rowCount to exclude empty lines across all formats (CSV-025) ([c898521](https://github.com/juspay/neurolink/commit/c8985212ff6bb43a6cefbf7a5551ed603b32bc55)), closes [#390](https://github.com/juspay/neurolink/issues/390)
|
|
6
|
+
|
|
1
7
|
## [8.31.2](https://github.com/juspay/neurolink/compare/v8.31.1...v8.31.2) (2026-01-05)
|
|
2
8
|
|
|
3
9
|
### Bug Fixes
|
|
@@ -85,8 +85,12 @@ export class CSVProcessor {
|
|
|
85
85
|
: lines;
|
|
86
86
|
const limitedLines = csvLines.slice(0, 1 + maxRows); // header + data rows
|
|
87
87
|
const limitedCSV = limitedLines.join("\n");
|
|
88
|
-
const rowCount = limitedLines
|
|
89
|
-
|
|
88
|
+
const rowCount = limitedLines
|
|
89
|
+
.slice(1)
|
|
90
|
+
.filter((line) => line.trim() !== "").length;
|
|
91
|
+
const originalRowCount = csvLines
|
|
92
|
+
.slice(1)
|
|
93
|
+
.filter((line) => line.trim() !== "").length;
|
|
90
94
|
const wasTruncated = rowCount < originalRowCount;
|
|
91
95
|
if (wasTruncated) {
|
|
92
96
|
logger.warn(`[CSVProcessor] CSV data truncated: showing ${rowCount} of ${originalRowCount} rows (limit: ${maxRows})`);
|
|
@@ -110,6 +114,7 @@ export class CSVProcessor {
|
|
|
110
114
|
confidence: 100,
|
|
111
115
|
size: content.length,
|
|
112
116
|
rowCount,
|
|
117
|
+
totalLines: limitedLines.length,
|
|
113
118
|
columnCount: (limitedLines[0] || "").split(",").length,
|
|
114
119
|
extension,
|
|
115
120
|
},
|
|
@@ -121,12 +126,26 @@ export class CSVProcessor {
|
|
|
121
126
|
maxRows,
|
|
122
127
|
});
|
|
123
128
|
const rows = await this.parseCSVString(csvString, maxRows);
|
|
129
|
+
// Filter out empty rows (empty objects or rows with only whitespace values from blank lines)
|
|
130
|
+
const nonEmptyRows = rows.filter((row) => {
|
|
131
|
+
if (!row || typeof row !== "object") {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
const keys = Object.keys(row);
|
|
135
|
+
if (keys.length === 0) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
// Check if all values are empty or whitespace-only
|
|
139
|
+
return !Object.values(row).every((val) => val === "" || (typeof val === "string" && val.trim() === ""));
|
|
140
|
+
});
|
|
124
141
|
// Extract metadata from parsed results
|
|
125
|
-
const rowCount =
|
|
126
|
-
const columnNames =
|
|
142
|
+
const rowCount = nonEmptyRows.length;
|
|
143
|
+
const columnNames = nonEmptyRows.length > 0
|
|
144
|
+
? Object.keys(nonEmptyRows[0])
|
|
145
|
+
: [];
|
|
127
146
|
const columnCount = columnNames.length;
|
|
128
147
|
const hasEmptyColumns = columnNames.some((col) => !col || col.trim() === "");
|
|
129
|
-
const sampleRows =
|
|
148
|
+
const sampleRows = nonEmptyRows.slice(0, 3);
|
|
130
149
|
const sampleData = this.formatSampleData(sampleRows, sampleDataFormat, includeHeaders);
|
|
131
150
|
if (hasEmptyColumns) {
|
|
132
151
|
logger.warn("[CSVProcessor] CSV contains empty or blank column headers", {
|
|
@@ -138,7 +157,7 @@ export class CSVProcessor {
|
|
|
138
157
|
}
|
|
139
158
|
// Format parsed data
|
|
140
159
|
logger.debug(`[CSVProcessor] Converting ${rowCount} rows to ${formatStyle} format`);
|
|
141
|
-
const formatted = this.formatForLLM(
|
|
160
|
+
const formatted = this.formatForLLM(nonEmptyRows, formatStyle, includeHeaders);
|
|
142
161
|
logger.info("[CSVProcessor] ✅ Processed CSV file", {
|
|
143
162
|
formatStyle,
|
|
144
163
|
rowCount,
|
|
@@ -85,8 +85,12 @@ export class CSVProcessor {
|
|
|
85
85
|
: lines;
|
|
86
86
|
const limitedLines = csvLines.slice(0, 1 + maxRows); // header + data rows
|
|
87
87
|
const limitedCSV = limitedLines.join("\n");
|
|
88
|
-
const rowCount = limitedLines
|
|
89
|
-
|
|
88
|
+
const rowCount = limitedLines
|
|
89
|
+
.slice(1)
|
|
90
|
+
.filter((line) => line.trim() !== "").length;
|
|
91
|
+
const originalRowCount = csvLines
|
|
92
|
+
.slice(1)
|
|
93
|
+
.filter((line) => line.trim() !== "").length;
|
|
90
94
|
const wasTruncated = rowCount < originalRowCount;
|
|
91
95
|
if (wasTruncated) {
|
|
92
96
|
logger.warn(`[CSVProcessor] CSV data truncated: showing ${rowCount} of ${originalRowCount} rows (limit: ${maxRows})`);
|
|
@@ -110,6 +114,7 @@ export class CSVProcessor {
|
|
|
110
114
|
confidence: 100,
|
|
111
115
|
size: content.length,
|
|
112
116
|
rowCount,
|
|
117
|
+
totalLines: limitedLines.length,
|
|
113
118
|
columnCount: (limitedLines[0] || "").split(",").length,
|
|
114
119
|
extension,
|
|
115
120
|
},
|
|
@@ -121,12 +126,26 @@ export class CSVProcessor {
|
|
|
121
126
|
maxRows,
|
|
122
127
|
});
|
|
123
128
|
const rows = await this.parseCSVString(csvString, maxRows);
|
|
129
|
+
// Filter out empty rows (empty objects or rows with only whitespace values from blank lines)
|
|
130
|
+
const nonEmptyRows = rows.filter((row) => {
|
|
131
|
+
if (!row || typeof row !== "object") {
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
const keys = Object.keys(row);
|
|
135
|
+
if (keys.length === 0) {
|
|
136
|
+
return false;
|
|
137
|
+
}
|
|
138
|
+
// Check if all values are empty or whitespace-only
|
|
139
|
+
return !Object.values(row).every((val) => val === "" || (typeof val === "string" && val.trim() === ""));
|
|
140
|
+
});
|
|
124
141
|
// Extract metadata from parsed results
|
|
125
|
-
const rowCount =
|
|
126
|
-
const columnNames =
|
|
142
|
+
const rowCount = nonEmptyRows.length;
|
|
143
|
+
const columnNames = nonEmptyRows.length > 0
|
|
144
|
+
? Object.keys(nonEmptyRows[0])
|
|
145
|
+
: [];
|
|
127
146
|
const columnCount = columnNames.length;
|
|
128
147
|
const hasEmptyColumns = columnNames.some((col) => !col || col.trim() === "");
|
|
129
|
-
const sampleRows =
|
|
148
|
+
const sampleRows = nonEmptyRows.slice(0, 3);
|
|
130
149
|
const sampleData = this.formatSampleData(sampleRows, sampleDataFormat, includeHeaders);
|
|
131
150
|
if (hasEmptyColumns) {
|
|
132
151
|
logger.warn("[CSVProcessor] CSV contains empty or blank column headers", {
|
|
@@ -138,7 +157,7 @@ export class CSVProcessor {
|
|
|
138
157
|
}
|
|
139
158
|
// Format parsed data
|
|
140
159
|
logger.debug(`[CSVProcessor] Converting ${rowCount} rows to ${formatStyle} format`);
|
|
141
|
-
const formatted = this.formatForLLM(
|
|
160
|
+
const formatted = this.formatForLLM(nonEmptyRows, formatStyle, includeHeaders);
|
|
142
161
|
logger.info("[CSVProcessor] ✅ Processed CSV file", {
|
|
143
162
|
formatStyle,
|
|
144
163
|
rowCount,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "8.31.
|
|
3
|
+
"version": "8.31.3",
|
|
4
4
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, and professional CLI. Built-in tools operational, 58+ external MCP servers discoverable. Connect to filesystem, GitHub, database operations, and more. Build, test, and deploy AI applications with 13 providers: OpenAI, Anthropic, Google AI, AWS Bedrock, Azure, Hugging Face, Ollama, and Mistral AI.",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "Juspay Technologies",
|