| title | Adapters |
|---|---|
| description | 七个 provider adapter 的目标、请求构建方式与各自特性。 |
adapter 负责在 opencodex 的内部请求/响应模型与某个 provider 的 wire 格式之间转换。每个
adapter 都实现 ProviderAdapter 接口(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 把 OcxParsedRequest 转成上游 HTTP 请求;parseStream / parseResponse 把 provider
回复转回内部 AdapterEvent。fetchResponse 允许 adapter 自己负责重试和 timeout;runTurn 支持
无法表示成一次 HTTP fetch 加一条响应流的 transport。随后
bridge.ts 把 event 转成 Responses SSE。
目标: OpenAI Chat Completions(POST {baseUrl}/chat/completions)以及所有兼容 provider,
包括 xAI、Kimi、DeepSeek、GLM、Groq、OpenRouter、Ollama(本地与云端)等。
认证: key(Bearer)。
- 把内部消息转换成 OpenAI role;工具映射为
{type:"function", function:{…}}和tool_choice(auto/none/required或具名函数)。 - 工具结果中的图片会在工具轮次结束后,作为后续 user vision 消息(
image_url部分)发送, 因为role:"tool"的内容只能是文本;[image]标记仍保留在工具消息中作为锚点。 - 重写 Codex 的 GPT-5 身份提示词,改成与模型无关的介绍,避免路由模型自称 OpenAI。
- 精确层级不可用时,把
reasoning_effort限制到模型公布的子集。除非 provider 显式配置 alias,xhigh与max保持为不同标签。对于provider.noReasoningModels中的 id,则完全 省略该参数。 - 流式输出
delta.content(文本)、delta.reasoning_content(thinking)和delta.tool_calls[],并收集usage。
目标: OpenAI Responses API。passthrough: true —— 转发原始请求 body,并把响应
不经转换地流式传回。
认证: forward(转发调用方 header)或 key。
forwardURL →{baseUrl}/responses。keyprovider 默认保留原有的{baseUrl}/v1/responses构造。keyprovider 可设置经过验证的相对responsesPath;adapter 会移除baseUrl末尾的一个/,并向{trimmedBaseUrl}{responsesPath}发送请求。Ark Agent Plan 使用baseUrl: "https://ark.cn-beijing.volces.com/api/plan/v3"和responsesPath: "/responses"。forward模式只会转发安全的 header allowlist(FORWARD_HEADERS):authorization、ChatGPT account id 和 OpenAI beta/originator/session header。这条 ChatGPT 登录路径也为 sidecar 提供支持。
目标: Anthropic Messages(/v1/messages)。
认证: key(默认 x-api-key,或设置 apiKeyTransport: "bearer" 后使用 Authorization: Bearer)或 oauth(Bearer + anthropic-beta,用于 Claude Pro/Max)。
- 把消息转换成 Anthropic content block(text、base64 image、
tool_use、thinking)。 - Extended thinking 计算: Anthropic 要求
max_tokens > thinking.budget_tokens。adapter 把 reasoning effort 映射成 budget(minimal 1024 … max 32000),再计算留有输出余量的安全max_tokens;启用 thinking 后会移除temperature/top_p,因为 Anthropic 禁止此组合。 - 始终发送
anthropic-version: 2023-06-01。流式输出content_block_delta(text_delta、thinking_delta、input_json_delta)。
目标: Google Gemini、Vertex AI 和 Antigravity Cloud Code Assist。AI Studio 使用
/v1beta/models/{model}:streamGenerateContent,其他模式使用各自的 Google 原生 endpoint。
认证: 根据 googleMode 选择 API key、Vertex ADC 或 Google Antigravity OAuth。
- 系统提示词 →
systemInstruction;消息 →contents[](assistant →model);工具 →functionDeclarations;data URL 图像 →inline_data。 - Gemini 省略 tool-call id 时会合成 id。Antigravity 会保留并重放真实
thoughtSignature,使 reasoning continuity 延续到后续 turn。
目标: Kiro 使用的 Amazon CodeWhisperer Streaming GenerateAssistantResponse 服务
(https://runtime.{region}.kiro.dev/)。
认证: Kiro credential 中的 region/profile metadata,加上作为 Bearer 的 Kiro OAuth access
token。
- 构建 Kiro
conversationState,映射 Codex 工具和工具结果,并发送 Kiro wire 支持的 image block。 - 解码
application/vnd.amazon.eventstream,重建 text/thinking/tool event,检测被截断的工具 JSON。上游不返回 token 数量,因此 usage 采用估算值。 - 经
fetchResponse负责有界重试和分类/脱敏后的错误;非流式 parser 会排空同一 event stream, 供 web-search loop 使用。
Kiro 的 assistant 文本本身没有可靠的回合结束标记,但终止的 metadataEvent 可能带有原生 stopReason。
END_TURN 和 STOP_SEQUENCE 只能证明本次推理已停止;Kiro 也可能给进展文本加上该标记。因此在启用工具的
回合中,普通文本仍作为 commentary,并通过私有完成工具做一次校验。
END_TURN、STOP_SEQUENCE 或缺失 stop reason 时可以走一次完成兼容路径。其他显式原因已在上游终止本次推理,因此适配器直接报告而不是
再发一次请求:输出 token 上限表现为可继续的 incomplete,上下文窗口耗尽表现为不可重试的 context-length
错误,内容过滤或 guardrail 停止表现为 filtered incomplete。没有真实工具调用却出现的 TOOL_USE 被视为
矛盾而非进展。
启用工具时,opencodex 会添加私有 codex_kiro_final_answer。重试不会制造空的 assistant/user 回合,
而会保留原始 user/tool-result,并在发送前校验角色交替、非空结构消息以及 tool use/result 配对。
完成工具的回答即使与先前 commentary 完全相同,也会作为 final_answer 发出。
gpt-5.6-sol 和 claude-opus-5 支持原生 effort,且请求字段名不同。low / medium / high /
xhigh / max 分别通过 additionalModelRequestFields.reasoning.effort 和
output_config.effort 发送。
目标: api2.cursor.sh 上采用 HTTP/2 Connect streaming 的
agent.v1.AgentService/Run。
认证: provider.apiKey 或转发 authorization header 中的 Cursor OAuth/access token。
- 使用
runTurn,而不是常规 fetch/parse 路径。请求、server event、工具参数、usage checkpoint 和 client reply 由cursor/gen/agent_pb.ts中的@bufbuild/protobufschema 编码,并 frame 成 Connect message。 - 经 content-addressed blob 重放对话状态,把 server tool call 映射回 Codex,用 protobuf
GetUsableModelsRPC 发现实时 Cursor 模型,并且只在 run request 尚未 commit 到 wire 前重试。 - Cursor 原生本地 filesystem/shell/network 执行默认被拒绝。显式
mcpServers与desktopExecutor集成分别需要 opt-in;unsafeAllowNativeLocalExec会启用更广泛的内置 executor,并绕过 Codex 审批和 sandbox 语义。
目标: Azure OpenAI。封装 openai-responses,因此同样是 passthrough: true。
认证: 用 api-key header 进行 key 认证,而非 Bearer。
- 把请求构建交给 Responses passthrough,验证
baseUrl不含未解析的 template placeholder, 再用api-key替换Authorization。配置的 URL 直接指向 Azure v1 Responses API,因此 adapter 不会追加api-version。
支持视觉的 adapter 共用以下 helper:
parseDataUrl(url)—— 把data:<type>;base64,<data>URL 拆成{ mediaType, base64 },供 Anthropic/Google image block 使用。contentPartsToText(content)—— 为纯文本工具消息把 content part 扁平化成文本。未描述的图像 会变成简短的[image]marker,而不是导致 token 暴涨的 base64 blob。