@juspay/neurolink 11.0.0 → 11.1.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/dist/browser/neurolink.min.js +524 -524
- package/dist/cli/commands/setup.d.ts +4 -0
- package/dist/cli/commands/setup.js +19 -33
- package/dist/cli/factories/commandFactory.d.ts +1157 -1
- package/dist/cli/factories/commandFactory.js +20 -53
- package/dist/factories/providerDescriptors.d.ts +18 -0
- package/dist/factories/providerDescriptors.js +536 -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/factories/providerDescriptors.d.ts +18 -0
- package/dist/lib/factories/providerDescriptors.js +537 -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/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/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/errors.d.ts +35 -0
- package/dist/lib/types/providers.d.ts +64 -0
- package/dist/lib/utils/errorClassifier.d.ts +30 -0
- package/dist/lib/utils/errorClassifier.js +94 -0
- package/dist/lib/utils/fileDetector.js +6 -43
- package/dist/lib/utils/providerHealth.d.ts +42 -7
- package/dist/lib/utils/providerHealth.js +115 -122
- package/dist/lib/utils/providerUtils.js +21 -63
- package/dist/neurolink.js +25 -37
- 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/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/errors.d.ts +35 -0
- package/dist/types/providers.d.ts +64 -0
- package/dist/utils/errorClassifier.d.ts +30 -0
- package/dist/utils/errorClassifier.js +93 -0
- package/dist/utils/fileDetector.js +6 -43
- package/dist/utils/providerHealth.d.ts +42 -7
- package/dist/utils/providerHealth.js +115 -122
- package/dist/utils/providerUtils.js +21 -63
- package/package.json +15 -70
|
@@ -4,6 +4,7 @@ import { createAnalytics } from "../../core/analytics.js";
|
|
|
4
4
|
import { BaseProvider } from "../../core/baseProvider.js";
|
|
5
5
|
import { DEFAULT_MAX_STEPS } from "../../core/constants.js";
|
|
6
6
|
import { AuthenticationError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
7
|
+
import { classifyProviderError } from "../../utils/errorClassifier.js";
|
|
7
8
|
import { isAbortError, withTimeout } from "../../utils/errorHandling.js";
|
|
8
9
|
import { emitToolEndFromStepFinish } from "../../utils/toolEndEmitter.js";
|
|
9
10
|
import { logger } from "../../utils/logger.js";
|
|
@@ -1724,22 +1725,39 @@ export class AmazonBedrockProvider extends BaseProvider {
|
|
|
1724
1725
|
}
|
|
1725
1726
|
}
|
|
1726
1727
|
formatProviderError(error) {
|
|
1727
|
-
|
|
1728
|
-
|
|
1729
|
-
|
|
1730
|
-
|
|
1731
|
-
|
|
1732
|
-
|
|
1733
|
-
|
|
1734
|
-
|
|
1735
|
-
|
|
1736
|
-
|
|
1737
|
-
|
|
1738
|
-
|
|
1739
|
-
|
|
1740
|
-
|
|
1741
|
-
|
|
1742
|
-
|
|
1728
|
+
const rules = [
|
|
1729
|
+
{
|
|
1730
|
+
match: (ctx) => /AccessDeniedException/i.test(ctx.message),
|
|
1731
|
+
errorClass: AuthenticationError,
|
|
1732
|
+
message: "AWS Bedrock access denied. Check your credentials and permissions.",
|
|
1733
|
+
},
|
|
1734
|
+
{
|
|
1735
|
+
// Checked before the generic ValidationException fallback — a
|
|
1736
|
+
// throttling error can be shaped like a validation error in some
|
|
1737
|
+
// AWS SDK error message templates, but .name/.code are authoritative.
|
|
1738
|
+
match: (ctx) => ctx.errorName === "ThrottlingException" ||
|
|
1739
|
+
ctx.errorCode === "ThrottlingException",
|
|
1740
|
+
errorClass: RateLimitError,
|
|
1741
|
+
message: (ctx) => `Bedrock rate limit (throttled): ${ctx.message}`,
|
|
1742
|
+
},
|
|
1743
|
+
{
|
|
1744
|
+
match: (ctx) => /ValidationException/i.test(ctx.message),
|
|
1745
|
+
errorClass: ProviderError,
|
|
1746
|
+
message: (ctx) => `Validation error: ${ctx.message}`,
|
|
1747
|
+
},
|
|
1748
|
+
{
|
|
1749
|
+
match: () => true,
|
|
1750
|
+
errorClass: ProviderError,
|
|
1751
|
+
message: (ctx) => `AWS Bedrock error: ${ctx.message}`,
|
|
1752
|
+
},
|
|
1753
|
+
];
|
|
1754
|
+
// this.providerName resolves to the literal "bedrock" (getProviderName()
|
|
1755
|
+
// returns it directly, and the constructor only overrides providerName
|
|
1756
|
+
// when an explicit providerName is passed in) — verified matches the
|
|
1757
|
+
// pre-migration hardcoded "bedrock" literal in the throttling branch, so
|
|
1758
|
+
// a single classifyProviderError call using this.providerName for every
|
|
1759
|
+
// rule (rather than a per-rule literal) is not a behavior change.
|
|
1760
|
+
return classifyProviderError(error, rules, this.providerName, this.modelName);
|
|
1743
1761
|
}
|
|
1744
1762
|
/**
|
|
1745
1763
|
* Generate embeddings for text using Amazon Bedrock embedding models
|
|
@@ -69,7 +69,7 @@ export declare class AmazonSageMakerProvider extends BaseProvider {
|
|
|
69
69
|
provider: string;
|
|
70
70
|
specificationVersion: "v2";
|
|
71
71
|
endpointName: string;
|
|
72
|
-
modelType: "huggingface" | "mistral" | "custom" | "
|
|
72
|
+
modelType: "huggingface" | "mistral" | "custom" | "claude" | "llama" | "jumpstart" | undefined;
|
|
73
73
|
region: string;
|
|
74
74
|
} | {
|
|
75
75
|
capabilities: {
|
|
@@ -13,6 +13,7 @@ import { createOAuthFetch } from "../../proxy/oauthFetch.js";
|
|
|
13
13
|
import { createProxyFetch } from "../../proxy/proxyFetch.js";
|
|
14
14
|
import { getCapturedLimitSnapshot, getCapturedResponseHeaders, logClaudeLimitSnapshot, runInLimitCaptureScope, setLimitSpanAttributes, withLimitCapture, wrapFetchWithLimitCapture, } from "./rateLimitCapture.js";
|
|
15
15
|
import { AuthenticationError, NetworkError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
16
|
+
import { classifyProviderError } from "../../utils/errorClassifier.js";
|
|
16
17
|
import { logger } from "../../utils/logger.js";
|
|
17
18
|
import { ANTHROPIC_ELISION_NOTE, planAnthropicLoopReclaim, previewAnthropicToolResultText, } from "../../context/anthropicLoopGuard.js";
|
|
18
19
|
import { getAvailableInputTokens } from "../../constants/contextWindows.js";
|
|
@@ -22,13 +23,14 @@ import { ANTHROPIC_MAX_CACHE_BREAKPOINTS, applyAnthropicHistoryCacheBreakpoints,
|
|
|
22
23
|
import { calculateCost } from "../../utils/pricing.js";
|
|
23
24
|
import { resolveDeferredTool } from "../../tools/toolDiscovery.js";
|
|
24
25
|
import { createAnthropicConfig, getProviderModel, validateApiKey, } from "../../utils/providerConfig.js";
|
|
25
|
-
import { composeAbortSignals, createTimeoutController, mergeAbortSignals,
|
|
26
|
+
import { composeAbortSignals, createTimeoutController, mergeAbortSignals, } from "../../utils/timeout.js";
|
|
26
27
|
import { resolveToolChoice } from "../../utils/toolChoice.js";
|
|
27
28
|
import { emitToolEndFromStepFinish } from "../../utils/toolEndEmitter.js";
|
|
28
29
|
import { NoOutputGeneratedError } from "../../utils/generationErrors.js";
|
|
29
30
|
import { buildNoOutputSentinel, stampNoOutputSpan, } from "../../utils/noOutputSentinel.js";
|
|
30
31
|
import { convertZodToJsonSchema } from "../../utils/schemaConversion.js";
|
|
31
32
|
import { resolveClaudeMaxTokens } from "../../utils/tokenLimits.js";
|
|
33
|
+
import { withProviderRetry } from "../../utils/providerRetry.js";
|
|
32
34
|
import { toAnthropicImageBlock, fileToAnthropicBlock, } from "../anthropicImageBlocks.js";
|
|
33
35
|
import { resolveSamplingParams } from "../../models/modelRegistry.js";
|
|
34
36
|
import { createChunkQueue, createDeferredAnalytics, stringifyToolInput, } from "../openaiChatCompletionsClient.js";
|
|
@@ -1315,37 +1317,40 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1315
1317
|
return delegatingModel;
|
|
1316
1318
|
}
|
|
1317
1319
|
formatProviderError(error) {
|
|
1318
|
-
|
|
1319
|
-
|
|
1320
|
-
|
|
1321
|
-
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
|
|
1329
|
-
|
|
1330
|
-
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
|
|
1334
|
-
|
|
1335
|
-
|
|
1336
|
-
|
|
1337
|
-
|
|
1338
|
-
|
|
1339
|
-
|
|
1340
|
-
|
|
1341
|
-
|
|
1342
|
-
|
|
1343
|
-
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1320
|
+
const rules = [
|
|
1321
|
+
{
|
|
1322
|
+
// Plan 02's mocked-contract work documented a pre-existing gap: the
|
|
1323
|
+
// Anthropic SDK formats auth failures as a bare "401 <msg>" string,
|
|
1324
|
+
// which the message-text regex alone does not catch — mirrors
|
|
1325
|
+
// Vertex's statusCode === 401 fallback in this same task.
|
|
1326
|
+
match: (ctx) => ctx.statusCode === 401 ||
|
|
1327
|
+
/API_KEY_INVALID|Invalid API key/i.test(ctx.message),
|
|
1328
|
+
errorClass: AuthenticationError,
|
|
1329
|
+
message: "Invalid Anthropic API key. Please check your ANTHROPIC_API_KEY environment variable.",
|
|
1330
|
+
},
|
|
1331
|
+
{
|
|
1332
|
+
match: (ctx) => ctx.statusCode === 429 ||
|
|
1333
|
+
/rate limit|too_many_requests|429/i.test(ctx.message),
|
|
1334
|
+
errorClass: RateLimitError,
|
|
1335
|
+
message: "Anthropic rate limit exceeded. Please try again later.",
|
|
1336
|
+
},
|
|
1337
|
+
{
|
|
1338
|
+
match: (ctx) => /ECONNRESET|ENOTFOUND|ECONNREFUSED|network|connection/i.test(ctx.message),
|
|
1339
|
+
errorClass: NetworkError,
|
|
1340
|
+
message: (ctx) => `Connection error: ${ctx.message}`,
|
|
1341
|
+
},
|
|
1342
|
+
{
|
|
1343
|
+
match: (ctx) => /500|502|503|504|server error/i.test(ctx.message),
|
|
1344
|
+
errorClass: ProviderError,
|
|
1345
|
+
message: (ctx) => `Server error: ${ctx.message}`,
|
|
1346
|
+
},
|
|
1347
|
+
{
|
|
1348
|
+
match: () => true,
|
|
1349
|
+
errorClass: ProviderError,
|
|
1350
|
+
message: (ctx) => `Anthropic error: ${ctx.message}`,
|
|
1351
|
+
},
|
|
1352
|
+
];
|
|
1353
|
+
return classifyProviderError(error, rules, this.providerName, this.modelName);
|
|
1349
1354
|
}
|
|
1350
1355
|
// executeGenerate removed - BaseProvider handles all generation with tools
|
|
1351
1356
|
/**
|
|
@@ -1662,9 +1667,9 @@ export class AnthropicProvider extends BaseProvider {
|
|
|
1662
1667
|
...(anthropicToolChoice ? { tool_choice: anthropicToolChoice } : {}),
|
|
1663
1668
|
...(thinking ? { thinking } : {}),
|
|
1664
1669
|
};
|
|
1665
|
-
const events = await client.messages.create(params, {
|
|
1670
|
+
const events = await withProviderRetry(() => client.messages.create(params, {
|
|
1666
1671
|
signal: abortSignal ?? undefined,
|
|
1667
|
-
});
|
|
1672
|
+
}), trace.getActiveSpan() ?? undefined, `${this.providerName} stream`);
|
|
1668
1673
|
// Per-step accumulators, keyed by content-block index so blocks are
|
|
1669
1674
|
// replayed to the conversation in order (thinking blocks must be
|
|
1670
1675
|
// passed back with their signatures when tool use continues a turn).
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { APIVersions } from "../constants/enums.js";
|
|
2
|
-
import { AuthenticationError
|
|
2
|
+
import { AuthenticationError } from "../types/index.js";
|
|
3
3
|
import { logger } from "../utils/logger.js";
|
|
4
|
+
import { classifyProviderError, DEFAULT_ERROR_RULES, } from "../utils/errorClassifier.js";
|
|
4
5
|
import { createAzureAPIKeyConfig, createAzureEndpointConfig, validateApiKey, } from "../utils/providerConfig.js";
|
|
5
|
-
import { TimeoutError } from "../utils/timeout.js";
|
|
6
6
|
import { transformParamsForLogging } from "../utils/transformationUtils.js";
|
|
7
7
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
8
8
|
import { requiresMaxCompletionTokens } from "./openaiChatCompletionsClient.js";
|
|
@@ -158,19 +158,21 @@ export class AzureOpenAIProvider extends OpenAIChatCompletionsProvider {
|
|
|
158
158
|
return this.azureDeployment;
|
|
159
159
|
}
|
|
160
160
|
formatProviderError(error) {
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
161
|
+
// RULING 1 fix: previously only a raw "401" substring was special-cased —
|
|
162
|
+
// everything else (429, 404, network errors, 5xx) fell through to one
|
|
163
|
+
// generic ProviderError. The 401 branch below is preserved byte-for-byte
|
|
164
|
+
// (message text + the raw-substring match style); DEFAULT_ERROR_RULES now
|
|
165
|
+
// gives 429/404/network/5xx their correct classifications instead of the
|
|
166
|
+
// old undifferentiated catch-all.
|
|
167
|
+
const rules = [
|
|
168
|
+
{
|
|
169
|
+
match: (ctx) => /401/.test(ctx.message),
|
|
170
|
+
errorClass: AuthenticationError,
|
|
171
|
+
message: "Invalid Azure OpenAI API key or endpoint.",
|
|
172
|
+
},
|
|
173
|
+
...DEFAULT_ERROR_RULES,
|
|
174
|
+
];
|
|
175
|
+
return classifyProviderError(error, rules, "azure", this.modelName);
|
|
174
176
|
}
|
|
175
177
|
// ===========================================================================
|
|
176
178
|
// New overridable hooks (provided by the base-enhancement branch)
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { CloudflareModels } from "../constants/enums.js";
|
|
2
|
-
import { AuthenticationError
|
|
2
|
+
import { AuthenticationError } 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 { createCloudflareConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
|
|
6
|
-
import { TimeoutError } from "../utils/timeout.js";
|
|
7
7
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
8
8
|
/**
|
|
9
9
|
* Cloudflare Workers AI exposes an OpenAI-compatible endpoint scoped per
|
|
@@ -68,24 +68,15 @@ export class CloudflareProvider extends OpenAIChatCompletionsProvider {
|
|
|
68
68
|
];
|
|
69
69
|
}
|
|
70
70
|
formatProviderError(error) {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
return new AuthenticationError("Invalid Cloudflare API key. Use a token with Workers AI Read+Write scope. Get one at https://dash.cloudflare.com/profile/api-tokens", "cloudflare");
|
|
82
|
-
}
|
|
83
|
-
if (message.includes("rate limit") || message.includes("429")) {
|
|
84
|
-
return new RateLimitError("Cloudflare Workers AI rate limit exceeded. Free-tier neurons reset daily.", "cloudflare");
|
|
85
|
-
}
|
|
86
|
-
if (message.includes("model_not_found") || message.includes("404")) {
|
|
87
|
-
return new InvalidModelError(`Cloudflare model '${this.modelName}' not found. Browse https://developers.cloudflare.com/workers-ai/models/`, "cloudflare");
|
|
88
|
-
}
|
|
89
|
-
return new ProviderError(`Cloudflare Workers AI error: ${message}`, "cloudflare");
|
|
71
|
+
const rules = [
|
|
72
|
+
{
|
|
73
|
+
match: (ctx) => ctx.statusCode === 401 ||
|
|
74
|
+
/Invalid API key|Authentication/i.test(ctx.message),
|
|
75
|
+
errorClass: AuthenticationError,
|
|
76
|
+
message: "Invalid Cloudflare API key. Use a token with Workers AI Read+Write scope. Get one at https://dash.cloudflare.com/profile/api-tokens",
|
|
77
|
+
},
|
|
78
|
+
...DEFAULT_ERROR_RULES,
|
|
79
|
+
];
|
|
80
|
+
return classifyProviderError(error, rules, "cloudflare", this.modelName);
|
|
90
81
|
}
|
|
91
82
|
}
|
package/dist/providers/cohere.js
CHANGED
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
import { CohereModels } from "../constants/enums.js";
|
|
2
|
-
import { AuthenticationError, InvalidModelError,
|
|
2
|
+
import { AuthenticationError, InvalidModelError, ProviderError, RateLimitError, } from "../types/index.js";
|
|
3
|
+
import { classifyProviderError, DEFAULT_ERROR_RULES, } from "../utils/errorClassifier.js";
|
|
3
4
|
import { logger } from "../utils/logger.js";
|
|
4
5
|
import { redactUrlCredentials } from "../utils/logSanitize.js";
|
|
5
6
|
import { createProxyFetch } from "../proxy/proxyFetch.js";
|
|
6
7
|
import { createCohereConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
|
|
7
|
-
import { createTimeoutController
|
|
8
|
+
import { createTimeoutController } from "../utils/timeout.js";
|
|
8
9
|
import { stripTrailingSlash } from "./openaiChatCompletionsClient.js";
|
|
9
10
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
10
11
|
const COHERE_DEFAULT_BASE_URL = "https://api.cohere.com/compatibility/v1";
|
|
@@ -59,29 +60,34 @@ export class CohereProvider extends OpenAIChatCompletionsProvider {
|
|
|
59
60
|
];
|
|
60
61
|
}
|
|
61
62
|
formatProviderError(error) {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
63
|
+
const rules = [
|
|
64
|
+
// "invalid api token" is checked lowercase (case-sensitive substring, as
|
|
65
|
+
// in the original) — deliberately NOT normalized to match the family's
|
|
66
|
+
// more common "Invalid API key" capitalization, since Cohere's actual
|
|
67
|
+
// wire message differs.
|
|
68
|
+
{
|
|
69
|
+
match: (ctx) => /invalid api token|Authentication|401|invalid_api_token/.test(ctx.message),
|
|
70
|
+
errorClass: AuthenticationError,
|
|
71
|
+
message: "Invalid Cohere API key. Check COHERE_API_KEY. Get one at https://dashboard.cohere.com/api-keys",
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
match: (ctx) => /rate limit|429/.test(ctx.message),
|
|
75
|
+
errorClass: RateLimitError,
|
|
76
|
+
message: "Cohere rate limit exceeded. Back off and retry.",
|
|
77
|
+
},
|
|
78
|
+
{
|
|
79
|
+
match: (ctx) => /model_not_found|404/.test(ctx.message),
|
|
80
|
+
errorClass: InvalidModelError,
|
|
81
|
+
message: () => `Cohere model '${this.modelName}' not found. Use command-r, command-r-plus, or command-r7b-12-2024.`,
|
|
82
|
+
},
|
|
83
|
+
{
|
|
84
|
+
match: (ctx) => /trial limit|trial_limit/.test(ctx.message),
|
|
85
|
+
errorClass: ProviderError,
|
|
86
|
+
message: "Cohere trial usage limit exceeded. Upgrade at https://dashboard.cohere.com/billing.",
|
|
87
|
+
},
|
|
88
|
+
...DEFAULT_ERROR_RULES,
|
|
89
|
+
];
|
|
90
|
+
return classifyProviderError(error, rules, "cohere", this.modelName);
|
|
85
91
|
}
|
|
86
92
|
async validateConfiguration() {
|
|
87
93
|
return (typeof this.config.apiKey === "string" &&
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { DeepSeekModels } from "../constants/enums.js";
|
|
2
|
-
import { AuthenticationError, InvalidModelError,
|
|
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 { createDeepSeekConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
|
|
6
|
-
import { TimeoutError } from "../utils/timeout.js";
|
|
7
7
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
8
8
|
const DEEPSEEK_BASE_URL = "https://api.deepseek.com";
|
|
9
9
|
const getDeepSeekApiKey = () => {
|
|
@@ -69,30 +69,27 @@ export class DeepSeekProvider extends OpenAIChatCompletionsProvider {
|
|
|
69
69
|
return getDefaultDeepSeekModel();
|
|
70
70
|
}
|
|
71
71
|
formatProviderError(error) {
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
return new InvalidModelError(`DeepSeek model '${this.modelName}' not found. Use 'deepseek-chat' or 'deepseek-reasoner'.`, "deepseek");
|
|
94
|
-
}
|
|
95
|
-
return new ProviderError(`DeepSeek error: ${message}`, "deepseek");
|
|
72
|
+
const rules = [
|
|
73
|
+
{
|
|
74
|
+
match: (ctx) => ctx.statusCode === 401 ||
|
|
75
|
+
/Invalid API key|Authentication/i.test(ctx.message),
|
|
76
|
+
errorClass: AuthenticationError,
|
|
77
|
+
message: "Invalid DeepSeek API key. Please check your DEEPSEEK_API_KEY environment variable.",
|
|
78
|
+
},
|
|
79
|
+
{
|
|
80
|
+
match: (ctx) => ctx.statusCode === 402 ||
|
|
81
|
+
/Insufficient Balance|insufficient_balance/i.test(ctx.message),
|
|
82
|
+
errorClass: ProviderError,
|
|
83
|
+
message: "DeepSeek account has insufficient balance. Top up at https://platform.deepseek.com/usage",
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
match: (ctx) => /model_not_found/i.test(ctx.message),
|
|
87
|
+
errorClass: InvalidModelError,
|
|
88
|
+
message: (ctx) => `DeepSeek model '${ctx.modelName}' not found. Use 'deepseek-chat' or 'deepseek-reasoner'.`,
|
|
89
|
+
},
|
|
90
|
+
...DEFAULT_ERROR_RULES,
|
|
91
|
+
];
|
|
92
|
+
return classifyProviderError(error, rules, "deepseek", this.modelName);
|
|
96
93
|
}
|
|
97
94
|
// ===========================================================================
|
|
98
95
|
// Optional hooks — provider-specific quirks
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
import { FireworksModels } from "../constants/enums.js";
|
|
2
|
-
import { AuthenticationError
|
|
2
|
+
import { AuthenticationError } 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 { createFireworksConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
|
|
6
|
-
import { TimeoutError } from "../utils/timeout.js";
|
|
7
7
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
8
8
|
const FIREWORKS_DEFAULT_BASE_URL = "https://api.fireworks.ai/inference/v1";
|
|
9
9
|
const getFireworksApiKey = () => validateApiKey(createFireworksConfig());
|
|
@@ -58,24 +58,15 @@ export class FireworksProvider extends OpenAIChatCompletionsProvider {
|
|
|
58
58
|
];
|
|
59
59
|
}
|
|
60
60
|
formatProviderError(error) {
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
return new AuthenticationError("Invalid Fireworks API key. Get one at https://fireworks.ai/account/api-keys", "fireworks");
|
|
72
|
-
}
|
|
73
|
-
if (message.includes("rate limit") || message.includes("429")) {
|
|
74
|
-
return new RateLimitError("Fireworks rate limit exceeded. Back off and retry.", "fireworks");
|
|
75
|
-
}
|
|
76
|
-
if (message.includes("model_not_found") || message.includes("404")) {
|
|
77
|
-
return new InvalidModelError(`Fireworks model '${this.modelName}' not found. Browse https://fireworks.ai/models`, "fireworks");
|
|
78
|
-
}
|
|
79
|
-
return new ProviderError(`Fireworks error: ${message}`, "fireworks");
|
|
61
|
+
const rules = [
|
|
62
|
+
{
|
|
63
|
+
match: (ctx) => ctx.statusCode === 401 ||
|
|
64
|
+
/Invalid API key|Authentication/i.test(ctx.message),
|
|
65
|
+
errorClass: AuthenticationError,
|
|
66
|
+
message: "Invalid Fireworks API key. Get one at https://fireworks.ai/account/api-keys",
|
|
67
|
+
},
|
|
68
|
+
...DEFAULT_ERROR_RULES,
|
|
69
|
+
];
|
|
70
|
+
return classifyProviderError(error, rules, "fireworks", this.modelName);
|
|
80
71
|
}
|
|
81
72
|
}
|
|
@@ -6,6 +6,7 @@ export declare class GoogleAIStudioProvider extends BaseProvider {
|
|
|
6
6
|
private credentials?;
|
|
7
7
|
constructor(modelName?: string, sdk?: unknown, credentials?: {
|
|
8
8
|
apiKey?: string;
|
|
9
|
+
baseURL?: string;
|
|
9
10
|
});
|
|
10
11
|
getProviderName(): AIProviderName;
|
|
11
12
|
getDefaultModel(): string;
|
|
@@ -86,5 +87,6 @@ export declare class GoogleAIStudioProvider extends BaseProvider {
|
|
|
86
87
|
*/
|
|
87
88
|
embedMany(texts: string[], modelName?: string): Promise<number[][]>;
|
|
88
89
|
private getApiKey;
|
|
90
|
+
private getBaseURL;
|
|
89
91
|
}
|
|
90
92
|
export default GoogleAIStudioProvider;
|