From 4eb101614763109b46d39209da657adffe2e8137 Mon Sep 17 00:00:00 2001 From: Bobby Wang Date: Sun, 17 May 2026 02:17:33 -0400 Subject: [PATCH] Expose terminal focus URL env vars --- app/src/pane_group/mod.rs | 13 ++++++-- app/src/terminal/focus_env.rs | 32 +++++++++++++++++++ app/src/terminal/focus_env_tests.rs | 29 +++++++++++++++++ .../terminal/local_tty/windows/environment.rs | 7 ++++ app/src/terminal/mod.rs | 1 + 5 files changed, 80 insertions(+), 2 deletions(-) create mode 100644 app/src/terminal/focus_env.rs create mode 100644 app/src/terminal/focus_env_tests.rs diff --git a/app/src/pane_group/mod.rs b/app/src/pane_group/mod.rs index 8c9827d744..588d072b98 100644 --- a/app/src/pane_group/mod.rs +++ b/app/src/pane_group/mod.rs @@ -115,6 +115,7 @@ use crate::shell_indicator::ShellIndicatorType; use crate::terminal::available_shells::{AvailableShell, AvailableShells}; #[cfg(not(target_family = "wasm"))] use crate::terminal::cli_agent_sessions::plugin_manager::PluginModalKind; +use crate::terminal::focus_env::add_session_focus_env_vars; use crate::terminal::general_settings::{GeneralSettings, GeneralSettingsChangedEvent}; #[cfg(feature = "local_tty")] use crate::terminal::local_tty; @@ -1321,6 +1322,7 @@ impl PaneGroup { // TODO(CORE-3187): On Windows, support WSL directory restoration. Some(cwd).filter(|p| p.exists()), HashMap::new(), + uuid.as_bytes(), IsSharedSessionCreator::No, resources, None, @@ -1621,6 +1623,7 @@ impl PaneGroup { let (terminal_view, terminal_manager) = PaneGroup::create_session( startup_directory, HashMap::new(), + uuid.0.as_slice(), IsSharedSessionCreator::No, resources, block_list, @@ -3815,9 +3818,11 @@ impl PaneGroup { pane_history: &mut Vec, ctx: &mut ViewContext, ) -> (PaneData, InitialFocus) { + let uuid = Uuid::new_v4(); let (view, terminal_manager) = PaneGroup::create_session( options.initial_directory, options.env_vars, + uuid.as_bytes(), options.is_shared_session_creator, resources, None, @@ -3829,7 +3834,6 @@ impl PaneGroup { None, ctx, ); - let uuid = Uuid::new_v4(); let pane_data = TerminalPane::new( uuid.as_bytes().to_vec(), @@ -6253,7 +6257,8 @@ impl PaneGroup { #[allow(clippy::too_many_arguments, unused_variables)] fn create_session( startup_directory: Option, - env_vars: HashMap, + mut env_vars: HashMap, + terminal_session_uuid: &[u8], is_shared_session: IsSharedSessionCreator, resources: TerminalViewResources, restored_blocks: Option<&Vec>, @@ -6268,6 +6273,8 @@ impl PaneGroup { ViewHandle, ModelHandle>, ) { + add_session_focus_env_vars(&mut env_vars, terminal_session_uuid); + cfg_if::cfg_if! { if #[cfg(feature = "remote_tty")] { let terminal_manager: ModelHandle> = crate::terminal::remote_tty::TerminalManager::create_model( @@ -6566,6 +6573,7 @@ impl PaneGroup { let (view, terminal_manager) = PaneGroup::create_session( startup_directory, HashMap::new(), + uuid.as_bytes(), IsSharedSessionCreator::No, resources, None, @@ -6682,6 +6690,7 @@ impl PaneGroup { let (view, terminal_manager) = PaneGroup::create_session( startup_directory, env_vars, + uuid.as_bytes(), is_shared_session_creator, resources, None, diff --git a/app/src/terminal/focus_env.rs b/app/src/terminal/focus_env.rs new file mode 100644 index 0000000000..44a4535d46 --- /dev/null +++ b/app/src/terminal/focus_env.rs @@ -0,0 +1,32 @@ +use std::{collections::HashMap, ffi::OsString}; + +use crate::channel::ChannelState; + +pub(crate) const FOCUS_URL_ENV: &str = "WARP_FOCUS_URL"; +pub(crate) const TERMINAL_SESSION_UUID_ENV: &str = "WARP_TERMINAL_SESSION_UUID"; + +pub(crate) fn session_focus_url(session_uuid_hex: &str) -> String { + format!( + "{}://session/{session_uuid_hex}", + ChannelState::url_scheme() + ) +} + +pub(crate) fn add_session_focus_env_vars( + env_vars: &mut HashMap, + session_uuid: &[u8], +) { + let session_uuid_hex = hex::encode(session_uuid); + env_vars.insert( + OsString::from(TERMINAL_SESSION_UUID_ENV), + OsString::from(session_uuid_hex.clone()), + ); + env_vars.insert( + OsString::from(FOCUS_URL_ENV), + OsString::from(session_focus_url(&session_uuid_hex)), + ); +} + +#[cfg(test)] +#[path = "focus_env_tests.rs"] +mod tests; diff --git a/app/src/terminal/focus_env_tests.rs b/app/src/terminal/focus_env_tests.rs new file mode 100644 index 0000000000..3a405687bf --- /dev/null +++ b/app/src/terminal/focus_env_tests.rs @@ -0,0 +1,29 @@ +use std::{collections::HashMap, ffi::OsString}; + +use crate::channel::ChannelState; + +use super::{add_session_focus_env_vars, FOCUS_URL_ENV, TERMINAL_SESSION_UUID_ENV}; + +#[test] +fn focus_env_vars_point_at_session_deeplink() { + let uuid = [ + 0x55, 0x0e, 0x84, 0x00, 0xe2, 0x9b, 0x41, 0xd4, 0xa7, 0x16, 0x44, 0x66, 0x55, 0x44, 0x00, + 0x00, + ]; + let mut env_vars = HashMap::new(); + + add_session_focus_env_vars(&mut env_vars, &uuid); + + let expected_hex = "550e8400e29b41d4a716446655440000"; + assert_eq!( + env_vars.get(&OsString::from(TERMINAL_SESSION_UUID_ENV)), + Some(&OsString::from(expected_hex)) + ); + assert_eq!( + env_vars.get(&OsString::from(FOCUS_URL_ENV)), + Some(&OsString::from(format!( + "{}://session/{expected_hex}", + ChannelState::url_scheme() + ))) + ); +} diff --git a/app/src/terminal/local_tty/windows/environment.rs b/app/src/terminal/local_tty/windows/environment.rs index 942470c0d6..624ed475de 100644 --- a/app/src/terminal/local_tty/windows/environment.rs +++ b/app/src/terminal/local_tty/windows/environment.rs @@ -13,6 +13,7 @@ use winreg::{RegKey, RegValue}; use crate::safe_info; use crate::terminal::cli_agent_sessions::event::current_protocol_version; +use crate::terminal::focus_env::{FOCUS_URL_ENV, TERMINAL_SESSION_UUID_ENV}; use crate::terminal::local_tty::shell::{extra_path_entries, ssh_socket_dir, ShellStarter}; use crate::terminal::local_tty::PtyOptions; @@ -198,6 +199,8 @@ fn wsl_env_allowlist(include_initial_working_dir: bool) -> OsString { format!("{IS_LOCAL_SESSION_NAME}/u"), format!("{SSH_SOCKET_DIR}/u"), format!("{CLIENT_VERSION_NAME}/u"), + format!("{TERMINAL_SESSION_UUID_ENV}/u"), + format!("{FOCUS_URL_ENV}/u"), ]; if FeatureFlag::HOANotifications.is_enabled() { @@ -382,6 +385,8 @@ mod tests { format!("{IS_LOCAL_SESSION_NAME}/u"), format!("{SSH_SOCKET_DIR}/u"), format!("{CLIENT_VERSION_NAME}/u"), + format!("{TERMINAL_SESSION_UUID_ENV}/u"), + format!("{FOCUS_URL_ENV}/u"), ], ); } @@ -402,6 +407,8 @@ mod tests { format!("{IS_LOCAL_SESSION_NAME}/u"), format!("{SSH_SOCKET_DIR}/u"), format!("{CLIENT_VERSION_NAME}/u"), + format!("{TERMINAL_SESSION_UUID_ENV}/u"), + format!("{FOCUS_URL_ENV}/u"), format!("{CLI_AGENT_PROTOCOL_VERSION_NAME}/u"), format!("{INITIAL_WORKING_DIR_NAME}/pu"), ], diff --git a/app/src/terminal/mod.rs b/app/src/terminal/mod.rs index 280fc3bf28..48225d807b 100644 --- a/app/src/terminal/mod.rs +++ b/app/src/terminal/mod.rs @@ -39,6 +39,7 @@ pub mod enable_auto_reload_modal; pub mod event; pub mod event_listener; pub mod find; +pub(crate) mod focus_env; pub mod general_settings; pub mod grid_renderer; pub mod grid_size_util;