Commit Graph
21 Commits
Author SHA1 Message Date
butubb cf075ba4e1 feat(任务): 滑动拟人化 + 每台设备有自己的手感(core/humanize.py)
用户反馈"滑动太像机器人""批量执行时每台设备都一样"。

core/humanize.py(新)分两个层次:
- **每次不同**:起止点/幅度/时长抖动、弧线方向随机——最容易被识别的不是"慢",
  是"每次都一模一样";
- **每台设备不同**:由 crc32(serial) 派生稳定的"性格"(手速 0.82~1.32、
  幅度 0.86~1.16、弧度、常用横坐标 ±9% 屏宽、停顿 0.80~1.35)。同设备多次运行
  风格一致,不同设备明显不同——13 台批量跑看着像 13 个人各刷各的。
  用独立 Random 实例播种,不碰全局 random(多线程 worker 会打乱取值顺序)。

轨迹用二次贝塞尔走 d.swipe_points(曲线),异常时自动退回直线 d.swipe。
**点数固定 4 个**:swipe_points 在慢设备上每多一个点约多 1 秒(实测 2 点
1.4s / 6 点 6.0s / 10 点 10.6s),设备自己会插值几十步,4 点已足够弯。

顺带修一个真机上的老毛病:滑动原本每次都要读 d.info,而它在部分设备上要
**14 秒**。改用 humanize.screen_size()(走 window_size,同设备 0.6s,缓存
120s)——所以哪怕多了弧线,真机单次滑动反而从 ~15s 降到 ~5s。

- tasks/generic/task.py:swipe / swipe_until 走拟人(新增 distance_ratio、
  jitter、humanize 参数,默认开);swipe_until 每轮停顿也抖动;wait 步骤新增
  可选 vary_pace(默认关,按设备节奏缩放 0.8~1.35 倍);
- static/admin/editor.js:滑动类步骤参数面板加"幅度/抖动/拟人轨迹"+ 说明;
- 文档:TASK_DEV.md §8.4(含"点数别调大""别用 d.info"两个坑)、步骤表、
  README 能力表与结构。

自测:假设备单测(曲线/抖动/设备间差异/退化路径/不越界/尺寸缓存)+ 真机联调
(4 次滑动全部 ok,标注"弧线"、坐标每次不同、对照的 humanize=false 仍是直线)。
2026-09-16 12:39:47 +08:00
butubb 621d48c800 feat(日志): 任务步骤明细表 + 「日志 → 步骤明细」面板(按设备/任务/时间过滤、按运行归组、导出 CSV)
文本日志只能 grep,"这台设备这次运行为什么失败"翻起来很费劲。新增一张
**结构化**的步骤明细表,把"哪一步、什么类型、哪个选择器、结果、耗时"落库。

- core/models.py:新增 task_step_log(run_id/job/设备/step_path/selector/
  result/detail/duration_ms),索引 run_id、created_at、(serial,created_at)、
  (job_id,created_at);
- core/step_log.py(新):**专用写线程 + 有界队列**批量落库——步骤执行是热路径,
  任务线程只 put_nowait(实测 9000 次入队 31ms),队列满丢弃并计数,绝不阻塞;
  另有保留期清理(默认 14 天,每日 04:13 + 每次启动);
- tasks/generic/task.py:_exec_one 记一条(异常=error / handler 返回 False=miss /
  未知类型=unknown / 概率未触发=skip);_exec_steps 维护路径栈得到 "2.1.3"
  这样的嵌套位置;**单次运行封顶 2000 条**——forever 循环任务否则会写爆表;
- 运行上下文 ctx(run_id/job_id/job_name/device_name)由 TaskManager 生成,
  经 create_worker(serial, params, ctx=None) 传入 worker(扩展点向后兼容);
- 接口:/api/step_logs(过滤+分页)、/runs(按运行归组)、/filters(下拉选项)、
  /download(CSV,带 BOM);
- 前端:日志页拆成「文件日志 / 步骤明细」子分栏 + static/admin/steplog.js。

红线:新表自动进备份覆盖清单(SUMMARY_TABLES 由元数据派生),已补
TABLE_LABELS 中文标签,导出实测 14 张表、coverage_missing 为空。

