/** Shared TypeScript types for the proxy server. */ /** Per-provider upstream configuration used by the generic forwarder. */ export interface ProviderConfig { /** Human-readable name for logging (e.g. "anthropic", "gemini"). */ readonly name: string; /** Upstream base URL (e.g. "https://api.anthropic.com"). */ readonly baseUrl: string; /** The API key value to inject into upstream requests. */ readonly apiKey: string; /** The header name for the API key (e.g. "x-api-key" for Anthropic, "x-goog-api-key" for Gemini). */ readonly apiKeyHeader: string; /** Headers from the client request that should be forwarded upstream. */ readonly forwardedHeaders: ReadonlyArray; } /** Typed server configuration derived from environment variables. */ export interface ProxyConfig { /** Anthropic API key (undefined = Anthropic relay disabled). */ readonly anthropicApiKey: string | undefined; /** Shared secret token for client authentication. */ readonly proxyAuthToken: string; /** Server listen port. */ readonly port: number; /** Server listen host. */ readonly host: string; /** Pino log level. */ readonly logLevel: string; /** Max requests per rate-limit window per IP. */ readonly rateLimitMax: number; /** Rate-limit window duration in ms. */ readonly rateLimitWindowMs: number; /** Max request body size in bytes. */ readonly bodyLimit: number; /** CORS origin (empty string = disabled). */ readonly corsOrigin: string; /** Upstream Anthropic base URL. */ readonly anthropicBaseUrl: string; /** Upstream request timeout in ms. */ readonly upstreamTimeoutMs: number; /** Gemini API key (undefined = Gemini relay disabled). */ readonly geminiApiKey: string | undefined; /** Upstream Gemini base URL. */ readonly geminiBaseUrl: string; } /** Headers forwarded to the Anthropic upstream API. */ export const ANTHROPIC_FORWARDED_HEADERS: ReadonlyArray = [ 'anthropic-beta', 'anthropic-version', 'content-type', 'accept', 'x-request-id', ] as const; /** Headers forwarded to the Gemini upstream API. */ export const GEMINI_FORWARDED_HEADERS: ReadonlyArray = [ 'content-type', 'accept', 'x-request-id', ] as const; /** Hop-by-hop headers that must be stripped before forwarding. */ export const HOP_BY_HOP_HEADERS: ReadonlyArray = [ 'connection', // Controls if the network connection stays open after the current transaction. 'keep-alive', // Settings for persistent connections. 'transfer-encoding', // Specifies the form of encoding used to safely transfer the payload. 'upgrade', // Mechanism for switching to a different protocol (e.g., WebSocket). 'proxy-authorization', // Credentials for authenticating the client with a proxy. 'te', // Specifies the transfer encodings the user agent is willing to accept. 'trailer', // Indicates that specific headers will be present in the trailer of a chunked message. ] as const; /** Allowed Anthropic proxy route paths. */ export const ANTHROPIC_ROUTES = [ '/v1/messages', '/v1/messages/count_tokens', ] as const; export type AnthropicRoute = (typeof ANTHROPIC_ROUTES)[number];