docs/08-agent-api-contract.md
identify
shareUrl
goodsId
url
pddProductId
ea970c7
goods_id 全程只由服务端产生,Agent 不参与认定。链路为:剪贴板文本 → PddShareLinkExtractor.extract(android/app/src/main/java/cn/ilapage/goauto/agent/automation/CurrentPageCollection.kt:113)→ identifyCurrentPageCollectionTask(shareUrl) → 服务端 ResolvePDDShareURL(server/app/goauto/task/current_page.go:262)→ goods_id。#107 只修了前台切换,这条解析链未改动。
PddShareLinkExtractor.extract
android/app/src/main/java/cn/ilapage/goauto/agent/automation/CurrentPageCollection.kt:113
identifyCurrentPageCollectionTask(shareUrl)
ResolvePDDShareURL
server/app/goauto/task/current_page.go:262
goods_id
服务端短链分支存在三个叠加问题:
response.Request.URL
current_page.go:294
p.pinduoduo.com/xxxx
PDD_SHARE_LINK_INVALID
io.Copy(io.Discard, ...)
current_page.go:289
GoAuto-Agent-Link-Resolver/1.0
current_page.go:285
覆盖缺口:server/app/goauto/task/current_page_test.go:66 用注入的假 resolver,:132 只覆盖 mobile.yangkeduo.com/goods.html?goods_id= 长链与非法输入;真实短链的 HTTP 展开在任何提交上都没有被验证过。
server/app/goauto/task/current_page_test.go:66
:132
mobile.yangkeduo.com/goods.html?goods_id=
Agent 端另有两个次级缺陷:
PddShareLinkExtractor
https://[^\s]+
CurrentPageCollection.kt:114
URI
extract
singleOrNull
CurrentPageCollection.kt:123
^[0-9]{5,32}$
https://mobile.yangkeduo.com/goods.html?goods_id=
pdd_product
p.pinduoduo.com
mobile.yangkeduo.com
HttpURLConnection
AgentApiClient
AgentDiagnosticStore
LONG_LINK_DIRECT / SHORT_LINK_EXPANDED / SHORT_LINK_FAILED / LINK_AMBIGUOUS / LINK_NOT_FOUND
IdentifyCurrentPage
httptest
./gradlew :app:testDebugUnitTest
go test ./app/goauto/task/... ./app/goauto/product/...
待实施(由 Codex 执行)。
已核对 #101/#105/#106/#107、当前 Android/Server 解析链与采集业务规则。按工单范围实施:
不修改数据库、identify 接口字段、任务创建顺序、Admin、规则、采购或支付能力。
LINK_RESOLUTION
cd android && .\gradlew.bat :app:testDebugUnitTest :app:assembleDebug
cd server && go test ./app/goauto/task/... ./app/goauto/product/...
cd server && go test ./...
python dev_scripts/harness.py check --strict
git diff --check
已更新线上页面并回读 revision:
2f4a3a546d12
2c2d84b24108
3ba5cf24adcd
7645ee794b5b
python dev_scripts/harness.py sync 与唯一一轮 sync --check 均通过。
python dev_scripts/harness.py sync
sync --check
20775cc1bfd74d3539a4bc54ec723b176b540e3e fix: resolve PDD share links on Agent (#108)
工单保持打开,等待人工验收。
20775cc
host == "p.pinduoduo.com"
https://mobile.yangkeduo.com/goods2.html?ps=...
select()
NOT_FOUND
current_page.go:279
refer_goods_id
用户于 2026-08-28 明确确认本工单验收通过。按项目流程记录验收结论并关闭工单;本次仅更新工单状态,无新增长期文档事实,不重复同步 Wiki。
No dependencies set.
The note is not visible to the blocked user.
所属与来源
docs/08-agent-api-contract.md中identify接口的请求与响应字段(仍为shareUrl入参、goodsId/url/pddProductId出参),属于恢复既有预期行为的缺陷修复,不另做原型。当前事实与根因(提交
ea970c7复核)goods_id 全程只由服务端产生,Agent 不参与认定。链路为:剪贴板文本 →
PddShareLinkExtractor.extract(android/app/src/main/java/cn/ilapage/goauto/agent/automation/CurrentPageCollection.kt:113)→identifyCurrentPageCollectionTask(shareUrl)→ 服务端ResolvePDDShareURL(server/app/goauto/task/current_page.go:262)→goods_id。#107 只修了前台切换,这条解析链未改动。服务端短链分支存在三个叠加问题:
response.Request.URL作为最终地址(current_page.go:294)。PDDp.pinduoduo.com/xxxx短链通常返回 200 HTML,靠页面内 JS/meta 跳转,最终 URL 仍是短链,goods_id为空 →PDD_SHARE_LINK_INVALID「商品链接中没有有效 goods_id」。io.Copy(io.Discard, ...)丢弃(current_page.go:289),即使正文含 goods_id 也从不解析。GoAuto-Agent-Link-Resolver/1.0(current_page.go:285),配合机房 IP,极易命中 PDD 风控页或落地页。覆盖缺口:
server/app/goauto/task/current_page_test.go:66用注入的假 resolver,:132只覆盖mobile.yangkeduo.com/goods.html?goods_id=长链与非法输入;真实短链的 HTTP 展开在任何提交上都没有被验证过。Agent 端另有两个次级缺陷:
PddShareLinkExtractor的正则为https://[^\s]+(CurrentPageCollection.kt:114),只裁剪尾部标点。PDD 复制文案若为「…https://p.pinduoduo.com/xxx,快来拼」这类链接后无空格的形式,中文会被并入 URL,URI解析仍通过(host 合法),于是把坏链接发给服务端。extract用singleOrNull(CurrentPageCollection.kt:123),文案含两个合法链接时直接放弃,而不是优先选商品链接。目标
非目标
identify接口的请求与响应字段,不修改数据库结构。分工原则(本工单的设计前提)
^[0-9]{5,32}$格式校验、归一化为https://mobile.yangkeduo.com/goods.html?goods_id=、查建pdd_product、同商品并发任务互斥,一步都不下放到 Agent。Agent 只上报它看到的链接,服务端决定这条链接算不算数。实施方案
Agent 侧
goods_id参数的商品长链,其次选择白名单短链;仍然为零候选或候选相互冲突(指向不同 goods_id)时明确失败,不做任意挑选;p.pinduoduo.com与mobile.yangkeduo.com。identify调用之前):goods_id的长链时直接上报,不发起任何网络请求;HttpURLConnection(与AgentApiClient一致,不引入新依赖)发起 GET,手动跟随 3xx,最多 4 跳,连接与读取超时各不超过 5 秒;goods_id时上报该长链;跟随结束仍无goods_id时,允许在受限正文(上限 64KB)中用受限正则提取goods_id,只接受数字并交由服务端再校验;AgentApiClient的鉴权头;UA 使用普通移动端 UA 常量。PDD_SHARE_LINK_INVALID,不回退为「把短链原样上报」以外的任何猜测行为;短链原样上报仍然允许(由服务端兜底解析),但必须记入诊断。AgentDiagnosticStore,新增链接解析阶段的结构化原因(LONG_LINK_DIRECT / SHORT_LINK_EXPANDED / SHORT_LINK_FAILED / LINK_AMBIGUOUS / LINK_NOT_FOUND)。诊断不得记录链接原文、goods_id、剪贴板正文与页面正文。Server 侧
IdentifyCurrentPage的校验、归一化、建档与互斥逻辑保持不变,继续以服务端结果为准;Agent 上报的链接一律重新校验,不因来自 Agent 而放宽。ResolvePDDShareURL的短链 HTTP 分支保留为兜底路径(Agent 只能给出短链时仍会用到),同时修正其明显缺陷:允许读取受限正文并从中提取goods_id,UA 改为普通移动端 UA;域名白名单、跳转上限、超时与「正文不落盘」保持不变。httptest覆盖 302 跳转到长链、200 + 正文内含 goods_id、200 无 goods_id、跳转到白名单外域名、跳转次数超限五种响应,断言错误码与归一化结果。安全边界
验收标准
goods_id的长链时,Agent 不发起额外网络请求,直接上报并成功识别。p.pinduoduo.com短链时,Agent 在手机侧展开为含goods_id的长链并成功识别。验证方式
./gradlew :app:testDebugUnitTest(Agent 单元测试,含链接提取与短链展开的纯函数测试)。go test ./app/goauto/task/... ./app/goauto/product/...(服务端)。风险与回退
文档影响
docs/08-agent-api-contract.md的字段不变,若其中有解析责任的文字描述则一并更新。无长期事实变化时在工单说明原因并跳过 Wiki 同步。状态
待实施(由 Codex 执行)。
开始实施(2026-08-27)
已核对 #101/#105/#106/#107、当前 Android/Server 解析链与采集业务规则。按工单范围实施:
不修改数据库、identify 接口字段、任务创建顺序、Admin、规则、采购或支付能力。
实现完成,待验收(2026-08-27)
实现
goods_id的白名单长链;p.pinduoduo.com短链优先在 Agent 手机网络侧展开:HttpURLConnection,不携带 Cookie、项目 Token、账号或个人数据;identify字段和最终裁决保持不变:重新校验链接、5~32 位数字格式、标准 URL、商品查建与同商品并发互斥。LINK_RESOLUTION及五个固定原因;数据结构没有链接、goods_id、剪贴板正文或响应正文字段。自动化验证
cd android && .\gradlew.bat :app:testDebugUnitTest :app:assembleDebug:通过。cd server && go test ./app/goauto/task/... ./app/goauto/product/...:通过。cd server && go test ./...:通过。python dev_scripts/harness.py check --strict、git diff --check:通过。真机
Wiki
已更新线上页面并回读 revision:
2f4a3a546d122c2d84b241083ba5cf24adcd7645ee794b5bpython dev_scripts/harness.py sync与唯一一轮sync --check均通过。提交
20775cc1bfd74d3539a4bc54ec723b176b540e3e fix: resolve PDD share links on Agent (#108)工单保持打开,等待人工验收。
后续关联
20775cc)实测仍无法解析链接。根因不在展开实现,而在触发条件:两端都按host == "p.pinduoduo.com"判断是否需要展开,而 PDD 实际复制到的是https://mobile.yangkeduo.com/goods2.html?ps=...,域名在白名单内但 query 无goods_id,于是在 Agent 端select()返回NOT_FOUND、服务端current_page.go:279直接拒绝,展开逻辑从未被执行。refer_goods_id误匹配)。用户于 2026-08-28 明确确认本工单验收通过。按项目流程记录验收结论并关闭工单;本次仅更新工单状态,无新增长期文档事实,不重复同步 Wiki。