From b6d6476459d972041569eff523c604930e7205e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E5=BE=B7=E5=AE=87?= Date: Mon, 7 Sep 2026 11:05:33 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=20DirectProject=20=E5=8E=86?= =?UTF-8?q?=E5=8F=B2=E4=B8=8E=E7=BA=BF=E7=A8=8B=E5=88=9D=E5=A7=8B=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 尾行损坏时先允许底层 JSONL 追加逻辑修复 历史注入失败时淘汰未完成初始化的 Codex thread turn/start 传递稳定 clientUserMessageId --- .../src-tauri/src/agent/codex_app_server.rs | 36 ++++++++++++++----- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs index 0d7017600..dcf02c0d8 100644 --- a/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs +++ b/apps/ai-game-creator-shell/src-tauri/src/agent/codex_app_server.rs @@ -977,6 +977,7 @@ fn codex_app_server_turn_start_params( model: &str, workspace_path: &std::path::Path, workspace_mode: CodexAppServerWorkspaceMode, + client_user_message_id: Option<&str>, ) -> serde_json::Value { let approval_policy = "never"; let mut params = serde_json::json!({ @@ -994,6 +995,13 @@ fn codex_app_server_turn_start_params( "networkAccess": false }); } + if let Some(client_user_message_id) = client_user_message_id + .map(str::trim) + .filter(|value| !value.is_empty()) + { + params["clientUserMessageId"] = + serde_json::Value::String(client_user_message_id.to_string()); + } params } @@ -2140,14 +2148,23 @@ impl CodexAppServerConnection { )); } if thread_created { - let items = read_direct_project_history_items_at(history_root) - .map_err(platform_llm::LlmError::InvalidRequest)?; - self.request( - "thread/inject_items", - serde_json::json!({"threadId": thread_id, "items": items}), - ) - .await - .map_err(platform_llm::LlmError::Transport)?; + let items = match read_direct_project_history_items_at(history_root) { + Ok(items) => items, + Err(error) => { + self.release_thread(snapshot, &thread_id).await; + return Err(platform_llm::LlmError::InvalidRequest(error)); + } + }; + if let Err(error) = self + .request( + "thread/inject_items", + serde_json::json!({"threadId": thread_id, "items": items}), + ) + .await + { + self.release_thread(snapshot, &thread_id).await; + return Err(platform_llm::LlmError::Transport(error)); + } } } let prompt = if self.inner.workspace_mode.uses_direct_conversation() { @@ -2186,6 +2203,7 @@ impl CodexAppServerConnection { model, &self.inner.workspace_path, self.inner.workspace_mode, + _direct_client_turn_id, ); apply_game_creator_codex_app_server_reasoning_effort(&mut params, &request); if let Some(schema) = game_creator_codex_cli_tool_output_schema(&request) { @@ -3630,6 +3648,7 @@ mod tests { "fixture-model", workspace, CodexAppServerWorkspaceMode::DirectHome, + None, ); assert_eq!(turn["threadId"], "home-thread"); assert_eq!(turn["approvalPolicy"], "never"); @@ -3690,6 +3709,7 @@ mod tests { "fixture-model", &workspace, CodexAppServerWorkspaceMode::DirectProject, + None, ); assert_eq!( turn.pointer("/sandboxPolicy/writableRoots/0"),