diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts index 747e09de..a3babddf 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.test.ts @@ -329,4 +329,102 @@ Add any other context about the problem here. expect(commandResult).toBe(true); }); }); + + describe('/tools command', () => { + it('should show an error if tool registry is not available', async () => { + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue(undefined), + } as unknown as Config; + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/tools'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.ERROR, + text: 'Could not retrieve tools.', + }), + expect.any(Number), + ); + expect(commandResult).toBe(true); + }); + + it('should show an error if getAllTools returns undefined', async () => { + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue({ + getAllTools: vi.fn().mockReturnValue(undefined), + }), + } as unknown as Config; + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/tools'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.ERROR, + text: 'Could not retrieve tools.', + }), + expect.any(Number), + ); + expect(commandResult).toBe(true); + }); + + it('should display available tools when tools are found', async () => { + const mockTools = [{ name: 'tool1' }, { name: 'tool2' }]; + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue({ + getAllTools: vi.fn().mockReturnValue(mockTools), + }), + } as unknown as Config; + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/tools'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.INFO, + text: 'Available tools:\n\ntool1\ntool2', + }), + expect.any(Number), + ); + expect(commandResult).toBe(true); + }); + + it('should display a message when no tools are available', async () => { + const mockTools: unknown[] = []; + mockConfig = { + ...mockConfig, + getToolRegistry: vi.fn().mockResolvedValue({ + getAllTools: vi.fn().mockReturnValue(mockTools), + }), + } as unknown as Config; + const { handleSlashCommand } = getProcessor(); + let commandResult: SlashCommandActionReturn | boolean = false; + await act(async () => { + commandResult = handleSlashCommand('/tools'); + }); + + expect(mockAddItem).toHaveBeenNthCalledWith( + 2, + expect.objectContaining({ + type: MessageType.INFO, + text: 'Available tools:\n\n', + }), + expect.any(Number), + ); + expect(commandResult).toBe(true); + }); + }); }); diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts index 51def9d5..6de2ceab 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts @@ -161,7 +161,28 @@ export const useSlashCommandProcessor = ( } }, }, - + { + name: 'tools', + description: 'list available tools', + action: async (_mainCommand, _subCommand, _args) => { + const toolRegistry = await config?.getToolRegistry(); + const tools = toolRegistry?.getAllTools(); + if (!tools) { + addMessage({ + type: MessageType.ERROR, + content: 'Could not retrieve tools.', + timestamp: new Date(), + }); + return; + } + const toolList = tools.map((tool) => tool.name); + addMessage({ + type: MessageType.INFO, + content: `Available tools:\n\n${toolList.join('\n')}`, + timestamp: new Date(), + }); + }, + }, { name: 'corgi', action: (_mainCommand, _subCommand, _args) => {