mirror of
https://gitcode.com/JianFeeeee/ModelRouter.git
synced 2026-11-07 09:47:23 +00:00
## 参考依据 `qoder-credits.ts` 的 `claimQoderDailyCheckin` / `parseQoderCampaigns` / `claimQoderCampaign` / `hasQoderCampaignRefreshedToday`。 参考用**抓包 + 用户报障**定位过三条会「误报」的陷阱,全部在实现与判据里钉死: ### ① 「无可领活动」必须是 inactive,不能报 already-claimed 旧实现 targets 为空就说"今天已领取" ⇒ 只要服务端没下发可领项(含**请求头不完整**、 未到刷新时间、本就无活动三种情形),界面就谎报已领,与官方 IDE 的"可领取"直接矛盾。 用户报障原文:「没领过却显示今日已领取,去 IDE 看还能领」。 ### ② 每日 10:00(UTC+8)刷新;刷新前的 CLAIMED 属于**昨天** 此时说"今天已领取"是谎报,且不可逆(用户以为今天不必再领)。 必须用**算术平移**判 UTC+8 —— 用本机时区在出差/改时区时会判错方向 (偏东提前把当天记为已处理、真漏领;偏西一天判两次)。 ### ③ 未开通要给 action_required 的可操作提示 判据是**两条同时**满足(无 CLAIM_BENEFIT + 用量响应里 `addOnQuota` **字段缺失**)。 ⚠️ 用「字段是否存在」而非「remaining 是否为 0」—— 后者对"额度用光"与"从未开通" 不可区分,会把用光额度的老账号误报成未开通。文案要可操作(去官方客户端登录一次), 并作为显式字段透传给 UI,而不是让 UI 猜文案。 ### 其他要点 - 一个账号可能同时有**多个** CLAIM_BENEFIT 活动 → 逐个领取(实测有每日 100 与运营活动) - 幂等判据是响应体的 **`replayed`**,不是 HTTP 状态码:重复领取同样回 200, 但 `replayed:true` 且不含 benefit(只看状态码会把"今天已领"误报成"成功 +100") - 请求体必须是**空串**(抓包实测 `content-length: 0`) - 缺 `Cosy-MachineToken/MachineType` 时服务端不下发可领活动(见上一个提交) ## 判据 - `TestQoderClaimDecisionTable`:6 个用例覆盖四类结果 + claim 次数 + body 必须为空 - `TestQoderRefreshUsesUTC8NotLocalTime`:**注入 UTC 时刻**验证刷新判定 ★ 修判据自身两处缺陷(首轮变异存活): 1. `TestMain` 把测试进程 TZ 钉成 **UTC** —— 本机恰是 HKT(+0800),于是 「UTC 平移」与「本机时区」结果**完全相同**,误用本机时区的实现抓不到(判据不可达)。 2. 决策表缺「无任何活动且已开通(addOnQuota 存在)」用例 → 把 inactive 误报成 already-claimed 的变异得以存活。补齐后两个变异都被抓。 ## 统一前向声明(Lua 作用域,本文件第 N 次) 把 `qoderMachineIdentity / rfc3986Escape / newToken / lobsteraiClientVersion` 统一在 PLATFORMS 之前前向声明。此前逐个补、位置还放错过一次,导致运行时报 `attempt to call global 'x' (a nil value)` 而编译期静默。 ## 文档 `docs/channels-parity.md` 更新:gemini-sigstore 标注为**⛔ 不适用** (llmsproxy 的推理走无状态适配器,插件不参与推理 —— 插件侧缓存会成为死代码; 若将来要支持,位置在适配器侧,与"适配器无状态"约定冲突,须单独决策)。
5.1 KiB
5.1 KiB
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) | ⛔ 不适用 | llmsproxy 里无处安放:推理走 internal/lua/adapters/gemini.lua(无状态、请求级),插件不参与推理 —— 插件侧缓存会成为死代码。参考需要它是因为它自己代理推理。若将来要支持,位置是适配器侧(需适配器具备跨请求状态,与"适配器无状态"约定冲突,须单独决策) |
| 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 |
浏览器栈显示器锁回收(防号段烧穿) |
五、已知未对齐项汇总(按对用户的影响排序)
- qoder 加密推理(WASM) — 影响:拿不到模型目录里的 key(如 Qwen 系列)
- zcode 领取验证码 — 影响:模型可用,但每日额度领不到(3007)
- lobsterai / qoder 活动领取 — 影响:余额能看,活动奖励领不到
- gemini thoughtSignature 缓存 — 影响:工具调用质量可能悄悄下降
- captcha 池/载体(6 模块) — 影响:zcode 领取的前置基础设施