diff --git a/docs/project-memory/plans/【里程碑】Provider推理与正文分离及策划Agent展示-2026-09-14.md b/docs/project-memory/plans/【里程碑】Provider推理与正文分离及策划Agent展示-2026-09-14.md new file mode 100644 index 000000000..d24ade5f6 --- /dev/null +++ b/docs/project-memory/plans/【里程碑】Provider推理与正文分离及策划Agent展示-2026-09-14.md @@ -0,0 +1,180 @@ +# 【里程碑】Provider 推理与正文分离及策划 Agent 展示 + +| 字段 | 值 | +| --- | --- | +| Version | 1.0 | +| Status | proposed | +| Date | 2026-09-14 | +| Parent Spec | `docs/technical/【技术方案】策划Agent生产迁移与工作区浏览-2026-09-10.md` | +| Related Issue | `GenarrativeAI/Genarrative#331` | + +## 一句话交付结果 + +让策划 Agent 能在流式回合中单独收到 Provider reasoning,并在 UI 中以默认折叠的思考过程展示;用户可见正文、工具调用和 GameAgent 现有行为保持不变。 + +## 背景与现状 + +- `platform-llm` 当前只向上层提供正文累计值、正文增量和结束状态。 +- Chat 兼容响应中的 `reasoning`、`reasoning_content` 以及 reasoning content part 会被正文提取器过滤。 +- Responses 响应中的 reasoning 类型 output item 也不会进入独立的上层字段。 +- 策划 Agent 已经预留 `DesignEvent.reasoningText`、`planningV2Reasoning` 和默认折叠 UI,但 Provider 解析链没有产出数据,因此折叠区通常不出现。 +- GameAgent 当前只消费 `delta_text`、`accumulated_text` 和 `finish_reason`,没有消费策划 Agent 的 `reasoningText`。 + +## 目标 + +1. 为 Provider 流式响应增加独立 reasoning 增量和累计通道。 +2. 为非流式终态响应提供独立 reasoning 字段。 +3. 支持 Responses 和 Chat 兼容协议的 reasoning 解析。 +4. 仅由策划 Agent 显式启用 reasoning 捕获和 UI 转发。 +5. 保证 reasoning 不进入用户可见正文、工具调用参数或 GameAgent 消息流。 +6. 在无 reasoning、reasoning 解析异常、重试和工具调用共存场景下保持可恢复行为。 + +## 非目标 + +- 不改变 GameAgent 的正文展示、工具调用、`` 过滤和运行时状态语义。 +- 不把 reasoning 自动拼接到 `delta_text`、`accumulated_text` 或正式 assistant 消息。 +- 不把 reasoning 作为新的业务消息类型写入策划会话历史。 +- 不新增通用 reasoning UI,不改造 Direct/Codex 的过程卡展示。 +- 不修改 Provider 请求模型、推理档位或 token 预算。 +- 不为 reasoning 增加新的 SpacetimeDB 表、公开 API 或持久化 schema。 + +## 受影响模块与边界 + +### Provider 共享层 + +`server-rs/crates/platform-llm` 负责协议解析和流式累计: + +- `LlmStreamDelta` 增加 `reasoning_delta` 与 `accumulated_reasoning`。 +- `LlmRunResponse` 增加终态 reasoning 字段。 +- `LlmRunRequest` 增加默认关闭的 reasoning 捕获开关。 +- 正文提取继续排除隐藏 reasoning part;reasoning 进入旁路字段。 +- reasoning 解析失败只丢弃 reasoning,不影响正文和工具调用。 + +### 策划 Runtime + +`apps/ai-game-creator-shell/src-tauri/src/agent/design_runtime.rs` 仅在策划专用请求中打开 reasoning 捕获: + +- 流式 reasoning 更新映射到已有 `DesignEvent.reasoningText`。 +- 正文继续使用已有 `text` 事件。 +- 新回合、重试、项目切换和请求失败时清理旧 reasoning。 +- debug 记录与正文记录分开,内容受现有 debug 开关和长度限制约束。 + +### 其它调用方 + +GameAgent、Agent Interaction、Direct/Codex 适配层和通用 runtime 继续只读取正文字段。新增 reasoning 字段默认为空,不改变这些调用方的业务判断。 + +### 前端 + +复用现有 `ProjectSupervisorView` 的 `designReasoning` 和默认折叠 `
` 展示。只补事件生命周期和状态清理,不新建平行组件或平行状态协议。 + +## 分步实施方案 + +### 第一步:冻结共享契约与兼容开关 + +明确字段语义、空值语义和捕获开关: + +- reasoning 字段只表示 Provider 返回的内部推理内容,不代表用户正文。 +- 捕获开关默认关闭;未启用时新增字段为空。 +- 正文、工具调用、finish reason 和 Responses 原生 output 的现有语义保持不变。 +- 该步只更新规范、类型定义和构造点,不接入策划 UI。 + +验收重点:所有现有 Rust 构造点可编译,GameAgent 现有调用仍只依赖正文字段。 + +### 第二步:实现 `platform-llm` 协议解析 + +分别补齐: + +- Responses reasoning 增量事件; +- Responses 终态 reasoning output item / summary; +- Chat `reasoning`、`reasoning_content` 和 reasoning content part; +- 正文与 reasoning 的独立累计; +- reasoning 与正文、工具调用同时出现时的顺序和去重; +- reasoning 解析失败时的降级行为。 + +Responses 的原生 output 仍按当前方式保留,用于后续 Responses 会话回放;新增 reasoning 字段只用于上层展示和调试消费。 + +验收重点:正文永远不含 reasoning;无 reasoning 的响应与当前行为一致。 + +### 第三步:补齐共享适配层并锁定 GameAgent 不变 + +更新 `LlmStreamDelta` 构造点、适配器和测试辅助函数,使它们为新增字段提供空值。检查并锁定: + +- GameAgent 正文流不读取 reasoning; +- 工具调用判断不读取 reasoning; +- Direct/Codex 过程卡不显示 reasoning; +- 通用 response stream 过滤逻辑不因新增字段改变。 + +验收重点:现有工具调用、正文流式、Direct 和 Agent Interaction 测试无行为回归。 + +### 第四步:接通策划 Runtime 与现有 UI + +仅在策划 Agent Provider 请求中启用捕获开关: + +- 收到 reasoning 增量时发出独立 `reasoningText`; +- 收到正文增量时继续发出原有 `text`; +- 重试时替换同一回合的临时 reasoning,不残留上一 attempt; +- 正式回合结束后保留本回合展示,下一回合开始时清理; +- UI 默认折叠,展开后显示累计 reasoning,不影响正文滚动和输入。 + +验收重点:策划 Agent 能看到独立 reasoning,正文气泡不重复、不混入推理文本。 + +### 第五步:完成回归、文档和验收证据 + +形成逐条证据矩阵,至少覆盖: + +- Responses reasoning 增量和终态; +- Chat reasoning 字段和 content part; +- 正文与 reasoning 分离; +- reasoning 与工具调用并存; +- reasoning 解析失败降级; +- 无 reasoning 兼容行为; +- 策划 Runtime 事件映射和 UI 生命周期; +- GameAgent 正文与工具调用回归。 + +## 契约与持久化策略 + +- 不修改 HTTP API、OpenAPI、SpacetimeDB schema 或生成绑定。 +- 不新增正式持久化字段;策划会话仍保存既有对话和 Responses 原生 output。 +- reasoning 捕获开关属于 Provider 请求的内部调用语义,默认关闭,不改变已有请求的默认指纹和展示行为。 +- reasoning 不作为下一轮普通用户可见正文回灌;Responses 原生 output 的恢复语义保持现状。 + +## 失败、重试与恢复 + +- reasoning 解析失败:保留正文和工具调用,reasoning 字段置空或保留已累计部分。 +- Provider 瞬态重试:reasoning 与正文使用同一回合、同一响应槽,新的 attempt 替换临时值。 +- 流中断:沿用现有 Provider 错误和策划会话恢复规则,不把未完成 reasoning 误判为正式消息。 +- UI 刷新或项目恢复:只从当前事件/状态恢复 reasoning,不隐式唤醒 Provider。 + +## 风险与回滚点 + +| 风险 | 控制措施 | 回滚点 | +| --- | --- | --- | +| 共享结构体新增字段导致构造点遗漏 | 先补齐所有构造点和编译检查 | 回退共享字段提交 | +| Provider 把 reasoning 混入正文 | 保留独立提取器和正文过滤测试 | 关闭 reasoning 捕获开关 | +| Responses summary 事件重复累计 | 以增量事件为主,终态仅做快照/兜底 | 关闭对应事件解析 | +| GameAgent 意外展示 reasoning | 捕获默认关闭,调用方只读正文字段 | 回退策划开关,不影响共享解析 | +| 重试残留旧 reasoning | 按回合和响应槽清理/替换 | 回退 UI 事件消费 | + +## 验收命令 + +代码实现阶段按里程碑执行,不在本计划阶段运行业务测试。预计命令: + +```text +cargo test -p platform-llm +cargo test -p ai-game-creator-shell +npm run typecheck +npm run check:encoding +git diff --check +``` + +文档阶段已要求补充运行: + +```text +npm run check:doc-index +npm run check:encoding +git diff --check +``` + +## 当前状态与下一步 + +当前仅完成问题定位和方案设计,未修改业务代码。进入实现前应先评审本里程碑的字段语义、默认关闭策略、Responses 事件覆盖范围和 reasoning 是否进入 debug 记录;评审通过后再为单个里程碑建立对应的 `【实施计划】` 文档。