diff --git a/codex-rs/core/src/tools/registry.rs b/codex-rs/core/src/tools/registry.rs index bdf18cf2fe0..98e8e227aa3 100644 --- a/codex-rs/core/src/tools/registry.rs +++ b/codex-rs/core/src/tools/registry.rs @@ -522,10 +522,6 @@ impl ToolRegistryBuilder { } } - pub fn push_spec(&mut self, spec: ToolSpec) { - self.push_spec_with_parallel_support(spec, /*supports_parallel_tool_calls*/ false); - } - pub fn push_spec_with_parallel_support( &mut self, spec: ToolSpec, @@ -535,6 +531,20 @@ impl ToolRegistryBuilder { .push(ConfiguredToolSpec::new(spec, supports_parallel_tool_calls)); } + pub(crate) fn push_spec( + &mut self, + spec: ToolSpec, + supports_parallel_tool_calls: bool, + code_mode_enabled: bool, + ) { + let spec = if code_mode_enabled { + codex_tools::augment_tool_spec_for_code_mode(spec) + } else { + spec + }; + self.push_spec_with_parallel_support(spec, supports_parallel_tool_calls); + } + pub fn register_handler(&mut self, handler: Arc) where H: ToolHandler + 'static, @@ -547,6 +557,10 @@ impl ToolRegistryBuilder { } } + pub(crate) fn specs(&self) -> &[ConfiguredToolSpec] { + &self.specs + } + pub fn build(self) -> (Vec, ToolRegistry) { let registry = ToolRegistry::new(self.handlers); (self.specs, registry) diff --git a/codex-rs/core/src/tools/spec.rs b/codex-rs/core/src/tools/spec.rs index b13345f3338..d79fda73a3e 100644 --- a/codex-rs/core/src/tools/spec.rs +++ b/codex-rs/core/src/tools/spec.rs @@ -1,18 +1,15 @@ use crate::shell::Shell; use crate::shell::ShellType; -use crate::tools::handlers::agent_jobs::ReportAgentJobResultHandler; -use crate::tools::handlers::agent_jobs::SpawnAgentsOnCsvHandler; use crate::tools::handlers::multi_agents_common::DEFAULT_WAIT_TIMEOUT_MS; use crate::tools::handlers::multi_agents_common::MAX_WAIT_TIMEOUT_MS; use crate::tools::handlers::multi_agents_common::MIN_WAIT_TIMEOUT_MS; use crate::tools::handlers::multi_agents_spec::WaitAgentTimeoutOptions; use crate::tools::registry::ToolRegistryBuilder; -use crate::tools::spec_plan::build_tool_registry_plan; -use crate::tools::spec_plan_types::ToolHandlerKind; +use crate::tools::spec_plan::build_tool_registry_builder; use crate::tools::spec_plan_types::ToolNamespace; -use crate::tools::spec_plan_types::ToolRegistryPlanDeferredTool; -use crate::tools::spec_plan_types::ToolRegistryPlanMcpTool; -use crate::tools::spec_plan_types::ToolRegistryPlanParams; +use crate::tools::spec_plan_types::ToolRegistryBuildDeferredTool; +use crate::tools::spec_plan_types::ToolRegistryBuildMcpTool; +use crate::tools::spec_plan_types::ToolRegistryBuildParams; use codex_mcp::ToolInfo; use codex_protocol::dynamic_tools::DynamicToolSpec; use codex_tools::AdditionalProperties; @@ -22,7 +19,6 @@ use codex_tools::ResponsesApiTool; use codex_tools::ToolName; use codex_tools::ToolUserShellType; use codex_tools::ToolsConfig; -use codex_tools::augment_tool_spec_for_code_mode; use std::collections::HashMap; use std::collections::HashSet; use std::sync::Arc; @@ -38,7 +34,7 @@ pub(crate) fn tool_user_shell_type(user_shell: &Shell) -> ToolUserShellType { } struct McpToolPlanInputs<'a> { - mcp_tools: Vec>, + mcp_tools: Vec>, tool_namespaces: HashMap, } @@ -46,7 +42,7 @@ fn map_mcp_tools_for_plan(mcp_tools: &HashMap) -> McpToolPlanI McpToolPlanInputs { mcp_tools: mcp_tools .values() - .map(|tool| ToolRegistryPlanMcpTool { + .map(|tool| ToolRegistryBuildMcpTool { name: tool.canonical_tool_name(), tool: &tool.tool, }) @@ -74,51 +70,15 @@ pub(crate) fn build_specs_with_discoverable_tools( discoverable_tools: Option>, dynamic_tools: &[DynamicToolSpec], ) -> ToolRegistryBuilder { - use crate::tools::handlers::ApplyPatchHandler; - use crate::tools::handlers::CodeModeExecuteHandler; - use crate::tools::handlers::CodeModeWaitHandler; - use crate::tools::handlers::ContainerExecHandler; - use crate::tools::handlers::CreateGoalHandler; - use crate::tools::handlers::DynamicToolHandler; - use crate::tools::handlers::ExecCommandHandler; - use crate::tools::handlers::GetGoalHandler; - use crate::tools::handlers::ListMcpResourceTemplatesHandler; - use crate::tools::handlers::ListMcpResourcesHandler; - use crate::tools::handlers::LocalShellHandler; - use crate::tools::handlers::McpHandler; - use crate::tools::handlers::PlanHandler; - use crate::tools::handlers::ReadMcpResourceHandler; - use crate::tools::handlers::RequestPermissionsHandler; - use crate::tools::handlers::RequestPluginInstallHandler; - use crate::tools::handlers::RequestUserInputHandler; - use crate::tools::handlers::ShellCommandHandler; - use crate::tools::handlers::ShellHandler; - use crate::tools::handlers::TestSyncHandler; - use crate::tools::handlers::ToolSearchHandler; use crate::tools::handlers::UnavailableToolHandler; - use crate::tools::handlers::UpdateGoalHandler; - use crate::tools::handlers::ViewImageHandler; - use crate::tools::handlers::WriteStdinHandler; - use crate::tools::handlers::multi_agents::CloseAgentHandler; - use crate::tools::handlers::multi_agents::ResumeAgentHandler; - use crate::tools::handlers::multi_agents::SendInputHandler; - use crate::tools::handlers::multi_agents::SpawnAgentHandler; - use crate::tools::handlers::multi_agents::WaitAgentHandler; - use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2; - use crate::tools::handlers::multi_agents_v2::FollowupTaskHandler as FollowupTaskHandlerV2; - use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHandlerV2; - use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2; - use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2; - use crate::tools::handlers::multi_agents_v2::WaitAgentHandler as WaitAgentHandlerV2; use crate::tools::handlers::unavailable_tool_message; use crate::tools::tool_search_entry::build_tool_search_entries_for_config; - let mut builder = ToolRegistryBuilder::new(); let mcp_tool_plan_inputs = mcp_tools.as_ref().map(map_mcp_tools_for_plan); let deferred_mcp_tool_sources = deferred_mcp_tools.as_ref().map(|tools| { tools .values() - .map(|tool| ToolRegistryPlanDeferredTool { + .map(|tool| ToolRegistryBuildDeferredTool { name: tool.canonical_tool_name(), server_name: tool.server_name.as_str(), connector_name: tool.connector_name.as_deref(), @@ -138,9 +98,19 @@ pub(crate) fn build_specs_with_discoverable_tools( }; let default_wait_timeout_ms = DEFAULT_WAIT_TIMEOUT_MS.clamp(min_wait_timeout_ms, MAX_WAIT_TIMEOUT_MS); - let plan = build_tool_registry_plan( + let deferred_dynamic_tools = dynamic_tools + .iter() + .filter(|tool| tool.defer_loading && (config.namespace_tools || tool.namespace.is_none())) + .cloned() + .collect::>(); + let tool_search_entries = build_tool_search_entries_for_config( + config, + deferred_mcp_tools.as_ref(), + &deferred_dynamic_tools, + ); + let mut builder = build_tool_registry_builder( config, - ToolRegistryPlanParams { + ToolRegistryBuildParams { mcp_tools: mcp_tool_plan_inputs .as_ref() .map(|inputs| inputs.mcp_tools.as_slice()), @@ -156,164 +126,15 @@ pub(crate) fn build_specs_with_discoverable_tools( min_timeout_ms: min_wait_timeout_ms, max_timeout_ms: MAX_WAIT_TIMEOUT_MS, }, + tool_search_entries: &tool_search_entries, }, ); - let deferred_dynamic_tools = dynamic_tools - .iter() - .filter(|tool| tool.defer_loading && (config.namespace_tools || tool.namespace.is_none())) - .cloned() - .collect::>(); - let mut existing_spec_names = plan - .specs + let mut existing_spec_names = builder + .specs() .iter() .map(|configured_tool| configured_tool.name().to_string()) .collect::>(); - for spec in plan.specs { - if spec.supports_parallel_tool_calls { - builder.push_spec_with_parallel_support( - spec.spec, /*supports_parallel_tool_calls*/ true, - ); - } else { - builder.push_spec(spec.spec); - } - } - - for handler in plan.handlers { - let name = handler.name; - match handler.kind { - ToolHandlerKind::ApplyPatch => { - builder.register_handler(Arc::new(ApplyPatchHandler)); - } - ToolHandlerKind::CloseAgentV1 => { - builder.register_handler(Arc::new(CloseAgentHandler)); - } - ToolHandlerKind::CloseAgentV2 => { - builder.register_handler(Arc::new(CloseAgentHandlerV2)); - } - ToolHandlerKind::CodeModeExecute => { - builder.register_handler(Arc::new(CodeModeExecuteHandler)); - } - ToolHandlerKind::CodeModeWait => { - builder.register_handler(Arc::new(CodeModeWaitHandler)); - } - ToolHandlerKind::ContainerExec => { - builder.register_handler(Arc::new(ContainerExecHandler)); - } - ToolHandlerKind::CreateGoal => { - builder.register_handler(Arc::new(CreateGoalHandler)); - } - ToolHandlerKind::DynamicTool => { - builder.register_handler(Arc::new(DynamicToolHandler::new(name))); - } - ToolHandlerKind::ExecCommand => { - builder.register_handler(Arc::new(ExecCommandHandler)); - } - ToolHandlerKind::FollowupTaskV2 => { - builder.register_handler(Arc::new(FollowupTaskHandlerV2)); - } - ToolHandlerKind::GetGoal => { - builder.register_handler(Arc::new(GetGoalHandler)); - } - ToolHandlerKind::ListAgentsV2 => { - builder.register_handler(Arc::new(ListAgentsHandlerV2)); - } - ToolHandlerKind::ListMcpResources => { - builder.register_handler(Arc::new(ListMcpResourcesHandler)); - } - ToolHandlerKind::ListMcpResourceTemplates => { - builder.register_handler(Arc::new(ListMcpResourceTemplatesHandler)); - } - ToolHandlerKind::LocalShell => { - builder.register_handler(Arc::new(LocalShellHandler)); - } - ToolHandlerKind::Mcp => { - builder.register_handler(Arc::new(McpHandler::new(name))); - } - ToolHandlerKind::Plan => { - builder.register_handler(Arc::new(PlanHandler)); - } - ToolHandlerKind::ReadMcpResource => { - builder.register_handler(Arc::new(ReadMcpResourceHandler)); - } - ToolHandlerKind::ReportAgentJobResult => { - builder.register_handler(Arc::new(ReportAgentJobResultHandler)); - } - ToolHandlerKind::RequestPermissions => { - builder.register_handler(Arc::new(RequestPermissionsHandler)); - } - ToolHandlerKind::RequestUserInput => { - builder.register_handler(Arc::new(RequestUserInputHandler { - available_modes: config.request_user_input_available_modes.clone(), - })); - } - ToolHandlerKind::ResumeAgentV1 => { - builder.register_handler(Arc::new(ResumeAgentHandler)); - } - ToolHandlerKind::SendInputV1 => { - builder.register_handler(Arc::new(SendInputHandler)); - } - ToolHandlerKind::SendMessageV2 => { - builder.register_handler(Arc::new(SendMessageHandlerV2)); - } - ToolHandlerKind::Shell => { - builder.register_handler(Arc::new(ShellHandler)); - } - ToolHandlerKind::ShellCommand => { - builder.register_handler(Arc::new(ShellCommandHandler::from( - config.shell_command_backend, - ))); - } - ToolHandlerKind::SpawnAgentsOnCsv => { - builder.register_handler(Arc::new(SpawnAgentsOnCsvHandler)); - } - ToolHandlerKind::SpawnAgentV1 => { - builder.register_handler(Arc::new(SpawnAgentHandler)); - } - ToolHandlerKind::SpawnAgentV2 => { - builder.register_handler(Arc::new(SpawnAgentHandlerV2)); - } - ToolHandlerKind::TestSync => { - builder.register_handler(Arc::new(TestSyncHandler)); - } - ToolHandlerKind::ToolSearch => { - let entries = build_tool_search_entries_for_config( - config, - deferred_mcp_tools.as_ref(), - &deferred_dynamic_tools, - ); - builder.register_handler(Arc::new(ToolSearchHandler::new(entries))); - } - ToolHandlerKind::RequestPluginInstall => { - builder.register_handler(Arc::new(RequestPluginInstallHandler)); - } - ToolHandlerKind::UpdateGoal => { - builder.register_handler(Arc::new(UpdateGoalHandler)); - } - ToolHandlerKind::ViewImage => { - builder.register_handler(Arc::new(ViewImageHandler)); - } - ToolHandlerKind::WaitAgentV1 => { - builder.register_handler(Arc::new(WaitAgentHandler)); - } - ToolHandlerKind::WaitAgentV2 => { - builder.register_handler(Arc::new(WaitAgentHandlerV2)); - } - ToolHandlerKind::WriteStdin => { - builder.register_handler(Arc::new(WriteStdinHandler)); - } - } - } - if let Some(deferred_mcp_tools) = deferred_mcp_tools.as_ref() { - for (_, tool) in deferred_mcp_tools.iter().filter(|(name, _)| { - !mcp_tools - .as_ref() - .is_some_and(|tools| tools.contains_key(*name)) - }) { - builder.register_handler(Arc::new(McpHandler::new(tool.canonical_tool_name()))); - } - } - for unavailable_tool in unavailable_called_tools { let tool_name = unavailable_tool.display(); if existing_spec_names.insert(tool_name.clone()) { @@ -332,12 +153,11 @@ pub(crate) fn build_specs_with_discoverable_tools( output_schema: None, defer_loading: None, }); - let spec = if config.code_mode_enabled { - augment_tool_spec_for_code_mode(spec) - } else { - spec - }; - builder.push_spec(spec); + builder.push_spec( + spec, + /*supports_parallel_tool_calls*/ false, + config.code_mode_enabled, + ); } builder.register_handler(Arc::new(UnavailableToolHandler::new(unavailable_tool))); } diff --git a/codex-rs/core/src/tools/spec_plan.rs b/codex-rs/core/src/tools/spec_plan.rs index e323bce741d..61850c41574 100644 --- a/codex-rs/core/src/tools/spec_plan.rs +++ b/codex-rs/core/src/tools/spec_plan.rs @@ -1,5 +1,31 @@ use crate::tools::code_mode::execute_spec::create_code_mode_tool; use crate::tools::code_mode::wait_spec::create_wait_tool; +use crate::tools::handlers::ApplyPatchHandler; +use crate::tools::handlers::CodeModeExecuteHandler; +use crate::tools::handlers::CodeModeWaitHandler; +use crate::tools::handlers::ContainerExecHandler; +use crate::tools::handlers::CreateGoalHandler; +use crate::tools::handlers::DynamicToolHandler; +use crate::tools::handlers::ExecCommandHandler; +use crate::tools::handlers::GetGoalHandler; +use crate::tools::handlers::ListMcpResourceTemplatesHandler; +use crate::tools::handlers::ListMcpResourcesHandler; +use crate::tools::handlers::LocalShellHandler; +use crate::tools::handlers::McpHandler; +use crate::tools::handlers::PlanHandler; +use crate::tools::handlers::ReadMcpResourceHandler; +use crate::tools::handlers::RequestPermissionsHandler; +use crate::tools::handlers::RequestPluginInstallHandler; +use crate::tools::handlers::RequestUserInputHandler; +use crate::tools::handlers::ShellCommandHandler; +use crate::tools::handlers::ShellHandler; +use crate::tools::handlers::TestSyncHandler; +use crate::tools::handlers::ToolSearchHandler; +use crate::tools::handlers::UpdateGoalHandler; +use crate::tools::handlers::ViewImageHandler; +use crate::tools::handlers::WriteStdinHandler; +use crate::tools::handlers::agent_jobs::ReportAgentJobResultHandler; +use crate::tools::handlers::agent_jobs::SpawnAgentsOnCsvHandler; use crate::tools::handlers::agent_jobs_spec::create_report_agent_job_result_tool; use crate::tools::handlers::agent_jobs_spec::create_spawn_agents_on_csv_tool; use crate::tools::handlers::apply_patch_spec::create_apply_patch_freeform_tool; @@ -10,6 +36,11 @@ use crate::tools::handlers::goal_spec::create_update_goal_tool; use crate::tools::handlers::mcp_resource_spec::create_list_mcp_resource_templates_tool; use crate::tools::handlers::mcp_resource_spec::create_list_mcp_resources_tool; use crate::tools::handlers::mcp_resource_spec::create_read_mcp_resource_tool; +use crate::tools::handlers::multi_agents::CloseAgentHandler; +use crate::tools::handlers::multi_agents::ResumeAgentHandler; +use crate::tools::handlers::multi_agents::SendInputHandler; +use crate::tools::handlers::multi_agents::SpawnAgentHandler; +use crate::tools::handlers::multi_agents::WaitAgentHandler; use crate::tools::handlers::multi_agents_spec::SpawnAgentToolOptions; use crate::tools::handlers::multi_agents_spec::create_close_agent_tool_v1; use crate::tools::handlers::multi_agents_spec::create_close_agent_tool_v2; @@ -22,9 +53,14 @@ use crate::tools::handlers::multi_agents_spec::create_spawn_agent_tool_v1; use crate::tools::handlers::multi_agents_spec::create_spawn_agent_tool_v2; use crate::tools::handlers::multi_agents_spec::create_wait_agent_tool_v1; use crate::tools::handlers::multi_agents_spec::create_wait_agent_tool_v2; +use crate::tools::handlers::multi_agents_v2::CloseAgentHandler as CloseAgentHandlerV2; +use crate::tools::handlers::multi_agents_v2::FollowupTaskHandler as FollowupTaskHandlerV2; +use crate::tools::handlers::multi_agents_v2::ListAgentsHandler as ListAgentsHandlerV2; +use crate::tools::handlers::multi_agents_v2::SendMessageHandler as SendMessageHandlerV2; +use crate::tools::handlers::multi_agents_v2::SpawnAgentHandler as SpawnAgentHandlerV2; +use crate::tools::handlers::multi_agents_v2::WaitAgentHandler as WaitAgentHandlerV2; use crate::tools::handlers::plan_spec::create_update_plan_tool; use crate::tools::handlers::request_plugin_install_spec::create_request_plugin_install_tool; -use crate::tools::handlers::request_user_input_spec::REQUEST_USER_INPUT_TOOL_NAME; use crate::tools::handlers::request_user_input_spec::create_request_user_input_tool; use crate::tools::handlers::request_user_input_spec::request_user_input_tool_description; use crate::tools::handlers::shell_spec::CommandToolOptions; @@ -43,17 +79,14 @@ use crate::tools::handlers::view_image_spec::create_view_image_tool; use crate::tools::hosted_spec::WebSearchToolOptions; use crate::tools::hosted_spec::create_image_generation_tool; use crate::tools::hosted_spec::create_web_search_tool; -use crate::tools::spec_plan_types::ToolHandlerKind; -use crate::tools::spec_plan_types::ToolRegistryPlan; -use crate::tools::spec_plan_types::ToolRegistryPlanParams; +use crate::tools::registry::ToolRegistryBuilder; +use crate::tools::spec_plan_types::ToolRegistryBuildParams; use crate::tools::spec_plan_types::agent_type_description; use codex_protocol::openai_models::ApplyPatchToolType; use codex_protocol::openai_models::ConfigShellToolType; -use codex_tools::REQUEST_PLUGIN_INSTALL_TOOL_NAME; use codex_tools::ResponsesApiNamespace; use codex_tools::ResponsesApiNamespaceTool; use codex_tools::TOOL_SEARCH_DEFAULT_LIMIT; -use codex_tools::TOOL_SEARCH_TOOL_NAME; use codex_tools::ToolEnvironmentMode; use codex_tools::ToolName; use codex_tools::ToolSearchSource; @@ -68,12 +101,13 @@ use codex_tools::default_namespace_description; use codex_tools::dynamic_tool_to_loadable_tool_spec; use codex_tools::mcp_tool_to_responses_api_tool; use std::collections::BTreeMap; +use std::sync::Arc; -pub fn build_tool_registry_plan( +pub fn build_tool_registry_builder( config: &ToolsConfig, - params: ToolRegistryPlanParams<'_>, -) -> ToolRegistryPlan { - let mut plan = ToolRegistryPlan::new(); + params: ToolRegistryBuildParams<'_>, +) -> ToolRegistryBuilder { + let mut builder = ToolRegistryBuilder::new(); let exec_permission_approvals_enabled = config.exec_permission_approvals_enabled; if config.code_mode_enabled { @@ -92,22 +126,22 @@ pub fn build_tool_registry_plan( }) .collect::>(); let nested_config = config.for_code_mode_nested_tools(); - let nested_plan = build_tool_registry_plan( + let nested_builder = build_tool_registry_builder( &nested_config, - ToolRegistryPlanParams { + ToolRegistryBuildParams { discoverable_tools: None, ..params }, ); let mut enabled_tools = collect_code_mode_exec_prompt_tool_definitions( - nested_plan - .specs + nested_builder + .specs() .iter() .map(|configured_tool| &configured_tool.spec), ); enabled_tools .sort_by(|left, right| compare_code_mode_tools(left, right, &namespace_descriptions)); - plan.push_spec( + builder.push_spec( create_code_mode_tool( &enabled_tools, &namespace_descriptions, @@ -120,19 +154,13 @@ pub fn build_tool_registry_plan( /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler( - codex_code_mode::PUBLIC_TOOL_NAME, - ToolHandlerKind::CodeModeExecute, - ); - plan.push_spec( + builder.register_handler(Arc::new(CodeModeExecuteHandler)); + builder.push_spec( create_wait_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler( - codex_code_mode::WAIT_TOOL_NAME, - ToolHandlerKind::CodeModeWait, - ); + builder.register_handler(Arc::new(CodeModeWaitHandler)); } if config.environment_mode.has_environment() { @@ -140,7 +168,7 @@ pub fn build_tool_registry_plan( matches!(config.environment_mode, ToolEnvironmentMode::Multiple); match &config.shell_type { ConfigShellToolType::Default => { - plan.push_spec( + builder.push_spec( create_shell_tool(ShellToolOptions { exec_permission_approvals_enabled, }), @@ -149,14 +177,14 @@ pub fn build_tool_registry_plan( ); } ConfigShellToolType::Local => { - plan.push_spec( + builder.push_spec( create_local_shell_tool(), /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); } ConfigShellToolType::UnifiedExec => { - plan.push_spec( + builder.push_spec( create_exec_command_tool_with_environment_id( CommandToolOptions { allow_login_shell: config.allow_login_shell, @@ -167,17 +195,17 @@ pub fn build_tool_registry_plan( /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_write_stdin_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("exec_command", ToolHandlerKind::ExecCommand); - plan.register_handler("write_stdin", ToolHandlerKind::WriteStdin); + builder.register_handler(Arc::new(ExecCommandHandler)); + builder.register_handler(Arc::new(WriteStdinHandler)); } ConfigShellToolType::Disabled => {} ConfigShellToolType::ShellCommand => { - plan.push_spec( + builder.push_spec( create_shell_command_tool(CommandToolOptions { allow_login_shell: config.allow_login_shell, exec_permission_approvals_enabled, @@ -192,82 +220,80 @@ pub fn build_tool_registry_plan( if config.environment_mode.has_environment() && config.shell_type != ConfigShellToolType::Disabled { - plan.register_handler("shell", ToolHandlerKind::Shell); - plan.register_handler("container.exec", ToolHandlerKind::ContainerExec); - plan.register_handler("local_shell", ToolHandlerKind::LocalShell); - plan.register_handler("shell_command", ToolHandlerKind::ShellCommand); + builder.register_handler(Arc::new(ShellHandler)); + builder.register_handler(Arc::new(ContainerExecHandler)); + builder.register_handler(Arc::new(LocalShellHandler)); + builder.register_handler(Arc::new(ShellCommandHandler::from( + config.shell_command_backend, + ))); } if params.mcp_tools.is_some() { - plan.push_spec( + builder.push_spec( create_list_mcp_resources_tool(), /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_list_mcp_resource_templates_tool(), /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_read_mcp_resource_tool(), /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); - plan.register_handler("list_mcp_resources", ToolHandlerKind::ListMcpResources); - plan.register_handler( - "list_mcp_resource_templates", - ToolHandlerKind::ListMcpResourceTemplates, - ); - plan.register_handler("read_mcp_resource", ToolHandlerKind::ReadMcpResource); + builder.register_handler(Arc::new(ListMcpResourcesHandler)); + builder.register_handler(Arc::new(ListMcpResourceTemplatesHandler)); + builder.register_handler(Arc::new(ReadMcpResourceHandler)); } - plan.push_spec( + builder.push_spec( create_update_plan_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("update_plan", ToolHandlerKind::Plan); + builder.register_handler(Arc::new(PlanHandler)); if config.goal_tools { - plan.push_spec( + builder.push_spec( create_get_goal_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("get_goal", ToolHandlerKind::GetGoal); - plan.push_spec( + builder.register_handler(Arc::new(GetGoalHandler)); + builder.push_spec( create_create_goal_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("create_goal", ToolHandlerKind::CreateGoal); - plan.push_spec( + builder.register_handler(Arc::new(CreateGoalHandler)); + builder.push_spec( create_update_goal_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("update_goal", ToolHandlerKind::UpdateGoal); + builder.register_handler(Arc::new(UpdateGoalHandler)); } - plan.push_spec( + builder.push_spec( create_request_user_input_tool(request_user_input_tool_description( &config.request_user_input_available_modes, )), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler( - REQUEST_USER_INPUT_TOOL_NAME, - ToolHandlerKind::RequestUserInput, - ); + builder.register_handler(Arc::new(RequestUserInputHandler { + available_modes: config.request_user_input_available_modes.clone(), + })); if config.request_permissions_tool_enabled { - plan.push_spec( + builder.push_spec( create_request_permissions_tool(request_permissions_tool_description()), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("request_permissions", ToolHandlerKind::RequestPermissions); + builder.register_handler(Arc::new(RequestPermissionsHandler)); } let deferred_dynamic_tools = params @@ -303,35 +329,28 @@ pub fn build_tool_registry_plan( }); } - plan.push_spec( + builder.push_spec( create_tool_search_tool(&search_source_infos, TOOL_SEARCH_DEFAULT_LIMIT), /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); - plan.register_handler(TOOL_SEARCH_TOOL_NAME, ToolHandlerKind::ToolSearch); - - if let Some(deferred_mcp_tools) = deferred_mcp_tools_for_search { - for tool in deferred_mcp_tools { - plan.register_handler(tool.name.clone(), ToolHandlerKind::Mcp); - } - } + builder.register_handler(Arc::new(ToolSearchHandler::new( + params.tool_search_entries.to_vec(), + ))); } if config.tool_suggest && let Some(discoverable_tools) = params.discoverable_tools.filter(|tools| !tools.is_empty()) { - plan.push_spec( + builder.push_spec( create_request_plugin_install_tool(&collect_request_plugin_install_entries( discoverable_tools, )), /*supports_parallel_tool_calls*/ true, /*code_mode_enabled*/ false, ); - plan.register_handler( - REQUEST_PLUGIN_INSTALL_TOOL_NAME, - ToolHandlerKind::RequestPluginInstall, - ); + builder.register_handler(Arc::new(RequestPluginInstallHandler)); } if config.environment_mode.has_environment() @@ -339,21 +358,21 @@ pub fn build_tool_registry_plan( { match apply_patch_tool_type { ApplyPatchToolType::Freeform => { - plan.push_spec( + builder.push_spec( create_apply_patch_freeform_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); } ApplyPatchToolType::Function => { - plan.push_spec( + builder.push_spec( create_apply_patch_json_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); } } - plan.register_handler("apply_patch", ToolHandlerKind::ApplyPatch); + builder.register_handler(Arc::new(ApplyPatchHandler)); } if config @@ -361,12 +380,12 @@ pub fn build_tool_registry_plan( .iter() .any(|tool| tool == "test_sync_tool") { - plan.push_spec( + builder.push_spec( create_test_sync_tool(), /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); - plan.register_handler("test_sync_tool", ToolHandlerKind::TestSync); + builder.register_handler(Arc::new(TestSyncHandler)); } if let Some(web_search_tool) = create_web_search_tool(WebSearchToolOptions { @@ -374,7 +393,7 @@ pub fn build_tool_registry_plan( web_search_config: config.web_search_config.as_ref(), web_search_tool_type: config.web_search_tool_type, }) { - plan.push_spec( + builder.push_spec( web_search_tool, /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, @@ -382,7 +401,7 @@ pub fn build_tool_registry_plan( } if config.image_gen_tool { - plan.push_spec( + builder.push_spec( create_image_generation_tool("png"), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, @@ -390,21 +409,21 @@ pub fn build_tool_registry_plan( } if config.environment_mode.has_environment() { - plan.push_spec( + builder.push_spec( create_view_image_tool(ViewImageToolOptions { can_request_original_image_detail: config.can_request_original_image_detail, }), /*supports_parallel_tool_calls*/ true, config.code_mode_enabled, ); - plan.register_handler("view_image", ToolHandlerKind::ViewImage); + builder.register_handler(Arc::new(ViewImageHandler)); } if config.collab_tools { if config.multi_agent_v2 { let agent_type_description = agent_type_description(config, params.default_agent_type_description); - plan.push_spec( + builder.push_spec( create_spawn_agent_tool_v2(SpawnAgentToolOptions { available_models: &config.available_models, agent_type_description, @@ -416,41 +435,41 @@ pub fn build_tool_registry_plan( /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_send_message_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_followup_task_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_wait_agent_tool_v2(params.wait_agent_timeouts), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_close_agent_tool_v2(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_list_agents_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("spawn_agent", ToolHandlerKind::SpawnAgentV2); - plan.register_handler("send_message", ToolHandlerKind::SendMessageV2); - plan.register_handler("followup_task", ToolHandlerKind::FollowupTaskV2); - plan.register_handler("wait_agent", ToolHandlerKind::WaitAgentV2); - plan.register_handler("close_agent", ToolHandlerKind::CloseAgentV2); - plan.register_handler("list_agents", ToolHandlerKind::ListAgentsV2); + builder.register_handler(Arc::new(SpawnAgentHandlerV2)); + builder.register_handler(Arc::new(SendMessageHandlerV2)); + builder.register_handler(Arc::new(FollowupTaskHandlerV2)); + builder.register_handler(Arc::new(WaitAgentHandlerV2)); + builder.register_handler(Arc::new(CloseAgentHandlerV2)); + builder.register_handler(Arc::new(ListAgentsHandlerV2)); } else { let agent_type_description = agent_type_description(config, params.default_agent_type_description); - plan.push_spec( + builder.push_spec( create_spawn_agent_tool_v1(SpawnAgentToolOptions { available_models: &config.available_models, agent_type_description, @@ -462,51 +481,48 @@ pub fn build_tool_registry_plan( /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_send_input_tool_v1(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_resume_agent_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("resume_agent", ToolHandlerKind::ResumeAgentV1); - plan.push_spec( + builder.register_handler(Arc::new(ResumeAgentHandler)); + builder.push_spec( create_wait_agent_tool_v1(params.wait_agent_timeouts), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.push_spec( + builder.push_spec( create_close_agent_tool_v1(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("spawn_agent", ToolHandlerKind::SpawnAgentV1); - plan.register_handler("send_input", ToolHandlerKind::SendInputV1); - plan.register_handler("wait_agent", ToolHandlerKind::WaitAgentV1); - plan.register_handler("close_agent", ToolHandlerKind::CloseAgentV1); + builder.register_handler(Arc::new(SpawnAgentHandler)); + builder.register_handler(Arc::new(SendInputHandler)); + builder.register_handler(Arc::new(WaitAgentHandler)); + builder.register_handler(Arc::new(CloseAgentHandler)); } } if config.agent_jobs_tools { - plan.push_spec( + builder.push_spec( create_spawn_agents_on_csv_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler("spawn_agents_on_csv", ToolHandlerKind::SpawnAgentsOnCsv); + builder.register_handler(Arc::new(SpawnAgentsOnCsvHandler)); if config.agent_jobs_worker_tools { - plan.push_spec( + builder.push_spec( create_report_agent_job_result_tool(), /*supports_parallel_tool_calls*/ false, config.code_mode_enabled, ); - plan.register_handler( - "report_agent_job_result", - ToolHandlerKind::ReportAgentJobResult, - ); + builder.register_handler(Arc::new(ReportAgentJobResultHandler)); } } @@ -548,7 +564,7 @@ pub fn build_tool_registry_plan( match mcp_tool_to_responses_api_tool(&tool.name, tool.tool) { Ok(converted_tool) => { tools.push(ResponsesApiNamespaceTool::Function(converted_tool)); - plan.register_handler(tool.name, ToolHandlerKind::Mcp); + builder.register_handler(Arc::new(McpHandler::new(tool.name))); } Err(error) => { let tool_name = &tool.name; @@ -559,8 +575,8 @@ pub fn build_tool_registry_plan( } } - if !tools.is_empty() { - plan.push_spec( + if config.namespace_tools && !tools.is_empty() { + builder.push_spec( ToolSpec::Namespace(ResponsesApiNamespace { name: namespace, description, @@ -579,7 +595,7 @@ pub fn build_tool_registry_plan( Ok(loadable_tool) => { let handler_name = ToolName::new(tool.namespace.clone(), tool.name.clone()); dynamic_tool_specs.push(loadable_tool); - plan.register_handler(handler_name, ToolHandlerKind::DynamicTool); + builder.register_handler(Arc::new(DynamicToolHandler::new(handler_name))); } Err(error) => { tracing::error!( @@ -590,19 +606,28 @@ pub fn build_tool_registry_plan( } } for spec in coalesce_loadable_tool_specs(dynamic_tool_specs) { - plan.push_spec( - spec.into(), - /*supports_parallel_tool_calls*/ false, - config.code_mode_enabled, - ); + let spec = spec.into(); + if config.namespace_tools || !matches!(spec, ToolSpec::Namespace(_)) { + builder.push_spec( + spec, + /*supports_parallel_tool_calls*/ false, + config.code_mode_enabled, + ); + } } - if !config.namespace_tools { - plan.specs - .retain(|configured_tool| !matches!(&configured_tool.spec, ToolSpec::Namespace(_))); + if let Some(deferred_mcp_tools) = params.deferred_mcp_tools { + for tool in deferred_mcp_tools { + let registered_directly = params + .mcp_tools + .is_some_and(|mcp_tools| mcp_tools.iter().any(|direct| direct.name == tool.name)); + if !registered_directly { + builder.register_handler(Arc::new(McpHandler::new(tool.name.clone()))); + } + } } - plan + builder } fn compare_code_mode_tools( diff --git a/codex-rs/core/src/tools/spec_plan_tests.rs b/codex-rs/core/src/tools/spec_plan_tests.rs index 1ad83888031..f41060906b9 100644 --- a/codex-rs/core/src/tools/spec_plan_tests.rs +++ b/codex-rs/core/src/tools/spec_plan_tests.rs @@ -1,11 +1,12 @@ use super::*; use crate::tools::handlers::multi_agents_spec::WaitAgentTimeoutOptions; +use crate::tools::handlers::request_user_input_spec::REQUEST_USER_INPUT_TOOL_NAME; use crate::tools::handlers::shell_spec::CommandToolOptions; use crate::tools::handlers::shell_spec::create_exec_command_tool; -use crate::tools::spec_plan_types::ToolHandlerSpec; +use crate::tools::registry::ToolRegistry; use crate::tools::spec_plan_types::ToolNamespace; -use crate::tools::spec_plan_types::ToolRegistryPlanDeferredTool; -use crate::tools::spec_plan_types::ToolRegistryPlanMcpTool; +use crate::tools::spec_plan_types::ToolRegistryBuildDeferredTool; +use crate::tools::spec_plan_types::ToolRegistryBuildMcpTool; use codex_app_server_protocol::AppInfo; use codex_features::Feature; use codex_features::Features; @@ -29,10 +30,12 @@ use codex_tools::FreeformTool; use codex_tools::JsonSchema; use codex_tools::JsonSchemaPrimitiveType; use codex_tools::JsonSchemaType; +use codex_tools::REQUEST_PLUGIN_INSTALL_TOOL_NAME; use codex_tools::ResponsesApiNamespaceTool; use codex_tools::ResponsesApiTool; use codex_tools::ResponsesApiWebSearchFilters; use codex_tools::ResponsesApiWebSearchUserLocation; +use codex_tools::TOOL_SEARCH_TOOL_NAME; use codex_tools::ToolEnvironmentMode; use codex_tools::ToolName; use codex_tools::ToolsConfigParams; @@ -1244,7 +1247,7 @@ fn namespace_specs_are_hidden_when_namespace_tools_are_disabled() { }); tools_config.namespace_tools = false; - let (tools, handlers) = build_specs( + let (tools, registry) = build_specs( &tools_config, Some(HashMap::from([( ToolName::namespaced("mcp__sample__", "echo"), @@ -1255,10 +1258,7 @@ fn namespace_specs_are_hidden_when_namespace_tools_are_disabled() { ); assert_lacks_tool_name(&tools, "mcp__sample__"); - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::namespaced("mcp__sample__", "echo"), - kind: ToolHandlerKind::Mcp, - })); + assert!(registry.has_handler(&ToolName::namespaced("mcp__sample__", "echo"))); } #[test] @@ -1412,7 +1412,7 @@ fn search_tool_description_lists_each_mcp_source_once() { windows_sandbox_level: WindowsSandboxLevel::Disabled, }); - let (tools, handlers) = build_specs( + let (tools, registry) = build_specs( &tools_config, Some(HashMap::from([ ( @@ -1477,14 +1477,11 @@ fn search_tool_description_lists_each_mcp_source_once() { assert!(description.contains("- rmcp: Remote memory tools.")); assert!(!description.contains("mcp__rmcp__echo")); - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::namespaced("mcp__codex_apps__calendar", "_create_event"), - kind: ToolHandlerKind::Mcp, - })); - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::namespaced("mcp__rmcp__", "echo"), - kind: ToolHandlerKind::Mcp, - })); + assert!(registry.has_handler(&ToolName::namespaced( + "mcp__codex_apps__calendar", + "_create_event", + ))); + assert!(registry.has_handler(&ToolName::namespaced("mcp__rmcp__", "echo"))); } #[test] @@ -1578,7 +1575,7 @@ fn search_tool_is_hidden_when_only_deferred_namespace_tools_are_available() { }); tools_config.namespace_tools = false; - let (tools, handlers) = build_specs( + let (tools, registry) = build_specs( &tools_config, /*mcp_tools*/ None, Some(vec![deferred_mcp_tool( @@ -1592,10 +1589,7 @@ fn search_tool_is_hidden_when_only_deferred_namespace_tools_are_available() { ); assert_lacks_tool_name(&tools, TOOL_SEARCH_TOOL_NAME); - assert!(!handlers.contains(&ToolHandlerSpec { - name: ToolName::plain(TOOL_SEARCH_TOOL_NAME), - kind: ToolHandlerKind::ToolSearch, - })); + assert!(!registry.has_handler(&ToolName::plain(TOOL_SEARCH_TOOL_NAME))); } #[test] @@ -1639,7 +1633,7 @@ fn search_tool_registers_for_deferred_dynamic_tools() { }, ]; - let (tools, handlers) = build_specs( + let (tools, registry) = build_specs( &tools_config, /*mcp_tools*/ None, /*deferred_mcp_tools*/ None, @@ -1670,18 +1664,9 @@ fn search_tool_registers_for_deferred_dynamic_tools() { let dynamic_tool = find_namespace_function_tool(&tools, "codex_app", tool_name); assert_eq!(dynamic_tool.defer_loading, Some(true)); } - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::plain(TOOL_SEARCH_TOOL_NAME), - kind: ToolHandlerKind::ToolSearch, - })); - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::namespaced("codex_app", "automation_update"), - kind: ToolHandlerKind::DynamicTool, - })); - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::namespaced("codex_app", "automation_list"), - kind: ToolHandlerKind::DynamicTool, - })); + assert!(registry.has_handler(&ToolName::plain(TOOL_SEARCH_TOOL_NAME))); + assert!(registry.has_handler(&ToolName::namespaced("codex_app", "automation_update"))); + assert!(registry.has_handler(&ToolName::namespaced("codex_app", "automation_list"))); } #[test] @@ -1718,7 +1703,7 @@ fn search_tool_keeps_plain_deferred_dynamic_tools_when_namespace_tools_are_disab }, ]; - let (tools, handlers) = build_specs( + let (tools, registry) = build_specs( &tools_config, /*mcp_tools*/ None, /*deferred_mcp_tools*/ None, @@ -1727,10 +1712,7 @@ fn search_tool_keeps_plain_deferred_dynamic_tools_when_namespace_tools_are_disab assert_contains_tool_names(&tools, &[TOOL_SEARCH_TOOL_NAME, "plain_dynamic"]); assert_lacks_tool_name(&tools, "codex_app"); - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::plain(TOOL_SEARCH_TOOL_NAME), - kind: ToolHandlerKind::ToolSearch, - })); + assert!(registry.has_handler(&ToolName::plain(TOOL_SEARCH_TOOL_NAME))); } #[test] @@ -1862,17 +1844,14 @@ fn request_plugin_install_description_lists_discoverable_tools() { })), ]; - let (tools, handlers) = build_specs_with_discoverable_tools( + let (tools, registry) = build_specs_with_discoverable_tools( &tools_config, /*mcp_tools*/ None, /*deferred_mcp_tools*/ None, Some(discoverable_tools), &[], ); - assert!(handlers.contains(&ToolHandlerSpec { - name: ToolName::plain(REQUEST_PLUGIN_INSTALL_TOOL_NAME), - kind: ToolHandlerKind::RequestPluginInstall, - })); + assert!(registry.has_handler(&ToolName::plain(REQUEST_PLUGIN_INSTALL_TOOL_NAME))); let request_plugin_install = find_tool(&tools, REQUEST_PLUGIN_INSTALL_TOOL_NAME); let ToolSpec::Function(ResponsesApiTool { @@ -2225,9 +2204,9 @@ fn search_capable_model_info() -> ModelInfo { fn build_specs<'a>( config: &ToolsConfig, mcp_tools: Option>, - deferred_mcp_tools: Option>>, + deferred_mcp_tools: Option>>, dynamic_tools: &[DynamicToolSpec], -) -> (Vec, Vec) { +) -> (Vec, ToolRegistry) { build_specs_with_discoverable_tools( config, mcp_tools, @@ -2240,10 +2219,10 @@ fn build_specs<'a>( fn build_specs_with_discoverable_tools<'a>( config: &ToolsConfig, mcp_tools: Option>, - deferred_mcp_tools: Option>>, + deferred_mcp_tools: Option>>, discoverable_tools: Option>, dynamic_tools: &[DynamicToolSpec], -) -> (Vec, Vec) { +) -> (Vec, ToolRegistry) { build_specs_with_optional_tool_namespaces( config, mcp_tools, @@ -2257,23 +2236,23 @@ fn build_specs_with_discoverable_tools<'a>( fn build_specs_with_optional_tool_namespaces<'a>( config: &ToolsConfig, mcp_tools: Option>, - deferred_mcp_tools: Option>>, + deferred_mcp_tools: Option>>, tool_namespaces: Option>, discoverable_tools: Option>, dynamic_tools: &[DynamicToolSpec], -) -> (Vec, Vec) { +) -> (Vec, ToolRegistry) { let mcp_tool_inputs = mcp_tools.as_ref().map(|mcp_tools| { mcp_tools .iter() - .map(|(name, tool)| ToolRegistryPlanMcpTool { + .map(|(name, tool)| ToolRegistryBuildMcpTool { name: name.clone(), tool, }) .collect::>() }); - let plan = build_tool_registry_plan( + let builder = build_tool_registry_builder( config, - ToolRegistryPlanParams { + ToolRegistryBuildParams { mcp_tools: mcp_tool_inputs.as_deref(), deferred_mcp_tools: deferred_mcp_tools.as_deref(), tool_namespaces: tool_namespaces.as_ref(), @@ -2281,9 +2260,10 @@ fn build_specs_with_optional_tool_namespaces<'a>( dynamic_tools, default_agent_type_description: DEFAULT_AGENT_TYPE_DESCRIPTION, wait_agent_timeouts: wait_agent_timeout_options(), + tool_search_entries: &[], }, ); - (plan.specs, plan.handlers) + builder.build() } fn mcp_tool(name: &str, description: &str, input_schema: serde_json::Value) -> rmcp::model::Tool { @@ -2397,8 +2377,8 @@ fn deferred_mcp_tool<'a>( server_name: &'a str, connector_name: Option<&'a str>, description: Option<&'a str>, -) -> ToolRegistryPlanDeferredTool<'a> { - ToolRegistryPlanDeferredTool { +) -> ToolRegistryBuildDeferredTool<'a> { + ToolRegistryBuildDeferredTool { name: ToolName::namespaced(tool_namespace, tool_name), server_name, connector_name, diff --git a/codex-rs/core/src/tools/spec_plan_types.rs b/codex-rs/core/src/tools/spec_plan_types.rs index 506c4bc7192..a1cb654dd77 100644 --- a/codex-rs/core/src/tools/spec_plan_types.rs +++ b/codex-rs/core/src/tools/spec_plan_types.rs @@ -1,75 +1,20 @@ use crate::tools::handlers::multi_agents_spec::WaitAgentTimeoutOptions; use codex_protocol::dynamic_tools::DynamicToolSpec; -use codex_tools::ConfiguredToolSpec; use codex_tools::DiscoverableTool; use codex_tools::ToolName; -use codex_tools::ToolSpec; use codex_tools::ToolsConfig; -use codex_tools::augment_tool_spec_for_code_mode; use std::collections::HashMap; -#[derive(Debug, Clone, Copy, PartialEq, Eq)] -pub enum ToolHandlerKind { - ApplyPatch, - CloseAgentV1, - CloseAgentV2, - CodeModeExecute, - CodeModeWait, - ContainerExec, - CreateGoal, - DynamicTool, - ExecCommand, - FollowupTaskV2, - GetGoal, - ListAgentsV2, - ListMcpResourceTemplates, - ListMcpResources, - LocalShell, - Mcp, - Plan, - ReadMcpResource, - ReportAgentJobResult, - RequestPluginInstall, - RequestPermissions, - RequestUserInput, - ResumeAgentV1, - SendInputV1, - SendMessageV2, - Shell, - ShellCommand, - SpawnAgentsOnCsv, - SpawnAgentV1, - SpawnAgentV2, - TestSync, - ToolSearch, - UpdateGoal, - ViewImage, - WaitAgentV1, - WaitAgentV2, - WriteStdin, -} - -#[derive(Debug, Clone, PartialEq, Eq)] -pub struct ToolHandlerSpec { - pub name: ToolName, - pub kind: ToolHandlerKind, -} - -#[derive(Debug, Clone, PartialEq)] -pub struct ToolRegistryPlan { - pub specs: Vec, - pub handlers: Vec, -} - -#[derive(Debug, Clone, Copy)] -pub struct ToolRegistryPlanParams<'a> { - pub mcp_tools: Option<&'a [ToolRegistryPlanMcpTool<'a>]>, - pub deferred_mcp_tools: Option<&'a [ToolRegistryPlanDeferredTool<'a>]>, +#[derive(Clone, Copy)] +pub struct ToolRegistryBuildParams<'a> { + pub mcp_tools: Option<&'a [ToolRegistryBuildMcpTool<'a>]>, + pub deferred_mcp_tools: Option<&'a [ToolRegistryBuildDeferredTool<'a>]>, pub tool_namespaces: Option<&'a HashMap>, pub discoverable_tools: Option<&'a [DiscoverableTool]>, pub dynamic_tools: &'a [DynamicToolSpec], pub default_agent_type_description: &'a str, pub wait_agent_timeouts: WaitAgentTimeoutOptions, + pub tool_search_entries: &'a [crate::tools::tool_search_entry::ToolSearchEntry], } #[derive(Debug, Clone, PartialEq, Eq)] @@ -82,50 +27,19 @@ pub struct ToolNamespace { /// while registering its runtime handler with the canonical namespace/name /// identity. #[derive(Debug, Clone)] -pub struct ToolRegistryPlanMcpTool<'a> { +pub struct ToolRegistryBuildMcpTool<'a> { pub name: ToolName, pub tool: &'a rmcp::model::Tool, } #[derive(Debug, Clone)] -pub struct ToolRegistryPlanDeferredTool<'a> { +pub struct ToolRegistryBuildDeferredTool<'a> { pub name: ToolName, pub server_name: &'a str, pub connector_name: Option<&'a str>, pub description: Option<&'a str>, } -impl ToolRegistryPlan { - pub(crate) fn new() -> Self { - Self { - specs: Vec::new(), - handlers: Vec::new(), - } - } - - pub(crate) fn push_spec( - &mut self, - spec: ToolSpec, - supports_parallel_tool_calls: bool, - code_mode_enabled: bool, - ) { - let spec = if code_mode_enabled { - augment_tool_spec_for_code_mode(spec) - } else { - spec - }; - self.specs - .push(ConfiguredToolSpec::new(spec, supports_parallel_tool_calls)); - } - - pub(crate) fn register_handler(&mut self, name: impl Into, kind: ToolHandlerKind) { - self.handlers.push(ToolHandlerSpec { - name: name.into(), - kind, - }); - } -} - pub(crate) fn agent_type_description( config: &ToolsConfig, default_agent_type_description: &str,