diff --git a/AGENTS.md b/AGENTS.md index 7960ebba9b..aaebd0dfd3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -85,6 +85,7 @@ If you don’t have the tool: - `ResponsesRequest` exposes helpers (`body_json`, `input`, `function_call_output`, `custom_tool_call_output`, `call_output`, `header`, `path`, `query_param`) so assertions can target structured payloads instead of manual JSON digging. - Build SSE payloads with the provided `ev_*` constructors and the `sse(...)`. - Prefer `wait_for_event` over `wait_for_event_with_timeout`. +- Prefer `mount_sse_once` over `mount_sse_once_match` or `mount_sse_sequence` - Typical pattern: diff --git a/codex-rs/core/tests/common/responses.rs b/codex-rs/core/tests/common/responses.rs index 7a60cbe83c..2c88dd8ff5 100644 --- a/codex-rs/core/tests/common/responses.rs +++ b/codex-rs/core/tests/common/responses.rs @@ -10,7 +10,6 @@ use wiremock::MockBuilder; use wiremock::MockServer; use wiremock::Respond; use wiremock::ResponseTemplate; -use wiremock::matchers::any; use wiremock::matchers::method; use wiremock::matchers::path_regex; @@ -546,13 +545,13 @@ pub async fn mount_function_call_agent_response( ev_function_call(call_id, tool_name, arguments), ev_completed("resp-1"), ]); - let function_call = mount_sse_once_match(server, any(), first_response).await; + let function_call = mount_sse_once(server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "done"), ev_completed("resp-2"), ]); - let completion = mount_sse_once_match(server, any(), second_response).await; + let completion = mount_sse_once(server, second_response).await; FunctionCallResponseMocks { function_call, diff --git a/codex-rs/core/tests/suite/cli_stream.rs b/codex-rs/core/tests/suite/cli_stream.rs index 64d6247f3d..b484eca22a 100644 --- a/codex-rs/core/tests/suite/cli_stream.rs +++ b/codex-rs/core/tests/suite/cli_stream.rs @@ -110,12 +110,7 @@ async fn exec_cli_applies_experimental_instructions_file() { "data: {\"type\":\"response.created\",\"response\":{}}\n\n", "data: {\"type\":\"response.completed\",\"response\":{\"id\":\"r1\"}}\n\n" ); - let resp_mock = core_test_support::responses::mount_sse_once_match( - &server, - path("/v1/responses"), - sse.to_string(), - ) - .await; + let resp_mock = core_test_support::responses::mount_sse_once(&server, sse.to_string()).await; // Create a temporary instructions file with a unique marker we can assert // appears in the outbound request payload. diff --git a/codex-rs/core/tests/suite/client.rs b/codex-rs/core/tests/suite/client.rs index 8c740e6333..79c158e084 100644 --- a/codex-rs/core/tests/suite/client.rs +++ b/codex-rs/core/tests/suite/client.rs @@ -238,9 +238,7 @@ async fn resume_includes_initial_messages_and_sends_prior_items() { // Mock server that will receive the resumed request let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; // Configure Codex to resume from our file let model_provider = ModelProviderInfo { @@ -381,9 +379,7 @@ async fn includes_base_instructions_override_in_request() { skip_if_no_network!(); // Mock server let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let model_provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), @@ -571,9 +567,7 @@ async fn includes_user_instructions_message_in_request() { skip_if_no_network!(); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let model_provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), @@ -631,9 +625,7 @@ async fn includes_configured_effort_in_request() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let TestCodex { codex, .. } = test_codex() .with_model("gpt-5.1-codex") .with_config(|config| { @@ -672,9 +664,7 @@ async fn includes_no_effort_in_request() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let TestCodex { codex, .. } = test_codex() .with_model("gpt-5.1-codex") .build(&server) @@ -711,9 +701,7 @@ async fn includes_default_reasoning_effort_in_request_when_defined_by_model_fami skip_if_no_network!(Ok(())); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let TestCodex { codex, .. } = test_codex().with_model("gpt-5.1").build(&server).await?; codex @@ -746,9 +734,7 @@ async fn includes_default_verbosity_in_request() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let TestCodex { codex, .. } = test_codex().with_model("gpt-5.1").build(&server).await?; codex @@ -781,9 +767,7 @@ async fn configured_verbosity_not_sent_for_models_without_support() -> anyhow::R skip_if_no_network!(Ok(())); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let TestCodex { codex, .. } = test_codex() .with_model("gpt-5-codex") .with_config(|config| { @@ -821,9 +805,7 @@ async fn configured_verbosity_is_sent() -> anyhow::Result<()> { skip_if_no_network!(Ok(())); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let TestCodex { codex, .. } = test_codex() .with_model("gpt-5") .with_config(|config| { @@ -862,9 +844,7 @@ async fn includes_developer_instructions_message_in_request() { skip_if_no_network!(); let server = MockServer::start().await; - let resp_mock = - responses::mount_sse_once_match(&server, path("/v1/responses"), sse_completed("resp1")) - .await; + let resp_mock = responses::mount_sse_once(&server, sse_completed("resp1")).await; let model_provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), diff --git a/codex-rs/core/tests/suite/items.rs b/codex-rs/core/tests/suite/items.rs index 7a96522090..4ec23e9de6 100644 --- a/codex-rs/core/tests/suite/items.rs +++ b/codex-rs/core/tests/suite/items.rs @@ -18,7 +18,7 @@ use core_test_support::responses::ev_reasoning_text_delta; use core_test_support::responses::ev_response_created; use core_test_support::responses::ev_web_search_call_added; use core_test_support::responses::ev_web_search_call_done; -use core_test_support::responses::mount_sse_once_match; +use core_test_support::responses::mount_sse_once; use core_test_support::responses::sse; use core_test_support::responses::start_mock_server; use core_test_support::skip_if_no_network; @@ -26,7 +26,6 @@ use core_test_support::test_codex::TestCodex; use core_test_support::test_codex::test_codex; use core_test_support::wait_for_event_match; use pretty_assertions::assert_eq; -use wiremock::matchers::any; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn user_message_item_is_emitted() -> anyhow::Result<()> { @@ -37,7 +36,7 @@ async fn user_message_item_is_emitted() -> anyhow::Result<()> { let TestCodex { codex, .. } = test_codex().build(&server).await?; let first_response = sse(vec![ev_response_created("resp-1"), ev_completed("resp-1")]); - mount_sse_once_match(&server, any(), first_response).await; + mount_sse_once(&server, first_response).await; codex .submit(Op::UserInput { @@ -93,7 +92,7 @@ async fn assistant_message_item_is_emitted() -> anyhow::Result<()> { ev_assistant_message("msg-1", "all done"), ev_completed("resp-1"), ]); - mount_sse_once_match(&server, any(), first_response).await; + mount_sse_once(&server, first_response).await; codex .submit(Op::UserInput { @@ -149,7 +148,7 @@ async fn reasoning_item_is_emitted() -> anyhow::Result<()> { reasoning_item, ev_completed("resp-1"), ]); - mount_sse_once_match(&server, any(), first_response).await; + mount_sse_once(&server, first_response).await; codex .submit(Op::UserInput { @@ -207,7 +206,7 @@ async fn web_search_item_is_emitted() -> anyhow::Result<()> { web_search_done, ev_completed("resp-1"), ]); - mount_sse_once_match(&server, any(), first_response).await; + mount_sse_once(&server, first_response).await; codex .submit(Op::UserInput { @@ -259,7 +258,7 @@ async fn agent_message_content_delta_has_item_metadata() -> anyhow::Result<()> { ev_assistant_message("msg-1", "streamed response"), ev_completed("resp-1"), ]); - mount_sse_once_match(&server, any(), stream).await; + mount_sse_once(&server, stream).await; codex .submit(Op::UserInput { @@ -324,7 +323,7 @@ async fn reasoning_content_delta_has_item_metadata() -> anyhow::Result<()> { ev_reasoning_item("reasoning-1", &["step one"], &[]), ev_completed("resp-1"), ]); - mount_sse_once_match(&server, any(), stream).await; + mount_sse_once(&server, stream).await; codex .submit(Op::UserInput { @@ -381,7 +380,7 @@ async fn reasoning_raw_content_delta_respects_flag() -> anyhow::Result<()> { ev_reasoning_item("reasoning-raw", &["complete"], &["raw detail"]), ev_completed("resp-1"), ]); - mount_sse_once_match(&server, any(), stream).await; + mount_sse_once(&server, stream).await; codex .submit(Op::UserInput { diff --git a/codex-rs/core/tests/suite/model_tools.rs b/codex-rs/core/tests/suite/model_tools.rs index b98d64328e..42bc655f57 100644 --- a/codex-rs/core/tests/suite/model_tools.rs +++ b/codex-rs/core/tests/suite/model_tools.rs @@ -42,7 +42,7 @@ async fn collect_tool_identifiers_for_model(model: &str) -> Vec { let server = MockServer::start().await; let sse = sse_completed(model); - let resp_mock = responses::mount_sse_once_match(&server, wiremock::matchers::any(), sse).await; + let resp_mock = responses::mount_sse_once(&server, sse).await; let model_provider = ModelProviderInfo { base_url: Some(format!("{}/v1", server.uri())), diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index 813226873c..0d0f52b47a 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -13,7 +13,7 @@ use codex_core::shell::Shell; use codex_core::shell::default_user_shell; use codex_protocol::user_input::UserInput; use core_test_support::load_sse_fixture_with_id; -use core_test_support::responses::mount_sse_once_match; +use core_test_support::responses::mount_sse_once; use core_test_support::responses::start_mock_server; use core_test_support::skip_if_no_network; use core_test_support::test_codex::TestCodex; @@ -21,7 +21,6 @@ use core_test_support::test_codex::test_codex; use core_test_support::wait_for_event; use std::collections::HashMap; use tempfile::TempDir; -use wiremock::matchers::any; fn text_user_input(text: String) -> serde_json::Value { serde_json::json!({ @@ -70,8 +69,8 @@ async fn codex_mini_latest_tools() -> anyhow::Result<()> { use pretty_assertions::assert_eq; let server = start_mock_server().await; - let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await; - let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await; + let req1 = mount_sse_once(&server, sse_completed("resp-1")).await; + let req2 = mount_sse_once(&server, sse_completed("resp-2")).await; let TestCodex { codex, .. } = test_codex() .with_config(|config| { @@ -128,8 +127,8 @@ async fn prompt_tools_are_consistent_across_requests() -> anyhow::Result<()> { use pretty_assertions::assert_eq; let server = start_mock_server().await; - let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await; - let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await; + let req1 = mount_sse_once(&server, sse_completed("resp-1")).await; + let req2 = mount_sse_once(&server, sse_completed("resp-2")).await; let TestCodex { codex, config, .. } = test_codex() .with_config(|config| { @@ -247,8 +246,8 @@ async fn prefixes_context_and_instructions_once_and_consistently_across_requests use pretty_assertions::assert_eq; let server = start_mock_server().await; - let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await; - let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await; + let req1 = mount_sse_once(&server, sse_completed("resp-1")).await; + let req2 = mount_sse_once(&server, sse_completed("resp-2")).await; let TestCodex { codex, config, .. } = test_codex() .with_config(|config| { @@ -328,8 +327,8 @@ async fn overrides_turn_context_but_keeps_cached_prefix_and_key_constant() -> an use pretty_assertions::assert_eq; let server = start_mock_server().await; - let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await; - let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await; + let req1 = mount_sse_once(&server, sse_completed("resp-1")).await; + let req2 = mount_sse_once(&server, sse_completed("resp-2")).await; let TestCodex { codex, .. } = test_codex() .with_config(|config| { @@ -427,8 +426,8 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() -> anyhow::Res use pretty_assertions::assert_eq; let server = start_mock_server().await; - let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await; - let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await; + let req1 = mount_sse_once(&server, sse_completed("resp-1")).await; + let req2 = mount_sse_once(&server, sse_completed("resp-2")).await; let TestCodex { codex, .. } = test_codex() .with_config(|config| { @@ -523,8 +522,8 @@ async fn send_user_turn_with_no_changes_does_not_send_environment_context() -> a use pretty_assertions::assert_eq; let server = start_mock_server().await; - let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await; - let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await; + let req1 = mount_sse_once(&server, sse_completed("resp-1")).await; + let req2 = mount_sse_once(&server, sse_completed("resp-2")).await; let TestCodex { codex, config, .. } = test_codex() .with_config(|config| { @@ -611,8 +610,8 @@ async fn send_user_turn_with_changes_sends_environment_context() -> anyhow::Resu let server = start_mock_server().await; - let req1 = mount_sse_once_match(&server, any(), sse_completed("resp-1")).await; - let req2 = mount_sse_once_match(&server, any(), sse_completed("resp-2")).await; + let req1 = mount_sse_once(&server, sse_completed("resp-1")).await; + let req2 = mount_sse_once(&server, sse_completed("resp-2")).await; let TestCodex { codex, config, .. } = test_codex() .with_config(|config| { config.user_instructions = Some("be consistent and helpful".to_string()); diff --git a/codex-rs/core/tests/suite/resume.rs b/codex-rs/core/tests/suite/resume.rs index 3a902b6b6f..bda27533cd 100644 --- a/codex-rs/core/tests/suite/resume.rs +++ b/codex-rs/core/tests/suite/resume.rs @@ -6,14 +6,13 @@ use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_reasoning_item; use core_test_support::responses::ev_response_created; -use core_test_support::responses::mount_sse_once_match; +use core_test_support::responses::mount_sse_once; use core_test_support::responses::sse; use core_test_support::responses::start_mock_server; use core_test_support::skip_if_no_network; use core_test_support::test_codex::test_codex; use core_test_support::wait_for_event; use std::sync::Arc; -use wiremock::matchers::any; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> { @@ -31,7 +30,7 @@ async fn resume_includes_initial_messages_from_rollout_events() -> Result<()> { ev_assistant_message("msg-1", "Completed first turn"), ev_completed("resp-initial"), ]); - mount_sse_once_match(&server, any(), initial_sse).await; + mount_sse_once(&server, initial_sse).await; codex .submit(Op::UserInput { @@ -83,7 +82,7 @@ async fn resume_includes_initial_messages_from_reasoning_events() -> Result<()> ev_assistant_message("msg-1", "Completed reasoning turn"), ev_completed("resp-initial"), ]); - mount_sse_once_match(&server, any(), initial_sse).await; + mount_sse_once(&server, initial_sse).await; codex .submit(Op::UserInput { diff --git a/codex-rs/core/tests/suite/rmcp_client.rs b/codex-rs/core/tests/suite/rmcp_client.rs index 343b506d4c..cc653a9c56 100644 --- a/codex-rs/core/tests/suite/rmcp_client.rs +++ b/codex-rs/core/tests/suite/rmcp_client.rs @@ -21,7 +21,7 @@ use codex_core::protocol::SandboxPolicy; use codex_protocol::config_types::ReasoningSummary; use codex_protocol::user_input::UserInput; use core_test_support::responses; -use core_test_support::responses::mount_sse_once_match; +use core_test_support::responses::mount_sse_once; use core_test_support::skip_if_no_network; use core_test_support::test_codex::test_codex; use core_test_support::wait_for_event; @@ -36,7 +36,6 @@ use tokio::process::Child; use tokio::process::Command; use tokio::time::Instant; use tokio::time::sleep; -use wiremock::matchers::any; static OPENAI_PNG: &str = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAD0AAAA9CAYAAAAeYmHpAAAE6klEQVR4Aeyau44UVxCGx1fZsmRLlm3Zoe0XcGQ5cUiCCIgJeS9CHgAhMkISQnIuGQgJEkBcxLW+nqnZ6uqqc+nuWRC7q/P3qetf9e+MtOwyX25O4Nep6JPyop++0qev9HrfgZ+F6r2DuB/vHOrt/UIkqdDHYvujOW6fO7h/CNEI+a5jc+pBR8uy0jVFsziYu5HtfSUk+Io34q921hLNctFSX0gwww+S8wce8K1LfCU+cYW4888aov8NxqvQILUPPReLOrm6zyLxa4i+6VZuFbJo8d1MOHZm+7VUtB/aIvhPWc/3SWg49JcwFLlHxuXKjtyloo+YNhuW3VS+WPBuUEMvCFKjEDVgFBQHXrnazpqiSxNZCkQ1kYiozsbm9Oz7l4i2Il7vGccGNWAc3XosDrZe/9P3ZnMmzHNEQw4smf8RQ87XEAMsC7Az0Au+dgXerfH4+sHvEc0SYGic8WBBUGqFH2gN7yDrazy7m2pbRTeRmU3+MjZmr1h6LJgPbGy23SI6GlYT0brQ71IY8Us4PNQCm+zepSbaD2BY9xCaAsD9IIj/IzFmKMSdHHonwdZATbTnYREf6/VZGER98N9yCWIvXQwXDoDdhZJoT8jwLnJXDB9w4Sb3e6nK5ndzlkTLnP3JBu4LKkbrYrU69gCVceV0JvpyuW1xlsUVngzhwMetn/XamtTORF9IO5YnWNiyeF9zCAfqR3fUW+vZZKLtgP+ts8BmQRBREAdRDhH3o8QuRh/YucNFz2BEjxbRN6LGzphfKmvP6v6QhqIQyZ8XNJ0W0X83MR1PEcJBNO2KC2Z1TW/v244scp9FwRViZxIOBF0Lctk7ZVSavdLvRlV1hz/ysUi9sr8CIcB3nvWBwA93ykTz18eAYxQ6N/K2DkPA1lv3iXCwmDUT7YkjIby9siXueIJj9H+pzSqJ9oIuJWTUgSSt4WO7o/9GGg0viR4VinNRUDoIj34xoCd6pxD3aK3zfdbnx5v1J3ZNNEJsE0sBG7N27ReDrJc4sFxz7dI/ZAbOmmiKvHBitQXpAdR6+F7v+/ol/tOouUV01EeMZQF2BoQDn6dP4XNr+j9GZEtEK1/L8pFw7bd3a53tsTa7WD+054jOFmPg1XBKPQgnqFfmFcy32ZRvjmiIIQTYFvyDxQ8nH8WIwwGwlyDjDznnilYyFr6njrlZwsKkBpO59A7OwgdzPEWRm+G+oeb7IfyNuzjEEVLrOVxJsxvxwF8kmCM6I2QYmJunz4u4TrADpfl7mlbRTWQ7VmrBzh3+C9f6Grc3YoGN9dg/SXFthpRsT6vobfXRs2VBlgBHXVMLHjDNbIZv1sZ9+X3hB09cXdH1JKViyG0+W9bWZDa/r2f9zAFR71sTzGpMSWz2iI4YssWjWo3REy1MDGjdwe5e0dFSiAC1JakBvu4/CUS8Eh6dqHdU0Or0ioY3W5ClSqDXAy7/6SRfgw8vt4I+tbvvNtFT2kVDhY5+IGb1rCqYaXNF08vSALsXCPmt0kQNqJT1p5eI1mkIV/BxCY1z85lOzeFbPBQHURkkPTlwTYK9gTVE25l84IbFFN+YJDHjdpn0gq6mrHht0dkcjbM4UL9283O5p77GN+SPW/QwVB4IUYg7Or+Kp7naR6qktP98LNF2UxWo9yObPIT9KYg+hK4i56no4rfnM0qeyFf6AwAAAP//trwR3wAAAAZJREFUAwBZ0sR75itw5gAAAABJRU5ErkJggg=="; @@ -51,9 +50,8 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> { let server_name = "rmcp"; let tool_name = format!("mcp__{server_name}__echo"); - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_response_created("resp-1"), responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"), @@ -61,9 +59,8 @@ async fn stdio_server_round_trip() -> anyhow::Result<()> { ]), ) .await; - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_assistant_message("msg-1", "rmcp echo tool completed successfully."), responses::ev_completed("resp-2"), @@ -190,9 +187,8 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> { let tool_name = format!("mcp__{server_name}__image"); // First stream: model decides to call the image tool. - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_response_created("resp-1"), responses::ev_function_call(call_id, &tool_name, "{}"), @@ -201,9 +197,8 @@ async fn stdio_image_responses_round_trip() -> anyhow::Result<()> { ) .await; // Second stream: after tool execution, assistant emits a message and completes. - let final_mock = mount_sse_once_match( + let final_mock = mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_assistant_message("msg-1", "rmcp image tool completed successfully."), responses::ev_completed("resp-2"), @@ -531,9 +526,8 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> { let server_name = "rmcp_whitelist"; let tool_name = format!("mcp__{server_name}__echo"); - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_response_created("resp-1"), responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"), @@ -541,9 +535,8 @@ async fn stdio_server_propagates_whitelisted_env_vars() -> anyhow::Result<()> { ]), ) .await; - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_assistant_message("msg-1", "rmcp echo tool completed successfully."), responses::ev_completed("resp-2"), @@ -666,9 +659,8 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> { let server_name = "rmcp_http"; let tool_name = format!("mcp__{server_name}__echo"); - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_response_created("resp-1"), responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"), @@ -676,9 +668,8 @@ async fn streamable_http_tool_call_round_trip() -> anyhow::Result<()> { ]), ) .await; - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_assistant_message( "msg-1", @@ -834,9 +825,8 @@ async fn streamable_http_with_oauth_round_trip() -> anyhow::Result<()> { let server_name = "rmcp_http_oauth"; let tool_name = format!("mcp__{server_name}__echo"); - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_response_created("resp-1"), responses::ev_function_call(call_id, &tool_name, "{\"message\":\"ping\"}"), @@ -844,9 +834,8 @@ async fn streamable_http_with_oauth_round_trip() -> anyhow::Result<()> { ]), ) .await; - mount_sse_once_match( + mount_sse_once( &server, - any(), responses::sse(vec![ responses::ev_assistant_message( "msg-1", diff --git a/codex-rs/core/tests/suite/tool_harness.rs b/codex-rs/core/tests/suite/tool_harness.rs index 3288822ff3..02c7494cc0 100644 --- a/codex-rs/core/tests/suite/tool_harness.rs +++ b/codex-rs/core/tests/suite/tool_harness.rs @@ -29,7 +29,6 @@ use core_test_support::test_codex::test_codex; use core_test_support::wait_for_event; use serde_json::Value; use serde_json::json; -use wiremock::matchers::any; fn call_output(req: &ResponsesRequest, call_id: &str) -> (String, Option) { let raw = req.function_call_output(call_id); @@ -73,13 +72,13 @@ async fn shell_tool_executes_command_and_streams_output() -> anyhow::Result<()> ev_local_shell_call(call_id, "completed", command), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "all done"), ev_completed("resp-2"), ]); - let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let second_mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); @@ -139,13 +138,13 @@ async fn update_plan_tool_emits_plan_update_event() -> anyhow::Result<()> { ev_function_call(call_id, "update_plan", &plan_args), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "plan acknowledged"), ev_completed("resp-2"), ]); - let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let second_mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); @@ -215,13 +214,13 @@ async fn update_plan_tool_rejects_malformed_payload() -> anyhow::Result<()> { ev_function_call(call_id, "update_plan", &invalid_args), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "malformed plan payload"), ev_completed("resp-2"), ]); - let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let second_mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); @@ -303,13 +302,13 @@ async fn apply_patch_tool_executes_and_emits_patch_events() -> anyhow::Result<() ev_apply_patch_function_call(call_id, &patch_content), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "patch complete"), ev_completed("resp-2"), ]); - let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let second_mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); @@ -399,13 +398,13 @@ async fn apply_patch_reports_parse_diagnostics() -> anyhow::Result<()> { ev_apply_patch_function_call(call_id, patch_content), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "failed"), ev_completed("resp-2"), ]); - let second_mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let second_mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); diff --git a/codex-rs/core/tests/suite/tools.rs b/codex-rs/core/tests/suite/tools.rs index ca844db4c8..a6086dcbfb 100644 --- a/codex-rs/core/tests/suite/tools.rs +++ b/codex-rs/core/tests/suite/tools.rs @@ -472,8 +472,7 @@ time.sleep(60) let start = Instant::now(); let output_str = tokio::time::timeout(Duration::from_secs(10), async { - submit_turn( - &test, + test.submit_turn_with_policies( "run a command with a detached grandchild", AskForApproval::Never, SandboxPolicy::DangerFullAccess, diff --git a/codex-rs/core/tests/suite/truncation.rs b/codex-rs/core/tests/suite/truncation.rs index 101bdc6199..37ee4f3990 100644 --- a/codex-rs/core/tests/suite/truncation.rs +++ b/codex-rs/core/tests/suite/truncation.rs @@ -20,7 +20,6 @@ use core_test_support::responses::ev_completed; use core_test_support::responses::ev_function_call; use core_test_support::responses::ev_response_created; use core_test_support::responses::mount_sse_once; -use core_test_support::responses::mount_sse_once_match; use core_test_support::responses::mount_sse_sequence; use core_test_support::responses::sse; use core_test_support::responses::start_mock_server; @@ -33,7 +32,6 @@ use serde_json::Value; use serde_json::json; use std::collections::HashMap; use std::time::Duration; -use wiremock::matchers::any; // Verifies byte-truncation formatting for function error output (RespondToModel errors) #[tokio::test(flavor = "multi_thread", worker_threads = 2)] @@ -140,9 +138,8 @@ async fn tool_call_output_exceeds_limit_truncated_for_model() -> Result<()> { ]), ) .await; - let mock2 = mount_sse_once_match( + let mock2 = mount_sse_once( &server, - any(), sse(vec![ responses::ev_assistant_message("msg-1", "done"), responses::ev_completed("resp-2"), @@ -222,9 +219,8 @@ async fn tool_call_output_truncated_only_once() -> Result<()> { }) }; - mount_sse_once_match( + mount_sse_once( &server, - any(), sse(vec![ responses::ev_response_created("resp-1"), responses::ev_function_call(call_id, "shell", &serde_json::to_string(&args)?), @@ -232,9 +228,8 @@ async fn tool_call_output_truncated_only_once() -> Result<()> { ]), ) .await; - let mock2 = mount_sse_once_match( + let mock2 = mount_sse_once( &server, - any(), sse(vec![ responses::ev_assistant_message("msg-1", "done"), responses::ev_completed("resp-2"), @@ -277,9 +272,8 @@ async fn mcp_tool_call_output_exceeds_limit_truncated_for_model() -> Result<()> let large_msg = "long-message-with-newlines-".repeat(600); let args_json = serde_json::json!({ "message": large_msg }); - mount_sse_once_match( + mount_sse_once( &server, - any(), sse(vec![ responses::ev_response_created("resp-1"), responses::ev_function_call(call_id, &tool_name, &args_json.to_string()), @@ -287,9 +281,8 @@ async fn mcp_tool_call_output_exceeds_limit_truncated_for_model() -> Result<()> ]), ) .await; - let mock2 = mount_sse_once_match( + let mock2 = mount_sse_once( &server, - any(), sse(vec![ responses::ev_assistant_message("msg-1", "rmcp echo tool completed."), responses::ev_completed("resp-2"), @@ -373,9 +366,8 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> { let server_name = "rmcp"; let tool_name = format!("mcp__{server_name}__image"); - mount_sse_once_match( + mount_sse_once( &server, - any(), sse(vec![ ev_response_created("resp-1"), ev_function_call(call_id, &tool_name, "{}"), @@ -383,9 +375,8 @@ async fn mcp_image_output_preserves_image_and_no_text_summary() -> Result<()> { ]), ) .await; - let final_mock = mount_sse_once_match( + let final_mock = mount_sse_once( &server, - any(), sse(vec![ ev_assistant_message("msg-1", "done"), ev_completed("resp-2"), diff --git a/codex-rs/core/tests/suite/user_notification.rs b/codex-rs/core/tests/suite/user_notification.rs index 74b59736f4..0d1e941d28 100644 --- a/codex-rs/core/tests/suite/user_notification.rs +++ b/codex-rs/core/tests/suite/user_notification.rs @@ -15,7 +15,6 @@ use pretty_assertions::assert_eq; use serde_json::Value; use serde_json::json; use tempfile::TempDir; -use wiremock::matchers::any; use responses::ev_assistant_message; use responses::ev_completed; @@ -35,7 +34,7 @@ async fn summarize_context_three_requests_and_instructions() -> anyhow::Result<( let sse1 = sse(vec![ev_assistant_message("m1", "Done"), ev_completed("r1")]); - responses::mount_sse_once_match(&server, any(), sse1).await; + responses::mount_sse_once(&server, sse1).await; let notify_dir = TempDir::new()?; // write a script to the notify that touches a file next to it diff --git a/codex-rs/core/tests/suite/user_shell_cmd.rs b/codex-rs/core/tests/suite/user_shell_cmd.rs index 8910161f1e..396b6c7d95 100644 --- a/codex-rs/core/tests/suite/user_shell_cmd.rs +++ b/codex-rs/core/tests/suite/user_shell_cmd.rs @@ -15,7 +15,7 @@ use core_test_support::responses::ev_assistant_message; use core_test_support::responses::ev_completed; use core_test_support::responses::ev_function_call; use core_test_support::responses::ev_response_created; -use core_test_support::responses::mount_sse_once_match; +use core_test_support::responses::mount_sse_once; use core_test_support::responses::sse; use core_test_support::responses::start_mock_server; use core_test_support::skip_if_no_network; @@ -25,7 +25,6 @@ use core_test_support::wait_for_event_match; use regex_lite::escape; use std::path::PathBuf; use tempfile::TempDir; -use wiremock::matchers::any; #[tokio::test] async fn user_shell_cmd_ls_and_cat_in_temp_dir() { @@ -293,9 +292,8 @@ async fn user_shell_command_is_truncated_only_once() -> anyhow::Result<()> { }) }; - mount_sse_once_match( + mount_sse_once( &server, - any(), sse(vec![ ev_response_created("resp-1"), ev_function_call(call_id, "shell", &serde_json::to_string(&args)?), @@ -303,9 +301,8 @@ async fn user_shell_command_is_truncated_only_once() -> anyhow::Result<()> { ]), ) .await; - let mock2 = mount_sse_once_match( + let mock2 = mount_sse_once( &server, - any(), sse(vec![ ev_assistant_message("msg-1", "done"), ev_completed("resp-2"), diff --git a/codex-rs/core/tests/suite/view_image.rs b/codex-rs/core/tests/suite/view_image.rs index 00931ebceb..394c5c2f14 100644 --- a/codex-rs/core/tests/suite/view_image.rs +++ b/codex-rs/core/tests/suite/view_image.rs @@ -24,7 +24,6 @@ use image::ImageBuffer; use image::Rgba; use image::load_from_memory; use serde_json::Value; -use wiremock::matchers::any; fn find_image_message(body: &Value) -> Option<&Value> { body.get("input") @@ -71,7 +70,7 @@ async fn user_turn_with_local_image_attaches_image() -> anyhow::Result<()> { ev_assistant_message("msg-1", "done"), ev_completed("resp-1"), ]); - let mock = responses::mount_sse_once_match(&server, any(), response).await; + let mock = responses::mount_sse_once(&server, response).await; let session_model = session_configured.model.clone(); @@ -156,13 +155,13 @@ async fn view_image_tool_attaches_local_image() -> anyhow::Result<()> { ev_function_call(call_id, "view_image", &arguments), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "done"), ev_completed("resp-2"), ]); - let mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); @@ -266,13 +265,13 @@ async fn view_image_tool_errors_when_path_is_directory() -> anyhow::Result<()> { ev_function_call(call_id, "view_image", &arguments), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "done"), ev_completed("resp-2"), ]); - let mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); @@ -338,13 +337,13 @@ async fn view_image_tool_placeholder_for_non_image_files() -> anyhow::Result<()> ev_function_call(call_id, "view_image", &arguments), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "done"), ev_completed("resp-2"), ]); - let mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); @@ -429,13 +428,13 @@ async fn view_image_tool_errors_when_file_missing() -> anyhow::Result<()> { ev_function_call(call_id, "view_image", &arguments), ev_completed("resp-1"), ]); - responses::mount_sse_once_match(&server, any(), first_response).await; + responses::mount_sse_once(&server, first_response).await; let second_response = sse(vec![ ev_assistant_message("msg-1", "done"), ev_completed("resp-2"), ]); - let mock = responses::mount_sse_once_match(&server, any(), second_response).await; + let mock = responses::mount_sse_once(&server, second_response).await; let session_model = session_configured.model.clone(); diff --git a/codex-rs/exec/tests/suite/output_schema.rs b/codex-rs/exec/tests/suite/output_schema.rs index 913270eff4..485f5e3c79 100644 --- a/codex-rs/exec/tests/suite/output_schema.rs +++ b/codex-rs/exec/tests/suite/output_schema.rs @@ -4,7 +4,6 @@ use core_test_support::responses; use core_test_support::test_codex_exec::test_codex_exec; use serde_json::Value; -use wiremock::matchers::any; #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn exec_includes_output_schema_in_request() -> anyhow::Result<()> { @@ -28,7 +27,7 @@ async fn exec_includes_output_schema_in_request() -> anyhow::Result<()> { responses::ev_assistant_message("m1", "fixture hello"), responses::ev_completed("resp1"), ]); - let response_mock = responses::mount_sse_once_match(&server, any(), body).await; + let response_mock = responses::mount_sse_once(&server, body).await; test.cmd_with_server(&server) .arg("--skip-git-repo-check") diff --git a/codex-rs/exec/tests/suite/server_error_exit.rs b/codex-rs/exec/tests/suite/server_error_exit.rs index 051306cedd..909f48be3c 100644 --- a/codex-rs/exec/tests/suite/server_error_exit.rs +++ b/codex-rs/exec/tests/suite/server_error_exit.rs @@ -3,7 +3,6 @@ use core_test_support::responses; use core_test_support::test_codex_exec::test_codex_exec; -use wiremock::matchers::any; /// Verify that when the server reports an error, `codex-exec` exits with a /// non-zero status code so automation can detect failures. @@ -21,7 +20,7 @@ async fn exits_non_zero_when_server_reports_error() -> anyhow::Result<()> { "error": {"code": "rate_limit_exceeded", "message": "synthetic server error"} } })]); - responses::mount_sse_once_match(&server, any(), body).await; + responses::mount_sse_once(&server, body).await; test.cmd_with_server(&server) .arg("--skip-git-repo-check")