From 7dbdfa43fa4ed135414f2b8acd7634759b46ecc2 Mon Sep 17 00:00:00 2001 From: Jack Amadeo Date: Tue, 19 May 2026 09:57:49 -0400 Subject: [PATCH] flag for login shell PATH (#9313) --- crates/goose/src/acp/server.rs | 17 ++++++++++++++++- crates/goose/src/agents/agent.rs | 11 +++++++++++ crates/goose/src/agents/extension_manager.rs | 3 +++ .../agents/platform_extensions/analyze/mod.rs | 1 + .../agents/platform_extensions/developer/mod.rs | 5 +++-- .../platform_extensions/developer/shell.rs | 9 ++++++--- .../goose/src/agents/platform_extensions/mod.rs | 1 + .../src/agents/platform_extensions/summon.rs | 1 + crates/goose/src/agents/prompt_manager.rs | 1 + crates/goose/src/skills/client.rs | 2 ++ crates/goose/tests/mcp_integration_test.rs | 1 + ui/goose2/src/shared/api/acpConnection.ts | 3 +++ 12 files changed, 49 insertions(+), 6 deletions(-) diff --git a/crates/goose/src/acp/server.rs b/crates/goose/src/acp/server.rs index 8d3033a0..b0b5e4f9 100644 --- a/crates/goose/src/acp/server.rs +++ b/crates/goose/src/acp/server.rs @@ -244,6 +244,7 @@ pub struct GooseAcpAgent { client_fs_capabilities: OnceCell, client_terminal: OnceCell, client_mcp_host_info: OnceCell, + use_login_shell_path: OnceCell, config_dir: std::path::PathBuf, session_manager: Arc, permission_manager: Arc, @@ -479,6 +480,14 @@ fn extract_client_mcp_host_info(args: &InitializeRequest) -> GooseMcpHostInfo { } } +fn extract_use_login_shell_path(args: &InitializeRequest) -> bool { + args.meta + .as_ref() + .and_then(|meta| meta.get("goose/useLoginShellPath")) + .and_then(|v| v.as_bool()) + .unwrap_or(false) +} + fn mcp_server_to_extension_config(mcp_server: McpServer) -> Result { match mcp_server { McpServer::Stdio(stdio) => { @@ -1179,6 +1188,7 @@ impl GooseAcpAgent { client_fs_capabilities: OnceCell::new(), client_terminal: OnceCell::new(), client_mcp_host_info: OnceCell::new(), + use_login_shell_path: OnceCell::new(), config_dir: options.config_dir, session_manager, permission_manager, @@ -1421,6 +1431,7 @@ impl GooseAcpAgent { .unwrap_or_default(); let client_terminal = self.client_terminal.get().copied().unwrap_or(false); let client_mcp_host_info = self.client_mcp_host_info.get().cloned(); + let use_login_shell_path = self.use_login_shell_path.get().copied().unwrap_or(false); let provider_factory = Arc::clone(&self.provider_factory); let disable_session_naming = self.disable_session_naming; let goose_platform = self.goose_platform.clone(); @@ -1454,7 +1465,8 @@ impl GooseAcpAgent { goose_platform, ) .with_mcp_host_info(client_mcp_host_info) - .with_session_name_update_tx(session_name_update_tx), + .with_session_name_update_tx(session_name_update_tx) + .with_use_login_shell_path(use_login_shell_path), )); // Init provider — reuse the pre-resolved name + model when @@ -2511,6 +2523,9 @@ impl GooseAcpAgent { let _ = self .client_mcp_host_info .set(extract_client_mcp_host_info(&args)); + let _ = self + .use_login_shell_path + .set(extract_use_login_shell_path(&args)); let capabilities = AgentCapabilities::new() .load_session(true) diff --git a/crates/goose/src/agents/agent.rs b/crates/goose/src/agents/agent.rs index 61eecf4d..cf785571 100644 --- a/crates/goose/src/agents/agent.rs +++ b/crates/goose/src/agents/agent.rs @@ -150,6 +150,7 @@ pub struct AgentConfig { pub goose_platform: GoosePlatform, pub mcp_host_info: Option, pub session_name_update_tx: Option>, + pub use_login_shell_path: Option, } impl AgentConfig { @@ -170,6 +171,7 @@ impl AgentConfig { goose_platform, mcp_host_info: None, session_name_update_tx: None, + use_login_shell_path: None, } } @@ -185,6 +187,11 @@ impl AgentConfig { self.session_name_update_tx = tx; self } + + pub fn with_use_login_shell_path(mut self, use_login_shell_path: bool) -> Self { + self.use_login_shell_path = Some(use_login_shell_path); + self + } } /// The main goose Agent @@ -295,6 +302,9 @@ impl Agent { .unwrap_or_else(|| goose_platform.to_string()); let session_manager = Arc::clone(&config.session_manager); let permission_manager = Arc::clone(&config.permission_manager); + let use_login_shell_path = config + .use_login_shell_path + .unwrap_or(matches!(goose_platform, GoosePlatform::GooseDesktop)); Self { provider: provider.clone(), config, @@ -304,6 +314,7 @@ impl Agent { session_manager, client_name, capabilities, + use_login_shell_path, )), final_output_tool: Arc::new(Mutex::new(None)), frontend_extensions: Mutex::new(HashMap::new()), diff --git a/crates/goose/src/agents/extension_manager.rs b/crates/goose/src/agents/extension_manager.rs index 02b4cb06..da7e2ce9 100644 --- a/crates/goose/src/agents/extension_manager.rs +++ b/crates/goose/src/agents/extension_manager.rs @@ -741,6 +741,7 @@ impl ExtensionManager { session_manager: Arc, client_name: String, capabilities: ExtensionManagerCapabilities, + use_login_shell_path: bool, ) -> Self { Self { extensions: Mutex::new(HashMap::new()), @@ -748,6 +749,7 @@ impl ExtensionManager { extension_manager: None, session_manager, session: None, + use_login_shell_path, }, provider, tools_cache: Mutex::new(None), @@ -767,6 +769,7 @@ impl ExtensionManager { mcpui: false, host_info: None, }, + false, ) } diff --git a/crates/goose/src/agents/platform_extensions/analyze/mod.rs b/crates/goose/src/agents/platform_extensions/analyze/mod.rs index ec98eded..a6587431 100644 --- a/crates/goose/src/agents/platform_extensions/analyze/mod.rs +++ b/crates/goose/src/agents/platform_extensions/analyze/mod.rs @@ -278,6 +278,7 @@ mod tests { extension_manager: None, session_manager: Arc::new(SessionManager::new(std::env::temp_dir())), session: None, + use_login_shell_path: false, } } diff --git a/crates/goose/src/agents/platform_extensions/developer/mod.rs b/crates/goose/src/agents/platform_extensions/developer/mod.rs index 21553cee..2a171fca 100644 --- a/crates/goose/src/agents/platform_extensions/developer/mod.rs +++ b/crates/goose/src/agents/platform_extensions/developer/mod.rs @@ -64,14 +64,14 @@ fn developer_instructions() -> &'static str { } impl DeveloperClient { - pub fn new(_context: PlatformExtensionContext) -> Result { + pub fn new(context: PlatformExtensionContext) -> Result { let info = InitializeResult::new(ServerCapabilities::builder().enable_tools().build()) .with_server_info(Implementation::new(EXTENSION_NAME, "1.0.0").with_title("Developer")) .with_instructions(developer_instructions()); Ok(Self { info, - shell_tool: Arc::new(ShellTool::new()?), + shell_tool: Arc::new(ShellTool::new(context.use_login_shell_path)?), edit_tools: Arc::new(EditTools::new()), tree_tool: Arc::new(TreeTool::new()), }) @@ -240,6 +240,7 @@ mod tests { extension_manager: None, session_manager: Arc::new(SessionManager::new(data_dir)), session: None, + use_login_shell_path: false, } } diff --git a/crates/goose/src/agents/platform_extensions/developer/shell.rs b/crates/goose/src/agents/platform_extensions/developer/shell.rs index bc8f4e6d..2f724594 100644 --- a/crates/goose/src/agents/platform_extensions/developer/shell.rs +++ b/crates/goose/src/agents/platform_extensions/developer/shell.rs @@ -284,7 +284,6 @@ impl LoginPath { } } - #[cfg(test)] fn resolved(value: Option) -> Self { let cell = OnceCell::new(); let _ = cell.set(value.map(Arc::from)); @@ -320,12 +319,16 @@ pub struct ShellTool { } impl ShellTool { - pub fn new() -> std::io::Result { + pub fn new(use_login_shell_path: bool) -> std::io::Result { Ok(Self { output_dir: tempfile::tempdir()?, call_index: AtomicUsize::new(0), #[cfg(not(windows))] - login_path: LoginPath::spawn(), + login_path: if use_login_shell_path { + LoginPath::spawn() + } else { + LoginPath::resolved(None) + }, }) } diff --git a/crates/goose/src/agents/platform_extensions/mod.rs b/crates/goose/src/agents/platform_extensions/mod.rs index c68d19ee..4b404937 100644 --- a/crates/goose/src/agents/platform_extensions/mod.rs +++ b/crates/goose/src/agents/platform_extensions/mod.rs @@ -212,6 +212,7 @@ pub struct PlatformExtensionContext { Option>, pub session_manager: std::sync::Arc, pub session: Option>, + pub use_login_shell_path: bool, } impl PlatformExtensionContext { diff --git a/crates/goose/src/agents/platform_extensions/summon.rs b/crates/goose/src/agents/platform_extensions/summon.rs index 6346f011..a1ba0d07 100644 --- a/crates/goose/src/agents/platform_extensions/summon.rs +++ b/crates/goose/src/agents/platform_extensions/summon.rs @@ -1715,6 +1715,7 @@ mod tests { extension_manager: None, session_manager: Arc::new(crate::session::SessionManager::instance()), session: None, + use_login_shell_path: false, } } diff --git a/crates/goose/src/agents/prompt_manager.rs b/crates/goose/src/agents/prompt_manager.rs index 4ce45fd3..6178b173 100644 --- a/crates/goose/src/agents/prompt_manager.rs +++ b/crates/goose/src/agents/prompt_manager.rs @@ -435,6 +435,7 @@ mod tests { extension_manager: None, session_manager, session: Some(Arc::new(session)), + use_login_shell_path: false, }; let mut extensions: Vec = PLATFORM_EXTENSIONS diff --git a/crates/goose/src/skills/client.rs b/crates/goose/src/skills/client.rs index b52b3fad..13bf9335 100644 --- a/crates/goose/src/skills/client.rs +++ b/crates/goose/src/skills/client.rs @@ -285,6 +285,7 @@ mod tests { extension_manager: None, session_manager: Arc::new(crate::session::SessionManager::instance()), session: Some(session), + use_login_shell_path: false, }) .unwrap(); @@ -311,6 +312,7 @@ mod tests { extension_manager: None, session_manager: Arc::new(crate::session::SessionManager::instance()), session: None, + use_login_shell_path: false, }) .unwrap(); diff --git a/crates/goose/tests/mcp_integration_test.rs b/crates/goose/tests/mcp_integration_test.rs index b85931c4..00dca62a 100644 --- a/crates/goose/tests/mcp_integration_test.rs +++ b/crates/goose/tests/mcp_integration_test.rs @@ -265,6 +265,7 @@ async fn test_replayed_session( mcpui: true, host_info: None, }, + true, )); #[allow(clippy::redundant_closure_call)] diff --git a/ui/goose2/src/shared/api/acpConnection.ts b/ui/goose2/src/shared/api/acpConnection.ts index e9cfa909..7abf58bc 100644 --- a/ui/goose2/src/shared/api/acpConnection.ts +++ b/ui/goose2/src/shared/api/acpConnection.ts @@ -86,6 +86,9 @@ async function initializeConnection(): Promise { const tInit = performance.now(); await client.initialize({ protocolVersion: PROTOCOL_VERSION, + _meta: { + "goose/useLoginShellPath": true, + }, clientCapabilities: { _meta: { goose: {