Skip to content

Latest commit

 

History

History
184 lines (138 loc) · 12 KB

File metadata and controls

184 lines (138 loc) · 12 KB

API 兼容说明

服务默认监听 http://127.0.0.1:8000,客户端不需要传入真实 OpenAI 或 Anthropic API key,但可以通过 Authorization 指定 OpenCode 上游模式。

鉴权与上游选择

  • 无 Authorization,或 Bearer public
    • 走 public Zen 免费模型。
    • /v1/models 只返回免费模型,且 ID 会去掉上游 -free 后缀(请求时会自动映射回 -free)。
  • Bearer <opencode-api-key>
    • 默认走 Zen。
    • 如果请求的是仅存在于 Go 目录中的模型,代理会自动切到 Go。
  • Bearer zen:<opencode-api-key>
    • 强制走 Zen。
  • Bearer go:<opencode-api-key>
    • 优先走 Go 订阅目录。
    • 对同时存在于 Zen 和 Go 的模型,也会按 Go 路径请求。

路由

路由 方法 说明
/v1/models GET 返回权限范围内的模型;-free 后缀会隐藏,已配置别名会替换对应上游模型 ID
/v1/chat/completions POST OpenAI Chat Completions 兼容入口
/v1/responses POST OpenAI Responses 兼容入口
/v1/messages POST Anthropic Messages 兼容入口
/v1/messages/count_tokens POST Anthropic token 计数入口:命中 anthropic 规则时直连上游 /zen/v1/messages/count_tokens,否则本地启发式估算
/v1/systemone POST TypeSafe System One 协议入口(state + typed questions → structured answers),直通上游 /zen/v1/systemone;仅 jev 系列模型可用——该模型不做文本生成,无法用 Chat / Responses / Messages 任何一条协议驱动。body 除 model 外原样透传,不走协议路由/协议转换,也不套用免费层指纹重做(该门禁只作用于 chat/completions/messages/responses 三个上游子路径)
/health GET 健康检查
/api/config GET/POST 管理面板配置接口
/api/stats GET/DELETE token 统计接口
/api/reload POST 刷新 OpenCode 会话和模型列表

GET /v1/models 的返回会随鉴权模式变化:

  • public 只显示免费 Zen 模型。
  • 默认或 zen: 模式显示 Zen 目录。
  • go: 模式显示 Go 目录,并附带 public 可用的免费模型。

上游协议路由

三个入站协议(/v1/chat/completions、/v1/responses、/v1/messages)默认经 Chat Completions 翻译后转发上游。配置 protocol_rules 后,按模型模式把请求分流到上游原生协议端点(anthropic → /zen/v1/messages、responses → /zen/v1/responses、chat_completions → /zen/v1/chat/completions),请求/响应由网关自动在入站与上游协议间转换,流式、工具调用、推理内容与 usage 统计均兼容。未命中规则时保持既有行为。规则语法、优先级与校验见 CONFIGURATION.md。

请求校验

temperature

入口 合法范围(闭区间)
/v1/messages 0..1
/v1/chat/completions 0..2
/v1/responses 0..2
  • 缺省(nil)、0、上界均合法;负数、越上界、NaN/Inf 在调用上游前被拒绝,不 clamp。
  • 拒绝时返回 HTTP 400,Content-Type: application/json,形状与入口协议一致:
    • Claude:{"type":"error","error":{"type":"invalid_request_error","message":...}}
    • Chat/Responses:{"error":{"type":"invalid_request_error","message":...,"param":"temperature"}}
  • 流式请求同样先返回普通 JSON 400,不会开始 SSE。

文件输入

  • document(Anthropic)/ input_file(Responses)是 best-effort file part,映射为 {type:"file",file:{...}}。并非所有上游模型支持 file 模态,上游拒绝时会透传明确错误。
  • 在受支持位置识别为文件输入但缺少任何可用 payload(无 file_data/file_id/file_url 或 document 无可用 source)时返回协议形状 HTTP 400 invalid_request_error,不会把 wrapper JSON 伪装成文本。

Chat Completions

