修复 DirectProject 流式正文逐 delta 脱敏吃掉段尾换行导致 Markdown 结构损坏 #533
Reference in New Issue
Block a user
Delete Branch "fix/direct-delta-markdown"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #532
问题
AGC 项目对话里 agent 汇报的 Markdown 结构在流式阶段整体失效:段落并进同一行、序号项挤成一段、表格整块不渲染(表头、
|---|---|与数据行连成一段正文);路径还会被切成game<absolute-path>ame.js。重开项目读历史时渲染正常,所以此前一直像「渲染器偶发」。原因
#384(30c377d0f)把 DirectProject 流式正文改成每个 delta 各自脱敏(意图正确:前端不得接触原始增量),但脱敏函数不满足拼接不变性,前端appendLiveText是裸拼接:codex_app_server/mod.rsdirect_codex_thread_delta_event→direct_thread_wire.rsdirect_thread_delta_text→generation/prompt_context.rssanitize_error_context旧实现用lines()+join("\n")往返,以换行结尾的段其末尾换行被吃掉("a\n"→"a"、"\n"→"")。redact_absolute_path_tokens把index == 0当文本边界,delta 从/开头时片段被误判成绝对路径("assets" + "/c" + "anvas-generated"→assets<absolute-path>anvas-generated)。directThreadChat.ts的mergeDirectChatEntry正文取「更长的一份」,被<absolute-path>撑长的流式正文会一直压过item.completed的正确快照。改动
apps/ai-game-creator-shell/src-tauri/src/agent/generation/prompt_context.rssanitize_error_context改为split_inclusive('\n')逐段处理、原样保留行终止符(CRLF 仍归一成 LF;私钥块整行吞掉的旧口径不变)。逐段脱敏因此与整段脱敏同形apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server/mod.rsdirect_thread_delta_sanitization_preserves_line_breaks:逐段脱敏必须逐字等于整段脱敏,去掉split_inclusive即红docs/project-memory/shared-memory/pitfalls.md前后对照(本机
gameagent-cfc64e7f真实汇报全文,1445 字符,38 个换行)ChatMarkdownMessage渲染结果table:0 th:0 li:0 h2:0 p:1(整条消息退化成一段正文,即问题现象)table:1 th:3 h2:4 p:8 li:6item.completed/ 历史读回)table:1 th:3 h2:4 p:8 li:6(修复后与流式路径一致)验证
cargo test --manifest-path apps/ai-game-creator-shell/src-tauri/Cargo.toml --bin genarrative-ai-game-creator-shell -- direct_thread(46 passed)、-- sanitize(7 passed)、新用例单跑通过。node .codex/hooks/pre-submit-compile-check.mjs:rustfmt + TS typecheck + admin-web typecheck + api-server 编译全部通过。ChatMarkdownMessage渲染(临时夹具已删)。npm run check:encoding、git diff --check通过。未覆盖
redact_absolute_path_tokens的index == 0边界误判(Issue 第 4 点)仍需跨 delta 的「上一个字符」上下文,本 PR 不处理,避免动到脱敏边界与协议。- prompt_context.rs:sanitize_error_context 改为 split_inclusive('\n') 逐段处理并原样保留行终止符,「逐段脱敏」与「整段脱敏」同形(CRLF 仍归一成 LF,私钥块整行吞掉的旧口径不变) - codex_app_server/mod.rs:新增 direct_thread_delta_sanitization_preserves_line_breaks,钉住逐段脱敏 == 整段脱敏,去掉 split_inclusive 即红 - pitfalls.md:记入本次排障(含 chunk 起点路径误判这一同源未修缺陷)