mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-21 01:07:46 +00:00
feat(core): refactor shell execution to use node-pty (#6491)
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
@@ -65,7 +65,10 @@ describe('useShellCommandProcessor', () => {
|
||||
setPendingHistoryItemMock = vi.fn();
|
||||
onExecMock = vi.fn();
|
||||
onDebugMessageMock = vi.fn();
|
||||
mockConfig = { getTargetDir: () => '/test/dir' } as Config;
|
||||
mockConfig = {
|
||||
getTargetDir: () => '/test/dir',
|
||||
getShouldUseNodePtyShell: () => false,
|
||||
} as Config;
|
||||
mockGeminiClient = { addHistory: vi.fn() } as unknown as GeminiClient;
|
||||
|
||||
vi.mocked(os.platform).mockReturnValue('linux');
|
||||
@@ -104,13 +107,12 @@ describe('useShellCommandProcessor', () => {
|
||||
): ShellExecutionResult => ({
|
||||
rawOutput: Buffer.from(overrides.output || ''),
|
||||
output: 'Success',
|
||||
stdout: 'Success',
|
||||
stderr: '',
|
||||
exitCode: 0,
|
||||
signal: null,
|
||||
error: null,
|
||||
aborted: false,
|
||||
pid: 12345,
|
||||
executionMethod: 'child_process',
|
||||
...overrides,
|
||||
});
|
||||
|
||||
@@ -141,6 +143,7 @@ describe('useShellCommandProcessor', () => {
|
||||
'/test/dir',
|
||||
expect.any(Function),
|
||||
expect.any(Object),
|
||||
false,
|
||||
);
|
||||
expect(onExecMock).toHaveBeenCalledWith(expect.any(Promise));
|
||||
});
|
||||
@@ -223,7 +226,6 @@ describe('useShellCommandProcessor', () => {
|
||||
act(() => {
|
||||
mockShellOutputCallback({
|
||||
type: 'data',
|
||||
stream: 'stdout',
|
||||
chunk: 'hello',
|
||||
});
|
||||
});
|
||||
@@ -238,7 +240,6 @@ describe('useShellCommandProcessor', () => {
|
||||
act(() => {
|
||||
mockShellOutputCallback({
|
||||
type: 'data',
|
||||
stream: 'stdout',
|
||||
chunk: ' world',
|
||||
});
|
||||
});
|
||||
@@ -319,6 +320,7 @@ describe('useShellCommandProcessor', () => {
|
||||
'/test/dir',
|
||||
expect.any(Function),
|
||||
expect.any(Object),
|
||||
false,
|
||||
);
|
||||
});
|
||||
|
||||
|
||||
@@ -101,10 +101,11 @@ export const useShellCommandProcessor = (
|
||||
commandToExecute = `{ ${command} }; __code=$?; pwd > "${pwdFilePath}"; exit $__code`;
|
||||
}
|
||||
|
||||
const execPromise = new Promise<void>((resolve) => {
|
||||
const executeCommand = async (
|
||||
resolve: (value: void | PromiseLike<void>) => void,
|
||||
) => {
|
||||
let lastUpdateTime = Date.now();
|
||||
let cumulativeStdout = '';
|
||||
let cumulativeStderr = '';
|
||||
let isBinaryStream = false;
|
||||
let binaryBytesReceived = 0;
|
||||
|
||||
@@ -134,7 +135,7 @@ export const useShellCommandProcessor = (
|
||||
onDebugMessage(`Executing in ${targetDir}: ${commandToExecute}`);
|
||||
|
||||
try {
|
||||
const { pid, result } = ShellExecutionService.execute(
|
||||
const { pid, result } = await ShellExecutionService.execute(
|
||||
commandToExecute,
|
||||
targetDir,
|
||||
(event) => {
|
||||
@@ -142,11 +143,7 @@ export const useShellCommandProcessor = (
|
||||
case 'data':
|
||||
// Do not process text data if we've already switched to binary mode.
|
||||
if (isBinaryStream) break;
|
||||
if (event.stream === 'stdout') {
|
||||
cumulativeStdout += event.chunk;
|
||||
} else {
|
||||
cumulativeStderr += event.chunk;
|
||||
}
|
||||
cumulativeStdout += event.chunk;
|
||||
break;
|
||||
case 'binary_detected':
|
||||
isBinaryStream = true;
|
||||
@@ -172,9 +169,7 @@ export const useShellCommandProcessor = (
|
||||
'[Binary output detected. Halting stream...]';
|
||||
}
|
||||
} else {
|
||||
currentDisplayOutput =
|
||||
cumulativeStdout +
|
||||
(cumulativeStderr ? `\n${cumulativeStderr}` : '');
|
||||
currentDisplayOutput = cumulativeStdout;
|
||||
}
|
||||
|
||||
// Throttle pending UI updates to avoid excessive re-renders.
|
||||
@@ -192,6 +187,7 @@ export const useShellCommandProcessor = (
|
||||
}
|
||||
},
|
||||
abortSignal,
|
||||
config.getShouldUseNodePtyShell(),
|
||||
);
|
||||
|
||||
executionPid = pid;
|
||||
@@ -295,6 +291,10 @@ export const useShellCommandProcessor = (
|
||||
|
||||
resolve(); // Resolve the promise to unblock `onExec`
|
||||
}
|
||||
};
|
||||
|
||||
const execPromise = new Promise<void>((resolve) => {
|
||||
executeCommand(resolve);
|
||||
});
|
||||
|
||||
onExec(execPromise);
|
||||
|
||||
Reference in New Issue
Block a user