@juspay/neurolink 9.10.0 → 9.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/adapters/video/videoAnalyzer.d.ts +3 -3
- package/dist/adapters/video/videoAnalyzer.js +39 -25
- package/dist/agent/directTools.d.ts +3 -3
- package/dist/cli/commands/config.d.ts +9 -9
- package/dist/cli/loop/optionsSchema.d.ts +1 -1
- package/dist/constants/contextWindows.d.ts +6 -3
- package/dist/constants/contextWindows.js +30 -3
- package/dist/constants/index.d.ts +3 -3
- package/dist/constants/retry.d.ts +4 -4
- package/dist/constants/retry.js +1 -1
- package/dist/context/contextCompactor.d.ts +1 -1
- package/dist/context/contextCompactor.js +59 -1
- package/dist/context/summarizationEngine.d.ts +2 -2
- package/dist/context/summarizationEngine.js +44 -18
- package/dist/context/toolOutputLimits.d.ts +22 -13
- package/dist/context/toolOutputLimits.js +58 -64
- package/dist/core/baseProvider.d.ts +11 -2
- package/dist/core/baseProvider.js +30 -1
- package/dist/core/conversationMemoryManager.d.ts +13 -1
- package/dist/core/conversationMemoryManager.js +36 -5
- package/dist/core/modules/GenerationHandler.d.ts +6 -0
- package/dist/core/modules/GenerationHandler.js +192 -7
- package/dist/core/modules/MessageBuilder.js +42 -4
- package/dist/core/modules/TelemetryHandler.js +4 -1
- package/dist/core/redisConversationMemoryManager.d.ts +19 -3
- package/dist/core/redisConversationMemoryManager.js +253 -58
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/lib/adapters/video/videoAnalyzer.d.ts +3 -3
- package/dist/lib/adapters/video/videoAnalyzer.js +39 -25
- package/dist/lib/agent/directTools.d.ts +7 -7
- package/dist/lib/constants/contextWindows.d.ts +6 -3
- package/dist/lib/constants/contextWindows.js +30 -3
- package/dist/lib/constants/index.d.ts +3 -3
- package/dist/lib/constants/retry.d.ts +4 -4
- package/dist/lib/constants/retry.js +1 -1
- package/dist/lib/context/contextCompactor.d.ts +1 -1
- package/dist/lib/context/contextCompactor.js +59 -1
- package/dist/lib/context/summarizationEngine.d.ts +2 -2
- package/dist/lib/context/summarizationEngine.js +44 -18
- package/dist/lib/context/toolOutputLimits.d.ts +22 -13
- package/dist/lib/context/toolOutputLimits.js +58 -64
- package/dist/lib/core/baseProvider.d.ts +11 -2
- package/dist/lib/core/baseProvider.js +30 -1
- package/dist/lib/core/conversationMemoryManager.d.ts +13 -1
- package/dist/lib/core/conversationMemoryManager.js +36 -5
- package/dist/lib/core/modules/GenerationHandler.d.ts +6 -0
- package/dist/lib/core/modules/GenerationHandler.js +192 -7
- package/dist/lib/core/modules/MessageBuilder.js +42 -4
- package/dist/lib/core/modules/TelemetryHandler.js +4 -1
- package/dist/lib/core/redisConversationMemoryManager.d.ts +19 -3
- package/dist/lib/core/redisConversationMemoryManager.js +253 -58
- package/dist/lib/files/fileTools.d.ts +3 -3
- package/dist/lib/index.d.ts +2 -0
- package/dist/lib/index.js +3 -0
- package/dist/lib/mcp/externalServerManager.js +36 -1
- package/dist/lib/memory/memoryRetrievalTools.d.ts +166 -0
- package/dist/lib/memory/memoryRetrievalTools.js +145 -0
- package/dist/lib/neurolink.d.ts +35 -1
- package/dist/lib/neurolink.js +471 -16
- package/dist/lib/providers/amazonBedrock.d.ts +1 -1
- package/dist/lib/providers/amazonBedrock.js +78 -45
- package/dist/lib/providers/amazonSagemaker.d.ts +1 -1
- package/dist/lib/providers/amazonSagemaker.js +1 -1
- package/dist/lib/providers/anthropic.d.ts +1 -1
- package/dist/lib/providers/anthropic.js +7 -7
- package/dist/lib/providers/anthropicBaseProvider.d.ts +1 -1
- package/dist/lib/providers/anthropicBaseProvider.js +7 -6
- package/dist/lib/providers/azureOpenai.d.ts +1 -1
- package/dist/lib/providers/azureOpenai.js +1 -1
- package/dist/lib/providers/googleAiStudio.d.ts +1 -1
- package/dist/lib/providers/googleAiStudio.js +5 -5
- package/dist/lib/providers/googleVertex.d.ts +1 -1
- package/dist/lib/providers/googleVertex.js +74 -17
- package/dist/lib/providers/huggingFace.d.ts +1 -1
- package/dist/lib/providers/huggingFace.js +1 -1
- package/dist/lib/providers/litellm.d.ts +1 -1
- package/dist/lib/providers/litellm.js +18 -16
- package/dist/lib/providers/mistral.d.ts +1 -1
- package/dist/lib/providers/mistral.js +1 -1
- package/dist/lib/providers/ollama.d.ts +1 -1
- package/dist/lib/providers/ollama.js +8 -7
- package/dist/lib/providers/openAI.d.ts +1 -1
- package/dist/lib/providers/openAI.js +6 -6
- package/dist/lib/providers/openRouter.d.ts +1 -1
- package/dist/lib/providers/openRouter.js +6 -2
- package/dist/lib/providers/openaiCompatible.d.ts +1 -1
- package/dist/lib/providers/openaiCompatible.js +1 -1
- package/dist/lib/proxy/proxyFetch.js +291 -65
- package/dist/lib/server/utils/validation.d.ts +4 -4
- package/dist/lib/services/server/ai/observability/instrumentation.js +12 -3
- package/dist/lib/telemetry/telemetryService.d.ts +2 -1
- package/dist/lib/telemetry/telemetryService.js +8 -1
- package/dist/lib/types/contextTypes.d.ts +26 -2
- package/dist/lib/types/conversation.d.ts +72 -40
- package/dist/lib/types/conversationMemoryInterface.d.ts +5 -1
- package/dist/lib/types/generateTypes.d.ts +26 -0
- package/dist/lib/types/modelTypes.d.ts +2 -2
- package/dist/lib/types/multimodal.d.ts +2 -0
- package/dist/lib/types/observability.d.ts +10 -0
- package/dist/lib/types/sdkTypes.d.ts +1 -1
- package/dist/lib/utils/conversationMemory.d.ts +4 -3
- package/dist/lib/utils/conversationMemory.js +44 -6
- package/dist/lib/utils/errorHandling.d.ts +5 -0
- package/dist/lib/utils/errorHandling.js +7 -2
- package/dist/lib/utils/logger.d.ts +8 -0
- package/dist/lib/utils/logger.js +56 -1
- package/dist/lib/utils/messageBuilder.js +74 -4
- package/dist/lib/utils/redis.js +6 -1
- package/dist/lib/utils/tokenEstimation.d.ts +2 -2
- package/dist/lib/utils/tokenEstimation.js +16 -1
- package/dist/lib/utils/videoAnalysisProcessor.d.ts +2 -1
- package/dist/lib/utils/videoAnalysisProcessor.js +7 -2
- package/dist/lib/workflow/config.d.ts +110 -110
- package/dist/mcp/externalServerManager.js +36 -1
- package/dist/memory/memoryRetrievalTools.d.ts +166 -0
- package/dist/memory/memoryRetrievalTools.js +144 -0
- package/dist/neurolink.d.ts +35 -1
- package/dist/neurolink.js +471 -16
- package/dist/providers/amazonBedrock.d.ts +1 -1
- package/dist/providers/amazonBedrock.js +78 -45
- package/dist/providers/amazonSagemaker.d.ts +1 -1
- package/dist/providers/amazonSagemaker.js +1 -1
- package/dist/providers/anthropic.d.ts +1 -1
- package/dist/providers/anthropic.js +7 -7
- package/dist/providers/anthropicBaseProvider.d.ts +1 -1
- package/dist/providers/anthropicBaseProvider.js +7 -6
- package/dist/providers/azureOpenai.d.ts +1 -1
- package/dist/providers/azureOpenai.js +1 -1
- package/dist/providers/googleAiStudio.d.ts +1 -1
- package/dist/providers/googleAiStudio.js +5 -5
- package/dist/providers/googleVertex.d.ts +1 -1
- package/dist/providers/googleVertex.js +74 -17
- package/dist/providers/huggingFace.d.ts +1 -1
- package/dist/providers/huggingFace.js +1 -1
- package/dist/providers/litellm.d.ts +1 -1
- package/dist/providers/litellm.js +18 -16
- package/dist/providers/mistral.d.ts +1 -1
- package/dist/providers/mistral.js +1 -1
- package/dist/providers/ollama.d.ts +1 -1
- package/dist/providers/ollama.js +8 -7
- package/dist/providers/openAI.d.ts +1 -1
- package/dist/providers/openAI.js +6 -6
- package/dist/providers/openRouter.d.ts +1 -1
- package/dist/providers/openRouter.js +6 -2
- package/dist/providers/openaiCompatible.d.ts +1 -1
- package/dist/providers/openaiCompatible.js +1 -1
- package/dist/proxy/proxyFetch.js +291 -65
- package/dist/services/server/ai/observability/instrumentation.js +12 -3
- package/dist/telemetry/telemetryService.d.ts +2 -1
- package/dist/telemetry/telemetryService.js +8 -1
- package/dist/types/contextTypes.d.ts +26 -2
- package/dist/types/conversation.d.ts +72 -40
- package/dist/types/conversationMemoryInterface.d.ts +5 -1
- package/dist/types/generateTypes.d.ts +26 -0
- package/dist/types/modelTypes.d.ts +10 -10
- package/dist/types/multimodal.d.ts +2 -0
- package/dist/types/observability.d.ts +10 -0
- package/dist/types/sdkTypes.d.ts +1 -1
- package/dist/utils/conversationMemory.d.ts +4 -3
- package/dist/utils/conversationMemory.js +44 -6
- package/dist/utils/errorHandling.d.ts +5 -0
- package/dist/utils/errorHandling.js +7 -2
- package/dist/utils/logger.d.ts +8 -0
- package/dist/utils/logger.js +56 -1
- package/dist/utils/messageBuilder.js +74 -4
- package/dist/utils/redis.js +6 -1
- package/dist/utils/tokenEstimation.d.ts +2 -2
- package/dist/utils/tokenEstimation.js +16 -1
- package/dist/utils/videoAnalysisProcessor.d.ts +2 -1
- package/dist/utils/videoAnalysisProcessor.js +7 -2
- package/dist/workflow/config.d.ts +12 -12
- package/package.json +1 -1
|
@@ -44,7 +44,7 @@ export declare class AmazonBedrockProvider extends BaseProvider {
|
|
|
44
44
|
* Uses ListFoundationModels API to validate connectivity and permissions
|
|
45
45
|
*/
|
|
46
46
|
checkBedrockHealth(): Promise<void>;
|
|
47
|
-
|
|
47
|
+
formatProviderError(error: unknown): Error;
|
|
48
48
|
/**
|
|
49
49
|
* Generate embeddings for text using Amazon Bedrock embedding models
|
|
50
50
|
* Uses the native AWS SDK InvokeModel command for Titan embeddings
|
|
@@ -4,6 +4,7 @@ import path from "path";
|
|
|
4
4
|
import { createAnalytics } from "../core/analytics.js";
|
|
5
5
|
import { BaseProvider } from "../core/baseProvider.js";
|
|
6
6
|
import { DEFAULT_MAX_STEPS } from "../core/constants.js";
|
|
7
|
+
import { AuthenticationError, ProviderError } from "../types/errors.js";
|
|
7
8
|
import { isAbortError } from "../utils/errorHandling.js";
|
|
8
9
|
import { logger } from "../utils/logger.js";
|
|
9
10
|
import { buildMultimodalMessagesArray } from "../utils/messageBuilder.js";
|
|
@@ -224,57 +225,66 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
224
225
|
logger.debug(`[AmazonBedrockProvider] Calling Bedrock with ${this.conversationHistory.length} messages and ${toolConfig?.tools?.length || 0} tools`);
|
|
225
226
|
// Create command and attempt API call
|
|
226
227
|
const command = new ConverseCommand(commandInput);
|
|
227
|
-
logger.
|
|
228
|
+
logger.debug("[Observability] Bedrock API request", {
|
|
229
|
+
model: commandInput.modelId,
|
|
230
|
+
region: region,
|
|
231
|
+
messageCount: commandInput.messages?.length || 0,
|
|
232
|
+
toolCount: commandInput.toolConfig?.tools?.length || 0,
|
|
233
|
+
maxTokens: commandInput.inferenceConfig?.maxTokens,
|
|
234
|
+
});
|
|
228
235
|
const apiCallStartTime = Date.now();
|
|
229
236
|
const response = await this.bedrockClient.send(command);
|
|
230
237
|
const apiCallDuration = Date.now() - apiCallStartTime;
|
|
231
|
-
logger.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
238
|
+
logger.debug("[Observability] Bedrock API response", {
|
|
239
|
+
model: commandInput.modelId,
|
|
240
|
+
durationMs: apiCallDuration,
|
|
241
|
+
hasContent: !!response.output?.message?.content?.length,
|
|
242
|
+
stopReason: response.stopReason,
|
|
243
|
+
usage: response.usage
|
|
244
|
+
? {
|
|
245
|
+
inputTokens: response.usage.inputTokens,
|
|
246
|
+
outputTokens: response.usage.outputTokens,
|
|
247
|
+
totalTokens: (response.usage.inputTokens || 0) +
|
|
248
|
+
(response.usage.outputTokens || 0),
|
|
249
|
+
}
|
|
250
|
+
: undefined,
|
|
251
|
+
});
|
|
252
|
+
logger.info(`[AmazonBedrockProvider] Bedrock API call successful`);
|
|
253
|
+
logger.info(`[AmazonBedrockProvider] API call duration: ${apiCallDuration}ms`);
|
|
237
254
|
const totalDuration = Date.now() - startTime;
|
|
238
|
-
logger.info(
|
|
255
|
+
logger.info(`[AmazonBedrockProvider] Total callBedrock duration: ${totalDuration}ms`);
|
|
239
256
|
return response;
|
|
240
257
|
}
|
|
241
258
|
catch (error) {
|
|
242
259
|
const errorDuration = Date.now() - startTime;
|
|
243
|
-
|
|
244
|
-
|
|
260
|
+
// Extract AWS metadata for structured logging
|
|
261
|
+
const awsError = error && typeof error === "object"
|
|
262
|
+
? error
|
|
263
|
+
: null;
|
|
264
|
+
const metadata = awsError?.$metadata && typeof awsError.$metadata === "object"
|
|
265
|
+
? awsError.$metadata
|
|
266
|
+
: null;
|
|
267
|
+
logger.debug("[Observability] Bedrock API request failed", {
|
|
268
|
+
model: this.modelName || this.getDefaultModel(),
|
|
269
|
+
durationMs: errorDuration,
|
|
270
|
+
error: error instanceof Error ? error.message : String(error),
|
|
271
|
+
errorName: error instanceof Error ? error.name : undefined,
|
|
272
|
+
httpStatus: metadata?.httpStatusCode,
|
|
273
|
+
awsRequestId: metadata?.requestId,
|
|
274
|
+
awsErrorCode: awsError?.Code,
|
|
275
|
+
});
|
|
276
|
+
logger.error(`[AmazonBedrockProvider] Bedrock API call failed after ${errorDuration}ms`);
|
|
245
277
|
if (error instanceof Error) {
|
|
246
|
-
logger.error(`
|
|
247
|
-
logger.error(` - Error message: ${error.message}`);
|
|
248
|
-
logger.error(` - Error stack: ${error.stack}`);
|
|
278
|
+
logger.error(`[AmazonBedrockProvider] Error: ${error.name} - ${error.message}`);
|
|
249
279
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
logger.error(` - Request ID: ${metadata.requestId}`);
|
|
258
|
-
logger.error(` - Attempts: ${metadata.attempts}`);
|
|
259
|
-
logger.error(` - Total retry delay: ${metadata.totalRetryDelay}`);
|
|
260
|
-
}
|
|
261
|
-
if (awsError.Code) {
|
|
262
|
-
logger.error(` - AWS Error Code: ${awsError.Code}`);
|
|
263
|
-
}
|
|
264
|
-
if (awsError.Type) {
|
|
265
|
-
logger.error(` - AWS Error Type: ${awsError.Type}`);
|
|
266
|
-
}
|
|
267
|
-
if (awsError.Fault) {
|
|
268
|
-
logger.error(` - AWS Fault: ${awsError.Fault}`);
|
|
269
|
-
}
|
|
280
|
+
if (metadata) {
|
|
281
|
+
logger.error(`[AmazonBedrockProvider] AWS SDK metadata`, {
|
|
282
|
+
httpStatus: metadata.httpStatusCode,
|
|
283
|
+
requestId: metadata.requestId,
|
|
284
|
+
attempts: metadata.attempts,
|
|
285
|
+
totalRetryDelay: metadata.totalRetryDelay,
|
|
286
|
+
});
|
|
270
287
|
}
|
|
271
|
-
// Log environment details for debugging
|
|
272
|
-
logger.error(`🌍 [AmazonBedrockProvider] Environment diagnostics:`);
|
|
273
|
-
logger.error(` - AWS_REGION: ${process.env.AWS_REGION || "not set"}`);
|
|
274
|
-
logger.error(` - AWS_PROFILE: ${process.env.AWS_PROFILE || "not set"}`);
|
|
275
|
-
logger.error(` - AWS_ACCESS_KEY_ID: ${process.env.AWS_ACCESS_KEY_ID ? "set" : "not set"}`);
|
|
276
|
-
logger.error(` - AWS_SECRET_ACCESS_KEY: ${process.env.AWS_SECRET_ACCESS_KEY ? "set" : "not set"}`);
|
|
277
|
-
logger.error(` - AWS_SESSION_TOKEN: ${process.env.AWS_SESSION_TOKEN ? "set" : "not set"}`);
|
|
278
288
|
throw error;
|
|
279
289
|
}
|
|
280
290
|
}
|
|
@@ -733,6 +743,10 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
733
743
|
// Fallback to generate method and convert to streaming format
|
|
734
744
|
const generateResult = await this.generate({
|
|
735
745
|
prompt: options.input.text,
|
|
746
|
+
input: options.input,
|
|
747
|
+
maxTokens: options.maxTokens,
|
|
748
|
+
temperature: options.temperature,
|
|
749
|
+
systemPrompt: options.systemPrompt,
|
|
736
750
|
});
|
|
737
751
|
if (!generateResult) {
|
|
738
752
|
throw new Error("Generate method returned null result");
|
|
@@ -793,8 +807,18 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
793
807
|
logger.debug("🟦 [TRACE] streamingConversationLoop - testing first streaming call");
|
|
794
808
|
const commandInput = await this.prepareStreamCommand(options);
|
|
795
809
|
const command = new ConverseStreamCommand(commandInput);
|
|
810
|
+
logger.debug("[Observability] Bedrock streaming API request", {
|
|
811
|
+
model: commandInput.modelId,
|
|
812
|
+
messageCount: commandInput.messages?.length || 0,
|
|
813
|
+
toolCount: commandInput.toolConfig?.tools?.length || 0,
|
|
814
|
+
});
|
|
815
|
+
const streamStartTime = Date.now();
|
|
796
816
|
const response = await this.bedrockClient.send(command);
|
|
797
|
-
logger.debug("
|
|
817
|
+
logger.debug("[Observability] Bedrock streaming API connection established", {
|
|
818
|
+
model: commandInput.modelId,
|
|
819
|
+
durationMs: Date.now() - streamStartTime,
|
|
820
|
+
hasStream: !!response.stream,
|
|
821
|
+
});
|
|
798
822
|
// Process the first response immediately to avoid waste
|
|
799
823
|
const stream = new ReadableStream({
|
|
800
824
|
start: async (controller) => {
|
|
@@ -925,7 +949,16 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
925
949
|
}
|
|
926
950
|
async processStreamResponse(commandInput, controller) {
|
|
927
951
|
const command = new ConverseStreamCommand(commandInput);
|
|
952
|
+
logger.debug("[Observability] Bedrock streaming API request (continuation)", {
|
|
953
|
+
model: commandInput.modelId,
|
|
954
|
+
messageCount: commandInput.messages?.length || 0,
|
|
955
|
+
});
|
|
956
|
+
const iterationStartTime = Date.now();
|
|
928
957
|
const response = await this.bedrockClient.send(command);
|
|
958
|
+
logger.debug("[Observability] Bedrock streaming API connection established (continuation)", {
|
|
959
|
+
model: commandInput.modelId,
|
|
960
|
+
durationMs: Date.now() - iterationStartTime,
|
|
961
|
+
});
|
|
929
962
|
if (!response.stream) {
|
|
930
963
|
throw new Error("No stream returned from Bedrock");
|
|
931
964
|
}
|
|
@@ -1176,16 +1209,16 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1176
1209
|
}
|
|
1177
1210
|
}
|
|
1178
1211
|
}
|
|
1179
|
-
|
|
1212
|
+
formatProviderError(error) {
|
|
1180
1213
|
// Handle AWS SDK specific errors
|
|
1181
1214
|
const message = error instanceof Error ? error.message : String(error);
|
|
1182
1215
|
if (message.includes("AccessDeniedException")) {
|
|
1183
|
-
return new
|
|
1216
|
+
return new AuthenticationError("AWS Bedrock access denied. Check your credentials and permissions.", this.providerName);
|
|
1184
1217
|
}
|
|
1185
1218
|
if (message.includes("ValidationException")) {
|
|
1186
|
-
return new
|
|
1219
|
+
return new ProviderError(`Validation error: ${message}`, this.providerName);
|
|
1187
1220
|
}
|
|
1188
|
-
return new
|
|
1221
|
+
return new ProviderError(`AWS Bedrock error: ${message}`, this.providerName);
|
|
1189
1222
|
}
|
|
1190
1223
|
/**
|
|
1191
1224
|
* Generate embeddings for text using Amazon Bedrock embedding models
|
|
@@ -21,7 +21,7 @@ export declare class AmazonSageMakerProvider extends BaseProvider {
|
|
|
21
21
|
protected getDefaultModel(): string;
|
|
22
22
|
protected getAISDKModel(): LanguageModelV1;
|
|
23
23
|
protected executeStream(_options: StreamOptions, _analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
|
|
24
|
-
protected
|
|
24
|
+
protected formatProviderError(error: unknown): Error;
|
|
25
25
|
/**
|
|
26
26
|
* Get SageMaker-specific provider information
|
|
27
27
|
*/
|
|
@@ -16,7 +16,7 @@ export declare class AnthropicProvider extends BaseProvider {
|
|
|
16
16
|
* Returns the Vercel AI SDK model instance for Anthropic
|
|
17
17
|
*/
|
|
18
18
|
getAISDKModel(): LanguageModelV1;
|
|
19
|
-
|
|
19
|
+
protected formatProviderError(error: unknown): Error;
|
|
20
20
|
protected executeStream(options: StreamOptions, _analysisSchema?: ValidationSchema): Promise<StreamResult>;
|
|
21
21
|
isAvailable(): Promise<boolean>;
|
|
22
22
|
getModel(): LanguageModelV1;
|
|
@@ -49,9 +49,9 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
49
49
|
getAISDKModel() {
|
|
50
50
|
return this.model;
|
|
51
51
|
}
|
|
52
|
-
|
|
52
|
+
formatProviderError(error) {
|
|
53
53
|
if (error instanceof TimeoutError) {
|
|
54
|
-
|
|
54
|
+
return new NetworkError(`Request timed out after ${error.timeout}ms`, this.providerName);
|
|
55
55
|
}
|
|
56
56
|
const errorRecord = error;
|
|
57
57
|
const message = typeof errorRecord?.message === "string"
|
|
@@ -59,28 +59,28 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
59
59
|
: "Unknown error";
|
|
60
60
|
if (message.includes("API_KEY_INVALID") ||
|
|
61
61
|
message.includes("Invalid API key")) {
|
|
62
|
-
|
|
62
|
+
return new AuthenticationError("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.", this.providerName);
|
|
63
63
|
}
|
|
64
64
|
if (message.includes("rate limit") ||
|
|
65
65
|
message.includes("too_many_requests") ||
|
|
66
66
|
message.includes("429")) {
|
|
67
|
-
|
|
67
|
+
return new RateLimitError("Anthropic rate limit exceeded. Please try again later.", this.providerName);
|
|
68
68
|
}
|
|
69
69
|
if (message.includes("ECONNRESET") ||
|
|
70
70
|
message.includes("ENOTFOUND") ||
|
|
71
71
|
message.includes("ECONNREFUSED") ||
|
|
72
72
|
message.includes("network") ||
|
|
73
73
|
message.includes("connection")) {
|
|
74
|
-
|
|
74
|
+
return new NetworkError(`Connection error: ${message}`, this.providerName);
|
|
75
75
|
}
|
|
76
76
|
if (message.includes("500") ||
|
|
77
77
|
message.includes("502") ||
|
|
78
78
|
message.includes("503") ||
|
|
79
79
|
message.includes("504") ||
|
|
80
80
|
message.includes("server error")) {
|
|
81
|
-
|
|
81
|
+
return new ProviderError(`Server error: ${message}`, this.providerName);
|
|
82
82
|
}
|
|
83
|
-
|
|
83
|
+
return new ProviderError(`Anthropic error: ${message}`, this.providerName);
|
|
84
84
|
}
|
|
85
85
|
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
86
86
|
async executeStream(options, _analysisSchema) {
|
|
@@ -16,7 +16,7 @@ export declare class AnthropicProviderV2 extends BaseProvider {
|
|
|
16
16
|
* Returns the Vercel AI SDK model instance for Anthropic
|
|
17
17
|
*/
|
|
18
18
|
protected getAISDKModel(): LanguageModelV1;
|
|
19
|
-
protected
|
|
19
|
+
protected formatProviderError(error: unknown): Error;
|
|
20
20
|
private getApiKey;
|
|
21
21
|
protected executeStream(options: StreamOptions, _analysisSchema?: ZodType<unknown, ZodTypeDef, unknown> | Schema<unknown>): Promise<StreamResult>;
|
|
22
22
|
}
|
|
@@ -2,6 +2,7 @@ import { createAnthropic } from "@ai-sdk/anthropic";
|
|
|
2
2
|
import { streamText } from "ai";
|
|
3
3
|
import { AIProviderName, AnthropicModels } from "../constants/enums.js";
|
|
4
4
|
import { BaseProvider } from "../core/baseProvider.js";
|
|
5
|
+
import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../types/errors.js";
|
|
5
6
|
import { logger } from "../utils/logger.js";
|
|
6
7
|
import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
7
8
|
import { validateApiKey, createAnthropicBaseConfig, } from "../utils/providerConfig.js";
|
|
@@ -35,21 +36,21 @@ export class AnthropicProviderV2 extends BaseProvider {
|
|
|
35
36
|
const anthropic = createAnthropic({ apiKey });
|
|
36
37
|
return anthropic(this.modelName);
|
|
37
38
|
}
|
|
38
|
-
|
|
39
|
+
formatProviderError(error) {
|
|
39
40
|
if (error instanceof TimeoutError) {
|
|
40
|
-
return new
|
|
41
|
+
return new NetworkError(`Request timed out: ${error.message}`, this.providerName);
|
|
41
42
|
}
|
|
42
43
|
const errorWithStatus = error;
|
|
43
44
|
if (errorWithStatus?.status === 401) {
|
|
44
|
-
return new
|
|
45
|
+
return new AuthenticationError("Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.", this.providerName);
|
|
45
46
|
}
|
|
46
47
|
if (errorWithStatus?.status === 429) {
|
|
47
|
-
return new
|
|
48
|
+
return new RateLimitError("Anthropic rate limit exceeded. Please try again later.", this.providerName);
|
|
48
49
|
}
|
|
49
50
|
if (errorWithStatus?.status === 400) {
|
|
50
|
-
return new
|
|
51
|
+
return new ProviderError(`Bad request: ${errorWithStatus?.message || "Invalid request parameters"}`, this.providerName);
|
|
51
52
|
}
|
|
52
|
-
return new
|
|
53
|
+
return new ProviderError(`Anthropic error: ${errorWithStatus?.message || String(error) || "Unknown error"}`, this.providerName);
|
|
53
54
|
}
|
|
54
55
|
// Configuration helper - now using consolidated utility
|
|
55
56
|
getApiKey() {
|
|
@@ -15,7 +15,7 @@ export declare class AzureOpenAIProvider extends BaseProvider {
|
|
|
15
15
|
* Returns the Vercel AI SDK model instance for Azure OpenAI
|
|
16
16
|
*/
|
|
17
17
|
getAISDKModel(): LanguageModelV1;
|
|
18
|
-
|
|
18
|
+
protected formatProviderError(error: unknown): Error;
|
|
19
19
|
protected executeStream(options: StreamOptions, _analysisSchema?: unknown): Promise<StreamResult>;
|
|
20
20
|
}
|
|
21
21
|
export default AzureOpenAIProvider;
|
|
@@ -62,7 +62,7 @@ export class AzureOpenAIProvider extends BaseProvider {
|
|
|
62
62
|
getAISDKModel() {
|
|
63
63
|
return this.azureProvider(this.deployment);
|
|
64
64
|
}
|
|
65
|
-
|
|
65
|
+
formatProviderError(error) {
|
|
66
66
|
if (error instanceof TimeoutError) {
|
|
67
67
|
return new Error(`Azure OpenAI request timed out: ${error.message}`);
|
|
68
68
|
}
|
|
@@ -43,7 +43,7 @@ export declare class GoogleAIStudioProvider extends BaseProvider {
|
|
|
43
43
|
* 🔧 PHASE 2: Return AI SDK model instance for tool calling
|
|
44
44
|
*/
|
|
45
45
|
getAISDKModel(): LanguageModelV1;
|
|
46
|
-
|
|
46
|
+
protected formatProviderError(error: unknown): Error;
|
|
47
47
|
/**
|
|
48
48
|
* Overrides the BaseProvider's image generation method to implement it for Google AI.
|
|
49
49
|
* This method calls the Google AI API to generate an image from a prompt.
|
|
@@ -91,21 +91,21 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
91
91
|
const google = createGoogleGenerativeAI({ apiKey });
|
|
92
92
|
return google(this.modelName);
|
|
93
93
|
}
|
|
94
|
-
|
|
94
|
+
formatProviderError(error) {
|
|
95
95
|
if (error instanceof TimeoutError) {
|
|
96
|
-
|
|
96
|
+
return new NetworkError(error.message, this.providerName);
|
|
97
97
|
}
|
|
98
98
|
const errorRecord = error;
|
|
99
99
|
const message = typeof errorRecord?.message === "string"
|
|
100
100
|
? errorRecord.message
|
|
101
101
|
: "Unknown error";
|
|
102
102
|
if (message.includes("API_KEY_INVALID")) {
|
|
103
|
-
|
|
103
|
+
return new AuthenticationError("Invalid Google AI API key. Please check your GOOGLE_AI_API_KEY environment variable.", this.providerName);
|
|
104
104
|
}
|
|
105
105
|
if (message.includes("RATE_LIMIT_EXCEEDED")) {
|
|
106
|
-
|
|
106
|
+
return new RateLimitError("Google AI rate limit exceeded. Please try again later.", this.providerName);
|
|
107
107
|
}
|
|
108
|
-
|
|
108
|
+
return new ProviderError(`Google AI error: ${message}`, this.providerName);
|
|
109
109
|
}
|
|
110
110
|
/**
|
|
111
111
|
* Overrides the BaseProvider's image generation method to implement it for Google AI.
|
|
@@ -130,7 +130,7 @@ export declare class GoogleVertexProvider extends BaseProvider {
|
|
|
130
130
|
* Override generate to route Gemini 3 models with tools to native SDK
|
|
131
131
|
*/
|
|
132
132
|
generate(optionsOrPrompt: TextGenerationOptions | string): Promise<EnhancedGenerateResult | null>;
|
|
133
|
-
protected
|
|
133
|
+
protected formatProviderError(error: unknown): Error;
|
|
134
134
|
/**
|
|
135
135
|
* Memory-safe cache management for model configurations
|
|
136
136
|
* Implements LRU eviction to prevent memory leaks in long-running processes
|
|
@@ -10,7 +10,7 @@ import { BaseProvider } from "../core/baseProvider.js";
|
|
|
10
10
|
import { DEFAULT_MAX_STEPS, GLOBAL_LOCATION_MODELS, } from "../core/constants.js";
|
|
11
11
|
import { ModelConfigurationManager } from "../core/modelConfiguration.js";
|
|
12
12
|
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
|
13
|
-
import { AuthenticationError, ProviderError } from "../types/errors.js";
|
|
13
|
+
import { AuthenticationError, NetworkError, ProviderError, RateLimitError, InvalidModelError, } from "../types/errors.js";
|
|
14
14
|
import { ERROR_CODES, NeuroLinkError } from "../utils/errorHandling.js";
|
|
15
15
|
import { FileDetector } from "../utils/fileDetector.js";
|
|
16
16
|
import { logger } from "../utils/logger.js";
|
|
@@ -20,6 +20,16 @@ import { convertZodToJsonSchema, inlineJsonSchema, } from "../utils/schemaConver
|
|
|
20
20
|
import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../utils/timeout.js";
|
|
21
21
|
import { buildNativeToolDeclarations, buildNativeConfig, computeMaxSteps as computeMaxStepsShared, collectStreamChunks, extractTextFromParts, executeNativeToolCalls, handleMaxStepsTermination, pushModelResponseToHistory, } from "./googleNativeGemini3.js";
|
|
22
22
|
// Import proper types for multimodal message handling
|
|
23
|
+
// Keep-alive note: Node.js native fetch and undici (used by createProxyFetch)
|
|
24
|
+
// handle HTTP keep-alive internally. The fetchWithRetry wrapper in proxyFetch.ts
|
|
25
|
+
// provides retry protection for transient ECONNRESET/ETIMEDOUT errors.
|
|
26
|
+
//
|
|
27
|
+
// Auth isolation note: @ai-sdk/google-vertex resolves auth tokens (via
|
|
28
|
+
// generateAuthToken → google-auth-library) BEFORE applying the user AbortSignal
|
|
29
|
+
// to the main API call. Auth token refresh uses gaxios internally, not our
|
|
30
|
+
// custom fetch, so it is inherently isolated from user cancellation signals.
|
|
31
|
+
// The image generation path (getImageGenerationAccessToken) has an additional
|
|
32
|
+
// explicit 15s timeout per attempt for direct REST API calls.
|
|
23
33
|
// Enhanced Anthropic support with direct imports
|
|
24
34
|
// Using the dual provider architecture from Vercel AI SDK
|
|
25
35
|
const hasAnthropicSupport = () => {
|
|
@@ -1315,29 +1325,44 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
1315
1325
|
// Fall back to BaseProvider implementation
|
|
1316
1326
|
return super.generate(optionsOrPrompt);
|
|
1317
1327
|
}
|
|
1318
|
-
|
|
1328
|
+
formatProviderError(error) {
|
|
1329
|
+
// Pass through AbortError as-is so callers can detect cancellation
|
|
1319
1330
|
const errorRecord = error;
|
|
1331
|
+
if (typeof errorRecord?.name === "string" &&
|
|
1332
|
+
errorRecord.name === "AbortError") {
|
|
1333
|
+
return error;
|
|
1334
|
+
}
|
|
1320
1335
|
if (typeof errorRecord?.name === "string" &&
|
|
1321
1336
|
errorRecord.name === "TimeoutError") {
|
|
1322
|
-
return new
|
|
1337
|
+
return new NetworkError(`Google Vertex AI request timed out. Consider increasing timeout or using a lighter model.`, this.providerName);
|
|
1323
1338
|
}
|
|
1324
1339
|
const message = typeof errorRecord?.message === "string"
|
|
1325
1340
|
? errorRecord.message
|
|
1326
1341
|
: "Unknown error occurred";
|
|
1342
|
+
const code = typeof errorRecord?.code === "string" ? errorRecord.code : undefined;
|
|
1343
|
+
if (code === "ECONNRESET" ||
|
|
1344
|
+
code === "ENOTFOUND" ||
|
|
1345
|
+
code === "ECONNREFUSED" ||
|
|
1346
|
+
message.includes("ECONNRESET") ||
|
|
1347
|
+
message.includes("ENOTFOUND") ||
|
|
1348
|
+
message.includes("ECONNREFUSED") ||
|
|
1349
|
+
message.includes("connect ETIMEDOUT")) {
|
|
1350
|
+
return new NetworkError(`Google Vertex AI network error: ${message}`, this.providerName);
|
|
1351
|
+
}
|
|
1327
1352
|
if (message.includes("PERMISSION_DENIED")) {
|
|
1328
|
-
return new
|
|
1353
|
+
return new AuthenticationError(`❌ Google Vertex AI Permission Denied\n\nYour Google Cloud credentials don't have permission to access Vertex AI.\n\nRequired Steps:\n1. Ensure your service account has Vertex AI User role\n2. Check if Vertex AI API is enabled in your project\n3. Verify your project ID is correct\n4. Confirm your location/region has Vertex AI available`, this.providerName);
|
|
1329
1354
|
}
|
|
1330
1355
|
if (message.includes("NOT_FOUND")) {
|
|
1331
1356
|
const modelSuggestions = this.getModelSuggestions(this.modelName);
|
|
1332
|
-
return new
|
|
1357
|
+
return new InvalidModelError(`❌ Google Vertex AI Model Not Found\n\n${message}\n\nModel '${this.modelName}' is not available.\n\nSuggested alternatives:\n${modelSuggestions}\n\nTroubleshooting:\n1. Check model name spelling and format\n2. Verify model is available in your region (${this.location})\n3. Ensure your project has access to the model\n4. For Claude models, enable Anthropic integration in Google Cloud Console`, this.providerName);
|
|
1333
1358
|
}
|
|
1334
1359
|
if (message.includes("QUOTA_EXCEEDED")) {
|
|
1335
|
-
return new
|
|
1360
|
+
return new RateLimitError(`❌ Google Vertex AI Quota Exceeded\n\n${message}\n\nSolutions:\n1. Check your Vertex AI quotas in Google Cloud Console\n2. Request quota increase if needed\n3. Try a different model or reduce request frequency\n4. Consider using a different region`, this.providerName);
|
|
1336
1361
|
}
|
|
1337
1362
|
if (message.includes("INVALID_ARGUMENT")) {
|
|
1338
|
-
return new
|
|
1363
|
+
return new ProviderError(`❌ Google Vertex AI Invalid Request\n\n${message}\n\nCheck:\n1. Request parameters are within model limits\n2. Input text is properly formatted\n3. Temperature and other settings are valid\n4. Model supports your request type`, this.providerName);
|
|
1339
1364
|
}
|
|
1340
|
-
return new
|
|
1365
|
+
return new ProviderError(`❌ Google Vertex AI Provider Error\n\n${message}\n\nTroubleshooting:\n1. Check Google Cloud credentials and permissions\n2. Verify project ID and location settings\n3. Ensure Vertex AI API is enabled\n4. Check network connectivity`, this.providerName);
|
|
1341
1366
|
}
|
|
1342
1367
|
/**
|
|
1343
1368
|
* Memory-safe cache management for model configurations
|
|
@@ -2048,20 +2073,52 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
2048
2073
|
* Obtain a Google Auth access token for Vertex AI REST API calls.
|
|
2049
2074
|
*/
|
|
2050
2075
|
async getImageGenerationAccessToken() {
|
|
2076
|
+
const maxRetries = 3;
|
|
2077
|
+
const baseDelay = 500;
|
|
2078
|
+
const authTimeoutMs = 15000;
|
|
2051
2079
|
const { GoogleAuth } = await import("google-auth-library");
|
|
2052
2080
|
// Priority: GOOGLE_APPLICATION_CREDENTIALS_NEUROLINK > GOOGLE_APPLICATION_CREDENTIALS
|
|
2053
2081
|
const credentialsPath = process.env.GOOGLE_APPLICATION_CREDENTIALS_NEUROLINK ||
|
|
2054
2082
|
process.env.GOOGLE_APPLICATION_CREDENTIALS;
|
|
2055
|
-
|
|
2056
|
-
|
|
2057
|
-
|
|
2058
|
-
|
|
2059
|
-
|
|
2060
|
-
|
|
2061
|
-
|
|
2062
|
-
|
|
2083
|
+
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
|
2084
|
+
// Enforce per-attempt timeout with AbortController
|
|
2085
|
+
const controller = new AbortController();
|
|
2086
|
+
const authTimer = setTimeout(() => {
|
|
2087
|
+
controller.abort();
|
|
2088
|
+
logger.warn(`[GoogleVertexProvider] Auth token refresh exceeded ${authTimeoutMs}ms timeout (attempt ${attempt}/${maxRetries})`);
|
|
2089
|
+
}, authTimeoutMs);
|
|
2090
|
+
try {
|
|
2091
|
+
const auth = new GoogleAuth({
|
|
2092
|
+
...(credentialsPath && { keyFilename: credentialsPath }),
|
|
2093
|
+
scopes: ["https://www.googleapis.com/auth/cloud-platform"],
|
|
2094
|
+
});
|
|
2095
|
+
const client = await auth.getClient();
|
|
2096
|
+
const accessToken = await client.getAccessToken();
|
|
2097
|
+
if (!accessToken.token) {
|
|
2098
|
+
throw new AuthenticationError("Failed to obtain access token from Google Auth", this.providerName);
|
|
2099
|
+
}
|
|
2100
|
+
return accessToken.token;
|
|
2101
|
+
}
|
|
2102
|
+
catch (error) {
|
|
2103
|
+
const err = error;
|
|
2104
|
+
const isRetryable = controller.signal.aborted ||
|
|
2105
|
+
err?.code === "ECONNRESET" ||
|
|
2106
|
+
err?.code === "ETIMEDOUT" ||
|
|
2107
|
+
err?.code === "ENOTFOUND" ||
|
|
2108
|
+
err?.message?.includes("socket hang up") ||
|
|
2109
|
+
err?.message?.includes("network socket disconnected");
|
|
2110
|
+
if (!isRetryable || attempt === maxRetries) {
|
|
2111
|
+
throw error;
|
|
2112
|
+
}
|
|
2113
|
+
const delay = baseDelay * Math.pow(2, attempt - 1);
|
|
2114
|
+
logger.warn(`[GoogleVertexProvider] Auth token transient error (${err?.code || err?.message}), retrying in ${delay}ms (attempt ${attempt}/${maxRetries})`);
|
|
2115
|
+
await new Promise((r) => setTimeout(r, delay));
|
|
2116
|
+
}
|
|
2117
|
+
finally {
|
|
2118
|
+
clearTimeout(authTimer);
|
|
2119
|
+
}
|
|
2063
2120
|
}
|
|
2064
|
-
|
|
2121
|
+
throw new AuthenticationError("Failed to obtain access token after retries", this.providerName);
|
|
2065
2122
|
}
|
|
2066
2123
|
/**
|
|
2067
2124
|
* Build request parts for image generation from prompt, PDFs, and images.
|
|
@@ -68,7 +68,7 @@ export declare class HuggingFaceProvider extends BaseProvider {
|
|
|
68
68
|
/**
|
|
69
69
|
* Enhanced error handling with HuggingFace-specific guidance
|
|
70
70
|
*/
|
|
71
|
-
|
|
71
|
+
formatProviderError(error: unknown): Error;
|
|
72
72
|
getProviderName(): AIProviderName;
|
|
73
73
|
getDefaultModel(): string;
|
|
74
74
|
/**
|
|
@@ -265,7 +265,7 @@ Available tools will be provided in the function calling format. Use them when t
|
|
|
265
265
|
/**
|
|
266
266
|
* Enhanced error handling with HuggingFace-specific guidance
|
|
267
267
|
*/
|
|
268
|
-
|
|
268
|
+
formatProviderError(error) {
|
|
269
269
|
if (error instanceof TimeoutError) {
|
|
270
270
|
return new Error(`HuggingFace request timed out: ${error.message}`);
|
|
271
271
|
}
|
|
@@ -19,7 +19,7 @@ export declare class LiteLLMProvider extends BaseProvider {
|
|
|
19
19
|
* Returns the Vercel AI SDK model instance for LiteLLM
|
|
20
20
|
*/
|
|
21
21
|
protected getAISDKModel(): LanguageModelV1;
|
|
22
|
-
|
|
22
|
+
formatProviderError(error: unknown): Error;
|
|
23
23
|
/**
|
|
24
24
|
* LiteLLM supports tools for compatible models
|
|
25
25
|
*/
|