feat: add versioned rule capabilities (#22)

This commit is contained in:
QiuSW
2026-08-15 15:01:19 +08:00
parent 4b38a876de
commit 9d4a0b9845
28 changed files with 1005 additions and 85 deletions
+1 -1
View File
@@ -32,4 +32,4 @@
## 当前阶段
当前 MVP 的 T01~T07、T09~T18 均已完成实现、验证并由用户验收。T08(只读实时屏幕)已延期且未实施,不属于当前 MVP。T17 已在一加/ColorOS 真机完成指定设备领取、空闲领取、PDD 商品详情页到达和部分结果提交验证,不包含华为兼容。当前范围仍只包含从人工添加 PDD URL 到任务详情查看结果的最小闭环,任何相邻业务必须另建 MVP 并重新确认。
当前 MVP 的 T01~T07、T09~T19 均已完成实现、验证并由用户验收。T08(只读实时屏幕)已延期且未实施,不属于当前 MVP。T17 已在一加/ColorOS 真机完成指定设备领取、空闲领取、PDD 商品详情页到达和部分结果提交验证,不包含华为兼容。T20 正在实现 v2 规则契约和设备能力协商,随后由 T21~T23 完成采集器、管理端规则模板和真机验收。当前实施范围仍是采集闭环;Agent 架构允许未来增加独立采购规则的创建订单能力,但付款能力禁止进入项目。
+3 -1
View File
@@ -43,7 +43,7 @@ Android Portal/Agent
| 表 | 必要内容 |
|---|---|
| `agent_device` | 唯一 `install_id`、设备信息、状态、Token 摘要、最后心跳 |
| `agent_device` | 唯一 `install_id`、设备信息、状态、Token 摘要、版本化能力、最后心跳 |
| `pdd_product` | `id`、唯一 `goods_id`、当前 `url`、创建/更新时间 |
| `collection_rule` | `id`、`name`、`content_json`、创建/更新时间、`deleted_at` |
| `collection_task` | 商品/设备外键、五态状态、URL/goods_id/规则快照、租约、结果摘要、错误和时间 |
@@ -55,6 +55,8 @@ Android Portal/Agent
`collection_task` 的状态仅为 `pending`、`running`、`completed`、`completed_partial`、`failed`。设备身份和心跳表属于 Agent 领取任务的必要基础,不承载 PDD 业务数据。
设备以 JSON 数组保存最后一次注册或心跳上报的版本化能力。v1 任务兼容未上报能力的旧 Agent;v2 任务在创建指定设备任务、获取下一任务、领取和开始四个边界重复校验能力,避免旧 APK 执行未知规则。
数据库使用两个可空 guard 列表达跨数据库唯一约束:活动任务的 `active_slot=1`,运行中设备的 `device_run_slot=1`;终态记录对应列为 `NULL`。复合唯一索引据此保证同商品最多一个活动任务、同设备最多一个运行中任务,同时允许保留任意数量的终态历史任务。状态与 guard 列还有数据库检查约束,必须在同一条状态变更语句中更新。
## 已建立的工程入口
+3
View File
@@ -19,6 +19,8 @@
- 删除采用软删除;删除后不能创建新任务,但已有任务继续执行自身快照。
- 商品详情步骤应声明精确 `activityName`,并与包名和唯一控件共同作为页面证据;进入 PDD 登录 Activity 必须返回 `PDD_LOGIN_REQUIRED`,不能提交采集成功。
- 唯一文字节点不可点击时,Agent 只可点击其最近的可点击父容器;不得改点兄弟节点或相似文字。
- v2 规则使用类型化动作和固定阶段钩子。已由 Agent 支持的选择器、别名、超时、滑动方向和有限次数可以只更新规则;新增动作类型或页面算法才需要升级 Agent。
- Agent 可扩展,但规则必须按任务类型授权:采集规则不能创建订单,采购规则未来可以使用独立的创建订单能力,任何规则都不能付款。
## 采集任务
@@ -47,6 +49,7 @@
- 登录失效、验证码、风控、人机验证和找不到唯一控件时失败并给出具体错误。
- 不使用 OCR/VLM 兜底,不猜测缺失数据,不保存原始控件树或截图。
- 当前 MVP 不创建订单、不支付、不提供实时屏幕或管理端远程控制。
- Agent 的长期能力可以扩展到采购规则中的“创建订单”,但采集规则不能调用该动作;采购必须作为独立高风险 MVP 实施。付款、免密支付及任何等价动作始终禁止。
## 设备身份与认证
+31 -7
View File
@@ -31,7 +31,7 @@ GET /api/admin/v1/collection-rules
规则只有 `name` 和 `content` 等当前值,创建成功后立即可用。删除为软删除;已删除规则不能创建新任务,已有任务继续使用任务内快照。
`content` 使用以下 `schemaVersion: 1` 契约:
`content` 支持原有 `schemaVersion: 1` 线性步骤和 `schemaVersion: 2` 类型化采集器契约。v1 契约如下:
```json
{
@@ -61,6 +61,25 @@ GET /api/admin/v1/collection-rules
- 规则解析阶段拒绝支付、付款、提交订单等危险目标。完整控件树只在 Android 内存中用于匹配,不保存也不上传。
- 浏览器和 Android 系统包中的 `click` 只允许精确目标 `打开拼多多APP`、`打开拼多多 App` 或 `打开`;其它点击在规则解析阶段拒绝。Android 先以浏览器打开服务端已规范化的 PDD URL,再由这些受控步骤进入拼多多。
### v2 PDD 商品详情规则
v2 完整示例见 [PDD 商品详情规则](rules/pdd-product-detail-v2.proposed.json)。规则声明:
- `ruleType: pddProductDetail`。
- `navigation.steps`:只负责浏览器和系统确认层;不能点击 PDD 页面。
- `pageEvidence`:精确的 PDD 包名、Activity 和非空节点证据。
- `collector.collectorId: pddProductDetailV1`:引用 Agent 中经过测试的类型化能力,不下发可执行代码。
- `hooks.afterSpecPanelOpen`:固定阶段的安全动作;当前只允许对语义目标 `specPanel` 执行 `swipe`,方向为上下左右、单动作次数 1~5、等待 0~2000 毫秒,单阶段最多 8 个动作。
- `collector.dimensionAliases`、`timeoutsMs` 和 `limits`:分别管理规格标题别名、超时和遍历/SKU 上限。
例如规格面板打开后向上滑动两次,只修改规则:
```json
{"hooks":{"afterSpecPanelOpen":[{"action":"swipe","target":"specPanel","direction":"up","count":2,"settleMs":350}]}}
```
Agent 使用可扩展的类型化动作注册表,而不是任意脚本。采集规则不能创建订单;未来采购规则可以引用单独审核的创建订单能力,但任何规则都不能执行付款。
## 管理端:采集任务
```http
@@ -110,12 +129,13 @@ POST /api/agent/v1/heartbeat
{
"requestId": "uuid",
"installId": "uuid",
"name": "HUAWEI-01",
"manufacturer": "HUAWEI",
"model": "Mate 60",
"androidVersion": "14",
"name": "OPPO-PKG110",
"manufacturer": "OPPO",
"model": "PKG110",
"androidVersion": "16",
"agentVersion": "0.1.0",
"pddVersion": "7.72.0"
"pddVersion": "7.72.0",
"capabilities": ["rule.schema.v2", "action.swipe.v1", "collector.pdd.product-detail.v1"]
}
```
@@ -124,6 +144,7 @@ POST /api/agent/v1/heartbeat
- 已存在 `installId` 的新请求必须携带该设备的 Bearer Token,认证成功后幂等更新设备信息,不轮换 Token。
- 缺少或使用错误/已吊销 Token 返回 HTTP 409 和 `DEVICE_INSTALL_ID_CONFLICT`。
- 生产模式只接受 TLS。只有服务部署在可信反向代理之后并显式设置 `GOAUTO_TRUST_FORWARDED_PROTO=true` 时,服务端才接受代理的 `X-Forwarded-Proto: https`;不得在服务直接暴露公网时开启。注册接口另有单实例、按直连来源 IP 的基础限流,网关仍须设置共享限流。
- `capabilities` 最多 32 项,使用小写的版本化能力名。旧 Agent 可以不提交该字段并继续执行 v1;v2 任务只能由包含规则所需全部能力的设备领取。
管理员设备动作:
@@ -139,7 +160,8 @@ POST /api/admin/v1/devices/{deviceId}/token/revoke
```json
{
"requestId": "uuid",
"currentTaskId": "task-id-or-null"
"currentTaskId": "task-id-or-null",
"capabilities": ["rule.schema.v2", "action.swipe.v1"]
}
```
@@ -163,6 +185,7 @@ POST /api/agent/v1/tasks/{taskId}/start
2. `deviceId` 为空的任务可由在线且没有活动任务的设备领取。
3. `claim` 在一个数据库事务中设置设备和租约,竞争失败返回 `TASK_ALREADY_CLAIMED`。
4. 设备已有活动任务时返回 `DEVICE_BUSY`。
5. 指定设备和领取设备必须具备规则快照要求的全部能力;不兼容时返回 `DEVICE_CAPABILITY_MISMATCH`。未指定设备任务会跳过不兼容设备。
`claim` 保持任务为 `pending`,写入设备、两分钟领取租约和递增的 `leaseVersion`;`start` 只接受当前设备持有的有效租约,将状态原子改为 `running`、记录开始时间并续租。Android 进程还必须以本地互斥锁确保同一时刻只有一个任务进入执行器。
@@ -234,3 +257,4 @@ POST /api/agent/v1/tasks/{taskId}/fail
| `RULE_AMBIGUOUS` | 规则同时匹配多个控件 | 否 |
| `TASK_ALREADY_CLAIMED` | 未指定任务已被其他设备领取 | 否 |
| `DEVICE_BUSY` | 设备已有活动任务 | 否 |
| `DEVICE_CAPABILITY_MISMATCH` | 设备缺少任务规则要求的版本化能力 | 否 |
+4
View File
@@ -27,6 +27,10 @@
| T17 | [#19](https://git.ilapage.cn/OPC/goauto/issues/19) | 一加最小闭环验收 | T05、T06、T09~T16 |
| T18 | [#20](https://git.ilapage.cn/OPC/goauto/issues/20) | 本地 config.yaml 数据库启动配置 | T01 |
| T19 | [#21](https://git.ilapage.cn/OPC/goauto/issues/21) | PDD 商品详情颜色价格与尺码采集规则 | T11、T12、T13、T17 |
| T20 | [#22](https://git.ilapage.cn/OPC/goauto/issues/22) | v2 规则契约、阶段钩子与能力协商 | T19 |
| T21 | [#23](https://git.ilapage.cn/OPC/goauto/issues/23) | Android PDD 商品详情采集器 | T20 |
| T22 | [#24](https://git.ilapage.cn/OPC/goauto/issues/24) | 内置规则模板与管理端校验 | T20、T21 |
| T23 | [#25](https://git.ilapage.cn/OPC/goauto/issues/25) | v2 一加真机验收 | T20~T22 |
## 延期
+29 -5
View File
@@ -4,7 +4,7 @@
从 `D:\chengma\cmautobuy\client` 迁移这套能力是合理的,但不能把其中的文字、resource-id 或坐标直接拼成 GoAuto `schemaVersion: 1` 规则。源项目的可靠性来自一套有状态采集算法,而 GoAuto v1 目前只支持唯一节点上的单次 `wait`、`click`、`input`、`back` 和 `extract`。
推荐新增 `schemaVersion: 2` 的受限高层采集动作:服务端规则管理页面证据、规格别名、超时和遍历上限;Android Agent 固化遍历、选中确认、稳定采价和禁止下单/支付的算法。规则草案见 [pdd-product-detail-v2.proposed.json](rules/pdd-product-detail-v2.proposed.json)。该文件目前是设计输入,v2 执行器完成前不能导入管理端。
推荐新增 `schemaVersion: 2`、可扩展的类型化动作注册表和高层采集动作:服务端规则管理页面证据、规格别名、阶段钩子、超时和遍历上限;Android Agent 提供经过测试的动作实现,并由策略层按 `ruleType` 授权。规则草案见 [pdd-product-detail-v2.proposed.json](rules/pdd-product-detail-v2.proposed.json)。该文件目前是设计输入,v2 执行器完成前不能导入管理端。
## 源项目实际做法
@@ -53,9 +53,11 @@ Android 受限状态机
结构化结果(不含原始控件树和截图)
```
### 为什么不做通用脚本 DSL
### 为什么采用可扩展动作注册表,而不是任意脚本 DSL
把循环、任意正则、坐标点击和条件跳转都开放给服务端,会使规则成为远程执行脚本:难以静态验证、难以保证不会触发下单,并且每条规则都要重复实现边界和超时。高层采集器只暴露有限配置,既保留集中管理,又能在 Android 内统一测试安全状态机。
Agent 不限制为“只能采集”,而是注册带版本的类型化能力,例如 `swipe.v1`、`pddProductDetail.v1` 和未来的 `pddCreateOrder.v1`。规则可以组合 Agent 已声明支持的动作,因此增加一次已支持的滑动不需要升级 APK;只有出现新动作类型或新页面算法时才升级 Agent。
把任意脚本、任意坐标和不受约束的循环开放给服务端仍不可取:它们无法静态校验,可能绕过任务类型边界,也很难证明不会误触付款。类型化动作注册表保留扩展性,同时让服务端校验参数,让 Android 策略层做最终授权。
### 服务端可配置内容
@@ -64,25 +66,47 @@ Android 受限状态机
- 颜色、尺码标题的精确别名列表。
- 页面、选中、价格稳定超时。
- 最大商品页纵向滑动、规格横向/纵向滑动和最大 SKU 数量。
- 固定阶段的安全钩子;当前支持语义目标、方向、次数和动作后等待。
例如规格面板打开后向上滑动两次,只需更新规则,不需要修改 Agent:
```json
{
"hooks": {
"afterSpecPanelOpen": [
{
"action": "swipe",
"target": "specPanel",
"direction": "up",
"count": 2,
"settleMs": 350
}
]
}
}
```
### Android 固定内容
- 规格入口只能使用 `safeBottomSpecEntryV1` 安全策略,禁止规则提供任意坐标。
- 动作注册表与参数边界;规则只能引用 Agent 声明支持的能力,不能提交可执行代码。
- 规格入口默认使用 `safeBottomSpecEntryV1` 策略,不接受规则提供任意坐标。
- 价格只能使用固定人民币解析器,金额输出为整数分。
- 每次颜色点击后必须重新获取内存控件树;不能复用旧节点。
- 若页面暴露 `selected`/`checked` 或“已选”摘要,必须据此确认颜色已选中。
- 价格必须连续两次读取一致才算该颜色的价格。
- 尺码只读,不点击;禁止任何提交订单和支付动作。
- 每个循环都有次数和总时长上限。
- `collection` 规则不能调用创建订单动作;未来 `purchase` 规则可以调用专用的 `pddCreateOrderV1`,但付款相关动作在最底层始终拒绝。
## 相对源项目的优化
1. **不复制 XML 解析实现。** GoAuto 直接把 `AccessibilityNodeInfo` 投影为仅存在内存的不可变树模型,避免序列化、落盘和再次解析 XML。
2. **保留浏览器链。** 源项目直接深链,GoAuto 则继续验证浏览器提示、系统确认和最终 PDD Activity,符合当前设备部署方式。
3. **能力协商。** 设备注册/心跳应上报 `collector.pdd.product-detail.v1`;服务端不能把 v2 任务发给旧 APK。只比较 `agentVersion` 不够可靠。
3. **能力协商。** 设备注册/心跳应上报 `rule.schema.v2`、`action.swipe.v1` 和 `collector.pdd.product-detail.v1`;服务端不能把 v2 任务发给旧 APK。只比较 `agentVersion` 不够可靠。
4. **第三维不静默合并。** 若出现颜色、尺码之外的维度,保存已确认的数据并提交 `completed_partial`,在 `missing` 标记不支持维度;不伪造完整 SKU。源项目当前直接失败,和 GoAuto“数据不齐仍提交”的规则不完全一致。
5. **缺价不伪造 SKU。** 颜色仍进入维度,缺少稳定价格时记录 `price:<颜色>`;不为该颜色生成带虚构价格的 SKU。
6. **规则能力版本独立。** `schemaVersion` 管契约形状,`collectorId` 管 Android 算法能力,便于以后修复页面适配而不破坏已有任务快照。
7. **采集与采购分权。** Agent 平台可以扩展到创建订单,但规则必须声明类型;采集规则无权创建订单,采购规则可以在独立高风险流程中创建订单,任何规则都无权付款。
## 建议实施顺序
@@ -35,6 +35,9 @@
"className": "android.widget.FrameLayout"
}
},
"hooks": {
"afterSpecPanelOpen": []
},
"collector": {
"collectorId": "pddProductDetailV1",
"specEntryStrategy": "safeBottomSpecEntryV1",