/** * Gateway backend ports and the model-routed dispatcher. Provider HTTP * transports live next to their codecs (`openai-backend.ts`, * `anthropic-backend.ts`, `google-backend.ts`, `codex-responses-backend.ts`). */ import type { ModelCapabilityMetadata, ModelReasoningCapabilities, RequestAttribution } from "@velum-labs/routekit-contracts"; import type { RouteKitPlatform } from "@velum-labs/routekit-runtime/effect"; import { type Context, Effect } from "effect"; export type BackendModelRoute = { /** Stable RouteKit catalog id (`provider/model`). */ publicId: string; /** Model id understood by the provider's native API. */ nativeId: string; /** Configured provider that owns the model. */ provider: string; metadata?: ModelCapabilityMetadata; reasoning?: ModelReasoningCapabilities; }; type BackendModelOperations = Readonly<{ list(): readonly string[]; resolve(requested: string | undefined): string | undefined; resolveRoute(requested: string | undefined, nativeProvider?: string): BackendModelRoute | undefined; serves(model: string): boolean; capabilities(model: string): Readonly>; metadata(model: string): ModelCapabilityMetadata | undefined; reasoning(model: string): ModelReasoningCapabilities | undefined; reasoningWireShape(model: string): string | undefined; }>; export type BackendModelPort = (BackendModelOperations & Readonly<{ kind: "static-model"; }>) | (BackendModelOperations & Readonly<{ kind: "model-catalog"; }>); export type BackendResponsesPort = Readonly<{ kind: "unsupported"; }> | Readonly<{ kind: "responses"; supports(model: string): boolean; execute(body: unknown, signal?: AbortSignal, options?: BackendRequestOptions): BackendRequest; }>; export type BackendLifecyclePort = Readonly<{ kind: "borrowed"; }> | Readonly<{ kind: "owned"; close: Effect.Effect; }>; export type BackendPorts = Readonly<{ models: BackendModelPort; responses: BackendResponsesPort; lifecycle: BackendLifecyclePort; }>; export declare function staticBackendModelPort(defaultModel: string | undefined, options?: Readonly<{ reasoningWireShape?: string; responses?: boolean; }>): BackendModelPort; export declare function borrowedBackendPorts(defaultModel: string | undefined, overrides?: Readonly<{ models?: BackendModelPort; responses?: BackendResponsesPort; lifecycle?: BackendLifecyclePort; }>): BackendPorts; /** Provider HTTP I/O. Callers yield this on a fiber that already has HttpClient. */ export type BackendRequest = Effect.Effect; export type Backend = { /** Explicit capability and ownership ports. */ ports: BackendPorts; /** Model id sent to the backend when a request omits one. */ readonly defaultModel: string | undefined; /** POST /chat/completions — supports streaming (SSE) upstream. */ chat(body: unknown, signal?: AbortSignal, options?: BackendRequestOptions): BackendRequest; /** GET /models. */ models(signal?: AbortSignal): BackendRequest; /** POST /embeddings. */ embeddings(body: unknown, signal?: AbortSignal, options?: BackendRequestOptions): BackendRequest; }; export type BackendResponseMode = "buffered" | "streaming"; export type BackendRequestOptions = { /** Original downstream response mode, before any provider forces upstream SSE. */ responseMode?: BackendResponseMode; modelCallId?: string; reasoningCapabilities?: ModelReasoningCapabilities; /** Request-local, sanitized attribution updates from routing/backends. */ onAttribution?: (update: RequestAttributionUpdate) => void; /** Distinguishes compound provider operations within one public request. */ attributionOperationId?: string; /** * Neutral request context captured at the HTTP boundary. Backends may * interpret their own namespaced headers; the gateway does not. */ requestContext?: { headers: Readonly>; }; /** * The caller will wrap the returned stream in a dialect translator * (Anthropic / Responses) that emits its own keepalive. */ translated?: boolean; /** * HttpClient context captured when the gateway HTTP app was built. * Server-tool search I/O reuses it instead of a nested runtime. */ platform?: Context.Context; }; export type RequestAttributionUpdate = Partial & { accountAttempt?: { operationId: string; seat: string; }; }; /** Join a base URL (which may end in `/`) with a route path. */ export declare function joinPath(baseUrl: string, path: string): string; export type ModelRoutedBackendOptions = { /** Requested model ids served by `routed` instead of the primary backend. */ routedModelIds: readonly string[]; /** Backend for the routed ids. */ routed: Backend; /** Backend for everything else (e.g. the member's router endpoint). */ primary: Backend; }; /** * A backend that dispatches by requested model id: ids in `routedModelIds` go * to the `routed` backend, everything else to `primary`. This lets selected * model ids use a secondary destination. */ export declare class ModelRoutedBackend implements Backend { #private; readonly defaultModel: string | undefined; readonly ports: BackendPorts; constructor(options: ModelRoutedBackendOptions); listModelIds(): readonly string[]; resolveModel(requested: string | undefined): string | undefined; reasoningWireShape(model: string): string | undefined; chat(body: unknown, signal?: AbortSignal, options?: BackendRequestOptions): BackendRequest; supportsResponses(model: string): boolean; responses(body: unknown, signal?: AbortSignal, options?: BackendRequestOptions): BackendRequest; models(signal?: AbortSignal): BackendRequest; embeddings(body: unknown, signal?: AbortSignal, options?: BackendRequestOptions): BackendRequest; close(): Effect.Effect; } export {};