Files
auto_control/doc/AI_TASK_GEN.md
T
butubb 24d57d3b96 docs: doc/ 全量重整——按现状重写并建立文档索引;项目统一更名 auto_control
背景:文档长期落后于代码(Tab 数、任务类型、接口示例等多处与现状不符),
且信息分散重复。这次按当前代码状态逐篇重写,并建立统一的文档体系。

新增
- doc/README.md:文档总索引(文档地图 / 推荐阅读路径 / **文档维护约定**)
- doc/DATA_MODEL.md:数据模型(7 张模型表 + 5 张非模型表、迁移机制、app_meta 键、
  数据目录、备份覆盖清单与双向自检)
- doc/AI_CONSOLE.md:AI 控制台机制(会话与 SSE、经验库/动作库蒸馏与召回、巡检、
  Markdown 渲染、推理链、token 统计、故障排查)

重写(按现状,去掉过时与重复)
- README.md:7 个 Tab、18 种步骤、设备生命周期、调度/窗口语义、常见问题;修掉
  「6 个 Tab / 分组为顶级 Tab」等过时内容与损坏的目录树
- doc/ARCHITECTURE.md:补启动装配顺序(import 期副作用、A~G 七阶段)、线程与锁清单、
  设备状态机、调度全链路、前端结构与实时通道、设计决策、**已知缺陷与踩坑清单**、扩展点
- doc/API.md:按蓝图重建「接口总索引」(107 条路由含鉴权)+ 分域详细说明 +
  非 JSON 响应汇总 + 错误分支速查
- doc/TASK_DEV.md:18 种步骤全表(参数/默认值/语义)、容器与公共参数、
  选择器与 XPath 序号语义、抓取器建议规则、新增任务类型骨架
- doc/DEPLOY.md:容器入口 start.sh 三件事、发布流程与检查清单、备份覆盖红线、
  按现象分类的故障排查
- doc/DEVELOPMENT.md:流程/红线/本地开发/**测试与写测试的约定**/配置速查/文档同步
- doc/MCP.md:19 个工具的参数级清单、坐标空间、写门控三连、安全与审计
- doc/MCP_DESIGN.md、doc/AI_TASK_GEN.md:标注设计 vs 实现现状,补交叉链接
- doc/backlog/TODO.md:新增「已知缺陷」小节(含复现与影响)+ 已完成留档
- .env.example:按代码实际读取的键重写(补 USB/DISCOVERY/MCP/AGENT,删死配置)

其它
- 项目名统一 auto_control:README/文档/scripts/pack.py 产物名;代码内的
  doc 章节引用(templates/admin/monitor.html)同步更新
- 校验:16 篇文档 156 条相对链接全部可解析;文档中的关键数字与代码核对一致
  (19 个 MCP 工具 / 18 种步骤 / 12 张备份表 / 1 种任务类型)
2026-09-10 22:19:18 +08:00

