276 lines
12 KiB
JavaScript
276 lines
12 KiB
JavaScript
/**
|
|
* Build Agents Hook - Generate optimized agent configurations
|
|
* Creates YAML agent definitions based on pretrain analysis
|
|
*/
|
|
import { z } from 'zod';
|
|
import * as path from 'path';
|
|
import * as fs from 'fs';
|
|
import { loadIntelligence } from './shared.js';
|
|
// Focus mode configurations
|
|
const focusConfigs = {
|
|
quality: {
|
|
description: 'Emphasizes code quality, best practices, and maintainability',
|
|
priorities: ['code-review', 'refactoring', 'documentation', 'testing'],
|
|
temperature: 0.3
|
|
},
|
|
speed: {
|
|
description: 'Optimized for rapid development and iteration',
|
|
priorities: ['implementation', 'prototyping', 'quick-fixes'],
|
|
temperature: 0.7
|
|
},
|
|
security: {
|
|
description: 'Security-first development with vulnerability awareness',
|
|
priorities: ['security-audit', 'input-validation', 'authentication', 'encryption'],
|
|
temperature: 0.2
|
|
},
|
|
testing: {
|
|
description: 'Test-driven development with comprehensive coverage',
|
|
priorities: ['unit-tests', 'integration-tests', 'e2e-tests', 'mocking'],
|
|
temperature: 0.4
|
|
},
|
|
fullstack: {
|
|
description: 'Balanced full-stack development capabilities',
|
|
priorities: ['frontend', 'backend', 'database', 'api-design'],
|
|
temperature: 0.5
|
|
}
|
|
};
|
|
export const hookBuildAgentsTool = {
|
|
name: 'hook_build_agents',
|
|
description: 'Generate optimized agent configurations from pretrain data',
|
|
parameters: z.object({
|
|
focus: z.enum(['quality', 'speed', 'security', 'testing', 'fullstack'])
|
|
.optional()
|
|
.default('quality')
|
|
.describe('Focus mode for agent generation'),
|
|
output: z.string().optional().default('.claude/agents').describe('Output directory'),
|
|
includePrompts: z.boolean().optional().default(true).describe('Include system prompts'),
|
|
format: z.enum(['yaml', 'json']).optional().default('yaml').describe('Output format')
|
|
}),
|
|
execute: async ({ focus, output, includePrompts, format }, { onProgress }) => {
|
|
const startTime = Date.now();
|
|
const intel = loadIntelligence();
|
|
const focusConfig = focusConfigs[focus];
|
|
onProgress?.({ progress: 0.1, message: 'Analyzing patterns...' });
|
|
// Detect languages from patterns
|
|
const detectedLangs = new Set();
|
|
const detectedFrameworks = new Set();
|
|
for (const state of Object.keys(intel.patterns)) {
|
|
if (state.includes('.rs'))
|
|
detectedLangs.add('rust');
|
|
if (state.includes('.ts') || state.includes('.js'))
|
|
detectedLangs.add('typescript');
|
|
if (state.includes('.tsx') || state.includes('.jsx'))
|
|
detectedFrameworks.add('react');
|
|
if (state.includes('.py'))
|
|
detectedLangs.add('python');
|
|
if (state.includes('.go'))
|
|
detectedLangs.add('go');
|
|
if (state.includes('.vue'))
|
|
detectedFrameworks.add('vue');
|
|
if (state.includes('.sql'))
|
|
detectedFrameworks.add('database');
|
|
}
|
|
onProgress?.({ progress: 0.3, message: 'Generating agent configs...' });
|
|
const agents = [];
|
|
// Language-specific agents
|
|
if (detectedLangs.has('rust')) {
|
|
agents.push({
|
|
name: 'rust-specialist',
|
|
type: 'rust-developer',
|
|
description: 'Rust development specialist for this codebase',
|
|
capabilities: ['cargo', 'unsafe-rust', 'async-rust', 'wasm', 'error-handling'],
|
|
focus: focusConfig.priorities,
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a Rust specialist.
|
|
Focus on: memory safety, zero-cost abstractions, idiomatic Rust patterns.
|
|
Use cargo conventions, prefer Result over panic, leverage the type system.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
if (detectedLangs.has('typescript')) {
|
|
agents.push({
|
|
name: 'typescript-specialist',
|
|
type: 'typescript-developer',
|
|
description: 'TypeScript development specialist',
|
|
capabilities: ['types', 'generics', 'decorators', 'async-await', 'modules'],
|
|
focus: focusConfig.priorities,
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a TypeScript specialist.
|
|
Focus on: strict typing, type inference, generic patterns, module organization.
|
|
Prefer type safety over any, use discriminated unions, leverage utility types.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
if (detectedLangs.has('python')) {
|
|
agents.push({
|
|
name: 'python-specialist',
|
|
type: 'python-developer',
|
|
description: 'Python development specialist',
|
|
capabilities: ['typing', 'async', 'testing', 'packaging', 'data-science'],
|
|
focus: focusConfig.priorities,
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a Python specialist.
|
|
Focus on: type hints, PEP standards, pythonic idioms, virtual environments.
|
|
Use dataclasses, prefer pathlib, leverage context managers.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
if (detectedLangs.has('go')) {
|
|
agents.push({
|
|
name: 'go-specialist',
|
|
type: 'go-developer',
|
|
description: 'Go development specialist',
|
|
capabilities: ['goroutines', 'channels', 'interfaces', 'testing', 'modules'],
|
|
focus: focusConfig.priorities,
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a Go specialist.
|
|
Focus on: simplicity, explicit error handling, goroutines, interface composition.
|
|
Follow Go conventions, use go fmt, prefer composition over inheritance.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
// Framework-specific agents
|
|
if (detectedFrameworks.has('react')) {
|
|
agents.push({
|
|
name: 'react-specialist',
|
|
type: 'react-developer',
|
|
description: 'React/Next.js development specialist',
|
|
capabilities: ['hooks', 'state-management', 'components', 'ssr', 'testing'],
|
|
focus: focusConfig.priorities,
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a React specialist.
|
|
Focus on: functional components, hooks, state management, performance optimization.
|
|
Prefer composition, use memo wisely, follow React best practices.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
if (detectedFrameworks.has('database')) {
|
|
agents.push({
|
|
name: 'database-specialist',
|
|
type: 'database-specialist',
|
|
description: 'Database design and optimization specialist',
|
|
capabilities: ['schema-design', 'queries', 'indexing', 'migrations', 'orm'],
|
|
focus: focusConfig.priorities,
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a database specialist.
|
|
Focus on: normalized schemas, efficient queries, proper indexing, data integrity.
|
|
Consider performance implications, use transactions appropriately.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
// Focus-specific agents
|
|
if (focus === 'testing' || focus === 'quality') {
|
|
agents.push({
|
|
name: 'test-architect',
|
|
type: 'test-engineer',
|
|
description: 'Testing and quality assurance specialist',
|
|
capabilities: ['unit-tests', 'integration-tests', 'mocking', 'coverage', 'tdd'],
|
|
focus: ['testing', 'quality', 'reliability'],
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a testing specialist.
|
|
Focus on: comprehensive test coverage, meaningful assertions, test isolation.
|
|
Write tests first when possible, mock external dependencies, aim for >80% coverage.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
if (focus === 'security') {
|
|
agents.push({
|
|
name: 'security-auditor',
|
|
type: 'security-specialist',
|
|
description: 'Security audit and hardening specialist',
|
|
capabilities: ['vulnerability-scan', 'auth', 'encryption', 'input-validation', 'owasp'],
|
|
focus: ['security', 'compliance', 'hardening'],
|
|
temperature: focusConfig.temperature,
|
|
systemPrompt: includePrompts ? `You are a security specialist.
|
|
Focus on: OWASP top 10, input validation, authentication, authorization, encryption.
|
|
Never trust user input, use parameterized queries, implement defense in depth.
|
|
${focusConfig.description}` : undefined
|
|
});
|
|
}
|
|
// Add coordinator
|
|
agents.push({
|
|
name: 'project-coordinator',
|
|
type: 'coordinator',
|
|
description: 'Coordinates multi-agent workflows for this project',
|
|
capabilities: ['task-decomposition', 'agent-routing', 'context-management'],
|
|
focus: focusConfig.priorities,
|
|
temperature: focusConfig.temperature
|
|
});
|
|
onProgress?.({ progress: 0.7, message: 'Writing agent files...' });
|
|
// Create output directory
|
|
const outputDir = path.join(process.cwd(), output || '.claude/agents');
|
|
if (!fs.existsSync(outputDir)) {
|
|
fs.mkdirSync(outputDir, { recursive: true });
|
|
}
|
|
// Write agent files
|
|
const savedFiles = [];
|
|
for (const agent of agents) {
|
|
const filename = `${agent.name}.${format}`;
|
|
const filePath = path.join(outputDir, filename);
|
|
let content;
|
|
if (format === 'yaml') {
|
|
content = `# ${agent.description}
|
|
name: ${agent.name}
|
|
type: ${agent.type}
|
|
description: ${agent.description}
|
|
capabilities:
|
|
${agent.capabilities.map(c => ` - ${c}`).join('\n')}
|
|
focus:
|
|
${agent.focus.map(f => ` - ${f}`).join('\n')}
|
|
temperature: ${agent.temperature}
|
|
${agent.systemPrompt ? `systemPrompt: |\n ${agent.systemPrompt.split('\n').join('\n ')}` : ''}
|
|
`;
|
|
}
|
|
else {
|
|
content = JSON.stringify(agent, null, 2);
|
|
}
|
|
fs.writeFileSync(filePath, content);
|
|
savedFiles.push(filename);
|
|
}
|
|
// Write index file
|
|
const indexPath = path.join(outputDir, `index.${format}`);
|
|
if (format === 'yaml') {
|
|
const indexContent = `# Generated Agent Index
|
|
# Focus: ${focus}
|
|
# Generated: ${new Date().toISOString()}
|
|
|
|
agents:
|
|
${agents.map(a => ` - ${a.name}`).join('\n')}
|
|
|
|
detected:
|
|
languages:
|
|
${[...detectedLangs].map(l => ` - ${l}`).join('\n') || ' - generic'}
|
|
frameworks:
|
|
${[...detectedFrameworks].map(f => ` - ${f}`).join('\n') || ' - none'}
|
|
`;
|
|
fs.writeFileSync(indexPath, indexContent);
|
|
}
|
|
else {
|
|
fs.writeFileSync(indexPath, JSON.stringify({
|
|
focus,
|
|
generated: new Date().toISOString(),
|
|
agents: agents.map(a => a.name),
|
|
detected: {
|
|
languages: [...detectedLangs],
|
|
frameworks: [...detectedFrameworks]
|
|
}
|
|
}, null, 2));
|
|
}
|
|
savedFiles.push(`index.${format}`);
|
|
onProgress?.({ progress: 1.0, message: 'Agent generation complete!' });
|
|
const latency = Date.now() - startTime;
|
|
return {
|
|
success: true,
|
|
focus,
|
|
agentsGenerated: agents.length,
|
|
agents: agents.map(a => a.name),
|
|
detectedLanguages: [...detectedLangs],
|
|
detectedFrameworks: [...detectedFrameworks],
|
|
savedFiles,
|
|
outputDir: output,
|
|
latencyMs: latency,
|
|
timestamp: new Date().toISOString()
|
|
};
|
|
}
|
|
};
|
|
//# sourceMappingURL=build-agents.js.map
|