list-agent-tools.test.js•7.83 kB
import { describe, it, expect, vi, beforeEach } from 'vitest';
import {
    handleListAgentTools,
    listAgentToolsDefinition,
} from '../../../tools/agents/list-agent-tools.js';
describe('List Agent Tools (LMP-95)', () => {
    let mockServer;
    beforeEach(() => {
        vi.clearAllMocks();
        mockServer = {
            api: {
                get: vi.fn(),
            },
            getApiHeaders: vi.fn().mockReturnValue({
                Authorization: 'Bearer test-password',
            }),
            createErrorResponse: vi.fn((error) => {
                throw error;
            }),
        };
    });
    describe('Tool Definition', () => {
        it('should have correct tool name', () => {
            expect(listAgentToolsDefinition.name).toBe('list_agent_tools');
        });
        it('should have a description', () => {
            expect(listAgentToolsDefinition.description).toBeDefined();
            expect(listAgentToolsDefinition.description).toContain('tools');
            expect(listAgentToolsDefinition.description).toContain('agent');
        });
        it('should have input schema', () => {
            expect(listAgentToolsDefinition.inputSchema).toBeDefined();
            expect(listAgentToolsDefinition.inputSchema.type).toBe('object');
            expect(listAgentToolsDefinition.inputSchema.properties).toHaveProperty('agent_id');
        });
        it('should require agent_id parameter', () => {
            expect(listAgentToolsDefinition.inputSchema.required).toContain('agent_id');
        });
    });
    describe('List Agent Tools Handler', () => {
        it('should successfully list tools for an agent', async () => {
            const mockAgentData = {
                id: 'agent-123',
                name: 'Test Agent',
                tools: ['tool-1', 'tool-2', 'tool-3'],
            };
            mockServer.api.get.mockResolvedValueOnce({ data: mockAgentData });
            const result = await handleListAgentTools(mockServer, {
                agent_id: 'agent-123',
            });
            // Verify API call
            expect(mockServer.api.get).toHaveBeenCalledWith('/agents/agent-123', {
                headers: {
                    Authorization: 'Bearer test-password',
                },
            });
            // Verify result format
            expect(result).toEqual({
                content: [
                    {
                        type: 'text',
                        text: JSON.stringify({
                            agent_id: 'agent-123',
                            agent_name: 'Test Agent',
                            tool_count: 3,
                            tools: ['tool-1', 'tool-2', 'tool-3'],
                        }),
                    },
                ],
            });
        });
        it('should handle empty tool list', async () => {
            mockServer.api.get.mockResolvedValueOnce({
                data: {
                    id: 'agent-empty',
                    name: 'Empty Agent',
                    tools: [],
                },
            });
            const result = await handleListAgentTools(mockServer, {
                agent_id: 'agent-empty',
            });
            const parsedText = JSON.parse(result.content[0].text);
            expect(parsedText.tool_count).toBe(0);
            expect(parsedText.tools).toEqual([]);
            expect(parsedText.agent_name).toBe('Empty Agent');
        });
        it('should handle agent without tools field', async () => {
            mockServer.api.get.mockResolvedValueOnce({
                data: {
                    id: 'agent-no-tools',
                    name: 'No Tools Agent',
                    // No tools field
                },
            });
            const result = await handleListAgentTools(mockServer, {
                agent_id: 'agent-no-tools',
            });
            const parsedText = JSON.parse(result.content[0].text);
            expect(parsedText.tool_count).toBe(0);
            expect(parsedText.tools).toEqual([]);
        });
        it('should handle API errors', async () => {
            const mockError = new Error('Failed to fetch agent');
            mockError.response = {
                status: 404,
                data: { detail: 'Agent not found' },
            };
            mockServer.api.get.mockRejectedValueOnce(mockError);
            await expect(
                handleListAgentTools(mockServer, {
                    agent_id: 'nonexistent-agent',
                }),
            ).rejects.toThrow('Failed to fetch agent');
            expect(mockServer.createErrorResponse).toHaveBeenCalledWith(mockError);
        });
        it('should handle missing agent_id', async () => {
            await expect(handleListAgentTools(mockServer, {})).rejects.toThrow(
                'Missing required argument: agent_id',
            );
        });
        it('should handle network errors', async () => {
            const mockError = new Error('Network error');
            mockError.code = 'ECONNREFUSED';
            mockServer.api.get.mockRejectedValueOnce(mockError);
            await expect(
                handleListAgentTools(mockServer, {
                    agent_id: 'agent-123',
                }),
            ).rejects.toThrow('Network error');
        });
        it('should handle server errors gracefully', async () => {
            const mockError = new Error('Internal server error');
            mockError.response = {
                status: 500,
                data: { detail: 'Database connection failed' },
            };
            mockServer.api.get.mockRejectedValueOnce(mockError);
            await expect(
                handleListAgentTools(mockServer, {
                    agent_id: 'agent-123',
                }),
            ).rejects.toThrow('Internal server error');
        });
        it('should handle unauthorized errors', async () => {
            const mockError = new Error('Unauthorized');
            mockError.response = {
                status: 401,
                data: { detail: 'Invalid authentication credentials' },
            };
            mockServer.api.get.mockRejectedValueOnce(mockError);
            await expect(
                handleListAgentTools(mockServer, {
                    agent_id: 'agent-123',
                }),
            ).rejects.toThrow('Unauthorized');
        });
        it('should handle agent with many tools', async () => {
            const manyTools = Array.from({ length: 50 }, (_, i) => `tool-${i + 1}`);
            mockServer.api.get.mockResolvedValueOnce({
                data: {
                    id: 'agent-many-tools',
                    name: 'Many Tools Agent',
                    tools: manyTools,
                },
            });
            const result = await handleListAgentTools(mockServer, {
                agent_id: 'agent-many-tools',
            });
            const parsedText = JSON.parse(result.content[0].text);
            expect(parsedText.tool_count).toBe(50);
            expect(parsedText.tools).toHaveLength(50);
            expect(parsedText.tools[0]).toBe('tool-1');
            expect(parsedText.tools[49]).toBe('tool-50');
        });
    });
    describe('Input Validation', () => {
        it('should validate required parameters', () => {
            const inputSchema = listAgentToolsDefinition.inputSchema;
            // Check schema structure
            expect(inputSchema.type).toBe('object');
            expect(inputSchema.required).toContain('agent_id');
            expect(inputSchema.properties.agent_id.type).toBe('string');
            // The actual validation happens in the handler
            // These tests verify the schema definition is correct
        });
    });
});