diff --git a/composer-layout-spec.md b/composer-layout-spec.md new file mode 100644 index 0000000000..eb4ede2799 --- /dev/null +++ b/composer-layout-spec.md @@ -0,0 +1,63 @@ +# Layout Refinement: Approval Mode & Composer Organization + +## Goal + +The primary objective is to streamline the main interaction area by moving the +Approval Mode status to the footer and reorganizing the remaining status +indicators within the Composer for a better information hierarchy. + +## Phase 1: The Move (Approval Mode to Footer) + +The `ApprovalModeIndicator` (manual, auto-accept, plan, YOLO) is removed +entirely from the Composer component and its "bleed-through" logic. It is +repositioned as the absolute first item (far left) in the application footer. + +- **Header:** `mode (Shift+Tab)` +- **Data:** Streamlined labels (`manual`, `auto-accept`, `plan`, `YOLO`) using + the existing semantic colors. +- **Default:** Visible by default for all users. + +## Phase 2: The Swap (Composer Internal Layout) + +Once the `ApprovalModeIndicator` is removed, the remaining transient and state +elements within the Composer are swapped across the horizontal divider. + +### 1. The "Above Divider" Zone (Transient Environment) + +This area is for transient notifications that contextualize the current +environment but are not the active process. + +- **Toast Messages:** (e.g., "Press Ctrl+C again to exit") +- **Shell Mode Indicator** +- **Raw Markdown Indicator** +- **Shortcuts Hint:** Remains flush right. + +### 2. The "Below Divider" Zone (Active Processing) + +This area is reserved exclusively for what the application is _currently doing_. +It sits directly above the input prompt. + +- **Loading Indicator:** (e.g., "Thinking...", "Executing Hooks") +- **Status Display:** (Context usage summary) + +## Target Layout Mockup + +```text +[ConfigInitDisplay] +[QueuedMessageDisplay] +[TodoTray] + +[ToastDisplay | ShellModeIndicator] [ShortcutsHint] +---------------------------------------------------------------------- +[LoadingIndicator (e.g., Thinking...)] + [StatusDisplay] + +[InputPrompt] +``` + +## Key Principles + +- **Clean Input:** The main input area should feel less crowded by offloading + persistent status (Mode) to the footer. +- **Logical Flow:** Transient "Alerts" (Toasts) go above the line; active "Work" + (Loading) goes below the line, closest to the prompt. diff --git a/packages/cli/src/config/footerItems.test.ts b/packages/cli/src/config/footerItems.test.ts index 420246811b..2dfd3899c2 100644 --- a/packages/cli/src/config/footerItems.test.ts +++ b/packages/cli/src/config/footerItems.test.ts @@ -15,6 +15,7 @@ describe('deriveItemsFromLegacySettings', () => { }).merged; const items = deriveItemsFromLegacySettings(settings); expect(items).toEqual([ + 'approval-mode', 'workspace', 'git-branch', 'sandbox', @@ -82,6 +83,7 @@ describe('deriveItemsFromLegacySettings', () => { }).merged; const items = deriveItemsFromLegacySettings(settings); expect(items).toEqual([ + 'approval-mode', 'git-branch', 'sandbox', 'context-used', diff --git a/packages/cli/src/config/footerItems.ts b/packages/cli/src/config/footerItems.ts index 8410d0b5ec..b030a9d153 100644 --- a/packages/cli/src/config/footerItems.ts +++ b/packages/cli/src/config/footerItems.ts @@ -7,6 +7,11 @@ import type { MergedSettings } from './settings.js'; export const ALL_ITEMS = [ + { + id: 'approval-mode', + header: 'mode (Shift+Tab)', + description: 'Current approval mode', + }, { id: 'workspace', header: 'workspace (/directory)', @@ -62,6 +67,7 @@ export const ALL_ITEMS = [ export type FooterItemId = (typeof ALL_ITEMS)[number]['id']; export const DEFAULT_ORDER = [ + 'approval-mode', 'workspace', 'git-branch', 'sandbox', @@ -78,6 +84,7 @@ export function deriveItemsFromLegacySettings( settings: MergedSettings, ): string[] { const defaults = [ + 'approval-mode', 'workspace', 'git-branch', 'sandbox', diff --git a/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame-Full-Terminal-Tool-Confirmation-Snapshot-renders-tool-confirmation-box-in-the-frame-of-the-entire-terminal.snap.svg b/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame-Full-Terminal-Tool-Confirmation-Snapshot-renders-tool-confirmation-box-in-the-frame-of-the-entire-terminal.snap.svg index e8f43ed9fa..d52c508564 100644 --- a/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame-Full-Terminal-Tool-Confirmation-Snapshot-renders-tool-confirmation-box-in-the-frame-of-the-entire-terminal.snap.svg +++ b/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame-Full-Terminal-Tool-Confirmation-Snapshot-renders-tool-confirmation-box-in-the-frame-of-the-entire-terminal.snap.svg @@ -225,15 +225,16 @@ Initializing... ──────────────────────────────────────────────────────────────────────────────────────────────────── - Shift+Tab to accept edits undefined undefined file - workspace (/directory) - sandbox - /model + mode (Shift+Tab) + workspace (/directory) + sandbox + /model context - /directory - no sandbox - gemini-pro + manual + /directory + no sandbox + gemini-pro 17% used \ No newline at end of file diff --git a/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame.test.tsx.snap b/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame.test.tsx.snap index 3e99760310..9513229a8d 100644 --- a/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame.test.tsx.snap +++ b/packages/cli/src/ui/__snapshots__/ToolConfirmationFullFrame.test.tsx.snap @@ -37,8 +37,8 @@ exports[`Full Terminal Tool Confirmation Snapshot > renders tool confirmation bo Initializing... ──────────────────────────────────────────────────────────────────────────────────────────────────── - Shift+Tab to accept edits undefined undefined file - workspace (/directory) sandbox /model context - /directory no sandbox gemini-pro 17% used + undefined undefined file + mode (Shift+Tab) workspace (/directory) sandbox /model context + manual /directory no sandbox gemini-pro 17% used " `; diff --git a/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx b/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx index 1b2decbe16..0e42f9238c 100644 --- a/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx +++ b/packages/cli/src/ui/components/ApprovalModeIndicator.test.tsx @@ -19,10 +19,7 @@ describe('ApprovalModeIndicator', () => { it('renders correctly for AUTO_EDIT mode with plan enabled', async () => { const { lastFrame } = await render( - , + , ); expect(lastFrame()).toMatchSnapshot(); }); @@ -50,10 +47,7 @@ describe('ApprovalModeIndicator', () => { it('renders correctly for DEFAULT mode with plan enabled', async () => { const { lastFrame } = await render( - , + , ); expect(lastFrame()).toMatchSnapshot(); }); diff --git a/packages/cli/src/ui/components/ApprovalModeIndicator.tsx b/packages/cli/src/ui/components/ApprovalModeIndicator.tsx index 7e8f388c82..7ed5da9c7c 100644 --- a/packages/cli/src/ui/components/ApprovalModeIndicator.tsx +++ b/packages/cli/src/ui/components/ApprovalModeIndicator.tsx @@ -8,62 +8,40 @@ import type React from 'react'; import { Box, Text } from 'ink'; import { theme } from '../semantic-colors.js'; import { ApprovalMode } from '@google/gemini-cli-core'; -import { formatCommand } from '../key/keybindingUtils.js'; -import { Command } from '../key/keyBindings.js'; interface ApprovalModeIndicatorProps { approvalMode: ApprovalMode; - allowPlanMode?: boolean; } export const ApprovalModeIndicator: React.FC = ({ approvalMode, - allowPlanMode, }) => { let textColor = ''; let textContent = ''; - let subText = ''; - - const cycleHint = formatCommand(Command.CYCLE_APPROVAL_MODE); - const yoloHint = formatCommand(Command.TOGGLE_YOLO); switch (approvalMode) { case ApprovalMode.AUTO_EDIT: textColor = theme.status.warning; - textContent = 'auto-accept edits'; - subText = allowPlanMode - ? `${cycleHint} to plan` - : `${cycleHint} to manual`; + textContent = 'auto-accept'; break; case ApprovalMode.PLAN: textColor = theme.status.success; textContent = 'plan'; - subText = `${cycleHint} to manual`; break; case ApprovalMode.YOLO: textColor = theme.status.error; textContent = 'YOLO'; - subText = yoloHint; break; case ApprovalMode.DEFAULT: default: textColor = theme.text.accent; - textContent = ''; - subText = `${cycleHint} to accept edits`; + textContent = 'manual'; break; } return ( - - {textContent ? textContent : null} - {subText ? ( - - {textContent ? ' ' : ''} - {subText} - - ) : null} - + {textContent} ); }; diff --git a/packages/cli/src/ui/components/Composer.test.tsx b/packages/cli/src/ui/components/Composer.test.tsx index 8df5f690e7..f80e53e5ef 100644 --- a/packages/cli/src/ui/components/Composer.test.tsx +++ b/packages/cli/src/ui/components/Composer.test.tsx @@ -80,10 +80,6 @@ vi.mock('./HookStatusDisplay.js', () => ({ HookStatusDisplay: () => HookStatusDisplay, })); -vi.mock('./ApprovalModeIndicator.js', () => ({ - ApprovalModeIndicator: () => ApprovalModeIndicator, -})); - vi.mock('./ShellModeIndicator.js', () => ({ ShellModeIndicator: () => ShellModeIndicator, })); @@ -471,7 +467,7 @@ describe('Composer', () => { expect(output).toContain('LoadingIndicator'); }); - it('renders both LoadingIndicator and ApprovalModeIndicator when streaming in full UI mode', async () => { + it('renders LoadingIndicator when streaming in full UI mode', async () => { const uiState = createMockUIState({ streamingState: StreamingState.Responding, thought: { @@ -485,7 +481,6 @@ describe('Composer', () => { 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', async () => { @@ -535,7 +530,7 @@ describe('Composer', () => { }); describe('Context and Status Display', () => { - it('shows StatusDisplay and ApprovalModeIndicator in normal state', async () => { + it('shows StatusDisplay in normal state', async () => { const uiState = createMockUIState({ ctrlCPressedOnce: false, ctrlDPressedOnce: false, @@ -546,11 +541,10 @@ describe('Composer', () => { const output = lastFrame(); expect(output).toContain('StatusDisplay'); - expect(output).toContain('ApprovalModeIndicator'); expect(output).not.toContain('ToastDisplay'); }); - it('shows ToastDisplay and hides ApprovalModeIndicator when a toast is present', async () => { + it('shows ToastDisplay when a toast is present', async () => { const uiState = createMockUIState({ ctrlCPressedOnce: true, }); @@ -559,7 +553,6 @@ describe('Composer', () => { const output = lastFrame(); expect(output).toContain('ToastDisplay'); - expect(output).not.toContain('ApprovalModeIndicator'); expect(output).toContain('StatusDisplay'); }); @@ -575,7 +568,6 @@ describe('Composer', () => { const output = lastFrame(); expect(output).toContain('ToastDisplay'); - expect(output).not.toContain('ApprovalModeIndicator'); }); }); @@ -591,7 +583,6 @@ describe('Composer', () => { expect(output).toContain('ShortcutsHint'); expect(output).toContain('InputPrompt'); expect(output).not.toContain('Footer'); - expect(output).not.toContain('ApprovalModeIndicator'); expect(output).not.toContain('ContextSummaryDisplay'); }); @@ -615,25 +606,6 @@ describe('Composer', () => { expect(lastFrame()).not.toContain('InputPrompt'); }); - it.each([ - [ApprovalMode.DEFAULT], - [ApprovalMode.AUTO_EDIT], - [ApprovalMode.PLAN], - [ApprovalMode.YOLO], - ])( - 'shows ApprovalModeIndicator when approval mode is %s and shell mode is inactive', - async (mode) => { - const uiState = createMockUIState({ - showApprovalModeIndicator: mode, - shellModeActive: false, - }); - - const { lastFrame } = await renderComposer(uiState); - - expect(lastFrame()).toMatch(/ApprovalModeIndic[\s\S]*ator/); - }, - ); - it('shows ShellModeIndicator when shell mode is active', async () => { const uiState = createMockUIState({ shellModeActive: true, @@ -664,55 +636,6 @@ describe('Composer', () => { expect(lastFrame()).not.toContain('raw markdown mode'); }); - it.each([ - [ApprovalMode.YOLO, 'YOLO'], - [ApprovalMode.PLAN, 'plan'], - [ApprovalMode.AUTO_EDIT, 'auto edit'], - ])( - 'shows minimal mode badge "%s" when clean UI details are hidden', - async (mode, label) => { - const uiState = createMockUIState({ - cleanUiDetailsVisible: false, - showApprovalModeIndicator: mode, - }); - - const { lastFrame } = await renderComposer(uiState); - expect(lastFrame()).toContain(label); - }, - ); - - it('hides minimal mode badge while loading in clean mode', async () => { - const uiState = createMockUIState({ - cleanUiDetailsVisible: false, - streamingState: StreamingState.Responding, - elapsedTime: 1, - showApprovalModeIndicator: ApprovalMode.PLAN, - }); - - const { lastFrame } = await renderComposer(uiState); - const output = lastFrame(); - expect(output).toContain('LoadingIndicator'); - expect(output).not.toContain('plan'); - expect(output).not.toContain('ShortcutsHint'); - }); - - it('hides minimal mode badge while action-required state is active', async () => { - const uiState = createMockUIState({ - cleanUiDetailsVisible: false, - showApprovalModeIndicator: ApprovalMode.PLAN, - customDialog: ( - - Prompt - - ), - }); - - const { lastFrame } = await renderComposer(uiState); - const output = lastFrame(); - expect(output).not.toContain('plan'); - expect(output).not.toContain('ShortcutsHint'); - }); - it('shows Esc rewind prompt in minimal mode without showing full UI', async () => { const uiState = createMockUIState({ cleanUiDetailsVisible: false, @@ -939,9 +862,7 @@ describe('Composer', () => { showApprovalModeIndicator: ApprovalMode.YOLO, }); - const { lastFrame } = await renderComposer(uiState); - - expect(lastFrame()).not.toContain('ApprovalModeIndicator'); + await renderComposer(uiState); }); it('keeps shortcuts hint when suggestions are visible below input in regular buffer', async () => { diff --git a/packages/cli/src/ui/components/Composer.tsx b/packages/cli/src/ui/components/Composer.tsx index 053aaa5260..cfb2c0c474 100644 --- a/packages/cli/src/ui/components/Composer.tsx +++ b/packages/cli/src/ui/components/Composer.tsx @@ -5,16 +5,11 @@ */ import { useState, useEffect, useMemo } from 'react'; -import { Box, Text, useIsScreenReaderEnabled } from 'ink'; -import { - ApprovalMode, - checkExhaustive, - CoreToolCallStatus, -} from '@google/gemini-cli-core'; +import { Box, useIsScreenReaderEnabled } from 'ink'; +import { CoreToolCallStatus } from '@google/gemini-cli-core'; import { LoadingIndicator } from './LoadingIndicator.js'; import { StatusDisplay } from './StatusDisplay.js'; import { ToastDisplay, shouldShowToast } from './ToastDisplay.js'; -import { ApprovalModeIndicator } from './ApprovalModeIndicator.js'; import { ShellModeIndicator } from './ShellModeIndicator.js'; import { DetailedMessagesDisplay } from './DetailedMessagesDisplay.js'; import { RawMarkdownIndicator } from './RawMarkdownIndicator.js'; @@ -39,7 +34,6 @@ import { ConfigInitDisplay } from '../components/ConfigInitDisplay.js'; import { TodoTray } from './messages/Todo.js'; import { getInlineThinkingMode } from '../utils/inlineThinkingMode.js'; import { isContextUsageHigh } from '../utils/contextUsage.js'; -import { theme } from '../semantic-colors.js'; export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { const config = useConfig(); @@ -112,34 +106,8 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { !hasPendingActionRequired; const hideUiDetailsForSuggestions = suggestionsVisible && suggestionsPosition === 'above'; - const showApprovalIndicator = - !uiState.shellModeActive && !hideUiDetailsForSuggestions; const showRawMarkdownIndicator = !uiState.renderMarkdown; - let modeBleedThrough: { text: string; color: string } | null = null; - switch (showApprovalModeIndicator) { - case ApprovalMode.YOLO: - modeBleedThrough = { text: 'YOLO', color: theme.status.error }; - break; - case ApprovalMode.PLAN: - modeBleedThrough = { text: 'plan', color: theme.status.success }; - break; - case ApprovalMode.AUTO_EDIT: - modeBleedThrough = { text: 'auto edit', color: theme.status.warning }; - break; - case ApprovalMode.DEFAULT: - modeBleedThrough = null; - break; - default: - checkExhaustive(showApprovalModeIndicator); - modeBleedThrough = null; - break; - } - const hideMinimalModeHintWhileBusy = - !showUiDetails && (showLoadingIndicator || hasPendingActionRequired); - const minimalModeBleedThrough = hideMinimalModeHintWhileBusy - ? null - : modeBleedThrough; const hasMinimalStatusBleedThrough = shouldShowToast(uiState); const showMinimalContextBleedThrough = @@ -177,14 +145,10 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { !hasPendingActionRequired; const showShortcutsHint = shouldReserveSpaceForShortcutsHint && showShortcutsHintDebounced; - const showMinimalModeBleedThrough = - !hideUiDetailsForSuggestions && Boolean(minimalModeBleedThrough); const showMinimalInlineLoading = !showUiDetails && showLoadingIndicator; const showMinimalBleedThroughRow = !showUiDetails && - (showMinimalModeBleedThrough || - hasMinimalStatusBleedThrough || - showMinimalContextBleedThrough); + (hasMinimalStatusBleedThrough || showMinimalContextBleedThrough); const showMinimalMetaRow = !showUiDetails && (showMinimalInlineLoading || @@ -226,26 +190,29 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { alignItems={isNarrow ? 'flex-start' : 'center'} flexGrow={1} > - {showUiDetails && showLoadingIndicator && ( - - )} + {showUiDetails && + (hasToast ? ( + + ) : ( + + {uiState.shellModeActive && ( + + + + )} + {showRawMarkdownIndicator && ( + + + + )} + + ))} { elapsedTime={uiState.elapsedTime} /> )} - {showMinimalModeBleedThrough && minimalModeBleedThrough && ( - - ● {minimalModeBleedThrough.text} - - )} {hasMinimalStatusBleedThrough && ( - + )} @@ -356,54 +312,25 @@ export const Composer = ({ isFocused = true }: { isFocused?: boolean }) => { alignItems="center" flexGrow={1} > - {hasToast ? ( - - ) : ( - - {showApprovalIndicator && ( - - )} - {!showLoadingIndicator && ( - <> - {uiState.shellModeActive && ( - - - - )} - {showRawMarkdownIndicator && ( - - - - )} - - )} - + {showLoadingIndicator && ( + )} diff --git a/packages/cli/src/ui/components/Footer.tsx b/packages/cli/src/ui/components/Footer.tsx index c6816339f5..925edabfe1 100644 --- a/packages/cli/src/ui/components/Footer.tsx +++ b/packages/cli/src/ui/components/Footer.tsx @@ -14,6 +14,7 @@ import { checkExhaustive, } from '@google/gemini-cli-core'; import { ConsoleSummaryDisplay } from './ConsoleSummaryDisplay.js'; +import { ApprovalModeIndicator } from './ApprovalModeIndicator.js'; import process from 'node:process'; import { MemoryUsageDisplay } from './MemoryUsageDisplay.js'; import { ContextUsageDisplay } from './ContextUsageDisplay.js'; @@ -261,6 +262,19 @@ export const Footer: React.FC = () => { const header = itemConfig?.header ?? id; switch (id) { + case 'approval-mode': { + addCol( + id, + header, + () => ( + + ), + 11, // 'auto-accept' is 11 chars + ); + break; + } case 'workspace': { const fullPath = tildeifyPath(targetDir); const debugSuffix = debugMode ? ' ' + (debugMessage || '--debug') : ''; diff --git a/packages/cli/src/ui/components/FooterConfigDialog.test.tsx b/packages/cli/src/ui/components/FooterConfigDialog.test.tsx index 12829cd99a..c797162f2c 100644 --- a/packages/cli/src/ui/components/FooterConfigDialog.test.tsx +++ b/packages/cli/src/ui/components/FooterConfigDialog.test.tsx @@ -46,7 +46,7 @@ describe('', () => { }); await waitFor(() => { - expect(lastFrame()).toContain('[ ] workspace'); + expect(lastFrame()).toContain('[ ] approval-mode'); }); act(() => { @@ -54,7 +54,7 @@ describe('', () => { }); await waitFor(() => { - expect(lastFrame()).toContain('[✓] workspace'); + expect(lastFrame()).toContain('[✓] approval-mode'); }); }); @@ -65,26 +65,26 @@ describe('', () => { { settings }, ); - // Initial order: workspace, git-branch, ... + // Initial order: approval-mode, workspace, ... const output = lastFrame(); + const modeIdx = output.indexOf('] approval-mode'); const cwdIdx = output.indexOf('] workspace'); - const branchIdx = output.indexOf('] git-branch'); + expect(modeIdx).toBeGreaterThan(-1); expect(cwdIdx).toBeGreaterThan(-1); - expect(branchIdx).toBeGreaterThan(-1); - expect(cwdIdx).toBeLessThan(branchIdx); + expect(modeIdx).toBeLessThan(cwdIdx); - // Move workspace down (right arrow) + // Move approval-mode down (right arrow) act(() => { stdin.write('\u001b[C'); // Right arrow }); await waitFor(() => { const outputAfter = lastFrame(); + const modeIdxAfter = outputAfter.indexOf('] approval-mode'); const cwdIdxAfter = outputAfter.indexOf('] workspace'); - const branchIdxAfter = outputAfter.indexOf('] git-branch'); + expect(modeIdxAfter).toBeGreaterThan(-1); expect(cwdIdxAfter).toBeGreaterThan(-1); - expect(branchIdxAfter).toBeGreaterThan(-1); - expect(branchIdxAfter).toBeLessThan(cwdIdxAfter); + expect(cwdIdxAfter).toBeLessThan(modeIdxAfter); }); }); @@ -116,7 +116,7 @@ describe('', () => { expect(lastFrame()).toContain('~/project/path'); // Move focus down to 'code-changes' (which has colored elements) - for (let i = 0; i < 8; i++) { + for (let i = 0; i < 9; i++) { act(() => { stdin.write('\u001b[B'); // Down arrow }); @@ -188,22 +188,22 @@ describe('', () => { const workspaceIdx = output.indexOf('] workspace'); expect(workspaceIdx).toBeLessThan(branchIdx); - // Try to move workspace up (left arrow) while it's at the top + // Try to move approval-mode up (left arrow) while it's at the top act(() => { stdin.write('\u001b[D'); // Left arrow }); - // Move workspace down (right arrow) + // Move approval-mode down (right arrow) act(() => { stdin.write('\u001b[C'); // Right arrow }); await waitFor(() => { const outputAfter = lastFrame(); - const bIdxAfter = outputAfter.indexOf('] git-branch'); - const wIdxAfter = outputAfter.indexOf('] workspace'); - // workspace should now be after git-branch - expect(bIdxAfter).toBeLessThan(wIdxAfter); + const modeIdxAfter = outputAfter.indexOf('] approval-mode'); + const cwdIdxAfter = outputAfter.indexOf('] workspace'); + // approval-mode should now be after workspace + expect(cwdIdxAfter).toBeLessThan(modeIdxAfter); }); }); diff --git a/packages/cli/src/ui/components/__snapshots__/ApprovalModeIndicator.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ApprovalModeIndicator.test.tsx.snap index 8ddb141478..e9e1674197 100644 --- a/packages/cli/src/ui/components/__snapshots__/ApprovalModeIndicator.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ApprovalModeIndicator.test.tsx.snap @@ -1,31 +1,31 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`ApprovalModeIndicator > renders correctly for AUTO_EDIT mode 1`] = ` -"auto-accept edits Shift+Tab to manual +"auto-accept " `; exports[`ApprovalModeIndicator > renders correctly for AUTO_EDIT mode with plan enabled 1`] = ` -"auto-accept edits Shift+Tab to plan +"auto-accept " `; exports[`ApprovalModeIndicator > renders correctly for DEFAULT mode 1`] = ` -"Shift+Tab to accept edits +"manual " `; exports[`ApprovalModeIndicator > renders correctly for DEFAULT mode with plan enabled 1`] = ` -"Shift+Tab to accept edits +"manual " `; exports[`ApprovalModeIndicator > renders correctly for PLAN mode 1`] = ` -"plan Shift+Tab to manual +"plan " `; exports[`ApprovalModeIndicator > renders correctly for YOLO mode 1`] = ` -"YOLO Ctrl+Y +"YOLO " `; diff --git a/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap index 3992cdd60c..1ab67a46db 100644 --- a/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/AskUserDialog.test.tsx.snap @@ -11,17 +11,6 @@ Enter to submit · Esc to cancel " `; -exports[`AskUserDialog > Choice question placeholder > uses default placeholder when not provided 2`] = ` -"Select your preferred language: - - 1. TypeScript - 2. JavaScript -● 3. Enter a custom value - -Enter to submit · Esc to cancel -" -`; - exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 1`] = ` "Select your preferred language: @@ -33,17 +22,6 @@ Enter to submit · Esc to cancel " `; -exports[`AskUserDialog > Choice question placeholder > uses placeholder for "Other" option when provided 2`] = ` -"Select your preferred language: - - 1. TypeScript - 2. JavaScript -● 3. Type another language... - -Enter to submit · Esc to cancel -" -`; - exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 1`] = ` "Choose an option @@ -60,20 +38,6 @@ Enter to select · ↑/↓ to navigate · Esc to cancel " `; -exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: false) > shows scroll arrows correctly when useAlternateBuffer is false 2`] = ` -"Choose an option - -▲ -● 1. Option 1 - Description 1 - 2. Option 2 - Description 2 -▼ - -Enter to select · ↑/↓ to navigate · Esc to cancel -" -`; - exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 1`] = ` "Choose an option @@ -113,45 +77,6 @@ Enter to select · ↑/↓ to navigate · Esc to cancel " `; -exports[`AskUserDialog > Scroll Arrows (useAlternateBuffer: true) > shows scroll arrows correctly when useAlternateBuffer is true 2`] = ` -"Choose an option - -● 1. Option 1 - Description 1 - 2. Option 2 - Description 2 - 3. Option 3 - Description 3 - 4. Option 4 - Description 4 - 5. Option 5 - Description 5 - 6. Option 6 - Description 6 - 7. Option 7 - Description 7 - 8. Option 8 - Description 8 - 9. Option 9 - Description 9 - 10. Option 10 - Description 10 - 11. Option 11 - Description 11 - 12. Option 12 - Description 12 - 13. Option 13 - Description 13 - 14. Option 14 - Description 14 - 15. Option 15 - Description 15 - 16. Enter a custom value - -Enter to select · ↑/↓ to navigate · Esc to cancel -" -`; - exports[`AskUserDialog > Text type questions > renders text input for type: "text" 1`] = ` "What should we name this component? @@ -294,19 +219,3 @@ exports[`AskUserDialog > verifies "All of the above" visual state with snapshot Enter to select · ↑/↓ to navigate · Esc to cancel " `; - -exports[`AskUserDialog > verifies "All of the above" visual state with snapshot 2`] = ` -"Which features? -(Select all that apply) - - 1. [x] TypeScript - 2. [x] ESLint -● 3. [x] All of the above - Select all options - 4. [ ] Enter a custom value - Done - Finish selection - -Enter to select · ↑/↓ to navigate · Esc to cancel -" -`; diff --git a/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap index 452663d719..d20c918b6a 100644 --- a/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Composer.test.tsx.snap @@ -3,7 +3,7 @@ exports[`Composer > Snapshots > matches snapshot in idle state 1`] = ` " ShortcutsHint ──────────────────────────────────────────────────────────────────────────────────────────────────── - ApprovalModeIndicator StatusDisplay + StatusDisplay InputPrompt: Type your message or @path/to/file Footer " @@ -25,7 +25,6 @@ exports[`Composer > Snapshots > matches snapshot in narrow view 1`] = ` " ShortcutsHint ──────────────────────────────────────── - ApprovalModeIndicator StatusDisplay InputPrompt: Type your message or @@ -35,9 +34,9 @@ Footer `; exports[`Composer > Snapshots > matches snapshot while streaming 1`] = ` -" LoadingIndicator: Thinking +" ──────────────────────────────────────────────────────────────────────────────────────────────────── - ApprovalModeIndicator + LoadingIndicator: Thinking InputPrompt: Type your message or @path/to/file Footer " diff --git a/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap index 9e210e3438..073c106ceb 100644 --- a/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/ExitPlanModeDialog.test.tsx.snap @@ -27,33 +27,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel " `; -exports[`ExitPlanModeDialog > useAlternateBuffer: false > bubbles up Ctrl+C when feedback is empty while editing 2`] = ` -"Overview - -Add user authentication to the CLI application. - -Implementation Steps - - 1. Create src/auth/AuthService.ts with login/logout methods - 2. Add session storage in src/storage/SessionStore.ts - 3. Update src/commands/index.ts to check auth status - 4. Add tests in src/auth/__tests__/ - -Files to Modify - - - src/index.ts - Add auth middleware - - src/config.ts - Add auth configuration options - - 1. Yes, automatically accept edits - Approves plan and allows tools to run automatically - 2. Yes, manually accept edits - Approves plan but requires confirmation for each tool -● 3. Type your feedback... - -Enter to submit · Ctrl+X to edit plan · Esc to cancel -" -`; - exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 1`] = ` "Overview @@ -81,33 +54,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel " `; -exports[`ExitPlanModeDialog > useAlternateBuffer: false > calls onFeedback when feedback is typed and submitted 2`] = ` -"Overview - -Add user authentication to the CLI application. - -Implementation Steps - - 1. Create src/auth/AuthService.ts with login/logout methods - 2. Add session storage in src/storage/SessionStore.ts - 3. Update src/commands/index.ts to check auth status - 4. Add tests in src/auth/__tests__/ - -Files to Modify - - - src/index.ts - Add auth middleware - - src/config.ts - Add auth configuration options - - 1. Yes, automatically accept edits - Approves plan and allows tools to run automatically - 2. Yes, manually accept edits - Approves plan but requires confirmation for each tool -● 3. Add tests - -Enter to submit · Ctrl+X to edit plan · Esc to cancel -" -`; - exports[`ExitPlanModeDialog > useAlternateBuffer: false > displays error state when file read fails 1`] = ` " Error reading plan: File not found " @@ -194,33 +140,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel " `; -exports[`ExitPlanModeDialog > useAlternateBuffer: true > bubbles up Ctrl+C when feedback is empty while editing 2`] = ` -"Overview - -Add user authentication to the CLI application. - -Implementation Steps - - 1. Create src/auth/AuthService.ts with login/logout methods - 2. Add session storage in src/storage/SessionStore.ts - 3. Update src/commands/index.ts to check auth status - 4. Add tests in src/auth/__tests__/ - -Files to Modify - - - src/index.ts - Add auth middleware - - src/config.ts - Add auth configuration options - - 1. Yes, automatically accept edits - Approves plan and allows tools to run automatically - 2. Yes, manually accept edits - Approves plan but requires confirmation for each tool -● 3. Type your feedback... - -Enter to submit · Ctrl+X to edit plan · Esc to cancel -" -`; - exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 1`] = ` "Overview @@ -248,33 +167,6 @@ Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel " `; -exports[`ExitPlanModeDialog > useAlternateBuffer: true > calls onFeedback when feedback is typed and submitted 2`] = ` -"Overview - -Add user authentication to the CLI application. - -Implementation Steps - - 1. Create src/auth/AuthService.ts with login/logout methods - 2. Add session storage in src/storage/SessionStore.ts - 3. Update src/commands/index.ts to check auth status - 4. Add tests in src/auth/__tests__/ - -Files to Modify - - - src/index.ts - Add auth middleware - - src/config.ts - Add auth configuration options - - 1. Yes, automatically accept edits - Approves plan and allows tools to run automatically - 2. Yes, manually accept edits - Approves plan but requires confirmation for each tool -● 3. Add tests - -Enter to submit · Ctrl+X to edit plan · Esc to cancel -" -`; - exports[`ExitPlanModeDialog > useAlternateBuffer: true > displays error state when file read fails 1`] = ` " Error reading plan: File not found " diff --git a/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap b/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap index 3980ddbd0a..2f93f3eb26 100644 --- a/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap +++ b/packages/cli/src/ui/components/__snapshots__/Footer.test.tsx.snap @@ -1,45 +1,49 @@ // Vitest Snapshot v1, https://vitest.dev/guide/snapshot.html exports[`