mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-04-20 02:00:40 -07:00
Shell approval rework (#11073)
This commit is contained in:
@@ -24,9 +24,14 @@ const mockSerializeTerminalToObject = vi.hoisted(() => vi.fn());
|
||||
vi.mock('@lydell/node-pty', () => ({
|
||||
spawn: mockPtySpawn,
|
||||
}));
|
||||
vi.mock('child_process', () => ({
|
||||
spawn: mockCpSpawn,
|
||||
}));
|
||||
vi.mock('node:child_process', async (importOriginal) => {
|
||||
const actual =
|
||||
(await importOriginal()) as typeof import('node:child_process');
|
||||
return {
|
||||
...actual,
|
||||
spawn: mockCpSpawn,
|
||||
};
|
||||
});
|
||||
vi.mock('../utils/textUtils.js', () => ({
|
||||
isBinary: mockIsBinary,
|
||||
}));
|
||||
@@ -465,15 +470,15 @@ describe('ShellExecutionService', () => {
|
||||
});
|
||||
|
||||
describe('Platform-Specific Behavior', () => {
|
||||
it('should use cmd.exe on Windows', async () => {
|
||||
it('should use powershell.exe on Windows', async () => {
|
||||
mockPlatform.mockReturnValue('win32');
|
||||
await simulateExecution('dir "foo bar"', (pty) =>
|
||||
pty.onExit.mock.calls[0][0]({ exitCode: 0, signal: null }),
|
||||
);
|
||||
|
||||
expect(mockPtySpawn).toHaveBeenCalledWith(
|
||||
'cmd.exe',
|
||||
'/c dir "foo bar"',
|
||||
'powershell.exe',
|
||||
['-NoProfile', '-Command', 'dir "foo bar"'],
|
||||
expect.any(Object),
|
||||
);
|
||||
});
|
||||
@@ -637,9 +642,9 @@ describe('ShellExecutionService child_process fallback', () => {
|
||||
});
|
||||
|
||||
expect(mockCpSpawn).toHaveBeenCalledWith(
|
||||
'ls -l',
|
||||
[],
|
||||
expect.objectContaining({ shell: 'bash' }),
|
||||
'bash',
|
||||
['-c', 'ls -l'],
|
||||
expect.objectContaining({ shell: false, detached: true }),
|
||||
);
|
||||
expect(result.exitCode).toBe(0);
|
||||
expect(result.signal).toBeNull();
|
||||
@@ -905,18 +910,19 @@ describe('ShellExecutionService child_process fallback', () => {
|
||||
});
|
||||
|
||||
describe('Platform-Specific Behavior', () => {
|
||||
it('should use cmd.exe on Windows', async () => {
|
||||
it('should use powershell.exe on Windows', async () => {
|
||||
mockPlatform.mockReturnValue('win32');
|
||||
await simulateExecution('dir "foo bar"', (cp) =>
|
||||
cp.emit('exit', 0, null),
|
||||
);
|
||||
|
||||
expect(mockCpSpawn).toHaveBeenCalledWith(
|
||||
'dir "foo bar"',
|
||||
[],
|
||||
'powershell.exe',
|
||||
['-NoProfile', '-Command', 'dir "foo bar"'],
|
||||
expect.objectContaining({
|
||||
shell: true,
|
||||
shell: false,
|
||||
detached: false,
|
||||
windowsVerbatimArguments: false,
|
||||
}),
|
||||
);
|
||||
});
|
||||
@@ -926,10 +932,10 @@ describe('ShellExecutionService child_process fallback', () => {
|
||||
await simulateExecution('ls "foo bar"', (cp) => cp.emit('exit', 0, null));
|
||||
|
||||
expect(mockCpSpawn).toHaveBeenCalledWith(
|
||||
'ls "foo bar"',
|
||||
[],
|
||||
'bash',
|
||||
['-c', 'ls "foo bar"'],
|
||||
expect.objectContaining({
|
||||
shell: 'bash',
|
||||
shell: false,
|
||||
detached: true,
|
||||
}),
|
||||
);
|
||||
|
||||
@@ -12,6 +12,7 @@ import { TextDecoder } from 'node:util';
|
||||
import os from 'node:os';
|
||||
import type { IPty } from '@lydell/node-pty';
|
||||
import { getCachedEncodingForBuffer } from '../utils/systemEncoding.js';
|
||||
import { getShellConfiguration } from '../utils/shell-utils.js';
|
||||
import { isBinary } from '../utils/textUtils.js';
|
||||
import pkg from '@xterm/headless';
|
||||
import {
|
||||
@@ -189,12 +190,14 @@ export class ShellExecutionService {
|
||||
): ShellExecutionHandle {
|
||||
try {
|
||||
const isWindows = os.platform() === 'win32';
|
||||
const { executable, argsPrefix } = getShellConfiguration();
|
||||
const spawnArgs = [...argsPrefix, commandToExecute];
|
||||
|
||||
const child = cpSpawn(commandToExecute, [], {
|
||||
const child = cpSpawn(executable, spawnArgs, {
|
||||
cwd,
|
||||
stdio: ['ignore', 'pipe', 'pipe'],
|
||||
windowsVerbatimArguments: true,
|
||||
shell: isWindows ? true : 'bash',
|
||||
windowsVerbatimArguments: isWindows ? false : undefined,
|
||||
shell: false,
|
||||
detached: !isWindows,
|
||||
env: {
|
||||
...process.env,
|
||||
@@ -400,13 +403,10 @@ export class ShellExecutionService {
|
||||
try {
|
||||
const cols = shellExecutionConfig.terminalWidth ?? 80;
|
||||
const rows = shellExecutionConfig.terminalHeight ?? 30;
|
||||
const isWindows = os.platform() === 'win32';
|
||||
const shell = isWindows ? 'cmd.exe' : 'bash';
|
||||
const args = isWindows
|
||||
? `/c ${commandToExecute}`
|
||||
: ['-c', commandToExecute];
|
||||
const { executable, argsPrefix } = getShellConfiguration();
|
||||
const args = [...argsPrefix, commandToExecute];
|
||||
|
||||
const ptyProcess = ptyInfo.module.spawn(shell, args, {
|
||||
const ptyProcess = ptyInfo.module.spawn(executable, args, {
|
||||
cwd,
|
||||
name: 'xterm',
|
||||
cols,
|
||||
|
||||
Reference in New Issue
Block a user