@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
|
@@ -22,10 +22,38 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
22
22
|
bedrockClient;
|
|
23
23
|
conversationHistory = [];
|
|
24
24
|
region;
|
|
25
|
+
/**
|
|
26
|
+
* Parse the region segment from a Bedrock ARN.
|
|
27
|
+
* Returns null when the input is not an ARN.
|
|
28
|
+
*
|
|
29
|
+
* Supports all AWS partitions:
|
|
30
|
+
* - `arn:aws:bedrock:…` (commercial)
|
|
31
|
+
* - `arn:aws-cn:bedrock:…` (China)
|
|
32
|
+
* - `arn:aws-us-gov:bedrock:…` (GovCloud)
|
|
33
|
+
*/
|
|
34
|
+
static extractRegionFromArn(modelId) {
|
|
35
|
+
if (!modelId) {
|
|
36
|
+
return null;
|
|
37
|
+
}
|
|
38
|
+
const match = modelId.match(/^arn:aws[a-z0-9-]*:bedrock:([^:]+):/);
|
|
39
|
+
return match?.[1] ?? null;
|
|
40
|
+
}
|
|
25
41
|
constructor(modelName, neurolink, region, credentials) {
|
|
26
42
|
super(modelName, "bedrock", neurolink);
|
|
43
|
+
// When the model is given as a Bedrock ARN (e.g. an inference profile
|
|
44
|
+
// like `arn:aws:bedrock:us-east-1:123:inference-profile/foo`), Bedrock
|
|
45
|
+
// requires the runtime client's region to match the region embedded
|
|
46
|
+
// in the ARN — otherwise it returns "The provided model identifier is
|
|
47
|
+
// invalid." Auto-extract so users don't have to keep AWS_REGION in
|
|
48
|
+
// sync with their model ARN.
|
|
49
|
+
const resolvedModel = modelName || process.env.BEDROCK_MODEL || this.modelName;
|
|
50
|
+
const arnRegion = AmazonBedrockProvider.extractRegionFromArn(resolvedModel);
|
|
27
51
|
this.region =
|
|
28
|
-
credentials?.region ||
|
|
52
|
+
credentials?.region ||
|
|
53
|
+
region ||
|
|
54
|
+
arnRegion ||
|
|
55
|
+
process.env.AWS_REGION ||
|
|
56
|
+
"us-east-1";
|
|
29
57
|
logger.debug("[AmazonBedrockProvider] Starting constructor with extensive logging for debugging");
|
|
30
58
|
// Log environment variables for debugging
|
|
31
59
|
logger.debug(`[AmazonBedrockProvider] Environment check: AWS_REGION=${process.env.AWS_REGION || "undefined"}, AWS_ACCESS_KEY_ID=${process.env.AWS_ACCESS_KEY_ID ? "SET" : "undefined"}, AWS_SECRET_ACCESS_KEY=${process.env.AWS_SECRET_ACCESS_KEY ? "SET" : "undefined"}`);
|
|
@@ -274,7 +302,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
274
302
|
"gen_ai.operation.name": "chat",
|
|
275
303
|
},
|
|
276
304
|
}, async (generateSpan) => {
|
|
277
|
-
logger.info(
|
|
305
|
+
logger.info(`[AmazonBedrockProvider] Starting Bedrock API call at ${new Date().toISOString()}`);
|
|
278
306
|
try {
|
|
279
307
|
// Pre-call validation and logging
|
|
280
308
|
let region = "unknown";
|
|
@@ -287,9 +315,9 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
287
315
|
catch {
|
|
288
316
|
// Region lookup failed — not critical, only used for logging
|
|
289
317
|
}
|
|
290
|
-
logger.info(
|
|
291
|
-
logger.info(
|
|
292
|
-
logger.info(
|
|
318
|
+
logger.info(`[AmazonBedrockProvider] Client region: ${region}`);
|
|
319
|
+
logger.info(`[AmazonBedrockProvider] Model: ${this.modelName || this.getDefaultModel()}`);
|
|
320
|
+
logger.info(`[AmazonBedrockProvider] Conversation history length: ${this.conversationHistory.length}`);
|
|
293
321
|
// Get all available tools
|
|
294
322
|
const aiTools = await this.getAllTools();
|
|
295
323
|
const allTools = this.convertAISDKToolsToToolDefinitions(aiTools);
|
|
@@ -310,10 +338,10 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
310
338
|
};
|
|
311
339
|
if (toolConfig) {
|
|
312
340
|
commandInput.toolConfig = toolConfig;
|
|
313
|
-
logger.info(
|
|
341
|
+
logger.info(`[AmazonBedrockProvider] Tools configured: ${toolConfig.tools?.length || 0}`);
|
|
314
342
|
}
|
|
315
343
|
// Log command details for debugging
|
|
316
|
-
logger.info(
|
|
344
|
+
logger.info(`[AmazonBedrockProvider] Command input summary:`);
|
|
317
345
|
logger.info(` - Model ID: ${commandInput.modelId}`);
|
|
318
346
|
logger.info(` - Messages count: ${commandInput.messages?.length || 0}`);
|
|
319
347
|
logger.info(` - System prompts: ${commandInput.system?.length || 0}`);
|
|
@@ -821,8 +849,8 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
821
849
|
return this.bedrockClient;
|
|
822
850
|
}
|
|
823
851
|
async executeStream(options) {
|
|
824
|
-
logger.debug("
|
|
825
|
-
logger.info("
|
|
852
|
+
logger.debug("[TRACE] executeStream ENTRY - starting streaming attempt");
|
|
853
|
+
logger.info("[AmazonBedrockProvider] Attempting real streaming with ConverseStreamCommand");
|
|
826
854
|
return bedrockTracer.startActiveSpan("bedrock.stream", {
|
|
827
855
|
kind: SpanKind.CLIENT,
|
|
828
856
|
attributes: {
|
|
@@ -832,7 +860,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
832
860
|
},
|
|
833
861
|
}, async (streamSpan) => {
|
|
834
862
|
try {
|
|
835
|
-
logger.debug("
|
|
863
|
+
logger.debug("[TRACE] executeStream TRY block - about to call streamingConversationLoop");
|
|
836
864
|
// Clear conversation history for new streaming session
|
|
837
865
|
this.conversationHistory = [];
|
|
838
866
|
// Check for multimodal input (images, PDFs, CSVs, files)
|
|
@@ -871,15 +899,15 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
871
899
|
}
|
|
872
900
|
logger.debug(`[AmazonBedrockProvider] Starting streaming conversation with ${this.conversationHistory.length} message(s)`);
|
|
873
901
|
// Call the actual streaming implementation that already exists
|
|
874
|
-
logger.debug("
|
|
902
|
+
logger.debug("[TRACE] executeStream - calling streamingConversationLoop NOW");
|
|
875
903
|
const result = await this.streamingConversationLoop(options, streamSpan);
|
|
876
|
-
logger.debug("
|
|
904
|
+
logger.debug("[TRACE] executeStream - streamingConversationLoop SUCCESS, returning result");
|
|
877
905
|
streamSpan.setStatus({ code: SpanStatusCode.OK });
|
|
878
906
|
streamSpan.end();
|
|
879
907
|
return result;
|
|
880
908
|
}
|
|
881
909
|
catch (error) {
|
|
882
|
-
logger.debug("
|
|
910
|
+
logger.debug("[TRACE] executeStream CATCH - error caught from streamingConversationLoop");
|
|
883
911
|
const errorObj = error;
|
|
884
912
|
// Check if error is related to streaming permissions
|
|
885
913
|
const isPermissionError = errorObj?.name ===
|
|
@@ -889,10 +917,10 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
889
917
|
errorObj?.message?.includes("bedrock:InvokeModelWithResponseStream") ||
|
|
890
918
|
errorObj?.message?.includes("streaming") ||
|
|
891
919
|
errorObj?.message?.includes("ConverseStream");
|
|
892
|
-
logger.debug("
|
|
893
|
-
logger.debug(
|
|
920
|
+
logger.debug("[TRACE] executeStream CATCH - checking if permission error");
|
|
921
|
+
logger.debug(`[TRACE] executeStream CATCH - isPermissionError=${isPermissionError}`);
|
|
894
922
|
if (isPermissionError) {
|
|
895
|
-
logger.debug("
|
|
923
|
+
logger.debug("[TRACE] executeStream CATCH - PERMISSION ERROR DETECTED, starting fallback");
|
|
896
924
|
logger.warn(`[AmazonBedrockProvider] Streaming permissions not available, falling back to generate method: ${errorObj.message}`);
|
|
897
925
|
streamSpan.addEvent("stream.fallback_to_generate", {
|
|
898
926
|
reason: errorObj.message,
|
|
@@ -917,16 +945,28 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
917
945
|
streamSpan.setAttribute("gen_ai.response.stop_reason", "fallback_end_turn");
|
|
918
946
|
streamSpan.setStatus({ code: SpanStatusCode.OK });
|
|
919
947
|
streamSpan.end();
|
|
920
|
-
// Convert generate result to streaming format
|
|
948
|
+
// Convert generate result to streaming format.
|
|
949
|
+
// Use whitespace-preserving split (matches BaseProvider's
|
|
950
|
+
// executeFakeStreaming) so newlines, tabs, indentation, code
|
|
951
|
+
// blocks, and markdown tables aren't collapsed to single spaces.
|
|
921
952
|
const stream = new ReadableStream({
|
|
922
953
|
start(controller) {
|
|
923
|
-
// Split the response into chunks for pseudo-streaming
|
|
924
954
|
const responseText = generateResult.content || "";
|
|
925
|
-
const
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
955
|
+
const tokens = responseText.split(/(\s+)/);
|
|
956
|
+
let buffer = "";
|
|
957
|
+
for (let i = 0; i < tokens.length; i++) {
|
|
958
|
+
buffer += tokens[i];
|
|
959
|
+
const shouldYield = i === tokens.length - 1 ||
|
|
960
|
+
buffer.length > 50 ||
|
|
961
|
+
/[.!?;,]\s*$/.test(buffer);
|
|
962
|
+
if (shouldYield && buffer.length > 0) {
|
|
963
|
+
controller.enqueue({ content: buffer });
|
|
964
|
+
buffer = "";
|
|
965
|
+
}
|
|
966
|
+
}
|
|
967
|
+
if (buffer.length > 0) {
|
|
968
|
+
controller.enqueue({ content: buffer });
|
|
969
|
+
}
|
|
930
970
|
controller.close();
|
|
931
971
|
},
|
|
932
972
|
});
|
|
@@ -970,7 +1010,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
970
1010
|
});
|
|
971
1011
|
}
|
|
972
1012
|
async streamingConversationLoop(options, streamSpan) {
|
|
973
|
-
logger.debug("
|
|
1013
|
+
logger.debug("[TRACE] streamingConversationLoop ENTRY");
|
|
974
1014
|
const startTime = Date.now();
|
|
975
1015
|
const maxIterations = options.maxSteps || DEFAULT_MAX_STEPS;
|
|
976
1016
|
let iteration = 0;
|
|
@@ -983,7 +1023,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
983
1023
|
// The REAL issue: ReadableStream errors don't bubble up to the caller
|
|
984
1024
|
// So we need to make the first streaming call synchronously to test permissions
|
|
985
1025
|
try {
|
|
986
|
-
logger.debug("
|
|
1026
|
+
logger.debug("[TRACE] streamingConversationLoop - testing first streaming call");
|
|
987
1027
|
const commandInput = await this.prepareStreamCommand(options);
|
|
988
1028
|
const command = new ConverseStreamCommand(commandInput);
|
|
989
1029
|
logger.debug("[Observability] Bedrock streaming API request", {
|
|
@@ -1005,7 +1045,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1005
1045
|
// Process the first response immediately to avoid waste
|
|
1006
1046
|
const stream = new ReadableStream({
|
|
1007
1047
|
start: async (controller) => {
|
|
1008
|
-
logger.debug("
|
|
1048
|
+
logger.debug("[TRACE] streamingConversationLoop - ReadableStream start() called");
|
|
1009
1049
|
try {
|
|
1010
1050
|
// Process the first response we already have, tracking all event types
|
|
1011
1051
|
let firstStopReason = "";
|
|
@@ -1114,6 +1154,10 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1114
1154
|
const shouldContinue = await this.handleStreamStopReason(firstStopReason, firstAssistantMessage, controller, options);
|
|
1115
1155
|
if (!shouldContinue) {
|
|
1116
1156
|
streamSpan.setAttribute("gen_ai.response.stop_reason", firstStopReason);
|
|
1157
|
+
// Close the controller so downstream `for await` exits;
|
|
1158
|
+
// see the close() comment near the bottom of this start()
|
|
1159
|
+
// function for the spec rationale.
|
|
1160
|
+
controller.close();
|
|
1117
1161
|
return;
|
|
1118
1162
|
}
|
|
1119
1163
|
}
|
|
@@ -1153,10 +1197,21 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1153
1197
|
if (iteration >= maxIterations) {
|
|
1154
1198
|
streamSpan.setAttribute("gen_ai.response.stop_reason", "max_iterations");
|
|
1155
1199
|
controller.error(new Error("Streaming conversation exceeded maximum iterations"));
|
|
1200
|
+
return;
|
|
1156
1201
|
}
|
|
1202
|
+
// CRITICAL: ReadableStream's start() returning does NOT auto-close
|
|
1203
|
+
// the controller per the WHATWG Streams spec. Without this, the
|
|
1204
|
+
// downstream `for await (const chunk of stream)` in
|
|
1205
|
+
// convertToAsyncIterable never sees `done: true` and the
|
|
1206
|
+
// consumer hangs forever — manifested as a 240s harness
|
|
1207
|
+
// PER_TEST_TIMEOUT_SKIP for `[bedrock] stream tokens`. The first-
|
|
1208
|
+
// iteration `return` path and the while-loop natural `break`
|
|
1209
|
+
// path both reach here, so closing once at the bottom covers
|
|
1210
|
+
// every non-error exit.
|
|
1211
|
+
controller.close();
|
|
1157
1212
|
}
|
|
1158
1213
|
catch (error) {
|
|
1159
|
-
logger.debug("
|
|
1214
|
+
logger.debug("[TRACE] streamingConversationLoop - CATCH block hit in ReadableStream");
|
|
1160
1215
|
controller.error(error);
|
|
1161
1216
|
}
|
|
1162
1217
|
},
|
|
@@ -1226,7 +1281,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1226
1281
|
};
|
|
1227
1282
|
}
|
|
1228
1283
|
catch (error) {
|
|
1229
|
-
logger.debug("
|
|
1284
|
+
logger.debug("[TRACE] streamingConversationLoop - first streaming call FAILED, throwing");
|
|
1230
1285
|
throw error; // This will be caught by executeStream
|
|
1231
1286
|
}
|
|
1232
1287
|
}
|
|
@@ -1426,7 +1481,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1426
1481
|
return false;
|
|
1427
1482
|
}
|
|
1428
1483
|
else if (stopReason === "tool_use") {
|
|
1429
|
-
logger.debug(
|
|
1484
|
+
logger.debug(`[AmazonBedrockProvider] Tool use detected in streaming - executing tools`);
|
|
1430
1485
|
await this.executeStreamTools(assistantMessage.content, options);
|
|
1431
1486
|
return true; // Continue conversation loop
|
|
1432
1487
|
}
|
|
@@ -1455,10 +1510,10 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1455
1510
|
toolUseCount++;
|
|
1456
1511
|
}
|
|
1457
1512
|
}
|
|
1458
|
-
logger.debug(
|
|
1513
|
+
logger.debug(`[AmazonBedrockProvider] Found ${toolUseCount} toolUse blocks in assistant message`);
|
|
1459
1514
|
for (const contentItem of messageContent) {
|
|
1460
1515
|
if (contentItem.toolUse) {
|
|
1461
|
-
logger.debug(
|
|
1516
|
+
logger.debug(`[AmazonBedrockProvider] Executing tool: ${contentItem.toolUse.name}`);
|
|
1462
1517
|
// Track tool call
|
|
1463
1518
|
toolCalls.push({
|
|
1464
1519
|
type: "tool-call",
|
|
@@ -1468,7 +1523,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1468
1523
|
});
|
|
1469
1524
|
try {
|
|
1470
1525
|
const toolResult = await this.executeSingleTool(contentItem.toolUse.name, contentItem.toolUse.input || {}, contentItem.toolUse.toolUseId);
|
|
1471
|
-
logger.debug(
|
|
1526
|
+
logger.debug(`[AmazonBedrockProvider] Tool execution successful: ${contentItem.toolUse.name}`);
|
|
1472
1527
|
// Track tool result for storage
|
|
1473
1528
|
toolResultsForStorage.push({
|
|
1474
1529
|
type: "tool-result",
|
|
@@ -1486,7 +1541,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1486
1541
|
});
|
|
1487
1542
|
}
|
|
1488
1543
|
catch (error) {
|
|
1489
|
-
logger.error(
|
|
1544
|
+
logger.error(`[AmazonBedrockProvider] Tool execution failed: ${contentItem.toolUse.name}`, error);
|
|
1490
1545
|
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
1491
1546
|
// Track failed tool result
|
|
1492
1547
|
toolResultsForStorage.push({
|
|
@@ -1509,10 +1564,10 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1509
1564
|
}
|
|
1510
1565
|
}
|
|
1511
1566
|
}
|
|
1512
|
-
logger.debug(
|
|
1567
|
+
logger.debug(`[AmazonBedrockProvider] Created ${toolResults.length} toolResult blocks for ${toolUseCount} toolUse blocks`);
|
|
1513
1568
|
// Validate 1:1 mapping before adding to conversation
|
|
1514
1569
|
if (toolResults.length !== toolUseCount) {
|
|
1515
|
-
logger.error(
|
|
1570
|
+
logger.error(`[AmazonBedrockProvider] Mismatch: ${toolResults.length} toolResults vs ${toolUseCount} toolUse blocks`);
|
|
1516
1571
|
throw new Error(`Tool mapping mismatch: ${toolResults.length} toolResults for ${toolUseCount} toolUse blocks`);
|
|
1517
1572
|
}
|
|
1518
1573
|
// Add tool results as user message - exact structure like Bedrock-MCP-Connector
|
|
@@ -1522,7 +1577,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1522
1577
|
content: toolResults,
|
|
1523
1578
|
};
|
|
1524
1579
|
this.conversationHistory.push(userMessageWithToolResults);
|
|
1525
|
-
logger.debug(
|
|
1580
|
+
logger.debug(`[AmazonBedrockProvider] Added ${toolResults.length} tool results to conversation (1:1 mapping validated)`);
|
|
1526
1581
|
// Emit tool:end for each completed tool result so Pipeline B
|
|
1527
1582
|
// captures telemetry for Bedrock-driven tool calls (gap S2).
|
|
1528
1583
|
emitToolEndFromStepFinish(this.neurolink?.getEventEmitter(), toolResultsForStorage.map((tr) => {
|
|
@@ -1558,14 +1613,14 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1558
1613
|
region: process.env.AWS_REGION || "us-east-1",
|
|
1559
1614
|
});
|
|
1560
1615
|
try {
|
|
1561
|
-
logger.debug("
|
|
1616
|
+
logger.debug("[AmazonBedrockProvider] Starting health check...");
|
|
1562
1617
|
const command = new ListFoundationModelsCommand({});
|
|
1563
1618
|
const response = await healthCheckClient.send(command, {
|
|
1564
1619
|
abortSignal: controller.signal,
|
|
1565
1620
|
});
|
|
1566
1621
|
const models = response.modelSummaries || [];
|
|
1567
1622
|
const activeModels = models.filter((model) => model.modelLifecycle?.status === "ACTIVE");
|
|
1568
|
-
logger.debug(
|
|
1623
|
+
logger.debug(`[AmazonBedrockProvider] Health check passed - Found ${activeModels.length} active models out of ${models.length} total models`);
|
|
1569
1624
|
if (activeModels.length === 0) {
|
|
1570
1625
|
throw new Error("No active foundation models available in the region");
|
|
1571
1626
|
}
|
|
@@ -1586,7 +1641,7 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1586
1641
|
if (errorObj.code === "ECONNREFUSED" || errorObj.code === "ENOTFOUND") {
|
|
1587
1642
|
throw new Error("Unable to connect to Bedrock service. Check your network connectivity and AWS region configuration", { cause: error });
|
|
1588
1643
|
}
|
|
1589
|
-
logger.error("
|
|
1644
|
+
logger.error("[AmazonBedrockProvider] Health check failed:", error);
|
|
1590
1645
|
throw new Error(`Bedrock health check failed: ${errorMessage || "Unknown error"}`, { cause: error });
|
|
1591
1646
|
}
|
|
1592
1647
|
finally {
|
|
@@ -323,12 +323,39 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
323
323
|
else {
|
|
324
324
|
// Traditional API key authentication
|
|
325
325
|
const apiKeyToUse = credentials?.apiKey ?? config?.apiKey ?? getAnthropicApiKey();
|
|
326
|
+
// The Vercel AI SDK builds `${baseURL}/messages` (no version prefix).
|
|
327
|
+
// Anthropic's REST API lives under `/v1/messages`, so a user-supplied
|
|
328
|
+
// bare host like `http://localhost:55669` 404s. Normalize: if the
|
|
329
|
+
// baseURL doesn't already end with `/vN`, append `/v1`.
|
|
330
|
+
//
|
|
331
|
+
// CAVEAT: this heuristic assumes the proxy exposes Anthropic-compatible
|
|
332
|
+
// endpoints rooted at `/vN/...`. Path-rooted proxies like
|
|
333
|
+
// `https://proxy.example.com/anthropic` will be silently rewritten to
|
|
334
|
+
// `…/anthropic/v1` and 404 if the proxy doesn't expose that path. To
|
|
335
|
+
// disable auto-append, set `ANTHROPIC_BASE_URL` explicitly ending in a
|
|
336
|
+
// version segment (e.g. `https://api.anthropic.com/v1`).
|
|
337
|
+
const normalizedBaseURL = (() => {
|
|
338
|
+
const raw = process.env.ANTHROPIC_BASE_URL;
|
|
339
|
+
if (!raw) {
|
|
340
|
+
return undefined;
|
|
341
|
+
}
|
|
342
|
+
const trimmed = raw.replace(/\/+$/, "");
|
|
343
|
+
if (/\/v\d+$/.test(trimmed)) {
|
|
344
|
+
return trimmed;
|
|
345
|
+
}
|
|
346
|
+
logger.warn("[AnthropicProvider] ANTHROPIC_BASE_URL does not end with /vN; " +
|
|
347
|
+
"appending /v1 so the Vercel AI SDK can build /messages correctly. " +
|
|
348
|
+
"To silence this warning, set ANTHROPIC_BASE_URL with an explicit " +
|
|
349
|
+
"version segment (e.g. https://api.anthropic.com/v1). " +
|
|
350
|
+
"If your proxy exposes Anthropic at a custom path that doesn't " +
|
|
351
|
+
"expose /v1/messages, the auto-append will produce a 404 — pass " +
|
|
352
|
+
"the full path including the version explicitly.", { baseURL: raw, rewrittenTo: `${trimmed}/v1` });
|
|
353
|
+
return `${trimmed}/v1`;
|
|
354
|
+
})();
|
|
326
355
|
anthropic = createAnthropic({
|
|
327
356
|
apiKey: apiKeyToUse,
|
|
328
357
|
headers,
|
|
329
|
-
...(
|
|
330
|
-
baseURL: process.env.ANTHROPIC_BASE_URL,
|
|
331
|
-
}),
|
|
358
|
+
...(normalizedBaseURL && { baseURL: normalizedBaseURL }),
|
|
332
359
|
fetch: createProxyFetch(),
|
|
333
360
|
});
|
|
334
361
|
logger.debug("Anthropic Provider initialized with API key", {
|
|
@@ -379,13 +406,23 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
379
406
|
const usingProxy = !!process.env.ANTHROPIC_BASE_URL;
|
|
380
407
|
if (this.enableBetaFeatures) {
|
|
381
408
|
if (usingProxy) {
|
|
382
|
-
|
|
409
|
+
// The 1M-context beta requires a plan upgrade on most accounts;
|
|
410
|
+
// surfacing it by default forces a "The long context beta is not
|
|
411
|
+
// yet available for this subscription." failure for everyone else.
|
|
412
|
+
// Gate behind ANTHROPIC_ENABLE_LONG_CONTEXT_BETA=1 so default-tier
|
|
413
|
+
// accounts (and CI) can use the proxy without the gated feature.
|
|
414
|
+
const longContextOptIn = process.env.ANTHROPIC_ENABLE_LONG_CONTEXT_BETA === "1" ||
|
|
415
|
+
process.env.ANTHROPIC_ENABLE_LONG_CONTEXT_BETA === "true";
|
|
416
|
+
const betas = [
|
|
383
417
|
...CLAUDE_CODE_OAUTH_BETAS,
|
|
384
418
|
"fine-grained-tool-streaming-2025-05-14",
|
|
385
|
-
"context-1m-2025-08-07",
|
|
386
419
|
"interleaved-thinking-2025-05-14",
|
|
387
420
|
"redact-thinking-2026-02-12",
|
|
388
|
-
]
|
|
421
|
+
];
|
|
422
|
+
if (longContextOptIn) {
|
|
423
|
+
betas.push("context-1m-2025-08-07");
|
|
424
|
+
}
|
|
425
|
+
headers["anthropic-beta"] = betas.join(",");
|
|
389
426
|
}
|
|
390
427
|
else {
|
|
391
428
|
headers["anthropic-beta"] = ANTHROPIC_BETA_HEADERS["anthropic-beta"];
|
|
@@ -414,8 +451,11 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
414
451
|
* ```
|
|
415
452
|
*/
|
|
416
453
|
validateModelAccess(model) {
|
|
417
|
-
// Proxy mode: bypass tier validation entirely — the proxy handles model
|
|
454
|
+
// Proxy mode: bypass tier validation entirely — the proxy handles model
|
|
455
|
+
// access. Log at debug level so users can tell why an unknown model name
|
|
456
|
+
// "validated" when their proxy may not actually expose it.
|
|
418
457
|
if (process.env.ANTHROPIC_BASE_URL) {
|
|
458
|
+
logger.debug("[validateModelAccess] Bypassing tier check (ANTHROPIC_BASE_URL set — proxy enforces access)", { model });
|
|
419
459
|
return true;
|
|
420
460
|
}
|
|
421
461
|
// API tier has access to all models
|
|
@@ -539,6 +579,14 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
539
579
|
const REFRESH_TIMEOUT_MS = 30_000;
|
|
540
580
|
const controller = new AbortController();
|
|
541
581
|
const timeoutId = setTimeout(() => controller.abort(), REFRESH_TIMEOUT_MS);
|
|
582
|
+
// User-Agent is set to CLAUDE_CLI_USER_AGENT so the refresh request
|
|
583
|
+
// matches what the official Claude CLI / CLIProxyAPI sends. Anthropic
|
|
584
|
+
// gates parts of the OAuth flow on this UA (the same `client_id` is
|
|
585
|
+
// rejected by `ANTHROPIC_TOKEN_URL` if the UA looks like a generic
|
|
586
|
+
// SDK), so this is required for OAuth refresh to succeed — not a
|
|
587
|
+
// cosmetic choice. If Anthropic ever publishes a separate UA for
|
|
588
|
+
// third-party OAuth clients, switch to that. See `auth/anthropicOAuth.ts`
|
|
589
|
+
// for the source of `CLAUDE_CLI_USER_AGENT` / `CLAUDE_CODE_CLIENT_ID`.
|
|
542
590
|
const response = await fetch(ANTHROPIC_TOKEN_URL, {
|
|
543
591
|
method: "POST",
|
|
544
592
|
headers: {
|
|
@@ -90,7 +90,7 @@ export class AnthropicProviderV2 extends BaseProvider {
|
|
|
90
90
|
try {
|
|
91
91
|
result = streamText({
|
|
92
92
|
model,
|
|
93
|
-
prompt: options.input.text,
|
|
93
|
+
prompt: options.input.text ?? "",
|
|
94
94
|
system: options.systemPrompt,
|
|
95
95
|
temperature: options.temperature,
|
|
96
96
|
maxOutputTokens: options.maxTokens, // No default limit - unlimited unless specified
|
|
@@ -5,6 +5,7 @@ import { BaseProvider } from "../core/baseProvider.js";
|
|
|
5
5
|
import { DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
6
6
|
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
|
7
7
|
import { emitToolEndFromStepFinish } from "../utils/toolEndEmitter.js";
|
|
8
|
+
import { AuthenticationError, NetworkError, ProviderError, } from "../types/index.js";
|
|
8
9
|
import { logger } from "../utils/logger.js";
|
|
9
10
|
import { createAzureAPIKeyConfig, createAzureEndpointConfig, validateApiKey, } from "../utils/providerConfig.js";
|
|
10
11
|
import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
@@ -19,12 +20,48 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
19
20
|
super(modelName, "azure", sdk);
|
|
20
21
|
this.apiKey = credentials?.apiKey || process.env.AZURE_OPENAI_API_KEY || "";
|
|
21
22
|
const endpoint = process.env.AZURE_OPENAI_ENDPOINT || "";
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
// Use URL parsing instead of string-replace so endpoints that already
|
|
24
|
+
// carry a path segment (e.g. "https://<host>/openai" — a valid Azure AI
|
|
25
|
+
// Foundry shape) don't end up duplicating it as "<host>/openai/openai".
|
|
26
|
+
// Tolerate missing scheme by prefixing https:// before parsing.
|
|
27
|
+
let endpointUrl;
|
|
28
|
+
if (endpoint) {
|
|
29
|
+
try {
|
|
30
|
+
endpointUrl = new URL(endpoint.includes("://") ? endpoint : `https://${endpoint}`);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
endpointUrl = undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
const endpointHost = endpointUrl?.hostname ?? "";
|
|
37
|
+
const endpointPath = endpointUrl?.pathname && endpointUrl.pathname !== "/"
|
|
38
|
+
? endpointUrl.pathname.replace(/\/+$/, "")
|
|
39
|
+
: "";
|
|
40
|
+
// Classic Azure OpenAI ("*.openai.azure.com") and Cognitive Services
|
|
41
|
+
// ("*.cognitiveservices.azure.com") endpoints encode the resource name as
|
|
42
|
+
// a subdomain that @ai-sdk/azure expects to receive verbatim. The newer
|
|
43
|
+
// Azure AI Foundry endpoint format ("*.services.ai.azure.com") does not
|
|
44
|
+
// round-trip through that subdomain rewrite, so passing the resource name
|
|
45
|
+
// would yield e.g. "<host>.services.ai.azure.com.openai.azure.com". For
|
|
46
|
+
// those hosts we hand the full URL back via baseURL instead.
|
|
47
|
+
const isClassicAzureHost = /\.(openai|cognitiveservices)\.azure\.com$/.test(endpointHost);
|
|
48
|
+
const envResourceName = isClassicAzureHost
|
|
49
|
+
? endpointHost
|
|
50
|
+
.replace(".openai.azure.com", "")
|
|
51
|
+
.replace(".cognitiveservices.azure.com", "")
|
|
52
|
+
: "";
|
|
27
53
|
this.resourceName = credentials?.resourceName || envResourceName;
|
|
54
|
+
// For Azure AI Foundry the SDK still routes to the OpenAI-compatible API
|
|
55
|
+
// (deployments/{deployment}/chat/completions); the `/openai` path suffix
|
|
56
|
+
// mirrors what the SDK derives in classic mode
|
|
57
|
+
// (`https://${resource}.openai.azure.com/openai`). Reuse the path the
|
|
58
|
+
// operator already supplied if it already terminates in `/openai` *or*
|
|
59
|
+
// a versioned form like `/openai/v1`; otherwise append `/openai`. Never
|
|
60
|
+
// duplicate.
|
|
61
|
+
const hasOpenAIPathSuffix = /\/openai(?:\/v\d+)?$/.test(endpointPath);
|
|
62
|
+
const baseURLForFoundry = !this.resourceName && endpointUrl
|
|
63
|
+
? `${endpointUrl.origin}${hasOpenAIPathSuffix ? endpointPath : `${endpointPath}/openai`}`
|
|
64
|
+
: undefined;
|
|
28
65
|
this.deployment =
|
|
29
66
|
credentials?.deploymentName ||
|
|
30
67
|
modelName ||
|
|
@@ -40,20 +77,32 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
40
77
|
if (!this.apiKey) {
|
|
41
78
|
validateApiKey(createAzureAPIKeyConfig());
|
|
42
79
|
}
|
|
43
|
-
if (!this.resourceName) {
|
|
80
|
+
if (!this.resourceName && !baseURLForFoundry) {
|
|
44
81
|
validateApiKey(createAzureEndpointConfig());
|
|
45
82
|
}
|
|
46
|
-
// Create the Azure provider instance with proxy support
|
|
83
|
+
// Create the Azure provider instance with proxy support.
|
|
84
|
+
// For classic *.openai.azure.com / *.cognitiveservices.azure.com hosts we
|
|
85
|
+
// pass `resourceName`, which @ai-sdk/azure rewrites into the canonical
|
|
86
|
+
// subdomain. For Azure AI Foundry hosts ("*.services.ai.azure.com") we
|
|
87
|
+
// pass the full URL via `baseURL` so no rewrite happens.
|
|
47
88
|
// useDeploymentBasedUrls is required because @ai-sdk/azure v3+ defaults to
|
|
48
89
|
// the /v1/ URL format, but most Azure deployments still require the legacy
|
|
49
90
|
// /deployments/{deployment}/ URL pattern.
|
|
50
|
-
this.azureProvider =
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
91
|
+
this.azureProvider = baseURLForFoundry
|
|
92
|
+
? createAzure({
|
|
93
|
+
baseURL: baseURLForFoundry,
|
|
94
|
+
apiKey: this.apiKey,
|
|
95
|
+
apiVersion: this.apiVersion,
|
|
96
|
+
useDeploymentBasedUrls: true,
|
|
97
|
+
fetch: createProxyFetch(),
|
|
98
|
+
})
|
|
99
|
+
: createAzure({
|
|
100
|
+
resourceName: this.resourceName,
|
|
101
|
+
apiKey: this.apiKey,
|
|
102
|
+
apiVersion: this.apiVersion,
|
|
103
|
+
useDeploymentBasedUrls: true,
|
|
104
|
+
fetch: createProxyFetch(),
|
|
105
|
+
});
|
|
57
106
|
logger.debug("Azure Vercel Provider initialized", {
|
|
58
107
|
deployment: this.deployment,
|
|
59
108
|
resourceName: this.resourceName,
|
|
@@ -77,18 +126,18 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
77
126
|
}
|
|
78
127
|
formatProviderError(error) {
|
|
79
128
|
if (error instanceof TimeoutError) {
|
|
80
|
-
return new
|
|
129
|
+
return new NetworkError(`Request timed out: ${error.message}`, "azure");
|
|
81
130
|
}
|
|
82
131
|
const errorObj = error;
|
|
83
132
|
if (errorObj?.message &&
|
|
84
133
|
typeof errorObj.message === "string" &&
|
|
85
134
|
errorObj.message.includes("401")) {
|
|
86
|
-
return new
|
|
135
|
+
return new AuthenticationError("Invalid Azure OpenAI API key or endpoint.", "azure");
|
|
87
136
|
}
|
|
88
137
|
const message = errorObj?.message && typeof errorObj.message === "string"
|
|
89
138
|
? errorObj.message
|
|
90
139
|
: "Unknown error";
|
|
91
|
-
return new
|
|
140
|
+
return new ProviderError(`Azure OpenAI error: ${message}`, "azure");
|
|
92
141
|
}
|
|
93
142
|
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
94
143
|
async executeStream(options, _analysisSchema) {
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { type LanguageModel } from "ai";
|
|
2
|
+
import type { AIProviderName } from "../constants/enums.js";
|
|
3
|
+
import { BaseProvider } from "../core/baseProvider.js";
|
|
4
|
+
import type { NeurolinkCredentials, StreamOptions, StreamResult, ValidationSchema } from "../types/index.js";
|
|
5
|
+
/**
|
|
6
|
+
* Cloudflare Workers AI Provider
|
|
7
|
+
*
|
|
8
|
+
* Edge-served open models (Llama / Mistral / Qwen / Gemma) at
|
|
9
|
+
* `https://api.cloudflare.com/client/v4/accounts/{accountId}/ai/v1`
|
|
10
|
+
* (OpenAI-compatible). Cheapest tier for high-volume usage.
|
|
11
|
+
*
|
|
12
|
+
* Required env: `CLOUDFLARE_API_KEY` + `CLOUDFLARE_ACCOUNT_ID`.
|
|
13
|
+
*
|
|
14
|
+
* @see https://developers.cloudflare.com/workers-ai/configuration/open-ai-compatibility/
|
|
15
|
+
*/
|
|
16
|
+
export declare class CloudflareProvider extends BaseProvider {
|
|
17
|
+
private model;
|
|
18
|
+
private apiKey;
|
|
19
|
+
private baseURL;
|
|
20
|
+
constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["cloudflare"]);
|
|
21
|
+
protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
|
|
22
|
+
private executeStreamInner;
|
|
23
|
+
protected getProviderName(): AIProviderName;
|
|
24
|
+
protected getDefaultModel(): string;
|
|
25
|
+
protected getAISDKModel(): LanguageModel;
|
|
26
|
+
protected formatProviderError(error: unknown): Error;
|
|
27
|
+
validateConfiguration(): Promise<boolean>;
|
|
28
|
+
getConfiguration(): {
|
|
29
|
+
provider: AIProviderName;
|
|
30
|
+
model: string;
|
|
31
|
+
defaultModel: string;
|
|
32
|
+
baseURL: string;
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
export default CloudflareProvider;
|