Files
ModelRouter/docs/channels-parity.md
JianFeeeee 1586a051da fix(channels): CodeArts 签名按参考重写(华为云 SDK-HMAC-SHA256)+ 完整 4 步领取
## 问题:签名是实现者凭印象编的
原实现用 `SDK-HMAC-SHA256 Credential={ak}/{ts}/{nonce}/sdk_request` —— 那是另一套
协议(阿里风格)的形状,与参考的**华为云 SDK-HMAC-SHA256** 完全不同:
- canonical request 拼装错(参考是 METHOD\nURI\nQUERY\n排序后的 k:v 行\n\nSIGNEDHEADERS\nPAYLOADHASH)
- string-to-sign 格式错(参考是 "SDK-HMAC-SHA256\n{dateStamp}\n{sha256(canonical)}")
- Authorization 头用 Credential= 而非 **Access=**
- 少了 x-sdk-content-sha256 / x-security-token 参与签名
- URI 末尾未补 '/'
⇒ 服务端只会回 `APIG.0301 ... verify ak sk signature fail`,看起来像"账号/权限问题",
这个平台注定领不到额度。

## 修
逐行对齐参考 `sign.ts:signRequestHuawei` + `codearts-credits.ts`:
1. canonical request / string-to-sign / signature 全部照参考
2. 参与签名的头:host / x-sdk-date / x-sdk-content-sha256 / x-security-token
   (非 GET 再加 content-type),按字典序拼 SignedHeaders
3. Authorization = `SDK-HMAC-SHA256 Access={ak},SignedHeaders=…,Signature=…`
4. Agent-Type / X-Language 是**签名后**追加的,绝不进 canonical(否则验签失败)
5. URI 末尾补 '/'
6. 完整领取 4 步(参考的 6 步判定顺序):账户类型 → 活动列表 → claim →(benefit.id
   非空时)confirm;用 done 哨兵回给 claim_daily(它自己发多个请求,契约只发一个)
   - 非积分账户 → inactive(Token 账户不该被报成"领取失败")
   - activity.claimable=false 且状态属已领取态 → already-claimed(**唯一的幂等保护**,
     本协议没有幂等键)
   - confirm 失败不算整体失败(积分已在待确认态),只是降级提示

## 判据(差分,与参考逐字节一致)
`TestCodeArtsSignatureMatchesReference` + `tools/codearts_sig_expected.mjs`
(照抄参考函数生成期望值)。覆盖 canonical / string_to_sign / signature /
SignedHeaders / Authorization 形状 / canonical 不得含签名后追加的头。
变异验证:`Access=`→`Credential=`、去掉 content-type 参与签名、URI 不补斜杠
—— 三个全部被抓。

★ 修判据自身缺陷:首版探针**自己重算** canonical,导致真实签名被改坏时判据仍绿
(去掉 content-type 的变异存活)。改为让签名函数返回真实中间值,探针直接取用。

## 文档
新增 docs/channels-parity.md:与参考逐平台对齐清单(登录 / 额度 / 推理链路三张表
+ 差分判据表 + 未对齐项按影响排序),未对齐项**明示**而非含糊。
2026-10-13 15:38:35 +08:00

4.8 KiB
Raw Blame History

channels 插件与参考实现(dsh-our-free-model / channel-pack)的对齐清单

参考位置:vendor/channel-pack/src/(本地克隆 /tmp/pi-github-repos/Ebony-Vinyl/dsh-our-free-model/)。 对齐口径:照对方代码行为逐行移植,并配「与参考逐字节一致」的差分判据。

状态口径:

  • ✅ 已对齐(有实现 + 有判据,关键算法与参考做逐字节差分)
  • ⚠️ 部分对齐(主链路可用,高阶环节缺失)
  • ❌ 未对齐(参考有的环节没有实现)

一、登录(登录 = 拿到凭据并接入上游源)

