用户报的"探索完无法点击创建任务"真因:一个 run 的事件原先只有**一条** queue.Queue, 聊天页与建任务页同时开着时两个 EventSource 会**瓜分**它——建任务页的回放卡在中间、 `done` 被聊天页取走 → 永远等不到草稿,页面上自然没有可点的"创建"。 一、修(根因 + 表现) - `web/agent_api.py` 新增 `_Fanout`:**每个订阅者一个专属队列**,多开页面各看各的, 还带单轮事件缓冲(晚订阅/刷新重连也能补齐回放,终止事件一定送达)。 实测两路订阅者收到完全一致的 1039 条事件(含 done)。 - `static/admin/agent.js`:断线重连的兜底订阅也按 `mode` 让开(此前漏了这一处)。 二、补齐上一批的三项 - **「直接创建」**:`POST /api/agent/task_draft/create`(草稿体只在服务端、创建前再校验一次、 成功后清草稿避免重复建)+ 草稿预览里的「✓ 直接创建任务」按钮 + 「探索完直接创建任务」勾选框。 - **草稿沉淀经验/动作**:designer 轮次也走 `_distill_experience/_distill_actions`, 但**只在草稿通过校验时**(没走通的试错不入库,免得把误点当经验)。 - **MCP `de_snapshot`**(第 20 个工具):截图+元素树一次取齐(省一次来回、不会因界面在动而错位), 附带 `screen_state`/`unstable`;两套提示词都改为优先用它。 平台侧 `/api/uiauto/snapshot` 随之多返回 `screen_state`。 三、文档 - AI_TASK_GEN §10:§10.3 记两个 bug 的真因与修法、§10.4 三项标完成、§10.5 剩余项。 - AI_CONSOLE(扇出语义、多页面同时看一轮)、API(task_draft/create、snapshot 字段)、 MCP/MCP_DESIGN/staffdeck/README/ARCHITECTURE:工具数 19→20 + de_snapshot 条目。 - backlog:记一条新发现的缺陷——`mcp_server/platform_client._login()` 会把"登录页 200" 当成登录成功(现场进程缺 `MCP_PLATFORM_PASS` 时表现为含糊的 platform_unavailable)。 自测:真机浏览器端到端(勾上"探索完直接创建")→ 探索 12 步 → 草稿 → 自动建任务成功; `de_snapshot` 直连真机校验;校验器 21 条用例、扇出单元用例、本地工具契约用例全绿。 自测产生的任务/草稿已全部清理(未碰用户既有数据)。
254 lines
14 KiB
Markdown
254 lines
14 KiB
Markdown
# 知识库 · 设备自动化平台(auto_control)接入与操作手册
|
||
|
||
> 读者:StaffDeck 数字员工(外部 Agent)。
|
||
> 目标:让你达到**与平台内置 AI 控制台同等**的操作水平——不是"能调工具",而是"会看、会判断、会收尾"。
|
||
> 版本:2026-09-10 | 工具清单权威版:`doc/MCP.md`|配置权威版:`mcp_server/config.py`
|
||
|
||
---
|
||
|
||
## 0. 快速开始(30 秒版)
|
||
|
||
```
|
||
1) de_list_devices → 选一台 online 且 worker_status 非 running/connecting 的设备
|
||
2) de_screenshot(serial) → 看当前屏;若画面黑/锁屏 → de_wake 后重截(见 §6、§7)
|
||
3) 判断当前页 → 不对就 de_open_app(package) 或 de_press_key(back) 回到起点
|
||
4) 循环体:观察 → 操作 → 验证(见 §8)
|
||
- 优先 de_tap_text(文字);有歧义用 de_ui_tree + de_tap_element;纯图形才 de_tap(坐标)
|
||
- 每次关键操作后再 de_screenshot 验证是否生效
|
||
5) 连续 6 步无进展 → 停止并如实汇报(不要空转、不要臆测成功)
|
||
```
|
||
|
||
---
|
||
|
||
## 1. 平台与能力边界
|
||
|
||
安卓设备自动化中台:管理一批手机(网络 `IP:5555` / USB 串号),支持任务调度、步骤编排、看屏与操作。
|
||
|
||
- 你能用的入口:**MCP Server**(推荐,20 个 `de_*` 工具);备选 REST(§2.2)。
|
||
- **可做**:看屏、截图、UI 树、OCR、开/关 App、点击、滑动、按键、输入、剪贴板、亮/熄屏、看前台包名、列应用、只读看平台任务。
|
||
- **不可做**:创建/修改/启停平台任务、分组/设备池/备份管理(MCP 未提供)。
|
||
|
||
---
|
||
|
||
## 2. 接入方式
|
||
|
||
### 2.1 首选:MCP(HTTP / streamable)
|
||
- 地址:`http://<host>:8033/mcp`。
|
||
- **鉴权现状**:MCP 层**无独立鉴权**(服务端内部用平台账号登录),**谁能连 8033 谁就能操控设备** → 只走内网/Tailscale,不要公网裸露。
|
||
- **审计**:每次调用(含只读)写一行 JSON。
|
||
|
||
### 2.2 备选:平台 REST(`http://<host>:18050`)
|
||
认证 = 表单登录 → 会话 Cookie + `X-CSRF-Token`。无 API Token。端点见 `doc/API.md`。
|
||
|
||
### 2.3 服务端配置(部署方设置,你只需知道含义)
|
||
| 变量 | 默认 | 对你的影响 |
|
||
|---|---|---|
|
||
| `MCP_ALLOW_WRITE` | `0` | `0` 时写工具全返回 `write_disabled`(只能看不能动) |
|
||
| `MCP_ALLOWED_SERIALS` | 空 | 非空=白名单;**为空时不自动限设备池**(仅校验非空) |
|
||
| `MCP_HTTP_HOST` / `MCP_HTTP_PORT` | `0.0.0.0` / `8033` | 监听 |
|
||
| `MCP_SCREENSHOT_WIDTH` / `MCP_JPEG_QUALITY` | `540` / `70` | 截图尺寸/质量 |
|
||
| `MCP_PLATFORM_TIMEOUT` | `30` | 平台请求超时 |
|
||
| `MCP_AUDIT_FILE` | `/var/log/mcp/audit.log` | 审计文件 |
|
||
|
||
---
|
||
|
||
## 3. 工具清单(20 个)
|
||
|
||
**只读(不触发占用锁)**:`de_list_devices` · `de_screenshot` · `de_snapshot`(截图+元素树一次取齐,**推荐**)· `de_ui_tree` · `de_ocr` · `de_foreground_app` · `de_list_apps` · `de_read_clipboard` · `de_list_tasks`
|
||
|
||
**写(受占用锁约束)**:`de_tap_text` · `de_tap_element` · `de_tap` · `de_swipe` · `de_press_key` · `de_type_text` · `de_set_clipboard` · `de_open_app` · `de_stop_app` · `de_wake` · `de_sleep`
|
||
|
||
参数与返回详见 `doc/MCP.md`。
|
||
|
||
---
|
||
|
||
## 4. 通用约定
|
||
|
||
### 4.1 serial
|
||
- 网络 `IP:5555`(如 `100.100.10.13:5555`);USB 纯串号(如 `ZY322XXXX`)。
|
||
- **用 `de_list_devices` 取,别猜。**
|
||
|
||
### 4.2 坐标空间(重要)
|
||
- `de_screenshot`/`de_snapshot` 返回**缩放图(≤540px 宽)+ `native_size`**;`de_tap`/`de_swipe` 用**截图坐标系**,服务端换算原生(两者都会建立坐标空间)。
|
||
- **必须先截图再坐标操作**;否则报「请先执行 de_screenshot」。
|
||
- 屏可能旋转/滚动 → **优先文字/元素,坐标仅兜底**。
|
||
|
||
### 4.3 占用锁(busy)
|
||
- 写工具执行前查设备任务状态:`running`/`connecting` → **`device_busy`**(不与任务抢设备)。换设备或等待,别硬试。
|
||
- 只读工具不受限(任务运行中也能安全截图)。
|
||
|
||
### 4.4 错误码
|
||
| 错误 | 含义 | 应对 |
|
||
|---|---|---|
|
||
| `write_disabled` | 写门控关闭 | 上报部署方 |
|
||
| `device_busy` | 设备被任务占用 | 换设备/等待 |
|
||
| `device_offline` | 设备不可达 | 换设备;报运维 |
|
||
| `device_not_allowed` | 不在白名单 | 换设备;加白名单 |
|
||
| `text_not_found` | 屏上无该文字 | 重截图/`de_ui_tree`/`de_ocr` 复核 |
|
||
| `platform_unavailable` | 平台不可达 | 稍后重试 |
|
||
| `invalid_param` | 参数不合法 | 修参数 |
|
||
|
||
---
|
||
|
||
## 5. 操作纪律(**与平台内置 AI 控制台等价**,务必遵守)
|
||
|
||
> 这是平台内置 Agent 的系统规范,逐条对齐即可达到同等效果。
|
||
|
||
1. **先看设备**:`de_list_devices` 确定目标设备(在线才可操作)。
|
||
2. **先看屏**:任何决策前 `de_screenshot` 理解当前界面(图会给你)。
|
||
3. **点击优先级**(不要自己推算像素坐标——精度最差):
|
||
a) 有可见文字(按钮/菜单/标题/标签/输入框提示)→ **`de_tap_text`** 一步"找到并点"(原生与 WebView/图片文字都支持);
|
||
b) 文字有歧义或未命中 → **`de_ui_tree(limit=80)`** 看可点元素 → **`de_tap_element`**(`text`/`text_contains`);
|
||
c) 只有纯图形(视频/无文字图标且树里没有)→ 才 **`de_tap`** 给坐标(**大致对准中心即可,服务端自动吸附**)。
|
||
4. **验证点击**:`de_tap` 返回 `snapped=true` 表示已吸附命中(可核对 `label`);**截图有变化=成功,无变化=未命中**。
|
||
5. **输入文字**:先 `de_tap_text`/`de_tap` 点中输入框 → 再 `de_type_text`。
|
||
6. **每关键步后再截图验证**,直到完成目标。
|
||
7. **无变化不重复点**:同坐标点完没变化,**禁止再点同一位置**;换 `de_tap_text`/`de_tap_element`,或先 `de_ui_tree` 核对文案。
|
||
8. **如实汇报**:做了什么、当前状态、注意事项;失败就说失败,**不臆测成功**。
|
||
9. **效率**:界面没变就别重复截图/点击;每步都要推进目标。
|
||
10. **收敛**:**连续 6 步无进展**(截图内容未变/操作无效)→ 停止并总结原因。
|
||
|
||
---
|
||
|
||
## 6. 开跑前状态检查清单(Pre-flight,逐项过)
|
||
|
||
| # | 检查 | 怎么做 | 通过条件 | 不通过怎么办 |
|
||
|---|---|---|---|---|
|
||
| 1 | 设备在线且空闲 | `de_list_devices` | `online=true` 且 `worker_status` 非 running/connecting | 换设备;全忙则上报 |
|
||
| 2 | **屏幕是否点亮/解锁** | `de_screenshot` 看 `screen_state` 与画面 | 亮屏且非锁屏界面 | **`de_wake`**(亮屏解锁)→ 重新 `de_screenshot` |
|
||
| 3 | 是否能看清画面 | 截图 | 非纯黑/非"正在加载"白屏 | 黑屏→`de_wake`;白屏→等 2~3s 重截 |
|
||
| 4 | 前台 App 是否正确 | `de_foreground_app` | 是目标 App(或桌面,准备开) | `de_open_app(package)` 或 `de_press_key(back)` 回退 |
|
||
| 5 | 是否在起点页 | `de_ui_tree`/截图 | 元素文案符合"首页/入口"预期 | 逐级 `de_press_key(back)` 或重开 App |
|
||
| 6 | 有无拦截弹窗 | 截图/`de_ui_tree` | 无权限/更新/广告弹窗 | 找"取消/关闭/允许(按需)/以后再说"文字点掉,或 `back` |
|
||
| 7 | 坐标基线 | 记下最近一次截图 | 本轮坐标操作前**必须有一次新截图** | 补一次 `de_screenshot` |
|
||
|
||
> **判断"屏幕有没有开启"的标准做法**:`de_screenshot` 的 `screen_state` + 画面是否可辨认。**黑屏/息屏一律先 `de_wake`**,再重新截图确认;**不要在未确认亮屏的情况下点按/滑动**。
|
||
|
||
---
|
||
|
||
## 7. 执行中的状态判据与规则
|
||
|
||
### 7.1 屏幕与锁屏
|
||
- 息屏/黑屏 → `de_wake` → 重截确认;长任务中途可能再次息屏,**每轮循环先确认一次**。
|
||
- 锁屏界面(有锁/时间/上滑提示)→ `de_wake` 解锁后重截;仍锁 → 上报(可能需要人工)。
|
||
- 需要保持常亮时:没有专门工具,可在长流程中周期性 `de_wake` 兜底。
|
||
|
||
### 7.2 页面判据(怎么算"到位了")
|
||
| 目标 | 判据(以 `de_ui_tree`/截图文字为准) | 未达成的处置 |
|
||
|---|---|---|
|
||
| 已到 App 首页 | 出现底部导航/搜索框等首页特征文本 | `back` 一次或重开 App |
|
||
| 已到视频页 | 出现点赞/评论/分享等交互图标或全屏画面 | 等待/滑一次再看 |
|
||
| 已到目标详情 | 目标条目标题文本可见 | 继续上滑查找(有上限,见 §10) |
|
||
| 输入框已聚焦 | 出现键盘/光标或输入法界面 | 重新点输入框 |
|
||
| 弹窗已处理 | 弹窗文本消失 | 换"取消/关闭/以后再说"再点 |
|
||
|
||
### 7.3 加载与抖动
|
||
- "正在加载/白屏/骨架屏" → 等 2~3s 重截,**不要连续狂点**。
|
||
- 连续两次截图完全一致且不符预期 → 视为**卡住**,走 §8.3。
|
||
|
||
### 7.4 幂等重放(**注意你的运行时特性**)
|
||
- 若你的平台会对"相同参数的工具调用"做**幂等重放/去重缓存**(如返回 `idempotent_replay`):
|
||
**观察类工具**(`de_screenshot`/`de_ui_tree`/`de_ocr`/`de_foreground_app`)**必须每次拿到新结果**,否则你会基于**过期画面**决策(表现为"屏幕没变/点不动")。
|
||
- 处置:请让编排方**对观察类工具关闭去重**;或在参数/调用上确保不被判定为重复。
|
||
- 兜底:用 `de_ui_tree`(文本随页面变化)作为"状态是否变化"的佐证;`de_screenshot` 用于确认视觉。
|
||
|
||
---
|
||
|
||
## 8. SOP(标准作业流程)
|
||
|
||
### 8.0 总体:五个阶段 + 一个循环
|
||
```
|
||
P0 接收与澄清 → P1 选设备与预检(§6) → P2 到达起点 → P3 主流程(观察-行动-验证循环) → P4 收尾与还原 → P5 汇报
|
||
└──────────── 循环体 ────────────┘
|
||
```
|
||
|
||
### P0 接收与澄清
|
||
- **输入**:用户指令(自然语言)。
|
||
- **必查**:目标 App?要做什么动作?哪台设备(或指定)?时长/次数?成功标准是什么?
|
||
- **闸门**:任一缺失且影响执行 → **先问,不猜**。
|
||
- **拒绝项**:L2/L3 级操作(见 §11)→ 停下要授权。
|
||
|
||
### P1 选设备与预检
|
||
- 动作:跑完 §6 的 7 项。
|
||
- **闸门**:设备在线 + 空闲 + **亮屏可达** + 前台/起点已就位。任一不过 → 按 §6 处置;仍不过 → 上报。
|
||
- 产出:记下 `serial`、起点页特征、最近一次截图基线。
|
||
|
||
### P2 到达起点
|
||
- 动作:`de_open_app`(冷启动到首页)→ `de_screenshot`/`de_ui_tree` 确认;或 `back` 逐级回退。
|
||
- **闸门**:起点特征文本出现(§7.2)。
|
||
- 失败:重开 App 一次;仍不行 → 上报(App 异常/未安装:`de_list_apps` 核对包名)。
|
||
|
||
### P3 主流程 —— 观察-行动-验证(OAV 三拍循环)
|
||
每一拍都按下面的节奏,**不许跳步**:
|
||
1. **观察**:`de_screenshot`(必要时 `de_ui_tree`)→ 用一句话说清"现在在哪、看到什么"。
|
||
2. **决策**:选定下一步**唯一**动作(按 §5 的定位优先级)。
|
||
3. **行动**:执行单个工具调用。
|
||
4. **验证**:再观察一次 → 变化符合预期?→ 是:进入下一拍;否:见 §8.3。
|
||
- **闸门**:每拍结束必须"状态有推进"的证据(文字/画面变化)。
|
||
- **边界**:只在目标 App 内活动,不跳出到系统设置等无关界面(除非任务要求)。
|
||
|
||
### 8.3 卡住判定(重要)
|
||
| 情形 | 判定 | 处置 |
|
||
|---|---|---|
|
||
| 同坐标点击无变化 | 未命中 | **禁止重复点**;换 `de_tap_text`/`de_tap_element`,或先 `de_ui_tree` 看文案 |
|
||
| 连续 2 步无变化 | 策略无效 | 换定位方式 / 检查是否在正确页面 |
|
||
| **连续 6 步无进展** | 卡死 | **停止**,汇报"卡在哪、试过什么、可能原因" |
|
||
| `device_busy`/`device_offline` | 设备不可用 | 换设备;无可用则中止汇报 |
|
||
|
||
### P4 收尾与还原
|
||
- 动作:`de_stop_app`(结束 App)或 `back` 回到桌面;确认设备状态(亮/熄屏按需)。
|
||
- **闸门**:设备处于明确的已知状态(不留在中间页/输入框)。
|
||
- 注意:**不做**非任务要求的破坏性/不可逆操作。
|
||
|
||
### P5 汇报(固定口径)
|
||
```
|
||
【设备操作员 · 汇报】
|
||
设备:<serial> | 目标:<一句话>
|
||
过程:<关键 3~5 步:做了什么 → 是否生效>
|
||
结果:✅完成 / ⚠️部分完成 / ❌失败(原因)
|
||
证据:<关键步骤截图/元素文本>
|
||
遗留:<需人工处理 / 未做的高危步骤 / 设备状态>
|
||
```
|
||
|
||
---
|
||
|
||
## 9. 常见异常与处置(速查)
|
||
|
||
| 现象 | 可能原因 | 处置 |
|
||
|---|---|---|
|
||
| 截图全黑/息屏 | 屏幕关闭 | `de_wake` → 重截 |
|
||
| 停在锁屏 | 未解锁 | `de_wake`;仍锁 → 上报 |
|
||
| 停在启动页/闪屏 | App 未就绪 | 等 2~3s 重截;不行重开 |
|
||
| 权限/更新弹窗遮挡 | 系统弹窗 | 点"取消/关闭/以后再说";`back` |
|
||
| 点不动、画面不变 | 未命中/被遮挡/图是旧的 | 换定位方式;核对截图是否新鲜(§7.4) |
|
||
| `text_not_found` | 文字不在当前屏 | 重截、`de_ocr`、滑一屏再找 |
|
||
| `device_busy` | 设备跑任务 | 换设备/等待 |
|
||
| 一直加载 | 网络/内容未就绪 | 等待重截,勿狂点 |
|
||
|
||
---
|
||
|
||
## 10. 效率与预算
|
||
- 每步必须推进目标;界面未变不重复截图/点击(但**每拍开始时需要一次新鲜观察**)。
|
||
- 找不到目标时:滑动查找设上限(建议 ≤ 5 屏),超出即停止汇报。
|
||
- 连续 6 步无进展 → 停止(§8.3)。
|
||
- 不要为"确认"而反复截图同一画面(除非上一拍是写操作,需要验证)。
|
||
|
||
---
|
||
|
||
## 11. 安全红线(不可违反)
|
||
1. **绝不 `adb kill-server` / `adb disconnect`**。
|
||
2. **不抢任务设备**(`device_busy` 就避开)。
|
||
3. **L2 敏感写**(发评论/私信、关注取关、发布、下单支付、改资料)→ **默认不做**,先截图请人工确认。
|
||
4. **L3 破坏性**(卸载/清数据/改系统设置/恢复出厂/删文件)→ **一律不做**。
|
||
5. **不泄露**设备上的个人信息与凭据;不外传截图。
|
||
6. **不绕过**写门控/白名单/审计。
|
||
|
||
---
|
||
|
||
## 12. 当前边界与相关文档
|
||
- MCP 无任务 CRUD、无独立鉴权(靠网络隔离)。
|
||
- `doc/MCP.md`(工具手册)|`doc/MCP_DESIGN.md`(设计与现状对照)|`doc/API.md`(REST 目录)
|
||
- 平台内部机制:`doc/AI_CONSOLE.md`(AI 控制台)、`doc/ARCHITECTURE.md`(架构)、`doc/DATA_MODEL.md`(数据)
|
||
- 文档总索引:`doc/README.md`
|
||
- 岗位职责与授权分级:`doc/staffdeck/JOB_SPEC.md`
|