184 lines
16 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.
# AI 建任务(AI Task Generator)设计文档
> 状态:**设计稿,尚未实现**(P0 未开工)——本文描述的是「要做什么、为什么这么做」,不是现状。
> 现状请读:[AI_CONSOLE.md](AI_CONSOLE.md)(AI 控制台已实现的能力)、[TASK_DEV.md](TASK_DEV.md)(任务与步骤)、[MCP.md](MCP.md)(已实现的 19 个工具)。
> 关联代码:`web/agent_api.py`、`mcp_server/`、`mcp_agent/`、`tasks/generic/`、`static/admin/editor.js`。最后核对:2026-09-10。
## 1. 背景与目标
平台已有两套能力,但互不相通:
- **AI 控制台**:一句话 + 选设备 → 多模态 Agent(DeepSeek)通过 19 个 `de_*` 工具在手机上「边看边做」(截图看屏、`de_ui_tree` 拿元素树、`de_tap_element/de_tap_text` 语义点按),流式回放步骤。
- **任务系统 + 步骤编辑器**:`generic_steps` 任务 = 一棵可嵌套步骤树(open_app/click/swipe/loop/group/if_el…18 种节点),在编辑器里拖拽编排、单步试跑、定时调度。
目标:让**非工程用户用一句自然语言需求**(例:「创建一个每日养号刷视频的任务,每天 8:00-9:00 在 100.100.10.13 跑」)得到**一条可直接调度、可继续在现有步骤编辑器里手改的任务**。AI 先自己在设备上打开 App、看 UI 树、确认可点元素,再直接撰写编辑器的步骤 JSON。
### 产品体验(一页)
1. 用户进入「AI 控制台 → 模式=AI 建任务」,选一台**空闲**设备,填需求 +(可选)任务名/调度/目标。
2. AI 自探并**流式回放**(工具卡 + 截图,与现在一致):开 App → dump UI 树 → 确认要点的元素可命中 → 写步骤。
3. 完成后平台返回任务草稿 `draft`,服务端 schema 校验后,**前端直接打开现有「新建任务 → 步骤编辑器」**预填。
4. 用户核对/手改/单步试跑 → 保存 → 进任务列表,走原有调度器执行。
**核心信任原则:AI 只“提案”,不直接建库、不直接执行最终任务;最终落库/执行都在用户确认后由现有机制完成。**
## 2. 范围(P0 定稿,2026-09-09 与用户确认)
- **入口**:AI 控制台加「聊天 / AI 建任务」模式开关,复用会话/SSE/设备选择/停止/刷新恢复骨架。不新建顶级 Tab。
- **产出方式**:**AI 直接撰写编辑器的步骤 JSON**(非操作轨迹翻译)。自探信息只作上下文与审计;探索中的误点/多余截图不会混入任务。
- **任务类型**:**只产 `generic_steps`**(通用步骤)——平台当前唯一的任务类型
(原 `douyin_nurture` 预设参数生成已随该类型删除,不再做)。
- **定位原则:全部基于 UI 树**:
- 模型定位/点击一律走 `de_ui_tree` 拿到的元素(`text`/`id`/`description`/`text_contains`),多实例用 index,或后端 `uiauto_helper` 生成的 `//*[@resource-id=..][k]` XPath;
- `de_tap_element` 确认能命中后才写进 `click` 步骤;
- **默认不产 `click_xy` 坐标点击**;UI 树给不了的元素记入 notes,交给人工/OCR 兜底;
- 滑动用方向语义 `swipe{direction}`,不用像素坐标。
- 产出完整任务信封:`{name, task_type:"generic_steps", target, schedule, retry, enabled, params:{max_duration, steps}}`。
## 3. 现状与可复用点(实现依据)
- 多模态 Agent 链路:`web/agent_api.py`(`POST /api/agent/run` 起后台线程、SSE `delta/step/done/error`、`/stop`、刷新恢复 `GET /api/agent/run`)→ `mcp_agent/agent.py`(OpenAI 兼容流式,工具经 fastmcp Client 拉 8033 的 19 个 `de_*`)→ `mcp_server/mcp_server.py`。
- 前端 AI 控制台骨架:`templates/admin/monitor.html` `#tab-agent` + `static/admin/agent.js`(设备选择、`sendAgentMsg`、`listenStream` 渲染 `agent-toolcard`、实时画面跟随)。
- 步骤权威 schema(前后端同构):`tasks/generic/task.py` `STEP_TYPES`(L44-83)/ `DEFAULT_PARAMS`(L86-103) 与 `static/admin/editor.js` `STEP_LIB`(L3-23)。
- 元素抓取 → XPath:`web/tasks_api.py /api/uiauto/elements`(L224)→ `core/uiauto_helper.get_elements`(`suggested.value` 即编辑器可用的 XPath)。
- 单步试跑:`/api/steps/test`(tasks_api.py L249)+ `editor.js _testStep`;`tasks/generic/task.py test_step`(L633)。
- 任务/调度/目标:`core/task_manager.py` `TaskJob`(L121-199);`POST /api/jobs`(tasks_api.py L68)。
- 设备占用语义:MCP 写工具 `_ensure_device_free`(mcp_server.py L60-78,running/connecting → `device_busy`);`agent_api` run 入口同样对 worker running/connecting 拒绝(409)。
- 经验库自进化:`agent_experience` + bigram 检索注入 + 每日巡检(`web/agent_api.py`)——P1 沉淀模板的现成载体。
## 4. 架构与数据流
```
需求+设备(空闲) ──▶ Designer Agent(自探, 模式=designer)
│ de_open_app / de_ui_tree / de_screenshot / de_tap_element…
▼
平台工具 submit_task(draft) ← 结束性调用
│ 服务端 draft schema 校验(白名单+必填+深度≤5)
▼
前端: 打开 openTaskModal 步骤编辑器, 预填 draft.task
│ 用户核对/手改/单步试跑(/api/steps/test)
▼
POST /api/jobs → 任务列表(原调度器执行)
(P1) draft+需求 沉淀 agent_experience, 相似需求注入参考
```
### 4.1 Designer Agent(新增模式,复用现有 Agent)
- `mcp_agent` 增加 designer 系统提示词:角色=自动化任务设计师;行为约束见 §5.1。
- 增加**平台级工具**(不属设备 `de_*`):
- `submit_task(draft)`:结束性工具,模型完成自探后提交草稿即停止,服务端立即校验。
- 会话内同时记录**结构化 trace**(每轮 `on_tool` 的 `{tool, args 精简, 屏号/证据}`),用于:校验证据(每个 selector 来自哪次树)、审计、P2 回放。
- `POST /api/agent/run` 增加 `mode:"designer"`;`done` 事件负载携带 `draft`(校验通过)或 `draft_error`(校验失败+原因,让模型补一轮)。
### 4.2 draft 契约
```json
{
"summary": "每日8-9点刷抖音养号:开抖音→循环(看5~35s+上滑)+随机间隔",
"task": {
"name": "抖音每日养号",
"task_type": "generic_steps",
"target": {"mode":"serial","serial":"100.100.10.13:5555"}
| {"mode":"group","group_name":"测试"} | {"mode":"all"},
"schedule": {"mode":"once"} | {"mode":"cron","cron":"0 8 * * *"}
| {"mode":"cron_stop","cron":"0 8 * * *","stop_cron":"0 9 * * *"},
"retry": {"max_attempts":5,"delay":30},
"enabled": true,
"params": {
"max_duration": 0,
"steps": [
{"type":"open_app","label":"打开抖音","params":{"package":"com.ss.android.ugc.aweme","wait_home":true}},
{"type":"loop","params":{"loop_mode":"rounds","max_iterations":30,"children":[
{"type":"wait","params":{"min":5,"max":35}},
{"type":"swipe","params":{"direction":"up","duration_min":0.25,"duration_max":0.5}}
]}}
]
}
},
"notes": ["评论按钮需先进入视频页才可见"],
"evidence": [{"screen":"抖音首页","element":{"text":"关注","id":"..."},"xpath":"//*[@resource-id=\".../gvo\"]"}]
}
```
- 步骤节点结构:`{id?, type, label?, params}`;`id` 执行端忽略(编辑器重新生成),`params` 必填。
- 必填字段语义(**空值会被执行端静默跳过**,校验器必须拦):
- `click / long_click / swipe_until / wait_el / if_el` → `params.selector_value`
- `open_app / stop_app` → `params.package`
- 容器:`loop / group` → `params.children`(非空);`if_el` → `params.then`(`else` 可选)
- `swipe_until` → direction + max_swipes;`click_xy` P0 不产(如允许则 x/y 0-100)
- 节点公共可选 `params.probability`(0-100,缺省 100)
- `selector_type` 允许值:`xpath / description / text / resourceId / descriptionContains / className`(`if_el` 可 `ocr`)。
### 4.3 服务端新增
- `core/task_draft.py`:
- `STEP_TYPES` 白名单 + 每类必填/深度校验 `validate_steps(steps, depth)`(嵌套≤5);
- `validate_draft(draft)`:任务信封(name 非空、task_type==generic_steps、target mode ∈ {all,group,serial}(group 名存在)、schedule cron 合法、steps 校验);
- 归一化:把 `schedule` 里「每天 8-9 点」这类由前端/向导填的值转成 cron/cron_stop。
- `web/taskgen_api.py`(或并入 `agent_api`,推荐并入以最大化复用):
- 入口检查:serial 必须、设备在池/在线、worker 非 running/connecting(409,与现有语义一致);
- 起 designer 后台线程;SSE 事件在现有 `delta/step/done/error` 基础上,`done` 可带 `draft`。
- **注意**:现有 `POST /api/jobs` 对 params **盲存**(只校验 name+task_type)。AI 通道在**保存前**必须过 `validate_steps`,避免「任务 done 但什么都没做」(执行器对未知 type/空 selector 静默跳过)。
### 4.4 前端
- `monitor.html` AI 控制台加模式切换;建任务模式下输入栏旁有折叠「任务设置」(名称/调度时间/目标 serial·分组·全部/备注)。
- `agent.js`:done 携带 draft 后:
- generic_steps → 调 `openTaskModal()`(tasks.js)并把 `draft.task` 灌入步骤编辑器(step 卡片可视化、可拖改、单步试跑、保存);
- 弹窗内对 `notes`(含“需人工复核/OCR 兜底”项)给出醒目提示。
- 过程回放沿用现有 `agent-toolcard` 渲染;可标记当前为 designer 轮以便后续区分。
## 5. 约束与安全(红线)
### 5.1 Designer 自探规则(写入提示词)
1. 先 `de_open_app(package)`,再 `de_ui_tree` + `de_screenshot` 看每屏;点到关键状态后再 dump 下一屏。
2. 每个将写入步骤的目标元素,先用 `de_tap_element`(by=text/id/desc…)+ 截图**确认可命中**,并记下证据。
3. **不做破坏性动作**:需“评论/发送”时只确认输入框/发送键存在,不真发;产物里这类步骤 `probability` 调低并在 notes 标注“请人工复核”。
4. 探索步数上限(P0 建议 30 步),可被 `/stop` 打断;结束后尽力还原前台 App。
5. 未命中的元素一律不进任务;拿不准的进 notes 而非硬编。
### 5.2 平台级约束
- 自探/试跑只在**用户选的空闲设备**(busy → 409),杜绝与运行中任务在设备上物理打架。
- AI 不直接建库;生成任务仍需用户点保存(POST /api/jobs 现有权限)。
- 尽量不写死坐标;P0 默认禁 `click_xy`,产物以树元素定位为主。
## 6. 里程碑
- **P0(本设计主体)**:designer 模式 → 自探(UI 树定位)→ 直接撰写 generic_steps draft → 服务端 schema 校验 → 前端步骤编辑器预填确认保存。验收:一句话在真实设备上生成一条可调度的 generic_steps,步骤全部来自 UI 树且编辑器可打开。(平台只剩 generic_steps 一种任务类型,与原规划一致)
- **P1**:模板沉淀:把 draft+需求写入 `agent_experience`(新列存结构化 steps 或 JSON),相似需求注入参考;整链「演示试跑」(把 steps 在设备上以受控方式跑一遍并截图回报,需新增端点,复刻 `device_busy` 拒绝语义)。
- **进展(2026-09-10)**:动作级沉淀已落地——`agent_action` 表 + 从**成功步骤**蒸馏"命名动作"(steps 用编辑器 schema、带元素定位、禁坐标)+ 执行前按名/别名召回注入(`web/agent_api.py`)。AI 建任务可直接把这些动作当作 generic_steps 的**预制件**复用。
- **P2**:自定义动作支持(内联展开成 group,或新增 `action_ref` 节点 + 执行器/编辑器同步);多设备并行;成本与 token 控制。
## 7. 实现时需新增/改动文件(规划)
- 改:`mcp_agent/`(designer 提示词与 `submit_task` 工具、结构化 trace)、`web/agent_api.py`(mode=designer、done 带 draft)、`static/admin/agent.js` + `templates/admin/monitor.html`(模式切换/任务设置/draft 预填)、`doc/`(本文档关联)。
- 新:`core/task_draft.py`(schema+校验+归一化)、(可选)`web/taskgen_api.py`。
- 不动:任务执行器、调度器、`POST /api/jobs` 主体(保持现有盲存,只在 AI 通道校验)。
## 8. 验收(P0 实现后自测)
1. 目标设备空闲时:需求「每日 8-9 点刷抖音养号」→ 生成 generic_steps 任务,步骤为 `open_app → loop(wait+swipe)` 结构,调度 cron_stop 8-9 点。
2. 打开编辑器中该任务:步骤卡片完整、可拖改、单步试跑命中;保存后任务列表出现且下次运行时间正确。
3. 反例:模型产出含 `click_xy` 或未知 type / 空 selector → 服务端校验拦截并让模型补正;busy 设备入口 409。
4. 探索全程可在前端回放(工具卡+截图),未发送真实评论/未污染设备状态。
## 9. 需要转成 MCP / 平台工具的能力(分层,2026-09-09 与用户确认)
> 背景问答结论:目前 MCP 只有**设备层 19 个 `de_*`**(控制 + 只读 `de_list_tasks`),平台 CRUD(任务增改/启停/立即运行、分组、设备池、自定义动作、APK、备份、用户)**都还没 MCP 化**。方向认同「先把工具链补完善」,但不做"把所有平台 CRUD 一次性搬成 MCP"的大而全——**按消费方(AI 建任务 / 外部自动化)分层、按需补**。新增 MCP 工具一律:进 `doc/MCP.md` 手册 + `doc/MCP_DESIGN.md` 规格 + 与 web 同源的权限/busy/审计 + 校验逻辑下沉到 `core/` 共用(防双份漂移)。
### 9.1 现状盘点
- MCP(`mcp_server/mcp_server.py`,19 个 `de_*`)= 设备控制 + 设备只读 + `de_list_tasks`(平台任务只读)。
- 任务创建/修改/删除、toggle、立即运行、分组、设备池管理、自定义动作、APK、系统备份等 **REST 路由只给前端用,未暴露 MCP**。
### 9.2 P0 —— AI 建任务链路真正需要的「平台工具」(最小集)
只补两小类,其余设备操作全部复用现有 `de_*`:
1. **只读清单**(供自探确定 target/能不能做):
- `list_task_types` / `list_groups`(target 选 group 用)/ `list_pool`(可调度设备,含 busy 状态)
- (可与现有 `de_list_devices` 合并语义,避免重复)
2. **校验 + 提交(结束性)**:
- `submit_task(draft)` → 服务端用 **共用** `core/task_draft.validate_steps()/validate_draft()` 校验,**不直接落库**,返回 draft 供前端打开步骤编辑器预填、人工确认后走 `POST /api/jobs`。
> 关键:P0 的 Agent **不暴露任务 CRUD 写权限**(create/update/toggle/run),否则模型可绕过"AI 提案 → 人工确认"直接入库,破坏信任模型。
### 9.3 P1 —— 外部自动化 / 后续 Agent 的「写 MCP」(受权限约束,逐块加)
若目标延伸为"外部程序能像调 REST 一样操控平台",则按此清单**逐个**补(每加一个都做权限+busy+审计+校验下沉):
- 任务:`create_job` / `update_job` / `delete_job` / `toggle_job` / `run_job_now` / `query_jobs`
- 分组:`list_groups` / `create_group` / `update_group` / `delete_group`
- 设备池:`pool_list` / `pool_add` / `pool_remove` / `pool_toggle`
- 自定义动作 / APK 清单 等视使用再加
- **只读清单优先搬**;写类确认有真实消费方再做,避免空转。
### 9.4 分层与登记(红线)
- 每新增/修改/删除一个 MCP 工具或平台配置:同步更新 `doc/MCP.md`(全清单)、`doc/MCP_DESIGN.md`(规格/层级),并在提交里体现——见全局「doc 同步红线」。
- `core/task_draft.py` 是 web 校验与 MCP 校验的**唯一来源**,杜绝两套规则漂移。