@juspay/neurolink 9.84.0 → 9.84.2
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 +12 -0
- package/dist/browser/neurolink.min.js +311 -312
- package/dist/lib/utils/csvProcessor.js +59 -8
- package/dist/utils/csvProcessor.js +59 -8
- package/package.json +4 -3
|
@@ -444,6 +444,47 @@ function isMetadataLine(lines) {
|
|
|
444
444
|
}
|
|
445
445
|
return false;
|
|
446
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Split CSV text into logical rows for metadata detection and raw row limiting.
|
|
449
|
+
*
|
|
450
|
+
* Supports Unix (LF), Windows (CRLF), and classic Mac (CR) line endings, and is
|
|
451
|
+
* quote-aware: a line ending that appears *inside* a quoted field (RFC 4180) is
|
|
452
|
+
* kept as part of that field rather than treated as a row boundary. A doubled
|
|
453
|
+
* `""` inside quotes is the RFC-4180 escaped quote and does not toggle the quote
|
|
454
|
+
* state. For unquoted input this yields exactly the same result as a plain
|
|
455
|
+
* `split(/\r\n|\n|\r/)`.
|
|
456
|
+
*/
|
|
457
|
+
function splitCsvLines(csvString) {
|
|
458
|
+
const rows = [];
|
|
459
|
+
let current = "";
|
|
460
|
+
let inQuotes = false;
|
|
461
|
+
for (let i = 0; i < csvString.length; i++) {
|
|
462
|
+
const ch = csvString[i];
|
|
463
|
+
if (ch === '"') {
|
|
464
|
+
if (inQuotes && csvString[i + 1] === '"') {
|
|
465
|
+
// Escaped quote ("") — stays inside the field, quote state unchanged.
|
|
466
|
+
current += '""';
|
|
467
|
+
i++;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
inQuotes = !inQuotes;
|
|
471
|
+
current += ch;
|
|
472
|
+
}
|
|
473
|
+
else if (!inQuotes && (ch === "\n" || ch === "\r")) {
|
|
474
|
+
// Row boundary outside quotes; collapse CRLF into a single boundary.
|
|
475
|
+
if (ch === "\r" && csvString[i + 1] === "\n") {
|
|
476
|
+
i++;
|
|
477
|
+
}
|
|
478
|
+
rows.push(current);
|
|
479
|
+
current = "";
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
current += ch;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
rows.push(current);
|
|
486
|
+
return rows;
|
|
487
|
+
}
|
|
447
488
|
/**
|
|
448
489
|
* CSV processor for converting CSV data to LLM-optimized formats
|
|
449
490
|
*
|
|
@@ -483,10 +524,10 @@ export class CSVProcessor {
|
|
|
483
524
|
includeHeaders,
|
|
484
525
|
});
|
|
485
526
|
const csvString = content.toString("utf-8");
|
|
486
|
-
// For raw format, return
|
|
487
|
-
// This preserves the
|
|
527
|
+
// For raw format, return CSV text with row limit (no parsing needed)
|
|
528
|
+
// This preserves the CSV shape while normalizing line endings for row handling.
|
|
488
529
|
if (formatStyle === "raw") {
|
|
489
|
-
const lines = csvString
|
|
530
|
+
const lines = splitCsvLines(csvString);
|
|
490
531
|
const hasMetadataLine = isMetadataLine(lines);
|
|
491
532
|
if (hasMetadataLine) {
|
|
492
533
|
logger.debug("[CSVProcessor] Detected metadata line, skipping first line");
|
|
@@ -649,7 +690,10 @@ export class CSVProcessor {
|
|
|
649
690
|
let buffer = "";
|
|
650
691
|
lineReader.on("data", (chunk) => {
|
|
651
692
|
buffer += chunk.toString();
|
|
652
|
-
const
|
|
693
|
+
const splitBuffer = buffer.endsWith("\r")
|
|
694
|
+
? buffer.slice(0, -1)
|
|
695
|
+
: buffer;
|
|
696
|
+
const lines = splitCsvLines(splitBuffer);
|
|
653
697
|
if (lines.length >= 2) {
|
|
654
698
|
firstLines.push(lines[0], lines[1]);
|
|
655
699
|
lineReader.destroy();
|
|
@@ -714,9 +758,11 @@ export class CSVProcessor {
|
|
|
714
758
|
maxRows: clampedMaxRows,
|
|
715
759
|
});
|
|
716
760
|
// Detect and skip metadata line
|
|
717
|
-
const lines = csvString
|
|
761
|
+
const lines = splitCsvLines(csvString);
|
|
718
762
|
const hasMetadataLine = isMetadataLine(lines);
|
|
719
|
-
const csvData = hasMetadataLine
|
|
763
|
+
const csvData = hasMetadataLine
|
|
764
|
+
? lines.slice(1).join("\n")
|
|
765
|
+
: lines.join("\n");
|
|
720
766
|
if (hasMetadataLine) {
|
|
721
767
|
logger.debug("[CSVProcessor] Detected metadata line in string, skipping");
|
|
722
768
|
}
|
|
@@ -773,7 +819,10 @@ export class CSVProcessor {
|
|
|
773
819
|
}
|
|
774
820
|
const headers = Object.keys(rows[0]);
|
|
775
821
|
// Escape backslashes, pipes, and sanitize newlines to keep rows intact
|
|
776
|
-
const escapePipe = (str) => str
|
|
822
|
+
const escapePipe = (str) => str
|
|
823
|
+
.replace(/\\/g, "\\\\")
|
|
824
|
+
.replace(/\|/g, "\\|")
|
|
825
|
+
.replace(/\r\n|\n|\r/g, " ");
|
|
777
826
|
let markdown = "";
|
|
778
827
|
if (includeHeaders) {
|
|
779
828
|
markdown = "| " + headers.map(escapePipe).join(" | ") + " |\n";
|
|
@@ -828,7 +877,9 @@ export class CSVProcessor {
|
|
|
828
877
|
const headers = Object.keys(rows[0]);
|
|
829
878
|
// Escape CSV values (wrap in quotes if contains comma, quote, or newline)
|
|
830
879
|
const escapeCSV = (value) => {
|
|
831
|
-
if (value.includes(",") ||
|
|
880
|
+
if (value.includes(",") ||
|
|
881
|
+
value.includes('"') ||
|
|
882
|
+
/\r\n|\n|\r/.test(value)) {
|
|
832
883
|
return `"${value.replace(/"/g, '""')}"`;
|
|
833
884
|
}
|
|
834
885
|
return value;
|
|
@@ -444,6 +444,47 @@ function isMetadataLine(lines) {
|
|
|
444
444
|
}
|
|
445
445
|
return false;
|
|
446
446
|
}
|
|
447
|
+
/**
|
|
448
|
+
* Split CSV text into logical rows for metadata detection and raw row limiting.
|
|
449
|
+
*
|
|
450
|
+
* Supports Unix (LF), Windows (CRLF), and classic Mac (CR) line endings, and is
|
|
451
|
+
* quote-aware: a line ending that appears *inside* a quoted field (RFC 4180) is
|
|
452
|
+
* kept as part of that field rather than treated as a row boundary. A doubled
|
|
453
|
+
* `""` inside quotes is the RFC-4180 escaped quote and does not toggle the quote
|
|
454
|
+
* state. For unquoted input this yields exactly the same result as a plain
|
|
455
|
+
* `split(/\r\n|\n|\r/)`.
|
|
456
|
+
*/
|
|
457
|
+
function splitCsvLines(csvString) {
|
|
458
|
+
const rows = [];
|
|
459
|
+
let current = "";
|
|
460
|
+
let inQuotes = false;
|
|
461
|
+
for (let i = 0; i < csvString.length; i++) {
|
|
462
|
+
const ch = csvString[i];
|
|
463
|
+
if (ch === '"') {
|
|
464
|
+
if (inQuotes && csvString[i + 1] === '"') {
|
|
465
|
+
// Escaped quote ("") — stays inside the field, quote state unchanged.
|
|
466
|
+
current += '""';
|
|
467
|
+
i++;
|
|
468
|
+
continue;
|
|
469
|
+
}
|
|
470
|
+
inQuotes = !inQuotes;
|
|
471
|
+
current += ch;
|
|
472
|
+
}
|
|
473
|
+
else if (!inQuotes && (ch === "\n" || ch === "\r")) {
|
|
474
|
+
// Row boundary outside quotes; collapse CRLF into a single boundary.
|
|
475
|
+
if (ch === "\r" && csvString[i + 1] === "\n") {
|
|
476
|
+
i++;
|
|
477
|
+
}
|
|
478
|
+
rows.push(current);
|
|
479
|
+
current = "";
|
|
480
|
+
}
|
|
481
|
+
else {
|
|
482
|
+
current += ch;
|
|
483
|
+
}
|
|
484
|
+
}
|
|
485
|
+
rows.push(current);
|
|
486
|
+
return rows;
|
|
487
|
+
}
|
|
447
488
|
/**
|
|
448
489
|
* CSV processor for converting CSV data to LLM-optimized formats
|
|
449
490
|
*
|
|
@@ -483,10 +524,10 @@ export class CSVProcessor {
|
|
|
483
524
|
includeHeaders,
|
|
484
525
|
});
|
|
485
526
|
const csvString = content.toString("utf-8");
|
|
486
|
-
// For raw format, return
|
|
487
|
-
// This preserves the
|
|
527
|
+
// For raw format, return CSV text with row limit (no parsing needed)
|
|
528
|
+
// This preserves the CSV shape while normalizing line endings for row handling.
|
|
488
529
|
if (formatStyle === "raw") {
|
|
489
|
-
const lines = csvString
|
|
530
|
+
const lines = splitCsvLines(csvString);
|
|
490
531
|
const hasMetadataLine = isMetadataLine(lines);
|
|
491
532
|
if (hasMetadataLine) {
|
|
492
533
|
logger.debug("[CSVProcessor] Detected metadata line, skipping first line");
|
|
@@ -649,7 +690,10 @@ export class CSVProcessor {
|
|
|
649
690
|
let buffer = "";
|
|
650
691
|
lineReader.on("data", (chunk) => {
|
|
651
692
|
buffer += chunk.toString();
|
|
652
|
-
const
|
|
693
|
+
const splitBuffer = buffer.endsWith("\r")
|
|
694
|
+
? buffer.slice(0, -1)
|
|
695
|
+
: buffer;
|
|
696
|
+
const lines = splitCsvLines(splitBuffer);
|
|
653
697
|
if (lines.length >= 2) {
|
|
654
698
|
firstLines.push(lines[0], lines[1]);
|
|
655
699
|
lineReader.destroy();
|
|
@@ -714,9 +758,11 @@ export class CSVProcessor {
|
|
|
714
758
|
maxRows: clampedMaxRows,
|
|
715
759
|
});
|
|
716
760
|
// Detect and skip metadata line
|
|
717
|
-
const lines = csvString
|
|
761
|
+
const lines = splitCsvLines(csvString);
|
|
718
762
|
const hasMetadataLine = isMetadataLine(lines);
|
|
719
|
-
const csvData = hasMetadataLine
|
|
763
|
+
const csvData = hasMetadataLine
|
|
764
|
+
? lines.slice(1).join("\n")
|
|
765
|
+
: lines.join("\n");
|
|
720
766
|
if (hasMetadataLine) {
|
|
721
767
|
logger.debug("[CSVProcessor] Detected metadata line in string, skipping");
|
|
722
768
|
}
|
|
@@ -773,7 +819,10 @@ export class CSVProcessor {
|
|
|
773
819
|
}
|
|
774
820
|
const headers = Object.keys(rows[0]);
|
|
775
821
|
// Escape backslashes, pipes, and sanitize newlines to keep rows intact
|
|
776
|
-
const escapePipe = (str) => str
|
|
822
|
+
const escapePipe = (str) => str
|
|
823
|
+
.replace(/\\/g, "\\\\")
|
|
824
|
+
.replace(/\|/g, "\\|")
|
|
825
|
+
.replace(/\r\n|\n|\r/g, " ");
|
|
777
826
|
let markdown = "";
|
|
778
827
|
if (includeHeaders) {
|
|
779
828
|
markdown = "| " + headers.map(escapePipe).join(" | ") + " |\n";
|
|
@@ -828,7 +877,9 @@ export class CSVProcessor {
|
|
|
828
877
|
const headers = Object.keys(rows[0]);
|
|
829
878
|
// Escape CSV values (wrap in quotes if contains comma, quote, or newline)
|
|
830
879
|
const escapeCSV = (value) => {
|
|
831
|
-
if (value.includes(",") ||
|
|
880
|
+
if (value.includes(",") ||
|
|
881
|
+
value.includes('"') ||
|
|
882
|
+
/\r\n|\n|\r/.test(value)) {
|
|
832
883
|
return `"${value.replace(/"/g, '""')}"`;
|
|
833
884
|
}
|
|
834
885
|
return value;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "9.84.
|
|
3
|
+
"version": "9.84.2",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "Universal AI Development Platform with working MCP integration, multi-provider support, voice (TTS/STT/realtime), and professional CLI. 58+ external MCP servers discoverable, multimodal file processing, RAG pipelines. Build, test, and deploy AI applications with 21+ providers: OpenAI, Anthropic, Google AI Studio, Google Vertex, AWS Bedrock, Azure OpenAI, Mistral, LiteLLM, SageMaker, Hugging Face, Ollama, OpenAI-compatible, OpenRouter, DeepSeek, NVIDIA NIM, LM Studio, llama.cpp, plus voice (OpenAI TTS, ElevenLabs, Deepgram, Azure Speech).",
|
|
6
6
|
"author": {
|
|
@@ -44,6 +44,7 @@
|
|
|
44
44
|
"build:react-hooks": "npx tsc --jsx react-jsx --module nodenext --moduleResolution nodenext --target esnext --esModuleInterop --skipLibCheck --outDir dist --declaration false src/lib/client/reactHooks.tsx",
|
|
45
45
|
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json && tsc --noEmit --strict",
|
|
46
46
|
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
|
|
47
|
+
"typecheck": "tsc --noEmit",
|
|
47
48
|
"modelServer": "tsx scripts/modelServer.ts",
|
|
48
49
|
"lint": "prettier --check . && NODE_OPTIONS='--max-old-space-size=8192' eslint .",
|
|
49
50
|
"format": "prettier --write .",
|
|
@@ -341,7 +342,7 @@
|
|
|
341
342
|
"@modelcontextprotocol/sdk": "^1.27.1",
|
|
342
343
|
"@opentelemetry/api-logs": "^0.214.0",
|
|
343
344
|
"@opentelemetry/context-async-hooks": "^2.6.1",
|
|
344
|
-
"@opentelemetry/core": "^2.
|
|
345
|
+
"@opentelemetry/core": "^2.8.0",
|
|
345
346
|
"@opentelemetry/exporter-logs-otlp-http": "^0.214.0",
|
|
346
347
|
"@opentelemetry/exporter-metrics-otlp-http": "^0.214.0",
|
|
347
348
|
"@opentelemetry/exporter-trace-otlp-http": "^0.214.0",
|
|
@@ -476,7 +477,7 @@
|
|
|
476
477
|
"esbuild": "^0.28.1",
|
|
477
478
|
"eslint": "^10.0.2",
|
|
478
479
|
"husky": "^9.1.7",
|
|
479
|
-
"js-yaml": "^4.
|
|
480
|
+
"js-yaml": "^4.2.0",
|
|
480
481
|
"lint-staged": "^16.3.0",
|
|
481
482
|
"playwright": "^1.58.2",
|
|
482
483
|
"prettier": "^3.8.1",
|