@juspay/neurolink 11.26.2 → 11.28.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 +3 -3
- package/dist/adapters/providerImageAdapter.js +20 -0
- package/dist/adapters/video/index.d.ts +30 -0
- package/dist/adapters/video/index.js +74 -0
- package/dist/avatar/index.d.ts +6 -3
- package/dist/avatar/index.js +21 -16
- package/dist/browser/neurolink.min.js +393 -393
- package/dist/cli/factories/commandFactory.d.ts +6 -0
- package/dist/cli/factories/commandFactory.js +6 -2
- package/dist/constants/contextWindows.d.ts +18 -4
- package/dist/constants/contextWindows.js +35 -4
- package/dist/core/baseProvider.js +5 -3
- package/dist/core/constants.js +59 -1
- package/dist/factories/mediaHandlerCatalog.d.ts +18 -0
- package/dist/factories/mediaHandlerCatalog.js +65 -0
- package/dist/factories/providerRegistry.js +50 -207
- package/dist/index.d.ts +1 -4
- package/dist/index.js +2 -5
- package/dist/models/anthropicModels.d.ts +3 -6
- package/dist/models/anthropicModels.js +97 -123
- package/dist/models/manifestRegistry.d.ts +9 -0
- package/dist/models/manifestRegistry.js +23 -0
- package/dist/models/manifests/anthropic.js +5 -3
- package/dist/models/manifests/azure.js +6 -1
- package/dist/models/modelRegistry.d.ts +22 -2
- package/dist/models/modelRegistry.js +143 -8
- package/dist/music/index.d.ts +6 -3
- package/dist/music/index.js +22 -21
- package/dist/neurolink.js +12 -0
- package/dist/providers/amazonSagemaker.d.ts +1 -1
- package/dist/providers/sagemaker/language-model.d.ts +2 -2
- package/dist/types/index.d.ts +1 -0
- package/dist/types/index.js +1 -0
- package/dist/types/mediaCatalog.d.ts +12 -0
- package/dist/types/mediaCatalog.js +7 -0
- package/dist/utils/pricing.js +51 -0
- package/dist/voice/index.d.ts +7 -3
- package/dist/voice/index.js +50 -40
- package/package.json +2 -1
|
@@ -105,6 +105,29 @@ function applyFamilyRules(manifest, model, base) {
|
|
|
105
105
|
* "llama3.2:latest" or OpenRouter's "openai/gpt-4o"), then undefined.
|
|
106
106
|
* Family rules are applied on top of whichever entry matched.
|
|
107
107
|
*/
|
|
108
|
+
/**
|
|
109
|
+
* Like resolveManifestEntryExact but WITHOUT the longest-prefix fallback:
|
|
110
|
+
* exact canonical id or declared alias only. For consumers where a prefix
|
|
111
|
+
* hit can steal precedence from a more-specific legacy row — boolean
|
|
112
|
+
* capability checks above all (a manifest "gpt-4" prefix match must never
|
|
113
|
+
* shadow the legacy table's explicit "gpt-4-vision-preview" vision row).
|
|
114
|
+
* Family rules still apply to a real match.
|
|
115
|
+
*/
|
|
116
|
+
export function resolveManifestEntryStrict(provider, model) {
|
|
117
|
+
const manifest = MANIFEST_REGISTRY[provider];
|
|
118
|
+
if (!manifest) {
|
|
119
|
+
return undefined;
|
|
120
|
+
}
|
|
121
|
+
const exact = manifest.models[model];
|
|
122
|
+
if (exact) {
|
|
123
|
+
return applyFamilyRules(manifest, model, exact);
|
|
124
|
+
}
|
|
125
|
+
const aliasMatch = Object.entries(manifest.models).find(([canonicalId, entry]) => canonicalId !== "_default" && entry.aliases.includes(model));
|
|
126
|
+
if (aliasMatch) {
|
|
127
|
+
return applyFamilyRules(manifest, model, aliasMatch[1]);
|
|
128
|
+
}
|
|
129
|
+
return undefined;
|
|
130
|
+
}
|
|
108
131
|
export function resolveManifestEntryExact(provider, model) {
|
|
109
132
|
const manifest = MANIFEST_REGISTRY[provider];
|
|
110
133
|
if (!manifest) {
|
|
@@ -28,9 +28,11 @@ export const anthropicManifest = {
|
|
|
28
28
|
displayName: "Claude Sonnet 5",
|
|
29
29
|
contextWindow: 1_000_000,
|
|
30
30
|
maxOutputTokens: 64_000,
|
|
31
|
-
// No pricingPerMTok:
|
|
32
|
-
//
|
|
33
|
-
//
|
|
31
|
+
// No pricingPerMTok DELIBERATELY: PRICING.anthropic carries real
|
|
32
|
+
// rates for this id, and findRates() is manifest-first with a legacy
|
|
33
|
+
// fallback — omitting the rate here defers to that table instead of
|
|
34
|
+
// duplicating it, and keeps this entry out of the manifest-derived
|
|
35
|
+
// MODEL_REGISTRY rows (which only admit priced entries).
|
|
34
36
|
vision: true,
|
|
35
37
|
functionCalling: true,
|
|
36
38
|
reasoning: true,
|
|
@@ -77,7 +77,12 @@ export const azureManifest = {
|
|
|
77
77
|
contextWindow: 200000,
|
|
78
78
|
maxOutputTokens: 32768,
|
|
79
79
|
pricingPerMTok: { input: 1.25, output: 10 },
|
|
80
|
-
|
|
80
|
+
// Azure publishes no such model (the registry row is deprecated for
|
|
81
|
+
// exactly that reason, modelRegistry.ts ~2550), and vision was
|
|
82
|
+
// deliberately removed from VISION_CAPABILITIES for it — this entry
|
|
83
|
+
// was generated from the registry BEFORE that fix and must not
|
|
84
|
+
// re-advertise a capability an undeployable id cannot have.
|
|
85
|
+
vision: false,
|
|
81
86
|
functionCalling: true,
|
|
82
87
|
reasoning: true,
|
|
83
88
|
jsonMode: true,
|
|
@@ -6,7 +6,16 @@
|
|
|
6
6
|
import { AIProviderName } from "../constants/enums.js";
|
|
7
7
|
import type { JsonValue, ModelCapabilities, ModelInfo } from "../types/index.js";
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
9
|
+
* Public MODEL_REGISTRY: the manifest-derived entries merged over the
|
|
10
|
+
* hand-authored LEGACY_MODEL_REGISTRY base. Spread order matters — manifest
|
|
11
|
+
* entries are spread last, so a manifest-priced model wins outright
|
|
12
|
+
* (whole-entry replacement, not a per-field merge) over a legacy row with
|
|
13
|
+
* the same id. Any legacy id the manifest doesn't also price (no
|
|
14
|
+
* pricingPerMTok, or no manifest entry at all — e.g. AnthropicModels.
|
|
15
|
+
* CLAUDE_OPUS_5/CLAUDE_FABLE_5, which have no manifest counterpart yet)
|
|
16
|
+
* passes through unchanged, which is what keeps resolveSamplingParams/
|
|
17
|
+
* modelSupportsSamplingParams behaviour identical for those "non-manifest"
|
|
18
|
+
* models: their capabilities.samplingParams (or absence of it) is untouched.
|
|
10
19
|
*/
|
|
11
20
|
export declare const MODEL_REGISTRY: Record<string, ModelInfo>;
|
|
12
21
|
/**
|
|
@@ -61,7 +70,18 @@ export declare function resolveSamplingParams(provider: string, model: string |
|
|
|
61
70
|
*/
|
|
62
71
|
export declare function getModelsByProvider(provider: AIProviderName): ModelInfo[];
|
|
63
72
|
/**
|
|
64
|
-
* Get available providers
|
|
73
|
+
* Get available providers.
|
|
74
|
+
*
|
|
75
|
+
* Deliberately does NOT derive from MODEL_REGISTRY membership: a registry
|
|
76
|
+
* keyed only by "real, priced, named models" under-reports providers whose
|
|
77
|
+
* manifest carries only a `_default` entry (the minimal-tier providers —
|
|
78
|
+
* e.g. voyage, jina, stability — have no priced named model and so
|
|
79
|
+
* contribute zero MODEL_REGISTRY rows). Reading getAllManifestProviders()
|
|
80
|
+
* directly gives every provider NeuroLink actually knows a manifest for,
|
|
81
|
+
* decoupled from MODEL_REGISTRY membership entirely. Manifest keys are
|
|
82
|
+
* literally the AIProviderName enum's kebab-case values by construction
|
|
83
|
+
* (see manifestRegistry.ts), so the cast is a same-value relabel, not a
|
|
84
|
+
* narrowing assumption.
|
|
65
85
|
*/
|
|
66
86
|
export declare function getAvailableProviders(): AIProviderName[];
|
|
67
87
|
/**
|
|
@@ -6,10 +6,15 @@
|
|
|
6
6
|
import { DEFAULT_MODEL_ALIASES } from "../types/index.js";
|
|
7
7
|
import { logger } from "../utils/logger.js";
|
|
8
8
|
import { AIProviderName, OpenAIModels, AzureOpenAIModels, GoogleAIModels, AnthropicModels, BedrockModels, MistralModels, OllamaModels, } from "../constants/enums.js";
|
|
9
|
+
import { getAllManifestProviders, getManifestForProvider, } from "./manifestRegistry.js";
|
|
9
10
|
/**
|
|
10
|
-
* Comprehensive model registry
|
|
11
|
+
* Comprehensive model registry — hand-authored base. Every id defined here
|
|
12
|
+
* that the manifest doesn't also carry a priced entry for stays exactly as
|
|
13
|
+
* authored below; see buildManifestDerivedEntries()/MODEL_REGISTRY's
|
|
14
|
+
* docblock further down for how the two are merged and why (Task 9, model
|
|
15
|
+
* metadata consolidation plan).
|
|
11
16
|
*/
|
|
12
|
-
|
|
17
|
+
const LEGACY_MODEL_REGISTRY = {
|
|
13
18
|
// OpenAI Models
|
|
14
19
|
[OpenAIModels.GPT_4O]: {
|
|
15
20
|
id: OpenAIModels.GPT_4O,
|
|
@@ -2450,6 +2455,129 @@ export const MODEL_REGISTRY = {
|
|
|
2450
2455
|
},
|
|
2451
2456
|
// Note: Azure models like O3, O4-mini, GPT-4o share IDs with OpenAI and use the OpenAI registry entries
|
|
2452
2457
|
};
|
|
2458
|
+
function deriveSpeed(id) {
|
|
2459
|
+
if (/mini|nano|haiku|flash|lite/i.test(id)) {
|
|
2460
|
+
return "fast";
|
|
2461
|
+
}
|
|
2462
|
+
if (/opus|^o1|^o3|-pro$/i.test(id)) {
|
|
2463
|
+
return "slow";
|
|
2464
|
+
}
|
|
2465
|
+
return "medium";
|
|
2466
|
+
}
|
|
2467
|
+
function deriveQuality(entry) {
|
|
2468
|
+
return entry.reasoning ? "high" : "medium";
|
|
2469
|
+
}
|
|
2470
|
+
/**
|
|
2471
|
+
* Builds the manifest-derived slice of MODEL_REGISTRY: every manifest model
|
|
2472
|
+
* that carries pricingPerMTok (ModelInfo.pricing is a required field, and
|
|
2473
|
+
* the manifest's pricingPerMTok is deliberately optional for un-priced
|
|
2474
|
+
* models like claude-sonnet-5 — see ProviderModelManifestEntry's docblock),
|
|
2475
|
+
* excluding each provider's synthetic "_default" entry.
|
|
2476
|
+
*
|
|
2477
|
+
* performance/useCases/category use entry.curated verbatim when present —
|
|
2478
|
+
* the ids that already had a hand-tuned LEGACY_MODEL_REGISTRY row before
|
|
2479
|
+
* this migration (5 Anthropic, 20 OpenAI) carry that exact triple forward
|
|
2480
|
+
* unchanged. Every other entry has no curated block and falls back to
|
|
2481
|
+
* mechanical derivation from the tracked capability flags.
|
|
2482
|
+
*/
|
|
2483
|
+
function buildManifestDerivedEntries() {
|
|
2484
|
+
const entries = {};
|
|
2485
|
+
for (const provider of getAllManifestProviders()) {
|
|
2486
|
+
const manifest = getManifestForProvider(provider);
|
|
2487
|
+
if (!manifest) {
|
|
2488
|
+
continue;
|
|
2489
|
+
}
|
|
2490
|
+
for (const [id, entry] of Object.entries(manifest.models)) {
|
|
2491
|
+
if (id === "_default" || !entry.pricingPerMTok) {
|
|
2492
|
+
continue;
|
|
2493
|
+
}
|
|
2494
|
+
// Keep-first on cross-manifest id collisions (Azure/OpenAI share ids):
|
|
2495
|
+
// getAllManifestProviders() order is deterministic, and silently
|
|
2496
|
+
// overwriting an earlier provider's row would make "which provider owns
|
|
2497
|
+
// this id" depend on iteration order.
|
|
2498
|
+
if (entries[id]) {
|
|
2499
|
+
logger.debug(`[modelRegistry] Manifest id collision: "${id}" already derived from ${entries[id].provider}; keeping first, skipping ${provider}`);
|
|
2500
|
+
continue;
|
|
2501
|
+
}
|
|
2502
|
+
const reasoningScore = entry.reasoning ? 9 : 6;
|
|
2503
|
+
const legacyRow = LEGACY_MODEL_REGISTRY[id];
|
|
2504
|
+
entries[id] = {
|
|
2505
|
+
id,
|
|
2506
|
+
name: entry.displayName ?? id,
|
|
2507
|
+
provider: provider,
|
|
2508
|
+
description: entry.displayName ?? id,
|
|
2509
|
+
capabilities: {
|
|
2510
|
+
vision: entry.vision,
|
|
2511
|
+
functionCalling: entry.functionCalling,
|
|
2512
|
+
codeGeneration: true,
|
|
2513
|
+
reasoning: entry.reasoning ?? false,
|
|
2514
|
+
multimodal: entry.vision || entry.nativeAudio === true,
|
|
2515
|
+
streaming: true,
|
|
2516
|
+
jsonMode: entry.jsonMode ?? false,
|
|
2517
|
+
samplingParams: entry.samplingParams,
|
|
2518
|
+
},
|
|
2519
|
+
pricing: {
|
|
2520
|
+
inputCostPer1K: entry.pricingPerMTok.input / 1000,
|
|
2521
|
+
outputCostPer1K: entry.pricingPerMTok.output / 1000,
|
|
2522
|
+
currency: "USD",
|
|
2523
|
+
},
|
|
2524
|
+
performance: entry.curated?.performance ?? {
|
|
2525
|
+
speed: deriveSpeed(id),
|
|
2526
|
+
quality: deriveQuality(entry),
|
|
2527
|
+
accuracy: deriveQuality(entry),
|
|
2528
|
+
},
|
|
2529
|
+
limits: {
|
|
2530
|
+
maxContextTokens: entry.contextWindow,
|
|
2531
|
+
maxOutputTokens: entry.maxOutputTokens,
|
|
2532
|
+
// Rate limits are operational knowledge the manifests don't track;
|
|
2533
|
+
// carry the hand-authored value forward rather than dropping it.
|
|
2534
|
+
...(legacyRow?.limits?.maxRequestsPerMinute !== undefined
|
|
2535
|
+
? { maxRequestsPerMinute: legacyRow.limits.maxRequestsPerMinute }
|
|
2536
|
+
: {}),
|
|
2537
|
+
},
|
|
2538
|
+
useCases: entry.curated?.useCases ?? {
|
|
2539
|
+
coding: entry.functionCalling ? 8 : 5,
|
|
2540
|
+
creative: entry.vision ? 7 : 6,
|
|
2541
|
+
analysis: reasoningScore,
|
|
2542
|
+
conversation: 7,
|
|
2543
|
+
reasoning: reasoningScore,
|
|
2544
|
+
translation: 6,
|
|
2545
|
+
summarization: 7,
|
|
2546
|
+
},
|
|
2547
|
+
aliases: entry.aliases,
|
|
2548
|
+
// Deprecation and release dates are editorial facts the manifests do
|
|
2549
|
+
// not track — a manifest-priced model must not silently un-deprecate
|
|
2550
|
+
// a row the hand-authored registry explicitly flagged.
|
|
2551
|
+
deprecated: legacyRow?.deprecated ?? false,
|
|
2552
|
+
...(legacyRow?.releaseDate !== undefined
|
|
2553
|
+
? { releaseDate: legacyRow.releaseDate }
|
|
2554
|
+
: {}),
|
|
2555
|
+
isLocal: provider === "ollama" ||
|
|
2556
|
+
provider === "lm-studio" ||
|
|
2557
|
+
provider === "llamacpp",
|
|
2558
|
+
category: entry.curated?.category ??
|
|
2559
|
+
(entry.reasoning ? "reasoning" : "general"),
|
|
2560
|
+
};
|
|
2561
|
+
}
|
|
2562
|
+
}
|
|
2563
|
+
return entries;
|
|
2564
|
+
}
|
|
2565
|
+
/**
|
|
2566
|
+
* Public MODEL_REGISTRY: the manifest-derived entries merged over the
|
|
2567
|
+
* hand-authored LEGACY_MODEL_REGISTRY base. Spread order matters — manifest
|
|
2568
|
+
* entries are spread last, so a manifest-priced model wins outright
|
|
2569
|
+
* (whole-entry replacement, not a per-field merge) over a legacy row with
|
|
2570
|
+
* the same id. Any legacy id the manifest doesn't also price (no
|
|
2571
|
+
* pricingPerMTok, or no manifest entry at all — e.g. AnthropicModels.
|
|
2572
|
+
* CLAUDE_OPUS_5/CLAUDE_FABLE_5, which have no manifest counterpart yet)
|
|
2573
|
+
* passes through unchanged, which is what keeps resolveSamplingParams/
|
|
2574
|
+
* modelSupportsSamplingParams behaviour identical for those "non-manifest"
|
|
2575
|
+
* models: their capabilities.samplingParams (or absence of it) is untouched.
|
|
2576
|
+
*/
|
|
2577
|
+
export const MODEL_REGISTRY = {
|
|
2578
|
+
...LEGACY_MODEL_REGISTRY,
|
|
2579
|
+
...buildManifestDerivedEntries(),
|
|
2580
|
+
};
|
|
2453
2581
|
/**
|
|
2454
2582
|
* Model aliases registry for quick resolution
|
|
2455
2583
|
*/
|
|
@@ -2644,14 +2772,21 @@ export function getModelsByProvider(provider) {
|
|
|
2644
2772
|
return Object.values(MODEL_REGISTRY).filter((model) => model.provider === provider);
|
|
2645
2773
|
}
|
|
2646
2774
|
/**
|
|
2647
|
-
* Get available providers
|
|
2775
|
+
* Get available providers.
|
|
2776
|
+
*
|
|
2777
|
+
* Deliberately does NOT derive from MODEL_REGISTRY membership: a registry
|
|
2778
|
+
* keyed only by "real, priced, named models" under-reports providers whose
|
|
2779
|
+
* manifest carries only a `_default` entry (the minimal-tier providers —
|
|
2780
|
+
* e.g. voyage, jina, stability — have no priced named model and so
|
|
2781
|
+
* contribute zero MODEL_REGISTRY rows). Reading getAllManifestProviders()
|
|
2782
|
+
* directly gives every provider NeuroLink actually knows a manifest for,
|
|
2783
|
+
* decoupled from MODEL_REGISTRY membership entirely. Manifest keys are
|
|
2784
|
+
* literally the AIProviderName enum's kebab-case values by construction
|
|
2785
|
+
* (see manifestRegistry.ts), so the cast is a same-value relabel, not a
|
|
2786
|
+
* narrowing assumption.
|
|
2648
2787
|
*/
|
|
2649
2788
|
export function getAvailableProviders() {
|
|
2650
|
-
|
|
2651
|
-
Object.values(MODEL_REGISTRY).forEach((model) => {
|
|
2652
|
-
providers.add(model.provider);
|
|
2653
|
-
});
|
|
2654
|
-
return Array.from(providers);
|
|
2789
|
+
return getAllManifestProviders();
|
|
2655
2790
|
}
|
|
2656
2791
|
/**
|
|
2657
2792
|
* Calculate estimated cost for a request
|
package/dist/music/index.d.ts
CHANGED
|
@@ -7,9 +7,12 @@
|
|
|
7
7
|
* Use `MusicProcessor.generate(provider, options)` to dispatch to the
|
|
8
8
|
* registered handler for `provider`.
|
|
9
9
|
*
|
|
10
|
-
* Importing this module
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Importing this module does NOT register any handlers as a side effect.
|
|
11
|
+
* Call `registerDefaultMusicHandlers()` explicitly (or go through
|
|
12
|
+
* `ProviderRegistry.registerAllProviders()`, which every documented
|
|
13
|
+
* `NeuroLink` entry point already calls) to register every shipped music
|
|
14
|
+
* handler whose backing API key is present in `process.env`. Registration
|
|
15
|
+
* is idempotent and silently skipped if a provider is already registered or
|
|
13
16
|
* its constructor throws (e.g. missing optional native dependency).
|
|
14
17
|
*
|
|
15
18
|
* @module music
|
package/dist/music/index.js
CHANGED
|
@@ -7,13 +7,17 @@
|
|
|
7
7
|
* Use `MusicProcessor.generate(provider, options)` to dispatch to the
|
|
8
8
|
* registered handler for `provider`.
|
|
9
9
|
*
|
|
10
|
-
* Importing this module
|
|
11
|
-
*
|
|
12
|
-
*
|
|
10
|
+
* Importing this module does NOT register any handlers as a side effect.
|
|
11
|
+
* Call `registerDefaultMusicHandlers()` explicitly (or go through
|
|
12
|
+
* `ProviderRegistry.registerAllProviders()`, which every documented
|
|
13
|
+
* `NeuroLink` entry point already calls) to register every shipped music
|
|
14
|
+
* handler whose backing API key is present in `process.env`. Registration
|
|
15
|
+
* is idempotent and silently skipped if a provider is already registered or
|
|
13
16
|
* its constructor throws (e.g. missing optional native dependency).
|
|
14
17
|
*
|
|
15
18
|
* @module music
|
|
16
19
|
*/
|
|
20
|
+
import { MEDIA_HANDLER_CATALOG } from "../factories/mediaHandlerCatalog.js";
|
|
17
21
|
import { logger } from "../utils/logger.js";
|
|
18
22
|
import { MusicProcessor } from "../utils/musicProcessor.js";
|
|
19
23
|
export { MUSIC_ERROR_CODES, MusicError, MusicProcessor, } from "../utils/musicProcessor.js";
|
|
@@ -31,20 +35,21 @@ import { BeatovenMusic } from "./providers/BeatovenMusic.js";
|
|
|
31
35
|
import { ElevenLabsMusic } from "./providers/ElevenLabsMusic.js";
|
|
32
36
|
import { LyriaMusic } from "./providers/LyriaMusic.js";
|
|
33
37
|
import { ReplicateMusic } from "./providers/ReplicateMusic.js";
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
}
|
|
47
|
-
|
|
38
|
+
// Provider names + aliases are the Task-8 catalog's job — only the factory
|
|
39
|
+
// (which needs the imported handler class) stays local to this module.
|
|
40
|
+
const MUSIC_HANDLER_FACTORIES = {
|
|
41
|
+
beatoven: () => new BeatovenMusic(),
|
|
42
|
+
"elevenlabs-music": () => new ElevenLabsMusic(),
|
|
43
|
+
lyria: () => new LyriaMusic(),
|
|
44
|
+
replicate: () => new ReplicateMusic(),
|
|
45
|
+
};
|
|
46
|
+
const MUSIC_HANDLER_CANDIDATES = MEDIA_HANDLER_CATALOG.filter((entry) => entry.kind === "music").map((entry) => {
|
|
47
|
+
const factory = MUSIC_HANDLER_FACTORIES[entry.name];
|
|
48
|
+
if (!factory) {
|
|
49
|
+
throw new Error(`[music] no handler factory for catalog entry "${entry.name}"`);
|
|
50
|
+
}
|
|
51
|
+
return { name: entry.name, aliases: entry.aliases, factory };
|
|
52
|
+
});
|
|
48
53
|
/**
|
|
49
54
|
* Register every shipped music handler whose backing credentials are
|
|
50
55
|
* present in the environment. Safe to call multiple times — existing
|
|
@@ -87,7 +92,3 @@ export function registerDefaultMusicHandlers() {
|
|
|
87
92
|
}
|
|
88
93
|
}
|
|
89
94
|
}
|
|
90
|
-
// Run once at module import so consumers who follow the documented
|
|
91
|
-
// `nl.generate(...)` flow get every configured handler without manually
|
|
92
|
-
// calling `registerHandler`.
|
|
93
|
-
registerDefaultMusicHandlers();
|
package/dist/neurolink.js
CHANGED
|
@@ -4382,6 +4382,13 @@ Current user's request: ${currentInput}`;
|
|
|
4382
4382
|
if (!providerName) {
|
|
4383
4383
|
throw new Error('output.music.provider is required (e.g. "beatoven", "elevenlabs-music", "lyria", "replicate").');
|
|
4384
4384
|
}
|
|
4385
|
+
// This early-dispatch path never creates an AI provider, so
|
|
4386
|
+
// ProviderRegistry.registerAllProviders() has NOT necessarily run —
|
|
4387
|
+
// with the module-scope auto-registration retired, the handlers must
|
|
4388
|
+
// be registered here explicitly. registerDefaultMusicHandlers() is
|
|
4389
|
+
// idempotent (skip-if-registered), so the repeat call is free.
|
|
4390
|
+
const { registerDefaultMusicHandlers } = await import("./music/index.js");
|
|
4391
|
+
registerDefaultMusicHandlers();
|
|
4385
4392
|
const { MusicProcessor } = await import("./utils/musicProcessor.js");
|
|
4386
4393
|
const musicResult = await MusicProcessor.generate(providerName, {
|
|
4387
4394
|
...musicOptions,
|
|
@@ -4414,6 +4421,11 @@ Current user's request: ${currentInput}`;
|
|
|
4414
4421
|
if (!providerName) {
|
|
4415
4422
|
throw new Error('output.avatar.provider is required (e.g. "d-id", "heygen", "replicate").');
|
|
4416
4423
|
}
|
|
4424
|
+
// Same early-dispatch registration as generateWithMusic above: no AI
|
|
4425
|
+
// provider is created on this path, so the retired module-scope
|
|
4426
|
+
// auto-run must be replaced by an explicit (idempotent) call here.
|
|
4427
|
+
const { registerDefaultAvatarHandlers } = await import("./avatar/index.js");
|
|
4428
|
+
registerDefaultAvatarHandlers();
|
|
4417
4429
|
const { AvatarProcessor } = await import("./utils/avatarProcessor.js");
|
|
4418
4430
|
const avatarResult = await AvatarProcessor.generate(providerName, avatarOptions);
|
|
4419
4431
|
generateSpan.setAttribute("neurolink.avatar.provider", providerName);
|
|
@@ -91,7 +91,7 @@ export declare class AmazonSageMakerProvider extends BaseProvider {
|
|
|
91
91
|
provider: string;
|
|
92
92
|
specificationVersion: "v2";
|
|
93
93
|
endpointName: string;
|
|
94
|
-
modelType: "huggingface" | "mistral" | "custom" | "
|
|
94
|
+
modelType: "huggingface" | "mistral" | "custom" | "llama" | "claude" | "jumpstart" | undefined;
|
|
95
95
|
region: string;
|
|
96
96
|
} | {
|
|
97
97
|
capabilities: {
|
|
@@ -153,7 +153,7 @@ export declare class SageMakerLanguageModel implements SageMakerAsLanguageModel
|
|
|
153
153
|
provider: string;
|
|
154
154
|
specificationVersion: "v2";
|
|
155
155
|
endpointName: string;
|
|
156
|
-
modelType: "huggingface" | "mistral" | "custom" | "
|
|
156
|
+
modelType: "huggingface" | "mistral" | "custom" | "llama" | "claude" | "jumpstart" | undefined;
|
|
157
157
|
region: string;
|
|
158
158
|
};
|
|
159
159
|
/**
|
|
@@ -200,7 +200,7 @@ export declare class SageMakerLanguageModel implements SageMakerAsLanguageModel
|
|
|
200
200
|
provider: string;
|
|
201
201
|
specificationVersion: "v2";
|
|
202
202
|
endpointName: string;
|
|
203
|
-
modelType: "huggingface" | "mistral" | "custom" | "
|
|
203
|
+
modelType: "huggingface" | "mistral" | "custom" | "llama" | "claude" | "jumpstart" | undefined;
|
|
204
204
|
region: string;
|
|
205
205
|
};
|
|
206
206
|
}
|
package/dist/types/index.d.ts
CHANGED
|
@@ -79,6 +79,7 @@ export * from "./video.js";
|
|
|
79
79
|
export * from "./avatar.js";
|
|
80
80
|
export * from "./music.js";
|
|
81
81
|
export * from "./replicate.js";
|
|
82
|
+
export * from "./mediaCatalog.js";
|
|
82
83
|
export * from "./safeFetch.js";
|
|
83
84
|
export * from "./modelPool.js";
|
|
84
85
|
export * from "./requestRouter.js";
|
package/dist/types/index.js
CHANGED
|
@@ -85,6 +85,7 @@ export * from "./video.js";
|
|
|
85
85
|
export * from "./avatar.js";
|
|
86
86
|
export * from "./music.js";
|
|
87
87
|
export * from "./replicate.js";
|
|
88
|
+
export * from "./mediaCatalog.js";
|
|
88
89
|
// Safe-fetch helper types (SSRF-hardened download)
|
|
89
90
|
export * from "./safeFetch.js";
|
|
90
91
|
// ModelPool — multi-provider failover with per-member cooldown (M9.x+)
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types backing the static media-handler catalog
|
|
3
|
+
* (src/lib/factories/mediaHandlerCatalog.ts) — the single source of truth
|
|
4
|
+
* for provider names/aliases across the six media-generation ecosystems
|
|
5
|
+
* (TTS, STT, Realtime, Video, Avatar, Music).
|
|
6
|
+
*/
|
|
7
|
+
export type MediaHandlerKind = "tts" | "stt" | "realtime" | "video" | "avatar" | "music";
|
|
8
|
+
export type MediaHandlerDescriptor = {
|
|
9
|
+
readonly kind: MediaHandlerKind;
|
|
10
|
+
readonly name: string;
|
|
11
|
+
readonly aliases?: readonly string[];
|
|
12
|
+
};
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Types backing the static media-handler catalog
|
|
3
|
+
* (src/lib/factories/mediaHandlerCatalog.ts) — the single source of truth
|
|
4
|
+
* for provider names/aliases across the six media-generation ecosystems
|
|
5
|
+
* (TTS, STT, Realtime, Video, Avatar, Music).
|
|
6
|
+
*/
|
|
7
|
+
export {};
|
package/dist/utils/pricing.js
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { getManifestForProvider, resolveManifestEntryExact, } from "../models/manifestRegistry.js";
|
|
1
2
|
/**
|
|
2
3
|
* Per-token pricing data (USD per token). Updated Feb 2026.
|
|
3
4
|
* Sources:
|
|
@@ -728,6 +729,22 @@ function isVersionOnlySuffix(model, key) {
|
|
|
728
729
|
}
|
|
729
730
|
return VERSION_SUFFIX_RE.test(model.slice(key.length));
|
|
730
731
|
}
|
|
732
|
+
/**
|
|
733
|
+
* Whether `model` matches a provider manifest by the manifest's own
|
|
734
|
+
* canonical id or by one of its declared aliases — deliberately excludes
|
|
735
|
+
* resolveManifestEntryExact's longest-prefix fallback. See the call site in
|
|
736
|
+
* findRates for why the prefix path is unsafe to use for pricing precedence.
|
|
737
|
+
*/
|
|
738
|
+
function isManifestNamedMatch(provider, model) {
|
|
739
|
+
const manifest = getManifestForProvider(provider);
|
|
740
|
+
if (!manifest) {
|
|
741
|
+
return false;
|
|
742
|
+
}
|
|
743
|
+
if (Object.prototype.hasOwnProperty.call(manifest.models, model)) {
|
|
744
|
+
return true;
|
|
745
|
+
}
|
|
746
|
+
return Object.values(manifest.models).some((entry) => entry.aliases.includes(model));
|
|
747
|
+
}
|
|
731
748
|
function findRates(provider, model,
|
|
732
749
|
/**
|
|
733
750
|
* Set to true when the rates came from a literal table key rather than a
|
|
@@ -778,6 +795,40 @@ matchKind) {
|
|
|
778
795
|
const modelKey = stripped === "bedrock" || stripped === "amazonbedrock"
|
|
779
796
|
? model.replace(/^.*\banthropic\./, "")
|
|
780
797
|
: model;
|
|
798
|
+
// Manifest-backed exact/alias match takes precedence over legacy PRICING
|
|
799
|
+
// (see Task 8 of the model metadata consolidation plan). Deliberately
|
|
800
|
+
// gated to a NAMED match only (manifest's own id or a declared alias) —
|
|
801
|
+
// never resolveManifestEntryExact's longest-prefix fallback. The
|
|
802
|
+
// manifest's model set is coarser-grained than PRICING's for several
|
|
803
|
+
// live ids today (e.g. openai's manifest names only "gpt-5" while
|
|
804
|
+
// PRICING.openai carries distinct exact entries for
|
|
805
|
+
// gpt-5.1/5.4/5.5/5.6-sol/terra/luna); letting the manifest's prefix
|
|
806
|
+
// match run first would silently steal a more specific PRICING entry's
|
|
807
|
+
// rate — confirmed: resolveManifestEntryExact("openai", "gpt-5.4")
|
|
808
|
+
// prefix-matches onto the "gpt-5" entry, $1.25/$10 instead of the
|
|
809
|
+
// correct $2.5/$15. Everything the manifest doesn't name exactly or
|
|
810
|
+
// alias — including a named entry with no pricingPerMTok, e.g.
|
|
811
|
+
// claude-sonnet-5 — falls straight through to PRICING's unchanged
|
|
812
|
+
// exact+prefix match below, which is exactly "legacy PRICING as the
|
|
813
|
+
// fallback for entries the manifest lacks."
|
|
814
|
+
if (isManifestNamedMatch(normalizedProvider, modelKey)) {
|
|
815
|
+
const manifestEntry = resolveManifestEntryExact(normalizedProvider, modelKey);
|
|
816
|
+
if (manifestEntry?.pricingPerMTok) {
|
|
817
|
+
if (matchKind) {
|
|
818
|
+
matchKind.exact = true;
|
|
819
|
+
}
|
|
820
|
+
return {
|
|
821
|
+
input: manifestEntry.pricingPerMTok.input / 1_000_000,
|
|
822
|
+
output: manifestEntry.pricingPerMTok.output / 1_000_000,
|
|
823
|
+
cacheRead: manifestEntry.pricingPerMTok.cacheRead !== undefined
|
|
824
|
+
? manifestEntry.pricingPerMTok.cacheRead / 1_000_000
|
|
825
|
+
: undefined,
|
|
826
|
+
cacheCreation: manifestEntry.pricingPerMTok.cacheWrite !== undefined
|
|
827
|
+
? manifestEntry.pricingPerMTok.cacheWrite / 1_000_000
|
|
828
|
+
: undefined,
|
|
829
|
+
};
|
|
830
|
+
}
|
|
831
|
+
}
|
|
781
832
|
// Exact match
|
|
782
833
|
if (providerPricing[modelKey]) {
|
|
783
834
|
if (matchKind) {
|
package/dist/voice/index.d.ts
CHANGED
|
@@ -8,9 +8,13 @@
|
|
|
8
8
|
* Use STTProcessor (src/lib/utils/sttProcessor.ts) for STT.
|
|
9
9
|
* Use RealtimeProcessor for realtime voice sessions.
|
|
10
10
|
*
|
|
11
|
-
* Importing this module
|
|
12
|
-
*
|
|
13
|
-
*
|
|
11
|
+
* Importing this module does NOT register any handlers as a side effect.
|
|
12
|
+
* Call `registerDefaultTTSHandlers()` / `registerDefaultSTTHandlers()` /
|
|
13
|
+
* `registerDefaultRealtimeHandlers()` explicitly (or go through
|
|
14
|
+
* `ProviderRegistry.registerAllProviders()`, which every documented
|
|
15
|
+
* `NeuroLink` entry point already calls) to register every shipped handler
|
|
16
|
+
* whose backing API key is present in `process.env`. Registration is
|
|
17
|
+
* idempotent and silently skipped on failure.
|
|
14
18
|
*
|
|
15
19
|
* @module voice
|
|
16
20
|
*/
|