文档:DATA_MODEL §2.8/§1、API §10.2、ARCHITECTURE §1.1/§2.2/§3.1、
DEVELOPMENT §5.2 与红线表、DEPLOY §5.2、TASK_DEV §8.3、README。
2026-09-16 08:58:43 +08:00
butubb 2c32c397c8 feat(日志): 日志页支持关键字/级别/时间过滤 + 下载(含滚动历史)
「日志」页原来只能 tail 固定行数、且文件下拉写死了 4 项(新增的 notify.log
根本选不到)。本次:

- core/logger.py 新增读取接口:list_log_files()(模块文件 + .1/.2 滚动历史,
  白名单)、query_log()(关键字/最低级别/时间过滤,返回结构化行)、
  read_log_text()(导出)。
  · 时间/级别过滤对**续行**用继承值(traceback 缩进行本身没有前缀),
    按 ERROR 筛不会把堆栈拆散;
  · 过滤按"最近 N 条命中"返回,保持文件原顺序;
- GET /api/logs 换新协议(rows/files/matched/scanned/truncated),
  新增 GET /api/logs/download(附件下载,支持同样过滤;无一条件时整文件);
- 顺带修 **目录穿越**:原实现 os.path.join(_LOG_DIR, file) 可用 ../../ 逃逸,
  现在 file 必须命中白名单;
- 顺带修 web/admin_api.py 里 _log 未定义(用户增删改的日志行会 NameError);
- 前端:文件下拉改为按接口渲染、加关键字(命中高亮)/级别/时间范围/下载/重置,
  自动刷新时不再把正在上翻的用户拽回底部。

文档:doc/API.md §10.1(参数与返回)、README 日志节。
2026-09-16 08:44:19 +08:00
butubb 3b6ec8c98f feat(通知): 加钉钉 / 飞书两种格式(含各自的加签算法)
## 两家签名算法不一样,照抄必错
| | 钉钉 | 飞书 |
|---|---|---|
| HMAC key | `secret` | `"{timestamp}\n{secret}"` |
| 被签内容 | `"{timestamp}\n{secret}"` | 空 |
| timestamp | 毫秒 | 秒 |
| 拼在哪 | URL query | JSON body |
| 结果 | Base64 再 urlencode | Base64 |
| 出错码 | `errcode 310000` | `code 19021` |

实现为 `BaseAdapter.sign_request()` 钩子(默认不动),两家各写各的;
`core/notifier.py` 的 `_post_once` 在发请求前调用它。

## 另外
- 钉钉:markdown 消息(title+text);成功码 0;默认限流 15/分(官方 20/分,**超限会被限 10 分钟**,留余量)
- 飞书:交互式卡片(header 颜色按事件级别 + markdown 元素);成功码 0;默认 60/分
- `PLANNED_FORMATS` 清空(下拉里不再有置灰项)
- **修一个泄漏**:`mask_url` 原来只打码 query 参数——**飞书的 token 在 URL 路径里**(`/hook/<token>`)
  → 接口回显会漏出去。现在同时处理路径 token(≥20 位随机串)与 Slack 的 `/services/T…/B…/X…` 三段。

## 验证(都跑过)
- **签名对拍官方示例**:钉钉逐字节一致(含 urlencode,`%2B` 级别)、飞书的 key/message 口径一致;
  时间戳钉住后比对,不靠"自己跟自己一致"
- 成功码按格式:wecom/dingtalk/feishu 的 0 与 bark 的 200 分别判成功,各自的错误码判失败
- 端到端 15 项:钉钉/飞书在假接收端上真发(URL 带签名、body 带 timestamp/sign、卡片是 markdown 元素、
  毫秒 vs 秒的时间戳),签名错时正确判失败(310000 / 19021),token 在回显里被打码
2026-09-15 14:29:11 +08:00
butubb 515cb5d580 docs: 根 README 结构表/前端 JS 加载清单补上 notify(含 notify_api/notifier/taskgen/notify.js,并修正文件数) 2026-09-15 14:05:44 +08:00
butubb 24ea289c15 feat(通知): 加 Bark 格式 + 格式切换时界面提示全部跟着变
## 用户报的第二件事:格式改了,提示没跟着改
弹窗里的 URL 示例/说明、密钥标签、限流说明都写死成企业微信了——选「通用 JSON」时
占位还是 `qyapi.weixin.qq.com`,限流还写着「企微硬限 20」。现在这些文案挂在**适配器**上
(`url_hint/url_help/secret_label/secret_help/limit_help`),由接口随格式下发,切格式即时更新;
限流值在用户没手动改过时也跟着格式的推荐值走(企微 20 / 通用 JSON 60 / Bark 60)。

