@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
111 lines (110 loc) • 5.66 kB
TypeScript
/**
* Peer-sharing admission policy.
*
* Pure evaluation, no I/O — every input is passed in, so this module is cheap on
* the hot path and directly exercisable from a test.
*
* The gate set is deliberately **orthogonal and AND-ed**: a grant may carry a
* headroom floor *and* a window-slice ceiling *and* a model allowlist, and each
* is checked independently. The effective allowance is therefore the minimum
* across whatever is configured, which is what lets "share only what I am not
* using, and never more than a fifth of it" be one grant rather than two
* competing modes.
*
* Evaluation splits in two, because the two halves answer different questions:
*
* - `evaluateShareAdmission` — request-level. Is this borrower allowed to ask at
* all, right now, for this model?
* - `filterAccountsForGrant` — account-level. Of the lender's accounts, which
* may serve this borrower? Headroom and slice ceilings live here because they
* are properties of an individual account's windows, not of the request.
*
* @module proxy/sharePolicy
*/
import type { ProxyShareAccountExclusion, ProxyShareAccountFilterResult, ProxyShareAccountView, ProxyShareAdmission, ProxyShareAdmissionInput, ProxyShareGates, ProxyShareGrant, ProxyShareRefusalReason, ProxyShareRefusedAdmission, ProxySharePoolUsage } from "../types/index.js";
/**
* Narrow an admission to its refusing half.
*
* A plain `!admission.admitted` check would do this under `strict`, but one of
* the package's build steps compiles without `strictNullChecks`, where TypeScript
* declines to narrow a boolean discriminant at all. An explicit predicate holds
* in both modes.
*/
export declare function isShareRefusal(admission: ProxyShareAdmission): admission is ProxyShareRefusedAdmission;
export declare function shareRefusalMessage(reason: ProxyShareRefusalReason): string;
/** HTTP status for a refusal. 401 is "who are you", 403 is "not you, not ever
* under this grant", 429 is "not now" — the borrower retries only the last. */
export declare function shareRefusalStatus(reason: ProxyShareRefusalReason): number;
/**
* Is `now` inside the grant's allowed hours?
*
* A window whose start hour is greater than its end hour wraps midnight
* (`21 → 9` means the night shift), which is the common case for lending
* capacity you are asleep through.
*/
export declare function isWithinSchedule(schedule: {
fromHour: number;
toHour: number;
}, now: number): boolean;
/**
* Does the requested model fall inside the allowlist?
*
* Entries are matched as case-insensitive substrings so a grant can name a tier
* (`sonnet`) rather than having to track every dated model id.
*/
export declare function isModelAllowed(models: string[] | undefined, model: string | undefined): boolean;
/**
* Request-level admission.
*
* Order matters: identity and lifecycle first (they are permanent refusals),
* then scope, then the transient limits that carry a `Retry-After`. A borrower
* that is told "paused" must not also be told "slow down".
*/
export declare function evaluateShareAdmission(input: ProxyShareAdmissionInput): ProxyShareAdmission;
/**
* Is the account inside its spillover window — close enough to a reset, with
* little enough consumed, that the remaining capacity would otherwise expire?
*
* Unknown reset times fail closed. A spillover grant is a promise about capacity
* that is *about to be lost*; without a reset time there is no such promise to
* keep, and guessing would hand out capacity the lender still intends to use.
*/
export declare function isSpilloverActive(gates: ProxyShareGates, account: ProxyShareAccountView, now: number): boolean;
/**
* Split the pool into the accounts this grant may draw on and the rest.
*
* An entry in `gates.accounts` matches either the full store key
* (`anthropic:alice`) or the bare label (`alice`), because operators think in
* labels and the routing path thinks in keys.
*
* Exported because the scope decides more than admission: it is also the
* denominator of the pool-wide slice, and computing that over accounts the grant
* can never touch would loosen the ceiling in proportion to how many there are.
*/
export declare function accountsInGrantScope(gates: ProxyShareGates, accounts: readonly ProxyShareAccountView[]): {
inScope: ProxyShareAccountView[];
outOfScope: ProxyShareAccountView[];
};
/**
* Decide which of the lender's accounts this grant may draw on.
*
* Returning exclusions alongside the survivors is deliberate: when nothing
* survives, the caller needs to say *why* — "your slice is spent" and "I am
* holding back my reserve" are different answers, and only one of them will
* change on its own.
*/
export declare function filterAccountsForGrant(grant: ProxyShareGrant, accounts: readonly ProxyShareAccountView[], now: number,
/**
* Required, not optional. `gates.maxSlice` is a ceiling on what this grant
* has already drawn from the pool, and with nothing to compare against the
* only available answer is "not yet" — so an omitted argument would not relax
* the ceiling, it would remove it. `readSharePoolWindowUsage` returns zeroed
* fractions for a grant with no history, which is the honest empty value.
*/
poolUsage: ProxySharePoolUsage): ProxyShareAccountFilterResult;
/**
* Collapse per-account exclusions into the single reason the borrower is told
* when nothing survived. A transient cause outranks a structural one so the
* borrower learns whether waiting is worth anything.
*/
export declare function summarizeAccountExclusions(excluded: readonly ProxyShareAccountExclusion[]): ProxyShareRefusalReason;