mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-05-15 22:33:05 -07:00
fix(cli): consistently clear sticky extension context
This fixes a bug where the active extension context would remain sticky when a user switched from an extension command to a standard non-plan command, or to an extension without a plan directory. The context is now correctly reset to undefined when an extension command without a plan directory is executed, preventing subsequent plan mode invocations from incorrectly targeting the previous extension's folder.
This commit is contained in:
@@ -3196,6 +3196,92 @@ describe('AppContainer State Management', () => {
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('sets activeExtensionContext when an extension command WITH a plan dir is executed', async () => {
|
||||
const { checkPermissions } = await import(
|
||||
'./hooks/atCommandProcessor.js'
|
||||
);
|
||||
vi.mocked(checkPermissions).mockResolvedValue([]);
|
||||
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: vi.fn(),
|
||||
slashCommands: [
|
||||
{
|
||||
name: 'conductor:setup',
|
||||
extensionName: 'conductor',
|
||||
description: 'test',
|
||||
action: vi.fn(),
|
||||
},
|
||||
],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
const spyHasExtensionPlanDir = vi
|
||||
.spyOn(mockConfig, 'hasExtensionPlanDir')
|
||||
.mockReturnValue(true);
|
||||
const spySetActiveExtensionContext = vi.spyOn(
|
||||
mockConfig,
|
||||
'setActiveExtensionContext',
|
||||
);
|
||||
|
||||
const { unmount } = await act(async () => renderAppContainer());
|
||||
|
||||
expect(capturedUIActions).toBeTruthy();
|
||||
|
||||
await act(async () =>
|
||||
capturedUIActions.handleFinalSubmit('/conductor:setup'),
|
||||
);
|
||||
|
||||
expect(spyHasExtensionPlanDir).toHaveBeenCalledWith('conductor');
|
||||
expect(spySetActiveExtensionContext).toHaveBeenCalledWith('conductor');
|
||||
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('clears activeExtensionContext when an extension command WITHOUT a plan dir is executed', async () => {
|
||||
const { checkPermissions } = await import(
|
||||
'./hooks/atCommandProcessor.js'
|
||||
);
|
||||
vi.mocked(checkPermissions).mockResolvedValue([]);
|
||||
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: vi.fn(),
|
||||
slashCommands: [
|
||||
{
|
||||
name: 'other:cmd',
|
||||
extensionName: 'other',
|
||||
description: 'test',
|
||||
action: vi.fn(),
|
||||
},
|
||||
],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
const spyHasExtensionPlanDir = vi
|
||||
.spyOn(mockConfig, 'hasExtensionPlanDir')
|
||||
.mockReturnValue(false);
|
||||
const spySetActiveExtensionContext = vi.spyOn(
|
||||
mockConfig,
|
||||
'setActiveExtensionContext',
|
||||
);
|
||||
|
||||
const { unmount } = await act(async () => renderAppContainer());
|
||||
|
||||
expect(capturedUIActions).toBeTruthy();
|
||||
|
||||
await act(async () => capturedUIActions.handleFinalSubmit('/other:cmd'));
|
||||
|
||||
expect(spyHasExtensionPlanDir).toHaveBeenCalledWith('other');
|
||||
expect(spySetActiveExtensionContext).toHaveBeenCalledWith(undefined);
|
||||
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('clears activeExtensionContext when /plan is explicitly executed', async () => {
|
||||
const { checkPermissions } = await import(
|
||||
'./hooks/atCommandProcessor.js'
|
||||
@@ -3228,6 +3314,38 @@ describe('AppContainer State Management', () => {
|
||||
|
||||
unmount();
|
||||
});
|
||||
|
||||
it('does NOT clear activeExtensionContext when a standard non-plan command is executed', async () => {
|
||||
const { checkPermissions } = await import(
|
||||
'./hooks/atCommandProcessor.js'
|
||||
);
|
||||
vi.mocked(checkPermissions).mockResolvedValue([]);
|
||||
|
||||
mockedUseSlashCommandProcessor.mockReturnValue({
|
||||
handleSlashCommand: vi.fn(),
|
||||
slashCommands: [{ name: 'help', description: 'test', action: vi.fn() }],
|
||||
pendingHistoryItems: [],
|
||||
commandContext: {},
|
||||
shellConfirmationRequest: null,
|
||||
confirmationRequest: null,
|
||||
});
|
||||
|
||||
const spySetActiveExtensionContext = vi.spyOn(
|
||||
mockConfig,
|
||||
'setActiveExtensionContext',
|
||||
);
|
||||
|
||||
const { unmount } = await act(async () => renderAppContainer());
|
||||
|
||||
expect(capturedUIActions).toBeTruthy();
|
||||
|
||||
await act(async () => capturedUIActions.handleFinalSubmit('/help'));
|
||||
|
||||
// It should not touch the context at all
|
||||
expect(spySetActiveExtensionContext).not.toHaveBeenCalled();
|
||||
|
||||
unmount();
|
||||
});
|
||||
});
|
||||
|
||||
describe('Overflow Hint Handling', () => {
|
||||
|
||||
@@ -1349,6 +1349,8 @@ Logging in with Google... Restarting Gemini CLI to continue.
|
||||
if (parsedCommand.extensionContext) {
|
||||
if (config.hasExtensionPlanDir(parsedCommand.extensionContext)) {
|
||||
config.setActiveExtensionContext(parsedCommand.extensionContext);
|
||||
} else {
|
||||
config.setActiveExtensionContext(undefined);
|
||||
}
|
||||
} else if (parsedCommand.commandToExecute?.name === 'plan') {
|
||||
config.setActiveExtensionContext(undefined);
|
||||
|
||||
Reference in New Issue
Block a user