mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-13 05:12:55 -07:00
fix(plan): persist the approval mode in UI even when agent is thinking (#18955)
This commit is contained in:
@@ -455,6 +455,23 @@ describe('Composer', () => {
|
|||||||
expect(output).toContain('LoadingIndicator');
|
expect(output).toContain('LoadingIndicator');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('renders both LoadingIndicator and ApprovalModeIndicator when streaming in full UI mode', () => {
|
||||||
|
const uiState = createMockUIState({
|
||||||
|
streamingState: StreamingState.Responding,
|
||||||
|
thought: {
|
||||||
|
subject: 'Thinking',
|
||||||
|
description: '',
|
||||||
|
},
|
||||||
|
showApprovalModeIndicator: ApprovalMode.PLAN,
|
||||||
|
});
|
||||||
|
|
||||||
|
const { lastFrame } = renderComposer(uiState);
|
||||||
|
|
||||||
|
const output = lastFrame();
|
||||||
|
expect(output).toContain('LoadingIndicator: Thinking');
|
||||||
|
expect(output).toContain('ApprovalModeIndicator');
|
||||||
|
});
|
||||||
|
|
||||||
it('does NOT render LoadingIndicator when embedded shell is focused and background shell is NOT visible', () => {
|
it('does NOT render LoadingIndicator when embedded shell is focused and background shell is NOT visible', () => {
|
||||||
const uiState = createMockUIState({
|
const uiState = createMockUIState({
|
||||||
streamingState: StreamingState.Responding,
|
streamingState: StreamingState.Responding,
|
||||||
@@ -937,4 +954,50 @@ describe('Composer', () => {
|
|||||||
expect(lastFrame()).not.toContain('ShortcutsHelp');
|
expect(lastFrame()).not.toContain('ShortcutsHelp');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('Snapshots', () => {
|
||||||
|
it('matches snapshot in idle state', () => {
|
||||||
|
const uiState = createMockUIState();
|
||||||
|
const { lastFrame } = renderComposer(uiState);
|
||||||
|
expect(lastFrame()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('matches snapshot while streaming', () => {
|
||||||
|
const uiState = createMockUIState({
|
||||||
|
streamingState: StreamingState.Responding,
|
||||||
|
thought: {
|
||||||
|
subject: 'Thinking',
|
||||||
|
description: 'Thinking about the meaning of life...',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
const { lastFrame } = renderComposer(uiState);
|
||||||
|
expect(lastFrame()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('matches snapshot in narrow view', () => {
|
||||||
|
const uiState = createMockUIState({
|
||||||
|
terminalWidth: 40,
|
||||||
|
});
|
||||||
|
const { lastFrame } = renderComposer(uiState);
|
||||||
|
expect(lastFrame()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('matches snapshot in minimal UI mode', () => {
|
||||||
|
const uiState = createMockUIState({
|
||||||
|
cleanUiDetailsVisible: false,
|
||||||
|
});
|
||||||
|
const { lastFrame } = renderComposer(uiState);
|
||||||
|
expect(lastFrame()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('matches snapshot in minimal UI mode while loading', () => {
|
||||||
|
const uiState = createMockUIState({
|
||||||
|
cleanUiDetailsVisible: false,
|
||||||
|
streamingState: StreamingState.Responding,
|
||||||
|
elapsedTime: 1000,
|
||||||
|
});
|
||||||
|
const { lastFrame } = renderComposer(uiState);
|
||||||
|
expect(lastFrame()).toMatchSnapshot();
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -141,8 +141,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
|||||||
settings.merged.ui.showShortcutsHint &&
|
settings.merged.ui.showShortcutsHint &&
|
||||||
!hideShortcutsHintForSuggestions &&
|
!hideShortcutsHintForSuggestions &&
|
||||||
!hideMinimalModeHintWhileBusy &&
|
!hideMinimalModeHintWhileBusy &&
|
||||||
!hasPendingActionRequired &&
|
!hasPendingActionRequired;
|
||||||
(!showUiDetails || !showLoadingIndicator);
|
|
||||||
const showMinimalModeBleedThrough =
|
const showMinimalModeBleedThrough =
|
||||||
!hideUiDetailsForSuggestions && Boolean(minimalModeBleedThrough);
|
!hideUiDetailsForSuggestions && Boolean(minimalModeBleedThrough);
|
||||||
const showMinimalInlineLoading = !showUiDetails && showLoadingIndicator;
|
const showMinimalInlineLoading = !showUiDetails && showLoadingIndicator;
|
||||||
@@ -189,7 +188,7 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
|||||||
marginLeft={1}
|
marginLeft={1}
|
||||||
marginRight={isNarrow ? 0 : 1}
|
marginRight={isNarrow ? 0 : 1}
|
||||||
flexDirection="row"
|
flexDirection="row"
|
||||||
alignItems="center"
|
alignItems={isNarrow ? 'flex-start' : 'center'}
|
||||||
flexGrow={1}
|
flexGrow={1}
|
||||||
>
|
>
|
||||||
{showUiDetails && showLoadingIndicator && (
|
{showUiDetails && showLoadingIndicator && (
|
||||||
@@ -326,7 +325,6 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
|||||||
{hasToast ? (
|
{hasToast ? (
|
||||||
<ToastDisplay />
|
<ToastDisplay />
|
||||||
) : (
|
) : (
|
||||||
!showLoadingIndicator && (
|
|
||||||
<Box
|
<Box
|
||||||
flexDirection={isNarrow ? 'column' : 'row'}
|
flexDirection={isNarrow ? 'column' : 'row'}
|
||||||
alignItems={isNarrow ? 'flex-start' : 'center'}
|
alignItems={isNarrow ? 'flex-start' : 'center'}
|
||||||
@@ -337,9 +335,13 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
|||||||
isPlanEnabled={config.isPlanEnabled()}
|
isPlanEnabled={config.isPlanEnabled()}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{!showLoadingIndicator && (
|
||||||
|
<>
|
||||||
{uiState.shellModeActive && (
|
{uiState.shellModeActive && (
|
||||||
<Box
|
<Box
|
||||||
marginLeft={showApprovalIndicator && !isNarrow ? 1 : 0}
|
marginLeft={
|
||||||
|
showApprovalIndicator && !isNarrow ? 1 : 0
|
||||||
|
}
|
||||||
marginTop={showApprovalIndicator && isNarrow ? 1 : 0}
|
marginTop={showApprovalIndicator && isNarrow ? 1 : 0}
|
||||||
>
|
>
|
||||||
<ShellModeIndicator />
|
<ShellModeIndicator />
|
||||||
@@ -348,13 +350,15 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
|||||||
{showRawMarkdownIndicator && (
|
{showRawMarkdownIndicator && (
|
||||||
<Box
|
<Box
|
||||||
marginLeft={
|
marginLeft={
|
||||||
(showApprovalIndicator || uiState.shellModeActive) &&
|
(showApprovalIndicator ||
|
||||||
|
uiState.shellModeActive) &&
|
||||||
!isNarrow
|
!isNarrow
|
||||||
? 1
|
? 1
|
||||||
: 0
|
: 0
|
||||||
}
|
}
|
||||||
marginTop={
|
marginTop={
|
||||||
(showApprovalIndicator || uiState.shellModeActive) &&
|
(showApprovalIndicator ||
|
||||||
|
uiState.shellModeActive) &&
|
||||||
isNarrow
|
isNarrow
|
||||||
? 1
|
? 1
|
||||||
: 0
|
: 0
|
||||||
@@ -363,8 +367,9 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => {
|
|||||||
<RawMarkdownIndicator />
|
<RawMarkdownIndicator />
|
||||||
</Box>
|
</Box>
|
||||||
)}
|
)}
|
||||||
|
</>
|
||||||
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
)
|
|
||||||
)}
|
)}
|
||||||
</Box>
|
</Box>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,44 @@
|
|||||||
|
// Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html
|
||||||
|
|
||||||
|
exports[`Composer > Snapshots > matches snapshot in idle state 1`] = `
|
||||||
|
"
|
||||||
|
ShortcutsHint
|
||||||
|
────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
ApprovalModeIndicator StatusDisplay
|
||||||
|
InputPrompt: Type your message or @path/to/file
|
||||||
|
Footer"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Composer > Snapshots > matches snapshot in minimal UI mode 1`] = `
|
||||||
|
"
|
||||||
|
ShortcutsHint
|
||||||
|
InputPrompt: Type your message or @path/to/file"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Composer > Snapshots > matches snapshot in minimal UI mode while loading 1`] = `
|
||||||
|
"
|
||||||
|
LoadingIndicator
|
||||||
|
InputPrompt: Type your message or @path/to/file"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Composer > Snapshots > matches snapshot in narrow view 1`] = `
|
||||||
|
"
|
||||||
|
|
||||||
|
ShortcutsHint
|
||||||
|
────────────────────────────────────────
|
||||||
|
ApprovalModeIndicator
|
||||||
|
|
||||||
|
StatusDisplay
|
||||||
|
InputPrompt: Type your message or
|
||||||
|
@path/to/file
|
||||||
|
Footer"
|
||||||
|
`;
|
||||||
|
|
||||||
|
exports[`Composer > Snapshots > matches snapshot while streaming 1`] = `
|
||||||
|
"
|
||||||
|
LoadingIndicator: Thinking ShortcutsHint
|
||||||
|
────────────────────────────────────────────────────────────────────────────────────────────────────
|
||||||
|
ApprovalModeIndicator
|
||||||
|
InputPrompt: Type your message or @path/to/file
|
||||||
|
Footer"
|
||||||
|
`;
|
||||||
Reference in New Issue
Block a user