UNPKG

claude-flow-novice

Version:

Claude Flow Novice - Advanced orchestration platform for multi-agent AI workflows with CFN Loop architecture Includes CodeSearch (hybrid SQLite + pgvector), mem0/memgraph specialists, and all CFN skills.

243 lines (242 loc) 8.52 kB
/** * Agent Type Validation and Fallback System * Prevents swarm coordination gaps by validating agent types before spawning */ import { isValidAgentType, resolveLegacyAgentType, getAvailableAgentTypes, searchAgents } from './agent-loader.js'; const CAPABILITY_EXPECTATIONS = { analyst: [ 'code-analysis', 'debugging', 'pattern-detection' ], 'consensus-builder': [ 'consensus-algorithms', 'distributed-decision-making', 'agreement-protocols' ], monitor: [ 'monitoring', 'metrics', 'performance-tracking' ], coordinator: [ 'task-orchestration', 'coordination', 'workflow-management' ], optimizer: [ 'performance-optimization', 'bottleneck-analysis', 'efficiency' ], documenter: [ 'documentation', 'api-docs', 'technical-writing' ], specialist: [ 'domain-expertise', 'specialized-knowledge', 'advanced-analysis' ], architect: [ 'system-design', 'architecture', 'high-level-design' ] }; const FALLBACK_MAPPING = { analyst: 'code-analyzer', 'consensus-builder': 'byzantine-coordinator', monitor: 'performance-benchmarker', coordinator: 'hierarchical-coordinator', optimizer: 'perf-analyzer', documenter: 'api-docs', specialist: 'system-architect', architect: 'system-architect' }; export class AgentValidator { validationCache = new Map(); CACHE_EXPIRY = 300_000; lastCacheUpdate = 0; async validateAgentType(type) { const cacheKey = type.toLowerCase(); // Check cache first if (this.validationCache.has(cacheKey) && this.isCacheValid()) { return this.validationCache.get(cacheKey); } const result = await this.performValidation(type); this.validationCache.set(cacheKey, result); this.lastCacheUpdate = Date.now(); return result; } async performValidation(type) { const originalType = type; const warnings = []; // Direct validation const isDirectlyValid = await isValidAgentType(type); if (isDirectlyValid) { return { isValid: true, resolvedType: type, originalType, fallbackUsed: false, warnings: [] }; } // Legacy mapping const legacyResolved = resolveLegacyAgentType(type); if (legacyResolved !== type) { const isLegacyValid = await isValidAgentType(legacyResolved); if (isLegacyValid) { warnings.push(`Agent type '${type}' is deprecated. Using '${legacyResolved}' instead.`); return { isValid: true, resolvedType: legacyResolved, originalType, fallbackUsed: true, warnings }; } } // Direct fallback mapping const directFallback = FALLBACK_MAPPING[type.toLowerCase()]; if (directFallback) { const isFallbackValid = await isValidAgentType(directFallback); if (isFallbackValid) { warnings.push(`Agent type '${type}' not found. Using '${directFallback}' as fallback.`); return { isValid: true, resolvedType: directFallback, originalType, fallbackUsed: true, warnings }; } } // Capability-based matching const capabilityFallback = await this.findCapabilityBasedFallback(type); if (capabilityFallback) { warnings.push(`Agent type '${type}' not found. Using '${capabilityFallback}' based on capability matching.`); return { isValid: true, resolvedType: capabilityFallback, originalType, fallbackUsed: true, warnings }; } // Fuzzy matching const fuzzyFallback = await this.findFuzzyMatch(type); if (fuzzyFallback) { warnings.push(`Agent type '${type}' not found. Using '${fuzzyFallback}' as closest match.`); return { isValid: true, resolvedType: fuzzyFallback, originalType, fallbackUsed: true, warnings }; } // Ultimate fallback to researcher warnings.push(`Agent type '${type}' not found. Using 'researcher' as default fallback.`); return { isValid: true, resolvedType: 'researcher', originalType, fallbackUsed: true, warnings }; } async findCapabilityBasedFallback(type) { const expectedCapabilities = CAPABILITY_EXPECTATIONS[type.toLowerCase()]; if (!expectedCapabilities) { return null; } for (const capability of expectedCapabilities){ const matchingAgents = await searchAgents(capability); if (matchingAgents.length > 0) { return matchingAgents[0].name; } } return null; } async findFuzzyMatch(type) { const availableTypes = await getAvailableAgentTypes(); const lowerType = type.toLowerCase(); for (const availableType of availableTypes){ const lowerAvailable = availableType.toLowerCase(); if (lowerAvailable.includes(lowerType) || lowerType.includes(lowerAvailable)) { return availableType; } } for (const availableType of availableTypes){ if (this.calculateSimilarity(type, availableType) > 0.6) { return availableType; } } return null; } calculateSimilarity(str1, str2) { // Levenshtein distance implementation const matrix = Array(str2.length + 1).fill(null).map(()=>Array(str1.length + 1).fill(null)); for(let i = 0; i <= str1.length; i++){ matrix[0][i] = i; } for(let j = 0; j <= str2.length; j++){ matrix[j][0] = j; } for(let j = 1; j <= str2.length; j++){ for(let i = 1; i <= str1.length; i++){ const substitutionCost = str1[i - 1] === str2[j - 1] ? 0 : 1; matrix[j][i] = Math.min(matrix[j][i - 1] + 1, matrix[j - 1][i] + 1, matrix[j - 1][i - 1] + substitutionCost); } } const maxLength = Math.max(str1.length, str2.length); return (maxLength - matrix[str2.length][str1.length]) / maxLength; } async getAgentTypeInfo() { const availableTypes = await getAvailableAgentTypes(); const legacyTypes = Object.keys(FALLBACK_MAPPING); const missingTypes = []; for (const legacyType of legacyTypes){ const resolved = resolveLegacyAgentType(legacyType); const isValid = await isValidAgentType(resolved); if (!isValid) { missingTypes.push(legacyType); } } return { available: availableTypes, legacy: legacyTypes, missing: missingTypes }; } async validateAgentTypes(types) { const results = new Map(); const validationPromises = types.map(async (type)=>{ const result = await this.validateAgentType(type); return [ type, result ]; }); const validationResults = await Promise.all(validationPromises); for (const [type, result] of validationResults){ results.set(type, result); } return results; } clearCache() { this.validationCache.clear(); this.lastCacheUpdate = 0; } isCacheValid() { return Date.now() - this.lastCacheUpdate < this.CACHE_EXPIRY; } } export const agentValidator = new AgentValidator(); export const validateAgentType = (type)=>agentValidator.validateAgentType(type); export const validateAgentTypes = (types)=>agentValidator.validateAgentTypes(types); export const getAgentTypeInfo = ()=>agentValidator.getAgentTypeInfo(); export const clearValidationCache = ()=>agentValidator.clearCache(); //# sourceMappingURL=agent-validator.js.map