diff --git a/codex-rs/tui/src/terminal_browser/tests.rs b/codex-rs/tui/src/terminal_browser/tests.rs index aedc83ef65..8a5b8d5286 100644 --- a/codex-rs/tui/src/terminal_browser/tests.rs +++ b/codex-rs/tui/src/terminal_browser/tests.rs @@ -158,7 +158,7 @@ fn cropped_wide_glyph_is_replaced_with_a_blank_cell() { } #[test] -fn dynamic_tools_are_namespaced_and_deferred() { +fn terminal_browser_open_is_eager_and_other_dynamic_tools_are_deferred() { let specs = dynamic_tool_specs(); let [DynamicToolSpec::Namespace(namespace)] = specs.as_slice() else { panic!("expected one terminal-browser namespace"); @@ -189,7 +189,14 @@ fn dynamic_tools_are_namespaced_and_deferred() { "close", ] ); - assert!(tools.iter().all(|spec| spec.defer_loading)); + assert!( + !tools[0].defer_loading, + "browser open must be visible immediately" + ); + assert!( + tools[1..].iter().all(|spec| spec.defer_loading), + "follow-up browser tools should remain deferred" + ); for tool_name in ["click", "fill"] { let node_id_pattern = tools .iter() diff --git a/codex-rs/tui/src/terminal_browser/tools.rs b/codex-rs/tui/src/terminal_browser/tools.rs index 9abf543243..c73fca0abf 100644 --- a/codex-rs/tui/src/terminal_browser/tools.rs +++ b/codex-rs/tui/src/terminal_browser/tools.rs @@ -16,9 +16,9 @@ pub(crate) fn dynamic_tool_specs() -> Vec { description: "Control the browser rendered inside the terminal. Use these tools when the user asks for the terminal browser; do not substitute shell text browsers." .to_string(), tools: vec![ - tool( + eager_tool( "open", - "Open a URL in the terminal browser. The browser panel is watch-only; Codex controls the page.", + "Open a URL in the browser panel rendered inside the terminal. Use this tool whenever the user asks for the terminal browser or browser tab; do not substitute web search. An ephemeral profile is active by default, and the user can click the panel to take control.", json!({ "type": "object", "properties": { @@ -114,7 +114,7 @@ pub(crate) fn dynamic_tool_specs() -> Vec { ), tool( "profile", - "List profiles or request a user-approved create, select, ephemeral, or forget operation.", + "List profiles or request a user-approved create, select, ephemeral, or forget operation. Profile changes are not required before opening a URL; an ephemeral profile is active by default.", json!({ "type": "object", "properties": { @@ -242,12 +242,34 @@ fn tool( name: &str, description: &str, input_schema: serde_json::Value, +) -> DynamicToolNamespaceTool { + dynamic_tool(name, description, input_schema, /*defer_loading*/ true) +} + +fn eager_tool( + name: &str, + description: &str, + input_schema: serde_json::Value, +) -> DynamicToolNamespaceTool { + dynamic_tool( + name, + description, + input_schema, + /*defer_loading*/ false, + ) +} + +fn dynamic_tool( + name: &str, + description: &str, + input_schema: serde_json::Value, + defer_loading: bool, ) -> DynamicToolNamespaceTool { DynamicToolNamespaceTool::Function(DynamicToolFunctionSpec { name: name.to_string(), description: description.to_string(), input_schema, - defer_loading: true, + defer_loading, }) } diff --git a/justfile b/justfile index 1a82f30f49..088a2dc6d3 100644 --- a/justfile +++ b/justfile @@ -104,6 +104,14 @@ test-terminal-browser-panel *args: -E 'package(codex-utils-pty) | package(codex-terminal-browser) | package(codex-sandboxing) | package(codex-linux-sandbox) | package(codex-features) | package(codex-protocol) | package(codex-app-server-protocol) | (package(codex-exec-server) & test(/sandbox_request_allows_prepared_managed_proxy_port|sandbox_exec_request_carries_helper_env/)) | (package(codex-core) & test(/config_schema_matches_fixture|active_profile_update_rebuilds_network_proxy_config|current_network_proxy_runtime|managed_network_proxy_decider_survives_full_access_start|managed_network_proxy_refresh_failure|new_turn_refreshes_managed_network_proxy_for_sandbox_change|danger_full_access_turns_do_not_expose_managed_network_proxy|workspace_write_turns_continue_to_expose_managed_network_proxy/)) | (package(codex-app-server) & test(/thread_start_returns_live_managed_proxy_in_experimental_extra|thread_settings_update_reports_current_managed_proxy_runtime/)) | (package(codex-tui) & test(/terminal_browser|owned_screen_browser|bare_browser|browser_show_alias|network_reconciliation|inactive_thread_settings_notification|proxy_runtime|thread_read_fallback_uses_active_permission_settings/))' \ "$@" +# Run the short permission and tool-routing regressions for the terminal browser. +[unix] +test-terminal-browser-routing *args: + just test \ + -p codex-tui \ + -E 'package(codex-tui) & test(/terminal_browser_(auto_review|managed_network|detects_user_network|open_is_eager)|permissions_auto_review_selection_defers/)' \ + "$@" + # Run from the repository root so scripts that resolve paths from `cwd` see # the same layout they use in GitHub Actions. [no-cd]