diff --git a/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadSanitize.ts b/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadSanitize.ts index 238f18ec9..dee35a447 100644 --- a/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadSanitize.ts +++ b/apps/ai-game-creator-shell/src/view/project-development/chat/conversation/directThreadSanitize.ts @@ -513,16 +513,18 @@ export function sanitizeDirectThreadText( const withoutAbsolutePaths = redactAbsolutePaths(withoutProjectRoot); const withoutSecrets = redactSecretTokens(withoutAbsolutePaths); const sanitized = sanitizeSensitiveLines(withoutSecrets); - // 旧版已经落盘的失败条目无法凭空恢复被删掉的原因;把它们明确标成“宿主未提供正文”, + // 旧版已经落盘的失败条目无法凭空恢复被删掉的原因;把它们明确标成“历史事件未记录正文”, // 避免历史记录继续伪装成当前仍在吞错的完整兜底句。新事件带 detail 时不命中这里。 - const legacyGenericFailure = - '陶泥儿智能创作 执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断'; - // 旧版本有的写入路径把连续空格 / 换行归一化方式不同;按空白折叠识别同一条历史 - // 兜底文案,避免截图里的旧消息继续以“完整原因”伪装展示。新事件带正文时不命中这里。 + // 旧版本把多个失败变体直接写成固定句,历史条目里没有可恢复的 detail。按空白折叠 + // 识别所有已知旧兜底句,避免“等待模型回执超时”这类截图继续伪装成完整原因;新事件 + // 带 typed failure/detail 时不经过这条历史兼容分支。 + const normalizedLegacyFailure = sanitized.trim().replace(/\s+/gu, ' '); const isLegacyGenericFailure = - sanitized.trim().replace(/\s+/gu, ' ') === legacyGenericFailure; + /^陶泥儿智能创作 (?:等待模型回执超时(?:(已尝试 \d+ 次))?,本轮未完成;请稍后重试|执行通道连接失败,本轮未完成;请重试,若持续失败请检查项目诊断|执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断|流式响应协议不可用,本轮未完成;请检查项目诊断后重试)$/u.test( + normalizedLegacyFailure, + ); return isLegacyGenericFailure - ? `${sanitized}:宿主未提供具体错误正文` + ? `${sanitized}:历史错误事件未记录具体错误正文` : sanitized; } diff --git a/apps/ai-game-creator-shell/tests/directThreadSanitize.test.ts b/apps/ai-game-creator-shell/tests/directThreadSanitize.test.ts index 360d425f5..32b503629 100644 --- a/apps/ai-game-creator-shell/tests/directThreadSanitize.test.ts +++ b/apps/ai-game-creator-shell/tests/directThreadSanitize.test.ts @@ -99,7 +99,7 @@ describe('directThreadSanitize', () => { '陶泥儿智能创作 执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断', ), ).toBe( - '陶泥儿智能创作 执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断:宿主未提供具体错误正文', + '陶泥儿智能创作 执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断:历史错误事件未记录具体错误正文', ); }); @@ -110,7 +110,18 @@ describe('directThreadSanitize', () => { '陶泥儿智能创作 执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断', ), ).toBe( - '陶泥儿智能创作 执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断:宿主未提供具体错误正文', + '陶泥儿智能创作 执行通道中断,本轮未完成;请重试,若持续失败请检查项目诊断:历史错误事件未记录具体错误正文', + ); + }); + + it('旧版等待模型回执超时条目也明确标记历史正文缺失', () => { + expect( + sanitizeDirectThreadText( + ROOT, + '陶泥儿智能创作 等待模型回执超时,本轮未完成;请稍后重试', + ), + ).toBe( + '陶泥儿智能创作 等待模型回执超时,本轮未完成;请稍后重试:历史错误事件未记录具体错误正文', ); }); diff --git a/docs/project-memory/shared-memory/pitfalls.md b/docs/project-memory/shared-memory/pitfalls.md index e1083b65f..587969793 100644 --- a/docs/project-memory/shared-memory/pitfalls.md +++ b/docs/project-memory/shared-memory/pitfalls.md @@ -5,7 +5,7 @@ ## 2026-10-06 AGC 失败终态与 CC/MCP 边界不能吞掉协议、清理和 I/O 错误 - **现象**:DirectProject 的 `turn.completed(status=failed)` 若跨 IPC 丢失 `failure` 载荷,前端会只收口回合而不显示任何说明;Claude Code sidecar 的非 UTF-8 stderr、进程树清理失败、会话表锁损坏,以及 MCP loopback 服务退出、插件能力桥超时、损坏 manifest,会分别被压成空 detail、继续成功取消、伪造 hash projectId 或静默不广告插件。 -- **现行口径**:失败载荷缺失显示明确的协议错误;CC 清理、stderr 解码、会话锁都保留原始正文;MCP server / capability bridge 失败写入统一应用日志,MCP manifest / journal / 时间 / metadata 读取失败返回具体错误;完成判定在把素材缺失归因于“未引用平台图”前先验证源码、manifest 和已登记图片的 I/O/PNG 错误。切片文件是可选投影,完整 spritesheet 不因无切片而误失败。 +- **现行口径**:失败载荷缺失显示明确的协议错误;旧历史里的已知通用失败句明确标成“历史错误事件未记录具体错误正文”,不伪装成当前仍在吞错;CC 清理、stderr 解码、会话锁都保留原始正文;MCP server / capability bridge 失败写入统一应用日志,MCP manifest / journal / 时间 / metadata 读取失败返回具体错误;完成判定在把素材缺失归因于“未引用平台图”前先验证源码、manifest 和已登记图片的 I/O/PNG 错误。切片文件是可选投影,完整 spritesheet 不因无切片而误失败。 - **验证**:`cargo test agent::claude_code_cli::tests::` 14 passed;`cargo test agent::direct_tools_mcp::tests::` 34 passed;`cargo test agent::direct_runtime::tests::` 92 passed;`npx vitest run tests/directThreadChat.test.ts tests/directTurnFailure.test.ts` 64 passed;另有损坏 manifest 回归用例 1 passed。新失败正文仍经既有脱敏边界处理。 - **关联**:`agent/claude_code_cli.rs`、`agent/direct_tools_mcp.rs`、`agent/direct_runtime/mod.rs`、`agent/thread_manager/dispatch.rs`、`chat/conversation/directThreadChat.ts`。