refactor(cli): standardize on 'reload' verb for all components (#20654)

Co-authored-by: Krishna Korade <MushuEE@users.noreply.github.com>
Co-authored-by: Jacob Richman <jacob314@gmail.com>
This commit is contained in:
Keith Guerin
2026-03-07 14:56:11 -08:00
committed by GitHub
parent dac3735626
commit dc6741097c
21 changed files with 125 additions and 101 deletions

View File

@@ -1009,10 +1009,10 @@ Logging in with Google... Restarting Gemini CLI to continue.
historyManager.addItem(
{
type: MessageType.INFO,
text: `Memory refreshed successfully. ${
text: `Memory reloaded successfully. ${
flattenedMemory.length > 0
? `Loaded ${flattenedMemory.length} characters from ${fileCount} file(s).`
: 'No memory content found.'
? `Loaded ${flattenedMemory.length} characters from ${fileCount} file(s)`
: 'No memory content found'
}`,
},
Date.now(),

View File

@@ -105,34 +105,40 @@ describe('agentsCommand', () => {
);
});
it('should reload the agent registry when refresh subcommand is called', async () => {
it('should reload the agent registry when reload subcommand is called', async () => {
const reloadSpy = vi.fn().mockResolvedValue(undefined);
mockConfig.getAgentRegistry = vi.fn().mockReturnValue({
reload: reloadSpy,
});
const refreshCommand = agentsCommand.subCommands?.find(
(cmd) => cmd.name === 'refresh',
const reloadCommand = agentsCommand.subCommands?.find(
(cmd) => cmd.name === 'reload',
);
expect(refreshCommand).toBeDefined();
expect(reloadCommand).toBeDefined();
const result = await refreshCommand!.action!(mockContext, '');
const result = await reloadCommand!.action!(mockContext, '');
expect(reloadSpy).toHaveBeenCalled();
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({
type: MessageType.INFO,
text: 'Reloading agent registry...',
}),
);
expect(result).toEqual({
type: 'message',
messageType: 'info',
content: 'Agents refreshed successfully.',
content: 'Agents reloaded successfully',
});
});
it('should show an error if agent registry is not available during refresh', async () => {
it('should show an error if agent registry is not available during reload', async () => {
mockConfig.getAgentRegistry = vi.fn().mockReturnValue(undefined);
const refreshCommand = agentsCommand.subCommands?.find(
(cmd) => cmd.name === 'refresh',
const reloadCommand = agentsCommand.subCommands?.find(
(cmd) => cmd.name === 'reload',
);
const result = await refreshCommand!.action!(mockContext, '');
const result = await reloadCommand!.action!(mockContext, '');
expect(result).toEqual({
type: 'message',

View File

@@ -322,9 +322,9 @@ const configCommand: SlashCommand = {
completion: completeAllAgents,
};
const agentsRefreshCommand: SlashCommand = {
name: 'refresh',
altNames: ['reload'],
const agentsReloadCommand: SlashCommand = {
name: 'reload',
altNames: ['refresh'],
description: 'Reload the agent registry',
kind: CommandKind.BUILT_IN,
action: async (context: CommandContext) => {
@@ -340,7 +340,7 @@ const agentsRefreshCommand: SlashCommand = {
context.ui.addItem({
type: MessageType.INFO,
text: 'Refreshing agent registry...',
text: 'Reloading agent registry...',
});
await agentRegistry.reload();
@@ -348,7 +348,7 @@ const agentsRefreshCommand: SlashCommand = {
return {
type: 'message',
messageType: 'info',
content: 'Agents refreshed successfully.',
content: 'Agents reloaded successfully',
};
},
};
@@ -359,7 +359,7 @@ export const agentsCommand: SlashCommand = {
kind: CommandKind.BUILT_IN,
subCommands: [
agentsListCommand,
agentsRefreshCommand,
agentsReloadCommand,
enableCommand,
disableCommand,
configCommand,

View File

@@ -892,7 +892,7 @@ describe('extensionsCommand', () => {
});
});
describe('restart', () => {
describe('reload', () => {
let restartAction: SlashCommand['action'];
let mockRestartExtension: MockedFunction<
typeof ExtensionLoader.prototype.restartExtension
@@ -900,7 +900,7 @@ describe('extensionsCommand', () => {
beforeEach(() => {
restartAction = extensionsCommand().subCommands?.find(
(c) => c.name === 'restart',
(c) => c.name === 'reload',
)?.action;
expect(restartAction).not.toBeNull();
@@ -911,7 +911,7 @@ describe('extensionsCommand', () => {
getExtensions: mockGetExtensions,
restartExtension: mockRestartExtension,
}));
mockContext.invocation!.name = 'restart';
mockContext.invocation!.name = 'reload';
});
it('should show a message if no extensions are installed', async () => {
@@ -930,7 +930,7 @@ describe('extensionsCommand', () => {
});
});
it('restarts all active extensions when --all is provided', async () => {
it('reloads all active extensions when --all is provided', async () => {
const mockExtensions = [
{ name: 'ext1', isActive: true },
{ name: 'ext2', isActive: true },
@@ -946,13 +946,13 @@ describe('extensionsCommand', () => {
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({
type: MessageType.INFO,
text: 'Restarting 2 extensions...',
text: 'Reloading 2 extensions...',
}),
);
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({
type: MessageType.INFO,
text: '2 extensions restarted successfully.',
text: '2 extensions reloaded successfully',
}),
);
expect(mockContext.ui.dispatchExtensionStateUpdate).toHaveBeenCalledWith({
@@ -986,7 +986,7 @@ describe('extensionsCommand', () => {
);
});
it('restarts only specified active extensions', async () => {
it('reloads only specified active extensions', async () => {
const mockExtensions = [
{ name: 'ext1', isActive: false },
{ name: 'ext2', isActive: true },
@@ -1024,13 +1024,13 @@ describe('extensionsCommand', () => {
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({
type: MessageType.ERROR,
text: 'Usage: /extensions restart <extension-names>|--all',
text: 'Usage: /extensions reload <extension-names>|--all',
}),
);
expect(mockRestartExtension).not.toHaveBeenCalled();
});
it('handles errors during extension restart', async () => {
it('handles errors during extension reload', async () => {
const mockExtensions = [
{ name: 'ext1', isActive: true },
] as GeminiCLIExtension[];
@@ -1043,7 +1043,7 @@ describe('extensionsCommand', () => {
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
expect.objectContaining({
type: MessageType.ERROR,
text: 'Failed to restart some extensions:\n ext1: Failed to restart',
text: 'Failed to reload some extensions:\n ext1: Failed to restart',
}),
);
});
@@ -1066,7 +1066,7 @@ describe('extensionsCommand', () => {
);
});
it('does not restart any extensions if none are found', async () => {
it('does not reload any extensions if none are found', async () => {
const mockExtensions = [
{ name: 'ext1', isActive: true },
] as GeminiCLIExtension[];
@@ -1083,8 +1083,8 @@ describe('extensionsCommand', () => {
);
});
it('should suggest only enabled extension names for the restart command', async () => {
mockContext.invocation!.name = 'restart';
it('should suggest only enabled extension names for the reload command', async () => {
mockContext.invocation!.name = 'reload';
const mockExtensions = [
{ name: 'ext1', isActive: true },
{ name: 'ext2', isActive: false },

View File

@@ -176,7 +176,7 @@ async function restartAction(
if (!all && names?.length === 0) {
context.ui.addItem({
type: MessageType.ERROR,
text: 'Usage: /extensions restart <extension-names>|--all',
text: 'Usage: /extensions reload <extension-names>|--all',
});
return Promise.resolve();
}
@@ -208,12 +208,12 @@ async function restartAction(
const s = extensionsToRestart.length > 1 ? 's' : '';
const restartingMessage = {
const reloadingMessage = {
type: MessageType.INFO,
text: `Restarting ${extensionsToRestart.length} extension${s}...`,
text: `Reloading ${extensionsToRestart.length} extension${s}...`,
color: theme.text.primary,
};
context.ui.addItem(restartingMessage);
context.ui.addItem(reloadingMessage);
const results = await Promise.allSettled(
extensionsToRestart.map(async (extension) => {
@@ -254,12 +254,12 @@ async function restartAction(
.join('\n ');
context.ui.addItem({
type: MessageType.ERROR,
text: `Failed to restart some extensions:\n ${errorMessages}`,
text: `Failed to reload some extensions:\n ${errorMessages}`,
});
} else {
const infoItem: HistoryItemInfo = {
type: MessageType.INFO,
text: `${extensionsToRestart.length} extension${s} restarted successfully.`,
text: `${extensionsToRestart.length} extension${s} reloaded successfully`,
icon: emptyIcon,
color: theme.text.primary,
};
@@ -729,7 +729,8 @@ export function completeExtensions(
}
if (
context.invocation?.name === 'disable' ||
context.invocation?.name === 'restart'
context.invocation?.name === 'restart' ||
context.invocation?.name === 'reload'
) {
extensions = extensions.filter((ext) => ext.isActive);
}
@@ -824,9 +825,10 @@ const exploreExtensionsCommand: SlashCommand = {
action: exploreAction,
};
const restartCommand: SlashCommand = {
name: 'restart',
description: 'Restart all extensions',
const reloadCommand: SlashCommand = {
name: 'reload',
altNames: ['restart'],
description: 'Reload all extensions',
kind: CommandKind.BUILT_IN,
autoExecute: false,
action: restartAction,
@@ -863,7 +865,7 @@ export function extensionsCommand(
listExtensionsCommand,
updateExtensionsCommand,
exploreExtensionsCommand,
restartCommand,
reloadCommand,
...conditionalCommands,
],
action: (context, args) =>

View File

@@ -149,7 +149,7 @@ const authCommand: SlashCommand = {
return {
type: 'message',
messageType: 'info',
content: `Successfully authenticated and refreshed tools for '${serverName}'.`,
content: `Successfully authenticated and reloaded tools for '${serverName}'`,
};
} catch (error) {
return {
@@ -325,10 +325,10 @@ const schemaCommand: SlashCommand = {
action: (context) => listAction(context, true, true),
};
const refreshCommand: SlashCommand = {
name: 'refresh',
altNames: ['reload'],
description: 'Restarts MCP servers',
const reloadCommand: SlashCommand = {
name: 'reload',
altNames: ['refresh'],
description: 'Reloads MCP servers',
kind: CommandKind.BUILT_IN,
autoExecute: true,
action: async (
@@ -354,7 +354,7 @@ const refreshCommand: SlashCommand = {
context.ui.addItem({
type: 'info',
text: 'Restarting MCP servers...',
text: 'Reloading MCP servers...',
});
await mcpClientManager.restart();
@@ -460,7 +460,7 @@ async function handleEnableDisable(
const mcpClientManager = config.getMcpClientManager();
if (mcpClientManager) {
context.ui.addItem(
{ type: 'info', text: 'Restarting MCP servers...' },
{ type: 'info', text: 'Reloading MCP servers...' },
Date.now(),
);
await mcpClientManager.restart();
@@ -521,7 +521,7 @@ export const mcpCommand: SlashCommand = {
descCommand,
schemaCommand,
authCommand,
refreshCommand,
reloadCommand,
enableCommand,
disableCommand,
],

View File

@@ -39,13 +39,13 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
return {
type: 'message',
messageType: 'info',
content: `Memory refreshed successfully. Loaded ${memoryContent.length} characters from ${fileCount} file(s).`,
content: `Memory reloaded successfully. Loaded ${memoryContent.length} characters from ${fileCount} file(s).`,
};
}
return {
type: 'message',
messageType: 'info',
content: 'Memory refreshed successfully.',
content: 'Memory reloaded successfully.',
};
}),
showMemory: vi.fn(),
@@ -63,7 +63,7 @@ describe('memoryCommand', () => {
let mockContext: CommandContext;
const getSubCommand = (
name: 'show' | 'add' | 'refresh' | 'list',
name: 'show' | 'add' | 'reload' | 'list',
): SlashCommand => {
const subCommand = memoryCommand.subCommands?.find(
(cmd) => cmd.name === name,
@@ -206,15 +206,15 @@ describe('memoryCommand', () => {
});
});
describe('/memory refresh', () => {
let refreshCommand: SlashCommand;
describe('/memory reload', () => {
let reloadCommand: SlashCommand;
let mockSetUserMemory: Mock;
let mockSetGeminiMdFileCount: Mock;
let mockSetGeminiMdFilePaths: Mock;
let mockContextManagerRefresh: Mock;
beforeEach(() => {
refreshCommand = getSubCommand('refresh');
reloadCommand = getSubCommand('reload');
mockSetUserMemory = vi.fn();
mockSetGeminiMdFileCount = vi.fn();
mockSetGeminiMdFilePaths = vi.fn();
@@ -266,7 +266,7 @@ describe('memoryCommand', () => {
});
it('should use ContextManager.refresh when JIT is enabled', async () => {
if (!refreshCommand.action) throw new Error('Command has no action');
if (!reloadCommand.action) throw new Error('Command has no action');
// Enable JIT in mock config
const config = mockContext.services.config;
@@ -276,7 +276,7 @@ describe('memoryCommand', () => {
vi.mocked(config.getUserMemory).mockReturnValue('JIT Memory Content');
vi.mocked(config.getGeminiMdFileCount).mockReturnValue(3);
await refreshCommand.action(mockContext, '');
await reloadCommand.action(mockContext, '');
expect(mockContextManagerRefresh).toHaveBeenCalledOnce();
expect(mockRefreshServerHierarchicalMemory).not.toHaveBeenCalled();
@@ -284,29 +284,29 @@ describe('memoryCommand', () => {
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
{
type: MessageType.INFO,
text: 'Memory refreshed successfully. Loaded 18 characters from 3 file(s).',
text: 'Memory reloaded successfully. Loaded 18 characters from 3 file(s).',
},
expect.any(Number),
);
});
it('should display success message when memory is refreshed with content (Legacy)', async () => {
if (!refreshCommand.action) throw new Error('Command has no action');
it('should display success message when memory is reloaded with content (Legacy)', async () => {
if (!reloadCommand.action) throw new Error('Command has no action');
const successMessage = {
type: 'message',
messageType: MessageType.INFO,
content:
'Memory refreshed successfully. Loaded 18 characters from 2 file(s).',
'Memory reloaded successfully. Loaded 18 characters from 2 file(s).',
};
mockRefreshMemory.mockResolvedValue(successMessage);
await refreshCommand.action(mockContext, '');
await reloadCommand.action(mockContext, '');
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
{
type: MessageType.INFO,
text: 'Refreshing memory from source files...',
text: 'Reloading memory from source files...',
},
expect.any(Number),
);
@@ -316,42 +316,42 @@ describe('memoryCommand', () => {
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
{
type: MessageType.INFO,
text: 'Memory refreshed successfully. Loaded 18 characters from 2 file(s).',
text: 'Memory reloaded successfully. Loaded 18 characters from 2 file(s).',
},
expect.any(Number),
);
});
it('should display success message when memory is refreshed with no content', async () => {
if (!refreshCommand.action) throw new Error('Command has no action');
it('should display success message when memory is reloaded with no content', async () => {
if (!reloadCommand.action) throw new Error('Command has no action');
const successMessage = {
type: 'message',
messageType: MessageType.INFO,
content: 'Memory refreshed successfully. No memory content found.',
content: 'Memory reloaded successfully. No memory content found.',
};
mockRefreshMemory.mockResolvedValue(successMessage);
await refreshCommand.action(mockContext, '');
await reloadCommand.action(mockContext, '');
expect(mockRefreshMemory).toHaveBeenCalledOnce();
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
{
type: MessageType.INFO,
text: 'Memory refreshed successfully. No memory content found.',
text: 'Memory reloaded successfully. No memory content found.',
},
expect.any(Number),
);
});
it('should display an error message if refreshing fails', async () => {
if (!refreshCommand.action) throw new Error('Command has no action');
it('should display an error message if reloading fails', async () => {
if (!reloadCommand.action) throw new Error('Command has no action');
const error = new Error('Failed to read memory files.');
mockRefreshMemory.mockRejectedValue(error);
await refreshCommand.action(mockContext, '');
await reloadCommand.action(mockContext, '');
expect(mockRefreshMemory).toHaveBeenCalledOnce();
expect(mockSetUserMemory).not.toHaveBeenCalled();
@@ -361,27 +361,27 @@ describe('memoryCommand', () => {
expect(mockContext.ui.addItem).toHaveBeenCalledWith(
{
type: MessageType.ERROR,
text: `Error refreshing memory: ${error.message}`,
text: `Error reloading memory: ${error.message}`,
},
expect.any(Number),
);
});
it('should not throw if config service is unavailable', async () => {
if (!refreshCommand.action) throw new Error('Command has no action');
if (!reloadCommand.action) throw new Error('Command has no action');
const nullConfigContext = createMockCommandContext({
services: { config: null },
});
await expect(
refreshCommand.action(nullConfigContext, ''),
reloadCommand.action(nullConfigContext, ''),
).resolves.toBeUndefined();
expect(nullConfigContext.ui.addItem).toHaveBeenCalledWith(
{
type: MessageType.INFO,
text: 'Refreshing memory from source files...',
text: 'Reloading memory from source files...',
},
expect.any(Number),
);

View File

@@ -63,16 +63,16 @@ export const memoryCommand: SlashCommand = {
},
},
{
name: 'refresh',
altNames: ['reload'],
description: 'Refresh the memory from the source',
name: 'reload',
altNames: ['refresh'],
description: 'Reload the memory from the source',
kind: CommandKind.BUILT_IN,
autoExecute: true,
action: async (context) => {
context.ui.addItem(
{
type: MessageType.INFO,
text: 'Refreshing memory from source files...',
text: 'Reloading memory from source files...',
},
Date.now(),
);
@@ -95,7 +95,7 @@ export const memoryCommand: SlashCommand = {
{
type: MessageType.ERROR,
// eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion
text: `Error refreshing memory: ${(error as Error).message}`,
text: `Error reloading memory: ${(error as Error).message}`,
},
Date.now(),
);

View File

@@ -20,6 +20,7 @@ vi.mock('@google/gemini-cli-core', async (importOriginal) => {
UserAccountManager: vi.fn().mockImplementation(() => ({
getCachedGoogleAccount: vi.fn().mockReturnValue('mock@example.com'),
})),
getG1CreditBalance: vi.fn().mockReturnValue(undefined),
};
});

View File

@@ -34,7 +34,7 @@ export const INFORMATIVE_TIPS = [
'Define custom context file names, like CONTEXT.md (settings.json)…',
'Set max directories to scan for context files (/settings)…',
'Expand your workspace with additional directories (/directory)…',
'Control how /memory refresh loads context files (/settings)…',
'Control how /memory reload loads context files (/settings)…',
'Toggle respect for .gitignore files in context (/settings)…',
'Toggle respect for .geminiignore files in context (/settings)…',
'Enable recursive file search for @-file completions (/settings)…',
@@ -142,10 +142,10 @@ export const INFORMATIVE_TIPS = [
'Create a project-specific GEMINI.md file with /init…',
'List configured MCP servers and tools with /mcp list…',
'Authenticate with an OAuth-enabled MCP server with /mcp auth…',
'Restart MCP servers with /mcp refresh…',
'Reload MCP servers with /mcp reload…',
'See the current instructional context with /memory show…',
'Add content to the instructional memory with /memory add…',
'Reload instructional context from GEMINI.md files with /memory refresh…',
'Reload instructional context from GEMINI.md files with /memory reload…',
'List the paths of the GEMINI.md files in use with /memory list…',
'Choose your Gemini model with /model…',
'Display the privacy notice with /privacy…',