docs(tasks): keep procurement execution on device
This commit is contained in:
+43
-38
@@ -11,12 +11,12 @@
|
||||
管理 Web(服务端渲染)
|
||||
|
|
||||
v
|
||||
统一 Backend API ---------------------+
|
||||
| |
|
||||
+--> SQLite / 文件存储 +--> VLM Provider
|
||||
统一 Backend API
|
||||
|
|
||||
+--> SQLite / 文件存储
|
||||
^
|
||||
|
|
||||
Android 采购 App
|
||||
Android 采购 App --------------------> VLM Provider
|
||||
|
|
||||
+--> AccessibilityService
|
||||
|
|
||||
@@ -25,9 +25,10 @@ Android 采购 App
|
||||
```
|
||||
|
||||
- 管理 Web 与 API 同属 `backend-api/`,但页面层不能直接访问数据库。
|
||||
- Android App 位于 `android-buyer/`,通过 API 领取任务、调用 AI 能力和回传证据。
|
||||
- Android App 位于 `android-buyer/`,通过 API 领取任务和回传证据,在本地调用 AI。
|
||||
- 拼多多是第三方受控边界,只能由 Android 设备在已登录会话中操作。
|
||||
- VLM 密钥的正式路径保留在后端;技术探针如需端上临时调用,只能使用本地忽略配置。
|
||||
- VLM 配置和 Key 位于手机,Key 使用 Android Keystore 包装的加密存储;管理后端不
|
||||
保存、下发或代理模型调用。
|
||||
|
||||
## 二、模块职责
|
||||
|
||||
@@ -41,7 +42,7 @@ internal/transport/http/ # Gin 路由、中间件、页面和请求/响应 DT
|
||||
internal/usecase/ # 创建、领取、状态迁移和结果归档
|
||||
internal/domain/ # 实体、状态机、权限和确定性约束
|
||||
internal/repository/sqlite/ # database/sql 仓储实现
|
||||
internal/platform/ # 配置、日志、文件存储和 VLM 适配器
|
||||
internal/platform/ # 配置、日志和文件存储
|
||||
```
|
||||
|
||||
职责:
|
||||
@@ -50,7 +51,6 @@ internal/platform/ # 配置、日志、文件存储和 VLM 适配器
|
||||
- 创建任务并保存原始输入,不让模型结果覆盖原始事实。
|
||||
- 原子领取下一条任务,签发有期限的 claim lease。
|
||||
- 校验任务状态迁移、幂等键和设备归属。
|
||||
- 代理 VLM 调用并把供应商响应转换为领域结构。
|
||||
- 保存候选、事件、截图元数据和结果。
|
||||
- 为管理 Web 提供任务列表、详情和取消能力。
|
||||
|
||||
@@ -88,7 +88,7 @@ taskclient/ # 后端 API、认证、幂等和重试
|
||||
tasksource/ # 统一任务源;本地探针与后端 API 实现
|
||||
workflow/ # ProcurementWorkflow 状态机
|
||||
automation/ # Accessibility 节点、截图、点击、输入、滑动
|
||||
ai/ # 结构化 AI 请求/响应,不含供应商业务类型
|
||||
ai/ # 结构化 AI、OpenAI 兼容适配器和本地安全配置
|
||||
evidence/ # 截图、步骤日志、脱敏和上传
|
||||
```
|
||||
|
||||
@@ -97,8 +97,10 @@ evidence/ # 截图、步骤日志、脱敏和上传
|
||||
- 检查无障碍、拼多多安装/登录可用性、网络和当前任务状态。
|
||||
- 由用户点击后领取任务;一台设备一次只运行一条。
|
||||
- 执行有界步骤:解析 -> 搜索 -> 浏览不超过 5 个候选 -> 判断 -> 停止确认。
|
||||
- 直接调用用户在本机明确配置的 VLM;没有可用模型时允许显式人工优先模式。
|
||||
- 显示当前步骤、停止原因和人工接管入口。
|
||||
- 用前台服务承载执行中任务,进程重启后从服务端状态恢复或安全失败。
|
||||
- 用前台服务承载执行中任务,以服务端授权截止时间支持有限离线;进程重启后从加密
|
||||
本地状态与服务端核对恢复或安全失败。
|
||||
- 回传步骤事件、候选、截图和最终结果。
|
||||
|
||||
不得:
|
||||
@@ -115,22 +117,22 @@ evidence/ # 截图、步骤日志、脱敏和上传
|
||||
1. **需求提取**:参考图 + 标题 + SKU -> 搜索词、类目、属性、置信度、警告。
|
||||
2. **候选评估**:候选截图/文本 + 原始约束 -> 匹配项、缺失项、拒绝原因、建议分。
|
||||
|
||||
正式数据流固定为 `Android App -> 肉包后端 -> VLM Provider`。生产采购 App 不选择
|
||||
provider、不保存供应商 API Key,也不直连模型地址;它只调用 task-scoped AI API。
|
||||
ADMIN 在管理 Web 维护一个供新 execution 使用的默认 OpenAI 兼容 provider 版本。
|
||||
第一版只支持 `/v1/chat/completions` 多模态协议。
|
||||
正式数据流固定为 `Android App -> VLM Provider`。管理后端只下发原始任务并接收
|
||||
结构化结果,不保存/下发 provider 配置或 Key,也不实现 `/tasks/{id}/ai/*` 代理。
|
||||
后台任务不能携带或覆盖本机 provider、Base URL、model、prompt 或 API Key。
|
||||
|
||||
provider 配置采用追加版本:保存名称、HTTPS Base URL、model、timeout、retry 上限、
|
||||
启用状态和非秘密审计字段。API Key 使用环境提供的 256 bit master key,通过 AEAD
|
||||
随机 nonce 加密;AAD 绑定 provider/version。读取接口只返回 `has_secret`,永不返回
|
||||
明文或密文。execution 在第一次 AI 调用时绑定 config/provider/model/prompt version,
|
||||
后续调用不随默认配置变化。master key 缺失或解密失败时真实调用安全失败,但管理任务、
|
||||
领取和非 AI 功能继续可用。
|
||||
App 支持两个显式模式:
|
||||
|
||||
后端 provider transport 禁止重定向,并在解析和连接时阻断 loopback、私网、链路
|
||||
本地、组播、云 metadata 和 DNS rebinding;生产只允许 HTTPS。无 Key 的 loopback
|
||||
HTTP 只属于显式 Debug mock,不能从生产管理 Web 创建。连接测试只使用内置脱敏文字
|
||||
和测试图片,不读取订单或任务资产。
|
||||
- `MANUAL_FIRST`:从原始标题/SKU 产生有界搜索词,由人员判断候选,不要求 VLM。
|
||||
- `AI_ASSISTED`:使用 App 本地配置的 OpenAI 兼容 provider 做需求提取和候选评估。
|
||||
|
||||
模式在 execution 开始时固定并写入结果;AI 失败后只能由人员明确切换,不能静默降级。
|
||||
App 同时固定 provider ID、model、prompt/schema version 和证据 SHA-256,作为非秘密
|
||||
provenance 回传。Key、Authorization、完整 endpoint 和供应商原始响应正文不回传。
|
||||
|
||||
provider Key 从旧设置迁移到 Android Keystore 包装的加密存储;迁移或解密失败时
|
||||
拒绝真实调用。每台设备使用独立、可撤销、有限额度的 Key。Keystore 只降低静态泄露
|
||||
风险,不能宣称可抵抗已 Root 或完全受控设备。
|
||||
|
||||
模型输出是不可信建议,必须通过 schema 和确定性校验:
|
||||
|
||||
@@ -154,19 +156,18 @@ T-103 的模型响应只允许
|
||||
输出并转人工。最终领域结果再由确定性代码补回原 SKU、数量、空预算、人工复核原因和
|
||||
`provider/model/prompt_version/reference_image_sha256`。
|
||||
|
||||
技术探针每次点击最多发出一次 VLM 请求,不沿用通用 Agent 的重试循环。T-207 后端
|
||||
默认不重试,管理员最多允许一次仅限确定未收到响应的临时网络失败;schema、4xx 和
|
||||
安全错误绝不重试。该结构化 HTTP 客户端关闭连接自动重试和 HTTP/HTTPS 重定向,
|
||||
整体调用超时为 75 秒;协程取消
|
||||
技术探针和后台 execution 的每个逻辑步骤最多发出一次 VLM 请求,不沿用通用 Agent
|
||||
的重试循环。该结构化 HTTP 客户端关闭连接自动重试和 HTTP/HTTPS 重定向,整体调用
|
||||
超时为 75 秒;协程取消
|
||||
会取消底层 HTTP call,成功响应正文上限为 64 KiB,非成功响应不读取正文。
|
||||
|
||||
远程 provider 只允许 HTTPS;HTTP 仅允许 Debug 下无 API Key 的 `localhost`、
|
||||
Release 远程 provider 只允许 HTTPS;HTTP 仅允许 Debug 下无 API Key 的 `localhost`、
|
||||
`127.0.0.1` 或 `::1` 本机 mock。端点不得包含 userinfo、query 或 fragment。标题
|
||||
和 SKU 在进入
|
||||
prompt 前分别限制为 2048 和 512 个 UTF-8 字节。JPEG 在调用前复核媒体类型、20 MiB
|
||||
上限、魔数和 SHA-256,按声明长度一次分配并精确读取,Android 解码后最长边限制为
|
||||
2048 px。请求和响应正文、Base64、API Key 不写普通日志;加密密钥存储不可用且存在
|
||||
密钥时拒绝调用。
|
||||
2048 px。请求和响应正文、Base64、API Key 不写普通日志;Keystore-backed 密钥存储
|
||||
不可用且存在 Key 时拒绝调用。
|
||||
|
||||
## 三、核心数据流
|
||||
|
||||
@@ -274,11 +275,12 @@ T-102/T-104 在搜索结果后追加一个有界候选步骤:
|
||||
管理员创建 PENDING 任务
|
||||
-> 采购员在 App 点击“获取任务”
|
||||
-> 后端事务内选取并置为 CLAIMED
|
||||
-> App 确认后置为 RUNNING
|
||||
-> 定期 heartbeat 续租并上报步骤
|
||||
-> 需求提取和拼多多自动化
|
||||
-> App 确认后置为 RUNNING,取得有限离线授权
|
||||
-> best-effort heartbeat 同步步骤和取消
|
||||
-> App 本地需求提取和拼多多自动化
|
||||
-> WAITING_CONFIRMATION
|
||||
-> 采购员接受/拒绝候选
|
||||
-> 加密 outbox 幂等回传结果和证据
|
||||
-> SUCCEEDED 或 FAILED/CANCELED
|
||||
-> 管理端展示结果
|
||||
```
|
||||
@@ -312,16 +314,19 @@ CLAIMED/RUNNING/WAITING_CONFIRMATION
|
||||
规则:
|
||||
|
||||
- `SUCCEEDED` 是验证结果成功,不代表已下单;`order_submitted=false`。
|
||||
- `CLAIMED` 默认租约为 10 分钟;`RUNNING/WAITING_CONFIRMATION` 默认租约为
|
||||
90 秒,App 计划每 30 秒 heartbeat 续租。三个时长均由有上下界的环境变量配置。
|
||||
- `CLAIMED` 默认租约为 10 分钟;T-206 将 `RUNNING/WAITING_CONFIRMATION` 默认
|
||||
授权从当前 90 秒扩展为 30 分钟,允许范围 5 至 120 分钟。App 每 30 秒
|
||||
best-effort heartbeat,成功后按服务端时间滑动续期。
|
||||
- 只有当前设备和有效 claim token 能启动、续租、上报或结束任务。
|
||||
- 终态不可回退;重试创建新的 execution attempt,不篡改历史证据。
|
||||
- App 在 claim 前生成并安全保存 256 bit Raw URL token;后端只存 SHA-256,
|
||||
token 与 `Idempotency-Key` 相互独立。
|
||||
- 过期 `CLAIMED` 可以原子回收;过期 `RUNNING/WAITING_CONFIRMATION` 保持原状态,
|
||||
不自动回队列。
|
||||
不自动回队列。App 到达服务端授权截止时间必须安全停止,但原设备可以在重连后
|
||||
补报已产生的终态结果并留下过期补报审计标志。
|
||||
- 管理取消 `PENDING/CLAIMED` 立即终态;执行中只设置停止请求,App 在下一个安全
|
||||
检查点停止并调用 `cancel-ack` 后才进入 `CANCELED`。
|
||||
检查点停止并调用 `cancel-ack` 后才进入 `CANCELED`。离线期间不能保证即时取消,
|
||||
App 恢复连接后必须先同步取消状态再继续页面动作。
|
||||
|
||||
### 4.2 Android 工作流状态
|
||||
|
||||
|
||||
Reference in New Issue
Block a user