mirror of
https://github.com/openai/codex.git
synced 2026-09-04 15:08:45 +00:00
core: require explicit cwd for foreign defaults
This commit is contained in:
@@ -682,7 +682,7 @@ Turns attach user input (text or images) to a thread and trigger Codex generatio
|
||||
- `{"type":"image","url":"https://…png"}`
|
||||
- `{"type":"localImage","path":"/tmp/screenshot.png"}`
|
||||
|
||||
You can optionally specify config overrides on the new turn. If specified, these settings become the default for subsequent turns on the same thread. `outputSchema` applies only to the current turn. Experimental `environments` is turn-scoped: omit it to inherit the thread's sticky environments, pass `[]` to run the turn with no environments, or pass explicit environment ids to override the sticky selection for this turn only. Each environment `cwd` must be absolute and use that environment's native path convention, so a Windows environment uses a value such as `C:\\workspace` even when app-server runs on Linux. The path must also be portable to the selected executor; app-server rejects malformed paths and Windows device names before starting the thread or turn.
|
||||
You can optionally specify config overrides on the new turn. If specified, these settings become the default for subsequent turns on the same thread. `outputSchema` applies only to the current turn. Experimental `environments` is turn-scoped: omit it to inherit the thread's sticky environments, pass `[]` to run the turn with no environments, or pass explicit environment ids to override the sticky selection for this turn only. Each environment `cwd` must be absolute and use that environment's native path convention, so a Windows environment uses a value such as `C:\\workspace` even when app-server runs on Linux. The path must also be portable to the selected executor; app-server rejects malformed paths and Windows device names before starting the thread or turn. If a default environment uses a different path convention from app-server, clients must provide an explicit environment `cwd`.
|
||||
|
||||
`approvalsReviewer` accepts:
|
||||
|
||||
|
||||
@@ -212,6 +212,28 @@ url = "ws://127.0.0.1:8765"
|
||||
assert!(err.to_string().contains("duplicate"));
|
||||
}
|
||||
|
||||
#[cfg(unix)]
|
||||
#[test]
|
||||
fn foreign_remote_environment_requires_explicit_native_cwd() {
|
||||
let environment = Arc::new(
|
||||
Environment::create_for_tests(Some("ws://127.0.0.1:8765".to_string()))
|
||||
.expect("remote environment"),
|
||||
);
|
||||
let error = TurnEnvironment::new_with_uri(
|
||||
REMOTE_ENVIRONMENT_ID.to_string(),
|
||||
environment,
|
||||
PathUri::parse("file:///workspace").expect("POSIX cwd URI"),
|
||||
codex_utils_path_uri::PathConvention::Windows,
|
||||
crate::shell::default_user_shell(),
|
||||
)
|
||||
.expect_err("host cwd must not be projected into a foreign environment");
|
||||
|
||||
assert_eq!(
|
||||
error.to_string(),
|
||||
"explicit environment cwd required for foreign environment `remote` using Windows path syntax"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn resolved_environment_selections_use_first_selection_as_primary() {
|
||||
let cwd = AbsolutePathBuf::current_dir().expect("cwd");
|
||||
|
||||
@@ -73,11 +73,19 @@ impl TurnEnvironment {
|
||||
path_convention: PathConvention,
|
||||
shell: shell::Shell,
|
||||
) -> CodexResult<Self> {
|
||||
ApiPathString::from_path_uri(&cwd, path_convention).map_err(|err| {
|
||||
CodexErr::InvalidRequest(format!(
|
||||
"turn environment cwd `{cwd}` cannot be rendered for {path_convention}: {err}"
|
||||
))
|
||||
})?;
|
||||
match ApiPathString::from_path_uri(&cwd, path_convention) {
|
||||
Ok(_) => {}
|
||||
Err(_) if environment.is_remote() && path_convention != PathConvention::native() => {
|
||||
return Err(CodexErr::InvalidRequest(format!(
|
||||
"explicit environment cwd required for foreign environment `{environment_id}` using {path_convention} path syntax"
|
||||
)));
|
||||
}
|
||||
Err(err) => {
|
||||
return Err(CodexErr::InvalidRequest(format!(
|
||||
"turn environment cwd `{cwd}` cannot be rendered for {path_convention}: {err}"
|
||||
)));
|
||||
}
|
||||
}
|
||||
Ok(Self {
|
||||
environment_id,
|
||||
environment,
|
||||
|
||||
@@ -163,6 +163,30 @@ async fn exercise_app_server(websocket_url: String) -> Result<()> {
|
||||
"invalid environment cwd must fail before model inference"
|
||||
);
|
||||
|
||||
let default_request_id = app_server
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let default_response: JSONRPCError = timeout(
|
||||
APP_SERVER_TIMEOUT,
|
||||
app_server.read_stream_until_error_message(RequestId::Integer(default_request_id)),
|
||||
)
|
||||
.await??;
|
||||
assert_eq!(default_response.id, RequestId::Integer(default_request_id));
|
||||
assert_eq!(default_response.error.code, -32600);
|
||||
assert_eq!(
|
||||
default_response.error.message,
|
||||
format!(
|
||||
"explicit environment cwd required for foreign environment `{REMOTE_ENVIRONMENT_ID}` using Windows path syntax"
|
||||
)
|
||||
);
|
||||
assert!(
|
||||
response_mock.requests().is_empty(),
|
||||
"foreign default cwd must fail before model inference"
|
||||
);
|
||||
|
||||
let environment = remote_windows_environment();
|
||||
let thread_request_id = app_server
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
|
||||
Reference in New Issue
Block a user