AnyRouter Codex Adapter 接入 CPA:从假成功到可用工具桥
AnyRouter 不能直接作为普通 OpenAI-compatible upstream 挂入 CPA;必须通过本地 Codex-shape adapter 模拟 Codex CLI /v1/responses 请求,才能稳定把 gpt-5.5 暴露为 CPA alias ANY-5.5。
保留 CPA 原生 Codex OAuth 作为主路,ANY-5.5 作为实验/备用 provider;adapter 继续本地监听 127.0.0.1:8331,CPA 通过 openai-compatibility 接入。
直连 AnyRouter TLS 会 SSLV3_ALERT_HANDSHAKE_FAILURE,必须走 127.0.0.1:7890;普通 Chat/Responses 调用会出现 HTML 假 200 或 invalid codex request;Codex-shape body + headers 后,CPA 非流式和流式都能返回 OK,并且非流式 usage 可记录 token。
已实现 /home/ht/code/anyrouter_codex_adapter.py,已创建并启用 anyrouter-codex-adapter.service,已在 CPA config.yaml 加入 alias ANY-5.5,并补齐工具调用桥接,避免 terminal、skill_view、web_search 等工具参数 JSON 泄漏成正文。
证据摘要
- 直连 AnyRouter TLS 会
SSLV3_ALERT_HANDSHAKE_FAILURE,必须走127.0.0.1:7890;普通 Chat/Responses 调用会出现 HTML 假 200 或invalid codex request;Codex-shape body + headers 后,CPA 非流式和流式都能返回OK,并且非流式 usage 可记录 token。
行动清单
ANY-5.5 当备用 provider 观察;若要作为主模型,需要压测多工具、多轮、长上下文和流式 usage;如需系统级托管,由涛哥执行 sudo/系统级 unit 安装。边界 / 风险
AnyRouter 若改变对 Codex CLI headers/body 的校验,adapter 可能需要同步调整。
当前直连 TLS 握手失败。若 7890 不在,service 虽然启动,调用会上游失败。
非流式 usage 可记录 token;流式 CPA-Manager usage 仍可能显示 total_tokens=0,因为 Chat SSE chunk 未完整回传 usage。
当前策略是高置信才转换:必须能匹配 tools schema / wrapper / tool_choice / 常见字段。低置信 JSON 会保留正文,避免误把正常 JSON 回答变成工具调用。
完整记录
AnyRouter Codex Adapter 接入 CPA:从假成功到可用工具桥的排障复盘
背景
用户提供 AnyRouter:
- 地址:
https://anyrouter.top - 模型:
gpt-5.5 - 目标:写入 CPA 后虽然显示通了,但实际不能稳定用,尤其工具调用异常。
最初 CPA 侧出现过 “HTTP 200 成功” 记录,但深入检查后发现它们不是模型成功,而是 HTML/边缘防护页或空 token 记录。后续围绕 AnyRouter、CPA、Codex CLI 请求形态和工具桥接做了完整排障。
关键发现
1. CPA 里的早期 AnyRouter 成功是“假成功”
CPA-Manager usage 中有 provider=any 的记录,表面:
- HTTP 200
failed=false- path 包含
/v1/chat/completions或/v1/responses
但 raw evidence 显示:
Content-Type: text/html; charset=utf-8X-Tengine-Error: denied by http_customtokens.total = 0
结论:这是边缘/WAF 返回的 HTML,不是模型 JSON/SSE 响应。
2. 真正成功的 23:36 附近调用是 CPA 原生 Codex OAuth
当时 request_id 6a103d71:
- provider:
codex - executor_type:
CodexExecutor - model:
gpt-5.5-high - resolved_model:
gpt-5.5 - total_tokens:
119639
这条与 AnyRouter 无关。
3. AnyRouter 直连不能省代理
A/B 测试:
- direct no proxy:
SSLV3_ALERT_HANDSHAKE_FAILURE - via
http://127.0.0.1:7890:可进入 API/SSE 层
因此 adapter service 当前必须保留:
4. 普通 Chat→Responses adapter 不够,必须 Codex-shape
普通 adapter 请求会被 AnyRouter 判定:
must be stream requestinvalid codex request
抓取 Codex CLI 0.130.0 真实请求体后确认关键形态:
/v1/responsesstream: truestore: falseinclude: ["reasoning.encrypted_content"]prompt_cache_keytext: {"verbosity":"low"}client_metadata.x-codex-installation-idtool_choice: autoparallel_tool_calls: true- Codex-style tools schema
- headers:
originator,session_id,x-codex-*,x-client-request-id, Codex User-Agent
补齐后,AnyRouter 返回真实 SSE,并可转换成 OpenAI Chat Completions。
已落地内容
Adapter 文件
能力:
GET /healthGET /v1/modelsPOST /v1/chat/completionsPOST /v1/responses- Chat messages → Codex-shaped Responses input
- OpenAI tools → Responses tools
- Responses SSE → Chat Completions JSON / SSE
- 工具调用 JSON 兜底 → Chat
tool_calls
systemd --user service
当前已创建:
状态:
unit 内容:
注意:这是用户级 systemd。当前:
如果要无人登录自动启动,应执行:
或者迁移为系统级 unit。
Env 文件
权限:
包含:
ANYROUTER_KEY=<redacted>ANYROUTER_ADAPTER_HOST=127.0.0.1ANYROUTER_ADAPTER_PORT=8331ANYROUTER_BASE=https://anyrouter.top/v1ANYROUTER_DEFAULT_MODEL=gpt-5.5ANYROUTER_MODELS=gpt-5.5ANYROUTER_TIMEOUT=240ANYROUTER_REASONING_EFFORT=mediumHTTPS_PROXY=http://127.0.0.1:7890HTTP_PROXY=http://127.0.0.1:7890
CPA 配置
已备份:
新增 provider:
CPA 已热加载,无需成功重启即可在 /v1/models 看到:
验证记录
本地 adapter health
返回:
CPA 非流式 smoke
请求:
返回:
CPA 流式 smoke
请求:
返回:
多轮历史修复
失败原因:adapter 把历史 assistant 消息转成了 input_text。
AnyRouter 报:
修复:assistant 历史用 output_text。
验证:user → assistant → user 多轮请求成功:
工具调用桥接修复
用户观察到正文出现:
以及:
根因:AnyRouter/Codex 有时把工具参数 JSON 作为普通文本输出,adapter 之前没有转回 OpenAI Chat tool_calls。
已补通用规范化层,覆盖:
- 裸参数 JSON:
{"command":"date"}、{"name":"hermes-agent","file_path":""}、{"query":"Hermes Agent"} - Markdown fenced JSON
- OpenAI wrapper:
{"name":"terminal","arguments":{...}} tool_calls数组- 多工具调用数组
tool_choice强制指定- Responses 原生
function_call - 流式
delta.tool_calls
验证通过:
- terminal nonstream →
message.tool_calls[0].function.name=terminal - skill_view nonstream →
skill_view - web_search nonstream →
web_search - skill_view stream →
delta.tool_calls,无正文 JSON 泄漏
离线回归测试
新增:
测试全部通过:
系统级 unit 建议
当前用户无权限直接写 /etc/systemd/system。如果要做成系统级 systemd,可执行:
如果保留 user service,只需要补:
风险与边界
风险 1:依赖 AnyRouter 对 Codex-shape 请求的兼容
AnyRouter 若改变对 Codex CLI headers/body 的校验,adapter 可能需要同步调整。
风险 2:必须走 7890 代理
当前直连 TLS 握手失败。若 7890 不在,service 虽然启动,调用会上游失败。
风险 3:流式 usage 仍不完整
非流式 usage 可记录 token;流式 CPA-Manager usage 仍可能显示 total_tokens=0,因为 Chat SSE chunk 未完整回传 usage。
风险 4:工具 JSON 兜底不能无限激进
当前策略是高置信才转换:必须能匹配 tools schema / wrapper / tool_choice / 常见字段。低置信 JSON 会保留正文,避免误把正常 JSON 回答变成工具调用。
后续建议
ANY-5.5先作为实验/备用 provider,不替换 CPA 原生 Codex OAuth 主路。- 如果要长期跑,建议补
loginctl enable-linger ht或迁移系统级 unit。 - 后续继续观察工具调用:如出现新的 JSON 泄漏形态,优先扩展
test_anyrouter_codex_adapter_tools.py,再 patch adapter。 - 如果要用于 Hermes 主模型,建议再压测:多轮工具调用、tool result 回灌、并行工具、长上下文、流式工具调用与真实 WebUI/Feishu 两端表现。