From 5ac26b99c95eaa86aa3cb42d09e43c44ec8b0625 Mon Sep 17 00:00:00 2001 From: Suzumiya Date: Fri, 11 Sep 2026 18:36:16 +0800 Subject: [PATCH] =?UTF-8?q?=E6=98=BE=E5=BC=8F=20Codex=20=E8=BF=94=E5=9B=9E?= =?UTF-8?q?=E4=B8=8D=E5=86=8D=E5=BE=80=E9=A1=B9=E7=9B=AE=E4=B8=BB=E5=AF=B9?= =?UTF-8?q?=E8=AF=9D=E6=8A=95=E5=BD=B1=E6=97=A7=E6=A0=BC=E5=BC=8F=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - direct_tools_mcp.rs:删除 conversation.record_codex_response 末尾往 project.jsonl 追加 legacy 行的投影,它写的是 {schemaVersion:game-creator-conversation.v1,...} 旧行,会毒化共用该文件的 DirectProject 历史 - 顺带删掉只为那条投影存在的 key/message_id 计算与描述它的注释,不留墓碑 - 该工具的事实来源仍是自己的只读 journal .agent/conversations/codex-responses.jsonl,返回内容与 conversation.list/read 行为不变 - 补断言:record_codex_response 只写 codex-responses.jsonl,project.jsonl 保持为空 --- .../src-tauri/src/agent/direct_tools_mcp.rs | 54 ++++++++++--------- 1 file changed, 29 insertions(+), 25 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs index 11e028cb4..a456b7596 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/direct_tools_mcp.rs @@ -1247,8 +1247,6 @@ fn external_mcp_record_response(root: &Path, arguments: &Value) -> Value { Err(error) => return mcp_tool_result(error, Vec::new(), true), }; let redacted = redact_external_mcp_response(&content); - let key = format!("{request_id}\u{0}{sequence}"); - let message_id = format!("external-codex-{:x}", Sha256::digest(key.as_bytes())); let guard = EXTERNAL_MCP_JOURNAL_LOCK .get_or_init(|| Mutex::new(())) .lock(); @@ -1358,29 +1356,6 @@ fn external_mcp_record_response(root: &Path, arguments: &Value) -> Value { true, ); } - // Reuse the existing conversation projection so the current UI can read - // the explicit external response without treating it as business truth. - if let Err(error) = append_local_conversation_message_for_session_idempotent_at( - root, - None, - None, - LocalConversationMessage { - role: "assistant".to_string(), - content: record - .get("content") - .and_then(Value::as_str) - .unwrap_or_default() - .to_string(), - agent_id: None, - }, - &message_id, - ) { - return mcp_tool_result( - format!("Codex 返回已写入但对话投影失败:{error}"), - Vec::new(), - true, - ); - } records.push(record.clone()); mcp_tool_result(record.to_string(), Vec::new(), false) } @@ -2280,4 +2255,33 @@ mod tests { })) .is_err()); } + + #[test] + fn recorded_codex_response_only_writes_its_own_journal() { + let temporary = crate::tests::canonical_test_tempdir("direct-tools-record-response-"); + let root = temporary.path(); + init_local_game_project_at(root, "direct-tools-record", "Codex 返回记录测试") + .expect("init project"); + + let result = external_mcp_record_response( + root, + &json!({ + "requestId": "req-1", + "sequence": 0, + "content": "已完成的返回正文" + }), + ); + assert_eq!(result.get("isError"), Some(&json!(false)), "{result}"); + + let journal = root.join(".agent/conversations/codex-responses.jsonl"); + let journal_text = std::fs::read_to_string(&journal).expect("read codex responses journal"); + assert!(journal_text.contains("已完成的返回正文"), "{journal_text}"); + + let project_history = root.join(".agent/conversations/project.jsonl"); + let project_history_text = std::fs::read_to_string(&project_history).unwrap_or_default(); + assert_eq!( + project_history_text, "", + "显式 Codex 返回不能再往项目主对话写 legacy 行" + ); + } }