UNPKG

@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

227 lines (226 loc) • 10.2 kB
/** * Single-JSON provider catalog — the authoring format for Tier-2 * (zero-quirk OpenAI-compatible) providers. One * src/lib/providers/catalog/<id>.json file per provider is the single * source of truth; see docs/superpowers/plans/2026-08-28-provider-json-catalog-spec.md. */ export type CatalogPricingPerMTok = { input: number; output: number; cachedInput?: number; }; export type CatalogModelStatus = "production" | "preview" | "retired"; /** * Descriptor-only per-provider turn-budget override — mirrors * ProviderDescriptor.timeouts field-for-field (src/lib/types/providers.ts). * Consumed only by buildCatalogDescriptor() (providerDescriptors.ts), never * by the OpenAI-compat runtime path (loader.ts's buildCatalogEntries()). * Optional and absent for every catalog provider except mistral, whose * value preserves its pre-migration hand-typed descriptor exactly. */ export type CatalogTimeouts = { generateMs?: number; streamMs?: number; }; export type CatalogModelSpec = { contextWindow?: number; maxOutputTokens?: number; pricingPerMTok?: CatalogPricingPerMTok; vision: boolean; status: CatalogModelStatus; description: string; /** * Enum member name override. Default is the derived constant-case of the * model id; REQUIRED where the derived name differs from a pre-existing * exported member (public-surface compatibility). */ enumMember?: string; }; export type CatalogWire = { baseURL?: string; baseURLTemplate?: string; extraCredentials?: string[]; missingCredentialMessage?: string; envOverrides?: { apiKey?: string; baseURL?: string; model?: string; }; /** Additional env vars validateApiKey() tries, in order, when the primary * apiKeyEnvVar is unset (e.g. HuggingFace's HF_TOKEN alongside * HUGGINGFACE_API_KEY). Consumed by buildCatalogConfigOptions() via * ProviderConfigOptions.fallbackEnvVars. */ apiKeyFallbackEnvVars?: string[]; }; export type CatalogErrorRuleClass = "authentication" | "rate-limit" | "invalid-model" | "network" | "provider"; export type CatalogErrorRuleJson = { status?: number; pattern?: string; /** Restrict the pattern to these HTTP statuses; status matching stays independent. */ patternStatuses?: number[]; class: CatalogErrorRuleClass; message: string; }; export type CatalogQuirks = { timeoutErrorClass?: "provider"; /** Vendor speaks OpenAI for chat but restricts how message content is * encoded. "string": `messages[].content` must be a plain string — * the content-parts array and the `null` OpenAI uses on an assistant * message with tool_calls are both rejected with HTTP 400. Normalized by * ConfiguredOpenAICompatProvider so tool round-trips work. */ messageContentFormat?: "string"; registryDefaultIgnoresModelEnvVar?: boolean; /** Vendor rejects `response_format: { type: "json_schema" }` outright but * accepts `{ type: "json_object" }`. Normalized by * ConfiguredOpenAICompatProvider so `generate({ schema })` keeps working * (mirrors the pre-catalog `supportsStructuredOutputs: false` behavior). */ responseFormatDowngrade?: "json-schema-to-json-object"; /** Vendor wants each assistant turn's `reasoning_content` sent back on * every later request of the conversation (DeepSeek documents a 400 * without it once tools are in play). ConfiguredOpenAICompatProvider * turns on the replay; every other provider leaves the field off. */ replayReasoningContent?: boolean; /** Vendor's chat-completions endpoint authenticates with a vendor-specific * header instead of the OpenAI-standard `Authorization: Bearer <key>`. * "x-api-key": send `X-Api-Key: <key>` and omit Authorization entirely — * Reka's OpenAPI spec declares this as its one security scheme (the * OpenAI-SDK-style examples elsewhere in its docs pass the key through a * client that still emits this header under the hood). Normalized by * ConfiguredOpenAICompatProvider.getAuthHeaders(); omitted means the * inherited Bearer default. */ authHeaderStyle?: "x-api-key"; }; export type CatalogBillingPolicy = "free-tier" | "free-with-card" | "no-free-tier"; export type CatalogSetup = { url: string; apiKeyFormat: string | null; billingPolicy: CatalogBillingPolicy; instructions: string[]; /** * Config-options description shown to callers for this credential. * Default: "API key". Set explicitly where the legacy entry's * description carries real information a generic "API key" loses * (e.g. Cloudflare's "API token (Workers AI Read+Write scope)"). */ description?: string; }; export type CatalogProbeEvidence = { date: string; status?: number; code?: string; method?: string; }; export type CatalogEvidence = { rosterVerified: CatalogProbeEvidence; authProbe?: CatalogProbeEvidence; billingProbe?: CatalogProbeEvidence; liveMatrix: { date: string; result: string; } | null; addedInPR: string; }; export type CatalogCapabilities = { text: boolean; streaming: boolean; /** "model-dependent" when tool support varies per served model and the * vendor doesn't reject `tools` for unsupported ones (the model just * never emits tool_calls) — e.g. HuggingFace's router. Maps to * ProviderDescriptor.toolSupport's own "model-dependent" member and * leaves OpenAICompatCatalogEntry.supportsTools unset so * ConfiguredOpenAICompatProvider falls through to the model-registry * default, exactly like an entry that never set supportsTools at all. */ tools: boolean | "model-dependent"; toolsWithStreaming: boolean; structuredOutput: boolean; /** * Whether a live wire probe proved the vendor accepts native tool * definitions and `response_format` in the SAME request (a 200, not a * schema/tools conflict error). Maps to * OpenAICompatCatalogEntry.supportsStructuredOutputWithTools; `true` lets * ConfiguredOpenAICompatProvider send both instead of suppressing * `response_format` on any request carrying tools (the conservative * default for an unknown endpoint). Only an explicit `true` opts in — * `false` is the same conservative behavior as leaving it unset. */ structuredOutputWithTools: boolean; embeddings: boolean; thinking: boolean; }; export type ProviderCatalogJson = { /** Editor-only pointer to provider-catalog.schema.json — accepted and ignored. */ $schema?: string; id: string; displayName: string; /** * Exported <Name>Models enum name override. Default: PascalCase(id) + * "Models". REQUIRED where the derived name differs from a pre-existing * export ("together-ai" derives "TogetherAiModels"; the legacy export is * "TogetherAIModels"). */ enumTypeName?: string; /** * NeurolinkCredentials key override. Default: toCamelCase(id). REQUIRED * where the derived key differs from a pre-existing public credential * field ("together-ai" derives "togetherAi"; the shipped public key is * "together" — renaming it would break any caller passing * `credentials: { together: {...} } }`, a public API break rule 5 * forbids). */ credentialsKey?: string; aliases: string[]; tier: 2; wire: CatalogWire; models: { default: string; fallbacks: string[]; /** Default: fallbacks[1] ?? fallbacks[0]. Set explicitly where the * legacy entry differs (behavior preservation — e.g. Groq). */ fallbackModelName?: string; /** Default: models.default. Set explicitly where the legacy entry's * registry-level default differs (behavior preservation — Mistral's * registryDefaultModel is MISTRAL_LARGE_LATEST while its defaultModel * is not). Must be a models.catalog key (validated). */ registryDefaultModel?: string; defaultContextWindow: number; defaultMaxOutputTokens: number; catalog: Record<string, CatalogModelSpec>; /** Ordered curated subset of `catalog` keys for wizard/choice surfaces * (e.g. the CLI setup wizard's top-N model picker). When absent, choice * surfaces fall back to the full catalog in file order. */ topModels?: string[]; /** The live-verified vision-capable model for capability tests, for * providers whose `default` model is text-only. Must be a * models.catalog key with vision: true (validated). When absent, the * first vision:true model in `catalog` file order is used. */ visionModel?: string; /** The live-verified model the capability matrix drives, for providers * whose `default` is retired upstream or gated off the testing account * (Fireworks serverless deployment, Groq's roster purges). May name a * model outside `catalog` — current account reality, not transcribed * history. When absent, the matrix drives `default`. Never affects the * runtime default. */ testModel?: string; }; capabilities: CatalogCapabilities; errorRules: CatalogErrorRuleJson[]; quirks?: CatalogQuirks; /** * Descriptor-only generate/stream turn-budget override — see * CatalogTimeouts. Absent = buildCatalogDescriptor() omits * ProviderDescriptor.timeouts entirely, matching every catalog provider's * behavior before this field existed. */ timeouts?: CatalogTimeouts; /** * Descriptor-only ascending auto-select priority override — mirrors * ProviderDescriptor.autoSelectPriority field-for-field (lower = tried * first in getBestProvider()'s fallback chain). Absent = not part of the * auto-select chain, matching every catalog provider's behavior before * this field existed (only mistral sets it today, preserving its * pre-migration hand-typed value). */ autoSelectPriority?: number; setup: CatalogSetup; evidence: CatalogEvidence; };