refactor(cli): unify Escape key handling in AppContainer

Consolidate Escape key behavior to improve UX and prevent conflicts:

- Move Escape handling from useGeminiStream to AppContainer
- Input with content: double-press to clear, then single-press to cancel
- Empty input: single-press immediately cancels ongoing request
- Preserve embeddedShellFocused check to allow shell's own escape handling
- Update tests to use cancelOngoingRequest directly instead of simulating keypress

Fixes inconsistent escape behavior between input clearing and request cancellation.

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
This commit is contained in:
mingholy.lmh 2026-02-12 20:20:51 +08:00
parent 76d31d50c4
commit e7290c5d9a
3 changed files with 74 additions and 51 deletions

View file

@ -63,7 +63,6 @@ import {
import { promises as fs } from 'node:fs';
import path from 'node:path';
import { useSessionStats } from '../contexts/SessionContext.js';
import { useKeypress } from './useKeypress.js';
import type { LoadedSettings } from '../../config/settings.js';
const debugLogger = createDebugLogger('GEMINI_STREAM');
@ -115,7 +114,6 @@ export const useGeminiStream = (
persistSessionModel?: string;
showGuidance?: boolean;
}>,
isShellFocused?: boolean,
) => {
const [initError, setInitError] = useState<string | null>(null);
const abortControllerRef = useRef<AbortController | null>(null);
@ -309,15 +307,6 @@ export const useGeminiStream = (
getPromptCount,
]);
useKeypress(
(key) => {
if (key.name === 'escape' && !isShellFocused) {
cancelOngoingRequest();
}
},
{ isActive: streamingState === StreamingState.Responding },
);
const prepareQueryForGemini = useCallback(
async (
query: PartListUnion,