fix(plan): persist the approval mode in UI even when agent is thinking (#18955)

This commit is contained in:
Adib234
2026-02-13 15:02:39 -05:00
committed by GitHub
parent c2f62b2a2b
commit f460ab841d
3 changed files with 154 additions and 42 deletions
@@ -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();
});
});
}); });
+13 -8
View File
@@ -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"
`;