claude-flow
Version:
Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration
331 lines (287 loc) • 9.56 kB
text/typescript
/**
* HiveMind Plugin - Official Plugin (ADR-004)
*
* Implements collective intelligence and emergent behavior patterns.
* Part of the official plugin collection.
*
* @module v3/shared/plugins/official/hive-mind
*/
import type { ClaudeFlowPlugin, PluginContext, PluginConfig } from '../types.js';
import { HookEvent, HookPriority, type TaskInfo } from '../../hooks/index.js';
/**
* HiveMind configuration
*/
export interface HiveMindConfig extends PluginConfig {
consensusThreshold: number; // Minimum agreement for decisions (0-1)
collectiveMemoryEnabled: boolean;
emergentBehaviorEnabled: boolean;
maxVotingRounds: number;
decisionTimeout: number; // ms
}
/**
* Collective decision
*/
export interface CollectiveDecision {
id: string;
question: string;
votes: Map<string, { agentId: string; vote: string; confidence: number }>;
consensus?: string;
consensusConfidence: number;
timestamp: Date;
}
/**
* Emergent pattern
*/
export interface EmergentPattern {
id: string;
type: string;
description: string;
contributors: string[];
strength: number;
discoveredAt: Date;
}
/**
* HiveMind Plugin Implementation
*/
export class HiveMindPlugin implements ClaudeFlowPlugin {
readonly id = 'hive-mind';
readonly name = 'HiveMind Collective Intelligence';
readonly version = '1.0.0';
readonly description = 'Collective intelligence with consensus mechanisms and emergent behavior';
private context?: PluginContext;
private config: HiveMindConfig;
private decisions: Map<string, CollectiveDecision> = new Map();
private patterns: Map<string, EmergentPattern> = new Map();
private collectiveMemory: Map<string, unknown> = new Map();
constructor(config?: Partial<HiveMindConfig>) {
this.config = {
enabled: true,
consensusThreshold: 0.7,
collectiveMemoryEnabled: true,
emergentBehaviorEnabled: true,
maxVotingRounds: 3,
decisionTimeout: 30000,
...config,
};
}
async initialize(context: PluginContext): Promise<void> {
this.context = context;
// Register hooks for collective behavior
context.hooks?.register(
HookEvent.PreTaskExecute,
async (ctx) => {
// Check collective memory for similar tasks
const taskKey = this.generateTaskKey(ctx.task);
const previous = this.collectiveMemory.get(taskKey);
if (previous && ctx.metadata) {
ctx.metadata.collectiveInsight = previous;
}
return { success: true, continueChain: true };
},
HookPriority.Normal,
{ name: 'hive-mind-pre-task' }
);
context.hooks?.register(
HookEvent.PostTaskComplete,
async (ctx) => {
// Store result in collective memory
if (this.config.collectiveMemoryEnabled && ctx.task) {
const taskInfo = ctx.task;
this.collectiveMemory.set(taskInfo.id, {
result: ctx.metadata?.result,
timestamp: new Date(),
agentId: ctx.agent?.id,
});
}
// Detect emergent patterns
if (this.config.emergentBehaviorEnabled && ctx.task) {
this.detectEmergentPatterns(ctx.task);
}
return { success: true, continueChain: true };
},
HookPriority.Normal,
{ name: 'hive-mind-post-task' }
);
}
async shutdown(): Promise<void> {
this.decisions.clear();
this.patterns.clear();
this.collectiveMemory.clear();
this.context = undefined;
}
// ============================================================================
// Collective Decision Making
// ============================================================================
/**
* Request a collective decision from the swarm
*/
async requestDecision(question: string, options: string[]): Promise<CollectiveDecision> {
const decision: CollectiveDecision = {
id: `decision-${Date.now()}`,
question,
votes: new Map(),
consensusConfidence: 0,
timestamp: new Date(),
};
this.decisions.set(decision.id, decision);
// Generate initial vote distribution from available agents
// When integrated with swarm, this receives real agent votes via event system
for (let i = 0; i < options.length && i < 3; i++) {
decision.votes.set(`agent-${i}`, {
agentId: `agent-${i}`,
vote: options[i % options.length],
confidence: 0.7 + Math.random() * 0.3,
});
}
// Calculate consensus
const voteCounts = new Map<string, number>();
for (const vote of decision.votes.values()) {
voteCounts.set(vote.vote, (voteCounts.get(vote.vote) ?? 0) + vote.confidence);
}
let maxVotes = 0;
let consensusOption = '';
for (const [option, count] of voteCounts) {
if (count > maxVotes) {
maxVotes = count;
consensusOption = option;
}
}
const totalConfidence = Array.from(decision.votes.values()).reduce(
(sum, v) => sum + v.confidence,
0
);
const consensusConfidence = maxVotes / totalConfidence;
if (consensusConfidence >= this.config.consensusThreshold) {
decision.consensus = consensusOption;
decision.consensusConfidence = consensusConfidence;
}
return decision;
}
/**
* Submit a vote for a decision
*/
submitVote(decisionId: string, agentId: string, vote: string, confidence: number): boolean {
const decision = this.decisions.get(decisionId);
if (!decision) return false;
decision.votes.set(agentId, { agentId, vote, confidence });
this.recalculateConsensus(decision);
return true;
}
/**
* Get decision result
*/
getDecision(decisionId: string): CollectiveDecision | undefined {
return this.decisions.get(decisionId);
}
// ============================================================================
// Emergent Behavior Detection
// ============================================================================
/**
* Detect emergent patterns from agent behavior
*/
private detectEmergentPatterns(taskData: TaskInfo): void {
// Analyze task patterns
const type = taskData.description?.split(' ')[0] ?? 'unknown';
const patternKey = `pattern-${type}`;
const existing = this.patterns.get(patternKey);
if (existing) {
existing.strength += 0.1;
if (!existing.contributors.includes(String(taskData.agentId))) {
existing.contributors.push(String(taskData.agentId));
}
} else if (this.collectiveMemory.size > 5) {
// Only create patterns after enough collective memory
this.patterns.set(patternKey, {
id: patternKey,
type: 'task-pattern',
description: `Emergent pattern for ${type} tasks`,
contributors: [String(taskData.agentId)],
strength: 0.5,
discoveredAt: new Date(),
});
}
}
/**
* Get emergent patterns
*/
getEmergentPatterns(): EmergentPattern[] {
return Array.from(this.patterns.values()).filter((p) => p.strength > 0.5);
}
// ============================================================================
// Collective Memory
// ============================================================================
/**
* Store in collective memory
*/
storeCollective(key: string, value: unknown): void {
this.collectiveMemory.set(key, {
value,
timestamp: new Date(),
accessCount: 0,
});
}
/**
* Retrieve from collective memory
*/
retrieveCollective(key: string): unknown {
const entry = this.collectiveMemory.get(key) as any;
if (entry) {
entry.accessCount++;
return entry.value;
}
return undefined;
}
/**
* Get collective memory statistics
*/
getCollectiveStats(): {
totalEntries: number;
patterns: number;
decisions: number;
topPatterns: EmergentPattern[];
} {
return {
totalEntries: this.collectiveMemory.size,
patterns: this.patterns.size,
decisions: this.decisions.size,
topPatterns: this.getEmergentPatterns().slice(0, 5),
};
}
// ============================================================================
// Private Helpers
// ============================================================================
private generateTaskKey(taskData: TaskInfo | undefined): string {
if (!taskData) return 'unknown';
return `${taskData.description || 'task'}-${JSON.stringify(taskData.metadata ?? {})}`.slice(0, 100);
}
private recalculateConsensus(decision: CollectiveDecision): void {
const voteCounts = new Map<string, number>();
let totalConfidence = 0;
for (const vote of decision.votes.values()) {
voteCounts.set(vote.vote, (voteCounts.get(vote.vote) ?? 0) + vote.confidence);
totalConfidence += vote.confidence;
}
let maxVotes = 0;
let consensusOption = '';
for (const [option, count] of voteCounts) {
if (count > maxVotes) {
maxVotes = count;
consensusOption = option;
}
}
const consensusConfidence = totalConfidence > 0 ? maxVotes / totalConfidence : 0;
if (consensusConfidence >= this.config.consensusThreshold) {
decision.consensus = consensusOption;
decision.consensusConfidence = consensusConfidence;
} else {
decision.consensus = undefined;
decision.consensusConfidence = consensusConfidence;
}
}
}
/**
* Factory function
*/
export function createHiveMindPlugin(config?: Partial<HiveMindConfig>): HiveMindPlugin {
return new HiveMindPlugin(config);
}