fix(coding-agent): resolve shell config from session settings
Stop shell resolution from consulting ambient process.cwd() during bash execution and use the active session's shellPath setting instead. closes #3452
This commit is contained in:
@@ -2320,6 +2320,7 @@ export class AgentSession {
|
||||
}): void {
|
||||
const autoResizeImages = this.settingsManager.getImageAutoResize();
|
||||
const shellCommandPrefix = this.settingsManager.getShellCommandPrefix();
|
||||
const shellPath = this.settingsManager.getShellPath();
|
||||
const baseToolDefinitions = this._baseToolsOverride
|
||||
? Object.fromEntries(
|
||||
Object.entries(this._baseToolsOverride).map(([name, tool]) => [
|
||||
@@ -2329,7 +2330,7 @@ export class AgentSession {
|
||||
)
|
||||
: createAllToolDefinitions(this._cwd, {
|
||||
read: { autoResizeImages },
|
||||
bash: { commandPrefix: shellCommandPrefix },
|
||||
bash: { commandPrefix: shellCommandPrefix, shellPath },
|
||||
});
|
||||
|
||||
this._baseToolDefinitions = new Map(
|
||||
@@ -2551,13 +2552,14 @@ export class AgentSession {
|
||||
|
||||
// Apply command prefix if configured (e.g., "shopt -s expand_aliases" for alias support)
|
||||
const prefix = this.settingsManager.getShellCommandPrefix();
|
||||
const shellPath = this.settingsManager.getShellPath();
|
||||
const resolvedCommand = prefix ? `${prefix}\n${command}` : command;
|
||||
|
||||
try {
|
||||
const result = await executeBashWithOperations(
|
||||
resolvedCommand,
|
||||
this.sessionManager.getCwd(),
|
||||
options?.operations ?? createLocalBashOperations(),
|
||||
options?.operations ?? createLocalBashOperations({ shellPath }),
|
||||
{
|
||||
onChunk,
|
||||
signal: this._bashAbortController.signal,
|
||||
|
||||
@@ -72,11 +72,11 @@ export interface BashOperations {
|
||||
* This is useful for extensions that intercept user_bash and still want pi's
|
||||
* standard local shell behavior while wrapping or rewriting commands.
|
||||
*/
|
||||
export function createLocalBashOperations(): BashOperations {
|
||||
export function createLocalBashOperations(options?: { shellPath?: string }): BashOperations {
|
||||
return {
|
||||
exec: (command, cwd, { onData, signal, timeout, env }) => {
|
||||
return new Promise((resolve, reject) => {
|
||||
const { shell, args } = getShellConfig();
|
||||
const { shell, args } = getShellConfig(options?.shellPath);
|
||||
if (!existsSync(cwd)) {
|
||||
reject(new Error(`Working directory does not exist: ${cwd}\nCannot execute bash commands.`));
|
||||
return;
|
||||
@@ -154,6 +154,8 @@ export interface BashToolOptions {
|
||||
operations?: BashOperations;
|
||||
/** Command prefix prepended to every command (for example shell setup commands) */
|
||||
commandPrefix?: string;
|
||||
/** Optional explicit shell path from settings */
|
||||
shellPath?: string;
|
||||
/** Hook to adjust command, cwd, or env before execution */
|
||||
spawnHook?: BashSpawnHook;
|
||||
}
|
||||
@@ -272,7 +274,7 @@ export function createBashToolDefinition(
|
||||
cwd: string,
|
||||
options?: BashToolOptions,
|
||||
): ToolDefinition<typeof bashSchema, BashToolDetails | undefined, BashRenderState> {
|
||||
const ops = options?.operations ?? createLocalBashOperations();
|
||||
const ops = options?.operations ?? createLocalBashOperations({ shellPath: options?.shellPath });
|
||||
const commandPrefix = options?.commandPrefix;
|
||||
const spawnHook = options?.spawnHook;
|
||||
return {
|
||||
|
||||
Reference in New Issue
Block a user