/** * Translate Cursor's BYOK request hybrid into OpenAI Chat Completions. * * When Cursor's "Override OpenAI Base URL" feature is active, Cursor POSTs to * `{base_url}/chat/completions` but — for agent mode and GPT-family routing — * the JSON body is shaped like the OpenAI *Responses* API (`input` item list, * flat tool definitions, `reasoning`/`text` objects), while the response it * renders is standard Chat Completions SSE. This module is the pure * translation layer behind the `/v1/cursor/*` routes. It maps the * Responses-hybrid body onto * the Chat Completions shape the rest of the gateway already handles. * * No I/O happens here. The translation is total: weird-but-parseable input is * never a reason to throw — unknown item and tool types are dropped so the * boundary stays defensive without 4xx-ing on new shapes. */ import type { ModelReasoningCapabilities } from "@velum-labs/routekit-contracts"; type JsonObject = Record; /** * Whether a parsed request body is routable by the cursor route: a JSON * object carrying either `messages` (plain Chat Completions, e.g. Ask mode) * or `input` (the Responses hybrid). Rejecting other shapes is the route's * job; the translation itself stays total. */ export declare function isCursorChatBody(body: unknown): body is JsonObject; export type CursorModelSelection = { model: string; reasoningEffort?: string; }; /** * Expand one served model into the opaque ids Cursor can put in its picker. * * Cursor's OpenAI-compatible BYOK path does not expose its reasoning picker, * so each discovered effort is represented as a model-name variant instead. */ export declare function cursorModelVariants(id: string, reasoning: unknown): CursorModelSelection[]; /** * Resolve a Cursor-facing model variant back to its served model and effort. * * Exact served ids win before qualification, so a provider model whose real * id contains a colon remains addressable. Effort aliases are accepted but * normalized to the provider's canonical id. */ export declare function resolveCursorModelSelection(model: unknown, servedIds: readonly string[], reasoningCapabilities?: (model: string) => ModelReasoningCapabilities | undefined): CursorModelSelection | undefined; /** * Resolve a Cursor-facing model name back to a served id. * * Returns `undefined` when the name is already a served id or cannot be * resolved. */ export declare function resolveCursorModelAlias(model: unknown, servedIds: readonly string[]): string | undefined; /** * Map a Cursor BYOK request body onto a Chat Completions body. * * Dual-shape tolerance: Cursor only sends the Responses hybrid for some * models/modes; Ask mode may send plain Chat Completions. A body that * already carries `messages` is returned unchanged; a body with `input` * is translated. A body with neither yields an empty `messages` list. */ export declare function translateCursorRequest(body: JsonObject): JsonObject; export {};