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 18a483969..1ba2bb9d1 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 @@ -1061,6 +1061,31 @@ fn quoted_toml_string(value: &str) -> Result { }) } +fn direct_tools_mcp_executable_path() -> Result { + // In Linux development mode Cargo may replace/unlink the running binary + // while Tauri's app-server pool is still alive. A child launched from the + // old `current_exe()` pathname then fails with ENOENT. `/proc//exe` + // keeps referring to this process' executable inode until this AGC process + // exits, so the MCP child remains launchable across hot rebuilds. + #[cfg(target_os = "linux")] + { + let proc_executable = std::path::PathBuf::from(format!("/proc/{}/exe", std::process::id())); + if proc_executable.exists() { + return Ok(proc_executable); + } + } + + let current_executable = std::env::current_exe().map_err(|error| { + platform_llm::LlmError::InvalidConfig(format!("定位 AGC 受控工具进程失败:{error}")) + })?; + if !current_executable.is_file() { + return Err(platform_llm::LlmError::InvalidConfig( + "定位 AGC 受控工具进程失败:当前客户端可执行文件已不存在".to_string(), + )); + } + Ok(current_executable) +} + fn configure_game_creator_codex_app_server_command( command: &mut tokio::process::Command, llm: &GameCreatorLlmConfig, @@ -1095,9 +1120,7 @@ fn configure_game_creator_codex_app_server_command_for_mode( command.arg("-c").arg("agents.enabled=false"); } if workspace_mode == CodexAppServerWorkspaceMode::DirectProject { - let current_executable = std::env::current_exe().map_err(|error| { - platform_llm::LlmError::InvalidConfig(format!("定位 AGC 受控工具进程失败:{error}")) - })?; + let current_executable = direct_tools_mcp_executable_path()?; command .arg("-c") .arg(format!( @@ -3592,6 +3615,15 @@ mod tests { assert!(game_creator_codex_app_server_validate_llm_config(&llm).is_ok()); } + #[cfg(target_os = "linux")] + #[test] + fn direct_tools_mcp_uses_a_stable_parent_executable_reference() { + assert_eq!( + direct_tools_mcp_executable_path().expect("resolve AGC MCP executable"), + std::path::PathBuf::from(format!("/proc/{}/exe", std::process::id())) + ); + } + #[test] fn direct_project_command_configures_the_reviewed_agc_tools_bridge() { let mut command = tokio::process::Command::new("fixture");