准确支持

  • model
  • messages
  • stream
  • temperature(闭区间 0..2)
  • max_tokens
  • top_p
  • thinking
  • reasoning_effort
  • extra_body
  • tools
  • tool_choice

流式响应会原样保留合法的 usage-only 尾块(choices: [])以及完整 usage details。

Best-effort

  • 上游 Anthropic 响应会转换 stop reason、usage、reasoning、refusal 和工具调用。
  • 不同上游模型对 thinking / reasoning_effort 的支持可能不同。

不支持

  • 本项目未声明支持的 Chat Completions beta 字段不会被合成或伪造。

model 通常会先经过 model_alias 解析;显式使用 go: 或 zen: 且原模型存在于对应目录时,同名的 模型 -> 模型-free 兼容别名会让位于对应目录中的原模型。reasoning_effort 会按 reasoning_effort_map 转换。

Responses API

准确支持

  • 字符串 input;含 input_text / input_image 的 message item;函数及内置工具的 call/output item
  • instructions、messages(使用 Chat content 形状,非 Responses input item 形状)、previous_response_id
  • 显式零值的 temperature(闭区间 0..2)、top_p、frequency_penalty、presence_penalty
  • max_output_tokens、stop、user、parallel_tool_calls、stream_options、store
  • 函数工具、项目已有的内置工具、tool_choice、reasoning、metadata
  • Anthropic-style tool_result(call_id,缺省时用 tool_use_id;content 支持 string、字符串数组、{type:"text"|"input_text"|"output_text",text} blocks;is_error:true 加 Error: 前缀)
  • 正常终态 response.completed;长度截断终态 response.incomplete,reason 为 max_output_tokens

Best-effort

  • Responses 会通过 Chat Completions 上游实现;内置工具被编码为函数工具后再还原。
  • 已确认只支持原生上游 /responses 端点的模型(静态预置、native_responses_models 配置项、运行时探测记忆)跳过 Chat 翻译,直接保真透传,上游 4xx/5xx 状态码与错误体原样返回。 唯一例外:上游因回放的 reasoning encrypted_content 不属于当前发起方而 400(was not issued to this caller,通常发生在 sticky 出口/域名改绑之后)时,网关会剥掉 input 中 reasoning item 的 id 与 encrypted_content 后重发一次;可见对话内容不变,仅不再回放旧推理密文。详见 responses-compatibility-analysis.md §9.7。
  • 仅在上游实际返回 reasoning 时生成 reasoning output item。
  • input 中的 top-level item 或 message content 可使用 input_file;支持 flat 字段 file_data、file_id、file_url、filename 以及 nested input_file object,并映射为 {type:"file",file:{...}}。模型不支持 file 模态时上游可能拒绝。

不支持

  • include 及未在上面列出的可选 Responses 字段;这些字段不会用占位值伪装成已支持。
  • input 中受支持位置的 input_file 若缺少任何可用 payload,会返回 HTTP 400,不会序列化为文本。

示例:

curl http://127.0.0.1:8000/v1/responses \
  -H "Content-Type: application/json" \
  -d '{
    "model": "gpt-4o-mini",
    "input": "Write one short sentence.",
    "stream": false
  }'

Anthropic Messages

鉴权

  • Authorization: Bearer <key> 与 x-api-key: <key> 同权;Bearer 优先。
  • 转发上游原生 /zen/v1/messages 时,网关同时发送 Authorization: Bearer <key> 与 Anthropic 原生 x-api-key: <key>;上游 /messages 以 x-api-key 为准。
  • 有效 opencode key:sk- 前缀且长度 > 15;go: / zen: 前缀路由同样适用于两种头。
  • Anthropic 真 key(sk-ant-)不会转发上游,回落 public。
  • 占位短 key(如 Claude Code 默认 sk-local)因长度不足走 public。

