UNPKG

cortexweaver

Version:

CortexWeaver is a command-line interface (CLI) tool that orchestrates a swarm of specialized AI agents, powered by Claude Code and Gemini CLI, to assist in software development. It transforms a high-level project plan (plan.md) into a series of coordinate

342 lines 14.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.PheromoneManager = void 0; class PheromoneManager { constructor(driver) { this.driver = driver; } async createPheromone(pheromoneData) { this.validatePheromoneData(pheromoneData); // Handle legacy pheromone types with warning if (!['guide_pheromone', 'warn_pheromone', 'guide', 'warn'].includes(pheromoneData.type)) { console.warn(`Using legacy pheromone type: ${pheromoneData.type}. Consider migrating to guide_pheromone or warn_pheromone.`); } // Convert Date objects to ISO strings for Neo4j storage const dbData = { ...pheromoneData, pattern: pheromoneData.pattern ? JSON.stringify(pheromoneData.pattern) : null, decayRate: pheromoneData.decayRate || (pheromoneData.type.includes('warn') ? 0.15 : 0.05), createdAt: pheromoneData.createdAt, expiresAt: pheromoneData.expiresAt || null }; const session = this.driver.session(); try { const labels = pheromoneData.type.includes('_') ? `:${pheromoneData.type}` : ''; const result = await session.run(`CREATE (ph:Pheromone${labels} {id: $id, type: $type, strength: $strength, context: $context, metadata: $metadata, pattern: $pattern, decayRate: $decayRate, createdAt: $createdAt, expiresAt: $expiresAt}) RETURN ph`, dbData); if (result.records.length === 0) { throw new Error('Failed to create pheromone'); } return pheromoneData; // Return original data with Date objects } finally { await session.close(); } } async createGuidePheromone(context, pattern, strength) { const id = `guide_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const pheromoneData = { id, type: 'guide_pheromone', strength, context, pattern, decayRate: 0.05, metadata: { successPattern: true, agentType: pattern.agentType, complexity: pattern.complexity }, createdAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 30 * 24 * 60 * 60 * 1000).toISOString() // 30 days }; return this.createPheromone(pheromoneData); } async createWarnPheromone(context, pattern, strength) { const id = `warn_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`; const pheromoneData = { id, type: 'warn_pheromone', strength, context, pattern, decayRate: 0.15, metadata: { failurePattern: true, agentType: pattern.agentType, complexity: pattern.complexity }, createdAt: new Date().toISOString(), expiresAt: new Date(Date.now() + 14 * 24 * 60 * 60 * 1000).toISOString() // 14 days }; return this.createPheromone(pheromoneData); } async queryPheromones(options) { const session = this.driver.session(); try { let whereClauses = ['ph.expiresAt > $now']; const params = { now: new Date().toISOString() }; if (options.type) { whereClauses.push('ph.type = $type'); params.type = options.type; } if (options.agentType) { whereClauses.push('ph.pattern CONTAINS $agentType'); params.agentType = options.agentType; } if (options.minStrength !== undefined) { whereClauses.push('ph.strength >= $minStrength'); params.minStrength = options.minStrength; } const whereClause = whereClauses.length > 0 ? `WHERE ${whereClauses.join(' AND ')}` : ''; const limit = options.limit ? `LIMIT ${options.limit}` : ''; const query = ` MATCH (ph:Pheromone) ${whereClause} RETURN ph ORDER BY ph.strength DESC ${limit} `; const result = await session.run(query, params); return result.records.map(record => { const properties = record.get('ph').properties; return { ...properties, pattern: properties.pattern ? JSON.parse(properties.pattern) : undefined }; }); } finally { await session.close(); } } async linkPheromoneToTask(pheromoneId, taskId, influence = 'positive') { const session = this.driver.session(); try { await session.run('MATCH (ph:Pheromone {id: $pheromoneId}), (t:Task {id: $taskId}) CREATE (ph)-[r:INFLUENCES {type: $influence, createdAt: $createdAt}]->(t) RETURN r', { pheromoneId, taskId, influence, createdAt: new Date().toISOString() }); } finally { await session.close(); } } async getPheromonesByType(type) { return this.queryPheromones({ type }); } async getContextPheromones(agentType, taskContext, taskComplexity) { const session = this.driver.session(); try { const result = await session.run(` MATCH (ph:Pheromone) WHERE ph.expiresAt > $now AND ( ph.context CONTAINS $taskContext OR ph.metadata.agentType = $agentType OR ph.metadata.complexity = $taskComplexity ) RETURN ph ORDER BY ph.strength DESC LIMIT 20 `, { now: new Date().toISOString(), agentType, taskContext, taskComplexity }); const allPheromones = result.records.map(record => { const properties = record.get('ph').properties; return { ...properties, pattern: properties.pattern ? JSON.parse(properties.pattern) : undefined }; }); // Separate into guides and warnings based on pheromone type const guides = allPheromones.filter(ph => ph.type === 'guide' || ph.type === 'guide_pheromone'); const warnings = allPheromones.filter(ph => ph.type === 'warn' || ph.type === 'warn_pheromone'); return { guides, warnings }; } finally { await session.close(); } } async analyzePatternCorrelations(agentType) { const session = this.driver.session(); try { const whereClause = agentType ? 'WHERE ph.pattern CONTAINS $agentType AND' : 'WHERE'; const params = agentType ? { agentType, now: new Date().toISOString() } : { now: new Date().toISOString() }; const result = await session.run(` MATCH (ph:Pheromone) ${whereClause} ph.expiresAt > $now RETURN ph, ph.pattern as pattern, collect(DISTINCT ph.context) as promptPatterns, count(ph) as frequency, avg(toFloat(ph.strength)) as successRate ORDER BY successRate DESC `, params); return result.records.map(record => { const ph = record.get('ph'); const pattern = record.get('pattern') ? JSON.parse(record.get('pattern')) : {}; const frequency = record.get('frequency').low || record.get('frequency'); const successRate = record.get('successRate'); // Calculate correlation score const correlationScore = successRate * Math.min(frequency / 10, 1); return { pheromoneId: ph.properties.id, correlatedPatterns: [pattern], correlationScore, temporalTrend: 'stable', recommendations: correlationScore > 0.7 ? ['replicate pattern'] : ['review pattern'] }; }); } finally { await session.close(); } } async analyzeTemporalPatterns(agentType, timeWindowMs) { const session = this.driver.session(); try { const result = await session.run(` MATCH (ph:Pheromone) WHERE ph.pattern CONTAINS $agentType AND ph.expiresAt > $now RETURN ph.pattern as pattern, count(ph) as frequency, avg(toFloat(ph.strength)) as successRate, min(ph.createdAt) as startTime, max(ph.createdAt) as endTime ORDER BY successRate DESC `, { agentType, now: new Date().toISOString() }); return result.records.map(record => { const pattern = record.get('pattern') ? JSON.parse(record.get('pattern')) : {}; const frequency = record.get('frequency').low || record.get('frequency'); const successRate = record.get('successRate'); const startTime = record.get('startTime'); const endTime = record.get('endTime'); // Determine evolution trend let evolutionTrend = 'stable'; if (successRate > 0.8) evolutionTrend = 'improving'; else if (successRate < 0.5) evolutionTrend = 'degrading'; return { pattern, frequency, successRate, evolutionTrend, timeframe: { start: startTime, end: endTime } }; }); } finally { await session.close(); } } async getPheromoneAnalysis(agentType) { const session = this.driver.session(); try { const statsResult = await session.run(` MATCH (ph:Pheromone) WHERE ph.expiresAt > $now RETURN count(ph) as totalPheromones, sum(CASE WHEN ph.type CONTAINS 'guide' THEN 1 ELSE 0 END) as guidePheromones, sum(CASE WHEN ph.type CONTAINS 'warn' THEN 1 ELSE 0 END) as warnPheromones, avg(toFloat(ph.strength)) as avgStrength `, { now: new Date().toISOString() }); const stats = statsResult.records[0]; const totalPheromones = stats.get('totalPheromones').low || 0; const guidePheromones = stats.get('guidePheromones').low || 0; const warnPheromones = stats.get('warnPheromones').low || 0; const avgStrength = stats.get('avgStrength') || 0; const [correlations, temporalInsights] = await Promise.all([ this.analyzePatternCorrelations(agentType), this.analyzeTemporalPatterns(agentType) ]); return { totalPheromones, guidePheromones, warnPheromones, avgStrength, correlations, temporalInsights }; } finally { await session.close(); } } async applyPheromoneDecay() { const session = this.driver.session(); try { // Apply decay to active pheromones const updateResult = await session.run(` MATCH (ph:Pheromone) WHERE ph.expiresAt > $now SET ph.strength = ph.strength * (1 - ph.decayRate) RETURN count(ph) as updated `, { now: new Date().toISOString() }); // Remove expired or very weak pheromones const expireResult = await session.run(` MATCH (ph:Pheromone) WHERE ph.expiresAt <= $now OR ph.strength <= 0.1 DETACH DELETE ph RETURN count(ph) as expired `, { now: new Date().toISOString() }); return { updated: updateResult.records[0]?.get('updated').low || 0, expired: expireResult.records[0]?.get('expired').low || 0 }; } finally { await session.close(); } } async cleanExpiredPheromones() { const session = this.driver.session(); try { const result = await session.run('MATCH (ph:Pheromone) WHERE ph.expiresAt <= $now DETACH DELETE ph', { now: new Date().toISOString() }); return result.summary.counters.updates().nodesDeleted; } finally { await session.close(); } } validatePheromoneData(data) { this.validateRequiredFields(data, ['id', 'type', 'strength', 'context', 'metadata', 'createdAt'], 'pheromone'); if (data.strength < 0 || data.strength > 1) { throw new Error('Pheromone strength must be between 0 and 1'); } // Validate pattern if present if (data.pattern) { const pattern = data.pattern; if (!['success', 'failure', 'partial'].includes(pattern.taskOutcome)) { throw new Error('Invalid task outcome'); } } // Validate that createdAt is a valid ISO string or Date object if (typeof data.createdAt === 'string') { if (isNaN(Date.parse(data.createdAt))) { throw new Error('Pheromone createdAt must be a valid ISO date string'); } } else if (!(data.createdAt instanceof Date)) { throw new Error('Pheromone createdAt must be a Date object or ISO date string'); } // Validate that expiresAt is a valid ISO string or Date object if provided if (data.expiresAt !== undefined) { if (typeof data.expiresAt === 'string') { if (isNaN(Date.parse(data.expiresAt))) { throw new Error('Pheromone expiresAt must be a valid ISO date string'); } } else if (!(data.expiresAt instanceof Date)) { throw new Error('Pheromone expiresAt must be a Date object or ISO date string if provided'); } } } validateRequiredFields(data, fields, type) { if (!fields.every(field => data[field] !== undefined && data[field] !== null)) { throw new Error(`Missing required ${type} fields: ${fields.join(', ')}`); } } } exports.PheromoneManager = PheromoneManager; //# sourceMappingURL=pheromone-manager.js.map