## 新格式:Bark(iOS 推送)
- `POST {url}`,body `{title, body, markdown, group, level[, device_key]}`
  —— `markdown` 传富文本、`body` 传纯文本兜底(老版本 App 不认 markdown 字段时也能看清)
- URL 两种填法都支持:直接粘 Bark 复制的那串(`https://api.day.app/<key>`,key 在路径里),
  或填 `https://api.day.app/push` + 把 key 填到「设备 Key」(作为 device_key 发送)
- **成功判定按格式**:Bark 是 `code==200`(企业微信是 `errcode==0`)→ 新增
  `BaseAdapter.ok_codes`,`_post_once` 用它判定。少了这一步 Bark 的每次成功都会被误判成失败
- 正文按 2048 字节截断(走 APNs,体量有限)

## 顺带
- 通用 JSON 的 `secret` 现在会作为 `X-Webhook-Secret` 请求头发出(原先填了没用)
- `_formats()` 改为序列化适配器元信息,新增格式只改一处

## 验证
- 格式切换 14 项断言全绿:三种格式的 URL 示例/密钥标签/密钥说明/限流说明/模板区/限流默认值
  全部跟着切换;下拉里 Bark 出现在已实现区
- Bark 端到端 7 项:`code=200` 判成功、`code=400` 判失败(含重试)、请求体带
  device_key/title/body/markdown/group、URL 里的 key 在接口回显里被打码
- 文档:NOTIFY.md §5 的格式表补 Bark 列(URL 怎么填 / 成功码 / 约束),并说明
  "提示文案挂在适配器上,别写死在页面里"
2026-09-15 14:05:33 +08:00
butubb 97cec6e211 feat(通知): 系统级 Webhook 通知子系统(事件目录 + 可插拔适配器 + 防刷屏)
平台此前出了问题只能靠人盯页面。现在各组件统一走 `notifier.notify(事件, **字段)`,
推到企业微信 / 自建服务;**所有可通知点都登记进事件目录,默认全关,用户按 webhook 勾选**。

## 架构(`core/notifier.py` + `core/notify_events.py`)
业务线程调 `notify()` → 只做内存操作(读配置快照/匹配订阅/入队)→ 返回;
后台 1 个 dispatcher(聚合 + 每 hook 限流 + 折叠摘要)+ 3 个 sender(真实 HTTP、退避重试)
负责真正发出去。硬约束:**notify 零 DB、零 HTTP、零阻塞、异常不冒泡**——所以任务线程里
可以直接调(不用 app_context、不用 try/except),但**必须放在所有 `with self._lock` 之外**。

- **事件目录 36 条**(任务批次/单设备/设备/Worker/业务/安装/系统/AI),支持 `task.*` 通配订阅;
  语义分工避免重复告警:`worker.*` 是单次尝试级,`task.device.success/failed` 是唯一权威结论。
- **适配器可插拔**:`wecom`(markdown,按 4096 **字节**截断、超限不截半个汉字)+
  `json`(模板占位符,替换值按 JSON 转义,保存前干跑校验);钉钉/飞书留了插槽(前端置灰)。
- **防打爆四层**:聚合窗口(默认 30s,同批次合并成一条并带样本)→ 令牌桶限流(默认 18/分,
  对齐企微硬限 20)→ 被限流的**折叠成摘要不丢弃** → 有界队列背压。取舍:失败通知最多延迟
  一个窗口,换来群不被刷屏。

## 安全与存储
- 配置只落 `app_meta.notify_webhooks` 一个键(**不建表** → 不涉及备份覆盖红线)。
- URL 本身就是凭据(企微 `?key=`)→ 接口回显/发送记录/日志一律 `mask_url()/scrub()`;
  编辑时留空即不修改;secret 永不回显。DATA_MODEL 的明文凭据告警补上了这一条。
