/** * gjc auth-gateway HTTP server. * * Accepts a provider-scoped provider-format request (OpenAI chat-completions, Anthropic * messages, OpenAI Responses) and dispatches through pi-ai's `streamSimple()` * — which handles credential injection, anthropic-beta headers, OpenAI code backend * websocket transport, and all the per-provider intricacies. The gateway is * pure protocol translation: foreign wire → gjc Context → pi-ai stream() → * gjc events → foreign wire. * * Endpoints: * GET /healthz → unauth; ok + version * GET /v1/usage → aggregated provider usage (5-min per-credential cache via AuthStorage) * GET /v1/credentials/check → per-credential auth probe (diagnose 401s in a multi-account pool) * GET /v1/models → list models from the selected provider scope * POST /v1/chat/completions → OpenAI chat-completions in/out * POST /v1/messages → Anthropic messages in/out * POST /v1/responses → OpenAI Responses in/out */ import type { AuthStorage } from "../auth-storage"; import type { Api, AssistantMessageEventStream, Model, Provider, SimpleStreamOptions } from "../types"; import type { AuthGatewayServerHandle, AuthGatewayServerOptions, AuthGatewayParsedRequest as ParsedFormatRequest } from "./types"; export type ModelResolver = (modelId: string) => Model | undefined; export interface AuthGatewayBootOptions extends AuthGatewayServerOptions { /** Source of credentials. Caller wires this to a broker-backed AuthStorage. */ storage: AuthStorage; /** * Current broker-backed scope authority. When supplied, this is checked on * every request so a live broker snapshot removal immediately fails closed. */ hasProviderCredential: () => boolean; /** Refresh the dispatch cache from the current broker snapshot before use. */ reloadProviderCredentials: (signal?: AbortSignal) => Promise; /** Confirm that the selected key is still present in the current authority snapshot. */ validateProviderCredential: (provider: string, apiKey: string) => boolean; /** * Resolve a client-requested model id to a pi-ai Model. Caller supplies * this from a ModelRegistry (lives in `coding-agent` to avoid an inverse * dependency in `pi-ai`). */ resolveModel: ModelResolver; /** Supplier for the source-backed model catalog used by `/v1/models`. */ listModels: () => Iterable>; } export interface AuthGatewayModelCatalog { readonly models: readonly Model[]; resolve(modelId: string): Model | undefined; } /** * Whether a model can be served through the broker-backed auth gateway. * * Bedrock's credential chain is process-local AWS authority, not a broker * credential. Advertising a native Bedrock model from this gateway would let * direct callers bypass the broker boundary (and make readiness lie about a * model the gateway cannot authenticate). Keep this predicate shared with the * CLI readiness checks so every entry point applies the same fence. */ export declare function isAuthGatewayModelBrokerConsumable(model: Pick, "api" | "transport">): boolean; /** * Build an unambiguous, provider-scoped catalog. * * Models from other providers are intentionally ignored rather than allowed * to compete for the same id. Duplicate ids within the selected provider are * rejected because choosing either one would make request dispatch * order-dependent. */ export declare function createAuthGatewayModelCatalog(provider: Provider, models: Iterable>): AuthGatewayModelCatalog; export declare function releaseGatewayCredentialLeaseOnAdmission(events: Pick, release: () => void, signal?: AbortSignal): void; /** Test seam for verifying translated gateway requests never acquire agent-owned provider identity. */ export declare function buildAuthGatewayStreamOptionsForTest(parsed: ParsedFormatRequest, api: Api): SimpleStreamOptions; export declare function startAuthGateway(opts: AuthGatewayBootOptions): AuthGatewayServerHandle; export declare function isSafeProviderScope(provider: unknown): provider is string;