@juspay/neurolink 12.23.3 → 12.24.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 +2 -3
- package/dist/browser/neurolink.min.js +367 -367
- package/dist/constants/enums.d.ts +61 -69
- package/dist/constants/enums.js +63 -96
- package/dist/factories/providerDescriptors.d.ts +1 -1
- package/dist/factories/providerDescriptors.js +50 -83
- package/dist/factories/providerRegistry.js +9 -16
- package/dist/models/manifestRegistry.js +11 -2
- package/dist/providers/catalog/deepseek.json +84 -0
- package/dist/providers/catalog/huggingface.json +405 -0
- package/dist/providers/catalog/index.generated.d.ts +1 -1
- package/dist/providers/catalog/index.generated.js +6 -0
- package/dist/providers/catalog/loader.js +20 -5
- package/dist/providers/catalog/mistral.json +8 -3
- package/dist/providers/catalog/provider-catalog.schema.json +31 -1
- package/dist/providers/catalog/schema.d.ts +8 -1
- package/dist/providers/catalog/schema.js +9 -1
- package/dist/providers/configuredOpenAICompat.d.ts +14 -5
- package/dist/providers/configuredOpenAICompat.js +19 -4
- package/dist/providers/embeddingResponseParsing.d.ts +1 -0
- package/dist/providers/embeddingResponseParsing.js +47 -0
- package/dist/providers/ideogram.js +7 -1
- package/dist/providers/jina.js +6 -15
- package/dist/providers/llamaCpp.js +4 -15
- package/dist/providers/lmStudio.js +4 -15
- package/dist/providers/localRuntimeOpenAICompat.d.ts +16 -0
- package/dist/providers/localRuntimeOpenAICompat.js +26 -0
- package/dist/providers/ollama/client.js +3 -9
- package/dist/providers/openaiChatCompletionsBase.d.ts +3 -3
- package/dist/providers/openaiChatCompletionsBase.js +3 -3
- package/dist/providers/openaiCompatCatalog.d.ts +16 -12
- package/dist/providers/openaiCompatCatalog.js +16 -12
- package/dist/providers/voyage.js +5 -18
- package/dist/types/providerCatalog.d.ts +46 -1
- package/dist/types/providerCatalog.generated.d.ts +2 -2
- package/dist/types/providers.d.ts +12 -8
- package/dist/utils/modelChoices.d.ts +2 -2
- package/dist/utils/modelChoices.js +10 -38
- package/dist/utils/sizeGuard.d.ts +8 -5
- package/dist/utils/sizeGuard.js +32 -9
- package/docs-site/static/search-index.json +11044 -1
- package/package.json +1 -1
- package/dist/providers/deepseek.d.ts +0 -47
- package/dist/providers/deepseek.js +0 -120
- package/dist/providers/huggingFace/client.d.ts +0 -54
- package/dist/providers/huggingFace/client.js +0 -120
- package/dist/providers/huggingFace/index.d.ts +0 -1
- package/dist/providers/huggingFace/index.js +0 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juspay/neurolink",
|
|
3
|
-
"version": "12.
|
|
3
|
+
"version": "12.24.1",
|
|
4
4
|
"packageManager": "pnpm@10.15.1",
|
|
5
5
|
"description": "The pipe layer of an AI nervous system: one interface connecting provider neurons to your application, across three inference types — generate, stream and decide. `decide` returns typed, calibrated judgements from a non-generative model (~400ms, ~$0.00002/call) for routing, tool selection and context budgeting. MCP-native (4 transports), voice TTS/STT/realtime, RAG, agents, memory, compaction, 9 observability exporters. OpenAI · Anthropic · Gemini · Bedrock · Azure · Ollama · TypeSafe Jev and more.",
|
|
6
6
|
"author": {
|
|
@@ -1,47 +0,0 @@
|
|
|
1
|
-
import type { AIProviderName } from "../constants/enums.js";
|
|
2
|
-
import type { NeurolinkCredentials, OpenAICompatResponseFormat } from "../types/index.js";
|
|
3
|
-
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
4
|
-
/**
|
|
5
|
-
* DeepSeek Provider — direct HTTP, no AI SDK.
|
|
6
|
-
*
|
|
7
|
-
* OpenAI-compatible chat completions at api.deepseek.com (deepseek-chat /
|
|
8
|
-
* deepseek-reasoner). All request/stream/tool-loop orchestration lives in
|
|
9
|
-
* `OpenAIChatCompletionsProvider`; this class declares configuration and
|
|
10
|
-
* provider-specific quirks:
|
|
11
|
-
*
|
|
12
|
-
* 1. Structured-output downgrade — DeepSeek rejects `response_format:
|
|
13
|
-
* { type: "json_schema" }` ("This response_format type is unavailable
|
|
14
|
-
* now"), so `adjustResponseFormat` downgrades it to `json_object` —
|
|
15
|
-
* matching the `supportsStructuredOutputs: false` behaviour of the
|
|
16
|
-
* `@ai-sdk/openai-compatible` path this migration replaced. The base
|
|
17
|
-
* client injects the literal "json" word the API requires for that mode.
|
|
18
|
-
*
|
|
19
|
-
* 2. Reasoning support — `reasoning_content` (deepseek-reasoner / R1) is
|
|
20
|
-
* surfaced automatically by the native base client: streamed deltas
|
|
21
|
-
* arrive as `{ content: "", reasoning }` chunks and the non-streaming
|
|
22
|
-
* result carries `result.reasoning`. The opt-in `thinking` request
|
|
23
|
-
* param (non-reasoner chat models) still needs thinking-signal plumbing
|
|
24
|
-
* and is tracked as a follow-up. All other behavior is preserved.
|
|
25
|
-
*
|
|
26
|
-
* @see https://api-docs.deepseek.com
|
|
27
|
-
*/
|
|
28
|
-
export declare class DeepSeekProvider extends OpenAIChatCompletionsProvider {
|
|
29
|
-
constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["deepseek"]);
|
|
30
|
-
protected getProviderName(): AIProviderName;
|
|
31
|
-
protected getDefaultModel(): string;
|
|
32
|
-
protected formatProviderError(error: unknown): Error;
|
|
33
|
-
protected getFallbackModelName(): string;
|
|
34
|
-
protected getFallbackModels(): string[];
|
|
35
|
-
/**
|
|
36
|
-
* DeepSeek's /chat/completions rejects `response_format: { type:
|
|
37
|
-
* "json_schema" }` outright ("This response_format type is unavailable
|
|
38
|
-
* now"). The `@ai-sdk/openai-compatible` provider this migration replaced
|
|
39
|
-
* ran with `supportsStructuredOutputs: false`, which downgraded structured-
|
|
40
|
-
* output requests to `{ type: "json_object" }`. Replicate that downgrade so
|
|
41
|
-
* `generate({ schema })` keeps working. (DeepSeek's json_object mode also
|
|
42
|
-
* requires the word "json" somewhere in the messages; the base client's
|
|
43
|
-
* `ensureJsonWordInBody` injects a minimal instruction when the prompt
|
|
44
|
-
* lacks it.)
|
|
45
|
-
*/
|
|
46
|
-
protected adjustResponseFormat(rf: OpenAICompatResponseFormat | undefined, _modelId: string): OpenAICompatResponseFormat | undefined;
|
|
47
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { DeepSeekModels } from "../constants/enums.js";
|
|
2
|
-
import { AuthenticationError, InvalidModelError, ProviderError, } from "../types/index.js";
|
|
3
|
-
import { logger } from "../utils/logger.js";
|
|
4
|
-
import { redactUrlCredentials } from "../utils/logSanitize.js";
|
|
5
|
-
import { classifyProviderError, DEFAULT_ERROR_RULES, } from "../utils/errorClassifier.js";
|
|
6
|
-
import { createDeepSeekConfig, getProviderModel, validateApiKey, } from "../utils/providerConfig.js";
|
|
7
|
-
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
8
|
-
const DEEPSEEK_BASE_URL = "https://api.deepseek.com";
|
|
9
|
-
const getDeepSeekApiKey = () => {
|
|
10
|
-
return validateApiKey(createDeepSeekConfig());
|
|
11
|
-
};
|
|
12
|
-
const getDefaultDeepSeekModel = () => {
|
|
13
|
-
return getProviderModel("DEEPSEEK_MODEL", DeepSeekModels.DEEPSEEK_CHAT);
|
|
14
|
-
};
|
|
15
|
-
/**
|
|
16
|
-
* DeepSeek Provider — direct HTTP, no AI SDK.
|
|
17
|
-
*
|
|
18
|
-
* OpenAI-compatible chat completions at api.deepseek.com (deepseek-chat /
|
|
19
|
-
* deepseek-reasoner). All request/stream/tool-loop orchestration lives in
|
|
20
|
-
* `OpenAIChatCompletionsProvider`; this class declares configuration and
|
|
21
|
-
* provider-specific quirks:
|
|
22
|
-
*
|
|
23
|
-
* 1. Structured-output downgrade — DeepSeek rejects `response_format:
|
|
24
|
-
* { type: "json_schema" }` ("This response_format type is unavailable
|
|
25
|
-
* now"), so `adjustResponseFormat` downgrades it to `json_object` —
|
|
26
|
-
* matching the `supportsStructuredOutputs: false` behaviour of the
|
|
27
|
-
* `@ai-sdk/openai-compatible` path this migration replaced. The base
|
|
28
|
-
* client injects the literal "json" word the API requires for that mode.
|
|
29
|
-
*
|
|
30
|
-
* 2. Reasoning support — `reasoning_content` (deepseek-reasoner / R1) is
|
|
31
|
-
* surfaced automatically by the native base client: streamed deltas
|
|
32
|
-
* arrive as `{ content: "", reasoning }` chunks and the non-streaming
|
|
33
|
-
* result carries `result.reasoning`. The opt-in `thinking` request
|
|
34
|
-
* param (non-reasoner chat models) still needs thinking-signal plumbing
|
|
35
|
-
* and is tracked as a follow-up. All other behavior is preserved.
|
|
36
|
-
*
|
|
37
|
-
* @see https://api-docs.deepseek.com
|
|
38
|
-
*/
|
|
39
|
-
export class DeepSeekProvider extends OpenAIChatCompletionsProvider {
|
|
40
|
-
constructor(modelName, sdk, _region, credentials) {
|
|
41
|
-
// Trim the override before applying precedence. A blank/whitespace
|
|
42
|
-
// `credentials.apiKey` must NOT bypass `getDeepSeekApiKey()` — that
|
|
43
|
-
// would build a client with an unusable bearer token and fail at
|
|
44
|
-
// request time with a confusing 401 instead of at construction time.
|
|
45
|
-
const overrideApiKey = credentials?.apiKey?.trim();
|
|
46
|
-
const apiKey = overrideApiKey && overrideApiKey.length > 0
|
|
47
|
-
? overrideApiKey
|
|
48
|
-
: getDeepSeekApiKey();
|
|
49
|
-
// Treat blank/whitespace overrides as unset so an empty
|
|
50
|
-
// `credentials.baseURL` or `DEEPSEEK_BASE_URL=` cannot silently override
|
|
51
|
-
// the default with "" (mirrors the apiKey precedence above).
|
|
52
|
-
const baseURL = credentials?.baseURL?.trim() ||
|
|
53
|
-
process.env.DEEPSEEK_BASE_URL?.trim() ||
|
|
54
|
-
DEEPSEEK_BASE_URL;
|
|
55
|
-
super("deepseek", modelName, sdk, { baseURL, apiKey });
|
|
56
|
-
logger.debug("DeepSeek Provider initialized", {
|
|
57
|
-
modelName: this.modelName,
|
|
58
|
-
providerName: this.providerName,
|
|
59
|
-
baseURL: redactUrlCredentials(this.config.baseURL),
|
|
60
|
-
});
|
|
61
|
-
}
|
|
62
|
-
// ===========================================================================
|
|
63
|
-
// Abstract hooks (required)
|
|
64
|
-
// ===========================================================================
|
|
65
|
-
getProviderName() {
|
|
66
|
-
return "deepseek";
|
|
67
|
-
}
|
|
68
|
-
getDefaultModel() {
|
|
69
|
-
return getDefaultDeepSeekModel();
|
|
70
|
-
}
|
|
71
|
-
formatProviderError(error) {
|
|
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, this.providerName, this.modelName);
|
|
93
|
-
}
|
|
94
|
-
// ===========================================================================
|
|
95
|
-
// Optional hooks — provider-specific quirks
|
|
96
|
-
// ===========================================================================
|
|
97
|
-
getFallbackModelName() {
|
|
98
|
-
return DeepSeekModels.DEEPSEEK_CHAT;
|
|
99
|
-
}
|
|
100
|
-
getFallbackModels() {
|
|
101
|
-
return [DeepSeekModels.DEEPSEEK_CHAT, DeepSeekModels.DEEPSEEK_REASONER];
|
|
102
|
-
}
|
|
103
|
-
/**
|
|
104
|
-
* DeepSeek's /chat/completions rejects `response_format: { type:
|
|
105
|
-
* "json_schema" }` outright ("This response_format type is unavailable
|
|
106
|
-
* now"). The `@ai-sdk/openai-compatible` provider this migration replaced
|
|
107
|
-
* ran with `supportsStructuredOutputs: false`, which downgraded structured-
|
|
108
|
-
* output requests to `{ type: "json_object" }`. Replicate that downgrade so
|
|
109
|
-
* `generate({ schema })` keeps working. (DeepSeek's json_object mode also
|
|
110
|
-
* requires the word "json" somewhere in the messages; the base client's
|
|
111
|
-
* `ensureJsonWordInBody` injects a minimal instruction when the prompt
|
|
112
|
-
* lacks it.)
|
|
113
|
-
*/
|
|
114
|
-
adjustResponseFormat(rf, _modelId) {
|
|
115
|
-
if (rf?.type === "json_schema") {
|
|
116
|
-
return { type: "json_object" };
|
|
117
|
-
}
|
|
118
|
-
return rf;
|
|
119
|
-
}
|
|
120
|
-
}
|
|
@@ -1,54 +0,0 @@
|
|
|
1
|
-
import type { AIProviderName } from "../../constants/enums.js";
|
|
2
|
-
import type { NeurolinkCredentials } from "../../types/index.js";
|
|
3
|
-
import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
|
|
4
|
-
/**
|
|
5
|
-
* HuggingFace Provider — direct HTTP, no AI SDK.
|
|
6
|
-
*
|
|
7
|
-
* OpenAI-compatible chat completions at router.huggingface.co/v1 (unified
|
|
8
|
-
* router endpoint, 2025). Supports the full HuggingFace model hub including
|
|
9
|
-
* Llama 3.x, Qwen 2.5, Mistral, DeepSeek, and tool-calling capable variants.
|
|
10
|
-
* All request/stream/tool-loop orchestration lives in
|
|
11
|
-
* `OpenAIChatCompletionsProvider`; this class only declares configuration
|
|
12
|
-
* and provider-specific error mapping.
|
|
13
|
-
*
|
|
14
|
-
* @see https://huggingface.co/docs/api-inference/index
|
|
15
|
-
*/
|
|
16
|
-
export declare class HuggingFaceProvider extends OpenAIChatCompletionsProvider {
|
|
17
|
-
constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["huggingFace"]);
|
|
18
|
-
protected getProviderName(): AIProviderName;
|
|
19
|
-
protected getDefaultModel(): string;
|
|
20
|
-
protected getFallbackModelName(): string;
|
|
21
|
-
/**
|
|
22
|
-
* Tool support is resolved by the base through MODEL_REGISTRY's
|
|
23
|
-
* `modelSupports()` facade, which defaults unknown models to supported.
|
|
24
|
-
*
|
|
25
|
-
* This class used to override that with a 13-entry allowlist of model-name
|
|
26
|
-
* substrings, written for the old per-model Inference API where many
|
|
27
|
-
* endpoints rejected the OpenAI `tools` field. The router replaced that, and
|
|
28
|
-
* the list did not keep up. Measured against the 142 models
|
|
29
|
-
* `GET router.huggingface.co/v1/models` served on 2026-09-13 (the
|
|
30
|
-
* catalogue drifts, so treat the totals as a snapshot; the ratio is the
|
|
31
|
-
* point):
|
|
32
|
-
*
|
|
33
|
-
* allowlist entries matching ANY served model 1 of 13
|
|
34
|
-
* served models the allowlist ADMITS 1 of 142
|
|
35
|
-
* served models the allowlist BLOCKS 141
|
|
36
|
-
*
|
|
37
|
-
* So it suppressed tool calling for 99% of the catalogue, including
|
|
38
|
-
* Qwen/Qwen2.5-72B-Instruct, which the router demonstrably tool-calls. A
|
|
39
|
-
* spread of the blocked models — GLM-5.3-Flash, gemma-4-31B-it,
|
|
40
|
-
* DeepSeek-V4-Flash — all accept `tools` with HTTP 200 and return
|
|
41
|
-
* `tool_calls`; none rejected the field.
|
|
42
|
-
*
|
|
43
|
-
* The allowlist's own comment named `microsoft/DialoGPT-medium` — which
|
|
44
|
-
* `getDefaultModel()`, not `getFallbackModelName()`, used to return — as a
|
|
45
|
-
* model that rejects `tools`. The router does not serve it under any
|
|
46
|
-
* request shape, so that path was never reachable; the default now points
|
|
47
|
-
* at a served model (see `getDefaultHuggingFaceModel`).
|
|
48
|
-
*
|
|
49
|
-
* A model that genuinely cannot use tools simply does not emit `tool_calls`,
|
|
50
|
-
* which the loop already handles, so the optimistic default costs nothing
|
|
51
|
-
* that the allowlist was protecting.
|
|
52
|
-
*/
|
|
53
|
-
protected formatProviderError(error: unknown): Error;
|
|
54
|
-
}
|
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
import { HuggingFaceModels } from "../../constants/enums.js";
|
|
2
|
-
import { AuthenticationError, InvalidModelError, ProviderError, RateLimitError, } from "../../types/index.js";
|
|
3
|
-
import { classifyProviderError, DEFAULT_ERROR_RULES, } from "../../utils/errorClassifier.js";
|
|
4
|
-
import { logger } from "../../utils/logger.js";
|
|
5
|
-
import { redactUrlCredentials } from "../../utils/logSanitize.js";
|
|
6
|
-
import { createHuggingFaceConfig, getProviderModel, validateApiKey, } from "../../utils/providerConfig.js";
|
|
7
|
-
import { OpenAIChatCompletionsProvider } from "../openaiChatCompletionsBase.js";
|
|
8
|
-
const HUGGINGFACE_DEFAULT_BASE_URL = "https://router.huggingface.co/v1";
|
|
9
|
-
const getHuggingFaceApiKey = () => validateApiKey(createHuggingFaceConfig());
|
|
10
|
-
/**
|
|
11
|
-
* Must stay the same id `providerRegistry` passes as the registration default
|
|
12
|
-
* (`process.env.HUGGINGFACE_MODEL || HuggingFaceModels.QWEN_2_5_72B_INSTRUCT`),
|
|
13
|
-
* hence the shared constant rather than a second literal.
|
|
14
|
-
*
|
|
15
|
-
* The registry supplies `modelName` on every factory-created provider, so this
|
|
16
|
-
* only decides a directly-constructed `new HuggingFaceProvider()`. It still
|
|
17
|
-
* matters: it previously read `microsoft/DialoGPT-medium`, which the router
|
|
18
|
-
* does not serve under any request shape — it answers 400 "not supported by
|
|
19
|
-
* any provider you have enabled" with or without `tools` — and that stale id
|
|
20
|
-
* was what the docs and setup guidance advertised as the default.
|
|
21
|
-
*/
|
|
22
|
-
const getDefaultHuggingFaceModel = () => getProviderModel("HUGGINGFACE_MODEL", HuggingFaceModels.QWEN_2_5_72B_INSTRUCT);
|
|
23
|
-
/**
|
|
24
|
-
* HuggingFace Provider — direct HTTP, no AI SDK.
|
|
25
|
-
*
|
|
26
|
-
* OpenAI-compatible chat completions at router.huggingface.co/v1 (unified
|
|
27
|
-
* router endpoint, 2025). Supports the full HuggingFace model hub including
|
|
28
|
-
* Llama 3.x, Qwen 2.5, Mistral, DeepSeek, and tool-calling capable variants.
|
|
29
|
-
* All request/stream/tool-loop orchestration lives in
|
|
30
|
-
* `OpenAIChatCompletionsProvider`; this class only declares configuration
|
|
31
|
-
* and provider-specific error mapping.
|
|
32
|
-
*
|
|
33
|
-
* @see https://huggingface.co/docs/api-inference/index
|
|
34
|
-
*/
|
|
35
|
-
export class HuggingFaceProvider extends OpenAIChatCompletionsProvider {
|
|
36
|
-
constructor(modelName, sdk, _region, credentials) {
|
|
37
|
-
const apiKey = credentials?.apiKey?.trim()
|
|
38
|
-
? credentials.apiKey.trim()
|
|
39
|
-
: getHuggingFaceApiKey();
|
|
40
|
-
// Treat blank/whitespace overrides as unset so an empty
|
|
41
|
-
// `credentials.baseURL` or `HUGGINGFACE_BASE_URL=` cannot override the
|
|
42
|
-
// default with "" (mirrors the apiKey precedence above).
|
|
43
|
-
const baseURL = credentials?.baseURL?.trim() ||
|
|
44
|
-
process.env.HUGGINGFACE_BASE_URL?.trim() ||
|
|
45
|
-
HUGGINGFACE_DEFAULT_BASE_URL;
|
|
46
|
-
super("huggingface", modelName, sdk, { baseURL, apiKey });
|
|
47
|
-
logger.debug("HuggingFaceProvider initialized", {
|
|
48
|
-
modelName: this.modelName,
|
|
49
|
-
providerName: this.providerName,
|
|
50
|
-
baseURL: redactUrlCredentials(this.config.baseURL),
|
|
51
|
-
});
|
|
52
|
-
}
|
|
53
|
-
getProviderName() {
|
|
54
|
-
return "huggingface";
|
|
55
|
-
}
|
|
56
|
-
getDefaultModel() {
|
|
57
|
-
return getDefaultHuggingFaceModel();
|
|
58
|
-
}
|
|
59
|
-
getFallbackModelName() {
|
|
60
|
-
return "meta-llama/Llama-3.1-8B-Instruct";
|
|
61
|
-
}
|
|
62
|
-
/**
|
|
63
|
-
* Tool support is resolved by the base through MODEL_REGISTRY's
|
|
64
|
-
* `modelSupports()` facade, which defaults unknown models to supported.
|
|
65
|
-
*
|
|
66
|
-
* This class used to override that with a 13-entry allowlist of model-name
|
|
67
|
-
* substrings, written for the old per-model Inference API where many
|
|
68
|
-
* endpoints rejected the OpenAI `tools` field. The router replaced that, and
|
|
69
|
-
* the list did not keep up. Measured against the 142 models
|
|
70
|
-
* `GET router.huggingface.co/v1/models` served on 2026-09-13 (the
|
|
71
|
-
* catalogue drifts, so treat the totals as a snapshot; the ratio is the
|
|
72
|
-
* point):
|
|
73
|
-
*
|
|
74
|
-
* allowlist entries matching ANY served model 1 of 13
|
|
75
|
-
* served models the allowlist ADMITS 1 of 142
|
|
76
|
-
* served models the allowlist BLOCKS 141
|
|
77
|
-
*
|
|
78
|
-
* So it suppressed tool calling for 99% of the catalogue, including
|
|
79
|
-
* Qwen/Qwen2.5-72B-Instruct, which the router demonstrably tool-calls. A
|
|
80
|
-
* spread of the blocked models — GLM-5.3-Flash, gemma-4-31B-it,
|
|
81
|
-
* DeepSeek-V4-Flash — all accept `tools` with HTTP 200 and return
|
|
82
|
-
* `tool_calls`; none rejected the field.
|
|
83
|
-
*
|
|
84
|
-
* The allowlist's own comment named `microsoft/DialoGPT-medium` — which
|
|
85
|
-
* `getDefaultModel()`, not `getFallbackModelName()`, used to return — as a
|
|
86
|
-
* model that rejects `tools`. The router does not serve it under any
|
|
87
|
-
* request shape, so that path was never reachable; the default now points
|
|
88
|
-
* at a served model (see `getDefaultHuggingFaceModel`).
|
|
89
|
-
*
|
|
90
|
-
* A model that genuinely cannot use tools simply does not emit `tool_calls`,
|
|
91
|
-
* which the loop already handles, so the optimistic default costs nothing
|
|
92
|
-
* that the allowlist was protecting.
|
|
93
|
-
*/
|
|
94
|
-
formatProviderError(error) {
|
|
95
|
-
const rules = [
|
|
96
|
-
{
|
|
97
|
-
match: (ctx) => /API_TOKEN_INVALID|Invalid token/.test(ctx.message),
|
|
98
|
-
errorClass: AuthenticationError,
|
|
99
|
-
message: "Invalid HuggingFace API token. Please check your HUGGINGFACE_API_KEY environment variable.",
|
|
100
|
-
},
|
|
101
|
-
{
|
|
102
|
-
match: (ctx) => /rate limit/.test(ctx.message),
|
|
103
|
-
errorClass: RateLimitError,
|
|
104
|
-
message: "HuggingFace rate limit exceeded. Consider using a paid plan or try again later.",
|
|
105
|
-
},
|
|
106
|
-
{
|
|
107
|
-
match: (ctx) => /model/.test(ctx.message) && /not found/.test(ctx.message),
|
|
108
|
-
errorClass: InvalidModelError,
|
|
109
|
-
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`,
|
|
110
|
-
},
|
|
111
|
-
{
|
|
112
|
-
match: (ctx) => /function|tool/.test(ctx.message),
|
|
113
|
-
errorClass: ProviderError,
|
|
114
|
-
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`,
|
|
115
|
-
},
|
|
116
|
-
...DEFAULT_ERROR_RULES,
|
|
117
|
-
];
|
|
118
|
-
return classifyProviderError(error, rules, this.providerName, this.modelName);
|
|
119
|
-
}
|
|
120
|
-
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./client.js";
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
export * from "./client.js";
|