准确支持

  • system(顶层)与消息内 role=system 合并为上游唯一首条 system(\n\n 拼接,顶层在前);system 为 block 数组时启发式递归计入 token
  • stop_sequences、temperature(闭区间 0..1)/ top_p / top_k(包括显式零值);开启 thinking 时这三个参数按上游 Anthropic 语义剥离(避免 400)
  • max_tokens:Chat/Responses 直通与翻译同样收敛 [128, cap](cap 来自 max_tokens_cap / max_tokens_cap_per_model);count_tokens 命中 anthropic 规则时只降不补
  • metadata.user_id:若为 JSON 串则只转发 session_id(避免 device_id 外泄);否则原样转发
  • 文本、base64/URL image、tool_use、tool_result(包括 is_error);合法的 tool result 在普通用户内容之前的顺序会被保留
  • tool_result 中的 image 转为紧随其后的 role=user + image_url,tool 文本保留字符串并标注 [image attached];tool_result 中的 document 同样转为紧随其后的 user file part 并标注 [document attached];orphan tool_use(无 matching tool_result)在翻译路径由 Worker A/B 的配对归一化处理
  • tool_choice 的 auto、any、tool、none;disable_parallel_tool_use:true 映射为上游 parallel_tool_calls=false
  • output_config.effort → 上游 reasoning_effort;thinking.type=adaptive 视为 enabled
  • JSON Schema 约束字段(包括 additionalParameters、format)
  • stop reason、usage 以及流式 content block 配对
  • /v1/messages/count_tokens:protocol_rules 命中 anthropic 上游时直连 /zen/v1/messages/count_tokens 透传取精确计数;未命中、仅命中 chat/responses 或上游失败时回落本地启发式(chat 上游对 thinking 的采样参数互斥剥参同样生效)

Best-effort / 显式丢弃(可观测)

  • document(source.type=base64,默认 application/pdf;source.type=url)映射为 Chat content part {type:"file",file:{...}},可保留 block/title 作为 filename。模型不支持 file 模态时上游可能拒绝;document 缺少可用 payload 时返回 HTTP 400。
  • thinking 会在没有 signature 时继续输出,以提高客户端兼容性。代理不会伪造 signature 或发送假的 signature_delta。
  • 请求历史中的 thinking signature 没有 Chat Completions 等价物,会被丢弃;代理仅统计历史中非空 signature block 数量到 request_plan(history_signature_count),不记录签名内容。
  • redacted_thinking.data 是不可解释的加密数据,无法无损转成请求侧 reasoning;请求历史中的 redacted data 会被丢弃。native Anthropic 响应中明确存在的 signature / redacted data 由第二批私有 roundtrip 字段(_opencode2api_anthropic_content)保留,仅用于 Claude Messages 往返,Chat/Responses 公共 payload 不会泄漏这些私有字段。
  • 无 Chat Completions 等价物的字段不进上游 body,但会绑定并记入 request_plan / body summary:context_management、cache_control、anthropic-beta、带 type 且无 input_schema 的 server tools(如 web_search_*)。
  • cache_control breakpoints 现在被保留:Claude 侧的 system[].cache_control、messages[].content[].cache_control、tools[].cache_control 会在转换到 Chat 上游时按文本/工具名重放到对应消息/工具上(config.cache_control_breakpoints 默认开启,rejectsCacheControl 列表内的 GLM/Zhipu 仍跳过),同时自动附加顶层 cache_control breakpoint;cached_tokens usage 由上游返回时映射到 prompt_tokens_details.cached_tokens 并累计到本地 stats。请求中的 cache_control 也仍然计入 cache_control_blocks 供诊断。

不支持(不实现语义)

  • prompt caching、context management、server tools 的真实能力
  • 转发 anthropic-beta 到上游

示例:

curl http://127.0.0.1:8000/v1/messages \
  -H "Content-Type: application/json" \
  -H "x-api-key: sk-your-opencode-key" \
  -d '{
    "model": "gpt-4o-mini",
    "max_tokens": 256,
    "messages": [{"role": "user", "content": "hello"}]
  }'

流式响应

stream: true 时服务会使用 SSE 返回,并在内部清理空 delta、空 finish reason 和不需要的 reasoning 字段。Responses 和 Anthropic 流式接口会把上游 Chat Completions chunk 转换成对应事件。