UNPKG

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

212 lines 8.42 kB
/** * V3 Consensus Engine Factory * Unified interface for different consensus algorithms */ import { EventEmitter } from 'events'; import { SWARM_CONSTANTS, } from '../types.js'; import { RaftConsensus, createRaftConsensus } from './raft.js'; import { ByzantineConsensus, createByzantineConsensus } from './byzantine.js'; import { GossipConsensus, createGossipConsensus } from './gossip.js'; export { RaftConsensus, ByzantineConsensus, GossipConsensus }; // ADR-095 G2 — pluggable consensus transport. Replaces the implicit // single-process EventEmitter messaging in the consensus protocols. // LocalTransport is the default (matches current behavior); FederationTransport // (separate file, ADR-104 wire) is the multi-host one. export { LocalTransport, LocalTransportRegistry, defaultLocalRegistry, generateNodeKeyPair, signMessage, verifyMessage, canonicalizeForSigning, messageDigest, } from './transport.js'; // ADR-095 G2 — FederationTransport: ConsensusTransport over the federation // plugin's ADR-104 WS wire (agentic-flow/transport/loader). Structural — // swarm doesn't import agentic-flow; the caller passes a transport instance. export { FederationTransport } from './federation-transport.js'; export class ConsensusEngine extends EventEmitter { config; nodeId; implementation; proposals = new Map(); constructor(nodeId, config = {}) { super(); this.nodeId = nodeId; this.config = { algorithm: config.algorithm ?? 'raft', threshold: config.threshold ?? SWARM_CONSTANTS.DEFAULT_CONSENSUS_THRESHOLD, timeoutMs: config.timeoutMs ?? SWARM_CONSTANTS.DEFAULT_CONSENSUS_TIMEOUT_MS, maxRounds: config.maxRounds ?? 10, requireQuorum: config.requireQuorum ?? true, }; } async initialize(config) { if (config) { this.config = { ...this.config, ...config }; } // Create implementation based on algorithm switch (this.config.algorithm) { case 'raft': this.implementation = createRaftConsensus(this.nodeId, { threshold: this.config.threshold, timeoutMs: this.config.timeoutMs, maxRounds: this.config.maxRounds, requireQuorum: this.config.requireQuorum, }); break; case 'byzantine': this.implementation = createByzantineConsensus(this.nodeId, { threshold: this.config.threshold, timeoutMs: this.config.timeoutMs, maxRounds: this.config.maxRounds, requireQuorum: this.config.requireQuorum, }); break; case 'gossip': this.implementation = createGossipConsensus(this.nodeId, { threshold: this.config.threshold, timeoutMs: this.config.timeoutMs, maxRounds: this.config.maxRounds, requireQuorum: this.config.requireQuorum, }); break; case 'paxos': // Fall back to Raft for Paxos (similar guarantees) this.implementation = createRaftConsensus(this.nodeId, { threshold: this.config.threshold, timeoutMs: this.config.timeoutMs, maxRounds: this.config.maxRounds, requireQuorum: this.config.requireQuorum, }); break; default: throw new Error(`Unknown consensus algorithm: ${this.config.algorithm}`); } await this.implementation.initialize(); // Forward events this.implementation.on('consensus.achieved', (data) => { this.emit('consensus.achieved', data); }); this.implementation.on('leader.elected', (data) => { this.emit('leader.elected', data); }); this.emit('initialized', { nodeId: this.nodeId, algorithm: this.config.algorithm }); } async shutdown() { if (this.implementation) { await this.implementation.shutdown(); } this.emit('shutdown'); } addNode(nodeId, options) { if (!this.implementation) { throw new Error('Consensus engine not initialized'); } if (this.implementation instanceof RaftConsensus) { this.implementation.addPeer(nodeId); } else if (this.implementation instanceof ByzantineConsensus) { this.implementation.addNode(nodeId, options?.isPrimary); } else if (this.implementation instanceof GossipConsensus) { this.implementation.addNode(nodeId); } } removeNode(nodeId) { if (!this.implementation) { return; } if (this.implementation instanceof RaftConsensus) { this.implementation.removePeer(nodeId); } else if (this.implementation instanceof ByzantineConsensus) { this.implementation.removeNode(nodeId); } else if (this.implementation instanceof GossipConsensus) { this.implementation.removeNode(nodeId); } } async propose(value, proposerId) { if (!this.implementation) { throw new Error('Consensus engine not initialized'); } const proposal = await this.implementation.propose(value); this.proposals.set(proposal.id, proposal); return proposal; } async vote(proposalId, vote) { if (!this.implementation) { throw new Error('Consensus engine not initialized'); } await this.implementation.vote(proposalId, vote); } getProposal(proposalId) { return this.proposals.get(proposalId); } async awaitConsensus(proposalId) { if (!this.implementation) { throw new Error('Consensus engine not initialized'); } return this.implementation.awaitConsensus(proposalId); } getActiveProposals() { return Array.from(this.proposals.values()).filter(p => p.status === 'pending'); } // Algorithm-specific queries isLeader() { if (this.implementation instanceof RaftConsensus) { return this.implementation.isLeader(); } if (this.implementation instanceof ByzantineConsensus) { return this.implementation.isPrimary(); } return false; // Gossip has no leader } getLeaderId() { if (this.implementation instanceof RaftConsensus) { return this.implementation.getLeaderId(); } return undefined; } getAlgorithm() { return this.config.algorithm; } getConfig() { return { ...this.config }; } // Metrics getStats() { const proposals = Array.from(this.proposals.values()); return { algorithm: this.config.algorithm, totalProposals: proposals.length, pendingProposals: proposals.filter(p => p.status === 'pending').length, acceptedProposals: proposals.filter(p => p.status === 'accepted').length, rejectedProposals: proposals.filter(p => p.status === 'rejected').length, expiredProposals: proposals.filter(p => p.status === 'expired').length, }; } } // Factory function export function createConsensusEngine(nodeId, algorithm = 'raft', config) { return new ConsensusEngine(nodeId, { ...config, algorithm }); } // Helper to select optimal algorithm based on requirements export function selectOptimalAlgorithm(requirements) { const { faultTolerance, consistency, networkScale, latencyPriority } = requirements; // Byzantine fault tolerance required if (faultTolerance === 'byzantine') { return 'byzantine'; } // Eventual consistency acceptable and large scale if (consistency === 'eventual' && networkScale === 'large') { return 'gossip'; } // Low latency priority with medium scale if (latencyPriority === 'high' && networkScale !== 'large') { return 'raft'; } // Strong consistency with small/medium scale if (consistency === 'strong') { return 'raft'; } // Default to Raft return 'raft'; } //# sourceMappingURL=index.js.map