Add `/tools` slash command to view available tools (#752)

This commit is contained in:
Eddie Santos 2025-06-04 14:01:38 -07:00 committed by GitHub
parent fdc8bd8ed9
commit d99d132cdf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 120 additions and 1 deletions

View File

@ -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);
});
});
});

View File

@ -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) => {