Files
Genarrative/docs/technical/AGENT_DRAFT_PROFILE_ID_STABILITY_FIX_2026-04-23.md
kdletters cbc27bad4a
Some checks failed
CI / verify (push) Has been cancelled
init with react+axum+spacetimedb
2026-04-26 18:06:23 +08:00

3.9 KiB
Raw Permalink Blame History

Agent 草稿编译后重复生成草稿修复 2026-04-23

更新时间:2026-04-23

1. 问题现象

当前创作链里,用户打开一个已有 Agent 草稿,继续编辑并触发结果页编译或自动保存后,作品库里会新增一份 draft而不是更新原来的那一份。

这会带来两个直接问题:

  1. 同一个会话在作品库里出现多份草稿
  2. 原草稿状态没有被正确推进,导致发布、恢复、继续创作都可能命中旧条目

2. 根因拆解

本次问题不是单点,而是两段身份链没有收口到同一套规则:

2.1 sync_result_profile 会直接覆盖 session 里的 draft_profile_json.id

当前 sync_result_profile 会把结果页传回来的 profile 直接写回 draft_profile_json

如果结果页上的 profile.id 已经不是原草稿 id那么

  1. session 主链中的 draft_profile_json.id 会被改成新 id
  2. resultPreview.preview.id 也会跟着变成新 id
  3. 前端 autosave 会拿着这个新 id 去调作品库 PUT /custom-world-library/:profileId

2.2 作品库 upsert 只按 profile_id 命中,不按 source_agent_session_id 兜底

当前作品库落库路径:

结果页 autosave -> PUT /custom-world-library/:profileId -> upsert_custom_world_profile_record

其中普通 autosave 路径此前存在两个问题:

  1. 前端没有透传 sourceAgentSessionId
  2. 后端普通 upsert 只按 (owner_user_id, profile_id) 查旧记录

所以一旦 profile.id 漂移,后端就会把它当作一条新的 draft 插入。

3. 修复目标

本轮修复要求同时满足下面两条:

  1. Agent 草稿结果页继续编辑时,必须优先继承当前 session 已有的稳定 profileId
  2. 即使前端传来的 profile.id 已经漂移,作品库 upsert 也要能按 source_agent_session_id 命中同一份 draft 并更新

4. 本轮落地策略

4.1 session 主链侧:稳定保留草稿 id

sync_result_profile 中,若当前 session 已经存在草稿身份:

  1. 优先读取 draft_profile_json.legacyResultProfile.id
  2. 其次读取 draft_profile_json.id
  3. 若命中稳定 id则把传入 profile 的:
    • 顶层 id
    • legacyResultProfile.id 都强制回写为这个稳定 id

这样可以保证:

  1. draft_profile_json.id 不会被结果页里的漂移 id 覆盖
  2. resultPreview.preview.id 会持续稳定
  3. 前端后续 autosave 会继续更新原草稿

4.2 作品库保存侧:透传 sourceAgentSessionId

前端 upsertRpgWorldProfile(...) 新增可选参数:

sourceAgentSessionId?: string | null

结果页属于 Agent 草稿视图时autosave 会把 activeAgentSessionId 一并传给作品库接口。

4.3 后端 upsert 侧:按 session 命中旧 draft

普通作品库 PUT /custom-world-library/:profileId 接口新增读取 sourceAgentSessionId

Spacetime upsert_custom_world_profile_record(...) 在按 profile_id 未命中时,新增二级兜底:

  1. owner_user_id 相同
  2. publication_status == draft
  3. deleted_at == None
  4. source_agent_session_id == input.source_agent_session_id

若命中这条旧 draft

  1. 删除旧 row
  2. 使用旧 row 的 profile_id
  3. 更新 payload / metadata / updated_at

这样即使前端 path 参数已经是新 id也仍然会命中原草稿并更新而不是再插入第二份草稿。

5. 验收标准

修复后应满足:

  1. 打开已有 Agent draft 后继续编译,不会新增第二份 draft
  2. 原 draft 的 profileId 保持不变
  3. resultPreview.preview.id 与作品库 profileId 一致
  4. 自动保存、继续创作、进入世界、发布前检查都围绕同一份草稿身份工作

6. 结论

这次问题的本质不是“自动保存重复调用”,而是:

Agent 草稿在 session 主链和作品库 upsert 两端都缺少稳定身份约束。

本轮通过“session 保 id + 作品库按 session 兜底命中”双保险,把同一份草稿重新收口为单一身份。