mirror of
https://github.com/google-gemini/gemini-cli
synced 2026-04-21 13:37:17 +00:00
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:
parent
dac3735626
commit
dc6741097c
21 changed files with 125 additions and 101 deletions
|
|
@ -24,6 +24,21 @@ and parameters.
|
|||
| -------- | ----------------- | ------------------------------------------------------------------------------------------------------------------ |
|
||||
| `query` | string (variadic) | Positional prompt. Defaults to one-shot mode. Use `-i/--prompt-interactive` to execute and continue interactively. |
|
||||
|
||||
## Interactive commands
|
||||
|
||||
These commands are available within the interactive REPL.
|
||||
|
||||
| Command | Description |
|
||||
| -------------------- | ---------------------------------------- |
|
||||
| `/skills reload` | Reload discovered skills from disk |
|
||||
| `/agents reload` | Reload the agent registry |
|
||||
| `/commands reload` | Reload custom slash commands |
|
||||
| `/memory reload` | Reload context files (e.g., `GEMINI.md`) |
|
||||
| `/mcp reload` | Restart and reload MCP servers |
|
||||
| `/extensions reload` | Reload all active extensions |
|
||||
| `/help` | Show help for all commands |
|
||||
| `/quit` | Exit the interactive session |
|
||||
|
||||
## CLI Options
|
||||
|
||||
| Option | Alias | Type | Default | Description |
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ You can interact with the loaded context files by using the `/memory` command.
|
|||
- **`/memory show`**: Displays the full, concatenated content of the current
|
||||
hierarchical memory. This lets you inspect the exact instructional context
|
||||
being provided to the model.
|
||||
- **`/memory refresh`**: Forces a re-scan and reload of all `GEMINI.md` files
|
||||
- **`/memory reload`**: Forces a re-scan and reload of all `GEMINI.md` files
|
||||
from all configured locations.
|
||||
- **`/memory add <text>`**: Appends your text to your global
|
||||
`~/.gemini/GEMINI.md` file. This lets you add persistent memories on the fly.
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ they appear in the UI.
|
|||
| UI Label | Setting | Description | Default |
|
||||
| ------------------------------------ | ------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |
|
||||
| Memory Discovery Max Dirs | `context.discoveryMaxDirs` | Maximum number of directories to search for memory. | `200` |
|
||||
| Load Memory From Include Directories | `context.loadMemoryFromIncludeDirectories` | Controls how /memory refresh loads GEMINI.md files. When true, include directories are scanned; when false, only the current directory is used. | `false` |
|
||||
| Load Memory From Include Directories | `context.loadMemoryFromIncludeDirectories` | Controls how /memory reload loads GEMINI.md files. When true, include directories are scanned; when false, only the current directory is used. | `false` |
|
||||
| Respect .gitignore | `context.fileFiltering.respectGitIgnore` | Respect .gitignore files when searching. | `true` |
|
||||
| Respect .geminiignore | `context.fileFiltering.respectGeminiIgnore` | Respect .geminiignore files when searching. | `true` |
|
||||
| Enable Recursive File Search | `context.fileFiltering.enableRecursiveFileSearch` | Enable recursive file search functionality when completing @ references in the prompt. | `true` |
|
||||
|
|
|
|||
|
|
@ -101,8 +101,8 @@ The agent will:
|
|||
|
||||
- **Server won't start?** Try running the docker command manually in your
|
||||
terminal to see if it prints an error (e.g., "image not found").
|
||||
- **Tools not found?** Run `/mcp refresh` to force the CLI to re-query the
|
||||
server for its capabilities.
|
||||
- **Tools not found?** Run `/mcp reload` to force the CLI to re-query the server
|
||||
for its capabilities.
|
||||
|
||||
## Next steps
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ excellent for debugging why the agent might be ignoring a rule.
|
|||
If you edit a `GEMINI.md` file while a session is running, the agent won't know
|
||||
immediately. Force a reload with:
|
||||
|
||||
**Command:** `/memory refresh`
|
||||
**Command:** `/memory reload`
|
||||
|
||||
## Best practices
|
||||
|
||||
|
|
|
|||
|
|
@ -75,7 +75,7 @@ Markdown file.
|
|||
Users can manage subagents using the following commands within the Gemini CLI:
|
||||
|
||||
- `/agents list`: Displays all available local and remote subagents.
|
||||
- `/agents refresh`: Reloads the agent registry. Use this after adding or
|
||||
- `/agents reload`: Reloads the agent registry. Use this after adding or
|
||||
modifying agent definition files.
|
||||
- `/agents enable <agent_name>`: Enables a specific subagent.
|
||||
- `/agents disable <agent_name>`: Disables a specific subagent.
|
||||
|
|
|
|||
|
|
@ -719,7 +719,7 @@ their corresponding top-level category object in your `settings.json` file.
|
|||
- **Default:** `[]`
|
||||
|
||||
- **`context.loadMemoryFromIncludeDirectories`** (boolean):
|
||||
- **Description:** Controls how /memory refresh loads GEMINI.md files. When
|
||||
- **Description:** Controls how /memory reload loads GEMINI.md files. When
|
||||
true, include directories are scanned; when false, only the current
|
||||
directory is used.
|
||||
- **Default:** `false`
|
||||
|
|
@ -1705,7 +1705,7 @@ conventions and context.
|
|||
loaded, allowing you to verify the hierarchy and content being used by the
|
||||
AI.
|
||||
- See the [Commands documentation](./commands.md#memory) for full details on
|
||||
the `/memory` command and its sub-commands (`show` and `refresh`).
|
||||
the `/memory` command and its sub-commands (`show` and `reload`).
|
||||
|
||||
By understanding and utilizing these configuration layers and the hierarchical
|
||||
nature of context files, you can effectively manage the AI's memory and tailor
|
||||
|
|
|
|||
|
|
@ -1169,7 +1169,7 @@ const SETTINGS_SCHEMA = {
|
|||
requiresRestart: false,
|
||||
default: false,
|
||||
description: oneLine`
|
||||
Controls how /memory refresh loads GEMINI.md files.
|
||||
Controls how /memory reload loads GEMINI.md files.
|
||||
When true, include directories are scanned; when false, only the current directory is used.
|
||||
`,
|
||||
showInDialog: true,
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
|
|
|
|||
|
|
@ -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',
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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 },
|
||||
|
|
|
|||
|
|
@ -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) =>
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
],
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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(),
|
||||
);
|
||||
|
|
|
|||
|
|
@ -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),
|
||||
};
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -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…',
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ describe('memory commands', () => {
|
|||
if (result.type === 'message') {
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(result.content).toBe(
|
||||
'Memory refreshed successfully. Loaded 33 characters from 2 file(s).',
|
||||
'Memory reloaded successfully. Loaded 33 characters from 2 file(s)',
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
@ -153,7 +153,7 @@ describe('memory commands', () => {
|
|||
if (result.type === 'message') {
|
||||
expect(result.messageType).toBe('info');
|
||||
expect(result.content).toBe(
|
||||
'Memory refreshed successfully. No memory content found.',
|
||||
'Memory reloaded successfully. No memory content found',
|
||||
);
|
||||
}
|
||||
});
|
||||
|
|
|
|||
|
|
@ -64,9 +64,9 @@ export async function refreshMemory(
|
|||
let content: string;
|
||||
|
||||
if (memoryContent.length > 0) {
|
||||
content = `Memory refreshed successfully. Loaded ${memoryContent.length} characters from ${fileCount} file(s).`;
|
||||
content = `Memory reloaded successfully. Loaded ${memoryContent.length} characters from ${fileCount} file(s)`;
|
||||
} else {
|
||||
content = 'Memory refreshed successfully. No memory content found.';
|
||||
content = 'Memory reloaded successfully. No memory content found';
|
||||
}
|
||||
|
||||
return {
|
||||
|
|
|
|||
|
|
@ -1222,8 +1222,8 @@
|
|||
},
|
||||
"loadMemoryFromIncludeDirectories": {
|
||||
"title": "Load Memory From Include Directories",
|
||||
"description": "Controls how /memory refresh loads GEMINI.md files. When true, include directories are scanned; when false, only the current directory is used.",
|
||||
"markdownDescription": "Controls how /memory refresh loads GEMINI.md files. When true, include directories are scanned; when false, only the current directory is used.\n\n- Category: `Context`\n- Requires restart: `no`\n- Default: `false`",
|
||||
"description": "Controls how /memory reload loads GEMINI.md files. When true, include directories are scanned; when false, only the current directory is used.",
|
||||
"markdownDescription": "Controls how /memory reload loads GEMINI.md files. When true, include directories are scanned; when false, only the current directory is used.\n\n- Category: `Context`\n- Requires restart: `no`\n- Default: `false`",
|
||||
"default": false,
|
||||
"type": "boolean"
|
||||
},
|
||||
|
|
|
|||
Loading…
Reference in a new issue