@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) • 5.73 kB
TypeScript
/**
* Proxy CLI Commands for NeuroLink
*
* Implements commands for managing the Claude multi-account proxy:
* - neurolink proxy start — Start the proxy server
* - neurolink proxy status — Show proxy status (accounts, sessions, routing)
*
* The proxy creates a NeuroLink instance and builds a Hono app that registers
* Claude-compatible proxy routes. All requests flow through ctx.neurolink
* (generate/stream), with an optional ModelRouter for model remapping.
*/
import type { CommandModule } from "yargs";
import type { Hono } from "hono";
import type { AccountAllowlist, LoadedProxyConfig, ModelRouterInterface, ProxyGuardArgs, ProxyHealthProbe, ProxyNeurolinkRuntime, ProxyStartArgs, ProxyStartStrategy, ProxyRestartSupervisorState as ProxySupervisorState, ProxyStatusArgs, ProxyTelemetryArgs, ProxyReadinessState } from "../../types/index.js";
import { ProxyRuntimeConfigStore } from "../../proxy/runtimeConfig.js";
/**
* Drop a supervisor `version` that is not a string.
*
* `StateFileManager.load()` is a bare `JSON.parse(content) as T` — it validates
* nothing. A state file written by a different build, or half-written during a
* crash, can carry any JSON type here, and every status renderer interpolates
* the field straight into `v${...}`. Coercing at the single load boundary keeps
* a non-string from reaching the output as "v[object Object]".
*/
export declare function normalizeSupervisorState(state: ProxySupervisorState | null): ProxySupervisorState | null;
/**
* Whether a rolling handoff can actually occur.
*
* A live supervisor PID alone is not enough: a supervisor from a build
* predating rolling state leaves `rolling` absent, and calling that a handoff
* makes both `/status` clients and the CLI wait for an activation that will
* never come. Gate on the capability, not on the process.
*/
export declare function isRollingHandoffCapable(state: ProxySupervisorState | null, isRunning?: (pid: number) => boolean): boolean;
/**
* Best-effort check that a pid actually belongs to a neurolink proxy process,
* so a stale/recycled supervisor pid is never mistaken for a live supervisor
* and signalled. Returns false when the process cannot be confirmed as ours.
*
* @param expectedStartTimeIso - The `ProxySupervisorState.startTime` (ISO
* string) recorded when the supervisor we expect at `pid` was launched.
* When provided, this is cross-checked against `pid`'s actual OS-reported
* start time (see {@link getProcessStartTime}) — the args match alone
* (the `neurolink proxy start` command is present) is not airtight, since an
* unrelated process (e.g. a shell running this very test suite, or a
* coincidentally-named script) could match it too. A pid recycled by such
* a process would have a start time far from the recorded supervisor
* startTime, which this catches.
*
* Deliberately fail-open on anything unparseable: `ps -o lstart=` output
* parsing is inherently a little fragile (locale/format quirks), and the
* cost of a false "can't confirm" is silently regressing to pre-hardening
* behavior, while the cost of a false "confirmed mismatch" is leaving a
* real supervisor running and orphaning its socket during uninstall — the
* former is the safer failure mode. So this only ever returns false for
* the startTime check when BOTH timestamps parsed successfully AND their
* drift exceeds the tolerance; any parse failure is treated as "can't
* confirm a mismatch" and falls through to the args-only result.
*/
export declare function processLooksLikeProxySupervisor(pid: number, expectedStartTimeIso?: string): Promise<boolean>;
export declare function probeProxyHealth(host: string, port: number, timeoutMs: number): Promise<ProxyHealthProbe>;
export declare function mapClaudeErrorTypeToStatus(errorType?: string): number;
/**
* Assemble proxy routes with shared admission, runtime error accounting,
* and response tracking.
*/
export declare function createProxyStartApp(params: {
neurolink: ProxyNeurolinkRuntime["neurolink"];
modelRouter: ModelRouterInterface | undefined;
strategy: ProxyStartStrategy;
passthrough: boolean;
port: number;
host: string;
proxyConfig: LoadedProxyConfig | null;
primaryAccountKey: string | undefined;
accountAllowlist: AccountAllowlist | undefined;
runtimeConfigStore?: ProxyRuntimeConfigStore;
updateControlToken?: string;
/** Port of the gate-only share listener, when one is configured. */
sharePort?: number;
}): Promise<{
app: Hono<import("hono/types").BlankEnv, import("hono/types").BlankSchema, "/">;
readiness: ProxyReadinessState;
}>;
/** Reload only the ready serving worker. A candidate still starting must not
* receive SIGHUP before it has installed its handlers. It loads fresh config
* during startup; draining workers already hold their request snapshots. */
export declare function registerProxySupervisorReload(activeWorkerPid: () => number | undefined): () => void;
export declare const proxyStartCommand: CommandModule<object, ProxyStartArgs>;
export declare function sanitizeProxyStatusTerminalErrorMessage(message: string): string;
export declare const proxyStatusCommand: CommandModule<object, ProxyStatusArgs>;
export declare const proxyTelemetryCommand: CommandModule<object, ProxyTelemetryArgs>;
export declare const proxyGuardCommand: CommandModule<object, ProxyGuardArgs>;
export declare const proxySetupCommand: CommandModule;
export declare function buildProxyLaunchdPlist(port: number, host: string, envFile?: string, configFile?: string): string;
export declare const proxyInstallCommand: CommandModule;
export declare const proxyUninstallCommand: CommandModule;