Skip to main content
Glama
agentMatcher.test.ts10.6 kB
import { describe, it, expect } from 'vitest'; import { matchAgentToTask, getSuggestedAgentType, getKeywordMatchDetails } from './agentMatcher.js'; import { Task, TaskStatus } from '../types/index.js'; // Helper function to create a test task function createTestTask(name: string, description?: string, notes?: string): Task { return { id: 'test-id', name, description: description || '', notes, status: TaskStatus.PENDING, dependencies: [], createdAt: new Date(), updatedAt: new Date(), }; } // Helper function to create test agents function createTestAgents() { return [ { name: 'Frontend Developer', type: 'frontend' }, { name: 'Backend Engineer', type: 'backend' }, { name: 'Database Admin', type: 'database' }, { name: 'Full Stack Developer', type: 'fullstack' }, { name: 'Mobile Developer', type: 'mobile' }, { name: 'QA Engineer', type: 'testing' }, { name: 'Security Expert', type: 'security' }, { name: 'Data Scientist', type: 'data' }, { name: 'General Purpose Agent' }, ]; } describe('agentMatcher', () => { describe('matchAgentToTask', () => { const agents = createTestAgents(); it('should match frontend tasks correctly', () => { const task = createTestTask( 'Update React component', 'Need to update the UserProfile component to use new CSS styles and improve responsive design' ); expect(matchAgentToTask(task, agents)).toBe('Frontend Developer'); }); it('should match backend tasks correctly', () => { const task = createTestTask( 'Create REST API endpoint', 'Implement a new Express.js endpoint for user authentication using JWT tokens' ); expect(matchAgentToTask(task, agents)).toBe('Backend Engineer'); }); it('should match database tasks correctly', () => { const task = createTestTask( 'Optimize database queries', 'Need to add indexes to PostgreSQL tables and optimize slow SQL queries' ); expect(matchAgentToTask(task, agents)).toBe('Database Admin'); }); it('should match fullstack tasks correctly', () => { const task = createTestTask( 'Deploy application to AWS', 'Set up CI/CD pipeline with Docker and Kubernetes for the MERN stack application' ); expect(matchAgentToTask(task, agents)).toBe('Full Stack Developer'); }); it('should match mobile tasks correctly', () => { const task = createTestTask( 'Fix iOS app crash', 'Debug and fix React Native app crash on iOS devices when using camera' ); expect(matchAgentToTask(task, agents)).toBe('Mobile Developer'); }); it('should match testing tasks correctly', () => { const task = createTestTask( 'Write unit tests', 'Create Jest unit tests for the new authentication service with mocking' ); expect(matchAgentToTask(task, agents)).toBe('QA Engineer'); }); it('should match security tasks correctly', () => { const task = createTestTask( 'Security audit', 'Perform OWASP security audit and fix XSS vulnerabilities in the application' ); expect(matchAgentToTask(task, agents)).toBe('Security Expert'); }); it('should match data/ML tasks correctly', () => { const task = createTestTask( 'Implement ML model', 'Create a machine learning model using TensorFlow for data analysis and visualization' ); expect(matchAgentToTask(task, agents)).toBe('Data Scientist'); }); it('should return undefined for empty task descriptions', () => { const task = createTestTask('', ''); expect(matchAgentToTask(task, agents)).toBeUndefined(); }); it('should return undefined when no agents are available', () => { const task = createTestTask('Update React component'); expect(matchAgentToTask(task, [])).toBeUndefined(); }); it('should return undefined for tasks with no matching keywords', () => { const task = createTestTask( 'Generic task', 'This is a task about something completely unrelated to programming' ); expect(matchAgentToTask(task, agents)).toBeUndefined(); }); it('should handle null/undefined task gracefully', () => { expect(matchAgentToTask(null as any, agents)).toBeUndefined(); expect(matchAgentToTask(undefined as any, agents)).toBeUndefined(); }); it('should match based on agent name when type is not available', () => { const agentsWithoutTypes = [ { name: 'React Specialist' }, { name: 'Node.js Developer' }, ]; const task = createTestTask('Fix React hooks issue'); expect(matchAgentToTask(task, agentsWithoutTypes)).toBe('React Specialist'); }); it('should match based on capabilities when available', () => { const agentsWithCapabilities = [ { name: 'Agent 1', capabilities: ['python', 'machine learning', 'data analysis'] }, { name: 'Agent 2', capabilities: ['javascript', 'react', 'frontend'] }, ]; const task = createTestTask('Build ML pipeline', 'Create a data pipeline for machine learning'); expect(matchAgentToTask(task, agentsWithCapabilities)).toBe('Agent 1'); }); it('should prefer exact type matches over name matches', () => { const mixedAgents = [ { name: 'Backend Specialist', type: 'frontend' }, // Misleading name { name: 'Frontend Expert', type: 'backend' }, // Misleading name ]; const task = createTestTask('Update React UI', 'Modify React components and CSS'); expect(matchAgentToTask(task, mixedAgents)).toBe('Backend Specialist'); // Has frontend type }); it('should handle multiple keyword matches correctly', () => { const task = createTestTask( 'Full stack development', 'Build React frontend with Node.js backend API and MongoDB database integration' ); expect(matchAgentToTask(task, agents)).toBe('Full Stack Developer'); }); }); describe('getSuggestedAgentType', () => { it('should suggest frontend for UI tasks', () => { const task = createTestTask('Style navigation bar', 'Update CSS and React components'); expect(getSuggestedAgentType(task)).toBe('frontend'); }); it('should suggest backend for API tasks', () => { const task = createTestTask('Create user endpoint', 'Build REST API with Express.js'); expect(getSuggestedAgentType(task)).toBe('backend'); }); it('should return undefined for unclear tasks', () => { const task = createTestTask('Do something', 'Generic task description'); expect(getSuggestedAgentType(task)).toBeUndefined(); }); }); describe('getKeywordMatchDetails', () => { it('should return detailed keyword matches', () => { const task = createTestTask( 'React and Node.js task', 'Build a React frontend with Node.js backend' ); const details = getKeywordMatchDetails(task); expect(details.length).toBeGreaterThan(0); expect(details[0].matchedKeywords).toContain('react'); expect(details.find((d: any) => d.type === 'backend')?.matchedKeywords).toContain('node'); }); it('should sort by score descending', () => { const task = createTestTask( 'Database optimization', 'Optimize PostgreSQL queries and add indexes to tables' ); const details = getKeywordMatchDetails(task); expect(details.length).toBeGreaterThan(0); expect(details[0].type).toBe('database'); for (let i = 1; i < details.length; i++) { expect(details[i].score).toBeLessThanOrEqual(details[i - 1].score); } }); it('should return empty array for no matches', () => { const task = createTestTask('Random task', 'No programming keywords here'); const details = getKeywordMatchDetails(task); expect(details).toEqual([]); }); it('should include implementation guide in matching', () => { const task: Task = { ...createTestTask('Task', 'Description'), implementationGuide: 'Use TensorFlow for machine learning implementation' }; const details = getKeywordMatchDetails(task); const dataMatch = details.find((d: any) => d.type === 'data'); expect(dataMatch).toBeDefined(); expect(dataMatch?.matchedKeywords).toContain('tensorflow'); expect(dataMatch?.matchedKeywords).toContain('machine learning'); }); }); describe('keyword scoring', () => { it('should give higher scores for multiple keyword matches', () => { const agents = createTestAgents(); const task1 = createTestTask('React task', 'Simple React component update'); const task2 = createTestTask( 'Complex React task', 'Update React components with TypeScript, add CSS animations, and improve responsive design' ); const details1 = getKeywordMatchDetails(task1); const details2 = getKeywordMatchDetails(task2); const frontend1 = details1.find((d: any) => d.type === 'frontend'); const frontend2 = details2.find((d: any) => d.type === 'frontend'); expect(frontend2?.score).toBeGreaterThan(frontend1?.score || 0); }); it('should handle case-insensitive matching', () => { const task = createTestTask('REACT COMPONENT', 'update the JAVASCRIPT and CSS'); expect(getSuggestedAgentType(task)).toBe('frontend'); }); it('should match whole words only', () => { const task = createTestTask( 'Database optimization', 'This is about database, not about databasesystem' ); const details = getKeywordMatchDetails(task); const databaseMatch = details.find((d: any) => d.type === 'database'); // Should match 'database' as a whole word expect(databaseMatch?.matchedKeywords).toContain('database'); // Test that partial matches don't count const task2 = createTestTask( 'Preact component', 'This is about Preact component' ); const details2 = getKeywordMatchDetails(task2); const frontendMatch = details2.find((d: any) => d.type === 'frontend'); // Should match 'component' but not 'react' (which is inside 'preact') expect(frontendMatch?.matchedKeywords).toContain('component'); expect(frontendMatch?.matchedKeywords).not.toContain('react'); }); }); });

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/cjo4m06/mcp-shrimp-task-manager'

If you have feedback or need assistance with the MCP directory API, please join our Discord server