@juspay/neurolink 9.64.0 → 9.65.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 +6 -0
- package/README.md +18 -17
- package/dist/adapters/providerImageAdapter.js +29 -1
- package/dist/adapters/replicate/auth.d.ts +19 -0
- package/dist/adapters/replicate/auth.js +32 -0
- package/dist/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/adapters/replicate/predictionLifecycle.js +283 -0
- package/dist/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/adapters/video/klingVideoHandler.js +305 -0
- package/dist/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/adapters/video/replicateVideoHandler.js +157 -0
- package/dist/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/adapters/video/runwayVideoHandler.js +316 -0
- package/dist/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/adapters/video/vertexVideoHandler.js +33 -9
- package/dist/autoresearch/runner.js +8 -2
- package/dist/avatar/index.d.ts +13 -0
- package/dist/avatar/index.js +13 -0
- package/dist/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/avatar/providers/DIDAvatar.js +501 -0
- package/dist/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/avatar/providers/HeyGenAvatar.js +337 -0
- package/dist/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/avatar/providers/ReplicateAvatar.js +267 -0
- package/dist/browser/neurolink.min.js +633 -610
- package/dist/cli/commands/mcp.js +29 -0
- package/dist/cli/commands/proxy.js +24 -5
- package/dist/cli/factories/commandFactory.d.ts +11 -1
- package/dist/cli/factories/commandFactory.js +291 -38
- package/dist/constants/contextWindows.js +101 -0
- package/dist/constants/enums.d.ts +273 -2
- package/dist/constants/enums.js +290 -1
- package/dist/constants/videoErrors.d.ts +4 -0
- package/dist/constants/videoErrors.js +4 -0
- package/dist/core/baseProvider.d.ts +22 -2
- package/dist/core/baseProvider.js +217 -11
- package/dist/core/constants.d.ts +11 -0
- package/dist/core/constants.js +69 -1
- package/dist/core/redisConversationMemoryManager.js +6 -0
- package/dist/evaluation/index.d.ts +2 -0
- package/dist/evaluation/index.js +4 -0
- package/dist/factories/providerFactory.js +7 -1
- package/dist/factories/providerRegistry.js +202 -5
- package/dist/features/ppt/contentPlanner.js +42 -14
- package/dist/index.d.ts +9 -1
- package/dist/index.js +16 -1
- package/dist/lib/adapters/providerImageAdapter.js +29 -1
- package/dist/lib/adapters/replicate/auth.d.ts +19 -0
- package/dist/lib/adapters/replicate/auth.js +33 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.d.ts +46 -0
- package/dist/lib/adapters/replicate/predictionLifecycle.js +284 -0
- package/dist/lib/adapters/video/klingVideoHandler.d.ts +37 -0
- package/dist/lib/adapters/video/klingVideoHandler.js +306 -0
- package/dist/lib/adapters/video/replicateVideoHandler.d.ts +29 -0
- package/dist/lib/adapters/video/replicateVideoHandler.js +158 -0
- package/dist/lib/adapters/video/runwayVideoHandler.d.ts +32 -0
- package/dist/lib/adapters/video/runwayVideoHandler.js +317 -0
- package/dist/lib/adapters/video/vertexVideoHandler.d.ts +19 -1
- package/dist/lib/adapters/video/vertexVideoHandler.js +33 -9
- package/dist/lib/autoresearch/runner.js +8 -2
- package/dist/lib/avatar/index.d.ts +13 -0
- package/dist/lib/avatar/index.js +14 -0
- package/dist/lib/avatar/providers/DIDAvatar.d.ts +49 -0
- package/dist/lib/avatar/providers/DIDAvatar.js +502 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.d.ts +30 -0
- package/dist/lib/avatar/providers/HeyGenAvatar.js +338 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.d.ts +36 -0
- package/dist/lib/avatar/providers/ReplicateAvatar.js +268 -0
- package/dist/lib/constants/contextWindows.js +101 -0
- package/dist/lib/constants/enums.d.ts +273 -2
- package/dist/lib/constants/enums.js +290 -1
- package/dist/lib/constants/videoErrors.d.ts +4 -0
- package/dist/lib/constants/videoErrors.js +4 -0
- package/dist/lib/core/baseProvider.d.ts +22 -2
- package/dist/lib/core/baseProvider.js +217 -11
- package/dist/lib/core/constants.d.ts +11 -0
- package/dist/lib/core/constants.js +69 -1
- package/dist/lib/core/redisConversationMemoryManager.js +6 -0
- package/dist/lib/evaluation/index.d.ts +2 -0
- package/dist/lib/evaluation/index.js +4 -0
- package/dist/lib/factories/providerFactory.js +7 -1
- package/dist/lib/factories/providerRegistry.js +202 -5
- package/dist/lib/features/ppt/contentPlanner.js +42 -14
- package/dist/lib/index.d.ts +9 -1
- package/dist/lib/index.js +16 -1
- package/dist/lib/middleware/builtin/lifecycle.js +39 -9
- package/dist/lib/music/index.d.ts +13 -0
- package/dist/lib/music/index.js +14 -0
- package/dist/lib/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/lib/music/providers/BeatovenMusic.js +334 -0
- package/dist/lib/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/lib/music/providers/ElevenLabsMusic.js +169 -0
- package/dist/lib/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/lib/music/providers/LyriaMusic.js +173 -0
- package/dist/lib/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/lib/music/providers/ReplicateMusic.js +262 -0
- package/dist/lib/neurolink.d.ts +30 -0
- package/dist/lib/neurolink.js +323 -77
- package/dist/lib/providers/amazonBedrock.d.ts +10 -0
- package/dist/lib/providers/amazonBedrock.js +94 -39
- package/dist/lib/providers/anthropic.js +55 -7
- package/dist/lib/providers/anthropicBaseProvider.js +1 -1
- package/dist/lib/providers/azureOpenai.js +66 -17
- package/dist/lib/providers/cloudflare.d.ts +35 -0
- package/dist/lib/providers/cloudflare.js +174 -0
- package/dist/lib/providers/cohere.d.ts +52 -0
- package/dist/lib/providers/cohere.js +253 -0
- package/dist/lib/providers/deepseek.js +72 -17
- package/dist/lib/providers/fireworks.d.ts +33 -0
- package/dist/lib/providers/fireworks.js +164 -0
- package/dist/lib/providers/googleAiStudio.js +45 -6
- package/dist/lib/providers/googleNativeGemini3.d.ts +24 -1
- package/dist/lib/providers/googleNativeGemini3.js +173 -21
- package/dist/lib/providers/googleVertex.js +173 -17
- package/dist/lib/providers/groq.d.ts +33 -0
- package/dist/lib/providers/groq.js +181 -0
- package/dist/lib/providers/huggingFace.js +9 -8
- package/dist/lib/providers/ideogram.d.ts +34 -0
- package/dist/lib/providers/ideogram.js +184 -0
- package/dist/lib/providers/index.d.ts +13 -0
- package/dist/lib/providers/index.js +13 -0
- package/dist/lib/providers/jina.d.ts +59 -0
- package/dist/lib/providers/jina.js +218 -0
- package/dist/lib/providers/llamaCpp.js +14 -46
- package/dist/lib/providers/lmStudio.js +14 -47
- package/dist/lib/providers/mistral.js +7 -7
- package/dist/lib/providers/nvidiaNim.js +160 -19
- package/dist/lib/providers/ollama.js +7 -7
- package/dist/lib/providers/openAI.d.ts +22 -1
- package/dist/lib/providers/openAI.js +181 -0
- package/dist/lib/providers/openRouter.js +35 -23
- package/dist/lib/providers/openaiCompatible.js +9 -8
- package/dist/lib/providers/perplexity.d.ts +33 -0
- package/dist/lib/providers/perplexity.js +179 -0
- package/dist/lib/providers/recraft.d.ts +34 -0
- package/dist/lib/providers/recraft.js +197 -0
- package/dist/lib/providers/replicate.d.ts +75 -0
- package/dist/lib/providers/replicate.js +403 -0
- package/dist/lib/providers/stability.d.ts +37 -0
- package/dist/lib/providers/stability.js +191 -0
- package/dist/lib/providers/togetherAi.d.ts +33 -0
- package/dist/lib/providers/togetherAi.js +176 -0
- package/dist/lib/providers/voyage.d.ts +47 -0
- package/dist/lib/providers/voyage.js +177 -0
- package/dist/lib/providers/xai.d.ts +33 -0
- package/dist/lib/providers/xai.js +172 -0
- package/dist/lib/telemetry/index.d.ts +1 -1
- package/dist/lib/telemetry/index.js +1 -1
- package/dist/lib/telemetry/tracers.d.ts +19 -0
- package/dist/lib/telemetry/tracers.js +19 -0
- package/dist/lib/telemetry/withSpan.d.ts +35 -0
- package/dist/lib/telemetry/withSpan.js +103 -0
- package/dist/lib/types/avatar.d.ts +143 -0
- package/dist/lib/types/avatar.js +20 -0
- package/dist/lib/types/cli.d.ts +6 -0
- package/dist/lib/types/generate.d.ts +62 -5
- package/dist/lib/types/index.d.ts +5 -0
- package/dist/lib/types/index.js +7 -0
- package/dist/lib/types/middleware.d.ts +27 -0
- package/dist/lib/types/multimodal.d.ts +35 -2
- package/dist/lib/types/music.d.ts +165 -0
- package/dist/lib/types/music.js +21 -0
- package/dist/lib/types/providers.d.ts +144 -1
- package/dist/lib/types/replicate.d.ts +67 -0
- package/dist/lib/types/replicate.js +10 -0
- package/dist/lib/types/safeFetch.d.ts +15 -0
- package/dist/lib/types/safeFetch.js +7 -0
- package/dist/lib/types/stream.d.ts +2 -1
- package/dist/lib/types/tools.d.ts +13 -0
- package/dist/lib/types/video.d.ts +89 -0
- package/dist/lib/types/video.js +15 -0
- package/dist/lib/utils/avatarProcessor.d.ts +68 -0
- package/dist/lib/utils/avatarProcessor.js +172 -0
- package/dist/lib/utils/cloneOptions.d.ts +36 -0
- package/dist/lib/utils/cloneOptions.js +62 -0
- package/dist/lib/utils/lifecycleCallbacks.d.ts +51 -8
- package/dist/lib/utils/lifecycleCallbacks.js +82 -26
- package/dist/lib/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/lib/utils/lifecycleTimeout.js +39 -0
- package/dist/lib/utils/logSanitize.d.ts +49 -0
- package/dist/lib/utils/logSanitize.js +170 -0
- package/dist/lib/utils/loggingFetch.d.ts +29 -0
- package/dist/lib/utils/loggingFetch.js +60 -0
- package/dist/lib/utils/messageBuilder.js +43 -25
- package/dist/lib/utils/modelChoices.js +236 -3
- package/dist/lib/utils/musicProcessor.d.ts +67 -0
- package/dist/lib/utils/musicProcessor.js +189 -0
- package/dist/lib/utils/optionsConversion.js +3 -2
- package/dist/lib/utils/parameterValidation.js +14 -4
- package/dist/lib/utils/pricing.js +193 -0
- package/dist/lib/utils/providerConfig.d.ts +55 -0
- package/dist/lib/utils/providerConfig.js +224 -0
- package/dist/lib/utils/safeFetch.d.ts +26 -0
- package/dist/lib/utils/safeFetch.js +83 -0
- package/dist/lib/utils/sizeGuard.d.ts +34 -0
- package/dist/lib/utils/sizeGuard.js +45 -0
- package/dist/lib/utils/ssrfGuard.d.ts +52 -0
- package/dist/lib/utils/ssrfGuard.js +411 -0
- package/dist/lib/utils/videoProcessor.d.ts +60 -0
- package/dist/lib/utils/videoProcessor.js +201 -0
- package/dist/lib/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/lib/voice/providers/FishAudioTTS.js +183 -0
- package/dist/lib/workflow/core/ensembleExecutor.js +26 -9
- package/dist/middleware/builtin/lifecycle.js +39 -9
- package/dist/music/index.d.ts +13 -0
- package/dist/music/index.js +13 -0
- package/dist/music/providers/BeatovenMusic.d.ts +31 -0
- package/dist/music/providers/BeatovenMusic.js +333 -0
- package/dist/music/providers/ElevenLabsMusic.d.ts +30 -0
- package/dist/music/providers/ElevenLabsMusic.js +168 -0
- package/dist/music/providers/LyriaMusic.d.ts +29 -0
- package/dist/music/providers/LyriaMusic.js +172 -0
- package/dist/music/providers/ReplicateMusic.d.ts +31 -0
- package/dist/music/providers/ReplicateMusic.js +261 -0
- package/dist/neurolink.d.ts +30 -0
- package/dist/neurolink.js +323 -77
- package/dist/providers/amazonBedrock.d.ts +10 -0
- package/dist/providers/amazonBedrock.js +94 -39
- package/dist/providers/anthropic.js +55 -7
- package/dist/providers/anthropicBaseProvider.js +1 -1
- package/dist/providers/azureOpenai.js +66 -17
- package/dist/providers/cloudflare.d.ts +35 -0
- package/dist/providers/cloudflare.js +173 -0
- package/dist/providers/cohere.d.ts +52 -0
- package/dist/providers/cohere.js +252 -0
- package/dist/providers/deepseek.js +72 -17
- package/dist/providers/fireworks.d.ts +33 -0
- package/dist/providers/fireworks.js +163 -0
- package/dist/providers/googleAiStudio.js +45 -6
- package/dist/providers/googleNativeGemini3.d.ts +24 -1
- package/dist/providers/googleNativeGemini3.js +173 -21
- package/dist/providers/googleVertex.js +173 -17
- package/dist/providers/groq.d.ts +33 -0
- package/dist/providers/groq.js +180 -0
- package/dist/providers/huggingFace.js +9 -8
- package/dist/providers/ideogram.d.ts +34 -0
- package/dist/providers/ideogram.js +183 -0
- package/dist/providers/index.d.ts +13 -0
- package/dist/providers/index.js +13 -0
- package/dist/providers/jina.d.ts +59 -0
- package/dist/providers/jina.js +217 -0
- package/dist/providers/llamaCpp.js +14 -46
- package/dist/providers/lmStudio.js +14 -47
- package/dist/providers/mistral.js +7 -7
- package/dist/providers/nvidiaNim.js +160 -19
- package/dist/providers/ollama.js +7 -7
- package/dist/providers/openAI.d.ts +22 -1
- package/dist/providers/openAI.js +181 -0
- package/dist/providers/openRouter.js +35 -23
- package/dist/providers/openaiCompatible.js +9 -8
- package/dist/providers/perplexity.d.ts +33 -0
- package/dist/providers/perplexity.js +178 -0
- package/dist/providers/recraft.d.ts +34 -0
- package/dist/providers/recraft.js +196 -0
- package/dist/providers/replicate.d.ts +75 -0
- package/dist/providers/replicate.js +402 -0
- package/dist/providers/stability.d.ts +37 -0
- package/dist/providers/stability.js +190 -0
- package/dist/providers/togetherAi.d.ts +33 -0
- package/dist/providers/togetherAi.js +175 -0
- package/dist/providers/voyage.d.ts +47 -0
- package/dist/providers/voyage.js +176 -0
- package/dist/providers/xai.d.ts +33 -0
- package/dist/providers/xai.js +171 -0
- package/dist/telemetry/index.d.ts +1 -1
- package/dist/telemetry/index.js +1 -1
- package/dist/telemetry/tracers.d.ts +19 -0
- package/dist/telemetry/tracers.js +19 -0
- package/dist/telemetry/withSpan.d.ts +35 -0
- package/dist/telemetry/withSpan.js +103 -0
- package/dist/types/avatar.d.ts +143 -0
- package/dist/types/avatar.js +19 -0
- package/dist/types/cli.d.ts +6 -0
- package/dist/types/generate.d.ts +62 -5
- package/dist/types/index.d.ts +5 -0
- package/dist/types/index.js +7 -0
- package/dist/types/middleware.d.ts +27 -0
- package/dist/types/multimodal.d.ts +35 -2
- package/dist/types/music.d.ts +165 -0
- package/dist/types/music.js +20 -0
- package/dist/types/providers.d.ts +144 -1
- package/dist/types/replicate.d.ts +67 -0
- package/dist/types/replicate.js +9 -0
- package/dist/types/safeFetch.d.ts +15 -0
- package/dist/types/safeFetch.js +6 -0
- package/dist/types/stream.d.ts +2 -1
- package/dist/types/tools.d.ts +13 -0
- package/dist/types/video.d.ts +89 -0
- package/dist/types/video.js +14 -0
- package/dist/utils/avatarProcessor.d.ts +68 -0
- package/dist/utils/avatarProcessor.js +171 -0
- package/dist/utils/cloneOptions.d.ts +36 -0
- package/dist/utils/cloneOptions.js +61 -0
- package/dist/utils/lifecycleCallbacks.d.ts +51 -8
- package/dist/utils/lifecycleCallbacks.js +82 -26
- package/dist/utils/lifecycleTimeout.d.ts +25 -0
- package/dist/utils/lifecycleTimeout.js +38 -0
- package/dist/utils/logSanitize.d.ts +49 -0
- package/dist/utils/logSanitize.js +169 -0
- package/dist/utils/loggingFetch.d.ts +29 -0
- package/dist/utils/loggingFetch.js +59 -0
- package/dist/utils/messageBuilder.js +43 -25
- package/dist/utils/modelChoices.js +236 -3
- package/dist/utils/musicProcessor.d.ts +67 -0
- package/dist/utils/musicProcessor.js +188 -0
- package/dist/utils/optionsConversion.js +3 -2
- package/dist/utils/parameterValidation.js +14 -4
- package/dist/utils/pricing.js +193 -0
- package/dist/utils/providerConfig.d.ts +55 -0
- package/dist/utils/providerConfig.js +224 -0
- package/dist/utils/safeFetch.d.ts +26 -0
- package/dist/utils/safeFetch.js +82 -0
- package/dist/utils/sizeGuard.d.ts +34 -0
- package/dist/utils/sizeGuard.js +44 -0
- package/dist/utils/ssrfGuard.d.ts +52 -0
- package/dist/utils/ssrfGuard.js +410 -0
- package/dist/utils/videoProcessor.d.ts +60 -0
- package/dist/utils/videoProcessor.js +200 -0
- package/dist/voice/providers/FishAudioTTS.d.ts +27 -0
- package/dist/voice/providers/FishAudioTTS.js +182 -0
- package/dist/workflow/core/ensembleExecutor.js +26 -9
- package/package.json +32 -5
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { LifecycleMiddlewareConfig } from "../types/index.js";
|
|
2
|
+
/**
|
|
3
|
+
* Default deadline applied to consumer-supplied lifecycle callbacks
|
|
4
|
+
* (`onChunk`, `onFinish`, `onError`) when neither
|
|
5
|
+
* `LifecycleMiddlewareConfig.timeoutMs` nor the
|
|
6
|
+
* `NEUROLINK_LIFECYCLE_TIMEOUT_MS` env var is set.
|
|
7
|
+
*
|
|
8
|
+
* 5s is generous — far longer than legitimate sync logging, far
|
|
9
|
+
* shorter than a stuck network call. Callers with slow telemetry
|
|
10
|
+
* sinks should set `timeoutMs` explicitly.
|
|
11
|
+
*/
|
|
12
|
+
export declare const DEFAULT_LIFECYCLE_TIMEOUT_MS = 5000;
|
|
13
|
+
/**
|
|
14
|
+
* Resolve the deadline for a single lifecycle callback invocation.
|
|
15
|
+
*
|
|
16
|
+
* Order of precedence:
|
|
17
|
+
* 1. `lifecycle.timeoutMs` from the per-call SDK config
|
|
18
|
+
* 2. `NEUROLINK_LIFECYCLE_TIMEOUT_MS` env var (also honored by the CLI)
|
|
19
|
+
* 3. `DEFAULT_LIFECYCLE_TIMEOUT_MS` (5_000)
|
|
20
|
+
*
|
|
21
|
+
* Negative / non-finite values fall through to the next source. `0`
|
|
22
|
+
* is accepted and means "no wait" (the consumer's async work is
|
|
23
|
+
* effectively fire-and-forget).
|
|
24
|
+
*/
|
|
25
|
+
export declare function resolveLifecycleTimeoutMs(lifecycle?: Pick<LifecycleMiddlewareConfig, "timeoutMs"> | null): number;
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Default deadline applied to consumer-supplied lifecycle callbacks
|
|
3
|
+
* (`onChunk`, `onFinish`, `onError`) when neither
|
|
4
|
+
* `LifecycleMiddlewareConfig.timeoutMs` nor the
|
|
5
|
+
* `NEUROLINK_LIFECYCLE_TIMEOUT_MS` env var is set.
|
|
6
|
+
*
|
|
7
|
+
* 5s is generous — far longer than legitimate sync logging, far
|
|
8
|
+
* shorter than a stuck network call. Callers with slow telemetry
|
|
9
|
+
* sinks should set `timeoutMs` explicitly.
|
|
10
|
+
*/
|
|
11
|
+
export const DEFAULT_LIFECYCLE_TIMEOUT_MS = 5_000;
|
|
12
|
+
/**
|
|
13
|
+
* Resolve the deadline for a single lifecycle callback invocation.
|
|
14
|
+
*
|
|
15
|
+
* Order of precedence:
|
|
16
|
+
* 1. `lifecycle.timeoutMs` from the per-call SDK config
|
|
17
|
+
* 2. `NEUROLINK_LIFECYCLE_TIMEOUT_MS` env var (also honored by the CLI)
|
|
18
|
+
* 3. `DEFAULT_LIFECYCLE_TIMEOUT_MS` (5_000)
|
|
19
|
+
*
|
|
20
|
+
* Negative / non-finite values fall through to the next source. `0`
|
|
21
|
+
* is accepted and means "no wait" (the consumer's async work is
|
|
22
|
+
* effectively fire-and-forget).
|
|
23
|
+
*/
|
|
24
|
+
export function resolveLifecycleTimeoutMs(lifecycle) {
|
|
25
|
+
if (lifecycle && typeof lifecycle.timeoutMs === "number") {
|
|
26
|
+
if (Number.isFinite(lifecycle.timeoutMs) && lifecycle.timeoutMs >= 0) {
|
|
27
|
+
return lifecycle.timeoutMs;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
const raw = process.env.NEUROLINK_LIFECYCLE_TIMEOUT_MS;
|
|
31
|
+
if (raw) {
|
|
32
|
+
const parsed = Number(raw);
|
|
33
|
+
if (Number.isFinite(parsed) && parsed >= 0) {
|
|
34
|
+
return parsed;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return DEFAULT_LIFECYCLE_TIMEOUT_MS;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=lifecycleTimeout.js.map
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared log-sanitization helpers.
|
|
3
|
+
*
|
|
4
|
+
* Centralises truncate + secret-redaction patterns so every provider stays
|
|
5
|
+
* consistent and any regex improvements only need one change.
|
|
6
|
+
*
|
|
7
|
+
* Coverage:
|
|
8
|
+
* - `Authorization: Bearer <token>` (with required whitespace)
|
|
9
|
+
* - `Authorization: Token <token>` (Replicate uses this, not Bearer)
|
|
10
|
+
* - `Authorization: Basic <base64>` (D-ID and similar)
|
|
11
|
+
* - Bare tokens by known provider prefix:
|
|
12
|
+
* sk-/pk- (OpenAI, Anthropic, Stability),
|
|
13
|
+
* r8_ (Replicate), gsk_ (Groq), xai- (xAI), tgp_ (Together),
|
|
14
|
+
* fw_ (Fireworks), pplx- (Perplexity), pa- (Voyage),
|
|
15
|
+
* jina_ (Jina), fish- (Fish Audio)
|
|
16
|
+
* - Generic key=value pairs: api_key=…, access_token: …, secret_key=…
|
|
17
|
+
*/
|
|
18
|
+
/**
|
|
19
|
+
* Truncate `text` to `maxLen` chars then replace embedded secrets with `***`.
|
|
20
|
+
*
|
|
21
|
+
* Use this for free-form text logged from response/request bodies. For
|
|
22
|
+
* structured data (records, headers) prefer {@link sanitizeRecord} and
|
|
23
|
+
* {@link sanitizeHeaders} which know to redact by key name as well.
|
|
24
|
+
*
|
|
25
|
+
* @param text - Raw text to sanitize (typically an HTTP response body).
|
|
26
|
+
* @param maxLen - Maximum number of characters to keep (default 500).
|
|
27
|
+
*/
|
|
28
|
+
export declare function sanitizeForLog(text: string, maxLen?: number): string;
|
|
29
|
+
/**
|
|
30
|
+
* Recursively sanitize a record/array, returning a structurally identical
|
|
31
|
+
* value with sensitive keys redacted and string values run through
|
|
32
|
+
* {@link sanitizeForLog}.
|
|
33
|
+
*
|
|
34
|
+
* Safe to call on any JSON-shaped data. Cycles are detected and replaced
|
|
35
|
+
* with the string `"[Circular]"` to avoid infinite recursion when logging
|
|
36
|
+
* mid-stream objects that reference themselves.
|
|
37
|
+
*
|
|
38
|
+
* @param value - The value to sanitize.
|
|
39
|
+
* @param maxStringLen - Per-string truncation cap (default 1000).
|
|
40
|
+
*/
|
|
41
|
+
export declare function sanitizeRecord<T>(value: T, maxStringLen?: number): T;
|
|
42
|
+
/**
|
|
43
|
+
* Sanitize an HTTP headers object — redacts sensitive header names entirely
|
|
44
|
+
* (`***`) and applies {@link sanitizeForLog} to remaining values.
|
|
45
|
+
*
|
|
46
|
+
* Accepts both `Headers` instances and plain-object header maps so providers
|
|
47
|
+
* can log either shape uniformly.
|
|
48
|
+
*/
|
|
49
|
+
export declare function sanitizeHeaders(headers: Headers | Record<string, string | undefined> | undefined): Record<string, string>;
|
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared log-sanitization helpers.
|
|
3
|
+
*
|
|
4
|
+
* Centralises truncate + secret-redaction patterns so every provider stays
|
|
5
|
+
* consistent and any regex improvements only need one change.
|
|
6
|
+
*
|
|
7
|
+
* Coverage:
|
|
8
|
+
* - `Authorization: Bearer <token>` (with required whitespace)
|
|
9
|
+
* - `Authorization: Token <token>` (Replicate uses this, not Bearer)
|
|
10
|
+
* - `Authorization: Basic <base64>` (D-ID and similar)
|
|
11
|
+
* - Bare tokens by known provider prefix:
|
|
12
|
+
* sk-/pk- (OpenAI, Anthropic, Stability),
|
|
13
|
+
* r8_ (Replicate), gsk_ (Groq), xai- (xAI), tgp_ (Together),
|
|
14
|
+
* fw_ (Fireworks), pplx- (Perplexity), pa- (Voyage),
|
|
15
|
+
* jina_ (Jina), fish- (Fish Audio)
|
|
16
|
+
* - Generic key=value pairs: api_key=…, access_token: …, secret_key=…
|
|
17
|
+
*/
|
|
18
|
+
const TOKEN_PREFIXES = [
|
|
19
|
+
"sk",
|
|
20
|
+
"pk",
|
|
21
|
+
"r8",
|
|
22
|
+
"gsk",
|
|
23
|
+
"xai",
|
|
24
|
+
"tgp",
|
|
25
|
+
"fw",
|
|
26
|
+
"pplx",
|
|
27
|
+
"pa",
|
|
28
|
+
"jina",
|
|
29
|
+
"fish",
|
|
30
|
+
];
|
|
31
|
+
const PREFIX_PATTERN = TOKEN_PREFIXES.join("|");
|
|
32
|
+
/**
|
|
33
|
+
* Pattern matching common bearer/API-key tokens in plain text.
|
|
34
|
+
*
|
|
35
|
+
* Case-insensitive (`i` flag) since header names ("Authorization") and scheme
|
|
36
|
+
* names ("Bearer", "Token", "Basic") are sometimes lower-cased in error
|
|
37
|
+
* bodies. `g` flag for replace-all.
|
|
38
|
+
*/
|
|
39
|
+
const SECRET_PATTERN = new RegExp(
|
|
40
|
+
// Authorization schemes — required whitespace between scheme and value
|
|
41
|
+
"\\bBearer\\s+[A-Za-z0-9_\\-\\.]{8,}\\b" +
|
|
42
|
+
"|\\bToken\\s+[A-Za-z0-9_\\-\\.]{8,}\\b" +
|
|
43
|
+
"|\\bBasic\\s+[A-Za-z0-9+/=]{12,}\\b" +
|
|
44
|
+
// Bare tokens by known prefix (e.g. `sk-abc…`, `r8_xyz…`)
|
|
45
|
+
`|\\b(?:${PREFIX_PATTERN})[_\\-][A-Za-z0-9_\\-\\.]{8,}\\b` +
|
|
46
|
+
// Generic key=value pairs (URL params, JSON bodies, header dumps)
|
|
47
|
+
"|\\b(?:api[_-]?key|access[_-]?token|secret[_-]?key|refresh[_-]?token)\\s*[:=]\\s*['\"]?[^\\s,;'\"&]+", "gi");
|
|
48
|
+
/** Header names that should always be redacted regardless of value shape. */
|
|
49
|
+
const SENSITIVE_HEADER_NAMES = [
|
|
50
|
+
"authorization",
|
|
51
|
+
"cookie",
|
|
52
|
+
"set-cookie",
|
|
53
|
+
"x-api-key",
|
|
54
|
+
"api-key",
|
|
55
|
+
"apikey",
|
|
56
|
+
"x-auth-token",
|
|
57
|
+
"x-csrf-token",
|
|
58
|
+
];
|
|
59
|
+
/** Object keys that should always be redacted regardless of value shape. */
|
|
60
|
+
const SENSITIVE_OBJECT_KEYS = [
|
|
61
|
+
"apikey",
|
|
62
|
+
"api_key",
|
|
63
|
+
"apiKey",
|
|
64
|
+
"access_token",
|
|
65
|
+
"accessToken",
|
|
66
|
+
"refresh_token",
|
|
67
|
+
"refreshToken",
|
|
68
|
+
"secret",
|
|
69
|
+
"secretkey",
|
|
70
|
+
"secret_key",
|
|
71
|
+
"secretKey",
|
|
72
|
+
"password",
|
|
73
|
+
"authorization",
|
|
74
|
+
"oauth",
|
|
75
|
+
"oauthToken",
|
|
76
|
+
"credentials",
|
|
77
|
+
];
|
|
78
|
+
/**
|
|
79
|
+
* Truncate `text` to `maxLen` chars then replace embedded secrets with `***`.
|
|
80
|
+
*
|
|
81
|
+
* Use this for free-form text logged from response/request bodies. For
|
|
82
|
+
* structured data (records, headers) prefer {@link sanitizeRecord} and
|
|
83
|
+
* {@link sanitizeHeaders} which know to redact by key name as well.
|
|
84
|
+
*
|
|
85
|
+
* @param text - Raw text to sanitize (typically an HTTP response body).
|
|
86
|
+
* @param maxLen - Maximum number of characters to keep (default 500).
|
|
87
|
+
*/
|
|
88
|
+
export function sanitizeForLog(text, maxLen = 500) {
|
|
89
|
+
if (!text) {
|
|
90
|
+
return text;
|
|
91
|
+
}
|
|
92
|
+
return text.slice(0, maxLen).replace(SECRET_PATTERN, "***");
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Recursively sanitize a record/array, returning a structurally identical
|
|
96
|
+
* value with sensitive keys redacted and string values run through
|
|
97
|
+
* {@link sanitizeForLog}.
|
|
98
|
+
*
|
|
99
|
+
* Safe to call on any JSON-shaped data. Cycles are detected and replaced
|
|
100
|
+
* with the string `"[Circular]"` to avoid infinite recursion when logging
|
|
101
|
+
* mid-stream objects that reference themselves.
|
|
102
|
+
*
|
|
103
|
+
* @param value - The value to sanitize.
|
|
104
|
+
* @param maxStringLen - Per-string truncation cap (default 1000).
|
|
105
|
+
*/
|
|
106
|
+
export function sanitizeRecord(value, maxStringLen = 1000) {
|
|
107
|
+
const seen = new WeakSet();
|
|
108
|
+
const walk = (v) => {
|
|
109
|
+
if (v === null || v === undefined) {
|
|
110
|
+
return v;
|
|
111
|
+
}
|
|
112
|
+
if (typeof v === "string") {
|
|
113
|
+
return sanitizeForLog(v, maxStringLen);
|
|
114
|
+
}
|
|
115
|
+
if (typeof v !== "object") {
|
|
116
|
+
return v;
|
|
117
|
+
}
|
|
118
|
+
if (seen.has(v)) {
|
|
119
|
+
return "[Circular]";
|
|
120
|
+
}
|
|
121
|
+
seen.add(v);
|
|
122
|
+
if (Array.isArray(v)) {
|
|
123
|
+
return v.map(walk);
|
|
124
|
+
}
|
|
125
|
+
const out = {};
|
|
126
|
+
for (const [k, val] of Object.entries(v)) {
|
|
127
|
+
if (SENSITIVE_OBJECT_KEYS.some((name) => name.toLowerCase() === k.toLowerCase())) {
|
|
128
|
+
out[k] = "***";
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
out[k] = walk(val);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
return out;
|
|
135
|
+
};
|
|
136
|
+
return walk(value);
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Sanitize an HTTP headers object — redacts sensitive header names entirely
|
|
140
|
+
* (`***`) and applies {@link sanitizeForLog} to remaining values.
|
|
141
|
+
*
|
|
142
|
+
* Accepts both `Headers` instances and plain-object header maps so providers
|
|
143
|
+
* can log either shape uniformly.
|
|
144
|
+
*/
|
|
145
|
+
export function sanitizeHeaders(headers) {
|
|
146
|
+
if (!headers) {
|
|
147
|
+
return {};
|
|
148
|
+
}
|
|
149
|
+
const out = {};
|
|
150
|
+
const set = (name, value) => {
|
|
151
|
+
if (value === undefined || value === null) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
154
|
+
const lower = name.toLowerCase();
|
|
155
|
+
if (SENSITIVE_HEADER_NAMES.includes(lower)) {
|
|
156
|
+
out[name] = "***";
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
out[name] = sanitizeForLog(value, 500);
|
|
160
|
+
};
|
|
161
|
+
if (headers instanceof Headers) {
|
|
162
|
+
headers.forEach((value, key) => set(key, value));
|
|
163
|
+
return out;
|
|
164
|
+
}
|
|
165
|
+
for (const [key, value] of Object.entries(headers)) {
|
|
166
|
+
set(key, value);
|
|
167
|
+
}
|
|
168
|
+
return out;
|
|
169
|
+
}
|
|
170
|
+
//# sourceMappingURL=logSanitize.js.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared logging-fetch wrapper.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `createProxyFetch()` and logs every non-2xx upstream response with:
|
|
5
|
+
* - provider label
|
|
6
|
+
* - HTTP status code
|
|
7
|
+
* - URL with embedded credentials / signed query params masked
|
|
8
|
+
* (via `maskProxyUrl`)
|
|
9
|
+
* - request body size (string-body only — multipart/streamed bodies
|
|
10
|
+
* report 0)
|
|
11
|
+
*
|
|
12
|
+
* Response bodies are NOT logged by default (they can echo prompt fragments,
|
|
13
|
+
* tool payloads, or echoed auth tokens). Set `NEUROLINK_DEBUG_HTTP=1` to opt
|
|
14
|
+
* into body logging — and even then bodies are run through `sanitizeForLog`
|
|
15
|
+
* to redact `Bearer …`, `sk-…`, `Token …`, and the other 11 token formats
|
|
16
|
+
* covered by `logSanitize.SECRET_PATTERN`.
|
|
17
|
+
*
|
|
18
|
+
* Previously this same function was hand-rolled in 11 provider files
|
|
19
|
+
* (cohere, xai, groq, togetherAi, fireworks, perplexity, cloudflare,
|
|
20
|
+
* llamaCpp, lmStudio, nvidiaNim, deepseek) with subtly different bodies.
|
|
21
|
+
* Extracting it kills the drift risk and gives a single place to harden.
|
|
22
|
+
*
|
|
23
|
+
* @module utils/loggingFetch
|
|
24
|
+
*/
|
|
25
|
+
/**
|
|
26
|
+
* Construct a fetch-compatible function that logs upstream non-OK responses
|
|
27
|
+
* under the given provider label.
|
|
28
|
+
*/
|
|
29
|
+
export declare function createLoggingFetch(provider: string): typeof fetch;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared logging-fetch wrapper.
|
|
3
|
+
*
|
|
4
|
+
* Wraps `createProxyFetch()` and logs every non-2xx upstream response with:
|
|
5
|
+
* - provider label
|
|
6
|
+
* - HTTP status code
|
|
7
|
+
* - URL with embedded credentials / signed query params masked
|
|
8
|
+
* (via `maskProxyUrl`)
|
|
9
|
+
* - request body size (string-body only — multipart/streamed bodies
|
|
10
|
+
* report 0)
|
|
11
|
+
*
|
|
12
|
+
* Response bodies are NOT logged by default (they can echo prompt fragments,
|
|
13
|
+
* tool payloads, or echoed auth tokens). Set `NEUROLINK_DEBUG_HTTP=1` to opt
|
|
14
|
+
* into body logging — and even then bodies are run through `sanitizeForLog`
|
|
15
|
+
* to redact `Bearer …`, `sk-…`, `Token …`, and the other 11 token formats
|
|
16
|
+
* covered by `logSanitize.SECRET_PATTERN`.
|
|
17
|
+
*
|
|
18
|
+
* Previously this same function was hand-rolled in 11 provider files
|
|
19
|
+
* (cohere, xai, groq, togetherAi, fireworks, perplexity, cloudflare,
|
|
20
|
+
* llamaCpp, lmStudio, nvidiaNim, deepseek) with subtly different bodies.
|
|
21
|
+
* Extracting it kills the drift risk and gives a single place to harden.
|
|
22
|
+
*
|
|
23
|
+
* @module utils/loggingFetch
|
|
24
|
+
*/
|
|
25
|
+
import { createProxyFetch, maskProxyUrl } from "../proxy/proxyFetch.js";
|
|
26
|
+
import { logger } from "./logger.js";
|
|
27
|
+
import { sanitizeForLog } from "./logSanitize.js";
|
|
28
|
+
/**
|
|
29
|
+
* Construct a fetch-compatible function that logs upstream non-OK responses
|
|
30
|
+
* under the given provider label.
|
|
31
|
+
*/
|
|
32
|
+
export function createLoggingFetch(provider) {
|
|
33
|
+
const base = createProxyFetch();
|
|
34
|
+
return (async (input, init) => {
|
|
35
|
+
const url = typeof input === "string"
|
|
36
|
+
? input
|
|
37
|
+
: input instanceof URL
|
|
38
|
+
? input.toString()
|
|
39
|
+
: input.url;
|
|
40
|
+
const reqSize = init?.body && typeof init.body === "string" ? init.body.length : 0;
|
|
41
|
+
const response = await base(input, init);
|
|
42
|
+
if (!response.ok) {
|
|
43
|
+
const safeUrl = maskProxyUrl(url) ?? "<redacted>";
|
|
44
|
+
if (process.env.NEUROLINK_DEBUG_HTTP === "1") {
|
|
45
|
+
const clone = response.clone();
|
|
46
|
+
const raw = await clone.text().catch(() => "<unreadable>");
|
|
47
|
+
logger.warn(`[${provider}] upstream ${response.status}`, {
|
|
48
|
+
url: safeUrl,
|
|
49
|
+
body: sanitizeForLog(raw),
|
|
50
|
+
reqSize,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
else {
|
|
54
|
+
logger.warn(`[${provider}] upstream ${response.status} url=${safeUrl} reqSize=${reqSize}`);
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
return response;
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
//# sourceMappingURL=loggingFetch.js.map
|
|
@@ -602,6 +602,7 @@ export async function buildMessagesArray(options) {
|
|
|
602
602
|
* Mutates options.input.files and options.input.text as needed.
|
|
603
603
|
*/
|
|
604
604
|
function enforceFileBudget(options, provider, model) {
|
|
605
|
+
options.input ??= {};
|
|
605
606
|
if (!options.input.files || options.input.files.length === 0) {
|
|
606
607
|
return;
|
|
607
608
|
}
|
|
@@ -659,6 +660,7 @@ function enforceFileBudget(options, provider, model) {
|
|
|
659
660
|
* Handles CSV, SVG, image, PDF, video, audio, archive, xlsx, docx, pptx, text, and unknown types.
|
|
660
661
|
*/
|
|
661
662
|
function appendDetectedFileResult(result, file, options) {
|
|
663
|
+
options.input ??= {};
|
|
662
664
|
const filename = extractFilename(file);
|
|
663
665
|
if (result.type === "csv") {
|
|
664
666
|
const filePath = typeof file === "string" ? file : filename;
|
|
@@ -786,6 +788,7 @@ function appendDetectedFileResult(result, file, options) {
|
|
|
786
788
|
* would silently never reach the model on those paths.
|
|
787
789
|
*/
|
|
788
790
|
export async function processUnifiedFilesArray(options, maxSize, provider) {
|
|
791
|
+
options.input ??= {};
|
|
789
792
|
if (!options.input.files || options.input.files.length === 0) {
|
|
790
793
|
return;
|
|
791
794
|
}
|
|
@@ -800,7 +803,12 @@ export async function processUnifiedFilesArray(options, maxSize, provider) {
|
|
|
800
803
|
},
|
|
801
804
|
}, async (span) => {
|
|
802
805
|
logger.info(`[NEUROLINK] Processing ${totalFiles} file(s) with auto-detection`);
|
|
803
|
-
options.input
|
|
806
|
+
// `options.input` was guaranteed non-null by the `??= {}` guard at the
|
|
807
|
+
// top of processUnifiedFilesArray; re-assert here so TypeScript is happy
|
|
808
|
+
// inside this withSpan closure (it doesn't track mutations across closures).
|
|
809
|
+
options.input ??= {};
|
|
810
|
+
const inp2 = options.input;
|
|
811
|
+
inp2.text = inp2.text || "";
|
|
804
812
|
let includedCount = 0;
|
|
805
813
|
const fileRegistry = options.fileRegistry;
|
|
806
814
|
for (let fileIdx = 0; fileIdx < files.length; fileIdx++) {
|
|
@@ -862,16 +870,13 @@ export async function processUnifiedFilesArray(options, maxSize, provider) {
|
|
|
862
870
|
if (fileRegistry && fileRegistry.size > 0) {
|
|
863
871
|
const previewText = await fileRegistry.generatePromptPreview();
|
|
864
872
|
if (previewText) {
|
|
865
|
-
|
|
873
|
+
inp2.text = (inp2.text || "") + previewText;
|
|
866
874
|
logger.info(`[FileDetector] Injected previews for ${fileRegistry.size} lazily-registered file(s)`);
|
|
867
875
|
}
|
|
868
876
|
const registeredFiles = fileRegistry.list();
|
|
869
877
|
for (const ref of registeredFiles) {
|
|
870
878
|
if (ref.extractedImages && ref.extractedImages.length > 0) {
|
|
871
|
-
|
|
872
|
-
...(options.input.images || []),
|
|
873
|
-
...ref.extractedImages,
|
|
874
|
-
];
|
|
879
|
+
inp2.images = [...(inp2.images || []), ...ref.extractedImages];
|
|
875
880
|
logger.info(`[FileDetector] Injected ${ref.extractedImages.length} extracted images from "${ref.filename}"`);
|
|
876
881
|
}
|
|
877
882
|
}
|
|
@@ -901,6 +906,7 @@ export async function processUnifiedFilesArray(options, maxSize, provider) {
|
|
|
901
906
|
* Process explicit CSV files array and append to options.input.text.
|
|
902
907
|
*/
|
|
903
908
|
async function processExplicitCsvFiles(options) {
|
|
909
|
+
options.input ??= {};
|
|
904
910
|
if (!options.input.csvFiles || options.input.csvFiles.length === 0) {
|
|
905
911
|
return;
|
|
906
912
|
}
|
|
@@ -942,6 +948,7 @@ async function processExplicitCsvFiles(options) {
|
|
|
942
948
|
* Enforce post-processing budget on accumulated text content and log token usage.
|
|
943
949
|
*/
|
|
944
950
|
function enforcePostProcessingBudget(options, provider, model) {
|
|
951
|
+
options.input ??= {};
|
|
945
952
|
if (!options.input.text) {
|
|
946
953
|
return;
|
|
947
954
|
}
|
|
@@ -980,6 +987,7 @@ function enforcePostProcessingBudget(options, provider, model) {
|
|
|
980
987
|
* Process explicit PDF files and return structured PDF entries for multimodal processing.
|
|
981
988
|
*/
|
|
982
989
|
async function processExplicitPdfFiles(options, maxSize, provider) {
|
|
990
|
+
options.input ??= {};
|
|
983
991
|
const pdfFiles = [];
|
|
984
992
|
if (!options.input.pdfFiles || options.input.pdfFiles.length === 0) {
|
|
985
993
|
return pdfFiles;
|
|
@@ -1015,6 +1023,7 @@ async function processExplicitPdfFiles(options, maxSize, provider) {
|
|
|
1015
1023
|
* conversation instructions, structured output instructions, and file handling guidance.
|
|
1016
1024
|
*/
|
|
1017
1025
|
function buildMultimodalSystemPrompt(options, hasPDFFiles) {
|
|
1026
|
+
options.input ??= {};
|
|
1018
1027
|
let systemPrompt = options.systemPrompt?.trim() || "";
|
|
1019
1028
|
const hasConversationHistory = options.conversationHistory && options.conversationHistory.length > 0;
|
|
1020
1029
|
if (hasConversationHistory) {
|
|
@@ -1023,9 +1032,10 @@ function buildMultimodalSystemPrompt(options, hasPDFFiles) {
|
|
|
1023
1032
|
if (shouldUseStructuredOutput(options)) {
|
|
1024
1033
|
systemPrompt = `${systemPrompt.trim()}${STRUCTURED_OUTPUT_INSTRUCTIONS}`;
|
|
1025
1034
|
}
|
|
1026
|
-
const
|
|
1027
|
-
|
|
1028
|
-
|
|
1035
|
+
const inp = options.input;
|
|
1036
|
+
const hasCSVFiles = (inp.csvFiles && inp.csvFiles.length > 0) ||
|
|
1037
|
+
(inp.files &&
|
|
1038
|
+
inp.files.some((f) => typeof f === "string" ? f.toLowerCase().endsWith(".csv") : false));
|
|
1029
1039
|
if (hasCSVFiles || hasPDFFiles) {
|
|
1030
1040
|
const fileTypes = [];
|
|
1031
1041
|
if (hasPDFFiles) {
|
|
@@ -1049,6 +1059,16 @@ function buildMultimodalSystemPrompt(options, hasPDFFiles) {
|
|
|
1049
1059
|
* Detects when images are present and routes through provider adapter
|
|
1050
1060
|
*/
|
|
1051
1061
|
export async function buildMultimodalMessagesArray(options, provider, model) {
|
|
1062
|
+
// Media-only callers (avatar / music / video) may omit `input` entirely.
|
|
1063
|
+
// Normalise to an empty object so all sub-functions can access input.*
|
|
1064
|
+
// without defensive null checks on every field access.
|
|
1065
|
+
if (!options.input) {
|
|
1066
|
+
options.input = {};
|
|
1067
|
+
}
|
|
1068
|
+
// After normalisation `input` is guaranteed non-undefined. Capture it in a
|
|
1069
|
+
// local const so TypeScript sees the definite (non-optional) type in the
|
|
1070
|
+
// rest of this function, avoiding 60+ "possibly undefined" errors.
|
|
1071
|
+
const inp = options.input;
|
|
1052
1072
|
// Compute provider-specific max PDF size once for consistent validation
|
|
1053
1073
|
const pdfConfig = PDFProcessor.getProviderConfig(provider);
|
|
1054
1074
|
const maxSize = pdfConfig
|
|
@@ -1065,20 +1085,19 @@ export async function buildMultimodalMessagesArray(options, provider, model) {
|
|
|
1065
1085
|
// Process explicit PDF files
|
|
1066
1086
|
const pdfFiles = await processExplicitPdfFiles(options, maxSize, provider);
|
|
1067
1087
|
// Check if this is a multimodal request
|
|
1068
|
-
const hasImages = (
|
|
1069
|
-
(
|
|
1070
|
-
options.input.content.some((c) => c.type === "image"));
|
|
1088
|
+
const hasImages = (inp.images && inp.images.length > 0) ||
|
|
1089
|
+
(inp.content && inp.content.some((c) => c.type === "image"));
|
|
1071
1090
|
const hasPDFs = pdfFiles.length > 0;
|
|
1072
1091
|
// If no images or PDFs, use standard message building and convert to MultimodalChatMessage[]
|
|
1073
1092
|
if (!hasImages && !hasPDFs) {
|
|
1074
|
-
if (
|
|
1075
|
-
|
|
1093
|
+
if (inp.csvFiles) {
|
|
1094
|
+
inp.csvFiles = [];
|
|
1076
1095
|
}
|
|
1077
|
-
if (
|
|
1078
|
-
|
|
1096
|
+
if (inp.pdfFiles) {
|
|
1097
|
+
inp.pdfFiles = [];
|
|
1079
1098
|
}
|
|
1080
|
-
if (
|
|
1081
|
-
|
|
1099
|
+
if (inp.files) {
|
|
1100
|
+
inp.files = [];
|
|
1082
1101
|
}
|
|
1083
1102
|
const standardMessages = await buildMessagesArray(options);
|
|
1084
1103
|
return standardMessages.map((msg) => {
|
|
@@ -1163,15 +1182,14 @@ export async function buildMultimodalMessagesArray(options, provider, model) {
|
|
|
1163
1182
|
// Handle multimodal content
|
|
1164
1183
|
try {
|
|
1165
1184
|
let userContent;
|
|
1166
|
-
if (
|
|
1167
|
-
userContent = await convertContentToProviderFormat(
|
|
1185
|
+
if (inp.content && inp.content.length > 0) {
|
|
1186
|
+
userContent = await convertContentToProviderFormat(inp.content, provider, model);
|
|
1168
1187
|
}
|
|
1169
|
-
else if ((
|
|
1170
|
-
|
|
1171
|
-
userContent = await convertMultimodalToProviderFormat(options.input.text, options.input.images || [], pdfFiles, provider, model);
|
|
1188
|
+
else if ((inp.images && inp.images.length > 0) || pdfFiles.length > 0) {
|
|
1189
|
+
userContent = await convertMultimodalToProviderFormat(inp.text ?? "", inp.images || [], pdfFiles, provider, model);
|
|
1172
1190
|
}
|
|
1173
1191
|
else {
|
|
1174
|
-
userContent =
|
|
1192
|
+
userContent = inp.text;
|
|
1175
1193
|
}
|
|
1176
1194
|
if (typeof userContent === "string") {
|
|
1177
1195
|
messages.push({
|
|
@@ -1195,7 +1213,7 @@ export async function buildMultimodalMessagesArray(options, provider, model) {
|
|
|
1195
1213
|
provider,
|
|
1196
1214
|
model,
|
|
1197
1215
|
hasImages,
|
|
1198
|
-
imageCount:
|
|
1216
|
+
imageCount: inp.images?.length || 0,
|
|
1199
1217
|
});
|
|
1200
1218
|
throw error;
|
|
1201
1219
|
}
|