@juspay/neurolink 11.2.2 → 11.2.4
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/browser/neurolink.min.js +408 -408
- package/dist/core/handlerRegistry.d.ts +29 -0
- package/dist/core/handlerRegistry.js +61 -0
- package/dist/factories/providerRegistry.js +14 -44
- package/dist/lib/core/handlerRegistry.d.ts +29 -0
- package/dist/lib/core/handlerRegistry.js +62 -0
- package/dist/lib/factories/providerRegistry.js +14 -44
- package/dist/lib/providers/configuredOpenAICompat.js +10 -3
- package/dist/lib/providers/openaiCompatCatalog.js +9 -11
- package/dist/lib/types/providers.d.ts +15 -1
- package/dist/lib/utils/avatarProcessor.d.ts +5 -1
- package/dist/lib/utils/avatarProcessor.js +13 -18
- package/dist/lib/utils/musicProcessor.d.ts +5 -1
- package/dist/lib/utils/musicProcessor.js +13 -18
- package/dist/lib/utils/sttProcessor.d.ts +10 -2
- package/dist/lib/utils/sttProcessor.js +22 -18
- package/dist/lib/utils/ttsProcessor.d.ts +10 -2
- package/dist/lib/utils/ttsProcessor.js +22 -18
- package/dist/lib/utils/videoProcessor.d.ts +5 -1
- package/dist/lib/utils/videoProcessor.js +13 -18
- package/dist/lib/voice/RealtimeVoiceAPI.d.ts +1 -1
- package/dist/lib/voice/RealtimeVoiceAPI.js +17 -28
- package/dist/providers/configuredOpenAICompat.js +10 -3
- package/dist/providers/openaiCompatCatalog.js +9 -11
- package/dist/types/providers.d.ts +15 -1
- package/dist/utils/avatarProcessor.d.ts +5 -1
- package/dist/utils/avatarProcessor.js +13 -18
- package/dist/utils/musicProcessor.d.ts +5 -1
- package/dist/utils/musicProcessor.js +13 -18
- package/dist/utils/sttProcessor.d.ts +10 -2
- package/dist/utils/sttProcessor.js +22 -18
- package/dist/utils/ttsProcessor.d.ts +10 -2
- package/dist/utils/ttsProcessor.js +22 -18
- package/dist/utils/videoProcessor.d.ts +5 -1
- package/dist/utils/videoProcessor.js +13 -18
- package/dist/voice/RealtimeVoiceAPI.d.ts +1 -1
- package/dist/voice/RealtimeVoiceAPI.js +17 -28
- package/package.json +8 -2
- package/dist/lib/providers/cloudflare.d.ts +0 -26
- package/dist/lib/providers/cloudflare.js +0 -83
- package/dist/lib/providers/fireworks.d.ts +0 -22
- package/dist/lib/providers/fireworks.js +0 -73
- package/dist/lib/providers/groq.d.ts +0 -24
- package/dist/lib/providers/groq.js +0 -83
- package/dist/lib/providers/mistral.d.ts +0 -25
- package/dist/lib/providers/mistral.js +0 -87
- package/dist/lib/providers/perplexity.d.ts +0 -24
- package/dist/lib/providers/perplexity.js +0 -69
- package/dist/lib/providers/togetherAi.d.ts +0 -23
- package/dist/lib/providers/togetherAi.js +0 -73
- package/dist/lib/providers/xai.d.ts +0 -22
- package/dist/lib/providers/xai.js +0 -77
- package/dist/providers/cloudflare.d.ts +0 -26
- package/dist/providers/cloudflare.js +0 -82
- package/dist/providers/fireworks.d.ts +0 -22
- package/dist/providers/fireworks.js +0 -72
- package/dist/providers/groq.d.ts +0 -24
- package/dist/providers/groq.js +0 -82
- package/dist/providers/mistral.d.ts +0 -25
- package/dist/providers/mistral.js +0 -86
- package/dist/providers/perplexity.d.ts +0 -24
- package/dist/providers/perplexity.js +0 -68
- package/dist/providers/togetherAi.d.ts +0 -23
- package/dist/providers/togetherAi.js +0 -72
- package/dist/providers/xai.d.ts +0 -22
- package/dist/providers/xai.js +0 -76
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic provider-name → handler registry shared by every media-generation
|
|
3
|
+
* ecosystem (TTS, STT, Realtime, Video, Music, Avatar). Each ecosystem's own
|
|
4
|
+
* processor class composes one instance of this class instead of hand-rolling
|
|
5
|
+
* its own `Map<string, THandler>` plus register/supports/get/list methods.
|
|
6
|
+
*
|
|
7
|
+
* Centralizes only the behavior that was byte-identical across all six
|
|
8
|
+
* hand-rolled registries: input validation, name normalization (lowercase),
|
|
9
|
+
* the overwrite-warning log line, and the four lookup/list/clear operations.
|
|
10
|
+
* Registration-outcome debug logging (whose exact phrasing differs per
|
|
11
|
+
* ecosystem — e.g. "Registered TTS handler..." vs "Registered video
|
|
12
|
+
* handler...") and any ecosystem-specific extra logging (e.g. TTS/STT's
|
|
13
|
+
* `supports()` diagnostics) stay in the owning processor's own wrapper
|
|
14
|
+
* methods; this class does not attempt to unify those.
|
|
15
|
+
*/
|
|
16
|
+
export declare class HandlerRegistry<THandler> {
|
|
17
|
+
private readonly scopeName;
|
|
18
|
+
private readonly handlers;
|
|
19
|
+
/**
|
|
20
|
+
* @param scopeName Log-line prefix, e.g. "TTSProcessor" — matches the
|
|
21
|
+
* `[ClassName]` prefix each processor already uses in its own logs.
|
|
22
|
+
*/
|
|
23
|
+
constructor(scopeName: string);
|
|
24
|
+
register(providerName: string, handler: THandler): void;
|
|
25
|
+
supports(providerName: string): boolean;
|
|
26
|
+
get(providerName: string): THandler | undefined;
|
|
27
|
+
list(): string[];
|
|
28
|
+
clear(): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import { logger } from "../utils/logger.js";
|
|
2
|
+
import { sanitizeForLog } from "../utils/logSanitize.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generic provider-name → handler registry shared by every media-generation
|
|
5
|
+
* ecosystem (TTS, STT, Realtime, Video, Music, Avatar). Each ecosystem's own
|
|
6
|
+
* processor class composes one instance of this class instead of hand-rolling
|
|
7
|
+
* its own `Map<string, THandler>` plus register/supports/get/list methods.
|
|
8
|
+
*
|
|
9
|
+
* Centralizes only the behavior that was byte-identical across all six
|
|
10
|
+
* hand-rolled registries: input validation, name normalization (lowercase),
|
|
11
|
+
* the overwrite-warning log line, and the four lookup/list/clear operations.
|
|
12
|
+
* Registration-outcome debug logging (whose exact phrasing differs per
|
|
13
|
+
* ecosystem — e.g. "Registered TTS handler..." vs "Registered video
|
|
14
|
+
* handler...") and any ecosystem-specific extra logging (e.g. TTS/STT's
|
|
15
|
+
* `supports()` diagnostics) stay in the owning processor's own wrapper
|
|
16
|
+
* methods; this class does not attempt to unify those.
|
|
17
|
+
*/
|
|
18
|
+
export class HandlerRegistry {
|
|
19
|
+
scopeName;
|
|
20
|
+
handlers = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* @param scopeName Log-line prefix, e.g. "TTSProcessor" — matches the
|
|
23
|
+
* `[ClassName]` prefix each processor already uses in its own logs.
|
|
24
|
+
*/
|
|
25
|
+
constructor(scopeName) {
|
|
26
|
+
this.scopeName = scopeName;
|
|
27
|
+
}
|
|
28
|
+
register(providerName, handler) {
|
|
29
|
+
if (!providerName) {
|
|
30
|
+
throw new Error("Provider name is required");
|
|
31
|
+
}
|
|
32
|
+
if (!handler) {
|
|
33
|
+
throw new Error("Handler is required");
|
|
34
|
+
}
|
|
35
|
+
const key = providerName.toLowerCase();
|
|
36
|
+
if (this.handlers.has(key)) {
|
|
37
|
+
// Every caller today passes a literal provider slug, but this class is
|
|
38
|
+
// generic over an arbitrary string — sanitize before logging it so a
|
|
39
|
+
// future caller building the key from untrusted input can't leak a
|
|
40
|
+
// bearer token/API key through this warning.
|
|
41
|
+
logger.warn(`[${this.scopeName}] Overwriting existing handler for provider: ${sanitizeForLog(key)}`);
|
|
42
|
+
}
|
|
43
|
+
this.handlers.set(key, handler);
|
|
44
|
+
}
|
|
45
|
+
supports(providerName) {
|
|
46
|
+
if (!providerName) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return this.handlers.has(providerName.toLowerCase());
|
|
50
|
+
}
|
|
51
|
+
get(providerName) {
|
|
52
|
+
return this.handlers.get(providerName.toLowerCase());
|
|
53
|
+
}
|
|
54
|
+
list() {
|
|
55
|
+
return Array.from(this.handlers.keys());
|
|
56
|
+
}
|
|
57
|
+
clear() {
|
|
58
|
+
this.handlers.clear();
|
|
59
|
+
logger.debug(`[${this.scopeName}] Cleared all handlers`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ProviderFactory } from "./providerFactory.js";
|
|
2
2
|
import { logger } from "../utils/logger.js";
|
|
3
|
-
import { AIProviderName, GoogleAIModels, OpenAIModels, AnthropicModels, VertexModels,
|
|
3
|
+
import { AIProviderName, GoogleAIModels, OpenAIModels, AnthropicModels, VertexModels, OllamaModels, LiteLLMModels, HuggingFaceModels, DeepSeekModels, NvidiaNimModels, OpenRouterModels, CohereModels, VoyageModels, JinaModels, StabilityModels, IdeogramModels, RecraftModels, ReplicateModels, } from "../constants/enums.js";
|
|
4
4
|
import { PROVIDER_DESCRIPTORS_BY_NAME } from "./providerDescriptors.js";
|
|
5
|
+
import { OPENAI_COMPAT_CATALOG } from "../providers/openaiCompatCatalog.js";
|
|
5
6
|
/**
|
|
6
7
|
* Provider Registry - registers all providers with the factory
|
|
7
8
|
* This is where we migrate providers one by one to the new pattern
|
|
@@ -111,12 +112,18 @@ export class ProviderRegistry {
|
|
|
111
112
|
return new HuggingFaceProvider(modelName, sdk, region, hfCreds);
|
|
112
113
|
}, process.env.HUGGINGFACE_MODEL ||
|
|
113
114
|
HuggingFaceModels.QWEN_2_5_72B_INSTRUCT, ["huggingface", "hf"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.HUGGINGFACE));
|
|
114
|
-
// Register
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
// Register the config-driven OpenAI-compatible catalog providers
|
|
116
|
+
// (groq, xai, together-ai, fireworks, perplexity, mistral, cloudflare).
|
|
117
|
+
// To add a new zero-quirk OpenAI-compatible provider, add one entry to
|
|
118
|
+
// OPENAI_COMPAT_CATALOG (openaiCompatCatalog.ts) — not a new block here.
|
|
119
|
+
for (const entry of OPENAI_COMPAT_CATALOG) {
|
|
120
|
+
ProviderFactory.registerProvider(entry.providerName, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
121
|
+
const { ConfiguredOpenAICompatProvider } = await import("../providers/configuredOpenAICompat.js");
|
|
122
|
+
return new ConfiguredOpenAICompatProvider(entry, modelName, sdk, credentials);
|
|
123
|
+
}, entry.registryDefaultModelChecksEnvVar
|
|
124
|
+
? process.env[entry.modelEnvVar] || entry.registryDefaultModel
|
|
125
|
+
: entry.registryDefaultModel, entry.aliases, PROVIDER_DESCRIPTORS_BY_NAME.get(entry.providerName));
|
|
126
|
+
}
|
|
120
127
|
// Register Ollama provider
|
|
121
128
|
ProviderFactory.registerProvider(AIProviderName.OLLAMA, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
122
129
|
const ollamaCreds = credentials;
|
|
@@ -178,49 +185,12 @@ export class ProviderRegistry {
|
|
|
178
185
|
const { LlamaCppProvider } = await import("../providers/llamaCpp.js");
|
|
179
186
|
return new LlamaCppProvider(modelName, sdk, undefined, llamaCppCreds);
|
|
180
187
|
}, process.env.LLAMACPP_MODEL || undefined, ["llamacpp", "llama.cpp", "llama-cpp"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.LLAMACPP));
|
|
181
|
-
// Register xAI Grok provider
|
|
182
|
-
ProviderFactory.registerProvider(AIProviderName.XAI, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
183
|
-
const xaiCreds = credentials;
|
|
184
|
-
const { XaiProvider } = await import("../providers/xai.js");
|
|
185
|
-
return new XaiProvider(modelName, sdk, undefined, xaiCreds);
|
|
186
|
-
}, process.env.XAI_MODEL || XaiModels.GROK_3, ["xai", "grok"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.XAI));
|
|
187
|
-
// Register Groq provider
|
|
188
|
-
ProviderFactory.registerProvider(AIProviderName.GROQ, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
189
|
-
const groqCreds = credentials;
|
|
190
|
-
const { GroqProvider } = await import("../providers/groq.js");
|
|
191
|
-
return new GroqProvider(modelName, sdk, undefined, groqCreds);
|
|
192
|
-
}, process.env.GROQ_MODEL || GroqModels.LLAMA_3_3_70B_VERSATILE, ["groq"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.GROQ));
|
|
193
188
|
// Register Cohere provider
|
|
194
189
|
ProviderFactory.registerProvider(AIProviderName.COHERE, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
195
190
|
const cohereCreds = credentials;
|
|
196
191
|
const { CohereProvider } = await import("../providers/cohere.js");
|
|
197
192
|
return new CohereProvider(modelName, sdk, undefined, cohereCreds);
|
|
198
193
|
}, process.env.COHERE_MODEL || CohereModels.COMMAND_R_PLUS, ["cohere"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.COHERE));
|
|
199
|
-
// Register Together AI provider
|
|
200
|
-
ProviderFactory.registerProvider(AIProviderName.TOGETHER_AI, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
201
|
-
const togetherCreds = credentials;
|
|
202
|
-
const { TogetherAIProvider } = await import("../providers/togetherAi.js");
|
|
203
|
-
return new TogetherAIProvider(modelName, sdk, undefined, togetherCreds);
|
|
204
|
-
}, process.env.TOGETHER_MODEL ||
|
|
205
|
-
TogetherAIModels.LLAMA_3_3_70B_INSTRUCT_TURBO, ["together-ai", "together"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.TOGETHER_AI));
|
|
206
|
-
// Register Fireworks AI provider
|
|
207
|
-
ProviderFactory.registerProvider(AIProviderName.FIREWORKS, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
208
|
-
const fireworksCreds = credentials;
|
|
209
|
-
const { FireworksProvider } = await import("../providers/fireworks.js");
|
|
210
|
-
return new FireworksProvider(modelName, sdk, undefined, fireworksCreds);
|
|
211
|
-
}, process.env.FIREWORKS_MODEL || FireworksModels.DEEPSEEK_V4_PRO, ["fireworks"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.FIREWORKS));
|
|
212
|
-
// Register Perplexity provider
|
|
213
|
-
ProviderFactory.registerProvider(AIProviderName.PERPLEXITY, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
214
|
-
const perplexityCreds = credentials;
|
|
215
|
-
const { PerplexityProvider } = await import("../providers/perplexity.js");
|
|
216
|
-
return new PerplexityProvider(modelName, sdk, undefined, perplexityCreds);
|
|
217
|
-
}, process.env.PERPLEXITY_MODEL || PerplexityModels.SONAR, ["perplexity", "pplx"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.PERPLEXITY));
|
|
218
|
-
// Register Cloudflare Workers AI provider
|
|
219
|
-
ProviderFactory.registerProvider(AIProviderName.CLOUDFLARE, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
220
|
-
const cloudflareCreds = credentials;
|
|
221
|
-
const { CloudflareProvider } = await import("../providers/cloudflare.js");
|
|
222
|
-
return new CloudflareProvider(modelName, sdk, undefined, cloudflareCreds);
|
|
223
|
-
}, process.env.CLOUDFLARE_MODEL || CloudflareModels.LLAMA_3_3_70B_FAST, ["cloudflare", "workers-ai", "cf-ai"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.CLOUDFLARE));
|
|
224
194
|
// Register Voyage AI embeddings provider
|
|
225
195
|
ProviderFactory.registerProvider(AIProviderName.VOYAGE, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
226
196
|
const voyageCreds = credentials;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generic provider-name → handler registry shared by every media-generation
|
|
3
|
+
* ecosystem (TTS, STT, Realtime, Video, Music, Avatar). Each ecosystem's own
|
|
4
|
+
* processor class composes one instance of this class instead of hand-rolling
|
|
5
|
+
* its own `Map<string, THandler>` plus register/supports/get/list methods.
|
|
6
|
+
*
|
|
7
|
+
* Centralizes only the behavior that was byte-identical across all six
|
|
8
|
+
* hand-rolled registries: input validation, name normalization (lowercase),
|
|
9
|
+
* the overwrite-warning log line, and the four lookup/list/clear operations.
|
|
10
|
+
* Registration-outcome debug logging (whose exact phrasing differs per
|
|
11
|
+
* ecosystem — e.g. "Registered TTS handler..." vs "Registered video
|
|
12
|
+
* handler...") and any ecosystem-specific extra logging (e.g. TTS/STT's
|
|
13
|
+
* `supports()` diagnostics) stay in the owning processor's own wrapper
|
|
14
|
+
* methods; this class does not attempt to unify those.
|
|
15
|
+
*/
|
|
16
|
+
export declare class HandlerRegistry<THandler> {
|
|
17
|
+
private readonly scopeName;
|
|
18
|
+
private readonly handlers;
|
|
19
|
+
/**
|
|
20
|
+
* @param scopeName Log-line prefix, e.g. "TTSProcessor" — matches the
|
|
21
|
+
* `[ClassName]` prefix each processor already uses in its own logs.
|
|
22
|
+
*/
|
|
23
|
+
constructor(scopeName: string);
|
|
24
|
+
register(providerName: string, handler: THandler): void;
|
|
25
|
+
supports(providerName: string): boolean;
|
|
26
|
+
get(providerName: string): THandler | undefined;
|
|
27
|
+
list(): string[];
|
|
28
|
+
clear(): void;
|
|
29
|
+
}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { logger } from "../utils/logger.js";
|
|
2
|
+
import { sanitizeForLog } from "../utils/logSanitize.js";
|
|
3
|
+
/**
|
|
4
|
+
* Generic provider-name → handler registry shared by every media-generation
|
|
5
|
+
* ecosystem (TTS, STT, Realtime, Video, Music, Avatar). Each ecosystem's own
|
|
6
|
+
* processor class composes one instance of this class instead of hand-rolling
|
|
7
|
+
* its own `Map<string, THandler>` plus register/supports/get/list methods.
|
|
8
|
+
*
|
|
9
|
+
* Centralizes only the behavior that was byte-identical across all six
|
|
10
|
+
* hand-rolled registries: input validation, name normalization (lowercase),
|
|
11
|
+
* the overwrite-warning log line, and the four lookup/list/clear operations.
|
|
12
|
+
* Registration-outcome debug logging (whose exact phrasing differs per
|
|
13
|
+
* ecosystem — e.g. "Registered TTS handler..." vs "Registered video
|
|
14
|
+
* handler...") and any ecosystem-specific extra logging (e.g. TTS/STT's
|
|
15
|
+
* `supports()` diagnostics) stay in the owning processor's own wrapper
|
|
16
|
+
* methods; this class does not attempt to unify those.
|
|
17
|
+
*/
|
|
18
|
+
export class HandlerRegistry {
|
|
19
|
+
scopeName;
|
|
20
|
+
handlers = new Map();
|
|
21
|
+
/**
|
|
22
|
+
* @param scopeName Log-line prefix, e.g. "TTSProcessor" — matches the
|
|
23
|
+
* `[ClassName]` prefix each processor already uses in its own logs.
|
|
24
|
+
*/
|
|
25
|
+
constructor(scopeName) {
|
|
26
|
+
this.scopeName = scopeName;
|
|
27
|
+
}
|
|
28
|
+
register(providerName, handler) {
|
|
29
|
+
if (!providerName) {
|
|
30
|
+
throw new Error("Provider name is required");
|
|
31
|
+
}
|
|
32
|
+
if (!handler) {
|
|
33
|
+
throw new Error("Handler is required");
|
|
34
|
+
}
|
|
35
|
+
const key = providerName.toLowerCase();
|
|
36
|
+
if (this.handlers.has(key)) {
|
|
37
|
+
// Every caller today passes a literal provider slug, but this class is
|
|
38
|
+
// generic over an arbitrary string — sanitize before logging it so a
|
|
39
|
+
// future caller building the key from untrusted input can't leak a
|
|
40
|
+
// bearer token/API key through this warning.
|
|
41
|
+
logger.warn(`[${this.scopeName}] Overwriting existing handler for provider: ${sanitizeForLog(key)}`);
|
|
42
|
+
}
|
|
43
|
+
this.handlers.set(key, handler);
|
|
44
|
+
}
|
|
45
|
+
supports(providerName) {
|
|
46
|
+
if (!providerName) {
|
|
47
|
+
return false;
|
|
48
|
+
}
|
|
49
|
+
return this.handlers.has(providerName.toLowerCase());
|
|
50
|
+
}
|
|
51
|
+
get(providerName) {
|
|
52
|
+
return this.handlers.get(providerName.toLowerCase());
|
|
53
|
+
}
|
|
54
|
+
list() {
|
|
55
|
+
return Array.from(this.handlers.keys());
|
|
56
|
+
}
|
|
57
|
+
clear() {
|
|
58
|
+
this.handlers.clear();
|
|
59
|
+
logger.debug(`[${this.scopeName}] Cleared all handlers`);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=handlerRegistry.js.map
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { ProviderFactory } from "./providerFactory.js";
|
|
2
2
|
import { logger } from "../utils/logger.js";
|
|
3
|
-
import { AIProviderName, GoogleAIModels, OpenAIModels, AnthropicModels, VertexModels,
|
|
3
|
+
import { AIProviderName, GoogleAIModels, OpenAIModels, AnthropicModels, VertexModels, OllamaModels, LiteLLMModels, HuggingFaceModels, DeepSeekModels, NvidiaNimModels, OpenRouterModels, CohereModels, VoyageModels, JinaModels, StabilityModels, IdeogramModels, RecraftModels, ReplicateModels, } from "../constants/enums.js";
|
|
4
4
|
import { PROVIDER_DESCRIPTORS_BY_NAME } from "./providerDescriptors.js";
|
|
5
|
+
import { OPENAI_COMPAT_CATALOG } from "../providers/openaiCompatCatalog.js";
|
|
5
6
|
/**
|
|
6
7
|
* Provider Registry - registers all providers with the factory
|
|
7
8
|
* This is where we migrate providers one by one to the new pattern
|
|
@@ -111,12 +112,18 @@ export class ProviderRegistry {
|
|
|
111
112
|
return new HuggingFaceProvider(modelName, sdk, region, hfCreds);
|
|
112
113
|
}, process.env.HUGGINGFACE_MODEL ||
|
|
113
114
|
HuggingFaceModels.QWEN_2_5_72B_INSTRUCT, ["huggingface", "hf"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.HUGGINGFACE));
|
|
114
|
-
// Register
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
115
|
+
// Register the config-driven OpenAI-compatible catalog providers
|
|
116
|
+
// (groq, xai, together-ai, fireworks, perplexity, mistral, cloudflare).
|
|
117
|
+
// To add a new zero-quirk OpenAI-compatible provider, add one entry to
|
|
118
|
+
// OPENAI_COMPAT_CATALOG (openaiCompatCatalog.ts) — not a new block here.
|
|
119
|
+
for (const entry of OPENAI_COMPAT_CATALOG) {
|
|
120
|
+
ProviderFactory.registerProvider(entry.providerName, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
121
|
+
const { ConfiguredOpenAICompatProvider } = await import("../providers/configuredOpenAICompat.js");
|
|
122
|
+
return new ConfiguredOpenAICompatProvider(entry, modelName, sdk, credentials);
|
|
123
|
+
}, entry.registryDefaultModelChecksEnvVar
|
|
124
|
+
? process.env[entry.modelEnvVar] || entry.registryDefaultModel
|
|
125
|
+
: entry.registryDefaultModel, entry.aliases, PROVIDER_DESCRIPTORS_BY_NAME.get(entry.providerName));
|
|
126
|
+
}
|
|
120
127
|
// Register Ollama provider
|
|
121
128
|
ProviderFactory.registerProvider(AIProviderName.OLLAMA, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
122
129
|
const ollamaCreds = credentials;
|
|
@@ -178,49 +185,12 @@ export class ProviderRegistry {
|
|
|
178
185
|
const { LlamaCppProvider } = await import("../providers/llamaCpp.js");
|
|
179
186
|
return new LlamaCppProvider(modelName, sdk, undefined, llamaCppCreds);
|
|
180
187
|
}, process.env.LLAMACPP_MODEL || undefined, ["llamacpp", "llama.cpp", "llama-cpp"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.LLAMACPP));
|
|
181
|
-
// Register xAI Grok provider
|
|
182
|
-
ProviderFactory.registerProvider(AIProviderName.XAI, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
183
|
-
const xaiCreds = credentials;
|
|
184
|
-
const { XaiProvider } = await import("../providers/xai.js");
|
|
185
|
-
return new XaiProvider(modelName, sdk, undefined, xaiCreds);
|
|
186
|
-
}, process.env.XAI_MODEL || XaiModels.GROK_3, ["xai", "grok"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.XAI));
|
|
187
|
-
// Register Groq provider
|
|
188
|
-
ProviderFactory.registerProvider(AIProviderName.GROQ, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
189
|
-
const groqCreds = credentials;
|
|
190
|
-
const { GroqProvider } = await import("../providers/groq.js");
|
|
191
|
-
return new GroqProvider(modelName, sdk, undefined, groqCreds);
|
|
192
|
-
}, process.env.GROQ_MODEL || GroqModels.LLAMA_3_3_70B_VERSATILE, ["groq"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.GROQ));
|
|
193
188
|
// Register Cohere provider
|
|
194
189
|
ProviderFactory.registerProvider(AIProviderName.COHERE, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
195
190
|
const cohereCreds = credentials;
|
|
196
191
|
const { CohereProvider } = await import("../providers/cohere.js");
|
|
197
192
|
return new CohereProvider(modelName, sdk, undefined, cohereCreds);
|
|
198
193
|
}, process.env.COHERE_MODEL || CohereModels.COMMAND_R_PLUS, ["cohere"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.COHERE));
|
|
199
|
-
// Register Together AI provider
|
|
200
|
-
ProviderFactory.registerProvider(AIProviderName.TOGETHER_AI, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
201
|
-
const togetherCreds = credentials;
|
|
202
|
-
const { TogetherAIProvider } = await import("../providers/togetherAi.js");
|
|
203
|
-
return new TogetherAIProvider(modelName, sdk, undefined, togetherCreds);
|
|
204
|
-
}, process.env.TOGETHER_MODEL ||
|
|
205
|
-
TogetherAIModels.LLAMA_3_3_70B_INSTRUCT_TURBO, ["together-ai", "together"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.TOGETHER_AI));
|
|
206
|
-
// Register Fireworks AI provider
|
|
207
|
-
ProviderFactory.registerProvider(AIProviderName.FIREWORKS, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
208
|
-
const fireworksCreds = credentials;
|
|
209
|
-
const { FireworksProvider } = await import("../providers/fireworks.js");
|
|
210
|
-
return new FireworksProvider(modelName, sdk, undefined, fireworksCreds);
|
|
211
|
-
}, process.env.FIREWORKS_MODEL || FireworksModels.DEEPSEEK_V4_PRO, ["fireworks"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.FIREWORKS));
|
|
212
|
-
// Register Perplexity provider
|
|
213
|
-
ProviderFactory.registerProvider(AIProviderName.PERPLEXITY, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
214
|
-
const perplexityCreds = credentials;
|
|
215
|
-
const { PerplexityProvider } = await import("../providers/perplexity.js");
|
|
216
|
-
return new PerplexityProvider(modelName, sdk, undefined, perplexityCreds);
|
|
217
|
-
}, process.env.PERPLEXITY_MODEL || PerplexityModels.SONAR, ["perplexity", "pplx"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.PERPLEXITY));
|
|
218
|
-
// Register Cloudflare Workers AI provider
|
|
219
|
-
ProviderFactory.registerProvider(AIProviderName.CLOUDFLARE, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
220
|
-
const cloudflareCreds = credentials;
|
|
221
|
-
const { CloudflareProvider } = await import("../providers/cloudflare.js");
|
|
222
|
-
return new CloudflareProvider(modelName, sdk, undefined, cloudflareCreds);
|
|
223
|
-
}, process.env.CLOUDFLARE_MODEL || CloudflareModels.LLAMA_3_3_70B_FAST, ["cloudflare", "workers-ai", "cf-ai"], PROVIDER_DESCRIPTORS_BY_NAME.get(AIProviderName.CLOUDFLARE));
|
|
224
194
|
// Register Voyage AI embeddings provider
|
|
225
195
|
ProviderFactory.registerProvider(AIProviderName.VOYAGE, async (modelName, _providerName, sdk, _region, credentials) => {
|
|
226
196
|
const voyageCreds = credentials;
|
|
@@ -2,6 +2,7 @@ import { logger } from "../utils/logger.js";
|
|
|
2
2
|
import { redactUrlCredentials } from "../utils/logSanitize.js";
|
|
3
3
|
import { getProviderModel, resolveOpenAICompatConfig, } from "../utils/providerConfig.js";
|
|
4
4
|
import { classifyProviderError } from "../utils/errorClassifier.js";
|
|
5
|
+
import { TimeoutError } from "../utils/timeout.js";
|
|
5
6
|
import { OpenAIChatCompletionsProvider } from "./openaiChatCompletionsBase.js";
|
|
6
7
|
/**
|
|
7
8
|
* Generic OpenAI-compatible provider driven entirely by an
|
|
@@ -51,9 +52,15 @@ export class ConfiguredOpenAICompatProvider extends OpenAIChatCompletionsProvide
|
|
|
51
52
|
return this.entry.fallbackModels;
|
|
52
53
|
}
|
|
53
54
|
formatProviderError(error) {
|
|
54
|
-
// classifyProviderError
|
|
55
|
-
//
|
|
56
|
-
//
|
|
55
|
+
// classifyProviderError hard-codes TimeoutError -> NetworkError ahead
|
|
56
|
+
// of any rule table and does not allow a per-provider override. An
|
|
57
|
+
// entry can opt out of that default via timeoutErrorClass (currently
|
|
58
|
+
// only Groq, reproducing its pre-migration subclass's own TimeoutError
|
|
59
|
+
// interception) — checked here, before ever reaching the shared
|
|
60
|
+
// classifier, so every other entry still gets its unmodified default.
|
|
61
|
+
if (error instanceof TimeoutError && this.entry.timeoutErrorClass) {
|
|
62
|
+
return new this.entry.timeoutErrorClass(`${this.entry.configOptions.providerName} request timed out: ${error.message}`, this.entry.providerName);
|
|
63
|
+
}
|
|
57
64
|
return classifyProviderError(error, this.entry.errorRules, this.entry.providerName, this.modelName);
|
|
58
65
|
}
|
|
59
66
|
}
|
|
@@ -49,17 +49,15 @@ export const OPENAI_COMPAT_CATALOG = [
|
|
|
49
49
|
GroqModels.LLAMA_3_2_90B_VISION_PREVIEW,
|
|
50
50
|
GroqModels.LLAMA_3_2_11B_VISION_PREVIEW,
|
|
51
51
|
],
|
|
52
|
-
//
|
|
53
|
-
//
|
|
54
|
-
//
|
|
55
|
-
//
|
|
56
|
-
//
|
|
57
|
-
//
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
|
|
61
|
-
// shape; the TimeoutError special case is a structural gap in
|
|
62
|
-
// ConfiguredOpenAICompatProvider, not a data error here.
|
|
52
|
+
// Groq's pre-migration subclass intercepted TimeoutError itself and
|
|
53
|
+
// returned a plain ProviderError, ahead of classifyProviderError's own
|
|
54
|
+
// non-overridable TimeoutError -> NetworkError default. Expressed here
|
|
55
|
+
// as data — see OpenAICompatCatalogEntry.timeoutErrorClass and
|
|
56
|
+
// ConfiguredOpenAICompatProvider.formatProviderError, which consults
|
|
57
|
+
// this field before ever delegating to the shared classifier. No other
|
|
58
|
+
// entry in this catalog sets it, so every other provider still gets
|
|
59
|
+
// the classifier's unmodified default.
|
|
60
|
+
timeoutErrorClass: ProviderError,
|
|
63
61
|
errorRules: [
|
|
64
62
|
{
|
|
65
63
|
match: (ctx) => ctx.statusCode === 401 ||
|
|
@@ -8,7 +8,7 @@ import type { ValidationSchema } from "./aliases.js";
|
|
|
8
8
|
import type { EnhancedGenerateResult, GenerateResult, TextGenerationOptions } from "./generate.js";
|
|
9
9
|
import type { MultimodalAudioEntry } from "./file.js";
|
|
10
10
|
import type { StreamOptions, StreamResult } from "./stream.js";
|
|
11
|
-
import type { ProviderErrorRule } from "./errors.js";
|
|
11
|
+
import type { ProviderError, ProviderErrorRule } from "./errors.js";
|
|
12
12
|
import type { ExternalMCPToolInfo } from "./externalMcp.js";
|
|
13
13
|
import type { ClaudeSubscriptionTier, AnthropicAuthMethod, AnthropicAuthConfig, SubscriptionInfo, OAuthToken } from "./subscription.js";
|
|
14
14
|
import type { Tool } from "./tools.js";
|
|
@@ -671,6 +671,20 @@ export type OpenAICompatCatalogEntry = {
|
|
|
671
671
|
* Task 4, so nothing actually mutates it at runtime.
|
|
672
672
|
*/
|
|
673
673
|
errorRules: ProviderErrorRule[];
|
|
674
|
+
/**
|
|
675
|
+
* Optional override for the Error subclass a TimeoutError should produce
|
|
676
|
+
* for this entry. classifyProviderError() hard-codes
|
|
677
|
+
* TimeoutError -> NetworkError unconditionally, ahead of any rule table,
|
|
678
|
+
* and does not make that mapping overridable per-provider (see
|
|
679
|
+
* errorClassifier.ts). Groq's pre-migration subclass predates that
|
|
680
|
+
* shared classifier and intercepted TimeoutError itself, returning a
|
|
681
|
+
* plain ProviderError instead — this field lets
|
|
682
|
+
* ConfiguredOpenAICompatProvider reproduce that one documented
|
|
683
|
+
* divergence as data (see its formatProviderError), rather than adding a
|
|
684
|
+
* class-level hook back in. Omit for every entry whose timeout should use
|
|
685
|
+
* the classifier's default (six of the seven catalog entries).
|
|
686
|
+
*/
|
|
687
|
+
timeoutErrorClass?: new (message: string, provider?: string) => ProviderError;
|
|
674
688
|
};
|
|
675
689
|
/** The subset of OpenAICompatCatalogEntry that resolveOpenAICompatConfig()
|
|
676
690
|
* needs — lets call sites pass a minimal object without the full catalog
|
|
@@ -43,7 +43,7 @@ export declare class AvatarError extends NeuroLinkError {
|
|
|
43
43
|
* Static processor managing the avatar handler registry.
|
|
44
44
|
*/
|
|
45
45
|
export declare class AvatarProcessor {
|
|
46
|
-
private static readonly
|
|
46
|
+
private static readonly registry;
|
|
47
47
|
/**
|
|
48
48
|
* Register an avatar handler for a specific provider.
|
|
49
49
|
*/
|
|
@@ -63,6 +63,10 @@ export declare class AvatarProcessor {
|
|
|
63
63
|
* already-registered primary handler when backfilling its aliases.
|
|
64
64
|
*/
|
|
65
65
|
static getHandler(providerName: string): AvatarHandler | undefined;
|
|
66
|
+
/**
|
|
67
|
+
* Clear all registered handlers (for testing).
|
|
68
|
+
*/
|
|
69
|
+
static clearHandlers(): void;
|
|
66
70
|
private static buildSpanAttributes;
|
|
67
71
|
/**
|
|
68
72
|
* Generate an avatar video via the registered handler.
|
|
@@ -13,6 +13,7 @@ import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
|
13
13
|
import { SpanSerializer, SpanStatus, SpanType, getMetricsAggregator, } from "../observability/index.js";
|
|
14
14
|
import { NeuroLinkError } from "./errorHandling.js";
|
|
15
15
|
import { logger } from "./logger.js";
|
|
16
|
+
import { HandlerRegistry } from "../core/handlerRegistry.js";
|
|
16
17
|
/**
|
|
17
18
|
* Avatar-specific error codes.
|
|
18
19
|
*/
|
|
@@ -47,38 +48,26 @@ export class AvatarError extends NeuroLinkError {
|
|
|
47
48
|
* Static processor managing the avatar handler registry.
|
|
48
49
|
*/
|
|
49
50
|
export class AvatarProcessor {
|
|
50
|
-
static
|
|
51
|
+
static registry = new HandlerRegistry("AvatarProcessor");
|
|
51
52
|
/**
|
|
52
53
|
* Register an avatar handler for a specific provider.
|
|
53
54
|
*/
|
|
54
55
|
static registerHandler(providerName, handler) {
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
}
|
|
58
|
-
if (!handler) {
|
|
59
|
-
throw new Error("Handler is required");
|
|
60
|
-
}
|
|
61
|
-
const key = providerName.toLowerCase();
|
|
62
|
-
if (this.handlers.has(key)) {
|
|
63
|
-
logger.warn(`[AvatarProcessor] Overwriting existing handler for provider: ${key}`);
|
|
64
|
-
}
|
|
65
|
-
this.handlers.set(key, handler);
|
|
56
|
+
const key = providerName ? providerName.toLowerCase() : providerName;
|
|
57
|
+
this.registry.register(providerName, handler);
|
|
66
58
|
logger.debug(`[AvatarProcessor] Registered avatar handler: ${key}`);
|
|
67
59
|
}
|
|
68
60
|
/**
|
|
69
61
|
* Check if a provider has a registered avatar handler.
|
|
70
62
|
*/
|
|
71
63
|
static supports(providerName) {
|
|
72
|
-
|
|
73
|
-
return false;
|
|
74
|
-
}
|
|
75
|
-
return this.handlers.has(providerName.toLowerCase());
|
|
64
|
+
return this.registry.supports(providerName);
|
|
76
65
|
}
|
|
77
66
|
/**
|
|
78
67
|
* List the names of all registered providers.
|
|
79
68
|
*/
|
|
80
69
|
static listProviders() {
|
|
81
|
-
return
|
|
70
|
+
return this.registry.list();
|
|
82
71
|
}
|
|
83
72
|
/**
|
|
84
73
|
* Get a registered avatar handler by provider name.
|
|
@@ -87,7 +76,13 @@ export class AvatarProcessor {
|
|
|
87
76
|
* already-registered primary handler when backfilling its aliases.
|
|
88
77
|
*/
|
|
89
78
|
static getHandler(providerName) {
|
|
90
|
-
return this.
|
|
79
|
+
return this.registry.get(providerName);
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clear all registered handlers (for testing).
|
|
83
|
+
*/
|
|
84
|
+
static clearHandlers() {
|
|
85
|
+
this.registry.clear();
|
|
91
86
|
}
|
|
92
87
|
static buildSpanAttributes(provider, options) {
|
|
93
88
|
return {
|
|
@@ -42,7 +42,7 @@ export declare class MusicError extends NeuroLinkError {
|
|
|
42
42
|
* Static processor managing the music handler registry.
|
|
43
43
|
*/
|
|
44
44
|
export declare class MusicProcessor {
|
|
45
|
-
private static readonly
|
|
45
|
+
private static readonly registry;
|
|
46
46
|
/**
|
|
47
47
|
* Register a music handler for a specific provider.
|
|
48
48
|
*/
|
|
@@ -62,6 +62,10 @@ export declare class MusicProcessor {
|
|
|
62
62
|
* already-registered primary handler when backfilling its aliases.
|
|
63
63
|
*/
|
|
64
64
|
static getHandler(providerName: string): MusicHandler | undefined;
|
|
65
|
+
/**
|
|
66
|
+
* Clear all registered handlers (for testing).
|
|
67
|
+
*/
|
|
68
|
+
static clearHandlers(): void;
|
|
65
69
|
private static buildSpanAttributes;
|
|
66
70
|
/**
|
|
67
71
|
* Generate a music track via the registered handler.
|
|
@@ -13,6 +13,7 @@ import { ErrorCategory, ErrorSeverity } from "../constants/enums.js";
|
|
|
13
13
|
import { SpanSerializer, SpanStatus, SpanType, getMetricsAggregator, } from "../observability/index.js";
|
|
14
14
|
import { NeuroLinkError } from "./errorHandling.js";
|
|
15
15
|
import { logger } from "./logger.js";
|
|
16
|
+
import { HandlerRegistry } from "../core/handlerRegistry.js";
|
|
16
17
|
/**
|
|
17
18
|
* Music-specific error codes.
|
|
18
19
|
*/
|
|
@@ -46,38 +47,26 @@ export class MusicError extends NeuroLinkError {
|
|
|
46
47
|
* Static processor managing the music handler registry.
|
|
47
48
|
*/
|
|
48
49
|
export class MusicProcessor {
|
|
49
|
-
static
|
|
50
|
+
static registry = new HandlerRegistry("MusicProcessor");
|
|
50
51
|
/**
|
|
51
52
|
* Register a music handler for a specific provider.
|
|
52
53
|
*/
|
|
53
54
|
static registerHandler(providerName, handler) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
}
|
|
57
|
-
if (!handler) {
|
|
58
|
-
throw new Error("Handler is required");
|
|
59
|
-
}
|
|
60
|
-
const key = providerName.toLowerCase();
|
|
61
|
-
if (this.handlers.has(key)) {
|
|
62
|
-
logger.warn(`[MusicProcessor] Overwriting existing handler for provider: ${key}`);
|
|
63
|
-
}
|
|
64
|
-
this.handlers.set(key, handler);
|
|
55
|
+
const key = providerName ? providerName.toLowerCase() : providerName;
|
|
56
|
+
this.registry.register(providerName, handler);
|
|
65
57
|
logger.debug(`[MusicProcessor] Registered music handler: ${key}`);
|
|
66
58
|
}
|
|
67
59
|
/**
|
|
68
60
|
* Check if a provider has a registered music handler.
|
|
69
61
|
*/
|
|
70
62
|
static supports(providerName) {
|
|
71
|
-
|
|
72
|
-
return false;
|
|
73
|
-
}
|
|
74
|
-
return this.handlers.has(providerName.toLowerCase());
|
|
63
|
+
return this.registry.supports(providerName);
|
|
75
64
|
}
|
|
76
65
|
/**
|
|
77
66
|
* List the names of all registered providers.
|
|
78
67
|
*/
|
|
79
68
|
static listProviders() {
|
|
80
|
-
return
|
|
69
|
+
return this.registry.list();
|
|
81
70
|
}
|
|
82
71
|
/**
|
|
83
72
|
* Get a registered music handler by provider name.
|
|
@@ -86,7 +75,13 @@ export class MusicProcessor {
|
|
|
86
75
|
* already-registered primary handler when backfilling its aliases.
|
|
87
76
|
*/
|
|
88
77
|
static getHandler(providerName) {
|
|
89
|
-
return this.
|
|
78
|
+
return this.registry.get(providerName);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Clear all registered handlers (for testing).
|
|
82
|
+
*/
|
|
83
|
+
static clearHandlers() {
|
|
84
|
+
this.registry.clear();
|
|
90
85
|
}
|
|
91
86
|
static buildSpanAttributes(provider, options) {
|
|
92
87
|
return {
|