From df914e508a33dc174bf3154af7e7341cf58f6e0b Mon Sep 17 00:00:00 2001 From: Taylor Mullen Date: Thu, 5 Feb 2026 17:24:06 -0800 Subject: [PATCH 1/2] fix(cli): reload skills and agents on extension restart Ensure that running /extensions restart also triggers a reload of agent skills and agents, removing the need for manual /skills reload or /agents refresh commands. Fixes https://github.com/google-gemini/gemini-cli/issues/REPLACE_WITH_ISSUE_NUMBER --- packages/cli/src/ui/commands/extensionsCommand.test.ts | 6 ++++++ packages/cli/src/ui/commands/extensionsCommand.ts | 5 +++++ 2 files changed, 11 insertions(+) diff --git a/packages/cli/src/ui/commands/extensionsCommand.test.ts b/packages/cli/src/ui/commands/extensionsCommand.test.ts index 608dee19421..62d7a45ea71 100644 --- a/packages/cli/src/ui/commands/extensionsCommand.test.ts +++ b/packages/cli/src/ui/commands/extensionsCommand.test.ts @@ -148,12 +148,18 @@ describe('extensionsCommand', () => { mockGetExtensions.mockReturnValue([inactiveExt, activeExt, allExt]); vi.mocked(open).mockClear(); + const mockReloadAgents = vi.fn().mockResolvedValue(undefined); + mockContext = createMockCommandContext({ services: { config: { getExtensions: mockGetExtensions, getExtensionLoader: vi.fn().mockReturnValue(mockExtensionLoader), getWorkingDir: () => '/test/dir', + reloadSkills: vi.fn().mockResolvedValue(undefined), + getAgentRegistry: vi.fn().mockReturnValue({ + reload: mockReloadAgents, + }), }, }, ui: { diff --git a/packages/cli/src/ui/commands/extensionsCommand.ts b/packages/cli/src/ui/commands/extensionsCommand.ts index 4cf48d7662d..fa2024fb17c 100644 --- a/packages/cli/src/ui/commands/extensionsCommand.ts +++ b/packages/cli/src/ui/commands/extensionsCommand.ts @@ -231,6 +231,11 @@ async function restartAction( (result): result is PromiseRejectedResult => result.status === 'rejected', ); + if (failures.length < extensionsToRestart.length) { + await context.services.config?.reloadSkills(); + await context.services.config?.getAgentRegistry()?.reload(); + } + if (failures.length > 0) { const errorMessages = failures .map((failure, index) => { From 003f4215b821a9a67cc20b38c8bb76d57894fa8d Mon Sep 17 00:00:00 2001 From: Taylor Mullen Date: Fri, 6 Feb 2026 16:29:18 -0800 Subject: [PATCH 2/2] fix(cli): add error handling for skill and agent reloading on restart - Adds try-catch block to reloadSkills and agentRegistry.reload in restartAction - Adds tests to verify error handling when reloading fails --- .../src/ui/commands/extensionsCommand.test.ts | 28 +++++++++++++++++-- .../cli/src/ui/commands/extensionsCommand.ts | 11 ++++++-- 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/packages/cli/src/ui/commands/extensionsCommand.test.ts b/packages/cli/src/ui/commands/extensionsCommand.test.ts index 62d7a45ea71..1e5f395a27b 100644 --- a/packages/cli/src/ui/commands/extensionsCommand.test.ts +++ b/packages/cli/src/ui/commands/extensionsCommand.test.ts @@ -129,6 +129,8 @@ describe('extensionsCommand', () => { let mockContext: CommandContext; const mockDispatchExtensionState = vi.fn(); let mockExtensionLoader: unknown; + let mockReloadSkills: MockedFunction<() => Promise>; + let mockReloadAgents: MockedFunction<() => Promise>; beforeEach(() => { vi.resetAllMocks(); @@ -148,7 +150,8 @@ describe('extensionsCommand', () => { mockGetExtensions.mockReturnValue([inactiveExt, activeExt, allExt]); vi.mocked(open).mockClear(); - const mockReloadAgents = vi.fn().mockResolvedValue(undefined); + mockReloadAgents = vi.fn().mockResolvedValue(undefined); + mockReloadSkills = vi.fn().mockResolvedValue(undefined); mockContext = createMockCommandContext({ services: { @@ -156,7 +159,7 @@ describe('extensionsCommand', () => { getExtensions: mockGetExtensions, getExtensionLoader: vi.fn().mockReturnValue(mockExtensionLoader), getWorkingDir: () => '/test/dir', - reloadSkills: vi.fn().mockResolvedValue(undefined), + reloadSkills: mockReloadSkills, getAgentRegistry: vi.fn().mockReturnValue({ reload: mockReloadAgents, }), @@ -898,6 +901,27 @@ describe('extensionsCommand', () => { type: 'RESTARTED', payload: { name: 'ext2' }, }); + expect(mockReloadSkills).toHaveBeenCalled(); + expect(mockReloadAgents).toHaveBeenCalled(); + }); + + it('handles errors during skill or agent reload', async () => { + const mockExtensions = [ + { name: 'ext1', isActive: true }, + ] as GeminiCLIExtension[]; + mockGetExtensions.mockReturnValue(mockExtensions); + mockReloadSkills.mockRejectedValue(new Error('Failed to reload skills')); + + await restartAction!(mockContext, '--all'); + + expect(mockRestartExtension).toHaveBeenCalledWith(mockExtensions[0]); + expect(mockReloadSkills).toHaveBeenCalled(); + expect(mockContext.ui.addItem).toHaveBeenCalledWith( + expect.objectContaining({ + type: MessageType.ERROR, + text: 'Failed to reload skills or agents: Failed to reload skills', + }), + ); }); it('restarts only specified active extensions', async () => { diff --git a/packages/cli/src/ui/commands/extensionsCommand.ts b/packages/cli/src/ui/commands/extensionsCommand.ts index fa2024fb17c..c7359a2a46e 100644 --- a/packages/cli/src/ui/commands/extensionsCommand.ts +++ b/packages/cli/src/ui/commands/extensionsCommand.ts @@ -232,8 +232,15 @@ async function restartAction( ); if (failures.length < extensionsToRestart.length) { - await context.services.config?.reloadSkills(); - await context.services.config?.getAgentRegistry()?.reload(); + try { + await context.services.config?.reloadSkills(); + await context.services.config?.getAgentRegistry()?.reload(); + } catch (error) { + context.ui.addItem({ + type: MessageType.ERROR, + text: `Failed to reload skills or agents: ${getErrorMessage(error)}`, + }); + } } if (failures.length > 0) {