mirror of
https://github.com/pchuan98/codex.git
synced 2026-07-01 00:31:56 +08:00
67009bc53f
## Why Remote stdio MCP servers can run in an environment whose path convention differs from the Codex host. A Windows cwd such as `C:\Users\openai\share` is absolute for the executor but was rejected by a POSIX orchestrator. Built on #29501, now merged, which only clarifies the host-native `PathUri` constructor name. ## What changed - Deserialize MCP cwd values as `LegacyAppPathString` so config does not apply host path rules. - Interpret that spelling as host-native for local launches and convert it to `PathUri` at executor launch. - Skip host filesystem and command resolution checks for remote stdio in `codex doctor`. - Add host-independent config and executor-boundary coverage using the foreign path convention for each test platform. ## Validation - `just test -p codex-utils-path-uri -p codex-config -p codex-mcp -p codex-rmcp-client` (408 passed) - `just test -p codex-cli -p codex-rmcp-client` (372 passed) - `cargo check --workspace --tests` - `just test` (11,311 passed; 43 unrelated environment/timing failures) - `just fix -p codex-cli -p codex-config -p codex-core -p codex-mcp -p codex-mcp-extension -p codex-rmcp-client -p codex-tui`
68 lines
2.0 KiB
Rust
68 lines
2.0 KiB
Rust
use std::ffi::OsString;
|
|
use std::sync::Arc;
|
|
use std::sync::Mutex;
|
|
|
|
use codex_exec_server::ExecBackend;
|
|
use codex_exec_server::ExecBackendFuture;
|
|
use codex_exec_server::ExecParams;
|
|
use codex_exec_server::ExecServerError;
|
|
use codex_rmcp_client::ExecutorStdioServerLauncher;
|
|
use codex_rmcp_client::RmcpClient;
|
|
use codex_utils_path_uri::PathUri;
|
|
use pretty_assertions::assert_eq;
|
|
|
|
#[derive(Default)]
|
|
struct RecordingExecBackend {
|
|
params: Mutex<Option<ExecParams>>,
|
|
}
|
|
|
|
impl ExecBackend for RecordingExecBackend {
|
|
fn start(&self, params: ExecParams) -> ExecBackendFuture<'_> {
|
|
let mut recorded_params = match self.params.lock() {
|
|
Ok(recorded_params) => recorded_params,
|
|
Err(poisoned) => poisoned.into_inner(),
|
|
};
|
|
*recorded_params = Some(params);
|
|
Box::pin(async {
|
|
Err(ExecServerError::Protocol(
|
|
"stop after recording executor request".to_string(),
|
|
))
|
|
})
|
|
}
|
|
}
|
|
|
|
#[tokio::test]
|
|
async fn executor_stdio_forwards_foreign_absolute_cwd_as_path_uri() {
|
|
#[cfg(not(windows))]
|
|
let cwd = r"C:\Users\openai\share";
|
|
#[cfg(windows)]
|
|
let cwd = "/home/openai/share";
|
|
#[cfg(not(windows))]
|
|
let expected_cwd: PathUri = "file:///C:/Users/openai/share"
|
|
.parse()
|
|
.expect("expected cwd should be a path URI");
|
|
#[cfg(windows)]
|
|
let expected_cwd: PathUri = "file:///home/openai/share"
|
|
.parse()
|
|
.expect("expected cwd should be a path URI");
|
|
let backend = Arc::new(RecordingExecBackend::default());
|
|
let launcher = Arc::new(ExecutorStdioServerLauncher::new(backend.clone()));
|
|
|
|
let _ = RmcpClient::new_stdio_client(
|
|
OsString::from("echo"),
|
|
Vec::new(),
|
|
/*env*/ None,
|
|
&[],
|
|
Some(cwd.to_string()),
|
|
launcher,
|
|
)
|
|
.await;
|
|
let params = backend
|
|
.params
|
|
.lock()
|
|
.expect("recorded params lock should not be poisoned")
|
|
.take()
|
|
.expect("executor start request should be recorded");
|
|
assert_eq!(params.cwd, expected_cwd);
|
|
}
|