@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
98 lines (97 loc) • 4.99 kB
TypeScript
import type { DecisionError, DecisionModelCard, DecisionQuestion, DecisionState, NeurolinkCredentials } from "../types/index.js";
import { SystemOneDecisionProvider } from "./systemOneDecision.js";
/**
* The binding limit in practice: `state` plus the SINGLE LONGEST question.
* Measured by bisection at single-character resolution — 33,002 reported
* input tokens accepted, 33,003 not.
*/
export declare const TYPESAFE_MAX_STATE_TOKENS = 33000;
/**
* The separate, larger ceiling on `state` plus ALL questions combined. A
* request can carry a near-ceiling state *and* 400 extra questions (37,679
* tokens total, verified) — questions do not compete with state for the
* 33K budget, only for this one.
*/
export declare const TYPESAFE_MAX_REQUEST_TOKENS = 64000;
/**
* TypeSafe Provider — the `decide` inference type only.
*
* Jev is a "System One" model: it takes one `state` plus a map of typed
* questions and returns one typed answer each, evaluated in a single
* parallel pass. The request loop, retries, auth circuit breaker and answer
* parsing are shared with every decision provider in
* {@link SystemOneDecisionProvider}; this class holds only what is TypeSafe's.
*
* Its descriptor declares `inferenceKinds: ["decide"]`, which keeps it out
* of auto-select and the health sweep.
*
* Two measured properties shape the API: latency is flat in question count
* (1 question 393ms, 400 questions 465ms) while concurrent requests queue.
* Callers therefore batch every question into one `decide()` call.
*
* Two transports reach the same model. The direct one is TypeSafe's own API,
* billed against a TypeSafe key. The gateway one is Vercel's AI Gateway
* evaluation-model route, billed against a Vercel account — useful to a host
* that already has one and does not want a second vendor relationship. They
* differ on the wire (vocabulary, where the model is named, and where
* `confidence` is reported) and not at all in `DecisionResult`.
*
* @see https://docs.typesafe.ai/api
*/
export declare class TypeSafeProvider extends SystemOneDecisionProvider {
private readonly apiKey;
private readonly baseURL;
private readonly gatewayURL;
/** Which wire this instance speaks. Resolved once, in the constructor. */
private readonly transport;
constructor(modelName?: string, sdk?: unknown, _region?: string, credentials?: NeurolinkCredentials["typesafe"]);
protected getDefaultModel(): string;
protected vendorLabel(): string;
protected vendorDisplayName(): string;
protected decisionApiKey(): string;
protected missingKeyMessage(): string;
/**
* The gateway already speaks the neutral vocabulary this codebase uses, so
* only the direct transport needs the `noul` rename.
*/
protected encodeQuestion(question: DecisionQuestion): Record<string, unknown>;
/**
* The gateway names the model in a header and rejects a body that carries
* one; the direct API requires it in the body.
*/
protected buildDecisionBody(state: DecisionState, questions: Record<string, Record<string, unknown>>, model: string): Record<string, unknown>;
protected parseDecisionError(status: number, payload: unknown, requestId: string | undefined): DecisionError;
/**
* The gateway does not omit confidence after all — it RELOCATES it, to
* `providerMetadata.typesafe.confidence.<questionId>`, and leaves the answer
* objects themselves without one. Preferring it over the derived peak
* matters because the two disagree on any distribution that is not already
* near-certain, and the router's asymmetric bars are tuned against the
* vendor's calibrated figure, not against max(probabilities).
*/
protected reportedConfidence(payload: unknown): Record<string, number>;
protected readRequestId(headers: Headers): string | undefined;
protected diagnosticContext(): Record<string, unknown>;
/** Where a decision request goes for this instance's transport. */
protected decisionEndpoint(): string;
/**
* Headers for this instance's transport.
*
* The gateway's three `ai-*` headers are all load-bearing:
* `ai-gateway-protocol-version` omitted fails the request outright rather
* than defaulting, `ai-model-id` is how the model is named at all (the body
* carries no `model`), and `ai-evaluation-model-specification-version`
* selects the request/response shape this provider parses.
*/
protected decisionHeaders(): Record<string, string>;
/** Which transport this instance resolved to. Exposed for diagnostics. */
getDecisionTransport(): "direct" | "gateway";
/**
* The model aliases this key may send in `model`.
*
* Direct transport only: the gateway names the model in a header and
* publishes its own catalogue, so there is no equivalent listing behind
* this key.
*/
listDecisionModels(): Promise<DecisionModelCard[]>;
}