feat(shell): enable interactive commands with virtual terminal (#6694)

This commit is contained in:
Gal Zahavi
2025-09-11 13:27:27 -07:00
committed by GitHub
parent 8969a232ec
commit 181898cb5d
43 changed files with 2345 additions and 324 deletions

View File

@@ -71,6 +71,7 @@ describe('ShellProcessor', () => {
getTargetDir: vi.fn().mockReturnValue('/test/dir'),
getApprovalMode: vi.fn().mockReturnValue(ApprovalMode.DEFAULT),
getShouldUseNodePtyShell: vi.fn().mockReturnValue(false),
getShellExecutionConfig: vi.fn().mockReturnValue({}),
};
context = createMockCommandContext({
@@ -147,6 +148,7 @@ describe('ShellProcessor', () => {
expect.any(Function),
expect.any(Object),
false,
expect.any(Object),
);
expect(result).toEqual([{ text: 'The current status is: On branch main' }]);
});
@@ -218,6 +220,7 @@ describe('ShellProcessor', () => {
expect.any(Function),
expect.any(Object),
false,
expect.any(Object),
);
expect(result).toEqual([{ text: 'Do something dangerous: deleted' }]);
});
@@ -410,6 +413,7 @@ describe('ShellProcessor', () => {
expect.any(Function),
expect.any(Object),
false,
expect.any(Object),
);
});
@@ -574,6 +578,7 @@ describe('ShellProcessor', () => {
expect.any(Function),
expect.any(Object),
false,
expect.any(Object),
);
expect(result).toEqual([{ text: 'Command: match found' }]);
@@ -598,6 +603,7 @@ describe('ShellProcessor', () => {
expect.any(Function),
expect.any(Object),
false,
expect.any(Object),
);
expect(result).toEqual([
@@ -668,6 +674,7 @@ describe('ShellProcessor', () => {
expect.any(Function),
expect.any(Object),
false,
expect.any(Object),
);
});
@@ -697,6 +704,7 @@ describe('ShellProcessor', () => {
expect.any(Function),
expect.any(Object),
false,
expect.any(Object),
);
});
});

View File

@@ -20,6 +20,7 @@ import {
SHORTHAND_ARGS_PLACEHOLDER,
} from './types.js';
import { extractInjections, type Injection } from './injectionParser.js';
import { themeManager } from '../../ui/themes/theme-manager.js';
export class ConfirmationRequiredError extends Error {
constructor(
@@ -159,12 +160,19 @@ export class ShellProcessor implements IPromptProcessor {
// Execute the resolved command (which already has ESCAPED input).
if (injection.resolvedCommand) {
const activeTheme = themeManager.getActiveTheme();
const shellExecutionConfig = {
...config.getShellExecutionConfig(),
defaultFg: activeTheme.colors.Foreground,
defaultBg: activeTheme.colors.Background,
};
const { result } = await ShellExecutionService.execute(
injection.resolvedCommand,
config.getTargetDir(),
() => {},
new AbortController().signal,
config.getShouldUseNodePtyShell(),
shellExecutionConfig,
);
const executionResult = await result;