This commit is contained in:
A.K.M. Adib
2026-03-04 16:37:12 -05:00
parent 07d2187a76
commit defc28e42d
12 changed files with 249 additions and 149 deletions
+1
View File
@@ -591,6 +591,7 @@ const mockUIActions: UIActions = {
setConstrainHeight: vi.fn(),
onEscapePromptChange: vi.fn(),
refreshStatic: vi.fn(),
handleClearPlanContext: vi.fn(),
handleFinalSubmit: vi.fn(),
handleClearScreen: vi.fn(),
handleProQuotaChoice: vi.fn(),
+28 -1
View File
@@ -50,7 +50,7 @@ import {
type GeminiUserTier,
type UserFeedbackPayload,
type AgentDefinition,
type ApprovalMode,
ApprovalMode,
IdeClient,
ideContextStore,
getErrorMessage,
@@ -398,6 +398,20 @@ export const AppContainer = (props: AppContainerProps) => {
);
const [isConfigInitialized, setConfigInitialized] = useState(false);
const [planModeUIHistoryStartIndex, setPlanModeUIHistoryStartIndex] =
useState<number | null>(null);
useEffect(() => {
const handleApprovalModeChanged = ({ mode }: { mode: ApprovalMode }) => {
if (mode === ApprovalMode.PLAN) {
setPlanModeUIHistoryStartIndex(historyManager.history.length);
}
};
coreEvents.on(CoreEvent.ApprovalModeChanged, handleApprovalModeChanged);
return () => {
coreEvents.off(CoreEvent.ApprovalModeChanged, handleApprovalModeChanged);
};
}, [historyManager.history.length]);
const logger = useLogger(config.storage);
const { inputHistory, addInput, initializeFromLogger } =
@@ -1346,6 +1360,17 @@ Logging in with Google... Restarting Gemini CLI to continue.
triggerExpandHint,
]);
const handleClearPlanContext = useCallback(() => {
if (planModeUIHistoryStartIndex !== null) {
const newHistory = historyManager.history.slice(
0,
planModeUIHistoryStartIndex,
);
historyManager.loadHistory(newHistory);
refreshStatic();
}
}, [planModeUIHistoryStartIndex, historyManager, refreshStatic]);
const { handleInput: vimHandleInput } = useVim(buffer, handleFinalSubmit);
/**
@@ -2456,6 +2481,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
setConstrainHeight,
onEscapePromptChange: handleEscapePromptChange,
refreshStatic,
handleClearPlanContext,
handleFinalSubmit,
handleClearScreen,
handleProQuotaChoice,
@@ -2548,6 +2574,7 @@ Logging in with Google... Restarting Gemini CLI to continue.
setConstrainHeight,
handleEscapePromptChange,
refreshStatic,
handleClearPlanContext,
handleFinalSubmit,
handleClearScreen,
handleProQuotaChoice,
@@ -207,7 +207,7 @@ Implement a comprehensive authentication system with multiple providers.
writeKey(stdin, '\r');
await waitFor(() => {
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.AUTO_EDIT);
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.AUTO_EDIT, false);
});
});
@@ -222,11 +222,12 @@ Implement a comprehensive authentication system with multiple providers.
expect(lastFrame()).toContain('Add user authentication');
});
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\r');
await waitFor(() => {
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.DEFAULT);
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.DEFAULT, false);
});
});
@@ -349,11 +350,11 @@ Implement a comprehensive authentication system with multiple providers.
expect(lastFrame()).toContain('Add user authentication');
});
// Press '2' to select second option directly
writeKey(stdin, '2');
// Press '3' to select third option directly
writeKey(stdin, '3');
await waitFor(() => {
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.DEFAULT);
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.DEFAULT, false);
});
});
@@ -371,6 +372,8 @@ Implement a comprehensive authentication system with multiple providers.
// Navigate to feedback option and start typing
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\r'); // Select to focus input
// Type some feedback
@@ -493,7 +496,9 @@ Implement a comprehensive authentication system with multiple providers.
expect(lastFrame()).toContain('Add user authentication');
});
// Navigate to feedback option
// Focus feedback option
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
@@ -523,6 +528,8 @@ Implement a comprehensive authentication system with multiple providers.
// Navigate to feedback option and start typing
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
writeKey(stdin, '\x1b[B'); // Down arrow
// Type some feedback
for (const char of 'test') {
@@ -531,12 +538,13 @@ Implement a comprehensive authentication system with multiple providers.
// Now use up arrow to navigate back to a different option
writeKey(stdin, '\x1b[A'); // Up arrow
writeKey(stdin, '\x1b[A'); // Up arrow
// Press Enter to select the second option (manually accept edits)
// Press Enter to select the manually accept edits option
writeKey(stdin, '\r');
await waitFor(() => {
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.DEFAULT);
expect(onApprove).toHaveBeenCalledWith(ApprovalMode.DEFAULT, false);
});
expect(onFeedback).not.toHaveBeenCalled();
});
@@ -27,7 +27,7 @@ import { formatCommand } from '../utils/keybindingUtils.js';
export interface ExitPlanModeDialogProps {
planPath: string;
onApprove: (approvalMode: ApprovalMode) => void;
onApprove: (approvalMode: ApprovalMode, clearConversation?: boolean) => void;
onFeedback: (feedback: string) => void;
onCancel: () => void;
getPreferredEditor: () => EditorType | undefined;
@@ -50,7 +50,9 @@ interface PlanContentState {
enum ApprovalOption {
Auto = 'Yes, automatically accept edits',
AutoClear = 'Yes, automatically accept edits & clear conversation',
Manual = 'Yes, manually accept edits',
ManualClear = 'Yes, manually accept edits & clear conversation',
}
/**
@@ -239,11 +241,21 @@ export const ExitPlanModeDialog: React.FC<ExitPlanModeDialogProps> = ({
description:
'Approves plan and allows tools to run automatically',
},
{
label: ApprovalOption.AutoClear,
description:
'Approves plan, runs automatically, and clears prior conversation context',
},
{
label: ApprovalOption.Manual,
description:
'Approves plan but requires confirmation for each tool',
},
{
label: ApprovalOption.ManualClear,
description:
'Approves plan, requires confirmation, and clears prior conversation context',
},
],
placeholder: 'Type your feedback...',
multiSelect: false,
@@ -251,10 +263,19 @@ export const ExitPlanModeDialog: React.FC<ExitPlanModeDialogProps> = ({
]}
onSubmit={(answers) => {
const answer = answers['0'];
if (answer === ApprovalOption.Auto) {
onApprove(ApprovalMode.AUTO_EDIT);
} else if (answer === ApprovalOption.Manual) {
onApprove(ApprovalMode.DEFAULT);
const clearConversation =
answer === ApprovalOption.AutoClear ||
answer === ApprovalOption.ManualClear;
if (
answer === ApprovalOption.Auto ||
answer === ApprovalOption.AutoClear
) {
onApprove(ApprovalMode.AUTO_EDIT, clearConversation);
} else if (
answer === ApprovalOption.Manual ||
answer === ApprovalOption.ManualClear
) {
onApprove(ApprovalMode.DEFAULT, clearConversation);
} else if (answer) {
onFeedback(answer);
}
@@ -17,43 +17,19 @@ 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...
● 2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
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
@@ -71,43 +47,19 @@ 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
2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
3. Type your feedback...
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
"
@@ -130,11 +82,14 @@ Implementation Steps
8. Add multi-factor authentication in src/auth/MFAService.ts
... last 22 lines hidden (Ctrl+O to show) ...
● 1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
3. Type your feedback...
Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
"
@@ -157,11 +112,14 @@ 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
2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
3. Type your feedback...
Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
"
@@ -186,41 +144,19 @@ Files to Modify
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...
● 2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
4. Yes, manually accept edits & clear conversation
Approves plan, requires confirmation, and clears prior conversation
context
5. Type your feedback...
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
@@ -240,41 +176,19 @@ Files to Modify
● 1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
3. Type your feedback...
4. Yes, manually accept edits & clear conversation
Approves plan, requires confirmation, and clears prior conversation
context
5. Type your feedback...
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
"
@@ -320,9 +234,14 @@ Testing Strategy
● 1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
3. Type your feedback...
4. Yes, manually accept edits & clear conversation
Approves plan, requires confirmation, and clears prior conversation
context
5. Type your feedback...
Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
"
@@ -347,9 +266,14 @@ Files to Modify
● 1. Yes, automatically accept edits
Approves plan and allows tools to run automatically
2. Yes, manually accept edits
2. Yes, automatically accept edits & clear conversation
Approves plan, runs automatically, and clears prior conversation context
3. Yes, manually accept edits
Approves plan but requires confirmation for each tool
3. Type your feedback...
4. Yes, manually accept edits & clear conversation
Approves plan, requires confirmation, and clears prior conversation
context
5. Type your feedback...
Enter to select · ↑/↓ to navigate · Ctrl+X to edit plan · Esc to cancel
"
@@ -29,6 +29,7 @@ import {
import { useKeypress } from '../../hooks/useKeypress.js';
import { theme } from '../../semantic-colors.js';
import { useSettings } from '../../contexts/SettingsContext.js';
import { useUIActions } from '../../contexts/UIActionsContext.js';
import { keyMatchers, Command } from '../../keyMatchers.js';
import { formatCommand } from '../../utils/keybindingUtils.js';
import {
@@ -68,6 +69,7 @@ export const ToolConfirmationMessage: React.FC<
terminalWidth,
}) => {
const { confirm, isDiffingEnabled } = useToolActions();
const { handleClearPlanContext } = useUIActions();
const [mcpDetailsExpansionState, setMcpDetailsExpansionState] = useState<{
callId: string;
expanded: boolean;
@@ -428,10 +430,14 @@ export const ToolConfirmationMessage: React.FC<
<ExitPlanModeDialog
planPath={confirmationDetails.planPath}
getPreferredEditor={getPreferredEditor}
onApprove={(approvalMode) => {
onApprove={(approvalMode, clearConversation) => {
if (clearConversation) {
handleClearPlanContext();
}
handleConfirm(ToolConfirmationOutcome.ProceedOnce, {
approved: true,
approvalMode,
clearConversation,
});
}}
onFeedback={(feedback) => {
@@ -623,17 +629,18 @@ export const ToolConfirmationMessage: React.FC<
return { question, bodyContent, options, securityWarnings };
}, [
confirmationDetails,
getOptions,
availableBodyContentHeight,
terminalWidth,
handleConfirm,
deceptiveUrlWarningText,
isMcpToolDetailsExpanded,
hasMcpToolDetails,
mcpToolDetailsText,
expandDetailsHintKey,
confirmationDetails,
terminalWidth,
availableBodyContentHeight,
handleConfirm,
getPreferredEditor,
handleClearPlanContext,
hasMcpToolDetails,
isMcpToolDetailsExpanded,
expandDetailsHintKey,
mcpToolDetailsText,
]);
const bodyOverflowDirection: 'top' | 'bottom' =
@@ -57,6 +57,7 @@ export interface UIActions {
setConstrainHeight: (value: boolean) => void;
onEscapePromptChange: (show: boolean) => void;
refreshStatic: () => void;
handleClearPlanContext: () => void;
handleFinalSubmit: (value: string) => Promise<void>;
handleClearScreen: () => void;
handleProQuotaChoice: (