- 发送记录:内存环形缓冲 200 条(重启清空)+ 独立 `logs/notify.log`。

## 接入点(每个都放在锁外、不改 return 顺序)
task_manager(批次开始/结束用新增的 `_BatchTracker` 统一在 finally 计数、单设备成功/失败/
离线/重试/停止/抢占/归还/cron 停止)、device_worker 心跳看门狗、generic 任务选择器连续失效、
apk 安装开始/完成、设备上下线(**状态沿检测**,只报新变化)、备份导出/恢复、经验巡检、
用户登录、服务启停。

## 前端
系统 Tab 新增「通知 / Webhook」子分栏:多条 webhook 列表(URL 打码)+ 编辑弹窗(格式/URL/
密钥/事件勾选树带 ★建议/聚合/限流/自定义模板/预览)+ 发送测试 + 发送记录。

## 自测
- 进程内逻辑 10 组断言全绿:聚合合并、限流+折叠、无配置/全局关静默丢弃、未知事件、
  内部异常不外泄、JSON 转义(标题含引号换行仍合法)、URL/异常消息脱敏、配置校验。
- 端到端(假 webhook 接收端)17 项断言全绿:真实事件投递(user.login / task.batch.no_device)、
  企微请求体形状、**HTTP 200 + errcode 93000 判为失败**、500 重试 3 次、记录里 URL 打码。
- 韧性:webhook 指向黑洞地址时登录耗时 100~114ms(基线 107~133ms,**异步隔离生效**);
  配置写成坏 JSON 服务照常启动、通知静默不发、日志有 error(服务端实测后已复原)。
- 页面:系统 → 通知 面板/弹窗/36 个事件复选框/预览全部正常,无 JS 报错。
- 自测数据已清理(webhook、自建任务、写坏又复原的配置键)。

文档:新增 doc/NOTIFY.md(事件表/配置/格式约束/防刷屏/加事件三步骤/排障)并登记进 doc/README;
API.md §2.11;DATA_MODEL 的 app_meta 键表与明文凭据告警;ARCHITECTURE 线程表/分层/扩展点;
根 README 功能索引与日志表。
2026-09-15 13:55:14 +08:00
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
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
butubb 98cdc39224 chore: 删除抖音养号任务类型,平台只保留 generic_steps
tasks/douyin/(task_type=douyin_nurture)整体删除,唯一任务类型是 generic_steps。
所有默认值/文档/接口示例同步改成 generic_steps:

- tasks/:删 douyin 包;__init__ 只注册 generic;base.py/generic 注释改为照 generic 抄
- 默认值:core/models.py(列默认 + 旧 JSON 迁移默认)、core/task_manager.py TaskJob、
  web/tasks_api.py 建任务默认、static/admin/tasks.js 新建任务默认
- core/task_manager.py:去掉 douyin 专属的"清理废弃 comment 参数"迁移块,改为**启动时告警**
  仍残留已删类型的任务(只告警不改数据);run_job_now 对已删类型直接返回明确错误,
  不再"报已触发、线程里静默失败"
