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
+53
View File
@@ -34,6 +34,7 @@ import {
getAllGeminiMdFilenames,
AuthType,
clearCachedCredentialFile,
ShellExecutionService,
} from '@google/gemini-cli-core';
import { validateAuthMethod } from '../config/auth.js';
import { loadHierarchicalGeminiMemory } from '../config/config.js';
@@ -97,6 +98,18 @@ interface AppContainerProps {
initializationResult: InitializationResult;
}
/**
* The fraction of the terminal width to allocate to the shell.
* This provides horizontal padding.
*/
const SHELL_WIDTH_FRACTION = 0.89;
/**
* The number of lines to subtract from the available terminal height
* for the shell. This provides vertical padding and space for other UI elements.
*/
const SHELL_HEIGHT_PADDING = 10;
export const AppContainer = (props: AppContainerProps) => {
const { settings, config, initializationResult } = props;
const historyManager = useHistory();
@@ -110,6 +123,8 @@ export const AppContainer = (props: AppContainerProps) => {
initializationResult.themeError,
);
const [isProcessing, setIsProcessing] = useState<boolean>(false);
const [shellFocused, setShellFocused] = useState(false);
const [geminiMdFileCount, setGeminiMdFileCount] = useState<number>(
initializationResult.geminiMdFileCount,
);
@@ -506,6 +521,7 @@ Logging in with Google... Please restart Gemini CLI to continue.
pendingHistoryItems: pendingGeminiHistoryItems,
thought,
cancelOngoingRequest,
activePtyId,
loopDetectionConfirmationRequest,
} = useGeminiStream(
config.getGeminiClient(),
@@ -523,6 +539,10 @@ Logging in with Google... Please restart Gemini CLI to continue.
setModelSwitchedFromQuotaError,
refreshStatic,
() => cancelHandlerRef.current(),
setShellFocused,
terminalWidth,
terminalHeight,
shellFocused,
);
const { messageQueue, addMessage, clearQueue, getQueuedMessagesText } =
@@ -603,6 +623,13 @@ Logging in with Google... Please restart Gemini CLI to continue.
return terminalHeight - staticExtraHeight;
}, [terminalHeight]);
config.setShellExecutionConfig({
terminalWidth: Math.floor(terminalWidth * SHELL_WIDTH_FRACTION),
terminalHeight: Math.floor(availableTerminalHeight - SHELL_HEIGHT_PADDING),
pager: settings.merged.tools?.shell?.pager,
showColor: settings.merged.tools?.shell?.showColor,
});
const isFocused = useFocus();
useBracketedPaste();
@@ -620,6 +647,22 @@ Logging in with Google... Please restart Gemini CLI to continue.
const initialPromptSubmitted = useRef(false);
const geminiClient = config.getGeminiClient();
useEffect(() => {
if (activePtyId) {
ShellExecutionService.resizePty(
activePtyId,
Math.floor(terminalWidth * SHELL_WIDTH_FRACTION),
Math.floor(availableTerminalHeight - SHELL_HEIGHT_PADDING),
);
}
}, [
terminalHeight,
terminalWidth,
availableTerminalHeight,
activePtyId,
geminiClient,
]);
useEffect(() => {
if (
initialPrompt &&
@@ -840,6 +883,10 @@ Logging in with Google... Please restart Gemini CLI to continue.
!enteringConstrainHeightMode
) {
setConstrainHeight(false);
} else if (keyMatchers[Command.TOGGLE_SHELL_INPUT_FOCUS](key)) {
if (activePtyId || shellFocused) {
setShellFocused((prev) => !prev);
}
}
},
[
@@ -866,6 +913,8 @@ Logging in with Google... Please restart Gemini CLI to continue.
isSettingsDialogOpen,
isFolderTrustDialogOpen,
showPrivacyNotice,
activePtyId,
shellFocused,
settings.merged.general?.debugKeystrokeLogging,
],
);
@@ -991,6 +1040,8 @@ Logging in with Google... Please restart Gemini CLI to continue.
updateInfo,
showIdeRestartPrompt,
isRestarting,
activePtyId,
shellFocused,
}),
[
historyManager.history,
@@ -1064,6 +1115,8 @@ Logging in with Google... Please restart Gemini CLI to continue.
showIdeRestartPrompt,
isRestarting,
currentModel,
activePtyId,
shellFocused,
],
);