mirror of
https://github.com/openai/codex.git
synced 2026-10-18 17:18:52 +00:00
test: migrate app-server v2 starts to auto env (#31614)
## Why We should be running as many integrations tests as possible against the split cross-OS configuration. ## What - migrate eligible thread starts and builders to auto env - keep explicit custom/local-executor cases local with rationale comments - keep auto-env coverage where possible and add narrow `TODO(anp)` skips for fixtures that are not target-native yet
This commit is contained in:
@@ -511,7 +511,6 @@ async fn external_auth_refreshes_on_unauthorized() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -538,7 +537,7 @@ async fn external_auth_refreshes_on_unauthorized() -> Result<()> {
|
||||
.await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(codex_app_server_protocol::ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(codex_app_server_protocol::ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -623,7 +622,6 @@ async fn external_auth_refresh_error_fails_turn() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -650,7 +648,7 @@ async fn external_auth_refresh_error_fails_turn() -> Result<()> {
|
||||
.await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(codex_app_server_protocol::ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(codex_app_server_protocol::ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -751,7 +749,6 @@ async fn external_auth_refresh_mismatched_workspace_fails_turn() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -778,7 +775,7 @@ async fn external_auth_refresh_mismatched_workspace_fails_turn() -> Result<()> {
|
||||
.await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(codex_app_server_protocol::ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(codex_app_server_protocol::ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -872,7 +869,6 @@ async fn external_auth_refresh_invalid_access_token_fails_turn() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -899,7 +895,7 @@ async fn external_auth_refresh_invalid_access_token_fails_turn() -> Result<()> {
|
||||
.await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(codex_app_server_protocol::ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(codex_app_server_protocol::ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -69,7 +69,6 @@ async fn attestation_generate_round_trip_adds_header_to_responses_websocket_hand
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -95,7 +94,7 @@ async fn attestation_generate_round_trip_adds_header_to_responses_websocket_hand
|
||||
};
|
||||
|
||||
let thread_request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let thread_response: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
|
||||
@@ -83,7 +83,6 @@ async fn auto_compaction_local_emits_started_and_completed_items() -> Result<()>
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -170,7 +169,6 @@ async fn auto_compaction_remote_emits_started_and_completed_items() -> Result<()
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -281,7 +279,6 @@ async fn thread_compact_start_triggers_compaction_and_returns_empty_response() -
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -335,7 +332,6 @@ async fn thread_compact_start_rejects_invalid_thread_id() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -375,7 +371,6 @@ async fn thread_compact_start_rejects_unknown_thread_id() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -399,7 +394,7 @@ async fn thread_compact_start_rejects_unknown_thread_id() -> Result<()> {
|
||||
|
||||
async fn start_thread(mcp: &mut TestAppServer) -> Result<String> {
|
||||
let thread_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -178,6 +178,7 @@ HTTP_PROXY = {http_proxy}
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
// This suite owns environments.toml to exercise explicit executor selection.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
@@ -13,6 +13,7 @@ use codex_app_server_protocol::TurnStartParams;
|
||||
use codex_app_server_protocol::UserInput;
|
||||
use codex_utils_path_uri::PathUri;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::skip_if_remote;
|
||||
use tempfile::TempDir;
|
||||
use tokio::time::timeout;
|
||||
|
||||
@@ -23,6 +24,12 @@ const LOCAL_SKILL_MARKER: &str = "LOCAL_SKILL_BODY_MARKER";
|
||||
|
||||
#[tokio::test]
|
||||
async fn selected_executor_root_exposes_plugin_skill() -> Result<()> {
|
||||
// TODO(anp): Remove after selected capability-root fixtures can be materialized in remote exec.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"selected capability root fixture is only materialized on the host"
|
||||
);
|
||||
|
||||
let server = responses::start_mock_server().await;
|
||||
let response_mock = responses::mount_sse_once(
|
||||
&server,
|
||||
@@ -83,13 +90,12 @@ stream_max_retries = 0
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(READ_TIMEOUT, app_server.initialize()).await??;
|
||||
|
||||
let request_id = app_server
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
selected_capability_roots: Some(vec![SelectedCapabilityRoot {
|
||||
id: "demo-plugin@1".to_string(),
|
||||
|
||||
@@ -253,7 +253,6 @@ async fn thread_start_mock_field_requires_experimental_api_capability() -> Resul
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
let init = mcp
|
||||
@@ -296,7 +295,6 @@ async fn thread_start_without_dynamic_tools_allows_without_experimental_api_capa
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
let init = mcp
|
||||
@@ -338,7 +336,6 @@ async fn thread_start_granular_approval_policy_requires_experimental_api_capabil
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
let init = mcp
|
||||
|
||||
@@ -206,14 +206,13 @@ memories = true
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().display().to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -26,6 +26,7 @@ use codex_core::config::set_project_trust_level;
|
||||
use codex_protocol::config_types::TrustLevel;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use core_test_support::skip_if_host_windows;
|
||||
use core_test_support::skip_if_remote;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde::Serialize;
|
||||
use tempfile::TempDir;
|
||||
@@ -137,7 +138,6 @@ async fn hooks_list_shows_discovered_hook() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -309,7 +309,6 @@ async fn hooks_list_warms_plugin_capabilities_for_thread_start() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -328,7 +327,7 @@ async fn hooks_list_warms_plugin_capabilities_for_thread_start() -> Result<()> {
|
||||
std::fs::remove_file(plugin_mcp_path)?;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let _: ThreadStartResponse = to_response(
|
||||
timeout(
|
||||
@@ -680,6 +679,8 @@ async fn config_batch_write_toggles_user_hook() -> Result<()> {
|
||||
#[tokio::test]
|
||||
async fn config_batch_write_updates_hook_trust_for_loaded_session() -> Result<()> {
|
||||
skip_if_host_windows!(Ok(()));
|
||||
// TODO(anp): Teach command-hook fixtures to run in selected remote environments.
|
||||
skip_if_remote!(Ok(()), "command hooks use host-local script and log paths");
|
||||
|
||||
let responses = vec![
|
||||
create_final_assistant_message_sse_response("Warmup")?,
|
||||
@@ -737,7 +738,6 @@ command = "python3 {hook_script_path}"
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -757,7 +757,7 @@ command = "python3 {hook_script_path}"
|
||||
assert_eq!(hook.trust_status, HookTrustStatus::Untrusted);
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -935,6 +935,8 @@ command = "python3 {hook_script_path}"
|
||||
#[tokio::test]
|
||||
async fn config_batch_write_disables_hook_for_loaded_session() -> Result<()> {
|
||||
skip_if_host_windows!(Ok(()));
|
||||
// TODO(anp): Teach command-hook fixtures to run in selected remote environments.
|
||||
skip_if_remote!(Ok(()), "command hooks use host-local script and log paths");
|
||||
|
||||
let responses = vec![
|
||||
create_final_assistant_message_sse_response("Warmup")?,
|
||||
@@ -991,7 +993,6 @@ command = "python3 {hook_script_path}"
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -1034,7 +1035,7 @@ command = "python3 {hook_script_path}"
|
||||
let _: codex_app_server_protocol::ConfigWriteResponse = to_response(response)?;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -19,6 +19,7 @@ use codex_app_server_protocol::TurnStartResponse;
|
||||
use codex_app_server_protocol::UserInput as V2UserInput;
|
||||
use codex_config::types::AuthCredentialsStoreMode;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::skip_if_remote;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use tempfile::TempDir;
|
||||
@@ -90,7 +91,6 @@ async fn standalone_image_generation_returns_saved_path_hint_to_model() -> Resul
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -192,7 +192,6 @@ async fn standalone_image_generation_failure_emits_terminal_item() -> Result<()>
|
||||
)?;
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -236,6 +235,11 @@ async fn standalone_image_generation_failure_emits_terminal_item() -> Result<()>
|
||||
|
||||
#[tokio::test]
|
||||
async fn standalone_image_edit_uses_attached_model_visible_image() -> Result<()> {
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"remote executors use different imagegen storage approaches, so host-local image paths are unavailable"
|
||||
);
|
||||
|
||||
let edit_request = run_image_edit_test(|codex_home| {
|
||||
let image_path = codex_home.join("attached.png");
|
||||
std::fs::write(&image_path, TINY_PNG_BYTES)?;
|
||||
@@ -317,7 +321,6 @@ async fn standalone_image_generation_is_exposed_in_code_mode_only() -> Result<()
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -384,7 +387,6 @@ generatedImage(result);
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -468,7 +470,6 @@ async fn run_image_edit_test(
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
@@ -499,7 +500,7 @@ async fn run_image_edit_test(
|
||||
|
||||
async fn start_turn(mcp: &mut TestAppServer, input: Vec<V2UserInput>) -> Result<()> {
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
|
||||
@@ -89,11 +89,15 @@ async fn mcp_resource_read_returns_resource_contents() -> Result<()> {
|
||||
let (apps_server_url, _apps_server_calls, apps_server_handle) =
|
||||
start_resource_apps_mcp_server().await?;
|
||||
let responses_server_uri = responses_server.uri();
|
||||
let (_codex_home, mut mcp) =
|
||||
start_resource_test_app_server(&apps_server_url, &responses_server_uri).await?;
|
||||
let (_codex_home, mut mcp) = start_resource_test_app_server(
|
||||
&apps_server_url,
|
||||
&responses_server_uri,
|
||||
ResourceTestEnvironment::Auto,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -133,8 +137,12 @@ async fn orchestrator_skill_can_read_referenced_resource_without_an_executor() -
|
||||
let (apps_server_url, apps_server_calls, apps_server_handle) =
|
||||
start_resource_apps_mcp_server().await?;
|
||||
let responses_server_uri = responses_server.uri();
|
||||
let (_codex_home, mut mcp) =
|
||||
start_resource_test_app_server(&apps_server_url, &responses_server_uri).await?;
|
||||
let (_codex_home, mut mcp) = start_resource_test_app_server(
|
||||
&apps_server_url,
|
||||
&responses_server_uri,
|
||||
ResourceTestEnvironment::Auto,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
@@ -369,8 +377,13 @@ async fn local_executor_does_not_expose_orchestrator_skills() -> Result<()> {
|
||||
let (apps_server_url, _apps_server_calls, apps_server_handle) =
|
||||
start_resource_apps_mcp_server().await?;
|
||||
let responses_server_uri = responses_server.uri();
|
||||
let (_codex_home, mut mcp) =
|
||||
start_resource_test_app_server(&apps_server_url, &responses_server_uri).await?;
|
||||
let (_codex_home, mut mcp) = start_resource_test_app_server(
|
||||
&apps_server_url,
|
||||
&responses_server_uri,
|
||||
// This test exercises the implicit local executor.
|
||||
ResourceTestEnvironment::Local,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
@@ -449,13 +462,13 @@ async fn disabled_orchestrator_skills_do_not_expose_skills_namespace() -> Result
|
||||
[orchestrator.skills]
|
||||
enabled = false
|
||||
"#,
|
||||
ResourceTestEnvironment::Auto,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
environments: Some(Vec::new()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
@@ -648,15 +661,22 @@ async fn mcp_resource_read_returns_error_for_unknown_thread() -> Result<()> {
|
||||
async fn start_resource_test_app_server(
|
||||
apps_server_url: &str,
|
||||
responses_server_uri: &str,
|
||||
environment: ResourceTestEnvironment,
|
||||
) -> Result<(TempDir, TestAppServer)> {
|
||||
start_resource_test_app_server_with_extra_config(apps_server_url, responses_server_uri, "")
|
||||
.await
|
||||
start_resource_test_app_server_with_extra_config(
|
||||
apps_server_url,
|
||||
responses_server_uri,
|
||||
"",
|
||||
environment,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
async fn start_resource_test_app_server_with_extra_config(
|
||||
apps_server_url: &str,
|
||||
responses_server_uri: &str,
|
||||
extra_config: &str,
|
||||
environment: ResourceTestEnvironment,
|
||||
) -> Result<(TempDir, TestAppServer)> {
|
||||
let codex_home = TempDir::new()?;
|
||||
std::fs::write(
|
||||
@@ -696,15 +716,22 @@ stream_max_retries = 0
|
||||
AuthCredentialsStoreMode::File,
|
||||
)?;
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
let builder = TestAppServer::builder().with_codex_home(codex_home.path());
|
||||
let builder = match environment {
|
||||
ResourceTestEnvironment::Auto => builder,
|
||||
// The Local caller explicitly exercises the implicit local executor.
|
||||
ResourceTestEnvironment::Local => builder.without_auto_env(),
|
||||
};
|
||||
let mut mcp = builder.build().await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
Ok((codex_home, mcp))
|
||||
}
|
||||
|
||||
enum ResourceTestEnvironment {
|
||||
Auto,
|
||||
Local,
|
||||
}
|
||||
|
||||
async fn start_resource_apps_mcp_server()
|
||||
-> Result<(String, Arc<ResourceAppsMcpCalls>, JoinHandle<()>)> {
|
||||
let listener = TcpListener::bind("127.0.0.1:0").await?;
|
||||
|
||||
@@ -138,13 +138,12 @@ async fn mcp_server_status_list_uses_thread_project_local_config() -> Result<()>
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -348,6 +348,7 @@ url = "{mcp_server_url}/mcp"
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
// This test adds and refreshes an explicitly selected runtime environment.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
@@ -56,6 +56,7 @@ use core_test_support::responses::WebSocketTestServer;
|
||||
use core_test_support::responses::start_websocket_server;
|
||||
use core_test_support::responses::start_websocket_server_with_headers;
|
||||
use core_test_support::skip_if_no_network;
|
||||
use core_test_support::skip_if_remote;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde_json::Value;
|
||||
@@ -293,14 +294,13 @@ impl RealtimeE2eHarness {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
login_with_api_key(&mut mcp, "sk-test-key").await?;
|
||||
|
||||
let thread_start_request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let thread_start_response: JSONRPCResponse = timeout(
|
||||
DEFAULT_TIMEOUT,
|
||||
@@ -1173,7 +1173,6 @@ async fn realtime_list_voices_returns_supported_names() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -2520,6 +2519,11 @@ async fn websocket_v2_background_agent_progress_is_sent_before_function_output()
|
||||
|
||||
#[tokio::test]
|
||||
async fn websocket_v2_tool_call_delegated_turn_can_execute_shell_tool() -> Result<()> {
|
||||
// TODO(anp): Remove after delegated shell commands resolve target-native cwd in remote environments.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"delegated shell command cwd is only materialized on the host"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
// Phase 1: keep the two mocked OpenAI conversations explicit. The realtime sideband only
|
||||
|
||||
@@ -74,7 +74,6 @@ async fn first_turn_after_external_login_waits_for_recommended_plugins() -> Resu
|
||||
let sqlite_home = codex_home.path().to_string_lossy();
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.with_env_overrides(&[("CODEX_SQLITE_HOME", Some(sqlite_home.as_ref()))])
|
||||
.build()
|
||||
@@ -105,7 +104,7 @@ async fn first_turn_after_external_login_waits_for_recommended_plugins() -> Resu
|
||||
);
|
||||
|
||||
let thread_id = app_server
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -142,6 +142,7 @@ async fn selected_capability_stack_tracks_environment_availability_and_resume()
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(fixture.codex_home.path())
|
||||
// This fixture owns environments.toml and selects its environments explicitly.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -192,6 +193,7 @@ async fn selected_capability_stack_tracks_environment_availability_and_resume()
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(fixture.codex_home.path())
|
||||
// This fixture owns environments.toml and selects its environments explicitly.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -343,6 +345,7 @@ async fn selected_capabilities_become_available_between_samples_in_one_turn() ->
|
||||
|
||||
let mut app_server = TestAppServer::builder()
|
||||
.with_codex_home(fixture.codex_home.path())
|
||||
// This fixture owns environments.toml and selects its environments explicitly.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
@@ -24,6 +24,7 @@ use codex_app_server_protocol::ThreadStartParams;
|
||||
use codex_config::types::AuthCredentialsStoreMode;
|
||||
use codex_exec_server::CODEX_EXEC_SERVER_URL_ENV_VAR;
|
||||
use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use core_test_support::skip_if_remote;
|
||||
use pretty_assertions::assert_eq;
|
||||
use tempfile::TempDir;
|
||||
use tokio::time::timeout;
|
||||
@@ -874,6 +875,12 @@ async fn skills_extra_roots_set_updates_process_runtime_roots() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn skills_changed_notification_is_emitted_after_skill_change() -> Result<()> {
|
||||
// TODO(anp): Remove after skill watching can bridge host-local storage into remote exec.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"host-local skill changes are not visible to remote executors"
|
||||
);
|
||||
|
||||
let server = create_mock_responses_server_repeating_assistant("Done").await;
|
||||
let codex_home = TempDir::new()?;
|
||||
write_mock_responses_config_toml_with_chatgpt_base_url(
|
||||
@@ -885,8 +892,6 @@ async fn skills_changed_notification_is_emitted_after_skill_change() -> Result<(
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[(CODEX_EXEC_SERVER_URL_ENV_VAR, None)])
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -911,7 +916,7 @@ async fn skills_changed_notification_is_emitted_after_skill_change() -> Result<(
|
||||
);
|
||||
|
||||
let thread_start_request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: None,
|
||||
model_provider: None,
|
||||
allow_provider_model_fallback: false,
|
||||
|
||||
@@ -120,7 +120,6 @@ async fn thread_fork_creates_new_thread_and_emits_started() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -263,13 +262,12 @@ async fn thread_fork_at_last_turn_id_keeps_only_terminal_prefix() -> Result<()>
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let start_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
|
||||
@@ -52,7 +52,6 @@ const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs
|
||||
async fn init_mcp(codex_home: &Path) -> Result<TestAppServer> {
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -261,7 +260,7 @@ async fn thread_list_reports_system_error_idle_flag_after_failed_turn() -> Resul
|
||||
let mut mcp = init_mcp(codex_home.path()).await?;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -85,6 +85,8 @@ use codex_utils_absolute_path::AbsolutePathBuf;
|
||||
use codex_utils_path_uri::LegacyAppPathString;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::skip_if_no_network;
|
||||
use core_test_support::skip_if_remote;
|
||||
use core_test_support::skip_if_wine_exec;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::json;
|
||||
use std::fs::FileTimes;
|
||||
@@ -269,6 +271,11 @@ async fn thread_resume_with_empty_path_uses_running_thread_id() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_resume_running_thread_uses_cached_instruction_sources() -> Result<()> {
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"cached instruction-source fixture is outside the selected remote cwd"
|
||||
);
|
||||
|
||||
let server = create_mock_responses_server_repeating_assistant("Done").await;
|
||||
let codex_home = TempDir::new()?;
|
||||
create_config_toml(codex_home.path(), &server.uri())?;
|
||||
@@ -278,6 +285,7 @@ async fn thread_resume_running_thread_uses_cached_instruction_sources() -> Resul
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
// TODO(anp): Move the cached instruction-source fixture into the auto environment cwd.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -360,13 +368,12 @@ async fn turn_start_updates_runtime_workspace_roots_for_loaded_thread() -> Resul
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -443,14 +450,13 @@ async fn thread_goal_get_rejects_unmaterialized_thread() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.2-codex".to_string()),
|
||||
ephemeral: Some(true),
|
||||
..Default::default()
|
||||
@@ -507,7 +513,6 @@ async fn goal_first_live_thread_appears_in_state_db_thread_list() -> Result<()>
|
||||
.expect("test codex home should be utf-8");
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home_path)
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.with_env_overrides(&[("CODEX_SQLITE_HOME", Some(sqlite_home))])
|
||||
.build()
|
||||
@@ -515,7 +520,7 @@ async fn goal_first_live_thread_appears_in_state_db_thread_list() -> Result<()>
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.2-codex".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -605,7 +610,6 @@ async fn thread_resume_tracks_thread_initialized_analytics() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -654,14 +658,13 @@ async fn thread_resume_running_thread_tracks_thread_originator_in_analytics() ->
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
thread_source: Some(ThreadSource::User),
|
||||
service_name: Some("codex_work_desktop".to_string()),
|
||||
@@ -778,7 +781,6 @@ async fn thread_resume_returns_rollout_history() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -977,7 +979,6 @@ async fn resume_redaction_fixture(client_name: Option<&str>) -> Result<ThreadRes
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
if let Some(client_name) = client_name {
|
||||
@@ -1091,7 +1092,6 @@ async fn thread_resume_can_skip_turns_for_metadata_only_resume() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -1142,7 +1142,6 @@ async fn thread_resume_rejects_archived_session_by_id() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -1185,14 +1184,13 @@ async fn thread_resume_keeps_paused_goal_paused() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.2-codex".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1295,14 +1293,13 @@ async fn thread_goal_set_preserves_budget_limited_same_objective() -> Result<()>
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.2-codex".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1399,14 +1396,13 @@ async fn thread_goal_set_persists_resumable_stopped_statuses() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.2-codex".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1499,7 +1495,6 @@ async fn thread_goal_set_edits_objective_without_resetting_usage() -> Result<()>
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -1616,14 +1611,13 @@ async fn thread_goal_lifecycle_emits_analytics_and_clear_deletes_goal() -> Resul
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT.saturating_mul(2), mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.2-codex".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1806,7 +1800,6 @@ async fn thread_resume_emits_restored_token_usage_before_next_turn() -> Result<(
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -1863,7 +1856,6 @@ async fn thread_resume_skips_restored_token_usage_when_turns_are_excluded() -> R
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -1975,7 +1967,6 @@ async fn thread_resume_token_usage_replay_ignores_stale_interrupted_tail_turn()
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -2103,7 +2094,6 @@ async fn thread_resume_token_usage_replay_can_belong_to_interrupted_turn() -> Re
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -2301,7 +2291,6 @@ stream_max_retries = 0
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -2399,7 +2388,6 @@ async fn thread_resume_and_read_interrupt_incomplete_rollout_turn_when_thread_is
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -2477,7 +2465,6 @@ async fn thread_resume_defers_updated_at_until_turn_start() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -2603,13 +2590,12 @@ async fn thread_resume_keeps_in_flight_turn_streaming() -> Result<()> {
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -2646,7 +2632,6 @@ async fn thread_resume_keeps_in_flight_turn_streaming() -> Result<()> {
|
||||
|
||||
let mut secondary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, secondary.initialize()).await??;
|
||||
@@ -2720,13 +2705,12 @@ async fn thread_resume_rejects_history_when_thread_is_running() -> Result<()> {
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -2843,13 +2827,12 @@ async fn thread_resume_rejects_mismatched_path_for_running_thread_id() -> Result
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -3016,13 +2999,12 @@ async fn thread_resume_rejoins_running_thread_even_with_override_mismatch() -> R
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -3151,13 +3133,12 @@ async fn thread_resume_can_skip_turns_when_thread_is_running() -> Result<()> {
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -3193,7 +3174,6 @@ async fn thread_resume_can_skip_turns_when_thread_is_running() -> Result<()> {
|
||||
|
||||
let mut secondary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, secondary.initialize()).await??;
|
||||
@@ -3223,6 +3203,12 @@ async fn thread_resume_can_skip_turns_when_thread_is_running() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_resume_replays_pending_command_execution_request_approval() -> Result<()> {
|
||||
// TODO(anp): Remove after shell approval replay can route target-native cwd across host OSes.
|
||||
skip_if_wine_exec!(
|
||||
Ok(()),
|
||||
"shell approval replay rejects the Windows cwd on the Linux host"
|
||||
);
|
||||
|
||||
let responses = vec![
|
||||
create_final_assistant_message_sse_response("seeded")?,
|
||||
create_shell_command_sse_response(
|
||||
@@ -3243,13 +3229,12 @@ async fn thread_resume_replays_pending_command_execution_request_approval() -> R
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -3365,6 +3350,12 @@ async fn thread_resume_replays_pending_command_execution_request_approval() -> R
|
||||
|
||||
#[tokio::test]
|
||||
async fn thread_resume_replays_pending_file_change_request_approval() -> Result<()> {
|
||||
// TODO(anp): Remove after apply-patch approval fixtures use a target-native workspace.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"apply-patch approval fixture is only materialized on the host"
|
||||
);
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
let codex_home = tmp.path().join("codex_home");
|
||||
std::fs::create_dir(&codex_home)?;
|
||||
@@ -3386,13 +3377,12 @@ async fn thread_resume_replays_pending_file_change_request_approval() -> Result<
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -3611,7 +3601,6 @@ async fn thread_resume_fails_when_required_mcp_server_fails_to_initialize() -> R
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -3694,7 +3683,6 @@ async fn thread_resume_surfaces_cloud_config_bundle_load_errors() -> Result<()>
|
||||
let refresh_token_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[
|
||||
("OPENAI_API_KEY", None),
|
||||
(
|
||||
@@ -3789,7 +3777,6 @@ async fn thread_resume_can_load_source_by_external_path() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -3883,13 +3870,12 @@ async fn start_materialized_thread_and_restart(
|
||||
) -> Result<RestartedThreadFixture> {
|
||||
let mut first_mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, first_mcp.initialize()).await??;
|
||||
|
||||
let start_id = first_mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.4".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -3946,7 +3932,6 @@ async fn start_materialized_thread_and_restart(
|
||||
|
||||
let mut second_mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, second_mcp.initialize()).await??;
|
||||
@@ -3981,13 +3966,12 @@ async fn thread_resume_accepts_personality_override() -> Result<()> {
|
||||
|
||||
let mut primary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, primary.initialize()).await??;
|
||||
|
||||
let start_id = primary
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("gpt-5.3-codex".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -4023,7 +4007,6 @@ async fn thread_resume_accepts_personality_override() -> Result<()> {
|
||||
|
||||
let mut secondary = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, secondary.initialize()).await??;
|
||||
|
||||
@@ -46,7 +46,6 @@ async fn thread_settings_update_emits_notification_and_updates_future_turns() ->
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -113,7 +112,6 @@ async fn thread_settings_update_cwd_retargets_default_environment() -> Result<()
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -167,7 +165,6 @@ async fn thread_settings_update_while_turn_is_active_emits_notification() -> Res
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -214,7 +211,6 @@ async fn thread_settings_update_null_service_tier_uses_default() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -284,7 +280,6 @@ async fn thread_settings_update_rejects_sandbox_policy_with_permissions() -> Res
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -322,7 +317,6 @@ async fn turn_start_settings_override_emits_thread_settings_updated() -> Result<
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -402,7 +396,7 @@ async fn start_text_turn(mcp: &mut TestAppServer, thread_id: String) -> Result<(
|
||||
|
||||
async fn start_thread(mcp: &mut TestAppServer) -> Result<ThreadStartResponse> {
|
||||
let request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -62,6 +62,7 @@ async fn thread_shell_command_history_responses_exclude_persisted_command_execut
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.as_path())
|
||||
// thread/shellCommand intentionally executes on the app-server host.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -199,6 +200,7 @@ async fn thread_shell_command_returns_error_when_local_environment_is_disabled()
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.as_path())
|
||||
// This test intentionally exercises thread/shellCommand without a local host environment.
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[(CODEX_EXEC_SERVER_URL_ENV_VAR, Some("none"))])
|
||||
.build()
|
||||
@@ -259,6 +261,7 @@ async fn thread_shell_command_uses_existing_active_turn() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.as_path())
|
||||
// thread/shellCommand intentionally joins the app-server's host-local active turn.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
@@ -525,13 +525,12 @@ async fn thread_start_accepts_absolute_runtime_workspace_roots() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(cwd.to_string_lossy().to_string()),
|
||||
runtime_workspace_roots: Some(vec![extra_root.abs()]),
|
||||
..Default::default()
|
||||
@@ -570,13 +569,12 @@ async fn thread_start_excludes_profile_workspace_roots_from_runtime_workspace_ro
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(cwd.path().to_string_lossy().to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -609,7 +607,6 @@ async fn thread_start_rejects_unknown_environment_as_invalid_request() -> Result
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -648,15 +645,15 @@ async fn thread_start_rejects_relative_environment_cwd_as_invalid_request() -> R
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let environment_id = mcp.auto_env_params()?.environment_id;
|
||||
|
||||
let request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
environments: Some(vec![TurnEnvironmentParams {
|
||||
environment_id: "local".to_string(),
|
||||
environment_id: environment_id.clone(),
|
||||
cwd: serde_json::from_value(json!("relative"))?,
|
||||
}]),
|
||||
..Default::default()
|
||||
@@ -672,7 +669,9 @@ async fn thread_start_rejects_relative_environment_cwd_as_invalid_request() -> R
|
||||
assert_eq!(error.error.code, INVALID_REQUEST_ERROR_CODE);
|
||||
assert_eq!(
|
||||
error.error.message,
|
||||
"invalid cwd for environment `local`: path `relative` does not use absolute POSIX or Windows path syntax"
|
||||
format!(
|
||||
"invalid cwd for environment `{environment_id}`: path `relative` does not use absolute POSIX or Windows path syntax"
|
||||
)
|
||||
);
|
||||
|
||||
Ok(())
|
||||
@@ -691,6 +690,7 @@ async fn thread_start_response_includes_loaded_instruction_sources() -> Result<(
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
// TODO(anp): Move the instruction-source fixture into the auto environment cwd.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -742,6 +742,7 @@ async fn thread_start_response_excludes_empty_project_instruction_source() -> Re
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
// TODO(anp): Move the instruction-source fixture into the auto environment cwd.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -789,7 +790,6 @@ async fn thread_start_without_selected_environment_includes_only_global_instruct
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
@@ -883,14 +883,13 @@ async fn thread_start_tracks_thread_initialized_analytics() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
thread_source: Some(ThreadSource::User),
|
||||
service_name: Some("codex_work_desktop".to_string()),
|
||||
..Default::default()
|
||||
@@ -938,13 +937,12 @@ model_reasoning_effort = "high"
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1294,7 +1292,6 @@ async fn thread_start_surfaces_cloud_config_bundle_load_errors() -> Result<()> {
|
||||
let refresh_token_url = format!("{}/oauth/token", server.uri());
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[
|
||||
("OPENAI_API_KEY", None),
|
||||
(
|
||||
@@ -1307,7 +1304,7 @@ async fn thread_start_surfaces_cloud_config_bundle_load_errors() -> Result<()> {
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
|
||||
let err: JSONRPCError = timeout(
|
||||
@@ -1355,13 +1352,12 @@ model_reasoning_effort = "high"
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let first_request = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().display().to_string()),
|
||||
sandbox: Some(SandboxMode::WorkspaceWrite),
|
||||
..Default::default()
|
||||
@@ -1374,7 +1370,7 @@ model_reasoning_effort = "high"
|
||||
.await??;
|
||||
|
||||
let second_request = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().display().to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1419,13 +1415,12 @@ async fn thread_start_with_nested_git_cwd_trusts_repo_root() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(nested.display().to_string()),
|
||||
sandbox: Some(SandboxMode::WorkspaceWrite),
|
||||
..Default::default()
|
||||
@@ -1461,13 +1456,12 @@ async fn thread_start_with_read_only_sandbox_does_not_persist_project_trust() ->
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().display().to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1503,13 +1497,12 @@ async fn thread_start_preserves_untrusted_project_trust() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().display().to_string()),
|
||||
sandbox: Some(SandboxMode::WorkspaceWrite),
|
||||
..Default::default()
|
||||
@@ -1548,13 +1541,12 @@ model_reasoning_effort = "high"
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let request_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().display().to_string()),
|
||||
sandbox: Some(SandboxMode::WorkspaceWrite),
|
||||
..Default::default()
|
||||
|
||||
@@ -30,14 +30,13 @@ async fn thread_status_changed_emits_runtime_updates() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("RUST_LOG", Some("info"))])
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -44,12 +44,23 @@ async fn thread_unsubscribe_keeps_thread_loaded_until_idle_timeout() -> Result<(
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(thread_req)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(thread_resp)?;
|
||||
let thread_id = thread.id;
|
||||
|
||||
let unsubscribe_id = mcp
|
||||
.send_thread_unsubscribe_request(ThreadUnsubscribeParams {
|
||||
@@ -99,8 +110,6 @@ async fn thread_unsubscribe_during_turn_keeps_turn_running() -> Result<()> {
|
||||
let tmp = TempDir::new()?;
|
||||
let codex_home = tmp.path().join("codex_home");
|
||||
std::fs::create_dir(&codex_home)?;
|
||||
let working_directory = tmp.path().join("workdir");
|
||||
std::fs::create_dir(&working_directory)?;
|
||||
|
||||
let (server, mut completions) = start_streaming_sse_server(vec![
|
||||
vec![StreamingSseChunk {
|
||||
@@ -127,13 +136,12 @@ async fn thread_unsubscribe_during_turn_keeps_turn_running() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
dynamic_tools: Some(vec![DynamicToolSpec::Function(DynamicToolFunctionSpec {
|
||||
name: tool_name.to_string(),
|
||||
@@ -164,7 +172,6 @@ async fn thread_unsubscribe_during_turn_keeps_turn_running() -> Result<()> {
|
||||
text: "run deterministic tool".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
cwd: Some(working_directory),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
@@ -263,12 +270,23 @@ async fn thread_unsubscribe_preserves_cached_status_before_idle_unload() -> Resu
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(thread_req)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(thread_resp)?;
|
||||
let thread_id = thread.id;
|
||||
|
||||
let turn_req = mcp
|
||||
.send_turn_start_request(TurnStartParams {
|
||||
@@ -354,12 +372,23 @@ async fn thread_unsubscribe_reports_not_subscribed_before_idle_unload() -> Resul
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_id = start_thread(&mut mcp).await?;
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(thread_req)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(thread_resp)?;
|
||||
let thread_id = thread.id;
|
||||
|
||||
let first_unsubscribe_id = mcp
|
||||
.send_thread_unsubscribe_request(ThreadUnsubscribeParams {
|
||||
@@ -434,19 +463,3 @@ stream_max_retries = 0
|
||||
),
|
||||
)
|
||||
}
|
||||
|
||||
async fn start_thread(mcp: &mut TestAppServer) -> Result<String> {
|
||||
let req_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
let resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
mcp.read_stream_until_response_message(RequestId::Integer(req_id)),
|
||||
)
|
||||
.await??;
|
||||
let ThreadStartResponse { thread, .. } = to_response::<ThreadStartResponse>(resp)?;
|
||||
Ok(thread.id)
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ use codex_app_server_protocol::TurnStartParams;
|
||||
use codex_app_server_protocol::TurnStartResponse;
|
||||
use codex_app_server_protocol::TurnStatus;
|
||||
use codex_app_server_protocol::UserInput as V2UserInput;
|
||||
use core_test_support::skip_if_remote;
|
||||
use tempfile::TempDir;
|
||||
use tokio::time::timeout;
|
||||
|
||||
@@ -30,6 +31,12 @@ const INVALID_REQUEST_ERROR_CODE: i64 = -32600;
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_interrupt_aborts_running_turn() -> Result<()> {
|
||||
// TODO(anp): Remove after the long-running command fixture can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"uses a host-local command and cwd fixture unavailable to remote executors"
|
||||
);
|
||||
|
||||
// Use a portable sleep command to keep the turn running.
|
||||
#[cfg(target_os = "windows")]
|
||||
let shell_command = vec![
|
||||
@@ -59,14 +66,13 @@ async fn turn_interrupt_aborts_running_turn() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// Start a v2 thread and capture its id.
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -215,6 +221,12 @@ async fn turn_interrupt_rejects_completed_turn() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_interrupt_resolves_pending_command_approval_request() -> Result<()> {
|
||||
// TODO(anp): Remove after the approval command fixture can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"uses a host-local command and cwd fixture unavailable to remote executors"
|
||||
);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let shell_command = vec![
|
||||
"powershell".to_string(),
|
||||
@@ -245,13 +257,12 @@ async fn turn_interrupt_resolves_pending_command_approval_request() -> Result<()
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -80,6 +80,8 @@ use codex_protocol::user_input::MAX_USER_INPUT_TEXT_CHARS;
|
||||
use codex_utils_absolute_path::test_support::PathExt;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::skip_if_no_network;
|
||||
use core_test_support::skip_if_remote;
|
||||
use core_test_support::skip_if_wine_exec;
|
||||
use pretty_assertions::assert_eq;
|
||||
use serde_json::Value;
|
||||
use serde_json::json;
|
||||
@@ -618,7 +620,6 @@ async fn turn_start_emits_thread_scoped_warning_notification_for_trimmed_skills(
|
||||
let isolated_home = codex_home.path().to_string_lossy();
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[
|
||||
("HOME", Some(isolated_home.as_ref())),
|
||||
("USERPROFILE", Some(isolated_home.as_ref())),
|
||||
@@ -628,7 +629,7 @@ async fn turn_start_emits_thread_scoped_warning_notification_for_trimmed_skills(
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -891,14 +892,13 @@ async fn turn_start_tracks_thread_originator_in_analytics() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
thread_source: Some(ThreadSource::User),
|
||||
service_name: Some("codex_work_desktop".to_string()),
|
||||
@@ -1021,14 +1021,13 @@ async fn turn_profile_tracks_blocking_tool_and_follow_up_sampling() -> Result<()
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -1348,13 +1347,12 @@ async fn turn_start_rejects_unknown_environment_before_starting_turn() -> Result
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -2214,6 +2212,11 @@ async fn turn_start_forwards_custom_local_image_detail() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_exec_approval_toggle_v2() -> Result<()> {
|
||||
// TODO(anp): Remove after shell-command approval routing supports target-native Windows cwd.
|
||||
skip_if_wine_exec!(
|
||||
Ok(()),
|
||||
"shell-command approval routing requires a host-native cwd under Wine-exec"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -2256,14 +2259,14 @@ async fn turn_start_exec_approval_toggle_v2() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.as_path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
let expected_environment_id = mcp.auto_env_params()?.environment_id;
|
||||
|
||||
// thread/start
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -2304,7 +2307,10 @@ async fn turn_start_exec_approval_toggle_v2() -> Result<()> {
|
||||
panic!("expected CommandExecutionRequestApproval request");
|
||||
};
|
||||
assert_eq!(params.item_id, "call1");
|
||||
assert_eq!(params.environment_id.as_deref(), Some("local"));
|
||||
assert_eq!(
|
||||
params.environment_id.as_deref(),
|
||||
Some(expected_environment_id.as_str())
|
||||
);
|
||||
let resolved_request_id = request_id.clone();
|
||||
|
||||
// Approve and wait for task completion
|
||||
@@ -2376,12 +2382,15 @@ async fn turn_start_exec_approval_toggle_v2() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_exec_approval_decline_v2() -> Result<()> {
|
||||
// TODO(anp): Remove after command approval routing accepts target-native Windows cwd.
|
||||
skip_if_wine_exec!(
|
||||
Ok(()),
|
||||
"command approval routing rejects the selected Windows cwd on the Linux host"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
let codex_home = tmp.path().to_path_buf();
|
||||
let workspace = tmp.path().join("workspace");
|
||||
std::fs::create_dir(&workspace)?;
|
||||
|
||||
let responses = vec![
|
||||
create_shell_command_sse_response(
|
||||
@@ -2406,13 +2415,12 @@ async fn turn_start_exec_approval_decline_v2() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.as_path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -2432,7 +2440,6 @@ async fn turn_start_exec_approval_decline_v2() -> Result<()> {
|
||||
text: "run python".to_string(),
|
||||
text_elements: Vec::new(),
|
||||
}],
|
||||
cwd: Some(workspace.clone()),
|
||||
..Default::default()
|
||||
})
|
||||
.await?;
|
||||
@@ -2525,6 +2532,8 @@ async fn turn_start_exec_approval_decline_v2() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
|
||||
// TODO(anp): Materialize cwd and shell-display fixtures in the selected remote environment.
|
||||
skip_if_remote!(Ok(()), "cwd fixtures are only materialized on the host");
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -2563,14 +2572,13 @@ async fn turn_start_updates_sandbox_and_cwd_between_turns_v2() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
// thread/start
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -2761,13 +2769,12 @@ stream_max_retries = 0
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -2876,6 +2883,8 @@ url = "ws://127.0.0.1:1"
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
// This test owns environments.toml and explicitly compares local selections
|
||||
// with a configured remote environment, so auto env would change its subject.
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
@@ -3008,6 +3017,11 @@ fn environment_params(ids: Option<&[&str]>, cwd: &Path) -> Option<Vec<TurnEnviro
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_file_change_approval_v2() -> Result<()> {
|
||||
// TODO(anp): Materialize apply-patch workspaces in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"apply-patch workspace fixture is only materialized on the host"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -3035,13 +3049,12 @@ async fn turn_start_file_change_approval_v2() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -3181,6 +3194,11 @@ async fn turn_start_file_change_approval_v2() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_does_not_stream_apply_patch_change_updates_without_feature_v2() -> Result<()> {
|
||||
// TODO(anp): Materialize apply-patch workspaces in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"apply-patch workspace fixture is only materialized on the host"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -3230,13 +3248,12 @@ async fn turn_start_does_not_stream_apply_patch_change_updates_without_feature_v
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -3283,6 +3300,11 @@ async fn turn_start_does_not_stream_apply_patch_change_updates_without_feature_v
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_streams_apply_patch_change_updates_v2() -> Result<()> {
|
||||
// TODO(anp): Materialize apply-patch workspaces in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"apply-patch workspace fixture is only materialized on the host"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -3372,13 +3394,12 @@ async fn turn_start_streams_apply_patch_change_updates_v2() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -4020,6 +4041,11 @@ config_file = "./custom-role.toml"
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_file_change_approval_accept_for_session_persists_v2() -> Result<()> {
|
||||
// TODO(anp): Materialize apply-patch workspaces in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"apply-patch workspace fixture is only materialized on the host"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -4057,13 +4083,12 @@ async fn turn_start_file_change_approval_accept_for_session_persists_v2() -> Res
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -4207,6 +4232,11 @@ async fn turn_start_file_change_approval_accept_for_session_persists_v2() -> Res
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_file_change_approval_decline_v2() -> Result<()> {
|
||||
// TODO(anp): Materialize apply-patch workspaces in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"apply-patch workspace fixture is only materialized on the host"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -4234,13 +4264,12 @@ async fn turn_start_file_change_approval_decline_v2() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -4367,6 +4396,11 @@ async fn turn_start_file_change_approval_decline_v2() -> Result<()> {
|
||||
#[tokio::test]
|
||||
#[cfg_attr(windows, ignore = "process id reporting differs on Windows")]
|
||||
async fn command_execution_notifications_include_process_id() -> Result<()> {
|
||||
// TODO(anp): Add target-Windows process-id expectations for remote executors.
|
||||
skip_if_wine_exec!(
|
||||
Ok(()),
|
||||
"process id reporting differs for a Windows executor"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let responses = vec![
|
||||
@@ -4385,13 +4419,12 @@ async fn command_execution_notifications_include_process_id() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -4523,13 +4556,12 @@ async fn turn_start_with_elevated_override_does_not_persist_project_trust() -> R
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_request = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
cwd: Some(workspace.path().display().to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -34,6 +34,7 @@ use codex_features::FEATURES;
|
||||
use codex_features::Feature;
|
||||
use core_test_support::responses;
|
||||
use core_test_support::skip_if_no_network;
|
||||
use core_test_support::skip_if_remote;
|
||||
use pretty_assertions::assert_eq;
|
||||
use std::collections::BTreeMap;
|
||||
use std::path::Path;
|
||||
@@ -48,6 +49,11 @@ const DEFAULT_READ_TIMEOUT: std::time::Duration = std::time::Duration::from_secs
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_shell_zsh_fork_executes_command_v2() -> Result<()> {
|
||||
// TODO(anp): Remove after zsh-fork fixtures can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"zsh-fork fixtures use host-local zsh and workspace paths"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -101,7 +107,7 @@ async fn turn_start_shell_zsh_fork_executes_command_v2() -> Result<()> {
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -177,6 +183,11 @@ async fn turn_start_shell_zsh_fork_executes_command_v2() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_shell_zsh_fork_exec_approval_decline_v2() -> Result<()> {
|
||||
// TODO(anp): Remove after zsh-fork fixtures can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"zsh-fork fixtures use host-local zsh and workspace paths"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -220,7 +231,7 @@ async fn turn_start_shell_zsh_fork_exec_approval_decline_v2() -> Result<()> {
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -313,6 +324,11 @@ async fn turn_start_shell_zsh_fork_exec_approval_decline_v2() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_shell_zsh_fork_exec_approval_cancel_v2() -> Result<()> {
|
||||
// TODO(anp): Remove after zsh-fork fixtures can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"zsh-fork fixtures use host-local zsh and workspace paths"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -353,7 +369,7 @@ async fn turn_start_shell_zsh_fork_exec_approval_cancel_v2() -> Result<()> {
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -444,6 +460,11 @@ async fn turn_start_shell_zsh_fork_exec_approval_cancel_v2() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2() -> Result<()> {
|
||||
// TODO(anp): Remove after zsh-fork fixtures can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"zsh-fork fixtures use host-local zsh and workspace paths"
|
||||
);
|
||||
skip_if_no_network!(Ok(()));
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
@@ -512,7 +533,7 @@ async fn turn_start_shell_zsh_fork_subcommand_decline_marks_parent_declined_v2()
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let start_id = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
cwd: Some(workspace.to_string_lossy().into_owned()),
|
||||
..Default::default()
|
||||
@@ -748,7 +769,6 @@ async fn create_zsh_test_mcp_process(
|
||||
let zdotdir = zdotdir.to_string_lossy().into_owned();
|
||||
TestAppServer::builder()
|
||||
.with_codex_home(codex_home)
|
||||
.without_auto_env()
|
||||
.with_program(&app_server)
|
||||
.with_env_overrides(&[("ZDOTDIR", Some(zdotdir.as_str()))])
|
||||
.build()
|
||||
|
||||
@@ -26,6 +26,7 @@ use codex_app_server_protocol::TurnSteerParams;
|
||||
use codex_app_server_protocol::TurnSteerResponse;
|
||||
use codex_app_server_protocol::UserInput as V2UserInput;
|
||||
use codex_protocol::user_input::MAX_USER_INPUT_TEXT_CHARS;
|
||||
use core_test_support::skip_if_remote;
|
||||
use serde_json::Value;
|
||||
use std::collections::HashMap;
|
||||
use tempfile::TempDir;
|
||||
@@ -52,14 +53,13 @@ async fn turn_steer_requires_active_turn() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -111,6 +111,12 @@ async fn turn_steer_requires_active_turn() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_steer_rejects_oversized_text_input() -> Result<()> {
|
||||
// TODO(anp): Remove after the active-turn fixture can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"uses a host-local command and cwd fixture unavailable to remote executors"
|
||||
);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let shell_command = vec![
|
||||
"powershell".to_string(),
|
||||
@@ -143,14 +149,13 @@ async fn turn_steer_rejects_oversized_text_input() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -228,6 +233,12 @@ async fn turn_steer_rejects_oversized_text_input() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_steer_returns_active_turn_id() -> Result<()> {
|
||||
// TODO(anp): Remove after the active-turn fixture can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"uses a host-local command and cwd fixture unavailable to remote executors"
|
||||
);
|
||||
|
||||
#[cfg(target_os = "windows")]
|
||||
let shell_command = vec![
|
||||
"powershell".to_string(),
|
||||
@@ -262,14 +273,13 @@ async fn turn_steer_returns_active_turn_id() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
@@ -379,6 +389,12 @@ async fn turn_steer_returns_active_turn_id() -> Result<()> {
|
||||
|
||||
#[tokio::test]
|
||||
async fn turn_steer_rejects_context_only_input_without_merging_context() -> Result<()> {
|
||||
// TODO(anp): Remove after the active-turn fixture can run in the selected remote environment.
|
||||
skip_if_remote!(
|
||||
Ok(()),
|
||||
"uses a host-local command and cwd fixture unavailable to remote executors"
|
||||
);
|
||||
|
||||
let tmp = TempDir::new()?;
|
||||
let codex_home = tmp.path().join("codex_home");
|
||||
std::fs::create_dir(&codex_home)?;
|
||||
@@ -404,14 +420,13 @@ async fn turn_steer_rejects_context_only_input_without_merging_context() -> Resu
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(&codex_home)
|
||||
.without_auto_env()
|
||||
.without_managed_config()
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams {
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams {
|
||||
model: Some("mock-model".to_string()),
|
||||
..Default::default()
|
||||
})
|
||||
|
||||
@@ -81,14 +81,13 @@ async fn standalone_web_search_round_trips_output() -> Result<()> {
|
||||
|
||||
let mut mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
timeout(DEFAULT_READ_TIMEOUT, mcp.initialize()).await??;
|
||||
|
||||
let thread_req = mcp
|
||||
.send_thread_start_request(ThreadStartParams::default())
|
||||
.send_thread_start_request_with_auto_env(ThreadStartParams::default())
|
||||
.await?;
|
||||
let thread_resp: JSONRPCResponse = timeout(
|
||||
DEFAULT_READ_TIMEOUT,
|
||||
@@ -203,7 +202,6 @@ async fn standalone_web_search_round_trips_output() -> Result<()> {
|
||||
drop(mcp);
|
||||
let mut reloaded_mcp = TestAppServer::builder()
|
||||
.with_codex_home(codex_home.path())
|
||||
.without_auto_env()
|
||||
.with_env_overrides(&[("OPENAI_API_KEY", None)])
|
||||
.build()
|
||||
.await?;
|
||||
|
||||
Reference in New Issue
Block a user