Files
AgentCheckin 556e45d642 feat(qoder): 弄清国际版每日 100 Credits 的「按设备下发」规则 + 一键设备授权登录
排查结论(本机对真实接口做了 30+ 组对照实验)
- GET /sash/api/v1/me/campaigns 只返回一条常驻 VIEW_DETAILS 广告
  (act-20260901-493,BOGO 订阅推广,claimStatus=CLAIMED 与签到无关)
- 无论 Cosy-MachineToken/Code/Type 用 env 0/3/4/prod、裸调用/带 stdin、
  是否附 Cosy-MachineId/OS/Hostname/Origin/Referer/X-*、是否带 clientType,
  都拿不到 CLAIM_BEFIT 轮次;账号本人 balances/achievements 正常
- 三个社区实现(qoder2api-hub、dsh-connect-qoder、CreditDaddy)一致:
  每日轮次按「登录过官方客户端的那台设备」下发,NAS 侧另造的设备看不到它

修复
- _benefits() 改为只认 actionType=CLAIM_BEFIT(不再把 VIEW_DETAILS 当签到),
  窗口过期也排除;claimStatus 未知按可领处理(领取接口幂等)
- 两段式取活动:先裸取拿 uid → 按 uid 生成风控身份 → 再带设备身份重取
- 状态文案改为「未下发每日签到活动」而不是误导性的「今日已领取」

新功能
- Qoder 一键登录(OAuth 设备授权 / PKCE S256):应用内点按钮 → 浏览器确认一次,
  Token 直接绑定本机设备;同 uid 已存在则更新凭证而不是新增重复账号
- 手工导入桌面端设备身份接口 /api/qoder/import_device
- 诊断接口:/api/qoder/{probe,experiment,growth,matrix,desktop}

测试:39 后端 + 25 E2E + 9 前端全绿
2026-10-19 12:49:06 +08:00

