1+ use anyhow:: anyhow;
12use base64:: Engine ;
23use ignore:: gitignore:: { Gitignore , GitignoreBuilder } ;
34use include_dir:: { include_dir, Dir } ;
@@ -17,6 +18,8 @@ use rmcp::{
1718use serde:: { Deserialize , Serialize } ;
1819use std:: {
1920 collections:: HashMap ,
21+ env:: join_paths,
22+ ffi:: OsString ,
2023 future:: Future ,
2124 io:: Cursor ,
2225 path:: { Path , PathBuf } ,
@@ -31,11 +34,11 @@ use tokio::{
3134use tokio_stream:: { wrappers:: SplitStream , StreamExt as _} ;
3235use tokio_util:: sync:: CancellationToken ;
3336
37+ use crate :: developer:: { paths:: get_shell_path_dirs, shell:: ShellConfig } ;
38+
3439use super :: analyze:: { types:: AnalyzeParams , CodeAnalyzer } ;
3540use super :: editor_models:: { create_editor_model, EditorModel } ;
36- use super :: shell:: {
37- configure_shell_command, expand_path, get_shell_config, is_absolute_path, kill_process_group,
38- } ;
41+ use super :: shell:: { configure_shell_command, expand_path, is_absolute_path, kill_process_group} ;
3942use super :: text_editor:: {
4043 text_editor_insert, text_editor_replace, text_editor_undo, text_editor_view, text_editor_write,
4144} ;
@@ -179,6 +182,8 @@ pub struct DeveloperServer {
179182 pub running_processes : Arc < RwLock < HashMap < String , CancellationToken > > > ,
180183 #[ cfg( not( test) ) ]
181184 running_processes : Arc < RwLock < HashMap < String , CancellationToken > > > ,
185+ bash_env_file : Option < PathBuf > ,
186+ extend_path_with_shell : bool ,
182187}
183188
184189#[ tool_handler( router = self . tool_router) ]
@@ -549,9 +554,21 @@ impl DeveloperServer {
549554 prompts : load_prompt_files ( ) ,
550555 code_analyzer : CodeAnalyzer :: new ( ) ,
551556 running_processes : Arc :: new ( RwLock :: new ( HashMap :: new ( ) ) ) ,
557+ extend_path_with_shell : false ,
558+ bash_env_file : None ,
552559 }
553560 }
554561
562+ pub fn extend_path_with_shell ( mut self , value : bool ) -> Self {
563+ self . extend_path_with_shell = value;
564+ self
565+ }
566+
567+ pub fn bash_env_file ( mut self , value : Option < PathBuf > ) -> Self {
568+ self . bash_env_file = value;
569+ self
570+ }
571+
555572 /// List all available windows that can be used with screen_capture.
556573 /// Returns a list of window titles that can be used with the window_title parameter
557574 /// of the screen_capture tool.
@@ -942,10 +959,34 @@ impl DeveloperServer {
942959 peer : & rmcp:: service:: Peer < RoleServer > ,
943960 cancellation_token : CancellationToken ,
944961 ) -> Result < String , ErrorData > {
945- // Get platform-specific shell configuration
946- let shell_config = get_shell_config ( ) ;
962+ let mut shell_config = ShellConfig :: default ( ) ;
963+ let shell_name = std:: path:: Path :: new ( & shell_config. executable )
964+ . file_name ( )
965+ . and_then ( |s| s. to_str ( ) )
966+ . unwrap_or ( "bash" ) ;
967+
968+ if let Some ( ref env_file) = self . bash_env_file {
969+ if shell_name == "bash" {
970+ shell_config. envs . push ( (
971+ OsString :: from ( "BASH_ENV" ) ,
972+ env_file. clone ( ) . into_os_string ( ) ,
973+ ) )
974+ }
975+ }
976+
977+ let mut command = configure_shell_command ( & shell_config, command) ;
978+
979+ if self . extend_path_with_shell {
980+ if let Err ( e) = get_shell_path_dirs ( )
981+ . await
982+ . and_then ( |dirs| join_paths ( dirs) . map_err ( |e| anyhow ! ( e) ) )
983+ . map ( |path| command. env ( "PATH" , path) )
984+ {
985+ tracing:: error!( "Failed to extend PATH with shell directories: {}" , e)
986+ }
987+ }
947988
948- let mut child = configure_shell_command ( & shell_config , command)
989+ let mut child = command
949990 . spawn ( )
950991 . map_err ( |e| ErrorData :: new ( ErrorCode :: INTERNAL_ERROR , e. to_string ( ) , None ) ) ?;
951992
0 commit comments