@fromsvenwithlove/devops-issues-cli
Version:
AI-powered CLI tool and library for Azure DevOps work item management with Claude agents
329 lines (293 loc) • 9.9 kB
JavaScript
/**
* Claude Agents Index
*
* Provides access to all Azure DevOps specialized Claude agents.
* These agents can be used to generate high-quality work items
* following Azure DevOps best practices.
*/
import { readFileSync } from 'fs';
import { join, dirname } from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);
/**
* Load agent content from markdown files
*/
function loadAgent(filename) {
try {
return readFileSync(join(__dirname, filename), 'utf-8');
} catch (error) {
throw new Error(`Failed to load agent ${filename}: ${error.message}`);
}
}
// Model tier definitions for cost optimization
export const MODEL_TIERS = {
OPUS: 'claude-3-opus-20240229',
SONNET: 'claude-3-5-sonnet-20241022',
HAIKU: 'claude-3-haiku-20240307'
};
// Export all agents
export const agents = {
// Core orchestration system
orchestrator: {
name: 'Orchestrator System',
description: 'Main agent coordination and workflow management',
file: 'CLAUDE.md',
complexity: 10,
recommendedModel: MODEL_TIERS.OPUS,
reasoning: 'Complex multi-agent coordination requiring sophisticated decision-making',
get content() { return loadAgent('../CLAUDE.md'); }
},
// Specialized work item agents
userStory: {
name: 'User Story Agent',
description: 'Creates INVEST-compliant user stories with acceptance criteria',
file: 'user-story-agent.md',
complexity: 3,
recommendedModel: MODEL_TIERS.HAIKU,
reasoning: 'Template-driven work following Agile patterns with structured validation',
get content() { return loadAgent('user-story-agent.md'); }
},
feature: {
name: 'Feature Agent',
description: 'Bridges Epics and User Stories with proper scope definition',
file: 'feature-agent.md',
complexity: 4,
recommendedModel: MODEL_TIERS.HAIKU,
reasoning: 'Structured work item creation with business analysis and scope management',
get content() { return loadAgent('feature-agent.md'); }
},
task: {
name: 'Task Agent',
description: 'Breaks down User Stories into implementable tasks',
file: 'task-agent.md',
complexity: 4,
recommendedModel: MODEL_TIERS.HAIKU,
reasoning: 'Work breakdown following established patterns with effort estimation',
get content() { return loadAgent('task-agent.md'); }
},
bug: {
name: 'Bug Agent',
description: 'Creates detailed bug reports with reproduction steps',
file: 'bug-agent.md',
complexity: 3,
recommendedModel: MODEL_TIERS.HAIKU,
reasoning: 'Highly structured reporting and categorization with clear templates',
get content() { return loadAgent('bug-agent.md'); }
},
// Development support agents
analyzer: {
name: 'Analyzer Agent',
description: 'Code quality and architecture analysis specialist',
file: 'analyzer-agent.md',
complexity: 9,
recommendedModel: MODEL_TIERS.OPUS,
reasoning: 'Deep technical analysis requiring sophisticated understanding of code patterns and architecture',
get content() { return loadAgent('analyzer-agent.md'); }
},
programmer: {
name: 'Programmer Agent',
description: 'Implementation specialist following project patterns',
file: 'programmer-agent.md',
complexity: 9,
recommendedModel: MODEL_TIERS.OPUS,
reasoning: 'Complex code generation and technical problem-solving with integration planning',
get content() { return loadAgent('programmer-agent.md'); }
},
validator: {
name: 'Validator Agent',
description: 'Quality assurance and testing specialist',
file: 'validator-agent.md',
complexity: 6,
recommendedModel: MODEL_TIERS.SONNET,
reasoning: 'Systematic testing and validation requiring methodical analysis and risk assessment',
get content() { return loadAgent('validator-agent.md'); }
},
research: {
name: 'Research Agent',
description: 'Information discovery and investigation specialist',
file: 'research-agent.md',
complexity: 6,
recommendedModel: MODEL_TIERS.SONNET,
reasoning: 'Information synthesis and comparative analysis with research methodology',
modelOptimization: {
defaultModel: MODEL_TIERS.SONNET,
canUseHaiku: true,
haikuSuitableFor: [
'Documentation lookups',
'Simple compatibility checks',
'Version comparisons',
'Installation/setup guides',
'Single technology research',
'Basic best practices documentation'
],
sonnetRequiredFor: [
'Multi-technology comparative analysis',
'Complex integration research',
'Research synthesis from multiple agents',
'Conflict resolution between sources',
'Cross-domain technology evaluation',
'Strategic technology recommendations'
],
complexityThreshold: 4 // Use Haiku for complexity <= 4, Sonnet for > 4
},
get content() { return loadAgent('research-agent.md'); }
},
documentation: {
name: 'Documentation Agent',
description: 'Technical writing and documentation specialist',
file: 'documentation-agent.md',
complexity: 5,
recommendedModel: MODEL_TIERS.SONNET,
reasoning: 'Technical writing and structured communication with audience adaptation',
get content() { return loadAgent('documentation-agent.md'); }
}
};
/**
* Get list of all available agents
*/
export function getAgentList() {
return Object.keys(agents).map(key => ({
key,
...agents[key]
}));
}
/**
* Get agent by key
*/
export function getAgent(key) {
return agents[key] || null;
}
/**
* Get agents by category
*/
export function getWorkItemAgents() {
return ['userStory', 'feature', 'task', 'bug'].map(key => ({
key,
...agents[key]
}));
}
export function getDevelopmentAgents() {
return ['analyzer', 'programmer', 'validator', 'research', 'documentation'].map(key => ({
key,
...agents[key]
}));
}
/**
* Load all agent contents for backup or distribution
*/
export function loadAllAgents() {
const result = {};
for (const [key, agent] of Object.entries(agents)) {
result[key] = {
...agent,
content: agent.content
};
}
return result;
}
/**
* Get agents by model tier for cost optimization
*/
export function getAgentsByModel(modelTier) {
return Object.keys(agents)
.filter(key => agents[key].recommendedModel === modelTier)
.map(key => ({
key,
...agents[key]
}));
}
/**
* Get model recommendation for specific agent
*/
export function getAgentModel(agentKey) {
const agent = agents[agentKey];
return agent ? agent.recommendedModel : null;
}
/**
* Get model tier based on complexity score
*/
export function getModelForComplexity(complexity) {
if (complexity >= 8) return MODEL_TIERS.OPUS;
if (complexity >= 5) return MODEL_TIERS.SONNET;
return MODEL_TIERS.HAIKU;
}
/**
* Get cost optimization summary
*/
export function getCostOptimizationSummary() {
const opusAgents = getAgentsByModel(MODEL_TIERS.OPUS);
const sonnetAgents = getAgentsByModel(MODEL_TIERS.SONNET);
const haikuAgents = getAgentsByModel(MODEL_TIERS.HAIKU);
return {
opus: {
count: opusAgents.length,
agents: opusAgents.map(a => a.key),
description: 'High-complexity agents requiring sophisticated reasoning'
},
sonnet: {
count: sonnetAgents.length,
agents: sonnetAgents.map(a => a.key),
description: 'Medium-complexity agents with balanced performance needs'
},
haiku: {
count: haikuAgents.length,
agents: haikuAgents.map(a => a.key),
description: 'Template-driven agents optimized for efficiency and cost'
}
};
}
/**
* Get dynamic model selection for research tasks
*/
export function getResearchModel(researchType, complexity = null) {
const researchAgent = agents.research;
if (!researchAgent.modelOptimization) {
return researchAgent.recommendedModel;
}
const { haikuSuitableFor, sonnetRequiredFor, complexityThreshold } = researchAgent.modelOptimization;
// Check if research type is explicitly suitable for Haiku
if (haikuSuitableFor.some(type => researchType.toLowerCase().includes(type.toLowerCase()))) {
return MODEL_TIERS.HAIKU;
}
// Check if research type requires Sonnet
if (sonnetRequiredFor.some(type => researchType.toLowerCase().includes(type.toLowerCase()))) {
return MODEL_TIERS.SONNET;
}
// Use complexity threshold if complexity is provided
if (complexity !== null) {
return complexity <= complexityThreshold ? MODEL_TIERS.HAIKU : MODEL_TIERS.SONNET;
}
// Default to Sonnet for unknown research types
return MODEL_TIERS.SONNET;
}
/**
* Get research model optimization recommendations
*/
export function getResearchOptimizationReport() {
const researchAgent = agents.research;
if (!researchAgent.modelOptimization) {
return { optimizationAvailable: false };
}
const { haikuSuitableFor, sonnetRequiredFor, complexityThreshold } = researchAgent.modelOptimization;
return {
optimizationAvailable: true,
defaultModel: researchAgent.recommendedModel,
costSavingsOpportunity: {
haikuSavings: '~90% cost reduction for simple research tasks',
haikuTaskTypes: haikuSuitableFor,
percentageOfTasksSuitable: '~40-50% of research tasks could use Haiku'
},
qualityPreservation: {
sonnetRequiredFor,
complexityThreshold,
recommendation: 'Use dynamic selection based on research scope and complexity'
},
implementationGuidance: {
assessmentNeeded: 'Evaluate research task complexity before model assignment',
fallbackStrategy: 'Default to Sonnet for uncertain complexity',
monitoringRequired: 'Track Haiku performance on research tasks for optimization'
}
};
}
export default agents;