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

113 lines (112 loc) • 5.85 kB
/** * Native Claude-to-Vertex passthrough. * * Claude on Vertex speaks the Anthropic Messages API, so a fallback to it needs * no translation at all — the client's body goes upstream essentially verbatim * and the SSE comes back in the shape the client already expects. * * This exists because the SDK/translation path cannot carry an agentic turn: * it runs its own tool loop, and a request whose tools have no executor (every * proxied request, since the caller executes them) ends with the pending tool * call discarded and a step-cap apology returned as assistant text. Tools, * `tool_use`, `tool_result`, `cache_control` and thinking blocks all survive * here because nothing reshapes them. */ import type { GoogleAuth } from "google-auth-library"; import type { VertexAccessTokenProvider, UsageContext, VertexPassthroughTerminal, VertexAnthropicPassthroughRequest, VertexAnthropicPassthroughTarget } from "../types/index.js"; /** * Translate `output_config` for Vertex. * * An effort level Vertex knows passes through; one it does not is mapped onto * the nearest level it does. A level with no mapping at all loses only the * `effort` key, never the sibling settings beside it. */ export declare function mapVertexOutputConfig(value: unknown): Record<string, unknown> | undefined; export declare function buildVertexAnthropicPayload(body: Readonly<Record<string, unknown>>, targetModel?: string): Record<string, unknown>; /** * Publisher endpoint for a Claude model on Vertex. * * Streaming and non-streaming are different verbs on the same resource, so the * caller's `stream` flag selects the verb rather than changing the body. */ export declare function buildVertexAnthropicUrl(target: VertexAnthropicPassthroughTarget): string; /** Exported only for continuous-test-suite-vertex-anthropic-fallback.ts, * which proves concurrent callers share one instance. Not part of the * package's public surface — this module isn't re-exported from index.ts. */ export declare function auth(): Promise<GoogleAuth>; /** Test-only: isolates the concurrency proof from cache state any earlier * test in the same process may have left behind. */ export declare function resetAuthCacheForTests(): void; /** * Replace the Google credential lookup, for tests only. * * Without this seam the two-leg fallback chain cannot be driven end to end. * The rest of the hop is reachable — `dispatchVertexAnthropicPassthrough` * calls the global `fetch`, which a test can replace — but the credential * lookup goes through gaxios, and gaxios resolves its transport to * `(await import("node-fetch")).default` rather than `globalThis.fetch`. A * test that swaps the global therefore cannot intercept the token exchange, * and on a machine with no Application Default Credentials the leg throws * before it ever reaches the model. That left the one path that bills in real * currency with no end-to-end coverage at all. * * Pass `undefined` to restore the real credential lookup. */ export declare function setVertexAccessTokenProviderForTests(provider: VertexAccessTokenProvider | undefined): void; /** * Run once more after a short pause when the first attempt hit a transient * network failure: anything the shared proxy classifier retries, plus a DNS * blip. One retry absorbs a blip without hiding a real outage: a second * failure, or any other error, surfaces unchanged. */ export declare function withTransientNetworkRetry<T>(run: () => Promise<T>, delayMs?: number): Promise<T>; /** * Send one Anthropic-shaped request to Vertex and return the upstream response * untouched, so the caller can stream its bytes straight to the client. */ export declare function dispatchVertexAnthropicPassthrough(request: VertexAnthropicPassthroughRequest): Promise<Response>; /** Claude models are the only publisher models this passthrough addresses. */ export declare function isVertexAnthropicModel(model: string): boolean; /** * Resolve where Vertex traffic is addressed, using the same environment the * Vertex provider reads so a fallback lands on the project and region the rest * of the process already uses. */ export declare function resolveVertexTarget(): { projectId: string; location: string; } | undefined; /** * Run one Claude-on-Vertex fallback attempt and hand back a response the route * can serve directly. * * A non-2xx upstream throws so the caller's attempt loop records the failure * and moves to the next hop, exactly as the other providers behave. */ export declare function executeVertexAnthropicFallback(args: { body: Readonly<Record<string, unknown>>; model: string; signal?: AbortSignal; /** Fires exactly once on every exit, so the hop is finalized like any other. */ onTerminal?: (terminal: VertexPassthroughTerminal) => void; }): Promise<Response>; /** * Read usage out of a non-streaming Anthropic reply. * * `rawPredict` returns a single `{"type":"message","usage":{...}}` object, which * carries the whole turn's counts at once rather than splitting them across * `message_start` and `message_delta`. */ export declare function readJsonUsage(text: string): UsageContext; /** * Forward a stream unchanged while observing its usage events. * * The bytes are passed through untouched — parsing happens on a copy of each * chunk — so the client sees exactly what Vertex sent. * * A transform's `flush` only runs on a clean end, which would leave a stream * error or a client disconnect with no terminal record at all. An explicit * reader loop is used instead, so `onTerminal` fires exactly once on every * exit: normal end, upstream failure, and cancellation. */ export declare function observeVertexUsage(body: ReadableStream<Uint8Array>, onTerminal: (terminal: VertexPassthroughTerminal) => void): ReadableStream<Uint8Array>;