feat(plan): inject message when user manually exits Plan mode (#20203)

This commit is contained in:
Jerop Kipruto
2026-02-24 14:31:41 -05:00
committed by GitHub
parent 87f7f0beb7
commit 4dd940f8ce
6 changed files with 171 additions and 22 deletions
+33 -1
View File
@@ -36,6 +36,7 @@ import {
CoreToolCallStatus,
buildUserSteeringHintPrompt,
generateSteeringAckMessage,
getPlanModeExitMessage,
} from '@google/gemini-cli-core';
import type {
Config,
@@ -203,6 +204,9 @@ export const useGeminiStream = (
const abortControllerRef = useRef<AbortController | null>(null);
const turnCancelledRef = useRef(false);
const activeQueryIdRef = useRef<string | null>(null);
const previousApprovalModeRef = useRef<ApprovalMode>(
config.getApprovalMode(),
);
const [isResponding, setIsResponding] = useState<boolean>(false);
const [thought, thoughtRef, setThought] =
useStateAndRef<ThoughtSummary | null>(null);
@@ -1435,6 +1439,34 @@ export const useGeminiStream = (
const handleApprovalModeChange = useCallback(
async (newApprovalMode: ApprovalMode) => {
if (
previousApprovalModeRef.current === ApprovalMode.PLAN &&
newApprovalMode !== ApprovalMode.PLAN &&
streamingState === StreamingState.Idle
) {
if (geminiClient) {
try {
await geminiClient.addHistory({
role: 'user',
parts: [
{
text: getPlanModeExitMessage(newApprovalMode, true),
},
],
});
} catch (error) {
onDebugMessage(
`Failed to notify model of Plan Mode exit: ${getErrorMessage(error)}`,
);
addItem({
type: MessageType.ERROR,
text: 'Failed to update the model about exiting Plan Mode. The model might be out of sync. Please consider restarting the session if you see unexpected behavior.',
});
}
}
}
previousApprovalModeRef.current = newApprovalMode;
// Auto-approve pending tool calls when switching to auto-approval modes
if (
newApprovalMode === ApprovalMode.YOLO ||
@@ -1473,7 +1505,7 @@ export const useGeminiStream = (
}
}
},
[config, toolCalls],
[config, toolCalls, geminiClient, streamingState, addItem, onDebugMessage],
);
const handleCompletedTools = useCallback(