Adapters
An adapter translates between opencodex’s internal request/response model and one provider wire
format. Every adapter implements the ProviderAdapter interface (src/adapters/base.ts):
interface ProviderAdapter { name: string; buildRequest(parsed, incoming?): AdapterRequest | Promise<AdapterRequest>; fetchResponse?(request, context): Promise<Response>; // custom retry/transport parseStream(response): AsyncGenerator<AdapterEvent>; parseResponse?(response): Promise<AdapterEvent[]>; // non-streaming runTurn?(parsed, incoming, emit): Promise<void>; // bidirectional transport}buildRequest lowers an OcxParsedRequest into an upstream HTTP request; parseStream /
parseResponse lift the provider’s reply back into internal AdapterEvents. fetchResponse lets an
adapter own retries/timeouts, while runTurn supports transports that cannot be represented as one
HTTP fetch followed by one response stream. bridge.ts
then turns the events into Responses SSE.
openai-chat
Section titled “openai-chat”Targets: OpenAI Chat Completions (POST {baseUrl}/chat/completions) and every compatible
provider — xAI, Kimi, DeepSeek, GLM, Groq, OpenRouter, Ollama (local & cloud), and more.
Auth: key (Bearer).
- Converts internal messages to OpenAI roles; maps tools to
{type:"function", function:{…}}andtool_choice(auto/none/requiredor a named function). - Rewrites Codex’s GPT-5 identity prompt to a model-agnostic intro so routed models don’t claim to be OpenAI.
- Clamps
reasoning_effortto the model’s advertised subset when an exact tier is unavailable;xhighandmaxremain distinct labels unless a provider explicitly configures an alias. The adapter omits it entirely for ids inprovider.noReasoningModels. - Streams
delta.content(text),delta.reasoning_content(thinking), anddelta.tool_calls[]; collectsusage.
openai-responses
Section titled “openai-responses”Targets: the OpenAI Responses API. passthrough: true — forwards the raw request body and
streams the response back untranslated.
Auth: forward (relay the caller’s headers) or key.
forwardURL →{baseUrl}/responses. Akeyprovider defaults to the legacy{baseUrl}/v1/responsesconstruction.- A
keyprovider may set a validated relativeresponsesPath; the adapter removes one trailing slash frombaseUrland sends{trimmedBaseUrl}{responsesPath}. For Ark Agent Plan, usebaseUrl: "https://ark.cn-beijing.volces.com/api/plan/v3"withresponsesPath: "/responses". - In
forwardmode only a safe header allowlist is relayed (FORWARD_HEADERS): authorization, ChatGPT account id, and the OpenAI beta/originator/session headers. This is the ChatGPT-login path that also powers the sidecars.
anthropic
Section titled “anthropic”Targets: Anthropic Messages (/v1/messages).
Auth: key (x-api-key) or oauth (Bearer + anthropic-beta, for Claude Pro/Max).
- Converts messages to Anthropic content blocks (text, base64 image,
tool_use,thinking). - Extended thinking math: Anthropic requires
max_tokens > thinking.budget_tokens. The adapter maps reasoning effort to a budget (minimal 1024 … max 32000), then computes a safemax_tokenswith output headroom, and dropstemperature/top_pwhen thinking is enabled (Anthropic forbids them there). - Always sends
anthropic-version: 2023-06-01. Streamscontent_block_delta(text_delta,thinking_delta, compatiblereasoning_delta,input_json_delta). The SSE decoder preserves event state across fetch chunks and accepts a terminalmessage_stopwithout a trailing newline.
google
Section titled “google”Targets: Google Gemini, Vertex AI, and Antigravity Cloud Code Assist. AI Studio uses
/v1beta/models/{model}:streamGenerateContent; the other modes use their native Google endpoints.
Auth: API key, Vertex ADC, or Google Antigravity OAuth, selected by googleMode.
- System prompt →
systemInstruction; messages →contents[](assistant →model); tools →functionDeclarations. Data-URL images →inline_data. - Tool-call ids are synthesized when Gemini omits them. Antigravity preserves and replays real
thoughtSignaturevalues so reasoning continuity survives later turns.
Targets: the Amazon CodeWhisperer Streaming GenerateAssistantResponse service used by Kiro
(https://runtime.{region}.kiro.dev/).
Auth: Kiro OAuth access token as Bearer, with region/profile metadata from the Kiro credential.
- Builds Kiro
conversationState, maps Codex tools and tool results, and sends image blocks supported by the Kiro wire. - Decodes
application/vnd.amazon.eventstream, reconstructs text/thinking/tool events, detects truncated tool JSON, and estimates usage because the upstream does not return token counts. - Uses the configured
baseUrlverbatim when it is custom. A canonicalruntime.{region}.kiro.devURL follows the imported credential’s API region; only that canonical shape is eligible for one bounded fallback toq.{region}.amazonaws.comafter an endpoint, signature, DNS, or connection failure. - Owns replay-safe connection-reset recovery, that single eligible endpoint fallback, and one OAuth refresh/replay after HTTP 401. The client owns throttling, timeout, and ordinary service retries; opencodex does not multiply those policies inside the adapter.
- Its non-streaming parser drains the same event stream for the web-search loop.
Completion semantics
Section titled “Completion semantics”Kiro text events do not carry a dependable end-turn phase. When an ordinary client tool is present,
opencodex therefore adds a private codex_kiro_final_answer tool to the upstream request. Progress
text streams as commentary and cannot terminate the turn. The adapter consumes the private call,
emits its answer as final text, and never exposes the private tool to Codex or Claude Code.
When the web-search sidecar is active, this commentary still streams immediately; only the events
needed to decide whether the model requested a synthetic search remain buffered.
If Kiro emits progress without calling the completion tool, the adapter makes one continuation. That single retry may finish with a validated private completion or plain final text. It cannot recurse: an empty or reasoning-only retry is returned as retryable incomplete, while a real client tool call keeps the turn open. If the retry only repeats the preceding commentary after whitespace normalization, the duplicate output is suppressed while the turn still completes. Tool-free requests retain normal text completion behavior.
Reasoning effort
Section titled “Reasoning effort”gpt-5.6-sol has verified native effort support. Its selected low, medium, high, xhigh, or
max value is sent as additionalModelRequestFields.reasoning.effort. Other Kiro models currently
use emulated reasoning: opencodex converts the selected level into bounded thinking instructions in
the user content because their native effort field has not been verified. Do not interpret an
advertised effort control on those models as proof of upstream-native reasoning support.
cursor
Section titled “cursor”Targets: Cursor’s agent.v1.AgentService/Run over HTTP/2 Connect streaming at api2.cursor.sh.
Auth: Cursor OAuth/access token from provider.apiKey or the forwarded authorization header.
- Uses
runTurnrather than the ordinary fetch/parse path. Requests, server events, tool arguments, usage checkpoints, and client replies are encoded with@bufbuild/protobufschemas incursor/gen/agent_pb.tsand framed as Connect messages. - Replays conversation state through content-addressed blobs, maps server tool calls back to Codex,
discovers live Cursor models through the protobuf
GetUsableModelsRPC, and retries only before a run request is committed to the wire. - Exposes Cursor Router as
cursor/autoplus explicitcursor/auto-cost,cursor/auto-balance, andcursor/auto-intelligenceentries. Explicit levels are encoded inrequested_model.parameterswhile the legacycursor/autoentry retains the account/team default. - Cursor-native local filesystem/shell/network execution is denied by default. Explicit
mcpServersanddesktopExecutorintegrations have separate opt-ins;nativeLocalExec: "on"enables the broader built-in executor and bypasses Codex approval/sandbox semantics, and legacyunsafeAllowNativeLocalExec: trueremains equivalent only whennativeLocalExecis unset.
azure-openai (alias: azure)
Section titled “azure-openai (alias: azure)”Targets: Azure OpenAI. Wraps openai-responses (so also passthrough: true).
Auth: key via the api-key header (not Bearer).
- Delegates request building to the Responses passthrough, validates that
baseUrlcontains no unresolved template placeholder, and replacesAuthorizationwithapi-key. The configured URL targets Azure’s v1 Responses API directly, so the adapter does not appendapi-version.
Image utilities (image.ts)
Section titled “Image utilities (image.ts)”Shared helpers used by the vision-aware adapters:
parseDataUrl(url)— split adata:<type>;base64,<data>URL into{ mediaType, base64 }for Anthropic/Google image blocks.contentPartsToText(content)— flatten content parts to text for text-only tool messages (an undescribed image becomes a short[image]marker, never a token-exploding base64 blob).

