flag for login shell PATH (#9313)

This commit is contained in:
Jack Amadeo
2026-05-19 09:57:49 -04:00
committed by GitHub
parent 259b04d1d4
commit 7dbdfa43fa
12 changed files with 49 additions and 6 deletions
+16 -1
View File
@@ -244,6 +244,7 @@ pub struct GooseAcpAgent {
client_fs_capabilities: OnceCell<FileSystemCapabilities>, client_fs_capabilities: OnceCell<FileSystemCapabilities>,
client_terminal: OnceCell<bool>, client_terminal: OnceCell<bool>,
client_mcp_host_info: OnceCell<GooseMcpHostInfo>, client_mcp_host_info: OnceCell<GooseMcpHostInfo>,
use_login_shell_path: OnceCell<bool>,
config_dir: std::path::PathBuf, config_dir: std::path::PathBuf,
session_manager: Arc<SessionManager>, session_manager: Arc<SessionManager>,
permission_manager: Arc<PermissionManager>, permission_manager: Arc<PermissionManager>,
@@ -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<ExtensionConfig, String> { fn mcp_server_to_extension_config(mcp_server: McpServer) -> Result<ExtensionConfig, String> {
match mcp_server { match mcp_server {
McpServer::Stdio(stdio) => { McpServer::Stdio(stdio) => {
@@ -1179,6 +1188,7 @@ impl GooseAcpAgent {
client_fs_capabilities: OnceCell::new(), client_fs_capabilities: OnceCell::new(),
client_terminal: OnceCell::new(), client_terminal: OnceCell::new(),
client_mcp_host_info: OnceCell::new(), client_mcp_host_info: OnceCell::new(),
use_login_shell_path: OnceCell::new(),
config_dir: options.config_dir, config_dir: options.config_dir,
session_manager, session_manager,
permission_manager, permission_manager,
@@ -1421,6 +1431,7 @@ impl GooseAcpAgent {
.unwrap_or_default(); .unwrap_or_default();
let client_terminal = self.client_terminal.get().copied().unwrap_or(false); let client_terminal = self.client_terminal.get().copied().unwrap_or(false);
let client_mcp_host_info = self.client_mcp_host_info.get().cloned(); 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 provider_factory = Arc::clone(&self.provider_factory);
let disable_session_naming = self.disable_session_naming; let disable_session_naming = self.disable_session_naming;
let goose_platform = self.goose_platform.clone(); let goose_platform = self.goose_platform.clone();
@@ -1454,7 +1465,8 @@ impl GooseAcpAgent {
goose_platform, goose_platform,
) )
.with_mcp_host_info(client_mcp_host_info) .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 // Init provider — reuse the pre-resolved name + model when
@@ -2511,6 +2523,9 @@ impl GooseAcpAgent {
let _ = self let _ = self
.client_mcp_host_info .client_mcp_host_info
.set(extract_client_mcp_host_info(&args)); .set(extract_client_mcp_host_info(&args));
let _ = self
.use_login_shell_path
.set(extract_use_login_shell_path(&args));
let capabilities = AgentCapabilities::new() let capabilities = AgentCapabilities::new()
.load_session(true) .load_session(true)
+11
View File
@@ -150,6 +150,7 @@ pub struct AgentConfig {
pub goose_platform: GoosePlatform, pub goose_platform: GoosePlatform,
pub mcp_host_info: Option<GooseMcpHostInfo>, pub mcp_host_info: Option<GooseMcpHostInfo>,
pub session_name_update_tx: Option<mpsc::UnboundedSender<SessionNameUpdate>>, pub session_name_update_tx: Option<mpsc::UnboundedSender<SessionNameUpdate>>,
pub use_login_shell_path: Option<bool>,
} }
impl AgentConfig { impl AgentConfig {
@@ -170,6 +171,7 @@ impl AgentConfig {
goose_platform, goose_platform,
mcp_host_info: None, mcp_host_info: None,
session_name_update_tx: None, session_name_update_tx: None,
use_login_shell_path: None,
} }
} }
@@ -185,6 +187,11 @@ impl AgentConfig {
self.session_name_update_tx = tx; self.session_name_update_tx = tx;
self 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 /// The main goose Agent
@@ -295,6 +302,9 @@ impl Agent {
.unwrap_or_else(|| goose_platform.to_string()); .unwrap_or_else(|| goose_platform.to_string());
let session_manager = Arc::clone(&config.session_manager); let session_manager = Arc::clone(&config.session_manager);
let permission_manager = Arc::clone(&config.permission_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 { Self {
provider: provider.clone(), provider: provider.clone(),
config, config,
@@ -304,6 +314,7 @@ impl Agent {
session_manager, session_manager,
client_name, client_name,
capabilities, capabilities,
use_login_shell_path,
)), )),
final_output_tool: Arc::new(Mutex::new(None)), final_output_tool: Arc::new(Mutex::new(None)),
frontend_extensions: Mutex::new(HashMap::new()), frontend_extensions: Mutex::new(HashMap::new()),
@@ -741,6 +741,7 @@ impl ExtensionManager {
session_manager: Arc<crate::session::SessionManager>, session_manager: Arc<crate::session::SessionManager>,
client_name: String, client_name: String,
capabilities: ExtensionManagerCapabilities, capabilities: ExtensionManagerCapabilities,
use_login_shell_path: bool,
) -> Self { ) -> Self {
Self { Self {
extensions: Mutex::new(HashMap::new()), extensions: Mutex::new(HashMap::new()),
@@ -748,6 +749,7 @@ impl ExtensionManager {
extension_manager: None, extension_manager: None,
session_manager, session_manager,
session: None, session: None,
use_login_shell_path,
}, },
provider, provider,
tools_cache: Mutex::new(None), tools_cache: Mutex::new(None),
@@ -767,6 +769,7 @@ impl ExtensionManager {
mcpui: false, mcpui: false,
host_info: None, host_info: None,
}, },
false,
) )
} }
@@ -278,6 +278,7 @@ mod tests {
extension_manager: None, extension_manager: None,
session_manager: Arc::new(SessionManager::new(std::env::temp_dir())), session_manager: Arc::new(SessionManager::new(std::env::temp_dir())),
session: None, session: None,
use_login_shell_path: false,
} }
} }
@@ -64,14 +64,14 @@ fn developer_instructions() -> &'static str {
} }
impl DeveloperClient { impl DeveloperClient {
pub fn new(_context: PlatformExtensionContext) -> Result<Self> { pub fn new(context: PlatformExtensionContext) -> Result<Self> {
let info = InitializeResult::new(ServerCapabilities::builder().enable_tools().build()) let info = InitializeResult::new(ServerCapabilities::builder().enable_tools().build())
.with_server_info(Implementation::new(EXTENSION_NAME, "1.0.0").with_title("Developer")) .with_server_info(Implementation::new(EXTENSION_NAME, "1.0.0").with_title("Developer"))
.with_instructions(developer_instructions()); .with_instructions(developer_instructions());
Ok(Self { Ok(Self {
info, info,
shell_tool: Arc::new(ShellTool::new()?), shell_tool: Arc::new(ShellTool::new(context.use_login_shell_path)?),
edit_tools: Arc::new(EditTools::new()), edit_tools: Arc::new(EditTools::new()),
tree_tool: Arc::new(TreeTool::new()), tree_tool: Arc::new(TreeTool::new()),
}) })
@@ -240,6 +240,7 @@ mod tests {
extension_manager: None, extension_manager: None,
session_manager: Arc::new(SessionManager::new(data_dir)), session_manager: Arc::new(SessionManager::new(data_dir)),
session: None, session: None,
use_login_shell_path: false,
} }
} }
@@ -284,7 +284,6 @@ impl LoginPath {
} }
} }
#[cfg(test)]
fn resolved(value: Option<String>) -> Self { fn resolved(value: Option<String>) -> Self {
let cell = OnceCell::new(); let cell = OnceCell::new();
let _ = cell.set(value.map(Arc::from)); let _ = cell.set(value.map(Arc::from));
@@ -320,12 +319,16 @@ pub struct ShellTool {
} }
impl ShellTool { impl ShellTool {
pub fn new() -> std::io::Result<Self> { pub fn new(use_login_shell_path: bool) -> std::io::Result<Self> {
Ok(Self { Ok(Self {
output_dir: tempfile::tempdir()?, output_dir: tempfile::tempdir()?,
call_index: AtomicUsize::new(0), call_index: AtomicUsize::new(0),
#[cfg(not(windows))] #[cfg(not(windows))]
login_path: LoginPath::spawn(), login_path: if use_login_shell_path {
LoginPath::spawn()
} else {
LoginPath::resolved(None)
},
}) })
} }
@@ -212,6 +212,7 @@ pub struct PlatformExtensionContext {
Option<std::sync::Weak<crate::agents::extension_manager::ExtensionManager>>, Option<std::sync::Weak<crate::agents::extension_manager::ExtensionManager>>,
pub session_manager: std::sync::Arc<crate::session::SessionManager>, pub session_manager: std::sync::Arc<crate::session::SessionManager>,
pub session: Option<std::sync::Arc<Session>>, pub session: Option<std::sync::Arc<Session>>,
pub use_login_shell_path: bool,
} }
impl PlatformExtensionContext { impl PlatformExtensionContext {
@@ -1715,6 +1715,7 @@ mod tests {
extension_manager: None, extension_manager: None,
session_manager: Arc::new(crate::session::SessionManager::instance()), session_manager: Arc::new(crate::session::SessionManager::instance()),
session: None, session: None,
use_login_shell_path: false,
} }
} }
@@ -435,6 +435,7 @@ mod tests {
extension_manager: None, extension_manager: None,
session_manager, session_manager,
session: Some(Arc::new(session)), session: Some(Arc::new(session)),
use_login_shell_path: false,
}; };
let mut extensions: Vec<ExtensionInfo> = PLATFORM_EXTENSIONS let mut extensions: Vec<ExtensionInfo> = PLATFORM_EXTENSIONS
+2
View File
@@ -285,6 +285,7 @@ mod tests {
extension_manager: None, extension_manager: None,
session_manager: Arc::new(crate::session::SessionManager::instance()), session_manager: Arc::new(crate::session::SessionManager::instance()),
session: Some(session), session: Some(session),
use_login_shell_path: false,
}) })
.unwrap(); .unwrap();
@@ -311,6 +312,7 @@ mod tests {
extension_manager: None, extension_manager: None,
session_manager: Arc::new(crate::session::SessionManager::instance()), session_manager: Arc::new(crate::session::SessionManager::instance()),
session: None, session: None,
use_login_shell_path: false,
}) })
.unwrap(); .unwrap();
@@ -265,6 +265,7 @@ async fn test_replayed_session(
mcpui: true, mcpui: true,
host_info: None, host_info: None,
}, },
true,
)); ));
#[allow(clippy::redundant_closure_call)] #[allow(clippy::redundant_closure_call)]
@@ -86,6 +86,9 @@ async function initializeConnection(): Promise<GooseClient> {
const tInit = performance.now(); const tInit = performance.now();
await client.initialize({ await client.initialize({
protocolVersion: PROTOCOL_VERSION, protocolVersion: PROTOCOL_VERSION,
_meta: {
"goose/useLoginShellPath": true,
},
clientCapabilities: { clientCapabilities: {
_meta: { _meta: {
goose: { goose: {