@juspay/neurolink 10.11.2 → 10.12.0
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/adapters/audioFormatSupport.d.ts +53 -0
- package/dist/adapters/audioFormatSupport.js +200 -0
- package/dist/browser/neurolink.min.js +399 -398
- package/dist/cli/commands/auth.d.ts +8 -1
- package/dist/cli/commands/auth.js +185 -6
- package/dist/cli/factories/authCommandFactory.js +7 -1
- package/dist/lib/adapters/audioFormatSupport.d.ts +53 -0
- package/dist/lib/adapters/audioFormatSupport.js +201 -0
- package/dist/lib/processors/archive/ArchiveProcessor.d.ts +37 -0
- package/dist/lib/processors/archive/ArchiveProcessor.js +347 -32
- package/dist/lib/providers/googleAiStudio/client.d.ts +17 -0
- package/dist/lib/providers/googleAiStudio/client.js +45 -19
- package/dist/lib/providers/googleNativeGemini3/utils.d.ts +22 -1
- package/dist/lib/providers/googleNativeGemini3/utils.js +54 -0
- package/dist/lib/providers/googleVertex/client.js +3 -0
- package/dist/lib/proxy/accountQuota.d.ts +6 -0
- package/dist/lib/proxy/accountQuota.js +19 -2
- package/dist/lib/proxy/accountUsage.d.ts +45 -0
- package/dist/lib/proxy/accountUsage.js +289 -0
- package/dist/lib/server/routes/claudeProxyRoutes.d.ts +15 -1
- package/dist/lib/server/routes/claudeProxyRoutes.js +166 -0
- package/dist/lib/types/cli.d.ts +12 -0
- package/dist/lib/types/file.d.ts +41 -0
- package/dist/lib/types/generate.d.ts +12 -1
- package/dist/lib/types/processor.d.ts +20 -1
- package/dist/lib/types/providers.d.ts +7 -0
- package/dist/lib/types/proxy.d.ts +101 -0
- package/dist/lib/utils/fileDetector.d.ts +27 -0
- package/dist/lib/utils/fileDetector.js +130 -7
- package/dist/lib/utils/imageProcessor.js +31 -0
- package/dist/lib/utils/messageBuilder.d.ts +0 -9
- package/dist/lib/utils/messageBuilder.js +380 -56
- package/dist/processors/archive/ArchiveProcessor.d.ts +37 -0
- package/dist/processors/archive/ArchiveProcessor.js +347 -32
- package/dist/providers/googleAiStudio/client.d.ts +17 -0
- package/dist/providers/googleAiStudio/client.js +45 -19
- package/dist/providers/googleNativeGemini3/utils.d.ts +22 -1
- package/dist/providers/googleNativeGemini3/utils.js +54 -0
- package/dist/providers/googleVertex/client.js +3 -0
- package/dist/proxy/accountQuota.d.ts +6 -0
- package/dist/proxy/accountQuota.js +19 -2
- package/dist/proxy/accountUsage.d.ts +45 -0
- package/dist/proxy/accountUsage.js +288 -0
- package/dist/server/routes/claudeProxyRoutes.d.ts +15 -1
- package/dist/server/routes/claudeProxyRoutes.js +166 -0
- package/dist/types/cli.d.ts +12 -0
- package/dist/types/file.d.ts +41 -0
- package/dist/types/generate.d.ts +12 -1
- package/dist/types/processor.d.ts +20 -1
- package/dist/types/providers.d.ts +7 -0
- package/dist/types/proxy.d.ts +101 -0
- package/dist/utils/fileDetector.d.ts +27 -0
- package/dist/utils/fileDetector.js +130 -7
- package/dist/utils/imageProcessor.js +31 -0
- package/dist/utils/messageBuilder.d.ts +0 -9
- package/dist/utils/messageBuilder.js +380 -56
- package/package.json +3 -2
|
@@ -290,6 +290,13 @@ export class FileDetector {
|
|
|
290
290
|
// These default ensure consistent timeout behavior across all file-detection logic.
|
|
291
291
|
static DEFAULT_NETWORK_TIMEOUT = 30000; // 30 seconds
|
|
292
292
|
static DEFAULT_HEAD_TIMEOUT = 5000; // 5 seconds
|
|
293
|
+
/**
|
|
294
|
+
* Ceiling on an in-process document parse (unzip + XML walk). Generous
|
|
295
|
+
* relative to the work, because the cost of firing early on a large but
|
|
296
|
+
* legitimate file is a lost extraction, while the cost of never firing is a
|
|
297
|
+
* held request.
|
|
298
|
+
*/
|
|
299
|
+
static DEFAULT_DOCUMENT_TIMEOUT = 30000; // 30 seconds
|
|
293
300
|
/**
|
|
294
301
|
* Auto-detect file type and process in one call
|
|
295
302
|
*
|
|
@@ -404,7 +411,14 @@ export class FileDetector {
|
|
|
404
411
|
if (Buffer.isBuffer(input)) {
|
|
405
412
|
return "buffer";
|
|
406
413
|
}
|
|
407
|
-
|
|
414
|
+
// Everything left is a `FileWithMetadata`, which states its own name, and
|
|
415
|
+
// `withResolvedExtension` reads this to recover an extension when a
|
|
416
|
+
// content-based strategy reported none. Falling straight through to
|
|
417
|
+
// "unknown-input" threw that name away, so an `.odp`, `.rtf` or `.tar`
|
|
418
|
+
// supplied as bytes-plus-name lost the extension its processor routes on.
|
|
419
|
+
// Still defensive about the value: the type says required, callers are
|
|
420
|
+
// untyped JavaScript often enough.
|
|
421
|
+
return input?.filename || "unknown-input";
|
|
408
422
|
}
|
|
409
423
|
/**
|
|
410
424
|
* Derive byte size from FileInput for tracing.
|
|
@@ -661,7 +675,7 @@ export class FileDetector {
|
|
|
661
675
|
source: FileDetector.deriveInputSource(input),
|
|
662
676
|
metadata: {
|
|
663
677
|
confidence: 95,
|
|
664
|
-
filename: FileDetector.deriveInputFilename(input),
|
|
678
|
+
filename: options?.filenameHint || FileDetector.deriveInputFilename(input),
|
|
665
679
|
size: FileDetector.deriveInputSize(input),
|
|
666
680
|
},
|
|
667
681
|
};
|
|
@@ -684,13 +698,68 @@ export class FileDetector {
|
|
|
684
698
|
}
|
|
685
699
|
if (result.metadata.confidence >= confidenceThreshold) {
|
|
686
700
|
logger.info(`[FileDetector] Type: ${result.type} (${result.metadata.confidence}%)`);
|
|
687
|
-
return result;
|
|
701
|
+
return FileDetector.withResolvedExtension(result, input, options);
|
|
688
702
|
}
|
|
689
703
|
}
|
|
690
704
|
// Below-threshold detection is the common case for any file under the
|
|
691
705
|
// ContentHeuristic ceiling — a debug detail, not a warning-worthy anomaly.
|
|
692
706
|
logger.debug(`[FileDetector] Best-effort type below threshold: ${best?.type ?? "unknown"} (${best?.metadata.confidence ?? 0}%, threshold ${confidenceThreshold}%)`);
|
|
693
|
-
return best;
|
|
707
|
+
return FileDetector.withResolvedExtension(best, input, options);
|
|
708
|
+
}
|
|
709
|
+
/**
|
|
710
|
+
* Fill in `extension` from the input's name when detection did not set it.
|
|
711
|
+
*
|
|
712
|
+
* Content-based strategies identify a type from magic bytes and legitimately
|
|
713
|
+
* have no extension to report, so they return null. That is fine for the type
|
|
714
|
+
* itself but not for routing: several processors are chosen by extension
|
|
715
|
+
* *after* detection has settled the type, because one routing type covers
|
|
716
|
+
* several formats — `docx` covers .docx, .odt and .rtf.
|
|
717
|
+
*
|
|
718
|
+
* With a null extension those branches were unreachable. An .rtf scored high
|
|
719
|
+
* on its `{\\rtf1` signature, arrived as type "docx" with no extension, and
|
|
720
|
+
* fell through to the Word processor, which cannot read RTF — so a file whose
|
|
721
|
+
* dedicated processor extracts it perfectly reported "Could not extract
|
|
722
|
+
* content". The extension was known the whole time; it was simply dropped on
|
|
723
|
+
* the way through.
|
|
724
|
+
*
|
|
725
|
+
* Only fills a gap — a strategy that did determine an extension keeps it, so
|
|
726
|
+
* content still wins over a lying filename.
|
|
727
|
+
*/
|
|
728
|
+
static withResolvedExtension(result, input, options) {
|
|
729
|
+
if (!result) {
|
|
730
|
+
return result;
|
|
731
|
+
}
|
|
732
|
+
// The caller's hint outranks a name derived from the input, because on the
|
|
733
|
+
// unified path the input has already been unwrapped to a bare Buffer and
|
|
734
|
+
// derives to the literal "buffer" — carrying no extension at all.
|
|
735
|
+
const filename = options?.filenameHint ||
|
|
736
|
+
result.metadata?.filename ||
|
|
737
|
+
FileDetector.deriveInputFilename(input);
|
|
738
|
+
if (!filename) {
|
|
739
|
+
return result;
|
|
740
|
+
}
|
|
741
|
+
// Split on both separators so a Windows-style path on a POSIX host still
|
|
742
|
+
// yields its basename, then take the final suffix.
|
|
743
|
+
const base = filename.split(/[\\/]/).pop() ?? filename;
|
|
744
|
+
const dot = base.lastIndexOf(".");
|
|
745
|
+
const extension = result.extension ??
|
|
746
|
+
(dot > 0 && dot < base.length - 1
|
|
747
|
+
? base.slice(dot + 1).toLowerCase()
|
|
748
|
+
: null);
|
|
749
|
+
// The name is carried alongside the extension for the same reason. A
|
|
750
|
+
// content strategy reports no filename, so every processor keyed on one
|
|
751
|
+
// received the literal fallback "archive" — and archive format detection
|
|
752
|
+
// reads the name, because TAR has no magic bytes at offset 0 (its "ustar"
|
|
753
|
+
// marker sits at byte 257). A .tar therefore arrived as an unidentifiable
|
|
754
|
+
// archive and reported "Could not extract content", while the same bytes
|
|
755
|
+
// handed to the processor WITH their name extract perfectly.
|
|
756
|
+
const metadata = result.metadata && !result.metadata.filename
|
|
757
|
+
? { ...result.metadata, filename: base }
|
|
758
|
+
: result.metadata;
|
|
759
|
+
if (extension === result.extension && metadata === result.metadata) {
|
|
760
|
+
return result;
|
|
761
|
+
}
|
|
762
|
+
return { ...result, extension, metadata };
|
|
694
763
|
}
|
|
695
764
|
/**
|
|
696
765
|
* Load file content from various sources
|
|
@@ -1343,6 +1412,40 @@ export class FileDetector {
|
|
|
1343
1412
|
static async processPptxFile(content, detection) {
|
|
1344
1413
|
const pptxFilename = detection.metadata.filename || "presentation";
|
|
1345
1414
|
try {
|
|
1415
|
+
// ODP is an OpenDocument package, not OOXML — the PPTX reader finds no
|
|
1416
|
+
// ppt/slides parts in it and returns nothing. It reaches this branch at
|
|
1417
|
+
// all because one routing type ("pptx") covers every presentation
|
|
1418
|
+
// format, the same way "docx" covers .odt.
|
|
1419
|
+
if (detection.extension?.toLowerCase() === "odp") {
|
|
1420
|
+
const { openDocumentProcessor } = await import("../processors/document/OpenDocumentProcessor.js");
|
|
1421
|
+
// Bounded per the project's async-timeout guideline: this unzips and
|
|
1422
|
+
// parses attacker-supplied bytes, and a stalled parse would otherwise
|
|
1423
|
+
// hold the request open with no ceiling. On timeout the throw lands in
|
|
1424
|
+
// this block's existing catch, which degrades to the placeholder.
|
|
1425
|
+
const odpResult = await withTimeout(openDocumentProcessor.processFile({
|
|
1426
|
+
id: pptxFilename,
|
|
1427
|
+
name: pptxFilename,
|
|
1428
|
+
mimetype: detection.mimeType ||
|
|
1429
|
+
"application/vnd.oasis.opendocument.presentation",
|
|
1430
|
+
size: content.length,
|
|
1431
|
+
buffer: content,
|
|
1432
|
+
}), FileDetector.DEFAULT_DOCUMENT_TIMEOUT);
|
|
1433
|
+
// Gated on success rather than on text, because a presentation of
|
|
1434
|
+
// nothing but images is a legitimate ODP that extracts to an empty
|
|
1435
|
+
// string. Requiring text sent that file on to the PPTX reader, which
|
|
1436
|
+
// cannot read OpenDocument at all — so a successful extraction was
|
|
1437
|
+
// discarded in favour of a guaranteed failure. Matches how the ODT and
|
|
1438
|
+
// ODS branches degrade.
|
|
1439
|
+
if (odpResult.success && odpResult.data) {
|
|
1440
|
+
return {
|
|
1441
|
+
type: "pptx",
|
|
1442
|
+
content: odpResult.data.textContent ||
|
|
1443
|
+
FileDetector.formatInformativePlaceholder("Presentation", pptxFilename, content, detection),
|
|
1444
|
+
mimeType: detection.mimeType,
|
|
1445
|
+
metadata: detection.metadata,
|
|
1446
|
+
};
|
|
1447
|
+
}
|
|
1448
|
+
}
|
|
1346
1449
|
const { PptxProcessor } = await import("../processors/document/PptxProcessor.js");
|
|
1347
1450
|
const pptxResult = await PptxProcessor.extractText(content);
|
|
1348
1451
|
if (pptxResult) {
|
|
@@ -2003,13 +2106,33 @@ class MagicBytesStrategy {
|
|
|
2003
2106
|
if (input.length >= 6 && input.toString("latin1", 0, 5) === "#!AMR") {
|
|
2004
2107
|
return this.result("audio", "audio/amr", 95);
|
|
2005
2108
|
}
|
|
2006
|
-
// JPEG 2000: 12-byte signature box
|
|
2007
|
-
|
|
2109
|
+
// JPEG 2000: the full 12-byte signature box, trailing 0D 0A 87 0A
|
|
2110
|
+
// included. Those four bytes are a deliberate line-ending probe — CR LF, a
|
|
2111
|
+
// high byte, LF — that any transfer which mangles newlines or strips the
|
|
2112
|
+
// eighth bit will visibly corrupt, so checking only the length and brand
|
|
2113
|
+
// accepts exactly the damaged files the signature exists to reject.
|
|
2114
|
+
if (input.length >= 12 &&
|
|
2008
2115
|
input[0] === 0x00 &&
|
|
2009
2116
|
input[1] === 0x00 &&
|
|
2010
2117
|
input[2] === 0x00 &&
|
|
2011
2118
|
input[3] === 0x0c &&
|
|
2012
|
-
input.toString("latin1", 4, 8) === "jP "
|
|
2119
|
+
input.toString("latin1", 4, 8) === "jP " &&
|
|
2120
|
+
input[8] === 0x0d &&
|
|
2121
|
+
input[9] === 0x0a &&
|
|
2122
|
+
input[10] === 0x87 &&
|
|
2123
|
+
input[11] === 0x0a) {
|
|
2124
|
+
return this.result("image", "image/jp2", 95);
|
|
2125
|
+
}
|
|
2126
|
+
// The other shape JPEG 2000 ships in: a bare codestream (.j2k/.j2c) opening
|
|
2127
|
+
// with the SOC + SIZ markers. `ImageProcessor.detectImageType` learned both
|
|
2128
|
+
// shapes; this strategy knew only the container, so a codestream uploaded
|
|
2129
|
+
// as bytes-plus-filename was typed "unknown" and delivered as a binary
|
|
2130
|
+
// blob — the codestream branch over there was unreachable from this path.
|
|
2131
|
+
if (input.length >= 4 &&
|
|
2132
|
+
input[0] === 0xff &&
|
|
2133
|
+
input[1] === 0x4f &&
|
|
2134
|
+
input[2] === 0xff &&
|
|
2135
|
+
input[3] === 0x51) {
|
|
2013
2136
|
return this.result("image", "image/jp2", 95);
|
|
2014
2137
|
}
|
|
2015
2138
|
// MP3: ID3 tag
|
|
@@ -468,6 +468,37 @@ export class ImageProcessor {
|
|
|
468
468
|
if (isoBmffMimeType) {
|
|
469
469
|
return isoBmffMimeType;
|
|
470
470
|
}
|
|
471
|
+
// JPEG 2000, in both shapes it ships in. The JP2 container opens with
|
|
472
|
+
// the 12-byte signature box `00 00 00 0C 6A 50 20 20 0D 0A 87 0A`; a
|
|
473
|
+
// bare codestream (.j2k/.j2c) opens with the SOC+SIZ markers FF 4F FF
|
|
474
|
+
// 51. Checked BEFORE ICO because the container's first three bytes are
|
|
475
|
+
// 00 00 00, which is one byte away from ICO's 00 00 01 00 and shares
|
|
476
|
+
// its leading zeros — an ordering mistake here would classify every
|
|
477
|
+
// JPEG 2000 as an icon rather than merely failing to recognise it.
|
|
478
|
+
// All twelve bytes are checked, not just the length and brand: the
|
|
479
|
+
// trailing 0D 0A 87 0A is the signature's whole point. It is a
|
|
480
|
+
// line-ending probe — CR LF, a high byte, LF — that a transfer which
|
|
481
|
+
// mangles newlines or strips the eighth bit will visibly corrupt, so
|
|
482
|
+
// skipping it accepts exactly the damaged files it exists to reject.
|
|
483
|
+
if (input.length >= 12 &&
|
|
484
|
+
input[0] === 0x00 &&
|
|
485
|
+
input[1] === 0x00 &&
|
|
486
|
+
input[2] === 0x00 &&
|
|
487
|
+
input[3] === 0x0c &&
|
|
488
|
+
input.subarray(4, 8).toString("latin1") === "jP " &&
|
|
489
|
+
input[8] === 0x0d &&
|
|
490
|
+
input[9] === 0x0a &&
|
|
491
|
+
input[10] === 0x87 &&
|
|
492
|
+
input[11] === 0x0a) {
|
|
493
|
+
return "image/jp2";
|
|
494
|
+
}
|
|
495
|
+
if (input.length >= 4 &&
|
|
496
|
+
input[0] === 0xff &&
|
|
497
|
+
input[1] === 0x4f &&
|
|
498
|
+
input[2] === 0xff &&
|
|
499
|
+
input[3] === 0x51) {
|
|
500
|
+
return "image/jp2";
|
|
501
|
+
}
|
|
471
502
|
// ICO: 00 00 01 00 (icon type=1)
|
|
472
503
|
if (input[0] === 0x00 &&
|
|
473
504
|
input[1] === 0x00 &&
|
|
@@ -37,15 +37,6 @@ export declare function mergeMediaFileAliases<TFile>(input: {
|
|
|
37
37
|
audioFiles?: Array<Buffer | string>;
|
|
38
38
|
videoFiles?: Array<Buffer | string>;
|
|
39
39
|
}): void;
|
|
40
|
-
/**
|
|
41
|
-
* Process the unified files array with auto-detection.
|
|
42
|
-
* Handles lazy file registration, full processing, and preview injection.
|
|
43
|
-
*
|
|
44
|
-
* Exported so providers that bypass BaseProvider.generate() (e.g.
|
|
45
|
-
* GoogleVertex's native @google/genai path) can still preprocess
|
|
46
|
-
* `input.files` — without this, mimetype-hint and text-file inputs
|
|
47
|
-
* would silently never reach the model on those paths.
|
|
48
|
-
*/
|
|
49
40
|
export declare function processUnifiedFilesArray(options: GenerateOptions, maxSize: number, provider: string): Promise<void>;
|
|
50
41
|
/**
|
|
51
42
|
* Build multimodal message array with image support
|