249 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Agent 签到助手(AgentCheckin)· 飞牛 fnOS 应用
TRAE、WorkBuddy / CodeBuddy 等 AI 编程工具的**每日积分自动签到**系统,以飞牛 fnOS 第三方应用(`.fpk`)形式运行。签到由 NAS 本地守护进程自动执行,多账号、多时段补签、积分看板、运行日志一应俱全。
> 非官方工具,仅供个人学习交流。接口来自社区逆向与实测,可能随官方调整失效。
## 每天能领多少
| 平台 | 规则 | 每月约 |
|---|---|---|
| TRAE(字节跳动·国内版) | 每天 200 Work 专属积分 | ≈ 6200 分 |
| WorkBuddy / CodeBuddy(腾讯) | 第 1-6 天每天 100 分,第 7 天 1000 分(7 天循环) | ≈ 6800 分 |
| Qoder(国内版) | 每天 100 Credits(活动非零点准时下发,自动补领) | ≈ 3000 Credits |
## 功能特性
- **三平台签到**:TRAE(字节·国内版,每日 200 积分)+ WorkBuddy / CodeBuddy(腾讯,7 天循环最高 1000 分/天)+ Qoder(国内版,每日 100 Credits)
- **多账号管理**:任意数量账号,独立启用/禁用,互不影响
- **WorkBuddy 网页授权**:生成官方登录链接,浏览器扫码/登录后自动绑定,无需手动抄 Token
- **多时段自动补签**:默认每天 00:05 / 09:00 / 12:30 / 19:00 四个时段,已签自动跳过;NAS 重启后自动补跑
- **幂等安全**:每次签到前先查状态,已签跳过;领取后回查服务器确认到账
- **TRAE 风控自愈**:触发 9074 设备号风控时自动更换设备号重试
- **Token 自动续期**:WorkBuddy 过期前自动用 refreshToken 续期;失效账号标记「需重新授权」
- **积分看板**:TRAE 当前积分、WorkBuddy 剩余额度实时展示
- **Webhook 通知**(可选):签到结果推送到企业微信/钉钉/飞书/Bark/Server酱/PushPlus 等机器人(按 URL 自动识别平台格式,也可手动指定)
- **数据本地化**:所有凭据仅保存在 NAS `@appdata/AgentCheckin`,不明文展示、不上传
## 快速开始
### 方式一:自动安装(推荐,已在 192.168.31.10 验证通过)
```bash
cd fnos-agent-checkin
./build.sh # 打包 AgentCheckin.fpk
FNOS_HOST=192.168.31.10 \
FNOS_USER=你的NAS管理员 \
FNOS_PASS=你的密码 \
node fnos-install.js # 自动上传并安装
```
安装脚本会自动处理:
- WebSocket 登录 → ticket → ost 会话 Cookie
- **依赖检测**:`install_dep_apps=python312` 未安装时安装会失败(code 16005),
需先在应用中心安装「Python 3.12」(或参考 `install_python312_full.js` 的云应用下载流程)
- **重复安装**:已安装时自动先卸载再安装(`@appdata` 数据保留)
### 方式二:手动安装
1. `./build.sh` 生成 `AgentCheckin/AgentCheckin.fpk`
2. 飞牛 Web 管理界面 → 应用中心 → 右上角「手动安装」→ 选择 fpk
3. 或设备命令行:`appcenter-cli install-fpk AgentCheckin.fpk`
安装后桌面/启动台出现「Agent 签到助手」图标,点击即可打开管理面板
(也可直接访问 `https://<NAS>:5667/cgi/ThirdParty/AgentCheckin/index.cgi/`)。
### 添加账号
**WorkBuddy(推荐网页授权)**
1. 管理面板 → 账号管理 → 添加账号 → 「WorkBuddy 网页授权」
2. 点击「生成授权链接」,在浏览器打开链接
3. 登录腾讯 CodeBuddy / WorkBuddy 账号(手机号/微信)
4. 页面自动完成绑定,无需其他操作
**WorkBuddy(手动)**:粘贴 accessToken(+ 可选 refreshToken)。
**TRAE**:粘贴 accessToken(`eyJ` 开头的 JWT)。
获取 TRAE Token:在登录了 TRAE 国内版客户端的电脑上,凭据在
`%APPDATA%\Trae CN\User\globalStorage\storage.json`,键
`iCubeAuthInfo://icube.cloudide` 的值为加密串(AES-128-CBC),解密后即得
`token`。也可用社区工具 `trae_get_token.py`(Trae-AutoCheckin 项目)一键提取。
Token 约 60 天有效,过期后在面板重新粘贴即可。
**Qoder**:粘贴 accessToken(`dt-` 开头)+ 可选 refreshToken(`drt-` 开头)。
获取 Qoder Token(三种方式,任选其一):
| 方式 | 操作 | 适合 |
|---|---|---|
| **A · 应用内一键登录(推荐)** | 添加账号 → Qoder → 点「一键登录(设备授权)」,浏览器里确认一次即可(PKCE S256 设备流)。**国际版必须走这条**:每日 100 Credits 只下发给登录过的那台设备 | 所有人,无需抓包 |
| **B · 浏览器抓包(最快)** | 浏览器登录 Qoder 网页版 → F12 开发者工具 → 网络 → 任选一个请求,看请求头 `authorization: Bearer dt-...`,`dt-` 后那串即 Access Token;若还能看到 `drt-...` 刷新串,一并填入可自动续期 | 会看开发者工具 |
| **C · 本机客户端提取** | 在装了并登录 Qoder 客户端的 Windows 上运行 `01_extract.py`([wallechfox/qoder-checkin](https://github.com/wallechfox/qoder-checkin)),自动 DPAPI+AES-GCM 解密 `%APPDATA%\com.qodercn.app.*\auth.v1.dat` 取出 Token 和设备标识 | 需要设备标识时 |
> 注意:方式 C 必须在**登录 Qoder 的同一个 Windows 用户**下运行(DPAPI 绑定用户身份)。
> 若同时安装了国内版和国际版客户端,`01_extract.py` 会解出两套 Token——
> 签到时用**国内版**那套(qoder.cn / QQ 邮箱账号),并在面板选国内站域名。
> Qoder Token 有效期较短(约两周),过期后重新获取粘贴即可;填了 Refresh Token 后应用会自动续期。
> **风控身份自动处理**:应用会从官方 `@qoder-ai/qodercli` 提取 UMID 组件自动生成
> Cosy-* 风控身份(首次约下载 30MB,之后缓存)。可在 设置 → Qoder 风控身份 查看状态、
> 或在账号列表点「刷新风控」重新生成。
## 使用说明
- **仪表盘**:今日各账号签到状态、积分、下次自动签到时间;可手动「立即签到」
- **账号管理**:添加/启用/禁用/删除账号,Token 脱敏展示,「测连接」验证凭据有效性
- **签到记录**:完整运行日志(含每次签到的结果与积分变化)
- **设置**:自定义签到时间点、Webhook 通知地址与通知时机
## 项目结构
```
fnos-agent-checkin/
├── AgentCheckin/ # fnpack 应用项目(fpk 源码)
│ ├── manifest # 应用元数据(install_dep_apps=python312)
│ ├── ICON.PNG / ICON_256.PNG
│ ├── config/
│ │ ├── privilege # 运行用户 agentcheckin
│ │ └── resource
│ ├── cmd/ # 生命周期脚本
│ │ └── main # start/stop/status 管理调度守护进程
│ ├── app/
│ │ ├── ui/
│ │ │ ├── index.cgi # CGI 入口:静态文件 + /api 路由
│ │ │ ├── config # 桌面入口配置
│ │ │ └── images/
│ │ ├── backend/ # Python 后端
│ │ │ ├── common.py # 路径/HTTP/原子存储/日志
│ │ │ ├── workbuddy.py # WorkBuddy OAuth + 签到 + 积分 + 续期
│ │ │ ├── trae.py # TRAE 签到(设备号管理/9074 换号)
│ │ │ ├── engine.py # 账号编排/结果记录/通知
│ │ │ ├── api.py # CGI JSON API
│ │ │ └── daemon.py # 调度守护进程
│ │ └── www/ # 前端(原生 HTML/CSS/JS,无第三方依赖)
├── genicon.py # 图标生成(纯标准库)
├── build.sh # 一键打包
├── fnos-install.js # NAS 自动安装(应用中心 API)
├── test_backend.py # 后端单元/接口测试(20 项)
├── test_e2e.py # 端到端测试(模拟 fnOS 布局,25 项)
├── test_schedule.py # 真实时钟调度测试
├── test_settings_ui.js # 设置页前端回归测试(DOM 桩,9 项)
├── test_live_nas.py # 真机全链路测试(需 NAS 凭据)
└── README.md
```
## 技术形态
- **原生 fnOS 应用**(非 Docker):CGI 入口 + Python 守护进程,沿用 fnOS 登录态校验
- 运行时依赖 `python312`(fnOS 应用中心运行时包,安装时自动拉起;缺失时回退系统 python3)
- 数据目录:`/vol{N}/@appdata/AgentCheckin/`(accounts.json / settings.json / state.json / logs/)
- 端口:不监听端口(纯 CGI),`checkport=false`
## 签到接口(社区逆向,仅供参考)
**WorkBuddy(CN: www.codebuddy.cn)**
| 功能 | 端点 |
|---|---|
| 签到状态 | `POST /v2/billing/meter/checkin-activity-status` |
| 执行签到 | `POST /v2/billing/meter/daily-checkin` |
| 积分查询 | `POST /v2/billing/meter/get-user-resource` |
| Token 续期 | `POST copilot.tencent.com/v2/plugin/auth/token/refresh` |
| 网页授权 | `POST /v2/plugin/auth/state` → 浏览器登录 → `GET /v2/plugin/auth/token?state=` |
**Qoder(openapi.qoder.com.cn)**
| 功能 | 端点 |
|---|---|
| 活动列表 | `GET /sash/api/v1/me/campaigns` |
| 领取 | `POST /sash/api/v1/me/campaigns/{cid}/claim` |
| Token 续期 | `POST /api/v1/deviceToken/refresh` |
请求需带 `Authorization: Bearer <token>` 与 Cosy-* 设备标识头。
> ⚠️ **重要实测结论**:
> 1. **Token 格式**:Qoder 的 `dt-`/`drt-` Token 原生就只有 **27/28 个字符**,不是截断。
> 2. **站点隔离**:国内版(qoder.cn 客户端)的 Token 只能用于 `openapi.qoder.com.cn`,
> 国际版(qoder.com 客户端)的 Token 只能用于 `openapi.qoder.sh`,混用直接 401。
> 面板的「修复站点」按钮会自动探测 Token 所属站点并切换。
> 3. **只有 `actionType=CLAIM_BENEFIT` 才是签到轮次**:同一个账号还挂着一条
> `actionType=VIEW_DETAILS` 的订阅推广(无 benefit、`claimStatus` 却是 `CLAIMED`),
> 只看 `claimStatus` 会把它误当成「今日已领取」。响应顶层的 `claimable` 也不可信——
> 「今天已领」和「当前没有活动」它都返回 `false`。
> 4. **国际版的每日 100 Credits 按「设备」下发**(实测 + 社区一致结论):服务端只把
> `CLAIM_BEFIT` 轮次下发给**登录过官方客户端的那台设备**;从 NAS 上另造一套
> `Cosy-MachineToken/Code/Type` 只能拿到常驻的 `VIEW_DETAILS` 广告,活动列表里
> 根本没有每日轮次(这就是「活动列表为空 / 看不到 100 Credits」的根因)。
> 本应用因此提供**「一键登录(设备授权,PKCE S256)」**:把登录绑定到本机,
> 之后才能看到并领取每日轮次;也支持把桌面客户端那台机器的
> `machineToken/Code/Type` 导入进来复用它的设备身份。
> 每日 10:00 (UTC+8) 刷新,错过不补,领取后 30 天有效;同一台设备每天只有一个
> 国际版账号能领到。
**TRAE(api.trae.cn)**
| 功能 | 端点 |
|---|---|
| 签到状态 | `POST /trae/api/v2/ug/checkin_credits/status` |
| 执行签到 | `POST /trae/api/v2/ug/checkin_credits/claim` |
## 常见问题
**Q:需要每天开着 WorkBuddy / TRAE 客户端吗?**
不需要。用的是登录时保存的凭据。只有约 60 天完全不用导致凭据过期时,才需要重新授权(面板会标记「需重新授权」并推送通知)。
**Q:应用中心里显示未运行?**
到 设置 → 应用 → AgentCheckin 点「启动」;或检查 `@appdata/AgentCheckin/daemon.out` 日志。确认 `python312` 运行时已随依赖安装。
**Q:签到失败会怎样?**
每个时段都会重试;TRAE 9074 风控会自动换设备号。全天失败且配置了 Webhook 时会推送通知。日志中可看到每次失败原因。
**Q:想改签到时间?**
设置页增删时间点即可,保存后守护进程下个 tick 生效。
## 免责声明
本项目仅供个人学习与研究使用,与腾讯、字节跳动无任何隶属关系。使用本工具产生的一切后果由使用者自行承担,请遵守各平台服务条款。
## 致谢
签到接口逻辑参考社区开源项目:[wb-trae-checkin](https://github.com/3338320742zh-collab/wb-trae-checkin)、
[workbuddy-checkin](https://github.com/Maquer/workbuddy-checkin)、
[Trae-AutoCheckin](https://github.com/L0NE-6/Trae-AutoCheckin)(MIT)。
## Webhook 通知申请教程
设置页 →「消息通知」→ 填入机器人 Webhook 地址(平台会自动识别,也可手动指定)。
### 企业微信群机器人(免费,推荐)
1. 手机/电脑安装「企业微信」,用手机号注册(个人可免费创建企业)
2. 创建一个内部群聊(或任选一个群)
3. 群聊右上角「…」→ **群机器人** → 添加机器人 → 复制 Webhook 地址
4. 地址形如 `https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=xxx-xxx-xxx`
### 钉钉群机器人(免费)
1. 钉钉 APP → 进入一个群 → 群设置 → **机器人** → 添加机器人 → **自定义(通过 Webhook 接入)**
2. 安全设置选「**自定义关键词**」,填写 `签到`(通知内容含该词才会放行)
3. 复制 Webhook 地址,形如 `https://oapi.dingtalk.com/robot/send?access_token=xxx`
### 飞书群机器人(免费)
1. 飞书 APP → 进入一个群 → 群设置 → **群机器人** → 添加机器人 → **自定义机器人**
2. 安全设置同样建议选「自定义关键词」填 `签到`
3. 复制 Webhook 地址,形如 `https://open.feishu.cn/open-apis/bot/v2/hook/xxx`
### Bark(iOS 推送,免费)
1. App Store 下载 **Bark**
2. 打开后首页即显示推送地址,形如 `https://api.day.app/XXXXXXXX/`
3. 整条复制粘贴即可(系统自动使用 Bark 的 URL 路径格式)
### Server酱 / PushPlus(微信模板消息)
- **Server酱**:微信扫码登录 `sct.ftqq.com` → 复制 SendKey → 地址填 `https://sctapi.ftqq.com/<SendKey>.send`
- **PushPlus**:`pushplus.plus` 登录 → 复制 token → 地址填 `http://www.pushplus.plus/send?token=<token>`
> 留空 Webhook 地址则不发送任何通知。测试按钮会先保存设置再触发一次真实签到,通知随结果一起送达。