diff --git a/codex-rs/core/tests/suite/prompt_caching.rs b/codex-rs/core/tests/suite/prompt_caching.rs index e56a00624d..346b52fbc5 100644 --- a/codex-rs/core/tests/suite/prompt_caching.rs +++ b/codex-rs/core/tests/suite/prompt_caching.rs @@ -609,178 +609,6 @@ async fn per_turn_overrides_keep_cached_prefix_and_key_constant() { assert_eq!(body2["input"], expected_body2); } -#[tokio::test(flavor = "multi_thread", worker_threads = 2)] -async fn changing_approval_policy_mid_session_preserves_shell_tool_description_and_json() { - use pretty_assertions::assert_eq; - - let server = MockServer::start().await; - - let sse = sse_completed("resp"); - let template = ResponseTemplate::new(200) - .insert_header("content-type", "text/event-stream") - .set_body_raw(sse, "text/event-stream"); - - // Expect two POSTs to /v1/responses - Mock::given(method("POST")) - .and(path("/v1/responses")) - .respond_with(template) - .expect(2) - .mount(&server) - .await; - - let model_provider = ModelProviderInfo { - base_url: Some(format!("{}/v1", server.uri())), - ..built_in_model_providers()["openai"].clone() - }; - - let cwd = TempDir::new().unwrap(); - let codex_home = TempDir::new().unwrap(); - let mut config = load_default_config_for_test(&codex_home); - config.cwd = cwd.path().to_path_buf(); - config.model_provider = model_provider; - config.user_instructions = Some("be consistent and helpful".to_string()); - // Keep toolset minimal/deterministic for this assertion - config.include_apply_patch_tool = false; - config.include_plan_tool = false; - - let conversation_manager = - ConversationManager::with_auth(CodexAuth::from_api_key("Test API Key")); - let codex = conversation_manager - .new_conversation(config) - .await - .expect("create new conversation") - .conversation; - - // First turn with default approval policy (on-request) - codex - .submit(Op::UserInput { - items: vec![InputItem::Text { - text: "hello 1".into(), - }], - }) - .await - .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; - - // Change approval policy mid-session to Never - codex - .submit(Op::OverrideTurnContext { - cwd: None, - approval_policy: Some(AskForApproval::Never), - sandbox_policy: None, - model: None, - effort: None, - summary: None, - }) - .await - .unwrap(); - - // Second turn after overrides - codex - .submit(Op::UserInput { - items: vec![InputItem::Text { - text: "hello 2".into(), - }], - }) - .await - .unwrap(); - wait_for_event(&codex, |ev| matches!(ev, EventMsg::TaskComplete(_))).await; - - let requests = server.received_requests().await.unwrap(); - assert_eq!(requests.len(), 2, "expected two POST requests"); - - let body1 = requests[0].body_json::().unwrap(); - let body2 = requests[1].body_json::().unwrap(); - - // Extract the shell tool from the tools array in each request - let find_shell = |body: &serde_json::Value| -> serde_json::Value { - body["tools"] - .as_array() - .unwrap() - .iter() - .find(|t| t["type"] == "function" && t["name"] == "shell") - .cloned() - .expect("shell tool present") - }; - - let shell1 = find_shell(&body1); - let shell2 = find_shell(&body2); - - // Description must be stable across approval policy changes - assert_eq!( - shell1["description"], - serde_json::json!("Runs a shell command and returns its output") - ); - assert_eq!(shell1["description"], shell2["description"]); - - // Raw JSON expectation for shell tool under on-request (ShellWithRequest) - let expected_shell_on_request = serde_json::json!({ - "type": "function", - "name": "shell", - "description": "Runs a shell command and returns its output", - "strict": false, - "parameters": { - "type": "object", - "properties": { - "command": { - "type": "array", - "items": { "type": "string" }, - "description": "The command to execute" - }, - "workdir": { - "type": "string", - "description": "Working directory to execute the command in." - }, - "timeout_ms": { - "type": "number", - "description": "Timeout for the command in milliseconds." - }, - "with_escalated_permissions": { - "type": "boolean", - "description": "Request escalated permissions, only for when a command would otherwise be blocked by the sandbox." - }, - "justification": { - "type": "string", - "description": "Required if and only if with_escalated_permissions == true. One sentence explaining why escalation is needed (e.g., write outside CWD, network fetch, git commit)." - } - }, - "required": ["command"], - "additionalProperties": false - } - }); - - // Raw JSON expectation for shell tool under never (DefaultShell) - let expected_shell_never = serde_json::json!({ - "type": "function", - "name": "shell", - "description": "Runs a shell command and returns its output", - "strict": false, - "parameters": { - "type": "object", - "properties": { - "command": { - "type": "array", - "items": { "type": "string" }, - "description": "The command to execute" - }, - "workdir": { - "type": "string", - "description": "The working directory to execute the command in" - }, - "timeout_ms": { - "type": "number", - "description": "The timeout for the command in milliseconds" - } - }, - "required": ["command"], - "additionalProperties": false - } - }); - - assert_eq!(shell1, expected_shell_on_request); - assert_eq!(shell2, expected_shell_never); -} - #[tokio::test(flavor = "multi_thread", worker_threads = 2)] async fn tools_stable_across_all_approval_policy_transitions() { use pretty_assertions::assert_eq;