@@ -266,125 +266,92 @@ export class AcpProcessManager implements AgentProcessManager<AcpProcessHandle,
266266 processedArgs . some ( ( arg ) => typeof arg === 'string' && arg . includes ( cmd ) )
267267 )
268268
269- // Define allowed environment variables whitelist for Node.js/UV commands
270- const allowedEnvVars = [
271- 'PATH' ,
272- 'path' ,
273- 'Path' ,
274- 'npm_config_registry' ,
275- 'npm_config_cache' ,
276- 'npm_config_prefix' ,
277- 'npm_config_tmp' ,
278- 'NPM_CONFIG_REGISTRY' ,
279- 'NPM_CONFIG_CACHE' ,
280- 'NPM_CONFIG_PREFIX' ,
281- 'NPM_CONFIG_TMP' ,
282- 'ANTHROPIC_BASE_URL' ,
283- 'ANTHROPIC_AUTH_TOKEN' ,
284- 'ANTHROPIC_MODEL' ,
285- 'OPENAI_BASE_URL' ,
286- 'OPENAI_API_KEY'
287- ]
288-
289269 const HOME_DIR = app . getPath ( 'home' )
290270 const env : Record < string , string > = { }
271+ Object . entries ( process . env ) . forEach ( ( [ key , value ] ) => {
272+ if ( value !== undefined && value !== '' ) {
273+ env [ key ] = value
274+ }
275+ } )
291276 let pathKey = process . platform === 'win32' ? 'Path' : 'PATH'
292277 let pathValue = ''
293278
294279 if ( isNodeCommand ) {
295- // Node.js/UV commands use whitelist processing
296- if ( process . env ) {
297- const existingPaths : string [ ] = [ ]
298-
299- // Collect all PATH-related values
300- Object . entries ( process . env ) . forEach ( ( [ key , value ] ) => {
301- if ( value !== undefined && value !== '' ) {
302- if ( [ 'PATH' , 'Path' , 'path' ] . includes ( key ) ) {
303- existingPaths . push ( value )
304- } else if ( allowedEnvVars . includes ( key ) && ! [ 'PATH' , 'Path' , 'path' ] . includes ( key ) ) {
305- env [ key ] = value
306- }
280+ // Node.js/UV commands need full environment propagation similar to ACP init
281+ const existingPaths : string [ ] = [ ]
282+ const pathKeys = [ 'PATH' , 'Path' , 'path' ]
283+ pathKeys . forEach ( ( key ) => {
284+ const value = env [ key ]
285+ if ( value ) {
286+ existingPaths . push ( value )
287+ }
288+ } )
289+
290+ // Get shell environment variables regardless of runtime choice
291+ let shellEnv : Record < string , string > = { }
292+ try {
293+ shellEnv = await getShellEnvironment ( )
294+ console . info ( `[ACP] Retrieved shell environment variables for agent ${ agent . id } ` )
295+ Object . entries ( shellEnv ) . forEach ( ( [ key , value ] ) => {
296+ if ( value !== undefined && value !== '' && ! pathKeys . includes ( key ) ) {
297+ env [ key ] = value
307298 }
308299 } )
300+ } catch ( error ) {
301+ console . warn (
302+ `[ACP] Failed to get shell environment variables for agent ${ agent . id } , using fallback:` ,
303+ error
304+ )
305+ }
309306
310- // Get shell environment variables when not using builtin runtime
311- // This ensures nvm/n/fnm/volta paths are available
312- let shellEnv : Record < string , string > = { }
313- if ( ! useBuiltinRuntime ) {
314- try {
315- shellEnv = await getShellEnvironment ( )
316- console . info ( `[ACP] Retrieved shell environment variables for agent ${ agent . id } ` )
317-
318- // Merge shell environment variables (except PATH which we handle separately)
319- Object . entries ( shellEnv ) . forEach ( ( [ key , value ] ) => {
320- if ( ! [ 'PATH' , 'Path' , 'path' ] . includes ( key ) && value ) {
321- env [ key ] = value
322- }
323- } )
324- } catch ( error ) {
325- console . warn (
326- `[ACP] Failed to get shell environment variables for agent ${ agent . id } , using fallback:` ,
327- error
328- )
329- }
330- }
307+ // Get shell PATH if available (priority: shell PATH > existing PATH)
308+ const shellPath = shellEnv . PATH || shellEnv . Path || shellEnv . path
309+ if ( shellPath ) {
310+ const shellPaths = shellPath . split ( process . platform === 'win32' ? ';' : ':' )
311+ existingPaths . unshift ( ...shellPaths )
312+ console . info ( `[ACP] Using shell PATH for agent ${ agent . id } (length: ${ shellPath . length } )` )
313+ }
331314
332- // Get shell PATH if available (priority: shell PATH > existing PATH)
333- const shellPath = shellEnv . PATH || shellEnv . Path
334- if ( shellPath ) {
335- // Use shell PATH as base, then merge existing paths
336- const shellPaths = shellPath . split ( process . platform === 'win32' ? ';' : ':' )
337- existingPaths . unshift ( ...shellPaths )
338- console . info ( `[ACP] Using shell PATH for agent ${ agent . id } (length: ${ shellPath . length } )` )
339- }
315+ // Get default paths
316+ const defaultPaths = this . runtimeHelper . getDefaultPaths ( HOME_DIR )
340317
341- // Get default paths
342- const defaultPaths = this . runtimeHelper . getDefaultPaths ( HOME_DIR )
343-
344- // Merge all paths (priority: shell PATH > existing PATH > default paths)
345- const allPaths = [ ...existingPaths , ...defaultPaths ]
346- // Add runtime paths only when using builtin runtime
347- if ( useBuiltinRuntime ) {
348- const uvRuntimePath = this . runtimeHelper . getUvRuntimePath ( )
349- const nodeRuntimePath = this . runtimeHelper . getNodeRuntimePath ( )
350- if ( process . platform === 'win32' ) {
351- // Windows platform only adds node and uv paths
352- if ( uvRuntimePath ) {
353- allPaths . unshift ( uvRuntimePath )
354- console . info ( `[ACP] Added UV runtime path to PATH: ${ uvRuntimePath } ` )
355- }
356- if ( nodeRuntimePath ) {
357- allPaths . unshift ( nodeRuntimePath )
358- console . info ( `[ACP] Added Node runtime path to PATH: ${ nodeRuntimePath } ` )
359- }
360- } else {
361- // Other platforms priority: node > uv
362- if ( uvRuntimePath ) {
363- allPaths . unshift ( uvRuntimePath )
364- console . info ( `[ACP] Added UV runtime path to PATH: ${ uvRuntimePath } ` )
365- }
366- if ( nodeRuntimePath ) {
367- const nodeBinPath = path . join ( nodeRuntimePath , 'bin' )
368- allPaths . unshift ( nodeBinPath )
369- console . info ( `[ACP] Added Node bin path to PATH: ${ nodeBinPath } ` )
370- }
318+ // Merge all paths (priority: shell PATH > existing PATH > default paths)
319+ const allPaths = [ ...existingPaths , ...defaultPaths ]
320+ // Add runtime paths only when using builtin runtime
321+ if ( useBuiltinRuntime ) {
322+ const uvRuntimePath = this . runtimeHelper . getUvRuntimePath ( )
323+ const nodeRuntimePath = this . runtimeHelper . getNodeRuntimePath ( )
324+ if ( process . platform === 'win32' ) {
325+ // Windows platform only adds node and uv paths
326+ if ( uvRuntimePath ) {
327+ allPaths . unshift ( uvRuntimePath )
328+ console . info ( `[ACP] Added UV runtime path to PATH: ${ uvRuntimePath } ` )
329+ }
330+ if ( nodeRuntimePath ) {
331+ allPaths . unshift ( nodeRuntimePath )
332+ console . info ( `[ACP] Added Node runtime path to PATH: ${ nodeRuntimePath } ` )
333+ }
334+ } else {
335+ // Other platforms priority: node > uv
336+ if ( uvRuntimePath ) {
337+ allPaths . unshift ( uvRuntimePath )
338+ console . info ( `[ACP] Added UV runtime path to PATH: ${ uvRuntimePath } ` )
339+ }
340+ if ( nodeRuntimePath ) {
341+ const nodeBinPath = path . join ( nodeRuntimePath , 'bin' )
342+ allPaths . unshift ( nodeBinPath )
343+ console . info ( `[ACP] Added Node bin path to PATH: ${ nodeBinPath } ` )
371344 }
372345 }
373-
374- // Normalize and set PATH
375- const normalized = this . runtimeHelper . normalizePathEnv ( allPaths )
376- pathKey = normalized . key
377- pathValue = normalized . value
378- env [ pathKey ] = pathValue
379346 }
347+
348+ // Normalize and set PATH
349+ const normalized = this . runtimeHelper . normalizePathEnv ( allPaths )
350+ pathKey = normalized . key
351+ pathValue = normalized . value
352+ env [ pathKey ] = pathValue
380353 } else {
381354 // Non Node.js/UV commands, preserve all system environment variables, only supplement PATH
382- Object . entries ( process . env ) . forEach ( ( [ key , value ] ) => {
383- if ( value !== undefined && value !== '' ) {
384- env [ key ] = value
385- }
386- } )
387-
388355 // Supplement PATH
389356 const existingPaths : string [ ] = [ ]
390357 if ( env . PATH ) {
0 commit comments