Files
wechat-ops/SKILL.md
T
kenyanghui d5850ce18a v0.2.0: add Linux server resident-agent route + ops-workflow discipline
- scripts/agent.py: GLM-vision WeChat guard agent (8s watch loop, red-dot
  detection, whitelist, title-verify gate, rate/quiet-hours caps, self-heal)
- scripts/setup-server.sh: idempotent xfce+TigerVNC+noVNC+WeChat-Linux setup
- scripts/check-skill.sh: skill guard (structure/secrets/privacy/claims/
  encoding/syntax/CHANGELOG/bundle parity), self-exclusion aware
- references/linux-server.md: deploy & ops guide for the 7x24 route
- references/pitfalls-linux.md: 17 field-tested pitfalls
- references/ops-workflow.md: baseline-first authoring + sync discipline
  (methodology credit: octopus-workflow)
- SKILL.md/README: dual-platform entry; CHANGELOG added
2026-09-29 08:54:59 +08:00

242 lines
12 KiB
Markdown
Raw 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.
---
name: wechat-ops
description: 用「截图 → 视觉识别 → 动作 → 截图验证」的闭环操作电脑,代替人手点按钮、输文字、切窗口、走界面流程。只要用户想让你「帮我点一下」「操作我的电脑」「自动发个朋友圈/消息」「把这段文字输入到某个软件」「帮我走一遍这个界面流程」「模拟点击」「识图点击」「截图找按钮」「GUI 自动化」「RPA」,都必须使用本技能——即使用户没说要"用技能"。核心特征:坐标绝不写死落盘,每次实时看图现算、事后验证。若目标是在 Linux 云服务器上 7x24 挂机微信、微信自动回复、微信值守机器人,走 references/linux-server.md 的常驻 Agent 路线。若目标是在 Figma 画布内做设计,请改用 Figma 系列技能。
---
# WeChat Ops
用视觉驱动的方式操作电脑:**看屏幕 → 判断点哪里 → 动手 → 再看一眼确认**。
## 零、两条路线,先选对
| | 路线 A:macOS 本机(本文件主体) | 路线 B:Linux 云服务器(references/linux-server.md) |
|---|---|---|
| 场景 | 操作你眼前电脑的一次性界面任务 | 微信 7x24 挂机、自动回复值守 |
| 工具 | `scripts/vision.py`(pyautogui) | `scripts/agent.py`(GLM 视觉 Agent,systemd 常驻) |
| 坐标哲学 | **易耗品**:每次实时定位,绝不落盘 | **固定资产**:虚拟屏分辨率+最大化窗口固定,一次校准长期有效 |
| 决策 | 你实时判断 | 白名单+GLM 拟回复+代码闸门 |
两条路线共享同一套纪律(见 references/ops-workflow.md):失败基线优先、每步截图验证、
安全闸门固化进代码、证据分级表述、守卫检查、三方同步。
---
## 一、核心原则
### 1. 坐标是易耗品,绝不落盘
分辨率、窗口位置、应用版本、系统语言——任何一样变了,写死的坐标就失效。所以:
- **技能里存的是「怎么找到它」,不是「它在哪」**
- ❌ `朋友圈入口在 (30, 297)`
- ✅ `朋友圈是左侧边栏第 5 个图标,光圈形状`
- 坐标只存在于**本次任务的上下文**里,任务结束即作废。
- 如果你正想「把这次成功的坐标记下来下次直接用」——**停**。那是在造一个明天就会坏的缓存。该记的是语义特征和判断方法。
这条是整个技能的地基。写死坐标的方案(无论存成 JSON 还是 Markdown)都只是把脆弱的快照换了个格式。
### 2. 每步都要验证
视觉方案真正的价值**不是"能看图",而是"点完能确认"**。
每次动作后截一张图,确认结果符合预期,再做下一步。看起来慢,实际上:
- 点错了能立刻发现并纠正,而不是一路错到底
- 界面和预想不一致时(弹窗、加载中、位置变了)能及时改道
**判断标准**:如果这一步失败了你不会察觉,那这一步就该加验证。
### 3. 先想清楚交互方式,再动手
同一个控件,单击和长按可能完全是两回事。动手前先问:这个操作是单击、双击、长按、右键还是拖拽?
> 真实案例:微信朋友圈的相机图标,**单击打开"选图片"文件框,长按才出纯文字发布框**。没搞清楚就会点出一个文件选择器。
拿不准就先用 `--dry` 或在无关紧要的地方试。
## 二、坐标系(先读这段,否则必错)
**macOS Retina 屏上,截图分辨率和点击分辨率不是一回事。**
- `screencapture` 输出的是**物理像素**(Retina 通常是 2 倍)
- `pyautogui` 点击用的是**逻辑像素**
`vision.py` 已经处理了这件事:**截图时自动缩放到逻辑分辨率**,所以
> **图上量到的坐标 = 直接可用的点击坐标**
这正是为什么所有操作都要走 `vision.py` 而不是直接 `screencapture`——手工换算 2 倍关系是最高频的错误来源。
## 三、工具:`scripts/vision.py`
| 命令 | 作用 |
|---|---|
| `shot [名字]` | 截当前屏,缩放到逻辑分辨率。始终刷新 `cur.png` |
| `grid [名字] [间距]` | 截图并叠加带刻度的坐标网格,**读位置不用估算** |
| `crop x1 y1 x2 y2 [名字] [倍数]` | 精确裁剪放大,看小图标/小字。左上角标注原点 |
| `click X Y` | 单击 |
| `dclick X Y` | 双击 |
| `longpress X Y [秒]` | 长按(默认 1.2 秒) |
| `move X Y` | 只移动鼠标 |
| `activate 名称` | 按窗口/进程名激活并置前 |
| `type "文本"` | 输入文本,走剪贴板,支持中文长文本 |
| `key cmd+v` | 按键,支持 `cmd+shift+f` 这类组合 |
| `scroll N [X Y]` | 滚动。**可指定鼠标落点**——滚轮事件发给指针所在的视图 |
| `pos` | 打印屏幕尺寸和当前鼠标位置 |
截图统一存在 `/tmp/wechat_ops/`。
**环境依赖**:`pip install pyautogui pyperclip pillow`,并在「系统设置 → 隐私与安全性 → 辅助功能」里授权终端。
## 四、标准流程
```
1. 激活目标窗口 activate <名称>
2. 看清全貌 shot / grid
3. 定位目标元素 grid 读数 → crop 放大确认(两种方法对上再动手)
4. 执行动作 click / longpress / type / key
5. 截图验证 shot,确认结果符合预期
└─ 不符合 → 回到 2 重新定位
```
第 3 步的「两种方法对上」很重要:网格给你绝对位置,裁剪放大给你细节确认。两者一致时基本不会点错。
## 五、定位技巧
### 网格读数(找大致位置)
```
python3 vision.py grid wxgrid 50
```
在截图上画出每 50px 的红色竖线、蓝色横线并标注刻度。直接读刻度,不靠目测。
### 裁剪放大(确认细节 + 精确定位)
```
python3 vision.py crop 0 275 70 335 icon_check 6
```
放大 6 倍后能看清图标形状、文字内容。输出图**左上角标注了裁剪原点**(如 `origin=(0,275) x6`),在放大图里量到的偏移除以倍数、加上原点,就是绝对坐标。
这条标注是刻意设计的:没有它,在放大图里读数极易把原点搞错。
### 判断元素身份
图标类元素靠**形状**认(光圈=朋友圈、相机=发表、铃铛=通知),不靠位置猜。文字类直接放大读。
## 六、已知陷阱(都是实测踩过的)
### 1. 中文输入法会吃掉组合键
`pyautogui.hotkey('command', 'v')` 在拼音输入法下会**退化成裸字母 `v`**,弹出一个拼音候选框,文字根本没粘进去。
**解法**:用 AppleScript 发组合键。`vision.py` 的 `type` 命令在 macOS 上已默认走这条路:
```bash
osascript -e 'tell application "System Events" to keystroke "v" using command down'
```
自己写脚本时也要注意这一点。
### 2. 读图命令会读到旧截图
这是**最隐蔽**的一类错误:图本身没错,错的是它描述的那个瞬间已经过去了。你会对着一个不存在的界面做判断,然后点空,而且**毫无察觉**。
实测踩过两次:`click → type → crop` 这样连写时,中间没有 `shot`,`crop` 读到的是动作**之前**的 `cur.png`——于是明明输入成功了,看到的却是「占位文字还在」,差点重输一遍。
`vision.py` 的处理:**`crop` / `grid` 每次自动重新截图**。宁可多截一张(几十毫秒),也不要看错。自己写脚本时照做。
### 3. 弹窗会挡住目标
点了一个按钮后可能弹出对话框、文件选择器、权限提示。**动作后一定截图**,否则下一步会点在弹窗上。
按 `esc` 通常能关掉误弹的框。
### 4. 输入前先确认焦点
点击输入框后,最好截图确认光标进去了(占位文字消失、出现光标),再输入。否则文字可能跑到搜索框之类的别处。
### 5. 滚动前先把鼠标移进目标区域
滚轮事件发给**指针当前所在的那个视图**。指针停在别处(比如左侧聊天列表),你想滚朋友圈流,滚的是聊天列表——而且界面上看起来"没反应",很容易误判成"已经到底了"。
`vision.py scroll N X Y` 会先移动鼠标再滚,就是为这个。
另外**滚动方向要实测**,别照搬直觉:本机实测 `pyautogui.scroll(正数)` 是让内容**往上走**(即翻到更旧的位置),和"正数向上"的字面意思相反。滚错方向时,你会以为已经到顶了,其实是在往下翻。
判断是否到顶:滚一大段后再反着滚回来,如果位置没变,那就是真到边界了。
### 6. 别在用户的真实账号里乱试
操作微信、邮箱、支付这类真实应用时,先想清楚这一步有没有副作用。
## 七、安全边界
以下动作**先跟用户确认再执行**:
- **对外发布**:发朋友圈、发消息、发邮件、提交表单
- **破坏性**:删除、覆盖、清空、退出未保存的编辑
- **花钱**:下单、支付、订阅
- **不可逆**:任何做了就回不去的操作
确认时把「将要发生什么」说清楚,而不是只问「可以吗」。
一个实用的做法:**把流程走到最后一步停住**,让用户看到完整状态(文案已填、设置已选),再决定要不要按下那个不可逆的按钮。
## 八、完整案例:微信朋友圈发布纯文字
这个案例贯穿了上面所有原则,可作模板参考。
> ⚠️ 下面括号里的坐标是**某一次实测值,仅供理解流程,不要照抄**——每次都要重新定位。
| 步骤 | 动作 | 定位方式 |
|---|---|---|
| 1 | `activate 微信` | 按进程名激活 |
| 2 | `grid` 看全貌 | 网格读数找到侧边栏第 5 个图标(光圈形状)= 朋友圈 |
| 3 | `crop` 放大确认形状 | 交叉验证坐标 (30, 297) |
| 4 | `click` 进入朋友圈 | 截图确认已进入 |
| 5 | 找发布按钮 | 裁剪右上角,认出三个图标中最右的**相机** |
| 6 | **`longpress` 相机图标** | ⚠️ 单击会弹文件框,长按才出纯文字框 |
| 7 | `click` 输入区 → `type "文案"` | 截图确认文字进去了 |
| 8 | 点「谁可以看」→ 选「私密」→ 确定 | 截图确认已变成「私密」 |
| 9 | ⏸️ **停住,问用户** | 发布是对外动作,确认后再点「发表」 |
关键教训都在这条流程里:长按 vs 单击、输入后验证、可见范围要显式设置、最后一步停下来问。
### 附:发图文朋友圈(和纯文字的关键差别)
同一个相机图标,**要图就单击,纯文字就长按**:
| 想要 | 对相机图标 | 后果 |
|---|---|---|
| 图文 | **单击** | 弹出系统文件选择器,选完图进发布框 |
| 纯文字 | **长按** | 直接进发布框(单击只会弹文件框) |
图文流程比纯文字多两步:
1. 文件选择器里进目标目录(左侧「下载」「桌面」等),选中文件 → 点「打开」
- 选完**先裁剪确认高亮**再点打开,否则可能选中的是相邻文件
2. 发布框里多了图片缩略图,其余(输入文案、谁可以看、发表)与纯文字一致
### 发表之后怎么验证
**微信 Mac 版的朋友圈信息流不显示自己发的私密动态**——发完回到信息流看不到自己的帖子,这是正常的,别据此判断失败、更别重发。
真正可靠的验证入口:**点左下角自己的头像 → 资料卡里的「朋友圈」一行 → 我的朋友圈相册**,按「今天 / 昨天 / 更早」分组列出自己的全部动态。刚发的那条会出现在最上面。
(顺带一提:这个「信息流看不到」的现象反过来也能当作旁证——如果一条动态在信息流里也出现了,那它多半不是私密。)
## 九、和「录制回放」方案的区别
| | 录制回放(写死坐标) | 本技能(视觉驱动) |
|---|---|---|
| 定位时机 | 录制时定一次 | **每次执行时实时定位** |
| 界面变了 | 静默点错 | 看图发现异常,改道 |
| 出错后 | 不知道,继续错 | **截图验证,立即发现** |
| 存什么 | 像素坐标 | 语义特征 + 判断方法 |
| 适合 | 固定不动的界面 | 会变、会弹窗、跨机器的真实场景 |
代价是慢一些、每步要截图。但对真实桌面应用来说,可靠性远比速度重要。