@juspay/neurolink 11.0.0 → 11.1.1
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 +15 -0
- package/dist/browser/neurolink.min.js +510 -510
- package/dist/cli/commands/setup.d.ts +8 -1
- package/dist/cli/commands/setup.js +62 -46
- package/dist/cli/factories/commandFactory.d.ts +1157 -1
- package/dist/cli/factories/commandFactory.js +20 -53
- package/dist/constants/networkErrorCodes.d.ts +14 -0
- package/dist/constants/networkErrorCodes.js +21 -0
- package/dist/factories/providerDescriptors.d.ts +18 -0
- package/dist/factories/providerDescriptors.js +546 -0
- package/dist/factories/providerFactory.d.ts +25 -14
- package/dist/factories/providerFactory.js +46 -23
- package/dist/factories/providerRegistry.js +31 -30
- package/dist/index.d.ts +10 -1
- package/dist/index.js +13 -3
- package/dist/lib/constants/networkErrorCodes.d.ts +14 -0
- package/dist/lib/constants/networkErrorCodes.js +22 -0
- package/dist/lib/factories/providerDescriptors.d.ts +18 -0
- package/dist/lib/factories/providerDescriptors.js +547 -0
- package/dist/lib/factories/providerFactory.d.ts +25 -14
- package/dist/lib/factories/providerFactory.js +46 -23
- package/dist/lib/factories/providerRegistry.js +31 -30
- package/dist/lib/index.d.ts +10 -1
- package/dist/lib/index.js +13 -3
- package/dist/lib/neurolink.js +25 -37
- package/dist/lib/processors/base/BaseFileProcessor.d.ts +17 -0
- package/dist/lib/processors/base/BaseFileProcessor.js +40 -0
- package/dist/lib/processors/document/OpenDocumentProcessor.js +12 -2
- package/dist/lib/providers/amazonBedrock/client.js +34 -16
- package/dist/lib/providers/anthropic/client.js +39 -34
- package/dist/lib/providers/azureOpenai.js +17 -15
- package/dist/lib/providers/cloudflare.js +12 -21
- package/dist/lib/providers/cohere.js +31 -25
- package/dist/lib/providers/deepseek.js +23 -26
- package/dist/lib/providers/fireworks.js +12 -21
- package/dist/lib/providers/googleAiStudio/client.d.ts +2 -0
- package/dist/lib/providers/googleAiStudio/client.js +39 -17
- package/dist/lib/providers/googleVertex/client.js +107 -99
- package/dist/lib/providers/groq.js +19 -22
- package/dist/lib/providers/huggingFace/client.js +26 -24
- package/dist/lib/providers/litellm/client.js +54 -39
- package/dist/lib/providers/llamaCpp.js +21 -18
- package/dist/lib/providers/lmStudio.js +22 -19
- package/dist/lib/providers/mistral.js +12 -24
- package/dist/lib/providers/nvidiaNim/client.js +37 -34
- package/dist/lib/providers/ollama/client.js +50 -35
- package/dist/lib/providers/openAI/client.js +37 -40
- package/dist/lib/providers/openRouter/client.js +53 -47
- package/dist/lib/providers/openaiChatCompletionsBase.js +40 -16
- package/dist/lib/providers/openaiCompatible/client.js +36 -32
- package/dist/lib/providers/perplexity.js +12 -21
- package/dist/lib/providers/togetherAi.js +12 -21
- package/dist/lib/providers/xai.js +17 -26
- package/dist/lib/proxy/proxyFetch.js +1 -9
- package/dist/lib/server/errors.d.ts +1 -1
- package/dist/lib/server/errors.js +2 -2
- package/dist/lib/server/index.d.ts +2 -2
- package/dist/lib/server/index.js +5 -3
- package/dist/lib/server/middleware/rateLimit.d.ts +0 -4
- package/dist/lib/server/middleware/rateLimit.js +0 -4
- package/dist/lib/types/cli.d.ts +2 -0
- package/dist/lib/types/errors.d.ts +35 -0
- package/dist/lib/types/providers.d.ts +79 -0
- package/dist/lib/utils/errorClassifier.d.ts +30 -0
- package/dist/lib/utils/errorClassifier.js +183 -0
- package/dist/lib/utils/fileDetector.js +6 -43
- package/dist/lib/utils/providerConfig.d.ts +16 -0
- package/dist/lib/utils/providerConfig.js +23 -0
- package/dist/lib/utils/providerHealth.d.ts +53 -12
- package/dist/lib/utils/providerHealth.js +125 -131
- package/dist/lib/utils/providerUtils.js +22 -64
- package/dist/neurolink.js +25 -37
- package/dist/processors/base/BaseFileProcessor.d.ts +17 -0
- package/dist/processors/base/BaseFileProcessor.js +40 -0
- package/dist/processors/document/OpenDocumentProcessor.js +12 -2
- package/dist/providers/amazonBedrock/client.js +34 -16
- package/dist/providers/amazonSagemaker.d.ts +1 -1
- package/dist/providers/anthropic/client.js +39 -34
- package/dist/providers/azureOpenai.js +17 -15
- package/dist/providers/cloudflare.js +12 -21
- package/dist/providers/cohere.js +31 -25
- package/dist/providers/deepseek.js +23 -26
- package/dist/providers/fireworks.js +12 -21
- package/dist/providers/googleAiStudio/client.d.ts +2 -0
- package/dist/providers/googleAiStudio/client.js +39 -17
- package/dist/providers/googleVertex/client.js +107 -99
- package/dist/providers/groq.js +19 -22
- package/dist/providers/huggingFace/client.js +26 -24
- package/dist/providers/litellm/client.js +54 -39
- package/dist/providers/llamaCpp.js +21 -18
- package/dist/providers/lmStudio.js +22 -19
- package/dist/providers/mistral.js +12 -24
- package/dist/providers/nvidiaNim/client.js +37 -34
- package/dist/providers/ollama/client.js +50 -35
- package/dist/providers/openAI/client.js +37 -40
- package/dist/providers/openRouter/client.js +53 -47
- package/dist/providers/openaiChatCompletionsBase.js +40 -16
- package/dist/providers/openaiCompatible/client.js +36 -32
- package/dist/providers/perplexity.js +12 -21
- package/dist/providers/sagemaker/language-model.d.ts +2 -2
- package/dist/providers/togetherAi.js +12 -21
- package/dist/providers/xai.js +17 -26
- package/dist/proxy/proxyFetch.js +1 -9
- package/dist/server/errors.d.ts +1 -1
- package/dist/server/errors.js +2 -2
- package/dist/server/index.d.ts +2 -2
- package/dist/server/index.js +5 -3
- package/dist/server/middleware/rateLimit.d.ts +0 -4
- package/dist/server/middleware/rateLimit.js +0 -4
- package/dist/types/cli.d.ts +2 -0
- package/dist/types/errors.d.ts +35 -0
- package/dist/types/providers.d.ts +79 -0
- package/dist/utils/errorClassifier.d.ts +30 -0
- package/dist/utils/errorClassifier.js +182 -0
- package/dist/utils/fileDetector.js +6 -43
- package/dist/utils/providerConfig.d.ts +16 -0
- package/dist/utils/providerConfig.js +23 -0
- package/dist/utils/providerHealth.d.ts +53 -12
- package/dist/utils/providerHealth.js +125 -131
- package/dist/utils/providerUtils.js +22 -64
- package/package.json +15 -70
|
@@ -6,6 +6,7 @@ import { ATTR, tracers, withClientSpan, withClientStreamSpan, withSpan, } from "
|
|
|
6
6
|
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
7
7
|
import { ERROR_CODES, NeuroLinkError } from "../../utils/errorHandling.js";
|
|
8
8
|
import { logger } from "../../utils/logger.js";
|
|
9
|
+
import { isToolsSchemaExclusionInForce } from "../../core/modules/structuredOutputPolicy.js";
|
|
9
10
|
import { GEMINI_ELISION_NOTE, planGeminiLoopReclaim, previewGeminiToolResponseText, } from "../../context/geminiLoopGuard.js";
|
|
10
11
|
import { getAvailableInputTokens, getContextWindowSize, } from "../../constants/contextWindows.js";
|
|
11
12
|
import { composeAbortSignals, createTimeoutController, TimeoutError, } from "../../utils/timeout.js";
|
|
@@ -18,7 +19,7 @@ import { createProxyFetch } from "../../proxy/proxyFetch.js";
|
|
|
18
19
|
// Google AI Live API types now imported from ../types/providerSpecific.js
|
|
19
20
|
// Import proper types for multimodal message handling
|
|
20
21
|
// Create Google GenAI client
|
|
21
|
-
async function createGoogleGenAIClient(apiKey) {
|
|
22
|
+
async function createGoogleGenAIClient(apiKey, baseURL) {
|
|
22
23
|
const mod = await import("@google/genai");
|
|
23
24
|
const ctor = mod.GoogleGenAI;
|
|
24
25
|
if (!ctor) {
|
|
@@ -32,11 +33,17 @@ async function createGoogleGenAIClient(apiKey) {
|
|
|
32
33
|
});
|
|
33
34
|
}
|
|
34
35
|
const Ctor = ctor;
|
|
35
|
-
// Include httpOptions with proxy fetch for corporate network support
|
|
36
|
+
// Include httpOptions with proxy fetch for corporate network support.
|
|
37
|
+
// baseUrl is only included when resolved — verified against
|
|
38
|
+
// @google/genai's ApiClient (dist/node/index.cjs) that it falls back to
|
|
39
|
+
// its own default whenever httpOptions.baseUrl is undefined, so omitting
|
|
40
|
+
// the key and passing `baseUrl: undefined` behave identically; the key is
|
|
41
|
+
// still omitted outright for a cleaner outbound config object.
|
|
36
42
|
return new Ctor({
|
|
37
43
|
apiKey,
|
|
38
44
|
httpOptions: {
|
|
39
45
|
fetch: createProxyFetch(),
|
|
46
|
+
...(baseURL ? { baseUrl: baseURL } : {}),
|
|
40
47
|
},
|
|
41
48
|
});
|
|
42
49
|
}
|
|
@@ -256,7 +263,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
256
263
|
// Use the @google/genai client for image generation
|
|
257
264
|
let client;
|
|
258
265
|
try {
|
|
259
|
-
client = await createGoogleGenAIClient(apiKey);
|
|
266
|
+
client = await createGoogleGenAIClient(apiKey, this.getBaseURL());
|
|
260
267
|
}
|
|
261
268
|
catch {
|
|
262
269
|
throw new AuthenticationError("Missing '@google/genai'. Install with: npm install @google/genai", this.providerName);
|
|
@@ -563,7 +570,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
563
570
|
// generate() does, or attached files are dropped on this path alone.
|
|
564
571
|
await this.preprocessNativeFileInput(options);
|
|
565
572
|
// Structured output (analysisSchema, JSON format, or schema) is incompatible with tools on Gemini.
|
|
566
|
-
const wantsStructuredOutput = analysisSchema || options.output?.format === "json" || options.schema;
|
|
573
|
+
const wantsStructuredOutput = Boolean(analysisSchema || options.output?.format === "json" || options.schema);
|
|
567
574
|
// Tool filter (a0269210): trust options.tools — caller (BaseProvider.stream)
|
|
568
575
|
// already merged MCP/built-in tools with user tools and applied any
|
|
569
576
|
// enabledToolNames filter. Re-attaching getAllTools() here would clobber
|
|
@@ -575,12 +582,10 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
575
582
|
...options,
|
|
576
583
|
tools: optionTools,
|
|
577
584
|
};
|
|
578
|
-
//
|
|
585
|
+
// Tools + JSON conflict (Gemini), via the shared predicate.
|
|
579
586
|
const wantsJsonOutput = options.output?.format === "json" || options.schema;
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
Object.keys(mergedOptions.tools).length > 0 &&
|
|
583
|
-
!mergedOptions.disableTools) {
|
|
587
|
+
const exclusionInForce = isToolsSchemaExclusionInForce(this.providerName, modelName, !mergedOptions.disableTools, Object.keys(mergedOptions.tools ?? {}).length);
|
|
588
|
+
if (wantsJsonOutput && exclusionInForce) {
|
|
584
589
|
logger.warn("[GoogleAIStudio] Gemini does not support tools and JSON schema output simultaneously. Disabling tools for this request.");
|
|
585
590
|
mergedOptions = { ...mergedOptions, disableTools: true, tools: {} };
|
|
586
591
|
}
|
|
@@ -618,7 +623,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
618
623
|
const timeoutController = createTimeoutController(timeout, this.providerName, "stream");
|
|
619
624
|
try {
|
|
620
625
|
const apiKey = this.getApiKey();
|
|
621
|
-
const client = await createGoogleGenAIClient(apiKey);
|
|
626
|
+
const client = await createGoogleGenAIClient(apiKey, this.getBaseURL());
|
|
622
627
|
logger.debug("[GoogleAIStudio] Using native @google/genai for Gemini 3", {
|
|
623
628
|
model: modelName,
|
|
624
629
|
hasTools: !!options.tools && Object.keys(options.tools).length > 0,
|
|
@@ -956,7 +961,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
956
961
|
const timeoutController = createTimeoutController(timeout, this.providerName, "generate");
|
|
957
962
|
try {
|
|
958
963
|
const apiKey = this.getApiKey();
|
|
959
|
-
const client = await createGoogleGenAIClient(apiKey);
|
|
964
|
+
const client = await createGoogleGenAIClient(apiKey, this.getBaseURL());
|
|
960
965
|
logger.debug("[GoogleAIStudio] Using native @google/genai for Gemini 3 generate", {
|
|
961
966
|
model: modelName,
|
|
962
967
|
hasTools: !!options.tools && Object.keys(options.tools).length > 0,
|
|
@@ -985,7 +990,16 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
985
990
|
let originalNameMap = new Map();
|
|
986
991
|
let declarationsResult;
|
|
987
992
|
const shouldUseTools = !options.disableTools;
|
|
988
|
-
|
|
993
|
+
// Structured output (JSON format or schema) is incompatible with
|
|
994
|
+
// tools on Gemini — routed through the shared predicate so this
|
|
995
|
+
// decision matches stream()'s orchestrator (previously this path
|
|
996
|
+
// had no proactive check and silently dropped the schema instead).
|
|
997
|
+
const wantsNativeJsonRequested = Boolean(options.output?.format === "json" || options.schema);
|
|
998
|
+
const exclusionInForce = isToolsSchemaExclusionInForce(this.providerName, modelName, shouldUseTools, Object.keys(options.tools || {}).length);
|
|
999
|
+
if (wantsNativeJsonRequested && exclusionInForce) {
|
|
1000
|
+
logger.warn("[GoogleAIStudio] Gemini does not support tools and JSON schema output simultaneously. Disabling tools for this request (generate()).");
|
|
1001
|
+
}
|
|
1002
|
+
if (shouldUseTools && !exclusionInForce) {
|
|
989
1003
|
const tools = options.tools || {};
|
|
990
1004
|
if (Object.keys(tools).length > 0) {
|
|
991
1005
|
const result = buildNativeToolDeclarations(tools);
|
|
@@ -1002,8 +1016,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1002
1016
|
// Native JSON / schema enforcement (generate path). Mirrors the
|
|
1003
1017
|
// stream block above; only set when no tools are being sent
|
|
1004
1018
|
// because Gemini cannot combine function calling with JSON mime.
|
|
1005
|
-
const wantsNativeJson = !toolsConfig &&
|
|
1006
|
-
(options.output?.format === "json" || !!options.schema);
|
|
1019
|
+
const wantsNativeJson = !toolsConfig && wantsNativeJsonRequested;
|
|
1007
1020
|
const nativeResponseSchema = wantsNativeJson && options.schema
|
|
1008
1021
|
? buildGeminiResponseSchema(options.schema)
|
|
1009
1022
|
: undefined;
|
|
@@ -1332,7 +1345,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1332
1345
|
// Dynamic import to avoid hard dependency unless audio streaming is used
|
|
1333
1346
|
let client;
|
|
1334
1347
|
try {
|
|
1335
|
-
client = await createGoogleGenAIClient(apiKey);
|
|
1348
|
+
client = await createGoogleGenAIClient(apiKey, this.getBaseURL());
|
|
1336
1349
|
}
|
|
1337
1350
|
catch {
|
|
1338
1351
|
throw new AuthenticationError("Missing '@google/genai'. Install with: pnpm add @google/genai", this.providerName);
|
|
@@ -1522,7 +1535,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1522
1535
|
});
|
|
1523
1536
|
try {
|
|
1524
1537
|
const apiKey = this.getApiKey();
|
|
1525
|
-
const client = await createGoogleGenAIClient(apiKey);
|
|
1538
|
+
const client = await createGoogleGenAIClient(apiKey, this.getBaseURL());
|
|
1526
1539
|
const result = await client.models.embedContent({
|
|
1527
1540
|
model: embeddingModelName,
|
|
1528
1541
|
contents: [text],
|
|
@@ -1562,7 +1575,7 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1562
1575
|
});
|
|
1563
1576
|
try {
|
|
1564
1577
|
const apiKey = this.getApiKey();
|
|
1565
|
-
const client = await createGoogleGenAIClient(apiKey);
|
|
1578
|
+
const client = await createGoogleGenAIClient(apiKey, this.getBaseURL());
|
|
1566
1579
|
const result = await client.models.embedContent({
|
|
1567
1580
|
model: embeddingModelName,
|
|
1568
1581
|
contents: texts,
|
|
@@ -1594,6 +1607,15 @@ export class GoogleAIStudioProvider extends BaseProvider {
|
|
|
1594
1607
|
}
|
|
1595
1608
|
return apiKey;
|
|
1596
1609
|
}
|
|
1610
|
+
// Mirrors mistral.ts's baseURL precedence (credentials override, then env,
|
|
1611
|
+
// then unset — the SDK's own default applies when unset). Blank/whitespace
|
|
1612
|
+
// values are treated as unset so an empty override can't accidentally
|
|
1613
|
+
// clobber the default.
|
|
1614
|
+
getBaseURL() {
|
|
1615
|
+
const baseURL = this.credentials?.baseURL?.trim() ||
|
|
1616
|
+
process.env.GOOGLE_AI_BASE_URL?.trim();
|
|
1617
|
+
return baseURL && baseURL.length > 0 ? baseURL : undefined;
|
|
1618
|
+
}
|
|
1597
1619
|
}
|
|
1598
1620
|
export default GoogleAIStudioProvider;
|
|
1599
1621
|
//# sourceMappingURL=client.js.map
|
|
@@ -13,6 +13,7 @@ import { isSchemaComplexityError } from "../../core/modules/structuredOutputPoli
|
|
|
13
13
|
import { redactUrlForError, stringifyContentSafe, } from "../../utils/logSanitize.js";
|
|
14
14
|
import { createProxyFetch } from "../../proxy/proxyFetch.js";
|
|
15
15
|
import { AuthenticationError, InvalidModelError, NetworkError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
16
|
+
import { classifyProviderError } from "../../utils/errorClassifier.js";
|
|
16
17
|
import { ERROR_CODES, NeuroLinkError } from "../../utils/errorHandling.js";
|
|
17
18
|
import { applyVertexAnthropicCacheBreakpoints } from "../../utils/anthropicCacheBreakpoints.js";
|
|
18
19
|
import { FileDetector } from "../../utils/fileDetector.js";
|
|
@@ -6098,110 +6099,117 @@ export class GoogleVertexProvider extends BaseProvider {
|
|
|
6098
6099
|
}
|
|
6099
6100
|
formatProviderError(error) {
|
|
6100
6101
|
const errorRecord = error;
|
|
6101
|
-
if (typeof errorRecord?.name === "string" &&
|
|
6102
|
-
errorRecord.name === "TimeoutError") {
|
|
6103
|
-
return new NetworkError(`Google Vertex AI request timed out. Consider increasing timeout or using a lighter model.`, this.providerName);
|
|
6104
|
-
}
|
|
6105
|
-
const message = typeof errorRecord?.message === "string"
|
|
6106
|
-
? errorRecord.message
|
|
6107
|
-
: "Unknown error occurred";
|
|
6108
6102
|
const statusCode = typeof errorRecord?.status === "number"
|
|
6109
6103
|
? errorRecord.status
|
|
6110
6104
|
: typeof errorRecord?.statusCode === "number"
|
|
6111
6105
|
? errorRecord.statusCode
|
|
6112
6106
|
: undefined;
|
|
6113
|
-
|
|
6114
|
-
|
|
6115
|
-
|
|
6116
|
-
|
|
6117
|
-
|
|
6118
|
-
|
|
6119
|
-
|
|
6120
|
-
|
|
6121
|
-
|
|
6122
|
-
|
|
6123
|
-
|
|
6124
|
-
|
|
6125
|
-
|
|
6126
|
-
|
|
6127
|
-
|
|
6128
|
-
|
|
6129
|
-
|
|
6130
|
-
|
|
6131
|
-
|
|
6132
|
-
`
|
|
6133
|
-
|
|
6134
|
-
|
|
6135
|
-
|
|
6136
|
-
|
|
6137
|
-
|
|
6138
|
-
|
|
6139
|
-
|
|
6140
|
-
|
|
6141
|
-
|
|
6142
|
-
|
|
6143
|
-
|
|
6144
|
-
|
|
6145
|
-
|
|
6146
|
-
|
|
6147
|
-
|
|
6148
|
-
|
|
6149
|
-
|
|
6150
|
-
|
|
6151
|
-
|
|
6152
|
-
|
|
6153
|
-
|
|
6154
|
-
|
|
6155
|
-
|
|
6156
|
-
|
|
6157
|
-
|
|
6158
|
-
|
|
6159
|
-
|
|
6160
|
-
|
|
6161
|
-
:
|
|
6162
|
-
|
|
6163
|
-
|
|
6164
|
-
|
|
6165
|
-
|
|
6166
|
-
|
|
6167
|
-
|
|
6168
|
-
|
|
6169
|
-
|
|
6170
|
-
|
|
6171
|
-
|
|
6172
|
-
|
|
6173
|
-
|
|
6174
|
-
|
|
6175
|
-
|
|
6176
|
-
|
|
6177
|
-
|
|
6178
|
-
|
|
6179
|
-
|
|
6180
|
-
|
|
6181
|
-
|
|
6182
|
-
|
|
6183
|
-
|
|
6184
|
-
|
|
6185
|
-
|
|
6186
|
-
|
|
6187
|
-
|
|
6188
|
-
|
|
6189
|
-
|
|
6190
|
-
|
|
6191
|
-
|
|
6192
|
-
|
|
6193
|
-
|
|
6194
|
-
|
|
6195
|
-
|
|
6196
|
-
|
|
6197
|
-
|
|
6198
|
-
|
|
6199
|
-
|
|
6200
|
-
|
|
6201
|
-
`
|
|
6202
|
-
|
|
6203
|
-
|
|
6204
|
-
|
|
6107
|
+
const rules = [
|
|
6108
|
+
{
|
|
6109
|
+
// Duck-typed on .name rather than `instanceof TimeoutError` —
|
|
6110
|
+
// Vertex's own `withTimeout` (../../utils/async/index.js) throws a
|
|
6111
|
+
// TimeoutError class distinct from the one classifyProviderError's
|
|
6112
|
+
// built-in fast path checks (../../utils/timeout.js), so that fast
|
|
6113
|
+
// path never fires for a real Vertex timeout. This rule preserves
|
|
6114
|
+
// the pre-migration duck-typed match (both classes set
|
|
6115
|
+
// `.name = "TimeoutError"`) and the original Vertex-specific
|
|
6116
|
+
// message — see task-4-report.md for the full writeup.
|
|
6117
|
+
match: (ctx) => ctx.errorName === "TimeoutError",
|
|
6118
|
+
errorClass: NetworkError,
|
|
6119
|
+
message: "Google Vertex AI request timed out. Consider increasing timeout or using a lighter model.",
|
|
6120
|
+
},
|
|
6121
|
+
{
|
|
6122
|
+
match: (ctx) => /PERMISSION_DENIED|UNAUTHENTICATED|Invalid API key/i.test(ctx.message) ||
|
|
6123
|
+
statusCode === 401 ||
|
|
6124
|
+
statusCode === 403,
|
|
6125
|
+
errorClass: AuthenticationError,
|
|
6126
|
+
message: () => `Google Vertex AI Permission Denied. Your Google Cloud credentials don't have permission to access Vertex AI. ` +
|
|
6127
|
+
`Required Steps: 1. Ensure your service account has Vertex AI User role ` +
|
|
6128
|
+
`2. Check if Vertex AI API is enabled in your project ` +
|
|
6129
|
+
`3. Verify your project ID is correct ` +
|
|
6130
|
+
`4. Confirm your location/region has Vertex AI available`,
|
|
6131
|
+
},
|
|
6132
|
+
{
|
|
6133
|
+
match: (ctx) => /NOT_FOUND|model not found|Model not found/i.test(ctx.message) ||
|
|
6134
|
+
statusCode === 404,
|
|
6135
|
+
errorClass: InvalidModelError,
|
|
6136
|
+
message: () => {
|
|
6137
|
+
const modelSuggestions = this.getModelSuggestions(this.modelName);
|
|
6138
|
+
return (`Model '${this.modelName}' is not available in region ${this.location}. ` +
|
|
6139
|
+
`Suggested alternatives: ${modelSuggestions}. ` +
|
|
6140
|
+
`Troubleshooting: 1. Check model name spelling and format ` +
|
|
6141
|
+
`2. Verify model is available in your region ` +
|
|
6142
|
+
`3. Ensure your project has access to the model ` +
|
|
6143
|
+
`4. For Claude models, enable Anthropic integration in Google Cloud Console`);
|
|
6144
|
+
},
|
|
6145
|
+
},
|
|
6146
|
+
{
|
|
6147
|
+
// Rate limit / quota / capacity errors. Anthropic-on-Vertex capacity
|
|
6148
|
+
// exhaustion surfaces as overloaded_error (HTTP 529) — same
|
|
6149
|
+
// operational meaning as a 429, so classify it here instead of the
|
|
6150
|
+
// generic 5xx branch below.
|
|
6151
|
+
match: (ctx) => /QUOTA_EXCEEDED|RATE_LIMIT_EXCEEDED|rate limit|429/i.test(ctx.message) ||
|
|
6152
|
+
statusCode === 429 ||
|
|
6153
|
+
statusCode === 529 ||
|
|
6154
|
+
/overloaded/i.test(ctx.message),
|
|
6155
|
+
errorClass: RateLimitError,
|
|
6156
|
+
message: (ctx) => {
|
|
6157
|
+
// Surface retry guidance when the SDK error carries it.
|
|
6158
|
+
// @google/genai ApiError nests RetryInfo inside the JSON error
|
|
6159
|
+
// body's details array, so fall back to scraping retryDelay out
|
|
6160
|
+
// of the raw message.
|
|
6161
|
+
const retryDelay = typeof errorRecord?.retryDelay === "string"
|
|
6162
|
+
? errorRecord.retryDelay
|
|
6163
|
+
: (/["']?retryDelay["']?\s*[:=]\s*["']?(\d+(?:\.\d+)?s)/.exec(ctx.message)?.[1] ?? undefined);
|
|
6164
|
+
// Prefer the per-request context the native catches attach to the
|
|
6165
|
+
// error (this.modelName can be stale when options.model overrides
|
|
6166
|
+
// the instance default). Gemini models are force-routed to the
|
|
6167
|
+
// "global" endpoint regardless of configured location — report
|
|
6168
|
+
// the region the request actually hit.
|
|
6169
|
+
const requestModel = typeof errorRecord?.requestModel === "string"
|
|
6170
|
+
? errorRecord.requestModel
|
|
6171
|
+
: this.modelName;
|
|
6172
|
+
const effectiveRegion = typeof errorRecord?.requestRegion === "string"
|
|
6173
|
+
? errorRecord.requestRegion
|
|
6174
|
+
: resolveVertexRegionForModel(requestModel, this.location);
|
|
6175
|
+
return (`Google Vertex AI rate limit / shared-capacity exhausted (429 RESOURCE_EXHAUSTED / overloaded) ` +
|
|
6176
|
+
`for model '${requestModel}' in region '${effectiveRegion}'.` +
|
|
6177
|
+
(retryDelay
|
|
6178
|
+
? ` Upstream suggests retrying after ${retryDelay}.`
|
|
6179
|
+
: "") +
|
|
6180
|
+
` Solutions: 1. Retry with backoff ` +
|
|
6181
|
+
`2. Check your Vertex AI quotas in Google Cloud Console (shared-capacity 429s can occur below quota) ` +
|
|
6182
|
+
`3. Try a different region or model ` +
|
|
6183
|
+
`4. Request provisioned throughput for sustained load`);
|
|
6184
|
+
},
|
|
6185
|
+
},
|
|
6186
|
+
{
|
|
6187
|
+
match: (ctx) => /ECONNRESET|ENOTFOUND|ETIMEDOUT|ECONNREFUSED|network|connection/i.test(ctx.message),
|
|
6188
|
+
errorClass: NetworkError,
|
|
6189
|
+
message: (ctx) => `Connection error: ${ctx.message}`,
|
|
6190
|
+
},
|
|
6191
|
+
{
|
|
6192
|
+
match: (ctx) => /500|502|503|504|server error|Internal Server Error|INTERNAL|UNAVAILABLE/i.test(ctx.message) ||
|
|
6193
|
+
(statusCode !== undefined && statusCode >= 500 && statusCode < 600),
|
|
6194
|
+
errorClass: ProviderError,
|
|
6195
|
+
message: (ctx) => `Google Vertex AI server error: ${ctx.message}. Please try again later.`,
|
|
6196
|
+
},
|
|
6197
|
+
{
|
|
6198
|
+
match: (ctx) => /INVALID_ARGUMENT/i.test(ctx.message),
|
|
6199
|
+
errorClass: ProviderError,
|
|
6200
|
+
message: (ctx) => `Google Vertex AI Invalid Request: ${ctx.message}. ` +
|
|
6201
|
+
`Check: 1. Request parameters are within model limits ` +
|
|
6202
|
+
`2. Input text is properly formatted ` +
|
|
6203
|
+
`3. Temperature and other settings are valid ` +
|
|
6204
|
+
`4. Model supports your request type`,
|
|
6205
|
+
},
|
|
6206
|
+
{
|
|
6207
|
+
match: () => true,
|
|
6208
|
+
errorClass: ProviderError,
|
|
6209
|
+
message: (ctx) => `Google Vertex AI error: ${ctx.message}`,
|
|
6210
|
+
},
|
|
6211
|
+
];
|
|
6212
|
+
return classifyProviderError(error, rules, this.providerName, this.modelName);
|
|
6205
6213
|
}
|
|
6206
6214
|
/**
|
|
6207
6215
|
* Memory-safe cache management for model configurations
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { GroqModels } from "../constants/enums.js";
|
|
2
|
-
import { AuthenticationError, InvalidModelError, ProviderError,
|
|
2
|
+
import { AuthenticationError, InvalidModelError, ProviderError, } from "../types/index.js";
|
|
3
3
|
import { logger } from "../utils/logger.js";
|
|
4
4
|
import { redactUrlCredentials } from "../utils/logSanitize.js";
|
|
5
|
+
import { classifyProviderError, DEFAULT_ERROR_RULES, } from "../utils/errorClassifier.js";
|
|
5
6
|
import { createGroqConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
|
|
6
7
|
import { TimeoutError } from "../utils/timeout.js";
|
|
7
8
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
@@ -57,30 +58,26 @@ export class GroqProvider extends OpenAIChatCompletionsProvider {
|
|
|
57
58
|
];
|
|
58
59
|
}
|
|
59
60
|
formatProviderError(error) {
|
|
61
|
+
// Groq's TimeoutError maps to plain ProviderError (not NetworkError, the
|
|
62
|
+
// classifier's built-in default) — intercept before delegating.
|
|
60
63
|
if (error instanceof TimeoutError) {
|
|
61
64
|
return new ProviderError(`Groq request timed out: ${error.message}`, "groq");
|
|
62
65
|
}
|
|
63
|
-
const
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
message.includes("model_decommissioned")) {
|
|
79
|
-
return new InvalidModelError(message.includes("model_decommissioned")
|
|
80
|
-
? `Groq model '${this.modelName}' was decommissioned. Pick a current model from https://console.groq.com/docs/models.`
|
|
81
|
-
: `Groq model '${this.modelName}' not found. See https://console.groq.com/docs/models for the current catalog.`, "groq");
|
|
82
|
-
}
|
|
83
|
-
return new ProviderError(`Groq error: ${message}`, "groq");
|
|
66
|
+
const rules = [
|
|
67
|
+
{
|
|
68
|
+
match: (ctx) => ctx.statusCode === 401 ||
|
|
69
|
+
/Invalid API key|Authentication|invalid_api_key/i.test(ctx.message),
|
|
70
|
+
errorClass: AuthenticationError,
|
|
71
|
+
message: "Invalid Groq API key. Check GROQ_API_KEY. Get one at https://console.groq.com/keys",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
match: (ctx) => /model_decommissioned/i.test(ctx.message),
|
|
75
|
+
errorClass: InvalidModelError,
|
|
76
|
+
message: (ctx) => `Groq model '${ctx.modelName}' was decommissioned. Pick a current model from https://console.groq.com/docs/models.`,
|
|
77
|
+
},
|
|
78
|
+
...DEFAULT_ERROR_RULES,
|
|
79
|
+
];
|
|
80
|
+
return classifyProviderError(error, rules, "groq", this.modelName);
|
|
84
81
|
}
|
|
85
82
|
}
|
|
86
83
|
//# sourceMappingURL=groq.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { AuthenticationError, InvalidModelError,
|
|
1
|
+
import { AuthenticationError, InvalidModelError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
2
|
+
import { classifyProviderError, DEFAULT_ERROR_RULES, } from "../../utils/errorClassifier.js";
|
|
2
3
|
import { logger } from "../../utils/logger.js";
|
|
3
4
|
import { redactUrlCredentials } from "../../utils/logSanitize.js";
|
|
4
5
|
import { createHuggingFaceConfig, getProviderModel, validateApiKey, } from "../../utils/providerConfig.js";
|
|
5
|
-
import { TimeoutError } from "../../utils/timeout.js";
|
|
6
6
|
import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
|
|
7
7
|
const HUGGINGFACE_DEFAULT_BASE_URL = "https://router.huggingface.co/v1";
|
|
8
8
|
const getHuggingFaceApiKey = () => validateApiKey(createHuggingFaceConfig());
|
|
@@ -74,28 +74,30 @@ export class HuggingFaceProvider extends OpenAIChatCompletionsProvider {
|
|
|
74
74
|
return toolCapableModels.some((capable) => modelName.includes(capable));
|
|
75
75
|
}
|
|
76
76
|
formatProviderError(error) {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
77
|
+
const rules = [
|
|
78
|
+
{
|
|
79
|
+
match: (ctx) => /API_TOKEN_INVALID|Invalid token/.test(ctx.message),
|
|
80
|
+
errorClass: AuthenticationError,
|
|
81
|
+
message: "Invalid HuggingFace API token. Please check your HUGGINGFACE_API_KEY environment variable.",
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
match: (ctx) => /rate limit/.test(ctx.message),
|
|
85
|
+
errorClass: RateLimitError,
|
|
86
|
+
message: "HuggingFace rate limit exceeded. Consider using a paid plan or try again later.",
|
|
87
|
+
},
|
|
88
|
+
{
|
|
89
|
+
match: (ctx) => /model/.test(ctx.message) && /not found/.test(ctx.message),
|
|
90
|
+
errorClass: InvalidModelError,
|
|
91
|
+
message: () => `HuggingFace model '${this.modelName}' not found.\n\nSuggestions:\n1. Check model name spelling\n2. Ensure model exists on HuggingFace Hub\n3. For tool calling, use: Llama-3.1-8B-Instruct, Hermes-3-Llama-3.2-3B, or CodeLlama-34b-Instruct-hf`,
|
|
92
|
+
},
|
|
93
|
+
{
|
|
94
|
+
match: (ctx) => /function|tool/.test(ctx.message),
|
|
95
|
+
errorClass: ProviderError,
|
|
96
|
+
message: (ctx) => `HuggingFace tool calling error: ${ctx.message}\n\nNotes:\n1. Ensure you're using a tool-capable model (Llama-3.1+, Hermes-3+, CodeLlama)\n2. Check that your model supports function calling\n3. Verify tool schema format is correct`,
|
|
97
|
+
},
|
|
98
|
+
...DEFAULT_ERROR_RULES,
|
|
99
|
+
];
|
|
100
|
+
return classifyProviderError(error, rules, "huggingface", this.modelName);
|
|
99
101
|
}
|
|
100
102
|
}
|
|
101
103
|
//# sourceMappingURL=client.js.map
|