@juspay/neurolink
Version:
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
131 lines (130 loc) • 6.03 kB
TypeScript
/**
* Model Registry for NeuroLink CLI Commands
* Provides centralized model data for models command system
* Part of Phase 4.1 - Models Command System
*/
import { AIProviderName } from "../constants/enums.js";
import type { ClaudeDisabledThinkingReplacement, JsonValue, ModelCapabilities, ModelInfo } from "../types/index.js";
/**
* Public MODEL_REGISTRY: the manifest-derived entries merged over the
* hand-authored LEGACY_MODEL_REGISTRY base. Spread order matters — manifest
* entries are spread last, so a manifest-priced model wins outright
* (whole-entry replacement, not a per-field merge) over a legacy row with
* the same id. Any legacy id the manifest doesn't also price (no
* pricingPerMTok, or no manifest entry at all — e.g. AnthropicModels.
* CLAUDE_OPUS_5/CLAUDE_FABLE_5, which have no manifest counterpart yet)
* passes through unchanged, which is what keeps resolveSamplingParams/
* modelSupportsSamplingParams behaviour identical for those "non-manifest"
* models: their capabilities.samplingParams (or absence of it) is untouched.
*/
export declare const MODEL_REGISTRY: Record<string, ModelInfo>;
/**
* Model aliases registry for quick resolution
*/
export declare const MODEL_ALIASES: Record<string, string>;
/**
* Use case to model mappings
*/
export declare const USE_CASE_RECOMMENDATIONS: Record<string, string[]>;
/**
* Get all models
*/
export declare function getAllModels(): ModelInfo[];
/**
* Get model by ID
*/
export declare function getModelById(id: string): ModelInfo | undefined;
/**
* Resolve a registry alias to the canonical model id for a given provider.
*
* The registry has carried per-model aliases ("gpt4o" -> "gpt-4o", "gpt4" ->
* "gpt-4") all along, and capability lookups like {@link modelSupports}
* already resolve through them — but the id actually sent to the provider did
* not, so `generate({ model: "gpt4o" })` put the alias on the wire and the
* provider 404'd. This closes that gap (#337).
*
* Deliberately conservative, because a wrong rewrite is worse than no rewrite:
*
* - An id the registry already knows is returned untouched, so a canonical id
* can never be displaced by an alias that happens to collide with it.
* - An alias is only applied when the model it names belongs to the provider
* being constructed. Without that check, an aggregator or self-hosted
* deployment whose model is literally named "gpt4" would be silently
* rewritten to OpenAI's "gpt-4".
* - Anything unrecognised passes through, so custom and brand-new model ids
* keep working exactly as before.
*
* @param provider - Provider being constructed (canonical name)
* @param model - Model id or alias as the caller supplied it
* @returns The canonical id when an alias resolved, otherwise null
*/
export declare function resolveProviderModelAlias(provider: string, model: string): string | null;
/**
* Check whether a model supports a registered capability.
*
* Aliases resolve to their canonical model ID before the provider is
* cross-checked. Unknown provider/model pairs default to supported so new or
* custom models retain the existing behavior until capability data is added.
*/
export declare function modelSupports(capability: keyof ModelCapabilities, provider: string, model: string): boolean;
/**
* Whether a model accepts classic sampling parameters
* (`temperature` / `topP`).
*
* Resolution order: an explicit `capabilities.samplingParams` on a matching
* registry entry wins; otherwise the known rejecting-family patterns decide.
* Unknown models default to supported (same fail-open contract as
* `modelSupports`). Providers strip the parameters — including on
* retry/fallback request rebuilds — when this returns false.
*/
export declare function modelSupportsSamplingParams(provider: string, model: string | undefined): boolean;
/**
* Sampling params to actually send for a model: passthrough when supported,
* `{}` (with a debug log) when the model rejects them. Apply at every
* request-build site, including retry/fallback rebuilds.
*/
export declare function resolveSamplingParams(provider: string, model: string | undefined, params: {
temperature?: number;
topP?: number;
}, site: string): {
temperature?: number;
topP?: number;
};
/**
* Whether a Claude model accepts a forced `tool_choice` (`any` or a named
* `tool`). Unknown models default to accepting it.
*/
export declare function modelSupportsForcedToolChoice(model: string | undefined): boolean;
/**
* What to send instead of `thinking: {type: "disabled"}` to a Claude model.
* `between_tools` is refused at `xhigh` and `max` effort, so those fall back
* to adaptive thinking (`omit`).
*/
export declare function claudeDisabledThinkingReplacement(model: string | undefined, effort: string | undefined): ClaudeDisabledThinkingReplacement;
/**
* Get models by provider
*/
export declare function getModelsByProvider(provider: AIProviderName): ModelInfo[];
/**
* Get available providers.
*
* Deliberately does NOT derive from MODEL_REGISTRY membership: a registry
* keyed only by "real, priced, named models" under-reports providers whose
* manifest carries only a `_default` entry (the minimal-tier providers —
* e.g. voyage, jina, stability — have no priced named model and so
* contribute zero MODEL_REGISTRY rows). Reading getAllManifestProviders()
* directly gives every provider NeuroLink actually knows a manifest for,
* decoupled from MODEL_REGISTRY membership entirely. Manifest keys are
* literally the AIProviderName enum's kebab-case values by construction
* (see manifestRegistry.ts), so the cast is a same-value relabel, not a
* narrowing assumption.
*/
export declare function getAvailableProviders(): AIProviderName[];
/**
* Calculate estimated cost for a request
*/
export declare function calculateCost(model: ModelInfo, input: number, output: number): number;
/**
* Format model for display
*/
export declare function formatModelForDisplay(model: ModelInfo): JsonValue;