CLIProxyAPI OpenAI-compatible `(high)` alias auth_not_found 修复与 8317 systemd 正式化
cpa-codex / CLIProxyAPI 的 OpenAI-compatible alias 在官方 v7.1.47 和官方 v7.1.50 下都存在真实运行时缺陷:形如 YT-GPT-5.5(high) 的模型虽然能在 /v1/models 列出来,但 chat 请求会在 0ms 内被本地 runtime 过滤掉,返回 auth_not_found。本次已在本机基于最新 v7.1.50 做最小修复,并已切到 live 8317。
保留修复版作为当前 live;不要用“去掉 (high) alias”作为长期方案。该 workaround 只能绕过问题,不能修复 runtime 行为,也会让模型名语义和配置口径变得不稳定。下一步应把这个最小补丁整理成面向官方的 PR,只提交通用代码和测试,不带任何本地隐私配置。
官方 v7.1.50 staging 在 18317 上复现:/v1/models 200,但 YT/ANY/JUN alias chat 都是 503 auth_not_found,且耗时 0ms;本地修复后,在 staging 18317 和 live 8317 上都验证通过:/v1/models 200,YT-GPT-5.5(high) / YT-GPT-5.4(high) / ANY-5.5(high) / JUN-GPT-5.5(high) 非流式返回 200,流式也返回 200;8317 现已纳入 systemd --user 服务 cli-proxy-api-8317.service 正式托管,不再依赖手工前台/后台进程。
当前先把修复版作为稳定 live 基线,保留 8317 systemd 托管;对外只推进通用补丁和 regression test,不把本机 alias 命名、私有 provider 配置或备份路径带进官方 PR。
证据摘要
- 官方
v7.1.50staging 在18317上复现:/v1/models200,但YT/ANY/JUNalias chat 都是503 auth_not_found,且耗时 0ms;本地修复后,在 staging18317和 live8317上都验证通过:/v1/models200,YT-GPT-5.5(high)/YT-GPT-5.4(high)/ANY-5.5(high)/JUN-GPT-5.5(high)非流式返回 200,流式也返回 200;8317现已纳入systemd --user服务cli-proxy-api-8317.service正式托管,不再依赖手工前台/后台进程。
行动清单
(high) alias 语义来掩盖 runtime bug。边界 / 风险
当前 live 使用的是基于官方 v7.1.50 的本地修复版,不是官方原版二进制。 本地 OpenAI-compatible provider 名、别名命名、真实上游和 key 都属于隐私/环境特定信息,不能直接带进官方 PR。 ANY 在 max_tokens=8 时会返回上游 400 integer_below_min_value,这不是 auth 调度故障;验证时需要给足 token。
完整记录
CLIProxyAPI OpenAI-compatible (high) alias auth_not_found 修复与 8317 systemd 正式化
证据摘要
- 官方
v7.1.50原版在 staging18317可稳定复现auth_not_found,说明不是 WebUI 或管理端误报。 - 修复版在 staging
18317与 live8317都通过/v1/models、non-stream、stream 三层验证。 - live 当前由
cli-proxy-api-8317.service托管,cpa-manager-plus.service仍保持在8318,控制面未被这次修复扰动。
下一步
- 保持修复版 live 运行,继续观察 alias 调用稳定性。
- 将本次通用修复整理为无隐私的官方 PR。
- 不把 workaround 当长期方案,不删除
(high)alias 语义来掩盖 runtime bug。
风险与边界
- 当前 live 使用的是基于官方
v7.1.50的本地修复版,不是官方原版二进制。 - 本地 OpenAI-compatible provider 名、别名命名、真实上游和 key 都属于隐私/环境特定信息,不能直接带进官方 PR。
ANY在max_tokens=8时会返回上游 400integer_below_min_value,这不是 auth 调度故障;验证时需要给足 token。
背景
涛哥反馈:cpa-codex 里多个模型“都调用不通了”。前置排查确认:
8317是CLIProxyAPI数据面;8318是CPA-Manager-Plus管理面。/v1/models依然能列出YT-GPT-5.5(high)、YT-GPT-5.4(high)、ANY-5.5(high)、JUN-GPT-5.5(high)这些 alias。- 但 chat completions 在本地就 0ms 失败,没有进入真实上游。
因此问题不在 WebUI,不在 Hermes provider catalog,也不在 CPA-Manager-Plus 控制面,而在 CLIProxyAPI runtime 自身的 auth/model candidate 过滤逻辑。
根因拆解
1. 真正击穿 live 的主因:suffixed alias 与 registry 查询名不一致
运行路径里,authSupportsRouteModel() 会用 canonicalModelKey(routeModel) 去判断某个 auth 是否支持请求模型;而 canonicalModelKey() 会把 (high) 这样的 thinking suffix 剥掉。
这就造成了错位:
- registry 注册的是用户可见 alias,例如
YT-GPT-5.5(high); - 调度查询时却变成
yt-gpt-5.5; - 两边对不上,candidate auth 在真正调用前就被筛空;
- 最终表现为
auth_not_found,而且因为没打上游,所以耗时接近 0ms。
2. 次级防御性问题:executor provider key 大小写/规范化不一致
OpenAI-compatible executor 和 auth/provider 名可能来自不同入口。为了避免 YT / yt、AnyRouter-Adapter / anyrouter-adapter 这种大小写差异在 legacy path 或 fallback path 里继续踩坑,本次顺手把 executor map 的注册和查询都收口为同一个 trim+lowercase helper。
这个问题不是本次 live 故障唯一主因,但不修会留下隐性炸点。
修复方案
代码修复
在 sdk/cliproxy/auth/conductor.go 中做了两类最小改动:
- 新增统一的
executorProviderKey(provider string),把RegisterExecutor()、Executor()、UnregisterExecutor()、legacy pick、refresh、credential inject 等路径全部收口到同一 provider key 规范。 - 调整
authSupportsRouteModel():
- 先按原始
routeModel查 registry; - 原始 alias 不命中时,再 fallback 到 canonical model key 和 selection key。
同时补了回归测试:
TestManagerExecutorReturnsRegisteredExecutorTestManagerMixedLegacyFindsExecutorWithCanonicalProviderKey
后者覆盖了“大写 executor id + 小写 auth provider + (high) alias route model”的实际故障形态。
运行方式修复
把 8317 从手工进程切到 systemd --user:
- unit:
~/.config/systemd/user/cli-proxy-api-8317.service - cwd:
/home/ht/cli-proxy-api - ExecStart:
/home/ht/cli-proxy-api/cli-proxy-api
这样后续重启、开机恢复、观察和回滚都更稳,不会再靠临时 shell 进程维持 live。
验证结果
官方 v7.1.50 staging 复现
在 18317 上使用官方二进制复现到:
修复版 staging 验证
修复版切到 18317 后:
live 8317 验证
切 live 并接入 systemd 后再次实测:
当前运行态
- live data-plane:
127.0.0.1:8317 - live unit:
cli-proxy-api-8317.service - manager sidecar:
cpa-manager-plus.serviceat127.0.0.1:8318 - live fixed binary sha256:
8563eefec0d2af655bed7babf60577e9c0ca0f77cb176b63afe45337eff7f0d7 - pre-cutover backup:
/home/ht/cli-proxy-api/backups/pre-v7150-canonical-executor-20260607-174924
采取的动作
- 复现官方
v7.1.50staging 故障。 - 在本地源码中修复 runtime candidate 过滤。
- 增加 focused regression test。
- 编译修复版并在
18317staging 验证非流式和流式。 - 备份 live
8317二进制和配置。 - 将修复版切到 live
8317。 - 将
8317纳入systemd --user正式托管。 - 再次进行 live API 验证。
- 整理本次排障经验,准备 wiki/HTML 与上游 PR。
回滚与边界
回滚
如需回退到切换前二进制:
上游 PR 边界
官方 PR 只提交:
conductor.go的通用修复;- 对应 regression tests;
- 干净的 PR 描述与复现方式。
官方 PR 不提交:
- 本机
config.yaml - 任何 key、token、base URL
- 本机路径、backup/staging 目录
- HTML、wiki、排障日志原文
- 私有 provider 命名或供应商配置细节
长期经验
/v1/models正常不代表 chat 路径正常,尤其是 alias + routing + auth 三层可能在 runtime 才断。- 带 suffix 的 alias 要同时核对“registry 注册名”和“调度查询名”。
- OpenAI-compatible alias 故障必须同时测
/v1/models、non-stream、stream,不能只测一个文本 200。 - 类似
8317这种 live 数据面要尽快 systemd 化,避免“功能修好了但运行态不可控”。 - 对官方提 PR 时,要把“本机问题”压缩为“通用 runtime 行为缺陷”,否则容易把隐私、环境噪音和产品口径绑进 patch。