@juspay/neurolink 9.56.1 → 9.57.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/auth/AuthProviderFactory.d.ts +3 -3
- package/dist/auth/providers/BaseAuthProvider.d.ts +2 -2
- package/dist/auth/providers/BaseAuthProvider.js +1 -1
- package/dist/auth/serverBridge.d.ts +2 -2
- package/dist/browser/neurolink.min.js +306 -306
- package/dist/cli/factories/commandFactory.js +32 -8
- package/dist/cli/loop/optionsSchema.js +4 -0
- package/dist/cli/parser.js +3 -3
- package/dist/dynamic/dynamicResolver.d.ts +282 -0
- package/dist/dynamic/dynamicResolver.js +633 -0
- package/dist/dynamic/index.d.ts +10 -0
- package/dist/dynamic/index.js +12 -0
- package/dist/dynamic/resolution.d.ts +17 -0
- package/dist/dynamic/resolution.js +21 -0
- package/dist/evaluation/index.js +1 -1
- package/dist/files/fileReferenceRegistry.js +25 -10
- package/dist/index.js +19 -2
- package/dist/lib/auth/AuthProviderFactory.d.ts +3 -3
- package/dist/lib/auth/providers/BaseAuthProvider.d.ts +2 -2
- package/dist/lib/auth/providers/BaseAuthProvider.js +1 -1
- package/dist/lib/auth/serverBridge.d.ts +2 -2
- package/dist/lib/dynamic/dynamicResolver.d.ts +282 -0
- package/dist/lib/dynamic/dynamicResolver.js +634 -0
- package/dist/lib/dynamic/index.d.ts +10 -0
- package/dist/lib/dynamic/index.js +13 -0
- package/dist/lib/dynamic/resolution.d.ts +17 -0
- package/dist/lib/dynamic/resolution.js +22 -0
- package/dist/lib/evaluation/index.js +1 -1
- package/dist/lib/files/fileReferenceRegistry.js +25 -10
- package/dist/lib/index.js +19 -2
- package/dist/lib/mcp/mcpServerBase.d.ts +1 -1
- package/dist/lib/mcp/mcpServerBase.js +1 -1
- package/dist/lib/neurolink.d.ts +12 -4
- package/dist/lib/neurolink.js +79 -6
- package/dist/lib/observability/exporters/baseExporter.d.ts +1 -1
- package/dist/lib/observability/exporters/baseExporter.js +1 -1
- package/dist/lib/types/auth.d.ts +6 -6
- package/dist/lib/types/config.d.ts +4 -4
- package/dist/lib/types/dynamic.d.ts +98 -0
- package/dist/lib/types/dynamic.js +10 -0
- package/dist/lib/types/file.d.ts +10 -0
- package/dist/lib/types/fileReference.d.ts +9 -0
- package/dist/lib/types/generate.d.ts +29 -0
- package/dist/lib/types/index.d.ts +1 -0
- package/dist/lib/types/index.js +2 -0
- package/dist/lib/types/scorer.d.ts +1 -1
- package/dist/lib/types/scorer.js +1 -1
- package/dist/lib/types/span.d.ts +1 -1
- package/dist/lib/types/span.js +1 -1
- package/dist/lib/types/stream.d.ts +6 -0
- package/dist/lib/utils/fileDetector.d.ts +7 -0
- package/dist/lib/utils/fileDetector.js +47 -0
- package/dist/lib/utils/messageBuilder.js +15 -1
- package/dist/lib/utils/mimeTypeHints.d.ts +40 -0
- package/dist/lib/utils/mimeTypeHints.js +122 -0
- package/dist/mcp/mcpServerBase.d.ts +1 -1
- package/dist/mcp/mcpServerBase.js +1 -1
- package/dist/neurolink.d.ts +12 -4
- package/dist/neurolink.js +79 -6
- package/dist/observability/exporters/baseExporter.d.ts +1 -1
- package/dist/observability/exporters/baseExporter.js +1 -1
- package/dist/types/auth.d.ts +6 -6
- package/dist/types/config.d.ts +4 -4
- package/dist/types/dynamic.d.ts +98 -0
- package/dist/types/dynamic.js +9 -0
- package/dist/types/file.d.ts +10 -0
- package/dist/types/fileReference.d.ts +9 -0
- package/dist/types/generate.d.ts +29 -0
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +2 -0
- package/dist/types/scorer.d.ts +1 -1
- package/dist/types/scorer.js +1 -1
- package/dist/types/span.d.ts +1 -1
- package/dist/types/span.js +1 -1
- package/dist/types/stream.d.ts +6 -0
- package/dist/utils/fileDetector.d.ts +7 -0
- package/dist/utils/fileDetector.js +47 -0
- package/dist/utils/messageBuilder.js +15 -1
- package/dist/utils/mimeTypeHints.d.ts +40 -0
- package/dist/utils/mimeTypeHints.js +121 -0
- package/package.json +1 -1
package/dist/types/config.d.ts
CHANGED
|
@@ -7,7 +7,7 @@ import type { TaskManagerConfig } from "./task.js";
|
|
|
7
7
|
import type { HITLConfig } from "../types/hitl.js";
|
|
8
8
|
import type { ConversationMemoryConfig } from "./conversation.js";
|
|
9
9
|
import type { ObservabilityConfig } from "./observability.js";
|
|
10
|
-
import type {
|
|
10
|
+
import type { AuthProvider, AuthProviderType, AuthProviderConfig, Auth0Config, ClerkConfig, FirebaseConfig, SupabaseConfig, WorkOSConfig, BetterAuthConfig, JWTConfig, OAuth2Config, CognitoConfig, KeycloakConfig, AuthenticatedContext } from "./auth.js";
|
|
11
11
|
import type { NeurolinkCredentials } from "./providers.js";
|
|
12
12
|
/**
|
|
13
13
|
* Main NeuroLink configuration type
|
|
@@ -130,8 +130,8 @@ export type MCPEnhancementsConfig = {
|
|
|
130
130
|
/**
|
|
131
131
|
* Authentication configuration for NeuroLink SDK
|
|
132
132
|
*/
|
|
133
|
-
export type NeuroLinkAuthConfig =
|
|
134
|
-
provider:
|
|
133
|
+
export type NeuroLinkAuthConfig = AuthProvider | {
|
|
134
|
+
provider: AuthProvider;
|
|
135
135
|
} | {
|
|
136
136
|
type: "auth0";
|
|
137
137
|
config: Auth0Config;
|
|
@@ -169,7 +169,7 @@ export type NeuroLinkAuthConfig = MastraAuthProvider | {
|
|
|
169
169
|
/**
|
|
170
170
|
* Re-export auth types for convenience
|
|
171
171
|
*/
|
|
172
|
-
export type {
|
|
172
|
+
export type { AuthProvider, AuthProviderType, AuthProviderConfig, AuthenticatedContext, };
|
|
173
173
|
/**
|
|
174
174
|
* Provider-specific configuration
|
|
175
175
|
*/
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Dynamic Arguments Type Definitions
|
|
3
|
+
*
|
|
4
|
+
* Pass functions instead of static values to generate() and stream().
|
|
5
|
+
* Functions are resolved at runtime before provider dispatch.
|
|
6
|
+
*
|
|
7
|
+
* @module types/dynamic
|
|
8
|
+
*/
|
|
9
|
+
import type { AIProviderName } from "../constants/enums.js";
|
|
10
|
+
/**
|
|
11
|
+
* Context passed to context-aware dynamic argument functions.
|
|
12
|
+
* `requestContext` is whatever the consumer passed as `dynamicContext` —
|
|
13
|
+
* NeuroLink does not prescribe its shape.
|
|
14
|
+
*/
|
|
15
|
+
export type DynamicResolutionContext = {
|
|
16
|
+
/** Consumer-provided context (any shape) */
|
|
17
|
+
requestContext: Record<string, unknown>;
|
|
18
|
+
/** Abort signal for cancellation */
|
|
19
|
+
signal?: AbortSignal;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* A value that can be static, a function, or a context-aware function.
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* ```typescript
|
|
26
|
+
* // Static
|
|
27
|
+
* model: "gpt-4o"
|
|
28
|
+
*
|
|
29
|
+
* // Function
|
|
30
|
+
* model: () => process.env.MODEL || "gpt-4o"
|
|
31
|
+
*
|
|
32
|
+
* // Context-aware
|
|
33
|
+
* model: (ctx) => ctx.requestContext.plan === "enterprise" ? "gpt-4o" : "gpt-4o-mini"
|
|
34
|
+
* ```
|
|
35
|
+
*/
|
|
36
|
+
export type DynamicArgument<T> = T | (() => T) | (() => Promise<T>) | ((context: DynamicResolutionContext) => T) | ((context: DynamicResolutionContext) => Promise<T>);
|
|
37
|
+
/**
|
|
38
|
+
* Dynamic options for generate() and stream() — pass functions
|
|
39
|
+
* instead of static values for context-aware resolution.
|
|
40
|
+
*/
|
|
41
|
+
export type DynamicOptions = {
|
|
42
|
+
model?: DynamicArgument<string>;
|
|
43
|
+
provider?: DynamicArgument<AIProviderName | string>;
|
|
44
|
+
temperature?: DynamicArgument<number>;
|
|
45
|
+
maxTokens?: DynamicArgument<number>;
|
|
46
|
+
systemPrompt?: DynamicArgument<string>;
|
|
47
|
+
/**
|
|
48
|
+
* Resolves to a `string[]` of tool names to enable.
|
|
49
|
+
* The resolved array is merged into `enabledToolNames` (and from there
|
|
50
|
+
* into `toolFilter`) — it does NOT replace `GenerateOptions.tools`,
|
|
51
|
+
* which is a `Record<string, Tool>` map of tool definitions.
|
|
52
|
+
*/
|
|
53
|
+
tools?: DynamicArgument<string[]>;
|
|
54
|
+
timeout?: DynamicArgument<number>;
|
|
55
|
+
thinkingLevel?: DynamicArgument<"minimal" | "low" | "medium" | "high">;
|
|
56
|
+
disableTools?: DynamicArgument<boolean>;
|
|
57
|
+
enableAnalytics?: DynamicArgument<boolean>;
|
|
58
|
+
enableEvaluation?: DynamicArgument<boolean>;
|
|
59
|
+
input: {
|
|
60
|
+
text: string;
|
|
61
|
+
images?: Array<Buffer | string>;
|
|
62
|
+
files?: Array<Buffer | string>;
|
|
63
|
+
};
|
|
64
|
+
/**
|
|
65
|
+
* Context passed to dynamic resolver functions — any shape you want.
|
|
66
|
+
*
|
|
67
|
+
* This is intentionally separate from `GenerateOptions.context` (which is
|
|
68
|
+
* for telemetry/tracing metadata). If your resolvers need values from
|
|
69
|
+
* telemetry context (sessionId, userId, etc.), pass them here as well.
|
|
70
|
+
*/
|
|
71
|
+
dynamicContext?: Record<string, unknown>;
|
|
72
|
+
};
|
|
73
|
+
export type ResolutionOptions = {
|
|
74
|
+
timeout?: number;
|
|
75
|
+
cache?: boolean;
|
|
76
|
+
cacheKey?: string;
|
|
77
|
+
cacheTtl?: number;
|
|
78
|
+
defaultValue?: unknown;
|
|
79
|
+
throwOnError?: boolean;
|
|
80
|
+
};
|
|
81
|
+
export type ResolutionResult<T> = {
|
|
82
|
+
value: T;
|
|
83
|
+
fromCache: boolean;
|
|
84
|
+
resolutionTime: number;
|
|
85
|
+
resolutionType: "static" | "sync-function" | "async-function" | "context-aware";
|
|
86
|
+
};
|
|
87
|
+
export type DynamicConfig<T> = {
|
|
88
|
+
[K in keyof T]: DynamicArgument<T[K]>;
|
|
89
|
+
};
|
|
90
|
+
export type ResolvedConfig<T> = {
|
|
91
|
+
[K in keyof T]: T[K] extends DynamicArgument<infer U> ? U : T[K];
|
|
92
|
+
};
|
|
93
|
+
export type DynamicCacheEntry<T> = {
|
|
94
|
+
value: T;
|
|
95
|
+
resolvedAt: number;
|
|
96
|
+
expiresAt: number;
|
|
97
|
+
key: string;
|
|
98
|
+
};
|
package/dist/types/file.d.ts
CHANGED
|
@@ -307,6 +307,16 @@ export type FileDetectorOptions = {
|
|
|
307
307
|
maxRetries?: number;
|
|
308
308
|
/** Initial retry delay in milliseconds with exponential backoff (default: 1000) */
|
|
309
309
|
retryDelay?: number;
|
|
310
|
+
/**
|
|
311
|
+
* Caller-provided MIME type hint (e.g. "text/plain", "application/json").
|
|
312
|
+
* Used when the filename has no extension and magic-byte detection cannot
|
|
313
|
+
* identify the content — the common Slack/Curator extension-less-buffer
|
|
314
|
+
* case. When set to a trustworthy mimetype (not "application/octet-stream"),
|
|
315
|
+
* it short-circuits the detection strategy loop with a high-confidence
|
|
316
|
+
* result so small files on the eager file-processing path still honor the
|
|
317
|
+
* hint (the lazy FileReferenceRegistry path has its own hint-handling).
|
|
318
|
+
*/
|
|
319
|
+
mimetypeHint?: string;
|
|
310
320
|
};
|
|
311
321
|
/**
|
|
312
322
|
* Google AI Studio Files API types
|
|
@@ -96,6 +96,15 @@ export type FileRegistrationOptions = {
|
|
|
96
96
|
filename?: string;
|
|
97
97
|
/** Override file type detection */
|
|
98
98
|
fileType?: FileType;
|
|
99
|
+
/**
|
|
100
|
+
* Caller-provided MIME type hint (e.g. "text/plain", "application/json").
|
|
101
|
+
* Used when the filename has no extension and magic-byte detection cannot
|
|
102
|
+
* identify the content (common for Slack/Curator-style buffers where the
|
|
103
|
+
* original extension was stripped). Honored during type detection, mimeType
|
|
104
|
+
* assignment, and filename-extension synthesis. An explicit `fileType`
|
|
105
|
+
* override still wins over this hint.
|
|
106
|
+
*/
|
|
107
|
+
mimetype?: string;
|
|
99
108
|
/** Maximum preview length in characters */
|
|
100
109
|
maxPreviewChars?: number;
|
|
101
110
|
/** Skip persisting buffer to temp directory */
|
package/dist/types/generate.d.ts
CHANGED
|
@@ -230,6 +230,20 @@ export type GenerateOptions = {
|
|
|
230
230
|
*/
|
|
231
231
|
schema?: ValidationSchema;
|
|
232
232
|
tools?: Record<string, Tool>;
|
|
233
|
+
/**
|
|
234
|
+
* Filter available tools by name.
|
|
235
|
+
* Only tools with names in this array will be made available.
|
|
236
|
+
* Used by dynamic arguments to dynamically select which tools to enable.
|
|
237
|
+
*
|
|
238
|
+
* @example
|
|
239
|
+
* ```typescript
|
|
240
|
+
* await neurolink.generate({
|
|
241
|
+
* input: { text: "Search for information" },
|
|
242
|
+
* enabledToolNames: ["websearchGrounding", "readFile"]
|
|
243
|
+
* });
|
|
244
|
+
* ```
|
|
245
|
+
*/
|
|
246
|
+
enabledToolNames?: string[];
|
|
233
247
|
timeout?: number | string;
|
|
234
248
|
/** AbortSignal for external cancellation of the AI call */
|
|
235
249
|
abortSignal?: AbortSignal;
|
|
@@ -738,6 +752,21 @@ export type TextGenerationOptions = {
|
|
|
738
752
|
director?: DirectorModeOptions;
|
|
739
753
|
};
|
|
740
754
|
tools?: Record<string, Tool>;
|
|
755
|
+
/**
|
|
756
|
+
* Filter available tools by name.
|
|
757
|
+
* Only tools with names in this array will be made available.
|
|
758
|
+
* Used by dynamic arguments to dynamically select which tools to enable.
|
|
759
|
+
* Merged into `toolFilter` before tool filtering runs.
|
|
760
|
+
*
|
|
761
|
+
* @example
|
|
762
|
+
* ```typescript
|
|
763
|
+
* await neurolink.generate({
|
|
764
|
+
* input: { text: "Search for information" },
|
|
765
|
+
* enabledToolNames: ["websearchGrounding", "readFile"]
|
|
766
|
+
* });
|
|
767
|
+
* ```
|
|
768
|
+
*/
|
|
769
|
+
enabledToolNames?: string[];
|
|
741
770
|
timeout?: number | string;
|
|
742
771
|
/** AbortSignal for external cancellation of the AI call */
|
|
743
772
|
abortSignal?: AbortSignal;
|
package/dist/types/index.d.ts
CHANGED
package/dist/types/index.js
CHANGED
package/dist/types/scorer.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @file Scorer type definitions for NeuroLink evaluation system
|
|
3
|
-
*
|
|
3
|
+
* Modular scorer interfaces and types
|
|
4
4
|
*/
|
|
5
5
|
import type { JsonObject } from "./common.js";
|
|
6
6
|
import type { EnhancedEvaluationContext } from "./evaluation.js";
|
package/dist/types/scorer.js
CHANGED
package/dist/types/span.d.ts
CHANGED
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
*/
|
|
5
5
|
/**
|
|
6
6
|
* Span types for AI operations
|
|
7
|
-
* Following
|
|
7
|
+
* Following OTel GenAI conventions for span categorization
|
|
8
8
|
*/
|
|
9
9
|
export declare enum SpanType {
|
|
10
10
|
/** Agent execution run (reserved for future multi-agent support) */
|
package/dist/types/span.js
CHANGED
package/dist/types/stream.d.ts
CHANGED
|
@@ -330,6 +330,12 @@ export type StreamOptions = {
|
|
|
330
330
|
} | undefined>;
|
|
331
331
|
/** Include only these tools by name (whitelist). If set, only matching tools are available. */
|
|
332
332
|
toolFilter?: string[];
|
|
333
|
+
/**
|
|
334
|
+
* Filter available tools by name.
|
|
335
|
+
* Used by dynamic arguments to dynamically select which tools to enable.
|
|
336
|
+
* Merged into `toolFilter` before tool filtering runs.
|
|
337
|
+
*/
|
|
338
|
+
enabledToolNames?: string[];
|
|
333
339
|
/** Exclude these tools by name (blacklist). Applied after toolFilter. */
|
|
334
340
|
excludeTools?: string[];
|
|
335
341
|
/** Disable tool result caching for this request (overrides global mcp.cache.enabled) */
|
|
@@ -43,6 +43,13 @@ export declare class FileDetector {
|
|
|
43
43
|
* Derive byte size from FileInput for tracing.
|
|
44
44
|
*/
|
|
45
45
|
private static deriveInputSize;
|
|
46
|
+
/**
|
|
47
|
+
* Classify a FileInput into the FileSource enum used by downstream
|
|
48
|
+
* loaders. Keeps the mimetype-hint short-circuit in detect() able to
|
|
49
|
+
* produce a valid FileDetectionResult without re-implementing the
|
|
50
|
+
* source-inference rules scattered across loadContent().
|
|
51
|
+
*/
|
|
52
|
+
private static deriveInputSource;
|
|
46
53
|
/**
|
|
47
54
|
* Try fallback parsing for a specific file type
|
|
48
55
|
* Used when file detection returns "unknown" but we want to try parsing anyway
|
|
@@ -23,6 +23,7 @@ import { tracers, ATTR, withSpan } from "../telemetry/index.js";
|
|
|
23
23
|
import { CSVProcessor } from "./csvProcessor.js";
|
|
24
24
|
import { ImageProcessor } from "./imageProcessor.js";
|
|
25
25
|
import { logger } from "./logger.js";
|
|
26
|
+
import { mimeHintToExtension, mimeHintToFileType, normalizeMimeHint, } from "./mimeTypeHints.js";
|
|
26
27
|
import { PDFProcessor } from "./pdfProcessor.js";
|
|
27
28
|
/**
|
|
28
29
|
* Default retry configuration constants
|
|
@@ -320,6 +321,27 @@ export class FileDetector {
|
|
|
320
321
|
}
|
|
321
322
|
return 0;
|
|
322
323
|
}
|
|
324
|
+
/**
|
|
325
|
+
* Classify a FileInput into the FileSource enum used by downstream
|
|
326
|
+
* loaders. Keeps the mimetype-hint short-circuit in detect() able to
|
|
327
|
+
* produce a valid FileDetectionResult without re-implementing the
|
|
328
|
+
* source-inference rules scattered across loadContent().
|
|
329
|
+
*/
|
|
330
|
+
static deriveInputSource(input) {
|
|
331
|
+
if (Buffer.isBuffer(input)) {
|
|
332
|
+
return "buffer";
|
|
333
|
+
}
|
|
334
|
+
if (typeof input === "string") {
|
|
335
|
+
if (input.startsWith("data:")) {
|
|
336
|
+
return "datauri";
|
|
337
|
+
}
|
|
338
|
+
if (input.startsWith("http://") || input.startsWith("https://")) {
|
|
339
|
+
return "url";
|
|
340
|
+
}
|
|
341
|
+
return "path";
|
|
342
|
+
}
|
|
343
|
+
return "buffer";
|
|
344
|
+
}
|
|
323
345
|
/**
|
|
324
346
|
* Try fallback parsing for a specific file type
|
|
325
347
|
* Used when file detection returns "unknown" but we want to try parsing anyway
|
|
@@ -520,6 +542,31 @@ export class FileDetector {
|
|
|
520
542
|
* Stops at first strategy with confidence >= threshold (default: 80%)
|
|
521
543
|
*/
|
|
522
544
|
static async detect(input, options) {
|
|
545
|
+
// Short-circuit on a trustworthy caller-provided mimetype hint. This is
|
|
546
|
+
// the eager-path counterpart to FileReferenceRegistry.register()'s hint
|
|
547
|
+
// handling — necessary for tiny files (<= TINY_MAX) that skip the lazy
|
|
548
|
+
// registry path. normalizeMimeHint drops "application/octet-stream" so a
|
|
549
|
+
// caller cannot hide real content behind the opaque sentinel.
|
|
550
|
+
const hintMime = normalizeMimeHint(options?.mimetypeHint);
|
|
551
|
+
if (hintMime) {
|
|
552
|
+
const type = mimeHintToFileType(hintMime);
|
|
553
|
+
if (type) {
|
|
554
|
+
const ext = mimeHintToExtension(hintMime);
|
|
555
|
+
const result = {
|
|
556
|
+
type,
|
|
557
|
+
mimeType: hintMime,
|
|
558
|
+
extension: ext || null,
|
|
559
|
+
source: FileDetector.deriveInputSource(input),
|
|
560
|
+
metadata: {
|
|
561
|
+
confidence: 95,
|
|
562
|
+
filename: FileDetector.deriveInputFilename(input),
|
|
563
|
+
size: FileDetector.deriveInputSize(input),
|
|
564
|
+
},
|
|
565
|
+
};
|
|
566
|
+
logger.info(`[FileDetector] Type: ${type} (95%, from mimetype hint: ${hintMime})`);
|
|
567
|
+
return result;
|
|
568
|
+
}
|
|
569
|
+
}
|
|
523
570
|
const confidenceThreshold = options?.confidenceThreshold ?? 80;
|
|
524
571
|
const strategies = [
|
|
525
572
|
new MagicBytesStrategy(),
|
|
@@ -554,6 +554,7 @@ export async function buildMessagesArray(options) {
|
|
|
554
554
|
maxSize: 50 * 1024 * 1024,
|
|
555
555
|
allowedTypes: ["csv"],
|
|
556
556
|
csvOptions: csvOptions,
|
|
557
|
+
mimetypeHint: isFileWithMetadata(file) ? file.mimetype : undefined,
|
|
557
558
|
});
|
|
558
559
|
if (result.type === "csv") {
|
|
559
560
|
let csvSection = `\n\n## CSV Data from "${filename}":\n`;
|
|
@@ -806,6 +807,12 @@ async function processUnifiedFilesArray(options, maxSize, provider) {
|
|
|
806
807
|
// ─── Full processing path (current behavior) ──────────────────
|
|
807
808
|
const genericFileMaxSize = Math.max(maxSize, 100 * 1024 * 1024);
|
|
808
809
|
const rawFileInput = isFileWithMetadata(file) ? file.buffer : file;
|
|
810
|
+
// Forward the caller's mimetype hint (Slack/Curator-style
|
|
811
|
+
// extension-less buffers) so the eager path classifies correctly
|
|
812
|
+
// for tiny files — the lazy registry path has its own hint wiring.
|
|
813
|
+
const fileMimetypeHint = isFileWithMetadata(file)
|
|
814
|
+
? file.mimetype
|
|
815
|
+
: undefined;
|
|
809
816
|
const result = await FileDetector.detectAndProcess(rawFileInput, {
|
|
810
817
|
maxSize: genericFileMaxSize,
|
|
811
818
|
allowedTypes: [
|
|
@@ -824,6 +831,7 @@ async function processUnifiedFilesArray(options, maxSize, provider) {
|
|
|
824
831
|
],
|
|
825
832
|
csvOptions: options.csvOptions,
|
|
826
833
|
provider: provider,
|
|
834
|
+
mimetypeHint: fileMimetypeHint,
|
|
827
835
|
});
|
|
828
836
|
appendDetectedFileResult(result, file, options);
|
|
829
837
|
includedCount++;
|
|
@@ -1658,7 +1666,13 @@ async function tryRegisterFileReference(file, fileSize, registry, index = 0) {
|
|
|
1658
1666
|
return false;
|
|
1659
1667
|
}
|
|
1660
1668
|
const filename = extractFilename(file, index);
|
|
1661
|
-
|
|
1669
|
+
const mimetype = typeof file === "object" && !Buffer.isBuffer(file)
|
|
1670
|
+
? file.mimetype
|
|
1671
|
+
: undefined;
|
|
1672
|
+
await registry.register(buffer, getFileSource(file), {
|
|
1673
|
+
filename,
|
|
1674
|
+
mimetype,
|
|
1675
|
+
});
|
|
1662
1676
|
logger.info(`[FileDetector] Registered "${filename}" (${(fileSize / 1024).toFixed(0)} KB) ` +
|
|
1663
1677
|
`as lazy reference — skipping upfront processing`);
|
|
1664
1678
|
return true;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared helpers for caller-provided MIME type hints.
|
|
3
|
+
*
|
|
4
|
+
* A "MIME hint" is a mimetype string the SDK receives alongside a raw Buffer
|
|
5
|
+
* whose original filename is missing (e.g. Slack/Curator file-uploads that
|
|
6
|
+
* arrive as { buffer, filename: "Untitled", mimetype: "text/plain" }). When
|
|
7
|
+
* the filename has no extension and magic-byte detection cannot identify the
|
|
8
|
+
* content, the hint is the only signal we have.
|
|
9
|
+
*
|
|
10
|
+
* Both FileReferenceRegistry.register() and FileDetector.detect() consume
|
|
11
|
+
* these helpers so the trust/normalization rules stay in one place:
|
|
12
|
+
*
|
|
13
|
+
* - `application/octet-stream` is never trusted — it is the opaque
|
|
14
|
+
* "I don't know" sentinel and would let a caller hide real content
|
|
15
|
+
* behind a generic label (a PNG hinted as octet-stream would otherwise
|
|
16
|
+
* record mimeType="application/octet-stream" instead of "image/png").
|
|
17
|
+
* - Empty/undefined hints pass through as `undefined`.
|
|
18
|
+
* - A hint that cannot be classified maps to `null` so the caller falls
|
|
19
|
+
* back to magic-byte / extension detection instead of synthesising a
|
|
20
|
+
* wrong type.
|
|
21
|
+
*/
|
|
22
|
+
import type { FileType } from "../types/index.js";
|
|
23
|
+
/**
|
|
24
|
+
* Normalize a caller-provided mimetype hint: strip any `;charset=...`
|
|
25
|
+
* parameter, lowercase, trim. Returns undefined for empty strings or for
|
|
26
|
+
* the opaque `application/octet-stream` sentinel so downstream code can
|
|
27
|
+
* treat the hint as absent instead of trusting it verbatim.
|
|
28
|
+
*/
|
|
29
|
+
export declare function normalizeMimeHint(raw?: string): string | undefined;
|
|
30
|
+
/**
|
|
31
|
+
* Map a normalized mimetype hint to a NeuroLink FileType. Returns null when
|
|
32
|
+
* the mimetype is unknown or too generic to classify confidently.
|
|
33
|
+
*/
|
|
34
|
+
export declare function mimeHintToFileType(mimetype: string): FileType | null;
|
|
35
|
+
/**
|
|
36
|
+
* Map a normalized mimetype hint to the canonical file extension (without
|
|
37
|
+
* leading dot). Returns "" when the mimetype is unknown — caller should
|
|
38
|
+
* then fall back to magic-byte detection.
|
|
39
|
+
*/
|
|
40
|
+
export declare function mimeHintToExtension(mimetype: string): string;
|
|
@@ -0,0 +1,121 @@
|
|
|
1
|
+
const OPAQUE_MIMETYPE = "application/octet-stream";
|
|
2
|
+
/**
|
|
3
|
+
* Normalize a caller-provided mimetype hint: strip any `;charset=...`
|
|
4
|
+
* parameter, lowercase, trim. Returns undefined for empty strings or for
|
|
5
|
+
* the opaque `application/octet-stream` sentinel so downstream code can
|
|
6
|
+
* treat the hint as absent instead of trusting it verbatim.
|
|
7
|
+
*/
|
|
8
|
+
export function normalizeMimeHint(raw) {
|
|
9
|
+
if (!raw) {
|
|
10
|
+
return undefined;
|
|
11
|
+
}
|
|
12
|
+
const cleaned = raw.split(";")[0].trim().toLowerCase();
|
|
13
|
+
if (!cleaned || cleaned === OPAQUE_MIMETYPE) {
|
|
14
|
+
return undefined;
|
|
15
|
+
}
|
|
16
|
+
return cleaned;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Map a normalized mimetype hint to a NeuroLink FileType. Returns null when
|
|
20
|
+
* the mimetype is unknown or too generic to classify confidently.
|
|
21
|
+
*/
|
|
22
|
+
export function mimeHintToFileType(mimetype) {
|
|
23
|
+
const exact = {
|
|
24
|
+
"text/csv": "csv",
|
|
25
|
+
"application/csv": "csv",
|
|
26
|
+
"image/svg+xml": "svg",
|
|
27
|
+
"application/pdf": "pdf",
|
|
28
|
+
"application/json": "text",
|
|
29
|
+
"application/xml": "text",
|
|
30
|
+
"text/xml": "text",
|
|
31
|
+
"application/yaml": "text",
|
|
32
|
+
"application/x-yaml": "text",
|
|
33
|
+
"text/yaml": "text",
|
|
34
|
+
"application/javascript": "text",
|
|
35
|
+
"application/typescript": "text",
|
|
36
|
+
"application/zip": "archive",
|
|
37
|
+
"application/x-tar": "archive",
|
|
38
|
+
"application/gzip": "archive",
|
|
39
|
+
"application/x-gzip": "archive",
|
|
40
|
+
"application/x-7z-compressed": "archive",
|
|
41
|
+
"application/vnd.rar": "archive",
|
|
42
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
43
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
|
|
44
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
|
45
|
+
};
|
|
46
|
+
if (exact[mimetype]) {
|
|
47
|
+
return exact[mimetype];
|
|
48
|
+
}
|
|
49
|
+
if (mimetype.startsWith("text/")) {
|
|
50
|
+
return "text";
|
|
51
|
+
}
|
|
52
|
+
if (mimetype.startsWith("image/")) {
|
|
53
|
+
return "image";
|
|
54
|
+
}
|
|
55
|
+
if (mimetype.startsWith("audio/")) {
|
|
56
|
+
return "audio";
|
|
57
|
+
}
|
|
58
|
+
if (mimetype.startsWith("video/")) {
|
|
59
|
+
return "video";
|
|
60
|
+
}
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Map a normalized mimetype hint to the canonical file extension (without
|
|
65
|
+
* leading dot). Returns "" when the mimetype is unknown — caller should
|
|
66
|
+
* then fall back to magic-byte detection.
|
|
67
|
+
*/
|
|
68
|
+
export function mimeHintToExtension(mimetype) {
|
|
69
|
+
const table = {
|
|
70
|
+
// Text
|
|
71
|
+
"text/plain": "txt",
|
|
72
|
+
"text/html": "html",
|
|
73
|
+
"text/css": "css",
|
|
74
|
+
"text/javascript": "js",
|
|
75
|
+
"application/javascript": "js",
|
|
76
|
+
"application/typescript": "ts",
|
|
77
|
+
"text/markdown": "md",
|
|
78
|
+
"text/csv": "csv",
|
|
79
|
+
"application/csv": "csv",
|
|
80
|
+
"application/json": "json",
|
|
81
|
+
"application/xml": "xml",
|
|
82
|
+
"text/xml": "xml",
|
|
83
|
+
"application/yaml": "yaml",
|
|
84
|
+
"application/x-yaml": "yaml",
|
|
85
|
+
"text/yaml": "yaml",
|
|
86
|
+
// Documents
|
|
87
|
+
"application/pdf": "pdf",
|
|
88
|
+
"application/vnd.openxmlformats-officedocument.wordprocessingml.document": "docx",
|
|
89
|
+
"application/vnd.openxmlformats-officedocument.presentationml.presentation": "pptx",
|
|
90
|
+
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet": "xlsx",
|
|
91
|
+
// Images
|
|
92
|
+
"image/png": "png",
|
|
93
|
+
"image/jpeg": "jpg",
|
|
94
|
+
"image/gif": "gif",
|
|
95
|
+
"image/webp": "webp",
|
|
96
|
+
"image/bmp": "bmp",
|
|
97
|
+
"image/tiff": "tiff",
|
|
98
|
+
"image/svg+xml": "svg",
|
|
99
|
+
// Video
|
|
100
|
+
"video/mp4": "mp4",
|
|
101
|
+
"video/webm": "webm",
|
|
102
|
+
"video/quicktime": "mov",
|
|
103
|
+
"video/x-matroska": "mkv",
|
|
104
|
+
"video/x-msvideo": "avi",
|
|
105
|
+
// Audio
|
|
106
|
+
"audio/mpeg": "mp3",
|
|
107
|
+
"audio/wav": "wav",
|
|
108
|
+
"audio/ogg": "ogg",
|
|
109
|
+
"audio/flac": "flac",
|
|
110
|
+
"audio/mp4": "m4a",
|
|
111
|
+
"audio/aac": "aac",
|
|
112
|
+
// Archives
|
|
113
|
+
"application/zip": "zip",
|
|
114
|
+
"application/x-tar": "tar",
|
|
115
|
+
"application/gzip": "gz",
|
|
116
|
+
"application/x-gzip": "gz",
|
|
117
|
+
"application/x-7z-compressed": "7z",
|
|
118
|
+
"application/vnd.rar": "rar",
|
|
119
|
+
};
|
|
120
|
+
return table[mimetype] || "";
|
|
121
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "9.
|
|
3
|
+
"version": "9.57.0",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"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.",
|
|
6
6
|
"author": {
|