feat(android): add Pinduoduo search probe

This commit is contained in:
QiuSW
2026-07-25 19:40:19 +08:00
parent 1c1c158149
commit f226d0f2ff
21 changed files with 1356 additions and 70 deletions
+3 -2
View File
@@ -51,8 +51,9 @@
## 当前阶段与优先路径
当前已完成 Phase 0:Android 可运行、设备就绪、workflow 测试和私有样本导入基线。
下一步是 T-101,用固定脱敏搜索词跑通拼多多关键词搜索并验证安全停止。
当前已完成 Phase 0 和 T-101:Android 可运行、设备就绪、workflow、私有样本导入
以及固定脱敏词拼多多搜索均已在真机验证。下一步是 T-102,只浏览并采集最多 5 个
候选,继续禁止订单提交和支付。
严格按以下顺序推进:
+3 -2
View File
@@ -8,7 +8,7 @@
| --- | --- |
| 任务来源 | 其他管理后台或本项目管理 Web 采集商品标题、描述、图片、数量和预算。 |
| 第一层样本来源 | 本机目录中的蝦皮订单文本和参考图;二者以蝦皮订单号作为同名文件名。 |
| 执行方式 | 采购人员使用 Android App 操作拼多多;当前没有可运行实现。 |
| 执行方式 | 采购人员使用 Android App 操作拼多多;固定词搜索探针已可运行,候选浏览和真实任务尚未实现。 |
| 核心痛点 | 人工把图片和描述转成搜索词、逐条比较商品并记录结果,耗时且不一致。 |
| 验证范围 | 一台设备、一个管理身份、一个采购执行人员、拼多多单平台。 |
| 资金边界 | MVP 不提交订单、不支付,只验证到人工确认位置。 |
@@ -140,7 +140,8 @@ T-004 已固定首版规则:推荐私有目录为被 Git 忽略的 `private-fi
`T-001` 完成。
- 首份蝦皮样本已由 T-004 真实导入验证;当前只支持单 SKU 和 JPEG,扩展格式需新
样例和独立任务。
- 拼多多版本、页面结构、账号登录状态和测试设备尚未形成可复现基线。
- OnePlus PKG110、Android 16/API 36、拼多多 8.17.0 的首页、搜索输入和结果页已形成
可复现基线;候选列表、详情页及账号风控差异仍待 T-102 验证。
- VLM 厂商、模型、成本上限、数据留存地区和图片隐私规则待确认。
- 拼多多平台条款、自动化允许范围和账号风控需要业务方确认;项目不实现绕过措施。
- 后续若允许提交订单,必须先明确 SKU、收货地址、运费、优惠、发票、金额审批、
+3 -3
View File
@@ -11,7 +11,7 @@
| Android 构建链 | Gradle 8.2;AGP 8.2.0;Kotlin 1.9.20;JVM target 17 | 已验证 | 已补齐上游缺失的 `gradlew.bat`,不依赖全局 Gradle。 |
| Android SDK | compileSdk/targetSdk 34;minSdk 26;SDK Build Tools 34.0.0 | 已验证 | 支持 Android 8.0+;本机使用 Command-line Tools 22.0。 |
| Android UI | Jetpack Compose + Material 3;Compose Compiler 1.5.5 | 上游已核实 | Compose BOM 为 2023.10.01。 |
| Android 自动化 | 项目目标以 `AccessibilityService` 为主,Shizuku 为兼容/增强路径 | 就绪观察基线已实现,动作待实现 | T-002 已实现只读前台/登录阻塞观察;搜索、点击和安全动作门禁由 T-101 开始实现。上游 `main` 仍保留 Shizuku 13.1.5。 |
| Android 自动化 | `AccessibilityService` 语义节点动作;Shizuku 保留为上游兼容路径 | 固定词搜索已真机验证 | T-101 已用可见、启用、唯一节点完成打开搜索、`ACTION_SET_TEXT` 精确回读、提交和结果页确认;没有坐标或 shell 降级。上游 `main` 仍保留 Shizuku 13.1.5。 |
| 第一层任务源 | UTF-8 无 BOM 四行蝦皮订单文本 + 同订单号 JPEG | 已实现 | `task-contract` 共享 `ProbeTask/TaskSource`;CLI 输出到 `.local/`,只有显式 Debug 属性才注入 APK,默认构建会清除私有资产。 |
| Android 长任务 | 前台服务 + 持续通知 | 计划采用 | 降低执行中被系统挂起的风险,仍需处理进程死亡恢复。 |
| 后端语言 | Go 1.23.0 | MVP 已定 | 与现有本机工具链一致;构建测试必须设置 `GOTOOLCHAIN=local` 防止静默升级。 |
@@ -27,7 +27,7 @@
| VLM 接入 | 应用内统一适配器,优先兼容 OpenAI 风格多模态接口 | 接口已定,供应商待定 | 模型输出必须符合本项目 JSON Schema。 |
| 通知 | MVP 不使用推送 | 已定 | 点击“获取任务”调用原子 claim API;V2 再评估厂商推送/WebSocket。 |
| 后端测试 | 标准库 `testing` + `httptest` | MVP 已定 | 覆盖状态机、权限、幂等、SQLite 事务和输入校验。 |
| Android 测试 | Gradle `test` + `kotlinx-coroutines-test` 1.7.3 + 真实设备 smoke | workflow 基线已实现 | T-003 已覆盖成功、timeout、有限 retry、安全阻塞、用户停止和并发拒绝;真实 UI 动作仍需真机 smoke。 |
| Android 测试 | Gradle `test` + `kotlinx-coroutines-test` 1.7.3 + 真实设备 smoke | 搜索探针已验证 | T-003 runner 与 T-101 页面分类/Fake driver 已覆盖;OnePlus PKG110 + 拼多多 8.17.0 固定词结果页 smoke 成功。 |
| 部署 | 单机局域网 Go 服务;容器化后置 | MVP 已定 | Android 测试机必须能通过 HTTPS 或受控测试网络访问。 |
## Roubao 上游版本基线
@@ -134,7 +134,7 @@ docs/
| --- | --- | --- |
| Android 标准验证 | `.\init.ps1` | 已验证 |
| Android 构建 | `android-buyer\gradlew.bat assembleDebug --no-daemon` | 已验证 |
| Android 测试任务 | `android-buyer\gradlew.bat test --no-daemon` | 已验证;无测试源 |
| Android 测试任务 | `android-buyer\gradlew.bat test --no-daemon` | 已验证;当前全工程 62 次测试通过 |
| Android 安装/启动 | `$env:RUN_START_COMMAND="1"; .\init.ps1` | 已在 Android 16 真机验证 |
| 后端依赖 | `go mod download`(在 `backend-api/`) | 待 `T-201` |
| 后端测试 | `go test ./...`(在 `backend-api/`) | 待 `T-201` |
+21 -1
View File
@@ -152,6 +152,23 @@ Debug 构建或测试装载。导入必须:
私有 fixture 只有在构建显式设置 `-PprobeFixturesDir` 时注入 Debug APK;普通构建
必须同步清空生成资产,防止上一次真实样本残留。
T-101 的固定词搜索已落在以下运行边界:
```text
SearchProbeScreen
-> WorkflowRunner(timeout / retry / stop)
-> PinduoduoSearchAutomation(纯 Kotlin)
-> AndroidPinduoduoUiDriver
-> BuyerAccessibilityBridge
-> BuyerAccessibilityService
-> 拼多多可见、启用、唯一语义节点
```
结果页成功不是“点击已发送”,而是同时确认精确查询词、搜索结果头和至少 3 个排序
控件。`ACTION_SET_TEXT` 后必须重新读取当前根节点并精确比对输入;任何稳定未知页以及
登录、验证码、风控、订单或支付边界都终止 workflow。该路径不提供坐标、ADB、
Shizuku shell、OCR 或 VLM 动作降级。
### 3.2 MVP 业务闭环
```text
@@ -306,7 +323,10 @@ IDLE
- 只允许目标拼多多包处于前台时发送动作。
- 关键动作前后都校验包名、页面特征和任务取消标志。
- 节点选择优先资源 ID、可访问性文本和稳定层级;文本版本变化要集中配置。
- 节点选择要求可见、启用且唯一匹配;优先可访问性语义、稳定文本和受限祖先层级,
不能因资源 ID 重复而任取第一个节点。
- 已验证的首页、搜索输入和结果页路径禁止坐标降级;新页面必须先取得版本化真机
证据并在独立任务中定义识别条件。
- 截图发送给模型前裁剪无关区域并按配置脱敏。
- 每个动作记录抽象步骤,不默认记录完整输入文本。
- 发现验证码、风险控制、支付、生物识别或系统权限页面立即停止。
+4 -1
View File
@@ -30,7 +30,10 @@
## 4. Android 自动化规则
- 动作前确认目标 App 包名和预期页面,动作后确认状态确实变化。
- 优先使用资源 ID、可访问性语义和稳定文本;坐标只能作为被验证的局部降级。
- 节点必须可见、启用且唯一匹配;资源 ID 重复时不得选择第一个结果。
- 首页、搜索输入和结果页的已验证路径只用可访问性语义和稳定文本,禁止坐标降级。
其他页面如需坐标必须另立任务、固定版本并提供语义方案确实不可用的证据。
- 文本写入动作返回成功不等于完成;必须从新的根节点精确回读后再推进。
- 每个步骤定义 timeout、有限 retry、成功条件和停止条件。
- 禁止无界循环、无限滑动、无限候选遍历和随机点击。
- 默认最多检查 5 个候选;扩大范围必须先改需求。
+13 -11
View File
@@ -5,7 +5,7 @@
## 当前快照
- 日期:2026-07-25
- 阶段:Phase 0 完成,准备执行 T-101 拼多多关键词搜索探针
- 阶段:T-101 已完成;准备 T-102 候选浏览和采集
- Git:当前分支为 `main`;T-001 至 T-004 均已纳入 Git 历史
- 生产代码:`android-buyer/` 已接入 Roubao Android 源码
- Android:固定 `main@c8a6d7f03422eb01744b01f3ee77bf7757741f7e`;MIT 许可证已保留
@@ -14,21 +14,21 @@
Build Tools 34.0.0、Platform Tools/ADB 37.0.0;用户级 SDK 环境变量已设置
- Android Studio:未安装;`winget` 静默安装卡住后已终止,不阻塞命令行构建
- 测试:`lintDebug test assembleDebug` 成功;App 两个变体、task contract 和导入器
共执行 38 次测试,0 failure、0 error、0 skipped
共执行 62 次测试,0 failure、0 error、0 skipped
- Workflow:纯 Kotlin runner 已支持步骤 timeout、最多 3 次 retry、安全阻塞、
用户停止和单 runner 并发拒绝;尚未连接真实拼多多动作
用户停止和单 runner 并发拒绝;T-101 已接入真实拼多多固定词搜索四步
- TaskSource:严格 CLI 已生成并验证真实私有 ProbeTask;默认 APK 不含私有 fixture
- 测试设备:OnePlus PKG110,Android 16/API 36;肉包 `1.4.2 (7)`;拼多多
`8.17.0 (81700)`
- 设备就绪:肉包采购无障碍已启用并连接;可观察前台包名;拼多多首页未发现登录、
验证码或风控文案,但该结果不等于账号已确认登录
- 设备就绪:肉包采购无障碍已启用并连接;拼多多首页、搜索输入和固定词结果页已通过
8.17.0 真机验证,结果页精确词、搜索头和 4 个排序控件均确认
- 版本控制内测试数据:仅有脱敏、运行时生成的单元测试 fixture;没有真实订单内容
- 本地私有样本:仓库根目录存在一组未跟踪、已本地排除的同名蝦皮文本/JPEG;
已用 CLI 真实导入并逐字段/图片哈希验证,生成物位于被忽略的 `.local/`
- 标准启动路径:`$env:RUN_START_COMMAND="1"; .\init.ps1`
- 标准验证路径:`.\init.ps1`
- 当前 blocker:拼多多账号是否满足后续搜索流程仍需在 T-101 用页面状态确认;
当前只支持单 SKU/JPEG;VLM 供应商和测试凭证未确认
- 当前 blocker:候选列表/详情页语义与有界返回路径尚待 T-102 验证;当前只支持单
SKU/JPEG;VLM 供应商、模型和测试凭证未确认
## 当前目录
@@ -40,6 +40,7 @@
| `docs/tasks/T-002.md` | DONE | 设备版本、无障碍、前台和登录阻塞就绪检查 |
| `docs/tasks/T-003.md` | DONE | 可注入 Fake automation 的受限 workflow runner |
| `docs/tasks/T-004.md` | DONE | 私有蝦皮文本/JPEG 严格导入和 Debug TaskSource |
| `docs/tasks/T-101.md` | DONE | 固定脱敏词拼多多搜索和结果页真机验证 |
| `deepseek总结.txt` | 已有 | 历史讨论摘要,不是正式需求权威 |
| `android-buyer/` | 已有 | Roubao `main` 固定 commit 的 Android 基线 |
| `android-buyer/task-contract/` | 已有 | Android/CLI 共享 ProbeTask 与 TaskSource |
@@ -49,9 +50,9 @@
## 任务摘要
- 已完成:T-001 至 T-004,Phase 0 可运行和输入基线。
- 已完成:T-001 至 T-004,以及 T-101 固定词搜索探针。
- 正在进行:无。
- 下一个可领取任务:T-101 固定任务跑通拼多多关键词搜索。
- 下一个可领取任务:T-102 浏览并采集最多 5 个候选。
## 当前可运行内容
@@ -62,8 +63,9 @@ $env:RUN_START_COMMAND = "1"
.\init.ps1
```
2026-07-25 已在 PKG110、Android 16/API 36 上完成 Debug APK 更新安装和启动;
首屏为设备就绪检查,肉包采购无障碍服务已绑定,进程存活且 logcat 无崩溃。
2026-07-25 已在 PKG110、Android 16/API 36、拼多多 8.17.0 上完成 Debug APK
固定词搜索。默认首屏为搜索探针,用户点击后四步全部完成并确认结果页;设备页保留
就绪检查入口,肉包采购无障碍服务已绑定,logcat 无崩溃或 ANR。
## 维护规则
+119
View File
@@ -0,0 +1,119 @@
---
id: T-101
title: 固定任务跑通拼多多关键词搜索
phase: 1
deps:
- T-002
- T-003
status: DONE
created: 2026-07-25
context_ref: 1c1c1581493af2d04433012064f44f58c1f1d56b
work_branch: main
write_paths:
- android-buyer/app/build.gradle.kts
- android-buyer/app/src/main/java/com/roubao/autopilot/MainActivity.kt
- android-buyer/app/src/main/java/com/roubao/autopilot/accessibility/**
- android-buyer/app/src/main/java/com/roubao/autopilot/pinduoduo/**
- android-buyer/app/src/main/java/com/roubao/autopilot/ui/screens/SearchProbeScreen.kt
- android-buyer/app/src/main/java/com/roubao/autopilot/workflow/**
- android-buyer/app/src/test/java/com/roubao/autopilot/pinduoduo/**
- android-buyer/app/src/test/java/com/roubao/autopilot/workflow/WorkflowRunnerTest.kt
- docs/00-ai-start-here.md
- docs/02-requirements.md
- docs/03-tech-stack.md
- docs/04-architecture.md
- docs/05-coding-rules.md
- docs/current-state.md
- docs/tasks/T-101.md
- progress.md
---
## 问题 / 背景
Phase 0 已证明设备、无障碍、workflow 和任务输入可用,但尚未让肉包执行任何真实
拼多多动作。最高风险假设是:在拼多多 8.17.0 上,能否只依赖可访问性语义稳定打开
搜索、输入固定关键词并确认进入结果页,同时对异常页面安全停止。
## 关联需求与交互
- 功能:F-004 的关键词搜索部分、F-007 安全失败。
- 用户故事:US-004、US-006。
- 交互:Android“探针”页,用户显式点击开始和停止。
- 架构:`WorkflowRunner` + `PinduoduoSearchAutomation` + 无障碍 driver。
## 方案
1. 使用固定脱敏关键词,不读取真实订单标题,也不调用 VLM。
2. 把页面文本分类和搜索 workflow adapter 保持为纯 Kotlin 可测边界。
3. 无障碍 driver 只对 `com.xunmeng.pinduoduo` 操作,使用 resource ID、editable、
文本和 content description,不使用屏幕坐标。
4. 步骤为打开 App、进入搜索、输入并提交、验证结果页;每步有 timeout 和最多一次
retry。
5. 登录、验证码、风控、支付边界立即 `BLOCKED`;未知页面连续观察后安全停止。
6. Android“探针”页展示当前步骤、终态和停止按钮;不执行商品点击或下单。
## 验收要点
- [x] 用户显式点击后打开拼多多并提交固定关键词。
- [x] 成功条件是识别到搜索结果页,不以“点击已发出”冒充成功。
- [x] 全流程不用坐标,不进入商品详情、不提交订单、不支付。
- [x] 登录、验证码、风控、未知页和支付边界产生可区分的 `BLOCKED`。
- [x] 每步 timeout、retry 和用户停止由 T-003 runner 执行。
- [x] 页面分类和 adapter 使用 Fake driver 有自动化测试。
- [x] 拼多多 8.17.0 真机 smoke 通过并保存不含私有内容的证据。
- [x] `lintDebug test assembleDebug` 通过。
## 边界
- 不从真实 Shopee 标题生成搜索词;固定词只验证页面自动化。
- 不浏览候选、不点击商品、不滚动结果列表。
- 不使用 Shizuku shell、ADB 坐标、OCR 或 VLM 作为降级。
- 不绕过登录、验证码、风控或平台提示。
## 执行记录
### 2026-07-25:任务开始
- 基于 T-004 提交 `1c1c158` 开始。
- 测试基线为 OnePlus PKG110、Android 16/API 36、拼多多 8.17.0;肉包采购无障碍
已启用并连接。
### 2026-07-25:实现
- 增加纯 Kotlin 页面分类器和 `PinduoduoSearchAutomation`。页面节点必须同时可见、
启用并唯一匹配;结果页必须同时出现精确固定关键词、搜索头和至少 3 个排序控件。
- 增加 Android 无障碍 driver。打开搜索只点击语义节点或其可点击祖先,输入只使用
`ACTION_SET_TEXT`,并从新的根节点重新读取精确文本后才算成功;没有坐标或 shell
降级。
- workflow 固定执行打开 App、输入、提交和验证四步,沿用 T-003 的 timeout、有限
retry、停止和单实例约束。登录、验证码、风控、未知页面及订单/支付边界直接阻塞。
- 新增“拼多多搜索探针”默认工作页,显示固定词、当前步骤、终态和开始/停止操作。
Activity 恢复后延迟复检无障碍连接,避免系统服务晚连接造成按钮状态滞后。
- 修正 Debug fixture 资产与 lint model 的 Gradle 任务依赖,使完整验证不受增量任务
顺序影响。
### 2026-07-25:自动化验证
- `gradlew.bat lintDebug test assembleDebug --no-daemon` 成功。
- App Debug/Release、task contract 和导入器共 12 份报告、62 次测试,0 failure、
0 error、0 skipped。
- 页面分类覆盖首页、输入页、精确结果页、隐藏/禁用伪节点以及登录、验证码、风控、
未知页和订单/支付边界;Fake driver 覆盖成功、瞬态 retry 和安全阻塞。
- 普通 Debug APK 中 `assets/probe-fixtures/` 条目数为 0。
### 2026-07-25:真机 smoke
- 从肉包“开始搜索探针”按钮显式启动;App 使用固定脱敏词执行,未读取或显示私有
蝦皮样本。
- 拼多多 8.17.0 结果页采集到 174 个可访问节点:精确关键词存在、结果页搜索头存在、
4 个排序控件存在、搜索输入框为 0、订单/支付边界为 0。
- `ACTION_SET_TEXT` 后的新根节点精确回读通过,肉包最终显示 `SUCCEEDED` 且四步均
完成;logcat 未发现肉包崩溃或 ANR。
- smoke XML/PNG 只保存在被忽略的 `.local/t101-smoke/`,未纳入 Git。重装后 ColorOS
出现一次系统无障碍“保持开启”确认,确认后服务正常绑定;产品代码没有绕过该权限。
## 后续
- T-102 从当前结果页浏览并采集最多 5 个候选;仍不得无界滚动、点击下单或支付。
- 从不属于已识别首页/输入页/当前固定词结果页的状态启动时,当前实现按
`UNKNOWN_PAGE` 安全阻塞,不猜测返回路径。