- 清理残留:douyin_running 状态位(无任何读取方)、core/__init__、core/actions/*、
  core/logger.py 注释里的抖音示例
- 文档:README(特性/目录树/类型表/参数表/示例)、TASK_DEV(目录树/注册说明/模板引用)、
  ARCHITECTURE(注册示例/action 注册表示例)、API.md(task_types 与任务 JSON 示例)、
  AI_TASK_GEN(P1 去掉 douyin 预设)、DEVELOPMENT
- 注:示例里"抖音"作为**App 名**(MCP 列应用、AI 建任务的需求举例)保留,与任务类型无关

自测(全部通过):类型列表只剩 generic_steps;建任务不传类型默认 generic_steps;传
douyin_nurture 被 400 拒;库里塞残留旧类型任务 → 启动日志告警 + 执行返回明确错误 +
不自动删用户数据;前端新建任务下拉 1 项且默认选中、界面建任务成功;监控页卡片两个按钮 +
覆盖设备正常。临时任务/数据验完已清理,任务集合复原。
2026-09-10 21:43:08 +08:00
butubb ce47a5b83d refactor: web_server 模块化拆分(web/ 蓝图包 auth/monitor/tasks/admin/tools/devices/apks/tailscale + context/common,web_server 1796→193 行仅留装配与启动)+ 大屏优化(网格 5s 轮询、弹窗独占缩略图、流支持 q/fps)+ 三修复(MIUI 屏幕状态检测改 dumpsys power、补 ADB_PATH 导入修复一键亮屏、renderGrid 增量渲染不重载缩略图) 2026-08-19 14:55:29 +08:00
butubb c78f17d72f feat: 监控大屏(/wall 全屏深色控制室风格:设备卡片网格+缩略图轮询+统计+时钟,缩略图 360px/q55 每 2.5s 一帧 20 台仅 ~0.2 核 CPU)+ /api/screen/thumb 接口 + 导航栏大屏入口 2026-08-19 14:13:15 +08:00
butubb 5543bad0e6 docs: 全面更新——README/API/DEVELOPMENT 摘除 STF 章节(设备池/型号/看屏/新端点文档,技术红线改为共享 transport 表述) 2026-08-19 14:07:53 +08:00
butubb 21d3aa8268 feat: 任务离线设备自动跳过(serial/分组模式触发时过滤 STF 池离线设备,默认开启,任务编辑器可勾选关闭) 2026-08-14 09:16:54 +08:00
butubb 060157ea1a refactor: 前端JS拆分为8个模块(base/list/monitor/editor/tasks/tools/apps/admin,按依赖顺序加载)+ 删除废弃文件(start_web.bat/main.py/fix_web.bat/cleanup.py,web已全覆盖)+ 文档同步 + 修复/api/summary缺导入 2026-08-11 14:53:04 +08:00
butubb 3bd56b4f59 feat: 工具Tab新增应用版本管理(按包名并发查询所有设备安装版本)+ 文档同步更新(README/API/ARCHITECTURE/DEPLOY:工具Tab各工具、条件判断if_el+OCR、STF设备管理、.env密钥配置) 2026-08-11 10:57:14 +08:00
butubb de66c6194b feat: 维护页 Tailscale 管理(设备列表/改名/授权/密钥不过期/设置IP/auth key,独立模块 core/tailscale_client.py)+ 密钥迁移 .env(STF_TOKEN/WEB_SECRET_KEY/TAILSCALE_API_KEY 不再入库)+ 修复设备更新端点(/device/{id} 405,改用 /name /authorized /key 专属端点)+ auth key description 仅 ASCII 2026-08-11 09:06:59 +08:00
butubb a48032da23 chore: 移除已废弃的一次性脚本 create_task.py(任务创建已由 Web 界面覆盖),README 同步清理引用 2026-08-11 08:34:38 +08:00
butubb a0d1a533c6 docs: 文档同步(README/API/架构/部署) 2026-08-11 08:27:33 +08:00
butubb e3afa5d36f docs: 新增开发手册(流程/准则/技术红线/手册),修正 README 文档索引
- doc/DEVELOPMENT.md:开发流程与 git 工作流(所有 git 操作需确认)、
  环境说明、技术红线(绝不 kill-server/断开IP:5555 等)、本地开发手册、常见开发任务
- README 修正错误的 Windows 绝对路径为相对路径,目录结构补充 monitor.js
2026-08-08 21:17:25 +08:00
butubb 468e86f0a9 feat: 新增通用步骤任务+元素抓取,完善全部项目文档
- 新增 generic_steps 通用步骤任务(可视化步骤编辑器编排流程,支持 open_app/click/swipe/input_text/wait/loop/group)

- 新增 core/uiauto_helper.py 封装 uiautodev 元素抓取客户端

- web_server 新增元素抓取/截图/设备列表等 API

- monitor.html 新增步骤编辑器、元素抓取模态框、独立关闭逻辑

- 新增 README.md 项目总览(快速上手/架构/配置/FAQ)

- 新增 doc/ARCHITECTURE.md 架构详解、doc/DEPLOY.md 部署指南、doc/API.md 接口文档

- 修复 doc/TASK_DEV.md:移除已删除的 comment 引用,补充 generic 包,更新注册示例

- .gitignore 忽略 .claude/ 工具产物
2026-08-08 10:40:06 +08:00