9.2 KiB
9.2 KiB
Eryao 解卦历史与个人档案后端单一数据源改造计划
日期:2026-04-05
状态:评审中(未开始编码)
1. 背景与目标
当前移动端存在两类不符合目标架构的问题:
- 个人档案(昵称、简介、头像)仍有前端本地状态路径,非后端权威数据源。
- 首页历史解卦无法稳定由后端快照直接重建结果页,前端被迫做本地兜底。
本计划目标:
- 实现“后端为唯一数据源,前端仅缓存”。
- 将
DIVINATION_DERIVED的完整结构进入消息metadata.agent_output并持久化。 - 历史接口返回可被前端直接解析的结构化 assistant 输出(不再依赖
ui_schema)。 - 个人档案全链路后端化,头像使用
avatarsbucket。
非目标:
- 本计划不直接提交代码实现。
- 本计划不包含 UI 视觉细节改稿。
2. 现状核对(基于仓库代码)
2.1 历史接口与消息转换
- 历史接口:
GET /api/v1/agent/history,定义于backend/src/v1/agent/router.py。 - 当前转换逻辑在
backend/src/v1/agent/utils.py:user消息主要输出content与attachments。assistant消息默认走ui_hints -> ui_schema编译路径。
- 历史响应结构
HistoryMessage当前包含ui_schema,不直接暴露结构化agent_output。
2.2 DIVINATION_DERIVED 与落库断点
- 运行时会发出
DIVINATION_DERIVED(见backend/src/core/agentscope/runtime/runner.py)。 - 消息落库由
backend/src/core/agentscope/events/store.py负责。 - 当前
TEXT_MESSAGE_END持久化字段包含sign_level/summary/.../ui_hints,未包含divination结构。 - 结果:历史快照难以完整重建结果页结构。
2.3 Profile 与头像
- 后端配置已有
storage.avatar.bucket,默认avatars(backend/src/core/config/settings.py)。 - 当前
v1仅挂载auth/agent/points路由(backend/src/v1/router.py),尚无 profile 专用路由。
3. 核心设计决策
决策 A:把 divination_derived 放入 metadata.agent_output
- 在
AgentOutput增加字段divination_derived(强类型,禁止裸dict)。 - 事件落库时把
DIVINATION_DERIVED内容并入 assistant 的metadata.agent_output.divination_derived。 - 与
sign_level/summary/advice/...同时持久化,形成一条可回放的 assistant 结构化输出。
理由:
- 最小改动复用现有消息表,不新增历史结果表即可满足回放需求。
- 前端可直接从历史响应解析结果页,避免本地拼装。
决策 B:历史接口返回 assistant.agent_output,移除 ui_schema
HistoryMessage改为:user:content + attachmentsassistant:content + agent_output
ui_schema从接口协议中移除(迁移自通用模块的历史遗留,不在本项目范围)。
理由:
- 减少中间编译层,契约更稳定、语义更清晰。
- 前端直接消费业务数据,不依赖通用 UI 编译器。
决策 C:Profile 全后端化 + 头像对象存储
- 新增 users/profile API,前端只保留缓存层。
- 头像上传走预签名 URL,bucket 固定
avatars,路径按用户隔离。
4. 协议与接口计划(先文档,后实现)
4.1 新增/修改协议文档
按“协议先行”更新以下文档:
docs/protocols/divination/divination-run-protocol.md- 增补:历史回放时 assistant
agent_output.divination_derived的字段契约。 - 标记:
ui_schema已废弃并移除。
- 增补:历史回放时 assistant
- 新增:
docs/protocols/profile/profile-protocol.md- 定义 profile 读写与头像上传签名协议。
- 如涉及错误码新增,更新:
docs/protocols/common/http-error-codes.md
4.2 后端 API 契约(目标)
A. 历史快照(改造)
GET /api/v1/agent/history- 响应中 assistant 消息新增(或替换为)
agent_output:sign_levelsummaryconclusionfocus_pointsadvicekeywordsanswerdivination_derived(完整卦象结构)
B. Profile(新增)
GET /api/v1/users/me/profilePATCH /api/v1/users/me/profilePOST /api/v1/users/me/avatar/upload-url- (可选)
GET /api/v1/users/me/avatar/signed-url
C. 头像上传约束
- bucket 固定:
config.storage.avatar.bucket - 路径前缀建议:
avatars/{user_id}/... - 文件类型:
image/png|image/jpeg|image/webp - 体积上限:
config.storage.avatar.max_size_mb
5. 数据模型改造计划
5.1 Runtime 模型
- 文件:
backend/src/schemas/agent/runtime_models.py - 变更:
AgentOutput增加divination_derived字段(类型复用schemas/domain/divination.py)。 - 规则:保持
extra="forbid",禁止无类型漂移。
5.2 事件到落库链路
- 文件:
backend/src/core/agentscope/runtime/stage_emitter.pyTEXT_MESSAGE_ENDpayload 带上divination_derived。
- 文件:
backend/src/core/agentscope/events/store.pyworker_output_fields纳入divination_derived并写入metadata.agent_output。
5.3 历史响应转换
- 文件:
backend/src/v1/agent/utils.py- 删除
ui_hints -> ui_schema编译路径。 - assistant 消息改为抽取并返回受控
agent_output。
- 删除
- 文件:
backend/src/v1/agent/schemas.pyHistoryMessage改字段定义(去ui_schema,加agent_output)。
6. 前端消费与缓存策略
6.1 历史与结果页
- 历史列表数据源改为后端
agent/history。 - 点开历史项时:
- 直接解析
assistant.agent_output.divination_derived+ 解释文本字段。 - 本地仅做缓存,不做真源 fallback。
- 直接解析
6.2 Profile
- 设置页资料读取改为
GET /users/me/profile。 - 编辑资料写入
PATCH /users/me/profile。 - 头像更新走 upload-url + 上传 + profile 更新引用路径。
6.3 点数
- 保持后端余额接口作为权威数据源(现有已接)。
- 前端只做短期缓存,解卦完成后强制 refresh。
7. 代码清理边界(你关心的“删除通用遗留”)
原则:先去引用,再删定义,最后删文件,避免误删。
分三步:
- 第一阶段(本次改造内)
- 删除
agent/history对ui_schema的输出与依赖。 - 删除前端对
ui_schema的消费路径(若存在)。
- 删除
- 第二阶段(安全清理)
- 搜索
schemas/domain与schemas/agent/ui_hints的实际引用。 - 对“零引用 + 非协议字段”进行清理。
- 搜索
- 第三阶段(文档与测试补齐)
- 更新协议文档、错误码、回归测试。
备注:
- 不建议在同一 PR 里“功能改造 + 大规模 schema 删除”,建议拆成两个 PR,降低回归风险。
8. 测试计划(必须项)
8.1 后端单元/集成
TEXT_MESSAGE_END持久化:metadata.agent_output.divination_derived落库断言。GET /api/v1/agent/history:assistant 返回agent_output,且不再返回ui_schema。- 历史分页与 owner 校验不回退。
- profile API:读写、权限、字段约束、头像路径安全性。
- 头像签名 URL:bucket/path/mime/size 约束。
8.2 前端
- 历史列表从后端数据渲染。
- 点击历史项成功进入结果页,字段一致性校验。
- profile 页面读写闭环(昵称/简介/头像)。
- 点数刷新与缓存失效策略验证。
9. 风险与回滚
主要风险:
- 历史消息中旧数据可能没有
divination_derived,前端需兼容空值。 ui_schema下线后,若有隐藏调用方会断。
回滚策略:
- 协议层采用短期双读兼容窗口(仅过渡期):
- 新字段优先;旧字段仅用于读,不再写。
- 若线上异常,先回滚 history 响应变更,再保持落库新增字段不删。
10. 实施顺序(最小风险)
- 协议文档更新并评审通过。
- 后端:
AgentOutput+ 事件落库 + history 响应新增agent_output(先加后切)。 - 前端:改消费到
agent_output,移除本地真源。 - 后端:移除
ui_schema输出。 - profile API + 前端接入头像上传。
- 清理无用 schema(独立 PR)。
11. 验收标准(DoD)
全部满足才算完成:
- 解卦后写入的 assistant 消息在 DB 中可见
metadata.agent_output.divination_derived。 - 首页历史完全来自后端,清空本地缓存后仍可正确展示。
- 历史详情可完整还原结果页,不依赖
ui_schema。 - profile 读写走后端,头像实际落
avatarsbucket。 - 前端不再把 profile/history 作为本地权威数据源。
- 协议文档与实现一致,相关测试通过。
12. GSTACK REVIEW REPORT
| Review | Trigger | Why | Runs | Status | Findings |
|---|---|---|---|---|---|
| Eng Review | /plan-eng-review |
锁定架构、契约、测试闭环 | 1 | Done | 确认后端单一数据源方向;建议分阶段移除 ui_schema 并将 schema 清理拆分独立 PR |
| CEO Review | /plan-ceo-review |
范围与优先级 | 0 | — | — |
| Design Review | /plan-design-review |
UI/UX 风险 | 0 | — | — |
| DX Review | /plan-devex-review |
开发体验风险 | 0 | — | — |
VERDICT:可以进入实现阶段,但必须先完成协议文档更新并冻结字段契约。