Files
auto_control/doc/staffdeck/KNOWLEDGE_BASE.md
T
butubb ed9e8bacb1 feat(AI 建任务): 直接创建 + 草稿沉淀 + MCP de_snapshot;修「建任务页收不到 done」
用户报的"探索完无法点击创建任务"真因:一个 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 条用例、扇出单元用例、本地工具契约用例全绿。
自测产生的任务/草稿已全部清理(未碰用户既有数据)。
2026-09-14 08:14:11 +08:00

254 lines
14 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.
# 知识库 · 设备自动化平台(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`