docs(#278): 同步 SYB 商品 PDD 图搜采集契约镜像
线上 Wiki 页面 Android-Agent-API-Contract 已更新并回读, revision 4d1ba4423229;本次提交为 harness sync 生成的本地镜像。 新增章节记录:批量创建接口与去重、批次上限 50(作用于去重后条数、 不可 env 覆盖及其原因)、设备能力 pdd.image-search.v1、任务载荷只下发 imageUrl/mediaType/sizeBytes/sha256、复用 identify 回填身份、自动关联的 CAS 谓词与跨币种拒绝、image_search_linked 标记只读出现在采购视图且不参与 门禁、采集 > 图搜的 ORDER BY 及其必须落在服务端的原因、管理端与 Agent 两侧错误码表、Agent 执行边界(禁 OCR/VLM、订单确认页只返回、相册最新项 须跨图片与视频比较),以及 2026-09-15 真机核对的 PDD 界面判据与已知偏差。 Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01NTDbDcwbDw1TSAcE6wfh2F
This commit is contained in:
@@ -1,3 +1,11 @@
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Android-Agent-API-Contract
|
||||
wiki_url: https://git.ilapage.cn/OPC/goauto/wiki/Android-Agent-API-Contract.-
|
||||
wiki_revision: 4d1ba4423229a611fa7ddabc3a4553c14433036d
|
||||
synchronized_at: 2026-09-15T03:10:13Z
|
||||
<!-- gitea-wiki-mirror:end -->
|
||||
|
||||
<!-- gitea-wiki-mirror:start -->
|
||||
generated: true (请先修改 Gitea Wiki,禁止直接编辑本文件)
|
||||
wiki_page: Android-Agent-API-Contract
|
||||
@@ -819,6 +827,158 @@ Content-Type: application/json
|
||||
- Admin 的 BatchRetry 接口和行为不变。相同 `requestId` 重放返回同一新任务;不同 requestId 再点由最新任务门禁拒绝。
|
||||
|
||||
|
||||
## SYB 商品 PDD 图搜采集(#275~#280)
|
||||
|
||||
图搜任务**就是采集任务**:同一张 `collection_task` 表、`source = 'image_search'`、同一个
|
||||
`/api/agent/v1/tasks/*` 端点。与 `agent_current_page` 的唯一区别是**谁打开那个商品页**——
|
||||
后者由采购员手动打开,图搜由 Agent 用 PDD 的拍照搜索找到并打开。打开之后的链路
|
||||
(分享链接 → goods_id → 身份回填 → 采集 → 提交结果)完全复用,没有新的采集接口。
|
||||
|
||||
### 管理端:批量创建
|
||||
|
||||
```http
|
||||
POST /api/admin/v1/collection-tasks/image-search/batch
|
||||
Content-Type: application/json
|
||||
|
||||
{"requestId":"<uuid>","sybProductIds":[1,2,3],"ruleId":3,"deviceId":null,"overwriteLinked":false}
|
||||
```
|
||||
|
||||
- **按 `shopee_product` 去重**:多条共用同一张参考图的 SYB 明细合并为一个任务。请求最多
|
||||
100 个 `sybProductIds`。
|
||||
- **批次上限作用于去重后的任务数**,不是入参明细数,上限 50(约 17~33 分钟设备占用,
|
||||
按单次图搜 20~40 秒估算)。超限整批拒绝,不部分创建。该值是服务端常量,**不可由环境
|
||||
变量覆盖**:确认对话框必须在提交前禁用按钮,前端持有同一个数字,可覆盖只会让两侧静默
|
||||
不一致。改动时两侧必须同改。
|
||||
- `deviceId` 可空,为空由具备能力的空闲设备领取。`overwriteLinked` 为 false 时已关联 PDD
|
||||
的蝦皮商品返回 `IMAGE_SEARCH_ALREADY_LINKED` 并跳过。
|
||||
- 响应逐条返回 `shopeeProductId` / `sybProductIds` / `taskId` 或 `code` + `message`。
|
||||
|
||||
### 设备能力
|
||||
|
||||
图搜任务要求设备声明 `pdd.image-search.v1`。不具备该能力的设备在领取阶段跳过图搜任务,
|
||||
不会失败。
|
||||
|
||||
### 任务下发
|
||||
|
||||
`GET /api/agent/v1/tasks/next` 与 `claim` 返回的载荷结构对所有来源一致,图搜任务额外携带
|
||||
`imageSearch`:
|
||||
|
||||
```json
|
||||
{"imageUrl":"https://...","mediaType":"image/jpeg","sizeBytes":81234,"sha256":"<64 位小写 hex>"}
|
||||
```
|
||||
|
||||
- **只下发这四个字段。** 关联关系、参考价、价格倍数、去重明细等快照留在服务端的
|
||||
`image_search_snapshot`,不下发给 Agent。
|
||||
- 服务端不下发图片字节;Agent 自行下载 `imageUrl` 并按 `sizeBytes` 与 `sha256` 校验。
|
||||
参考图上限 10MB。
|
||||
- 身份回填前 `pddProductId` 为 `null`,`urlSnapshot` 与 `goodsIdSnapshot` 为空字符串,
|
||||
与 `agent_current_page` 相同。
|
||||
|
||||
### 身份回填
|
||||
|
||||
图搜复用 `POST /api/agent/v1/current-page-collection-tasks/{taskId}/identify`,该接口已同时
|
||||
接受 `agent_current_page` 与 `image_search` 两种来源。
|
||||
|
||||
- `[已核对]` 该接口要求任务已绑定 `device_id`。批量创建允许 `deviceId` 为空,但
|
||||
`Claim` 在事务中写入 `device_id = <领取设备>`,因此 Agent 调用 identify 时设备必定已绑定。
|
||||
- 回填之后的结果提交、失败上报、reset 重采与 `agent_current_page` 完全一致。
|
||||
**`ruleSnapshot` 结构与普通采集任务同构**,图搜不引入第二种规则形态。
|
||||
|
||||
### 结果自动关联与价格兜底
|
||||
|
||||
任务完成后服务端尝试建立 shopee↔PDD 关联,条件全部满足才写入:
|
||||
|
||||
- 任务 `source = 'image_search'`、状态 `completed`、已回填 `pddProductId`;
|
||||
- 目标蝦皮商品 `pdd_product_id IS NULL AND image_search_linked = false`(CAS 谓词:Agent
|
||||
执行期间发生的人工改动胜出,不被覆盖);
|
||||
- 蝦皮商品币种为 CNY。**非 CNY 一律不自动关联**,快照记 `priceGuardSkipped` 与
|
||||
`CROSS_CURRENCY_TWD_PDD_CNY`,留给人工复核;
|
||||
- 候选价与 `syb_product.unit_price_cent` 的偏离在 `maxPriceRatio`(1~100 的整数)之内。
|
||||
|
||||
自动建立的关联置 `shopee_product.image_search_linked = true`,含义是**「机器找的,没人核过」**。
|
||||
采购员在虾皮商品页手动关联(`LinkPDD`)时置回 false。该标记只读地出现在批量采购预览
|
||||
(`BatchPreviewItem.imageSearchLinked`)与采购任务列表,**不参与任何采购门禁、资格判定或
|
||||
下单条件**。
|
||||
|
||||
### 调度:采集 > 图搜
|
||||
|
||||
图搜任务在领取队列中垫底,由 `task.Service.Next` 的 `ORDER BY` 实现:
|
||||
|
||||
```sql
|
||||
-- 共享候选池
|
||||
CASE WHEN device_id IS NULL THEN 1 ELSE 0 END,
|
||||
CASE WHEN source = 'image_search' THEN 1 ELSE 0 END,
|
||||
created_at ASC, id ASC
|
||||
```
|
||||
|
||||
- `[必须]` 该排序只能落在服务端。图搜任务是同一端点下发的普通采集任务,Agent 调用
|
||||
`next` 时服务端已经选好了行,客户端无从推翻。
|
||||
- `[必须]` 来源降级排在 `device_id` **之后**:指派设备是人的显式选择,必须继续优先于来源
|
||||
降级,否则未指派的采集任务会抢在运营明确路由到本机的图搜任务前面。
|
||||
- 采购任务不需要此处排序:它们在独立表、独立端点,Agent 已在检查采集之前处理。
|
||||
|
||||
### 错误码
|
||||
|
||||
管理端(批量创建):
|
||||
|
||||
| 错误码 | 含义 |
|
||||
|---|---|
|
||||
| `IMAGE_SEARCH_BATCH_TOO_LARGE` | 去重后任务数超过单批上限 |
|
||||
| `IMAGE_SEARCH_ALREADY_LINKED` | 蝦皮商品已关联 PDD,逐条跳过 |
|
||||
| `IMAGE_SEARCH_TASK_ACTIVE` | 该蝦皮商品已有未结束的图搜任务 |
|
||||
| `IMAGE_SEARCH_IMAGE_INVALID` | 参考图下载失败、格式不支持或超过限制 |
|
||||
| `IMAGE_SEARCH_INPUT_CHANGED` | 关联、参考图、价格或币种在请求期间变化 |
|
||||
| `IMAGE_SEARCH_REQUEST_CONFLICT` | 同一 `requestId` 的参数已变化 |
|
||||
| `IMAGE_SEARCH_CONFIG_INVALID` | 价格倍数配置不是 1~100 的整数 |
|
||||
| `IMAGE_SEARCH_SNAPSHOT_INVALID` | 任务快照无效 |
|
||||
|
||||
Agent 上报(`POST /api/agent/v1/tasks/{taskId}/fail`):
|
||||
|
||||
| 错误码 | 含义 |
|
||||
|---|---|
|
||||
| `IMAGE_SEARCH_PERMISSION_REQUIRED` | 未授予相册权限 |
|
||||
| `IMAGE_SEARCH_ASSET_INVALID` | 参考图下载、校验或写入相册失败 |
|
||||
| `IMAGE_SEARCH_ASSET_NOT_LATEST` | 相册中存在更新的图片或视频,无法确认会选中我们准备的图 |
|
||||
| `IMAGE_SEARCH_ENTRY_NOT_FOUND` | 找不到唯一可点的拍照搜索入口,或归位失败 |
|
||||
| `IMAGE_SEARCH_NO_CANDIDATES` | 结果页没有可用候选(含全部为广告) |
|
||||
| `IMAGE_SEARCH_AUTOMATION_UNAVAILABLE` | Agent 版本尚未接入图搜自动化 |
|
||||
|
||||
### Agent 执行边界
|
||||
|
||||
- 只使用无障碍树,**禁止 OCR / VLM**。
|
||||
- 相册权限:Android 13+ `READ_MEDIA_IMAGES`,10~12 `READ_EXTERNAL_STORAGE`
|
||||
(`maxSdkVersion=32`)。这是本功能新增的权限,既有设备升级后需重新授权。
|
||||
- 参考图写入设备相册后,Agent 先确认它是相册中**最新的一项(图片与视频一起比较)**,
|
||||
再点击网格第一格;不是最新一项时以 `IMAGE_SEARCH_ASSET_NOT_LATEST` 明确失败,
|
||||
不往后找、不猜测。任务结束(成功或失败)都删除本次写入的图片。
|
||||
- 归位状态机可从商品详情、规格弹层、订单确认页、结果页、重试弹窗回到图搜入口,上限
|
||||
50 次动作。**订单确认页只执行返回**;支付与下单文案仅作只读识别信号,任何情况下都不是
|
||||
点击目标。
|
||||
- 结果页默认打开第一个候选,跳过带「广告」标记的卡片。
|
||||
- 「重新采集」对图搜任务的语义是**重采同一个商品**,不重新搜索;搜错了由采购员在管理端
|
||||
手动改关联(该动作同时清除图搜标记)。
|
||||
|
||||
### PDD 界面判据(2026-09-15 真机核对,设备 1080×2354)
|
||||
|
||||
常量集中在 `PinduoduoImageSearchCriteria`。以下为核对结论,PDD 版本更新后需要重新 dump:
|
||||
|
||||
| 位置 | 判据 | 状态 |
|
||||
|---|---|---|
|
||||
| 首页入口 | `content-desc='拍照搜索'` 且 **clickable** 的唯一节点,实测 `[941,161][1080,228]` | 命中 |
|
||||
| 图搜页 | `我的相册` + `最近搜索` + `历史浏览` + `点击拍照` | 命中 |
|
||||
| 选图网格 | `最近项目` 锚点下方 4 列等宽网格,每格 267px,屏宽 1080,容差 ±24 | 命中 |
|
||||
| 结果页 | `搜图片同款` 且排序控件 ≥ 3(实测 综合/销量/价格/品牌) | 命中 |
|
||||
| 重试弹窗 | `请对准商品或码,保持手机稳定` + `取消` + `再试一次` | **未验证** |
|
||||
|
||||
`[必须]` 入口判定必须同时要求 clickable:个人中心 tab 的**根节点**也带
|
||||
`content-desc='拍照搜索'`,覆盖全屏且不可点,而 `visibleTexts()` 会把 `contentDescription`
|
||||
当文本收集。只按文案匹配会把个人中心判成首页,随后几何兜底会点到该页顶部最靠右的可点
|
||||
节点——实测那是「设置」按钮。
|
||||
|
||||
已知偏差:取景提示真机为「对准商品/条形码/二维码,自动识别」,历史常量
|
||||
`即可进行自动识别` 不命中,靠 `点击拍照` 兜住。相册网格同时包含视频(实测见到带时长的
|
||||
格子),这是上面「最新一项须跨图片与视频比较」的由来。
|
||||
|
||||
## 采集颜色图片上传(#133)
|
||||
|
||||
结构化采集结果成功提交后,Agent 可为任务已采集的颜色逐张调用:
|
||||
|
||||
Reference in New Issue
Block a user