WorkBuddy 每日积分自动签到。自动解密本地登录令牌,调用官方签到 API 完成每日积分领取(100 积分/天,连续第 7 天 1000 积分),并支持配置定时任务。触发词:WorkBuddy 签到、每日积分、check-in、credits。
编程
Wb Buddy Checkin Publish
试用自动完成 WorkBuddy 桌面客户端「Buddy 加油站」每日签到、领取积分。当用户需要在 Windows 上自动点击头像→Buddy加油站→立即领取,并通过截图灰度校验是否成功(灰底「今日已领」)时使用。基于纯 ctypes 实现窗口置前、坐标点击与窗口截图,零第三方 Python 依赖,仅依赖 Windows 系统 API(可选复用 desktop-control-win skill 的截图)。
它能做什么
自动完成 WorkBuddy 桌面客户端「Buddy 加油站」每日签到、领取积分。当用户需要在 Windows 上自动点击头像→Buddy加油站→立即领取,并通过截图灰度校验是否成功(灰底「今日已领」)时使用。基于纯 ctypes 实现窗口置前、坐标点击与窗口截图,零第三方 Python 依赖,仅依赖 Windows 系统 API(可选复用 desktop-control-win skill 的截图)。
技能文档
wb-buddy-checkin —— WorkBuddy 每日签到
在 Windows 上自动给 WorkBuddy 桌面客户端的「Buddy 加油站」签到领积分(每日 100 积分)。 脚本用相对坐标点击 + 截图灰度校验,无需 OCR,主题无关(亮/暗色都能正确判定)。
何时使用
- 用户说「自动签到」「每天领 WorkBuddy 积分」「Buddy 加油站签到」。
- 配置定时任务,让它在每天固定时间(如 9:00)自动跑。
- 注意:这是通用、可分享的实现,不包含任何个人身份、路径或通知目标;若要把结果推送给某人(微信/钉钉等),由调用方在 skill 之外自行配置。
前置条件
- Windows 系统(脚本依赖
ctypes.windll/user32/gdi32)。 - Python 3(标准库即可,无需
pip install任何包)。 - WorkBuddy 桌面客户端正在运行。
- 首次使用必须校准坐标(见
references/calibration.md),因为不同屏幕/布局下点击点不同。这步跳过是移植后"只会点头像"的头号原因。
⚠️ 移植给别人 / 第一次用:先做这件事
先跑一次校准,再 -run。脚本内置的坐标是作者屏幕的校准值,别人的屏幕八成对不上——头像在左下角还能蒙对,但加油站/领取位置一偏,后续点击全打空,看起来就像"只点了头像"。
校准有两种,推荐用弹窗校准(通用、傻瓜、零依赖):
# 弹窗校准(推荐):自动弹出一个悬浮窗,按提示把鼠标移到三个目标点,
# 每步倒计时结束自动记录,三步写 calibrate.json。无需终端/微信/任何外部通道。
python scripts/wb_mouse_checkin.py -calibrate-gui
无 GUI 环境(如某些精简 Python 没带 tkinter)时,退而用终端文字校准:
# 终端校准:把鼠标依次移到 头像 / Buddy加油站 / 立即领取 三个点,各按一次回车
python scripts/wb_mouse_checkin.py -calibrate
校准后直接:
python scripts/wb_mouse_checkin.py -run
没校准就
-run,脚本会红字警告"用的是示例默认坐标,大概率打空",并打印算出的三个屏幕坐标供你对照。
使用方法
脚本位于 scripts/,两套方案:
方案 A:API 直连(推荐,2026-08-18 新增)
零 GUI 依赖,无窗口位置/DPI/更新横幅遮挡问题。读本地登录态直调官方接口:
# 查询状态 + 未签则领取(幂等)
python scripts/wb_api_checkin.py
# 仅查询,不领取
python scripts/wb_api_checkin.py -status
退出码:0=成功/已签到 / 2=失败(无登录态/接口异常)。
原理(2026-08-18 逆向自 app.asar + 实测验证):
- 登录态文件:
%LOCALAPPDATA%\CodeBuddyExtension\Data\Public\auth\workbuddy-desktop.info(明文 JSON,auth.accessToken为 JWT;同一账号体系,WorkBuddy/CodeBuddy 通用) - 后端 host:
https://copilot.tencent.com(前端 origin,getFullUrl = window.location.origin + path) - 接口:
POST /billing/meter/checkin-status(查询)、POST /billing/meter/daily-checkin(领取,幂等,已签返回 code 10001「今天已签到,请明天再来」) - 认证:
Authorization: Bearer;必须带浏览器 User-Agent,否则服务端裸 400(2026-08-18 实测坑) - 接口调用方式与 SkillHub workbuddy-checkin / workbuddy-daily-checkin 同款(官方路径社区也已证实)
方案 B:GUI 坐标点击(原方案,兜底)
# 1) 干跑:打印窗口信息 + 计算好的点击坐标 + 校准状态告警,不点击
python scripts/wb_mouse_checkin.py
# 2) 真实签到(自动读取 calibrate.json;无则告警并退回示例坐标)
python scripts/wb_mouse_checkin.py -run
# 3) 弹窗校准(推荐):悬浮窗倒计时自动采样鼠标,三步写 calibrate.json
python scripts/wb_mouse_checkin.py -calibrate-gui
# 3b) 终端校准(无 GUI 时):鼠标移到三个目标点各按回车
python scripts/wb_mouse_checkin.py -calibrate
推荐组合:每日任务先跑方案 A(API,稳、快),退出码 2 时回退方案 B(GUI 点击,覆盖登录态异常场景)。
退出码:0=成功(已处于「今日已领」) / 2=失败(未领取、面板异常,或无更新横幅时的真实失败) / 3=未找到 WorkBuddy 窗口 / 4=更新重启中(已点「重启升级」但 180s 内未等到新窗口,脚本已写 checkin_state.json 续签标记,需外部定时任务在更新完成后接管续签)。
结果截图保存在脚本同目录 checkin_result.png,可用于人工确认或后续通知。
失败兜底与更新续签(2026-08-17 老板需求)
签到失败时脚本自动检查是否「更新横幅作祟」,是则完成更新并继续签到(最多 3 轮):
attempt_checkin() ← 单轮签到(前置横幅检测 + 头像→加油站→领取→灰度校验)
│
├─ 成功 → 清除 checkin_state.json → 退出码 0
│
└─ 失败 → 截图 detect_update_overlay()
│
├─ 检测到绿色[重启升级] → announce_move + click → mark_pending()
│ → 等应用重启(最长 180s, wait_for_new_window)
│ ├─ 新窗口出现 → 绑定 _target → 下一轮继续签到
│ └─ 超时 → 退出码 4 (checkin_state.json 留续签标记)
│
└─ 无横幅 → 真实失败 → 退出码 2
- 续签标记:
scripts/checkin_state.json({"pending": true, "reason": "...", "ts": "..."})。签到成功自动清除;应用更新重启中由脚本写入,供续签流程读取判断。 - 续签载体 = Windows 计划任务(关键,2026-08-17 老板质疑后修复):WorkBuddy 重启时,运行在它进程内的 agent 会话会连带终止——「等几分钟重跑」这类会话内逻辑不可靠。正确做法:脚本点「重启升级」后先
schedule_resume_task()用schtasks /create注册 8 分钟后的-resume计划任务(python wb_mouse_checkin.py -resume)。该任务独立于 WorkBuddy 进程,重启不影响它;到点由独立 python 进程唤醒,do_resume()检查续签标记 → 等 WorkBuddy 窗口出现(最长 600s)→attempt_checkin()补签 → 成功则清标记 +cancel_resume_task()删任务。 - 双保险:脚本点更新后本进程若还活着,会先自己等重启 180s 并续签(此时顺手删掉计划任务,避免重复);只有等不到(进程随重启被杀)才靠计划任务兜底。
- 注意:点「重启升级」后 WorkBuddy 会退出并重装新版本,旧窗口句柄失效;脚本用
wait_for_new_window()(轮询重新枚举)等新窗口,绑定后继续签到。
关键实现要点(避免重踩坑)
- 所有 Win32 调用必须显式声明
argtypes,HWND按c_void_p(64 位指针)传,回调签名用WINFUNCTYPE(BOOL, HWND, c_void_p)。不声明会被 ctypes 默认按 32 位c_int截断,导致SetForegroundWindow/EnumWindows静默失败——表现为「窗口没置顶、点击打空」。 - 可靠置前 = 解决"窗口不在前台":最小化先
ShowWindow(SW_RESTORE)(恢复后验证GetWindowRect已脱离 -32000 幽灵坐标,最多重试 3 次)→AttachThreadInput线程绑定绕过系统前台锁 →SetForegroundWindow。不要用SetWindowPos(HWND_TOP)钉死窗口位置——WorkBuddy 会主动把它移回原位置/改尺寸(实测移到 (831,411) 之类),反而导致坐标全乱。 - 窗口枚举必须精确匹配标题:本机可能同时存在「WorkBuddy」(主窗口) 与「WorkBuddy - 个人中心 - xxx」等子窗口。
if TARGET_TITLE in buf.value子串匹配会命中 z 序最前的子窗口(可能是最小化/未显示的幽灵窗口)→ 所有点击打空。修复:if title == TARGET_TITLE精确匹配优先,找不到再兜底子串匹配。 - 坐标原点用
GetWindowRect的 left/top,不用ClientToScreen:实测点击头像弹出菜单后ClientToScreen返回 2× 错误值(GetWindowRect正常 (619,169) 时它返回 (1238,338)),导致全部坐标翻倍打空——这是 2026-08-04 的真正根因。WorkBuddy 是无边框窗口(Chrome_WidgetWin_1,客户区 = 整个窗口),客户区原点 = 窗口左上角,用GetWindowRect永远稳定。窗口被移去哪坐标就跟随到哪,天然免疫"窗口不在前台/被移动",根本不需要钉窗。 - 脚本开头设置 DPI 感知:
SetProcessDpiAwareness(2)(per-monitor DPI aware),失败则回退SetProcessDPIAware()。避免 Windows DPI 虚拟化导致 GetWindowRect/SetCursorPos 坐标系不一致(备用保险)。 - 坐标用「相对客户区左下角」(x=距左, y=距底),窗口任意缩放都命中,校准一次永久复用。
- 校验用「近黑像素数」而非白字数:灰底「今日已领」按钮也含白字,不能靠白字判定;黑底「立即领取」有大量近黑像素(r,g,b<70),灰按钮近黑像素≈0。用此区分,主题无关。
- 中段校验防假阳性(必须保留):点完「Buddy 加油站」后先截图,
verify_claimed要求按钮位置是黑像素(unclaimed,即面板已打开、黑底「立即领取」按钮存在)才继续点领取。否则若面板没打开,最终截图是 WorkBuddy 主界面,verify_claimed会在按钮位置采样到主界面灰色背景误判claimed→ 假阳性签到成功。 - 截图优先 desktop-control-win 的
screen-info.ps1(若存在),否则回退PrintWindow客户区截图;PNG编解码全用标准库手写(支持所有 filter),无外部依赖。 - 幽灵矩形防御(2026-08-06):点完加油站后窗口可能短暂进入最小化/恢复动画态,
GetWindowRect返回(-32000,-32000,160x28)幽灵矩形,直接把坐标算飞(立即领取点到屏幕外)。检测到wr.left < -10000时先IsIconic → SW_RESTORE重读一次,仍异常则保留上次有效坐标不更新全局。 - 防"撞用户操作"三件套(2026-08-12):定时任务在用户正用电脑时跑,脚本点击会和用户实时鼠标操作打架(用户反馈"你控制鼠标时我在用,移动不到正确位置")。解法不是更用力抢鼠标(
SetCursorPos本来就能强制移动),而是:wait_mouse_idle():接管前纯读取鼠标位置(GetCursorPos不碰鼠标)连续采样,静止 2s 才接管(最多等 60s 超时不阻塞)。用户在用电脑时安静等待,绝不抢。announce_move():点头像前鼠标「飞向目标 → 移开右上角 → 飞回目标」两次可见位移(各停 0.5s),用户看到鼠标自己动就知道脚本要操作了,提前松手。click_at()点击前停顿 0.4s:SetCursorPos后多留反应时间。- 调用顺序:
wait_mouse_idle()→focus()→announce_move(sa,...)→click_at(*sa,...)
- 更新提示(底部横幅)遮住头像自动处理(2026-08-17):WorkBuddy 有新版本时会弹出横跨客户区底部的白色横幅(左侧升级图标 + 文案"新版本就绪" + 绿色按钮「重启升级」 + 白色按钮「更新日志」 + 右侧 ×),横幅会盖住左下角头像 → 脚本点头像实际点到横幅上 → 账户菜单不弹出 → 后续全错位 → 签到失败。老板 2026-08-17 提供实测截图确认形态。
- 检测:
focus()后、点头像前先截checkin_pre.png;在客户区底部 85%~100% 区域扫描 teal 色像素(实测按钮 avgRGB=(95,208,169),判定g>=150 and g-r>=40 and b>=90 and r<=180),找最大 60px 簇(≥ 80 采样点)。teal 是品牌青绿,普通灰色 UI(g-r≈0)天然不命中,误判率低。 - 处理:检测到即
announce_move + click_at点击(点的就是绿色「重启升级」,不是白色「更新日志」);然后轮询 3s 间隔:- 旧窗口句柄
IsWindow()失效(应用重启升级中)→wait_for_new_window(最长 60s)找新窗口 → 重新绑定_target→'restarted',重新 focus + 截图确认无横幅后继续签到。 - 横幅消失(
detect_update_overlay返回 None)→'done',重新focus + recompute_geometry后继续签到。 - 超时 120s 仍异常 → 失败退出(避免定时任务长期卡住)。
- 旧窗口句柄
- 验证:用
checkin_after_ctrlw.png实测,检测中心 (333,1132) vs 按钮实际中心 (309,1141),偏差 24px,落在按钮内部。
- 检测:
配置定时任务(示例)
在 WorkBuddy 自动化里建一个每日任务,prompt 大致为:
运行
python scripts/wb_mouse_checkin.py -run(脚本内置:窗口精确匹配 + 最小化恢复置前 + 固定坐标点击 + 中段校验面板是否打开 + 灰度校验是否已领)。 读checkin_result.png确认结果:灰色「今日已领」=完成;黑底「立即领取」仍在=失败。 按你的通知偏好(微信/钉钉等)把结果发给本人。通知目标和通道由你自己的配置决定,本 skill 不内置任何推送。
cwd 设为该 skill 的 scripts/ 所在目录(或脚本实际位置)。
参考
- 坐标校准与常见问题:
references/calibration.md
相关技能
一条命令给 WorkBuddy 环境做八维安全稳定体检:磁盘/备份新鲜度/自动化存活/凭据硬编码/备份包完整性/配置/记忆/同步载体,输出体检报告+分级处置清单。适用"WorkBuddy 安不安全/稳不稳定/体检一下/备份还好吗/凭据有没有泄露"等场景。
WorkBuddy 安全稳定运行专家团(WB-SAFE)——凭据、积分、连通、配置、加密、健康、风险、恢复八条防线一个团,守护 AI 工作台既安全又不掉线。对齐 NIST CSF 2.0 六职能与 ISO/IEC 27001。触发词:安全体检、凭据安全、Token 安全、积分省钱、连接器掉线、配置漂移、加密、密钥、系统卡死、OOM、灾备恢复、离线兜底、黄金包、备份。
构建、修改、调试和发布 Windows 版 WorkBuddy Skin Studio(Tauri v2 + Rust)桌面换肤工具。用于用户要求为 WorkBuddy 制作 GUI 换肤器、调整主题/按钮/本地 CDP 注入流程、处理 WorkBuddy.exe 路径、创建自定义皮肤、或构建 NSIS 安装包时。
【仅限 WorkBuddy 桌面版使用】会话回调(Session Callback)——实现"一个会话调起另一个会话"的能力:外部进程、定时任务(cron job)或另一个 agent 会话,向目标会话注入消息,唤醒其 agent 带完整上下文继续处理。适用于 WorkBuddy 桌面版:监控回传后唤醒主会话推进任务、定时任务回调指定会话、异步任务完成后通知会话、多会话协作接力、替代 openclaw 的 sessions_send 机制。当用户在 WorkBuddy 中提到"会话回调"、"唤醒会话"、"session callback"、"会话调起另一个会话"、"cron 唤醒指定会话"、"向会话注入消息"、"主会话收到提醒后推进"、"sessions_send" 时使用本 skill。注意:本技能依赖 WorkBuddy 本地结构(~/.workbuddy/sessions/、projects/*.jsonl、/api/v1/acp/*),不适用于 openclaw 等其他平台。
当用户要换电脑、切换设备或在另一台机器继续开发时,帮助把当前 WorkBuddy 项目和工作现场(未提交改动、Git、项目内配置、Agent 规则/Skill 与交接上下文)安全打包成加密工作包,或恢复已有 .wbpack 并接着上次工作。适用于“跨设备项目迁移/接力”“工作现场打包/恢复”“把项目和 Agent 上下文一起带走”等请求;不把单纯云同步、实时多人协作、普通 Git 同步或部署作为主要场景。