fix(core,cli): resolve TOCTOU, concurrency, and performance regressions in plan resolution

This commit is contained in:
Mahima Shanware
2026-04-07 02:30:35 +00:00
parent ded474c2d0
commit 7ab4c3d61f
11 changed files with 80 additions and 96 deletions
+4 -5
View File
@@ -1340,11 +1340,6 @@ Logging in with Google... Restarting Gemini CLI to continue.
}
}
const parsedCommand = parseSlashCommand(
submittedValue,
slashCommands ?? [],
);
const isSlash = isSlashCommand(submittedValue.trim());
const isIdle = streamingState === StreamingState.Idle;
const isAgentRunning =
@@ -1352,6 +1347,10 @@ Logging in with Google... Restarting Gemini CLI to continue.
isToolExecuting(pendingHistoryItems);
if (isSlash && isAgentRunning) {
const parsedCommand = parseSlashCommand(
submittedValue,
slashCommands ?? [],
);
const commandToExecute = parsedCommand.commandToExecute;
if (commandToExecute?.isSafeConcurrent) {
void handleSlashCommand(submittedValue);
@@ -1130,18 +1130,19 @@ describe('useSlashCommandProcessor', () => {
});
expect(spySetContext).toHaveBeenLastCalledWith('extB');
// 3. Run /plan (Default)
// 3. Run /help (Concurrent global command)
spySetContext.mockClear();
await act(async () => {
await hook.current.handleSlashCommand('/help');
});
// A concurrent command should NOT modify the active extension context
expect(spySetContext).not.toHaveBeenCalled();
// 4. Run /plan (Default)
await act(async () => {
await hook.current.handleSlashCommand('/plan my task');
});
expect(spySetContext).toHaveBeenLastCalledWith(undefined);
// 4. Run /clear (Global)
await act(async () => {
await hook.current.handleSlashCommand('/help');
});
// Context should still be undefined
expect(spySetContext).toHaveBeenLastCalledWith(undefined);
});
});
});
@@ -371,7 +371,7 @@ export const useSlashCommandProcessor = (
extensionContext,
} = parseSlashCommand(trimmed, commands);
if (config) {
if (config && commandToExecute && !commandToExecute.isSafeConcurrent) {
if (extensionContext) {
if (config.hasExtensionPlanDir(extensionContext)) {
config.setActiveExtensionContext(extensionContext);