feat(qoder): 适配国际版每日签到 — UMID 设备风控身份 + 国际版活动 schema

核心发现(实测):
- Qoder 国际版服务端只对带 Cosy-MachineToken/Code/Type 的请求下发签到活动,
  否则 campaigns 返回空数组(国内版无此限制)
- 国际版活动 actionType=VIEW_DETAILS(国内版 CLAIM_BENEFIT),claimStatus 一致
- 活动窗口 2026-09-01~10-31,每日 10:00 (UTC+8) 刷新,领取后 30 天有效

实现:
- 新增 umid.py:从官方 npm 包 @qoder-ai/qodercli 下载并提取内嵌 UMID 二进制
  (x86_64/arm64 ELF),试跑校验后缓存到 @appdata/AgentCheckin/umid/
- qoder.py:签到前自动确保风控身份,支持国际版/国内版双 schema 活动解析
- API:/api/umid/status、/api/umid/install、/api/accounts/refresh_risk
- 前端:设置页风控身份面板(下载/状态)、账号列表「刷新风控」按钮
- 诊断:测连接返回 risk_identity / campaigns_debug(原始字段)

验证:NAS 实测 Qoder 国际版从「活动列表为空」变为「今日已领取(75 积分)」
测试:37 后端 + 25 E2E + 9 前端,全部通过
This commit is contained in:
cbb
2026-10-19 12:04:44 +08:00
parent a3b84d5ce2
commit c263edc3e7
10 changed files with 484 additions and 17 deletions
+34
View File
@@ -203,6 +203,37 @@ def h_fix_qoder_domain(_params, body):
return {"ok": False, "probe": probe,
"error": "两个站点均无法认证(Token 可能已过期),请重新获取 Token"}
def h_umid_status(_params, _body):
"""Qoder 风控身份(UMID runtime-info)安装状态。"""
import umid as _u
return _u.status()
def h_umid_install(_params, _body):
"""下载官方 qodercli 并提取 runtime-info(约 30MB,耗时 1-3 分钟)。"""
import umid as _u
ok, msg = _u.install(force=bool((_body or {}).get("force")))
return {"ok": ok, "message": msg, "status": _u.status()}
def h_qoder_refresh_risk(_params, body):
"""为某个 Qoder 账号重新生成风控身份。"""
acc_id = body.get("id")
if not acc_id:
return ("error", "缺少 id")
accounts = load_accounts()
acc = engine.find_account(accounts, acc_id)
if not acc or acc.get("platform") != "qoder":
return ("error", "账号不存在或不是 Qoder 账号")
import qoder as _q
tok, code, mtype, err = _q.risk_identity(acc, force=True)
if err:
return {"ok": False, "error": err}
engine.save_accounts([acc if a.get("id") == acc_id else a for a in accounts])
return {"ok": True, "machineToken": tok[:12] + "…", "machineCode": code, "machineType": mtype}
def h_delete_account(_params, body):
acc_id = body.get("id")
if not acc_id:
@@ -356,6 +387,9 @@ ROUTES = {
("POST", "/api/accounts/test"): h_test_account,
("POST", "/api/wb_oauth_begin"): h_wb_oauth_begin,
("GET", "/api/wb_oauth_poll"): h_wb_oauth_poll,
("GET", "/api/umid/status"): h_umid_status,
("POST", "/api/umid/install"): h_umid_install,
("POST", "/api/accounts/refresh_risk"): h_qoder_refresh_risk,
("GET", "/api/settings"): h_settings_get,
("POST", "/api/settings"): h_settings_post,
("GET", "/api/logs"): h_logs,