平台 flow 参考模块 状态 说明
trae callback trae-oauth.ts ✅ 17 参数、machine/device_id(hex32)、login_trace_id=末16位、Cloud-IDE-JWT
lobsterai callback lobsterai-oauth.ts ✅ loopback /auth/callback、5 字段交换、版本号动态解析(远端 data.value.version)
gemini callback gemini-oauth.ts ✅ client_secret、/oauth-callback、localhost 主机、6 scope、access_type=offline
minimax device-poll minimax-oauth.ts ✅ PKCE S256 设备码、scope/audience
cline device-poll cline-oauth.ts ✅ WorkOS 设备码 → register 两跳
qoder device-poll qoder-oauth.ts ⚠️ 登录是纯 HTTP PKCE(已对齐);加密推理需 WASM(见三)
zcode init-poll zcode-login.ts ⚠️ 登录链路已对齐;领取需滑块验证码(见三)
loomy wechat-poll loomy-wechat-login.ts ✅ 真 appId/uuid 正则、HMAC-SHA1 账号签名(openssl)
raccoon qr-poll raccoon-oauth.ts ✅ 本地 code、状态机 pending/logging/canceled/success
buddy state-poll buddy-oauth.ts ✅ state→token 轮询
opencode paste opencode-auth.ts ✅ 手动 key
codearts paste — ✅ 手动凭据

二、额度(领额度 = 每日领取 + 余额查询)

平台 参考模块 状态 说明
codearts codearts-credits.ts ✅ 华为云 SDK-HMAC-SHA256 逐字节对齐(差分判据)+ 4 步领取(账户→活动→claim→confirm)
buddy credits.ts ✅ 双层嵌套余额、身份头、只累加有效包
trae trae-credits.ts ✅ Cloud-IDE-JWT + 派生设备身份(差分判据)
lobsterai lobsterai-credits.ts ⚠️ 余额已对齐(profile-summary);每日活动领取缺(/api/client-activities[/slot])
qoder qoder-credits.ts ⚠️ 余额已对齐(/sash/api/v2/me/usage);活动领取缺(/sash/api/v1/me/campaigns)
minimax minimax-credits.ts ✅ 两步签到(status + claim)
cline cline-quota.ts ✅ plan usage-limits
其余 — ⚠️ 参考无额度端点,如实显示"不可用"(不编造)

三、推理链路(高阶,参考有专门模块)

平台 参考模块 状态 影响
qoder qoder-wasm.ts (706) + qoder-envelope.ts (226) + qoder-machine.ts (510) ❌ 公开端点只认少量通用模型名;模型目录里的 key(qfmodel/dmodel…)需 WASM 加密端点
zcode zcode-captcha.ts (2119) + zcode-carrier*.ts ❌ 模型请求自 3.14.4 起不再索要验证码;领取始终索要(code 3007),且一次性
gemini gemini-sigstore.ts (268) ❌ thoughtSignature 缓存;缺失不报错但可能悄悄降质
loomy loomy-sign.ts ✅ 已对齐(仅账号端点用,唯一调用不带 query)
各平台 captcha-*.ts (6 模块 1223 行) ❌ 验证码池/载体/退避

四、差分判据(关键算法的"与参考一致"证据)

判据 覆盖 生成器
TestCodeArtsSignatureMatchesReference 华为云 canonical / string-to-sign / signature / SignedHeaders / Authorization tools/codearts_sig_expected.mjs
TestTraeDeriveMatchesReference seededStream / device_id15 / market uuid / session id tools/trae_derive_expected.mjs
TestTraeCheckinHeaders Cloud-IDE-JWT + 派生设备身份 + 客户端头
TestCallbackPlatformsLoopback 三平台回调路径 + state 规则(Trae 无 state)
TestLobsterLoopbackClosedLoop 有道 loopback 闭环 + state 拒绝 + 凭据完整性
TestXDisplaySelectionReclaimsStaleLocks 浏览器栈显示器锁回收(防号段烧穿)

五、已知未对齐项汇总(按对用户的影响排序)

  1. qoder 加密推理(WASM) — 影响:拿不到模型目录里的 key(如 Qwen 系列)
  2. zcode 领取验证码 — 影响:模型可用,但每日额度领不到(3007)
  3. lobsterai / qoder 活动领取 — 影响:余额能看,活动奖励领不到
  4. gemini thoughtSignature 缓存 — 影响:工具调用质量可能悄悄下降
  5. captcha 池/载体(6 模块) — 影响:zcode 领取的前置基础设施