core/src/tools/handlers/request_user_input_tests.rs
68 lines
use super::*;use crate::session::tests::make_session_and_context;use crate::tools::context::ToolInvocation;use crate::tools::context::ToolPayload;use crate::turn_diff_tracker::TurnDiffTracker;use codex_protocol::ThreadId;use codex_protocol::protocol::SessionSource;use codex_protocol::protocol::SubAgentSource;use pretty_assertions::assert_eq;use serde_json::json;use std::sync::Arc;use tokio::sync::Mutex;#[tokio::test]async fn multi_agent_v2_request_user_input_rejects_subagent_threads() { let (session, mut turn) = make_session_and_context().await; turn.session_source = SessionSource::SubAgent(SubAgentSource::ThreadSpawn { parent_thread_id: ThreadId::new(), depth: 1, agent_path: None, agent_nickname: None, agent_role: None, }); let result = RequestUserInputHandler { available_modes: Vec::new(), } .handle(ToolInvocation { session: Arc::new(session), turn: Arc::new(turn), cancellation_token: tokio_util::sync::CancellationToken::new(), tracker: Arc::new(Mutex::new(TurnDiffTracker::default())), call_id: "call-1".to_string(), tool_name: codex_tools::ToolName::plain(REQUEST_USER_INPUT_TOOL_NAME), source: crate::tools::context::ToolCallSource::Direct, payload: ToolPayload::Function { arguments: json!({ "questions": [{ "header": "Hdr", "question": "Pick one", "id": "pick_one", "options": [ { "label": "A", "description": "A" }, { "label": "B", "description": "B" } ] }] }) .to_string(), }, }) .await; let Err(err) = result else { panic!("sub-agent request_user_input should fail"); }; assert_eq!( err, FunctionCallError::RespondToModel( "request_user_input can only be used by the root thread".to_string(), ) );}