@claude-flow/swarm 3.0.0-alpha.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (190) hide show
  1. package/.agentic-flow/intelligence.json +16 -0
  2. package/MIGRATION.md +472 -0
  3. package/README.md +634 -0
  4. package/__tests__/consensus.test.ts +577 -0
  5. package/__tests__/coordinator.test.ts +501 -0
  6. package/__tests__/queen-coordinator.test.ts +1335 -0
  7. package/__tests__/topology.test.ts +621 -0
  8. package/dist/agent-pool.d.ts +52 -0
  9. package/dist/agent-pool.d.ts.map +1 -0
  10. package/dist/agent-pool.js +365 -0
  11. package/dist/agent-pool.js.map +1 -0
  12. package/dist/application/commands/create-task.command.d.ts +64 -0
  13. package/dist/application/commands/create-task.command.d.ts.map +1 -0
  14. package/dist/application/commands/create-task.command.js +77 -0
  15. package/dist/application/commands/create-task.command.js.map +1 -0
  16. package/dist/application/commands/spawn-agent.command.d.ts +63 -0
  17. package/dist/application/commands/spawn-agent.command.d.ts.map +1 -0
  18. package/dist/application/commands/spawn-agent.command.js +74 -0
  19. package/dist/application/commands/spawn-agent.command.js.map +1 -0
  20. package/dist/application/index.d.ts +9 -0
  21. package/dist/application/index.d.ts.map +1 -0
  22. package/dist/application/index.js +11 -0
  23. package/dist/application/index.js.map +1 -0
  24. package/dist/application/services/swarm-application-service.d.ts +112 -0
  25. package/dist/application/services/swarm-application-service.d.ts.map +1 -0
  26. package/dist/application/services/swarm-application-service.js +153 -0
  27. package/dist/application/services/swarm-application-service.js.map +1 -0
  28. package/dist/attention-coordinator.d.ts +212 -0
  29. package/dist/attention-coordinator.d.ts.map +1 -0
  30. package/dist/attention-coordinator.js +667 -0
  31. package/dist/attention-coordinator.js.map +1 -0
  32. package/dist/consensus/byzantine.d.ts +63 -0
  33. package/dist/consensus/byzantine.d.ts.map +1 -0
  34. package/dist/consensus/byzantine.js +316 -0
  35. package/dist/consensus/byzantine.js.map +1 -0
  36. package/dist/consensus/gossip.d.ts +69 -0
  37. package/dist/consensus/gossip.d.ts.map +1 -0
  38. package/dist/consensus/gossip.js +378 -0
  39. package/dist/consensus/gossip.js.map +1 -0
  40. package/dist/consensus/index.d.ts +49 -0
  41. package/dist/consensus/index.d.ts.map +1 -0
  42. package/dist/consensus/index.js +203 -0
  43. package/dist/consensus/index.js.map +1 -0
  44. package/dist/consensus/raft.d.ts +62 -0
  45. package/dist/consensus/raft.d.ts.map +1 -0
  46. package/dist/consensus/raft.js +324 -0
  47. package/dist/consensus/raft.js.map +1 -0
  48. package/dist/coordination/agent-registry.d.ts +68 -0
  49. package/dist/coordination/agent-registry.d.ts.map +1 -0
  50. package/dist/coordination/agent-registry.js +412 -0
  51. package/dist/coordination/agent-registry.js.map +1 -0
  52. package/dist/coordination/index.d.ts +8 -0
  53. package/dist/coordination/index.d.ts.map +1 -0
  54. package/dist/coordination/index.js +8 -0
  55. package/dist/coordination/index.js.map +1 -0
  56. package/dist/coordination/swarm-hub.d.ts +150 -0
  57. package/dist/coordination/swarm-hub.d.ts.map +1 -0
  58. package/dist/coordination/swarm-hub.js +617 -0
  59. package/dist/coordination/swarm-hub.js.map +1 -0
  60. package/dist/coordination/task-orchestrator.d.ts +96 -0
  61. package/dist/coordination/task-orchestrator.d.ts.map +1 -0
  62. package/dist/coordination/task-orchestrator.js +412 -0
  63. package/dist/coordination/task-orchestrator.js.map +1 -0
  64. package/dist/domain/entities/agent.d.ts +151 -0
  65. package/dist/domain/entities/agent.d.ts.map +1 -0
  66. package/dist/domain/entities/agent.js +280 -0
  67. package/dist/domain/entities/agent.js.map +1 -0
  68. package/dist/domain/entities/task.d.ts +133 -0
  69. package/dist/domain/entities/task.d.ts.map +1 -0
  70. package/dist/domain/entities/task.js +261 -0
  71. package/dist/domain/entities/task.js.map +1 -0
  72. package/dist/domain/index.d.ts +11 -0
  73. package/dist/domain/index.d.ts.map +1 -0
  74. package/dist/domain/index.js +11 -0
  75. package/dist/domain/index.js.map +1 -0
  76. package/dist/domain/repositories/agent-repository.interface.d.ts +57 -0
  77. package/dist/domain/repositories/agent-repository.interface.d.ts.map +1 -0
  78. package/dist/domain/repositories/agent-repository.interface.js +9 -0
  79. package/dist/domain/repositories/agent-repository.interface.js.map +1 -0
  80. package/dist/domain/repositories/task-repository.interface.d.ts +61 -0
  81. package/dist/domain/repositories/task-repository.interface.d.ts.map +1 -0
  82. package/dist/domain/repositories/task-repository.interface.js +9 -0
  83. package/dist/domain/repositories/task-repository.interface.js.map +1 -0
  84. package/dist/domain/services/coordination-service.d.ts +84 -0
  85. package/dist/domain/services/coordination-service.d.ts.map +1 -0
  86. package/dist/domain/services/coordination-service.js +231 -0
  87. package/dist/domain/services/coordination-service.js.map +1 -0
  88. package/dist/federation-hub.d.ts +284 -0
  89. package/dist/federation-hub.d.ts.map +1 -0
  90. package/dist/federation-hub.js +692 -0
  91. package/dist/federation-hub.js.map +1 -0
  92. package/dist/index.d.ts +107 -0
  93. package/dist/index.d.ts.map +1 -0
  94. package/dist/index.js +142 -0
  95. package/dist/index.js.map +1 -0
  96. package/dist/message-bus.d.ts +48 -0
  97. package/dist/message-bus.d.ts.map +1 -0
  98. package/dist/message-bus.js +499 -0
  99. package/dist/message-bus.js.map +1 -0
  100. package/dist/queen-coordinator.d.ts +576 -0
  101. package/dist/queen-coordinator.d.ts.map +1 -0
  102. package/dist/queen-coordinator.js +1307 -0
  103. package/dist/queen-coordinator.js.map +1 -0
  104. package/dist/shared/events.d.ts +63 -0
  105. package/dist/shared/events.d.ts.map +1 -0
  106. package/dist/shared/events.js +203 -0
  107. package/dist/shared/events.js.map +1 -0
  108. package/dist/shared/types.d.ts +212 -0
  109. package/dist/shared/types.d.ts.map +1 -0
  110. package/dist/shared/types.js +22 -0
  111. package/dist/shared/types.js.map +1 -0
  112. package/dist/topology-manager.d.ts +62 -0
  113. package/dist/topology-manager.d.ts.map +1 -0
  114. package/dist/topology-manager.js +538 -0
  115. package/dist/topology-manager.js.map +1 -0
  116. package/dist/types.d.ts +353 -0
  117. package/dist/types.d.ts.map +1 -0
  118. package/dist/types.js +43 -0
  119. package/dist/types.js.map +1 -0
  120. package/dist/unified-coordinator.d.ts +260 -0
  121. package/dist/unified-coordinator.d.ts.map +1 -0
  122. package/dist/unified-coordinator.js +1460 -0
  123. package/dist/unified-coordinator.js.map +1 -0
  124. package/dist/workers/index.d.ts +29 -0
  125. package/dist/workers/index.d.ts.map +1 -0
  126. package/dist/workers/index.js +49 -0
  127. package/dist/workers/index.js.map +1 -0
  128. package/dist/workers/worker-dispatch.d.ts +234 -0
  129. package/dist/workers/worker-dispatch.d.ts.map +1 -0
  130. package/dist/workers/worker-dispatch.js +842 -0
  131. package/dist/workers/worker-dispatch.js.map +1 -0
  132. package/package.json +33 -0
  133. package/src/agent-pool.ts +476 -0
  134. package/src/application/commands/create-task.command.ts +124 -0
  135. package/src/application/commands/spawn-agent.command.ts +122 -0
  136. package/src/application/index.ts +30 -0
  137. package/src/application/services/swarm-application-service.ts +200 -0
  138. package/src/attention-coordinator.ts +1000 -0
  139. package/src/consensus/byzantine.ts +431 -0
  140. package/src/consensus/gossip.ts +513 -0
  141. package/src/consensus/index.ts +267 -0
  142. package/src/consensus/raft.ts +443 -0
  143. package/src/coordination/agent-registry.ts +544 -0
  144. package/src/coordination/index.ts +23 -0
  145. package/src/coordination/swarm-hub.ts +776 -0
  146. package/src/coordination/task-orchestrator.ts +605 -0
  147. package/src/domain/entities/agent.d.ts +151 -0
  148. package/src/domain/entities/agent.d.ts.map +1 -0
  149. package/src/domain/entities/agent.js +280 -0
  150. package/src/domain/entities/agent.js.map +1 -0
  151. package/src/domain/entities/agent.ts +370 -0
  152. package/src/domain/entities/task.d.ts +133 -0
  153. package/src/domain/entities/task.d.ts.map +1 -0
  154. package/src/domain/entities/task.js +261 -0
  155. package/src/domain/entities/task.js.map +1 -0
  156. package/src/domain/entities/task.ts +319 -0
  157. package/src/domain/index.ts +41 -0
  158. package/src/domain/repositories/agent-repository.interface.d.ts +57 -0
  159. package/src/domain/repositories/agent-repository.interface.d.ts.map +1 -0
  160. package/src/domain/repositories/agent-repository.interface.js +9 -0
  161. package/src/domain/repositories/agent-repository.interface.js.map +1 -0
  162. package/src/domain/repositories/agent-repository.interface.ts +69 -0
  163. package/src/domain/repositories/task-repository.interface.d.ts +61 -0
  164. package/src/domain/repositories/task-repository.interface.d.ts.map +1 -0
  165. package/src/domain/repositories/task-repository.interface.js +9 -0
  166. package/src/domain/repositories/task-repository.interface.js.map +1 -0
  167. package/src/domain/repositories/task-repository.interface.ts +75 -0
  168. package/src/domain/services/coordination-service.ts +320 -0
  169. package/src/federation-hub.d.ts +284 -0
  170. package/src/federation-hub.d.ts.map +1 -0
  171. package/src/federation-hub.js +692 -0
  172. package/src/federation-hub.js.map +1 -0
  173. package/src/federation-hub.ts +979 -0
  174. package/src/index.ts +348 -0
  175. package/src/message-bus.ts +607 -0
  176. package/src/queen-coordinator.ts +2024 -0
  177. package/src/shared/events.ts +285 -0
  178. package/src/shared/types.ts +389 -0
  179. package/src/topology-manager.ts +656 -0
  180. package/src/types.ts +545 -0
  181. package/src/unified-coordinator.ts +1844 -0
  182. package/src/workers/index.ts +65 -0
  183. package/src/workers/worker-dispatch.d.ts +234 -0
  184. package/src/workers/worker-dispatch.d.ts.map +1 -0
  185. package/src/workers/worker-dispatch.js +842 -0
  186. package/src/workers/worker-dispatch.js.map +1 -0
  187. package/src/workers/worker-dispatch.ts +1072 -0
  188. package/tsconfig.json +9 -0
  189. package/tsconfig.tsbuildinfo +1 -0
  190. package/vitest.config.ts +20 -0
@@ -0,0 +1,1460 @@
1
+ /**
2
+ * V3 Unified Swarm Coordinator
3
+ * Consolidates SwarmCoordinator, HiveMind, Maestro, and AgentManager into a single system
4
+ * Supports the 15-agent hierarchical mesh structure with domain-based task routing
5
+ *
6
+ * Performance Targets:
7
+ * - Agent coordination: <100ms for 15 agents
8
+ * - Consensus: <100ms
9
+ * - Message throughput: 1000+ msgs/sec
10
+ *
11
+ * Agent Hierarchy:
12
+ * - Queen (Agent 1): Top-level coordinator
13
+ * - Security Domain (Agents 2-4): security-architect, security-auditor, test-architect
14
+ * - Core Domain (Agents 5-9): core-architect, type-modernization, memory-specialist, swarm-specialist, mcp-optimizer
15
+ * - Integration Domain (Agents 10-12): integration-architect, cli-modernizer, neural-integrator
16
+ * - Support Domain (Agents 13-15): test-architect, performance-engineer, deployment-engineer
17
+ */
18
+ import { EventEmitter } from 'events';
19
+ import { SWARM_CONSTANTS, } from './types.js';
20
+ import { createTopologyManager } from './topology-manager.js';
21
+ import { createMessageBus } from './message-bus.js';
22
+ import { createAgentPool } from './agent-pool.js';
23
+ import { createConsensusEngine } from './consensus/index.js';
24
+ // =============================================================================
25
+ // 15-Agent Domain Configuration
26
+ // =============================================================================
27
+ const DOMAIN_CONFIGS = [
28
+ {
29
+ name: 'queen',
30
+ agentNumbers: [1],
31
+ priority: 0,
32
+ capabilities: ['coordination', 'planning', 'oversight', 'consensus'],
33
+ description: 'Top-level swarm coordination and orchestration',
34
+ },
35
+ {
36
+ name: 'security',
37
+ agentNumbers: [2, 3, 4],
38
+ priority: 1,
39
+ capabilities: ['security-architecture', 'cve-remediation', 'security-testing', 'threat-modeling'],
40
+ description: 'Security architecture, CVE fixes, and security testing',
41
+ },
42
+ {
43
+ name: 'core',
44
+ agentNumbers: [5, 6, 7, 8, 9],
45
+ priority: 2,
46
+ capabilities: ['ddd-design', 'type-modernization', 'memory-unification', 'swarm-coordination', 'mcp-optimization'],
47
+ description: 'Core architecture, DDD, memory unification, and MCP optimization',
48
+ },
49
+ {
50
+ name: 'integration',
51
+ agentNumbers: [10, 11, 12],
52
+ priority: 3,
53
+ capabilities: ['agentic-flow-integration', 'cli-modernization', 'neural-integration', 'hooks-system'],
54
+ description: 'agentic-flow integration, CLI modernization, and neural features',
55
+ },
56
+ {
57
+ name: 'support',
58
+ agentNumbers: [13, 14, 15],
59
+ priority: 4,
60
+ capabilities: ['tdd-testing', 'performance-benchmarking', 'deployment', 'release-management'],
61
+ description: 'Testing, performance optimization, and deployment',
62
+ },
63
+ ];
64
+ export class UnifiedSwarmCoordinator extends EventEmitter {
65
+ config;
66
+ state;
67
+ topologyManager;
68
+ messageBus;
69
+ consensusEngine;
70
+ agentPools = new Map();
71
+ // Domain-based tracking for 15-agent hierarchy
72
+ domainConfigs = new Map();
73
+ domainPools = new Map();
74
+ agentDomainMap = new Map();
75
+ taskAssignments = new Map();
76
+ domainTaskQueues = new Map();
77
+ // Performance tracking
78
+ startTime;
79
+ taskCounter = 0;
80
+ agentCounter = 0;
81
+ coordinationLatencies = [];
82
+ lastMetricsUpdate = new Date();
83
+ // Background intervals
84
+ heartbeatInterval;
85
+ healthCheckInterval;
86
+ metricsInterval;
87
+ constructor(config = {}) {
88
+ super();
89
+ this.config = this.createDefaultConfig(config);
90
+ this.state = this.createInitialState();
91
+ // Initialize components
92
+ this.topologyManager = createTopologyManager(this.config.topology);
93
+ this.messageBus = createMessageBus(this.config.messageBus);
94
+ this.consensusEngine = createConsensusEngine(this.state.id.id, this.config.consensus.algorithm, this.config.consensus);
95
+ // Initialize domain configurations
96
+ this.initializeDomainConfigs();
97
+ this.setupEventForwarding();
98
+ }
99
+ // =============================================================================
100
+ // Domain Configuration Initialization
101
+ // =============================================================================
102
+ initializeDomainConfigs() {
103
+ for (const config of DOMAIN_CONFIGS) {
104
+ this.domainConfigs.set(config.name, config);
105
+ this.domainTaskQueues.set(config.name, []);
106
+ }
107
+ }
108
+ async initialize() {
109
+ if (this.state.status !== 'initializing' && this.state.status !== 'stopped') {
110
+ throw new Error(`Cannot initialize from status: ${this.state.status}`);
111
+ }
112
+ const startTime = performance.now();
113
+ try {
114
+ // Initialize all components in parallel
115
+ await Promise.all([
116
+ this.topologyManager.initialize(this.config.topology),
117
+ this.messageBus.initialize(this.config.messageBus),
118
+ this.consensusEngine.initialize(this.config.consensus),
119
+ ]);
120
+ // Initialize default agent pools
121
+ await this.initializeAgentPools();
122
+ // Start background processes
123
+ this.startBackgroundProcesses();
124
+ this.state.status = 'running';
125
+ this.startTime = new Date();
126
+ this.state.startedAt = this.startTime;
127
+ const duration = performance.now() - startTime;
128
+ this.recordCoordinationLatency(duration);
129
+ this.emitEvent('swarm.initialized', {
130
+ swarmId: this.state.id.id,
131
+ initDurationMs: duration,
132
+ });
133
+ this.emitEvent('swarm.started', {
134
+ swarmId: this.state.id.id,
135
+ topology: this.config.topology.type,
136
+ consensus: this.config.consensus.algorithm,
137
+ });
138
+ }
139
+ catch (error) {
140
+ this.state.status = 'failed';
141
+ throw error;
142
+ }
143
+ }
144
+ async shutdown() {
145
+ if (this.state.status === 'stopped') {
146
+ return;
147
+ }
148
+ this.state.status = 'shutting_down';
149
+ // Stop background processes
150
+ this.stopBackgroundProcesses();
151
+ // Shutdown all components including domain pools
152
+ await Promise.all([
153
+ this.messageBus.shutdown(),
154
+ this.consensusEngine.shutdown(),
155
+ ...Array.from(this.agentPools.values()).map(pool => pool.shutdown()),
156
+ ...Array.from(this.domainPools.values()).map(pool => pool.shutdown()),
157
+ ]);
158
+ // Clear all tracking data
159
+ this.state.agents.clear();
160
+ this.state.tasks.clear();
161
+ this.agentDomainMap.clear();
162
+ this.taskAssignments.clear();
163
+ for (const queue of this.domainTaskQueues.values()) {
164
+ queue.length = 0;
165
+ }
166
+ this.state.status = 'stopped';
167
+ this.emitEvent('swarm.stopped', {
168
+ swarmId: this.state.id.id,
169
+ totalTasks: this.state.metrics.totalTasks,
170
+ completedTasks: this.state.metrics.completedTasks,
171
+ });
172
+ }
173
+ async pause() {
174
+ if (this.state.status !== 'running') {
175
+ return;
176
+ }
177
+ this.state.status = 'paused';
178
+ this.stopBackgroundProcesses();
179
+ this.emitEvent('swarm.paused', { swarmId: this.state.id.id });
180
+ }
181
+ async resume() {
182
+ if (this.state.status !== 'paused') {
183
+ return;
184
+ }
185
+ this.startBackgroundProcesses();
186
+ this.state.status = 'running';
187
+ this.emitEvent('swarm.resumed', { swarmId: this.state.id.id });
188
+ }
189
+ // ===== AGENT MANAGEMENT =====
190
+ async registerAgent(agentData) {
191
+ const startTime = performance.now();
192
+ if (this.state.agents.size >= this.config.maxAgents) {
193
+ throw new Error(`Maximum agents (${this.config.maxAgents}) reached`);
194
+ }
195
+ this.agentCounter++;
196
+ const agentId = {
197
+ id: `agent_${this.state.id.id}_${this.agentCounter}`,
198
+ swarmId: this.state.id.id,
199
+ type: agentData.type,
200
+ instance: this.agentCounter,
201
+ };
202
+ const agent = {
203
+ ...agentData,
204
+ id: agentId,
205
+ lastHeartbeat: new Date(),
206
+ connections: [],
207
+ };
208
+ // Add to state
209
+ this.state.agents.set(agentId.id, agent);
210
+ // Add to topology
211
+ const role = this.determineTopologyRole(agent.type);
212
+ await this.topologyManager.addNode(agentId.id, role);
213
+ // Subscribe to message bus
214
+ this.messageBus.subscribe(agentId.id, (message) => {
215
+ this.handleAgentMessage(agentId.id, message);
216
+ });
217
+ // Add to consensus engine
218
+ this.consensusEngine.addNode(agentId.id);
219
+ const duration = performance.now() - startTime;
220
+ this.recordCoordinationLatency(duration);
221
+ this.emitEvent('agent.joined', {
222
+ agentId: agentId.id,
223
+ type: agent.type,
224
+ registrationDurationMs: duration,
225
+ });
226
+ return agentId.id;
227
+ }
228
+ async unregisterAgent(agentId) {
229
+ const agent = this.state.agents.get(agentId);
230
+ if (!agent) {
231
+ return;
232
+ }
233
+ // Cancel any assigned tasks
234
+ if (agent.currentTask) {
235
+ await this.cancelTask(agent.currentTask.id);
236
+ }
237
+ // Remove from components
238
+ await this.topologyManager.removeNode(agentId);
239
+ this.messageBus.unsubscribe(agentId);
240
+ this.consensusEngine.removeNode(agentId);
241
+ // Remove from state
242
+ this.state.agents.delete(agentId);
243
+ this.emitEvent('agent.left', { agentId });
244
+ }
245
+ getAgent(agentId) {
246
+ return this.state.agents.get(agentId);
247
+ }
248
+ getAllAgents() {
249
+ return Array.from(this.state.agents.values());
250
+ }
251
+ getAgentsByType(type) {
252
+ return this.getAllAgents().filter(a => a.type === type);
253
+ }
254
+ getAvailableAgents() {
255
+ return this.getAllAgents().filter(a => a.status === 'idle');
256
+ }
257
+ // ===== TASK MANAGEMENT =====
258
+ async submitTask(taskData) {
259
+ const startTime = performance.now();
260
+ if (this.state.tasks.size >= this.config.maxTasks) {
261
+ throw new Error(`Maximum tasks (${this.config.maxTasks}) reached`);
262
+ }
263
+ this.taskCounter++;
264
+ const taskId = {
265
+ id: `task_${this.state.id.id}_${this.taskCounter}`,
266
+ swarmId: this.state.id.id,
267
+ sequence: this.taskCounter,
268
+ priority: taskData.priority,
269
+ };
270
+ const task = {
271
+ ...taskData,
272
+ id: taskId,
273
+ status: 'created',
274
+ createdAt: new Date(),
275
+ };
276
+ this.state.tasks.set(taskId.id, task);
277
+ this.state.metrics.totalTasks++;
278
+ // Assign to available agent
279
+ const assignedAgent = await this.assignTask(task);
280
+ const duration = performance.now() - startTime;
281
+ this.recordCoordinationLatency(duration);
282
+ this.emitEvent('task.created', {
283
+ taskId: taskId.id,
284
+ type: task.type,
285
+ priority: task.priority,
286
+ assignedTo: assignedAgent?.id.id,
287
+ assignmentDurationMs: duration,
288
+ });
289
+ return taskId.id;
290
+ }
291
+ async cancelTask(taskId) {
292
+ const task = this.state.tasks.get(taskId);
293
+ if (!task) {
294
+ return;
295
+ }
296
+ // Notify assigned agent
297
+ if (task.assignedTo) {
298
+ await this.messageBus.send({
299
+ type: 'task_fail',
300
+ from: this.state.id.id,
301
+ to: task.assignedTo.id,
302
+ payload: { taskId, reason: 'cancelled' },
303
+ priority: 'high',
304
+ requiresAck: true,
305
+ ttlMs: SWARM_CONSTANTS.DEFAULT_MESSAGE_TTL_MS,
306
+ });
307
+ // Release agent
308
+ const agent = this.state.agents.get(task.assignedTo.id);
309
+ if (agent) {
310
+ agent.status = 'idle';
311
+ agent.currentTask = undefined;
312
+ }
313
+ }
314
+ task.status = 'cancelled';
315
+ this.emitEvent('task.failed', {
316
+ taskId,
317
+ reason: 'cancelled',
318
+ });
319
+ }
320
+ getTask(taskId) {
321
+ return this.state.tasks.get(taskId);
322
+ }
323
+ getAllTasks() {
324
+ return Array.from(this.state.tasks.values());
325
+ }
326
+ getTasksByStatus(status) {
327
+ return this.getAllTasks().filter(t => t.status === status);
328
+ }
329
+ // ===== COORDINATION =====
330
+ async proposeConsensus(value) {
331
+ const startTime = performance.now();
332
+ const proposal = await this.consensusEngine.propose(value, this.state.id.id);
333
+ const result = await this.consensusEngine.awaitConsensus(proposal.id);
334
+ const duration = performance.now() - startTime;
335
+ this.recordCoordinationLatency(duration);
336
+ if (result.approved) {
337
+ this.emitEvent('consensus.achieved', {
338
+ proposalId: proposal.id,
339
+ approvalRate: result.approvalRate,
340
+ durationMs: duration,
341
+ });
342
+ }
343
+ else {
344
+ this.emitEvent('consensus.failed', {
345
+ proposalId: proposal.id,
346
+ approvalRate: result.approvalRate,
347
+ reason: 'threshold_not_met',
348
+ });
349
+ }
350
+ return result;
351
+ }
352
+ async broadcastMessage(payload, priority = 'normal') {
353
+ await this.messageBus.broadcast({
354
+ type: 'broadcast',
355
+ from: this.state.id.id,
356
+ payload,
357
+ priority,
358
+ requiresAck: false,
359
+ ttlMs: SWARM_CONSTANTS.DEFAULT_MESSAGE_TTL_MS,
360
+ });
361
+ }
362
+ // ===== MONITORING =====
363
+ getState() {
364
+ return {
365
+ ...this.state,
366
+ agents: new Map(this.state.agents),
367
+ tasks: new Map(this.state.tasks),
368
+ topology: this.topologyManager.getState(),
369
+ };
370
+ }
371
+ getMetrics() {
372
+ return { ...this.state.metrics };
373
+ }
374
+ getPerformanceReport() {
375
+ const recentLatencies = this.coordinationLatencies.slice(-100);
376
+ const sortedLatencies = [...recentLatencies].sort((a, b) => a - b);
377
+ return {
378
+ timestamp: new Date(),
379
+ window: 60000, // 1 minute
380
+ coordinationLatencyP50: sortedLatencies[Math.floor(sortedLatencies.length * 0.5)] || 0,
381
+ coordinationLatencyP99: sortedLatencies[Math.floor(sortedLatencies.length * 0.99)] || 0,
382
+ messagesPerSecond: this.messageBus.getStats().messagesPerSecond,
383
+ taskThroughput: this.calculateTaskThroughput(),
384
+ agentUtilization: this.calculateAgentUtilization(),
385
+ consensusSuccessRate: this.state.metrics.consensusSuccessRate,
386
+ };
387
+ }
388
+ // ===== PRIVATE METHODS =====
389
+ createDefaultConfig(config) {
390
+ return {
391
+ topology: {
392
+ type: config.topology?.type ?? 'mesh',
393
+ maxAgents: config.topology?.maxAgents ?? SWARM_CONSTANTS.DEFAULT_MAX_AGENTS,
394
+ replicationFactor: config.topology?.replicationFactor ?? 2,
395
+ partitionStrategy: config.topology?.partitionStrategy ?? 'hash',
396
+ failoverEnabled: config.topology?.failoverEnabled ?? true,
397
+ autoRebalance: config.topology?.autoRebalance ?? true,
398
+ },
399
+ consensus: {
400
+ algorithm: config.consensus?.algorithm ?? 'raft',
401
+ threshold: config.consensus?.threshold ?? SWARM_CONSTANTS.DEFAULT_CONSENSUS_THRESHOLD,
402
+ timeoutMs: config.consensus?.timeoutMs ?? SWARM_CONSTANTS.DEFAULT_CONSENSUS_TIMEOUT_MS,
403
+ maxRounds: config.consensus?.maxRounds ?? 10,
404
+ requireQuorum: config.consensus?.requireQuorum ?? true,
405
+ },
406
+ messageBus: {
407
+ maxQueueSize: config.messageBus?.maxQueueSize ?? SWARM_CONSTANTS.MAX_QUEUE_SIZE,
408
+ processingIntervalMs: config.messageBus?.processingIntervalMs ?? 10,
409
+ ackTimeoutMs: config.messageBus?.ackTimeoutMs ?? 5000,
410
+ retryAttempts: config.messageBus?.retryAttempts ?? SWARM_CONSTANTS.MAX_RETRIES,
411
+ enablePersistence: config.messageBus?.enablePersistence ?? false,
412
+ compressionEnabled: config.messageBus?.compressionEnabled ?? false,
413
+ },
414
+ maxAgents: config.maxAgents ?? SWARM_CONSTANTS.DEFAULT_MAX_AGENTS,
415
+ maxTasks: config.maxTasks ?? SWARM_CONSTANTS.DEFAULT_MAX_TASKS,
416
+ heartbeatIntervalMs: config.heartbeatIntervalMs ?? SWARM_CONSTANTS.DEFAULT_HEARTBEAT_INTERVAL_MS,
417
+ healthCheckIntervalMs: config.healthCheckIntervalMs ?? SWARM_CONSTANTS.DEFAULT_HEALTH_CHECK_INTERVAL_MS,
418
+ taskTimeoutMs: config.taskTimeoutMs ?? SWARM_CONSTANTS.DEFAULT_TASK_TIMEOUT_MS,
419
+ autoScaling: config.autoScaling ?? true,
420
+ autoRecovery: config.autoRecovery ?? true,
421
+ };
422
+ }
423
+ createInitialState() {
424
+ const swarmId = {
425
+ id: `swarm_${Date.now()}_${Math.random().toString(36).substr(2, 9)}`,
426
+ namespace: 'default',
427
+ version: '3.0.0',
428
+ createdAt: new Date(),
429
+ };
430
+ return {
431
+ id: swarmId,
432
+ status: 'initializing',
433
+ topology: {
434
+ type: 'mesh',
435
+ nodes: [],
436
+ edges: [],
437
+ partitions: [],
438
+ },
439
+ agents: new Map(),
440
+ tasks: new Map(),
441
+ metrics: {
442
+ uptime: 0,
443
+ activeAgents: 0,
444
+ totalTasks: 0,
445
+ completedTasks: 0,
446
+ failedTasks: 0,
447
+ avgTaskDurationMs: 0,
448
+ messagesPerSecond: 0,
449
+ consensusSuccessRate: 1.0,
450
+ coordinationLatencyMs: 0,
451
+ memoryUsageBytes: 0,
452
+ },
453
+ };
454
+ }
455
+ async initializeAgentPools() {
456
+ // Initialize type-based pools (legacy support)
457
+ const defaultPoolTypes = ['worker', 'coordinator', 'researcher', 'coder'];
458
+ for (const type of defaultPoolTypes) {
459
+ const pool = createAgentPool({
460
+ name: `${type}-pool`,
461
+ type,
462
+ minSize: 0,
463
+ maxSize: Math.floor(this.config.maxAgents / defaultPoolTypes.length),
464
+ scaleUpThreshold: 0.8,
465
+ scaleDownThreshold: 0.2,
466
+ cooldownMs: 30000,
467
+ healthCheckIntervalMs: this.config.healthCheckIntervalMs,
468
+ });
469
+ await pool.initialize();
470
+ this.agentPools.set(type, pool);
471
+ }
472
+ // Initialize domain-based pools for 15-agent hierarchy
473
+ await this.initializeDomainPools();
474
+ }
475
+ async initializeDomainPools() {
476
+ for (const [domain, config] of this.domainConfigs) {
477
+ const agentType = this.domainToAgentType(domain);
478
+ const pool = createAgentPool({
479
+ name: `${domain}-domain-pool`,
480
+ type: agentType,
481
+ minSize: 0,
482
+ maxSize: config.agentNumbers.length,
483
+ scaleUpThreshold: 0.8,
484
+ scaleDownThreshold: 0.2,
485
+ cooldownMs: 30000,
486
+ healthCheckIntervalMs: this.config.healthCheckIntervalMs,
487
+ });
488
+ await pool.initialize();
489
+ this.domainPools.set(domain, pool);
490
+ }
491
+ }
492
+ domainToAgentType(domain) {
493
+ switch (domain) {
494
+ case 'queen':
495
+ return 'queen';
496
+ case 'security':
497
+ return 'specialist';
498
+ case 'core':
499
+ return 'architect';
500
+ case 'integration':
501
+ return 'coder';
502
+ case 'support':
503
+ return 'tester';
504
+ default:
505
+ return 'worker';
506
+ }
507
+ }
508
+ setupEventForwarding() {
509
+ // Forward topology events
510
+ this.topologyManager.on('node.added', (data) => {
511
+ this.emitEvent('topology.updated', { action: 'node_added', ...data });
512
+ });
513
+ this.topologyManager.on('node.removed', (data) => {
514
+ this.emitEvent('topology.updated', { action: 'node_removed', ...data });
515
+ });
516
+ this.topologyManager.on('topology.rebalanced', (data) => {
517
+ this.emitEvent('topology.rebalanced', data);
518
+ });
519
+ // Forward consensus events
520
+ this.consensusEngine.on('consensus.achieved', (data) => {
521
+ this.state.metrics.consensusSuccessRate =
522
+ (this.state.metrics.consensusSuccessRate * 0.9) + (data.approved ? 0.1 : 0);
523
+ });
524
+ // Forward message bus events
525
+ this.messageBus.on('message.delivered', (data) => {
526
+ this.emitEvent('message.received', data);
527
+ });
528
+ }
529
+ startBackgroundProcesses() {
530
+ // Heartbeat monitoring
531
+ this.heartbeatInterval = setInterval(() => {
532
+ this.checkHeartbeats();
533
+ }, this.config.heartbeatIntervalMs);
534
+ // Health checks
535
+ this.healthCheckInterval = setInterval(() => {
536
+ this.performHealthChecks();
537
+ }, this.config.healthCheckIntervalMs);
538
+ // Metrics collection
539
+ this.metricsInterval = setInterval(() => {
540
+ this.updateMetrics();
541
+ }, 1000);
542
+ }
543
+ stopBackgroundProcesses() {
544
+ if (this.heartbeatInterval) {
545
+ clearInterval(this.heartbeatInterval);
546
+ this.heartbeatInterval = undefined;
547
+ }
548
+ if (this.healthCheckInterval) {
549
+ clearInterval(this.healthCheckInterval);
550
+ this.healthCheckInterval = undefined;
551
+ }
552
+ if (this.metricsInterval) {
553
+ clearInterval(this.metricsInterval);
554
+ this.metricsInterval = undefined;
555
+ }
556
+ }
557
+ async assignTask(task) {
558
+ // Find best available agent
559
+ const availableAgents = this.getAvailableAgents();
560
+ if (availableAgents.length === 0) {
561
+ task.status = 'queued';
562
+ return undefined;
563
+ }
564
+ // Score agents based on capabilities and workload
565
+ const scoredAgents = availableAgents.map(agent => ({
566
+ agent,
567
+ score: this.scoreAgentForTask(agent, task),
568
+ })).sort((a, b) => b.score - a.score);
569
+ const bestAgent = scoredAgents[0]?.agent;
570
+ if (!bestAgent) {
571
+ task.status = 'queued';
572
+ return undefined;
573
+ }
574
+ // Assign task
575
+ task.assignedTo = bestAgent.id;
576
+ task.status = 'assigned';
577
+ bestAgent.status = 'busy';
578
+ bestAgent.currentTask = task.id;
579
+ // Notify agent via message bus
580
+ await this.messageBus.send({
581
+ type: 'task_assign',
582
+ from: this.state.id.id,
583
+ to: bestAgent.id.id,
584
+ payload: { task },
585
+ priority: this.mapTaskPriorityToMessagePriority(task.priority),
586
+ requiresAck: true,
587
+ ttlMs: this.config.taskTimeoutMs,
588
+ });
589
+ this.emitEvent('task.assigned', {
590
+ taskId: task.id.id,
591
+ agentId: bestAgent.id.id,
592
+ });
593
+ return bestAgent;
594
+ }
595
+ scoreAgentForTask(agent, task) {
596
+ let score = 100;
597
+ // Type matching
598
+ const typeScores = {
599
+ research: ['researcher'],
600
+ analysis: ['analyst', 'researcher'],
601
+ coding: ['coder'],
602
+ testing: ['tester'],
603
+ review: ['reviewer'],
604
+ documentation: ['documenter'],
605
+ coordination: ['coordinator', 'queen'],
606
+ consensus: ['coordinator', 'queen'],
607
+ custom: ['worker'],
608
+ };
609
+ const preferredTypes = typeScores[task.type] || ['worker'];
610
+ if (preferredTypes.includes(agent.type)) {
611
+ score += 50;
612
+ }
613
+ // Workload adjustment
614
+ score -= agent.workload * 20;
615
+ // Health adjustment
616
+ score *= agent.health;
617
+ // Metrics-based adjustment
618
+ score += agent.metrics.successRate * 10;
619
+ score -= (agent.metrics.averageExecutionTime / 60000) * 5;
620
+ return score;
621
+ }
622
+ mapTaskPriorityToMessagePriority(priority) {
623
+ const mapping = {
624
+ critical: 'urgent',
625
+ high: 'high',
626
+ normal: 'normal',
627
+ low: 'low',
628
+ background: 'low',
629
+ };
630
+ return mapping[priority];
631
+ }
632
+ determineTopologyRole(agentType) {
633
+ switch (agentType) {
634
+ case 'queen':
635
+ return 'queen';
636
+ case 'coordinator':
637
+ return 'coordinator';
638
+ default:
639
+ return this.config.topology.type === 'mesh' ? 'peer' : 'worker';
640
+ }
641
+ }
642
+ handleAgentMessage(agentId, message) {
643
+ const agent = this.state.agents.get(agentId);
644
+ if (!agent)
645
+ return;
646
+ // Update heartbeat
647
+ agent.lastHeartbeat = new Date();
648
+ agent.metrics.messagesProcessed++;
649
+ switch (message.type) {
650
+ case 'task_complete':
651
+ this.handleTaskComplete(agentId, message.payload);
652
+ break;
653
+ case 'task_fail':
654
+ this.handleTaskFail(agentId, message.payload);
655
+ break;
656
+ case 'heartbeat':
657
+ this.handleHeartbeat(agentId, message.payload);
658
+ break;
659
+ case 'status_update':
660
+ this.handleStatusUpdate(agentId, message.payload);
661
+ break;
662
+ }
663
+ }
664
+ handleTaskComplete(agentId, data) {
665
+ const task = this.state.tasks.get(data.taskId);
666
+ const agent = this.state.agents.get(agentId);
667
+ if (task && agent) {
668
+ task.status = 'completed';
669
+ task.output = data.result;
670
+ task.completedAt = new Date();
671
+ agent.status = 'idle';
672
+ agent.currentTask = undefined;
673
+ agent.metrics.tasksCompleted++;
674
+ this.state.metrics.completedTasks++;
675
+ // Update average task duration
676
+ if (task.startedAt) {
677
+ const duration = task.completedAt.getTime() - task.startedAt.getTime();
678
+ this.state.metrics.avgTaskDurationMs =
679
+ (this.state.metrics.avgTaskDurationMs * 0.9) + (duration * 0.1);
680
+ }
681
+ this.emitEvent('task.completed', {
682
+ taskId: data.taskId,
683
+ agentId,
684
+ result: data.result,
685
+ });
686
+ }
687
+ }
688
+ handleTaskFail(agentId, data) {
689
+ const task = this.state.tasks.get(data.taskId);
690
+ const agent = this.state.agents.get(agentId);
691
+ if (task && agent) {
692
+ // Check retry
693
+ if (task.retries < task.maxRetries) {
694
+ task.retries++;
695
+ task.status = 'queued';
696
+ task.assignedTo = undefined;
697
+ agent.currentTask = undefined;
698
+ agent.status = 'idle';
699
+ // Re-assign
700
+ this.assignTask(task);
701
+ }
702
+ else {
703
+ task.status = 'failed';
704
+ agent.status = 'idle';
705
+ agent.currentTask = undefined;
706
+ agent.metrics.tasksFailed++;
707
+ this.state.metrics.failedTasks++;
708
+ this.emitEvent('task.failed', {
709
+ taskId: data.taskId,
710
+ agentId,
711
+ error: data.error,
712
+ });
713
+ }
714
+ }
715
+ }
716
+ handleHeartbeat(agentId, data) {
717
+ const agent = this.state.agents.get(agentId);
718
+ if (agent) {
719
+ agent.lastHeartbeat = new Date();
720
+ if (data.metrics) {
721
+ agent.metrics = { ...agent.metrics, ...data.metrics };
722
+ }
723
+ this.emitEvent('agent.heartbeat', { agentId });
724
+ }
725
+ }
726
+ handleStatusUpdate(agentId, data) {
727
+ const agent = this.state.agents.get(agentId);
728
+ if (agent) {
729
+ if (data.status)
730
+ agent.status = data.status;
731
+ if (data.health !== undefined)
732
+ agent.health = data.health;
733
+ if (data.workload !== undefined)
734
+ agent.workload = data.workload;
735
+ this.emitEvent('agent.status_changed', { agentId, status: agent.status });
736
+ }
737
+ }
738
+ checkHeartbeats() {
739
+ const now = Date.now();
740
+ const timeout = this.config.heartbeatIntervalMs * 3;
741
+ for (const [agentId, agent] of this.state.agents) {
742
+ const timeSinceHeartbeat = now - agent.lastHeartbeat.getTime();
743
+ if (timeSinceHeartbeat > timeout && agent.status !== 'terminated') {
744
+ agent.status = 'error';
745
+ agent.health = Math.max(0, agent.health - 0.2);
746
+ // Auto-recovery
747
+ if (this.config.autoRecovery && agent.health <= 0.2) {
748
+ this.recoverAgent(agentId);
749
+ }
750
+ }
751
+ }
752
+ }
753
+ async recoverAgent(agentId) {
754
+ const agent = this.state.agents.get(agentId);
755
+ if (!agent)
756
+ return;
757
+ // Reassign any tasks
758
+ if (agent.currentTask) {
759
+ const task = this.state.tasks.get(agent.currentTask.id);
760
+ if (task) {
761
+ task.status = 'queued';
762
+ task.assignedTo = undefined;
763
+ await this.assignTask(task);
764
+ }
765
+ }
766
+ // Reset agent
767
+ agent.status = 'idle';
768
+ agent.currentTask = undefined;
769
+ agent.health = 1.0;
770
+ agent.lastHeartbeat = new Date();
771
+ }
772
+ performHealthChecks() {
773
+ const activeAgents = this.getAllAgents().filter(a => a.status === 'idle' || a.status === 'busy');
774
+ this.state.metrics.activeAgents = activeAgents.length;
775
+ // Update topology state
776
+ this.state.topology = this.topologyManager.getState();
777
+ }
778
+ updateMetrics() {
779
+ const now = new Date();
780
+ const uptime = this.startTime
781
+ ? (now.getTime() - this.startTime.getTime()) / 1000
782
+ : 0;
783
+ this.state.metrics.uptime = uptime;
784
+ this.state.metrics.messagesPerSecond = this.messageBus.getStats().messagesPerSecond;
785
+ // Calculate coordination latency
786
+ if (this.coordinationLatencies.length > 0) {
787
+ const recent = this.coordinationLatencies.slice(-50);
788
+ this.state.metrics.coordinationLatencyMs =
789
+ recent.reduce((a, b) => a + b, 0) / recent.length;
790
+ }
791
+ // Memory usage (approximation)
792
+ this.state.metrics.memoryUsageBytes =
793
+ (this.state.agents.size * 2000) +
794
+ (this.state.tasks.size * 1000) +
795
+ (this.messageBus.getQueueDepth() * 500);
796
+ this.lastMetricsUpdate = now;
797
+ }
798
+ recordCoordinationLatency(latencyMs) {
799
+ this.coordinationLatencies.push(latencyMs);
800
+ if (this.coordinationLatencies.length > 1000) {
801
+ this.coordinationLatencies.shift();
802
+ }
803
+ }
804
+ calculateTaskThroughput() {
805
+ if (!this.startTime)
806
+ return 0;
807
+ const uptimeSeconds = (Date.now() - this.startTime.getTime()) / 1000;
808
+ return uptimeSeconds > 0
809
+ ? this.state.metrics.completedTasks / uptimeSeconds
810
+ : 0;
811
+ }
812
+ calculateAgentUtilization() {
813
+ const agents = this.getAllAgents();
814
+ if (agents.length === 0)
815
+ return 0;
816
+ const busyAgents = agents.filter(a => a.status === 'busy').length;
817
+ return busyAgents / agents.length;
818
+ }
819
+ emitEvent(type, data) {
820
+ const event = {
821
+ id: `event_${Date.now()}_${Math.random().toString(36).substr(2, 6)}`,
822
+ type,
823
+ source: this.state.id.id,
824
+ timestamp: new Date(),
825
+ data,
826
+ };
827
+ this.emit(type, event);
828
+ this.emit('event', event);
829
+ }
830
+ // ===== UTILITY METHODS =====
831
+ getTopology() {
832
+ return this.config.topology.type;
833
+ }
834
+ setTopology(type) {
835
+ this.config.topology.type = type;
836
+ }
837
+ getConsensusAlgorithm() {
838
+ return this.config.consensus.algorithm;
839
+ }
840
+ isHealthy() {
841
+ return (this.state.status === 'running' &&
842
+ this.state.metrics.activeAgents > 0 &&
843
+ this.state.metrics.coordinationLatencyMs < SWARM_CONSTANTS.COORDINATION_LATENCY_TARGET_MS * 2);
844
+ }
845
+ getAgentPool(type) {
846
+ return this.agentPools.get(type);
847
+ }
848
+ // =============================================================================
849
+ // DOMAIN-BASED TASK ROUTING (15-Agent Hierarchy Support)
850
+ // =============================================================================
851
+ /**
852
+ * Assign a task to a specific domain
853
+ * Routes the task to the most suitable agent within that domain
854
+ */
855
+ async assignTaskToDomain(taskId, domain) {
856
+ const startTime = performance.now();
857
+ const task = this.state.tasks.get(taskId);
858
+ if (!task) {
859
+ throw new Error(`Task ${taskId} not found`);
860
+ }
861
+ const pool = this.domainPools.get(domain);
862
+ if (!pool) {
863
+ throw new Error(`Domain pool ${domain} not found`);
864
+ }
865
+ // Try to acquire an agent from the domain pool
866
+ const agent = await pool.acquire();
867
+ if (!agent) {
868
+ // Add to domain queue if no agents available
869
+ const queue = this.domainTaskQueues.get(domain) || [];
870
+ queue.push(taskId);
871
+ this.domainTaskQueues.set(domain, queue);
872
+ task.status = 'queued';
873
+ this.emitEvent('task.queued', {
874
+ taskId,
875
+ domain,
876
+ queuePosition: queue.length,
877
+ reason: 'no_available_agents'
878
+ });
879
+ return undefined;
880
+ }
881
+ // Update task
882
+ task.status = 'assigned';
883
+ task.assignedTo = agent.id;
884
+ task.startedAt = new Date();
885
+ // Track assignment
886
+ const assignment = {
887
+ taskId,
888
+ domain,
889
+ agentId: agent.id.id,
890
+ priority: task.priority,
891
+ assignedAt: new Date(),
892
+ };
893
+ this.taskAssignments.set(taskId, assignment);
894
+ // Notify agent via message bus
895
+ await this.messageBus.send({
896
+ type: 'task_assign',
897
+ from: this.state.id.id,
898
+ to: agent.id.id,
899
+ payload: { taskId, task, domain },
900
+ priority: this.mapTaskPriorityToMessagePriority(task.priority),
901
+ requiresAck: true,
902
+ ttlMs: this.config.taskTimeoutMs,
903
+ });
904
+ const duration = performance.now() - startTime;
905
+ this.recordCoordinationLatency(duration);
906
+ this.emitEvent('task.assigned', {
907
+ taskId,
908
+ agentId: agent.id.id,
909
+ domain,
910
+ assignmentDurationMs: duration,
911
+ });
912
+ return agent.id.id;
913
+ }
914
+ /**
915
+ * Get all agents belonging to a specific domain
916
+ */
917
+ getAgentsByDomain(domain) {
918
+ const agents = [];
919
+ for (const [agentId, agentDomain] of this.agentDomainMap) {
920
+ if (agentDomain === domain) {
921
+ const agent = this.state.agents.get(agentId);
922
+ if (agent) {
923
+ agents.push(agent);
924
+ }
925
+ }
926
+ }
927
+ return agents;
928
+ }
929
+ /**
930
+ * Execute multiple tasks in parallel across different domains
931
+ * This is the key method for achieving >85% agent utilization
932
+ */
933
+ async executeParallel(tasks) {
934
+ const startTime = performance.now();
935
+ const executionPromises = [];
936
+ // Submit all tasks first
937
+ const taskIds = [];
938
+ for (const { task, domain } of tasks) {
939
+ const taskId = await this.submitTask(task);
940
+ taskIds.push({ taskId, domain });
941
+ }
942
+ // Execute all tasks in parallel across domains
943
+ for (const { taskId, domain } of taskIds) {
944
+ const promise = this.executeTaskInDomain(taskId, domain);
945
+ executionPromises.push(promise);
946
+ }
947
+ // Wait for all tasks to complete (with individual error handling)
948
+ const settledResults = await Promise.allSettled(executionPromises);
949
+ const results = [];
950
+ for (let i = 0; i < settledResults.length; i++) {
951
+ const result = settledResults[i];
952
+ const { taskId, domain } = taskIds[i];
953
+ if (result.status === 'fulfilled') {
954
+ results.push(result.value);
955
+ }
956
+ else {
957
+ results.push({
958
+ taskId,
959
+ domain,
960
+ success: false,
961
+ error: result.reason instanceof Error ? result.reason : new Error(String(result.reason)),
962
+ durationMs: performance.now() - startTime,
963
+ });
964
+ }
965
+ }
966
+ this.emitEvent('parallel.execution.completed', {
967
+ totalTasks: tasks.length,
968
+ successful: results.filter(r => r.success).length,
969
+ failed: results.filter(r => !r.success).length,
970
+ totalDurationMs: performance.now() - startTime,
971
+ });
972
+ return results;
973
+ }
974
+ async executeTaskInDomain(taskId, domain) {
975
+ const startTime = performance.now();
976
+ try {
977
+ // Assign to domain
978
+ const agentId = await this.assignTaskToDomain(taskId, domain);
979
+ if (!agentId) {
980
+ // Task was queued, wait for it to be assigned and complete
981
+ return await this.waitForQueuedTask(taskId, domain, startTime);
982
+ }
983
+ // Wait for completion
984
+ const result = await this.waitForTaskCompletion(taskId, this.config.taskTimeoutMs);
985
+ return {
986
+ taskId,
987
+ domain,
988
+ success: result.status === 'completed',
989
+ result: result.output,
990
+ durationMs: performance.now() - startTime,
991
+ };
992
+ }
993
+ catch (error) {
994
+ return {
995
+ taskId,
996
+ domain,
997
+ success: false,
998
+ error: error instanceof Error ? error : new Error(String(error)),
999
+ durationMs: performance.now() - startTime,
1000
+ };
1001
+ }
1002
+ }
1003
+ async waitForQueuedTask(taskId, domain, startTime) {
1004
+ return new Promise((resolve) => {
1005
+ const checkInterval = setInterval(() => {
1006
+ const task = this.state.tasks.get(taskId);
1007
+ if (!task) {
1008
+ clearInterval(checkInterval);
1009
+ resolve({
1010
+ taskId,
1011
+ domain,
1012
+ success: false,
1013
+ error: new Error(`Task ${taskId} not found`),
1014
+ durationMs: performance.now() - startTime,
1015
+ });
1016
+ return;
1017
+ }
1018
+ if (task.status === 'completed') {
1019
+ clearInterval(checkInterval);
1020
+ resolve({
1021
+ taskId,
1022
+ domain,
1023
+ success: true,
1024
+ result: task.output,
1025
+ durationMs: performance.now() - startTime,
1026
+ });
1027
+ }
1028
+ else if (task.status === 'failed' || task.status === 'cancelled' || task.status === 'timeout') {
1029
+ clearInterval(checkInterval);
1030
+ resolve({
1031
+ taskId,
1032
+ domain,
1033
+ success: false,
1034
+ error: new Error(`Task ${task.status}`),
1035
+ durationMs: performance.now() - startTime,
1036
+ });
1037
+ }
1038
+ }, 100);
1039
+ // Timeout after configured duration
1040
+ setTimeout(() => {
1041
+ clearInterval(checkInterval);
1042
+ const task = this.state.tasks.get(taskId);
1043
+ if (task && task.status !== 'completed') {
1044
+ task.status = 'timeout';
1045
+ }
1046
+ resolve({
1047
+ taskId,
1048
+ domain,
1049
+ success: false,
1050
+ error: new Error('Task timed out'),
1051
+ durationMs: performance.now() - startTime,
1052
+ });
1053
+ }, this.config.taskTimeoutMs);
1054
+ });
1055
+ }
1056
+ async waitForTaskCompletion(taskId, timeoutMs) {
1057
+ return new Promise((resolve, reject) => {
1058
+ const checkInterval = setInterval(() => {
1059
+ const task = this.state.tasks.get(taskId);
1060
+ if (!task) {
1061
+ clearInterval(checkInterval);
1062
+ reject(new Error(`Task ${taskId} not found`));
1063
+ return;
1064
+ }
1065
+ if (task.status === 'completed' || task.status === 'failed' || task.status === 'cancelled') {
1066
+ clearInterval(checkInterval);
1067
+ resolve(task);
1068
+ }
1069
+ }, 100);
1070
+ setTimeout(() => {
1071
+ clearInterval(checkInterval);
1072
+ const task = this.state.tasks.get(taskId);
1073
+ if (task) {
1074
+ task.status = 'timeout';
1075
+ task.completedAt = new Date();
1076
+ resolve(task);
1077
+ }
1078
+ else {
1079
+ reject(new Error(`Task ${taskId} timed out`));
1080
+ }
1081
+ }, timeoutMs);
1082
+ });
1083
+ }
1084
+ /**
1085
+ * Get the current status of all domains
1086
+ */
1087
+ getStatus() {
1088
+ const domains = [];
1089
+ for (const [domain, config] of this.domainConfigs) {
1090
+ const pool = this.domainPools.get(domain);
1091
+ const stats = pool?.getPoolStats();
1092
+ const queue = this.domainTaskQueues.get(domain) || [];
1093
+ const completedTasks = Array.from(this.taskAssignments.values())
1094
+ .filter(a => a.domain === domain)
1095
+ .map(a => this.state.tasks.get(a.taskId))
1096
+ .filter(t => t?.status === 'completed')
1097
+ .length;
1098
+ domains.push({
1099
+ name: domain,
1100
+ agentCount: stats?.total ?? 0,
1101
+ availableAgents: stats?.available ?? 0,
1102
+ busyAgents: stats?.busy ?? 0,
1103
+ tasksQueued: queue.length,
1104
+ tasksCompleted: completedTasks,
1105
+ });
1106
+ }
1107
+ return {
1108
+ swarmId: this.state.id,
1109
+ status: this.state.status,
1110
+ topology: this.config.topology.type,
1111
+ domains,
1112
+ metrics: this.getMetrics(),
1113
+ };
1114
+ }
1115
+ /**
1116
+ * Register an agent and automatically assign it to the appropriate domain
1117
+ * based on its agent number (1-15)
1118
+ */
1119
+ async registerAgentWithDomain(agentData, agentNumber) {
1120
+ // First register the agent normally
1121
+ const agentId = await this.registerAgent(agentData);
1122
+ // Determine domain based on agent number
1123
+ const domain = this.getAgentDomain(agentNumber);
1124
+ // Add to domain tracking
1125
+ this.agentDomainMap.set(agentId, domain);
1126
+ // Add to domain pool
1127
+ const pool = this.domainPools.get(domain);
1128
+ const agent = this.state.agents.get(agentId);
1129
+ if (pool && agent) {
1130
+ await pool.add(agent);
1131
+ }
1132
+ this.emitEvent('agent.domain_assigned', {
1133
+ agentId,
1134
+ agentNumber,
1135
+ domain,
1136
+ });
1137
+ return { agentId, domain };
1138
+ }
1139
+ /**
1140
+ * Get the domain for a given agent number (1-15)
1141
+ */
1142
+ getAgentDomain(agentNumber) {
1143
+ for (const [domain, config] of this.domainConfigs) {
1144
+ if (config.agentNumbers.includes(agentNumber)) {
1145
+ return domain;
1146
+ }
1147
+ }
1148
+ return 'core'; // Default to core domain
1149
+ }
1150
+ /**
1151
+ * Spawn the full 15-agent hierarchy
1152
+ * Returns a map of agent numbers to their IDs and domains
1153
+ */
1154
+ async spawnFullHierarchy() {
1155
+ const results = new Map();
1156
+ for (const [domain, config] of this.domainConfigs) {
1157
+ for (const agentNumber of config.agentNumbers) {
1158
+ const agentType = this.domainToAgentType(domain);
1159
+ const agentData = {
1160
+ name: `${domain}-agent-${agentNumber}`,
1161
+ type: agentType,
1162
+ status: 'idle',
1163
+ capabilities: this.createDomainCapabilities(domain),
1164
+ metrics: this.createDefaultAgentMetrics(),
1165
+ workload: 0,
1166
+ health: 1.0,
1167
+ lastHeartbeat: new Date(),
1168
+ topologyRole: domain === 'queen' ? 'queen' : 'worker',
1169
+ connections: [],
1170
+ };
1171
+ const result = await this.registerAgentWithDomain(agentData, agentNumber);
1172
+ results.set(agentNumber, result);
1173
+ }
1174
+ }
1175
+ this.emitEvent('hierarchy.spawned', {
1176
+ totalAgents: results.size,
1177
+ domains: Array.from(this.domainConfigs.keys()),
1178
+ });
1179
+ return results;
1180
+ }
1181
+ createDomainCapabilities(domain) {
1182
+ const domainConfig = this.domainConfigs.get(domain);
1183
+ const capabilities = domainConfig?.capabilities || [];
1184
+ return {
1185
+ codeGeneration: domain === 'core' || domain === 'integration',
1186
+ codeReview: domain === 'security' || domain === 'core',
1187
+ testing: domain === 'support' || domain === 'security',
1188
+ documentation: true,
1189
+ research: true,
1190
+ analysis: true,
1191
+ coordination: domain === 'queen',
1192
+ languages: ['typescript', 'javascript', 'python'],
1193
+ frameworks: ['node', 'react', 'vitest'],
1194
+ domains: capabilities,
1195
+ tools: ['git', 'npm', 'editor', 'claude'],
1196
+ maxConcurrentTasks: domain === 'queen' ? 1 : 3,
1197
+ maxMemoryUsage: 512 * 1024 * 1024,
1198
+ maxExecutionTime: SWARM_CONSTANTS.DEFAULT_TASK_TIMEOUT_MS,
1199
+ reliability: 0.95,
1200
+ speed: 1.0,
1201
+ quality: 0.9,
1202
+ };
1203
+ }
1204
+ createDefaultAgentMetrics() {
1205
+ return {
1206
+ tasksCompleted: 0,
1207
+ tasksFailed: 0,
1208
+ averageExecutionTime: 0,
1209
+ successRate: 1.0,
1210
+ cpuUsage: 0,
1211
+ memoryUsage: 0,
1212
+ messagesProcessed: 0,
1213
+ lastActivity: new Date(),
1214
+ responseTime: 0,
1215
+ health: 1.0,
1216
+ };
1217
+ }
1218
+ /**
1219
+ * Get the domain pool for a specific domain
1220
+ */
1221
+ getDomainPool(domain) {
1222
+ return this.domainPools.get(domain);
1223
+ }
1224
+ /**
1225
+ * Get all domain configurations
1226
+ */
1227
+ getDomainConfigs() {
1228
+ return new Map(this.domainConfigs);
1229
+ }
1230
+ /**
1231
+ * Release an agent back to its domain pool after task completion
1232
+ */
1233
+ async releaseAgentToDomain(agentId) {
1234
+ const domain = this.agentDomainMap.get(agentId);
1235
+ if (!domain)
1236
+ return;
1237
+ const pool = this.domainPools.get(domain);
1238
+ if (pool) {
1239
+ await pool.release(agentId);
1240
+ }
1241
+ // Check if there are queued tasks for this domain
1242
+ const queue = this.domainTaskQueues.get(domain) || [];
1243
+ if (queue.length > 0) {
1244
+ const nextTaskId = queue.shift();
1245
+ this.domainTaskQueues.set(domain, queue);
1246
+ await this.assignTaskToDomain(nextTaskId, domain);
1247
+ }
1248
+ }
1249
+ // =============================================================================
1250
+ // MCP-Compatible API Methods (agentic-flow@alpha compatibility)
1251
+ // =============================================================================
1252
+ /**
1253
+ * Spawn a new agent (MCP-compatible alias for registerAgent)
1254
+ * Compatible with agentic-flow@alpha's agent spawn API
1255
+ *
1256
+ * @param options - Agent spawn options
1257
+ * @returns Spawned agent ID and details
1258
+ */
1259
+ async spawnAgent(options) {
1260
+ const startTime = performance.now();
1261
+ // Create agent data from options
1262
+ const agentData = {
1263
+ name: options.name || `${options.type}-agent-${this.agentCounter + 1}`,
1264
+ type: options.type,
1265
+ status: 'idle',
1266
+ capabilities: this.createCapabilitiesFromList(options.capabilities || []),
1267
+ metrics: this.createDefaultAgentMetrics(),
1268
+ workload: 0,
1269
+ health: 1.0,
1270
+ lastHeartbeat: new Date(),
1271
+ topologyRole: options.type === 'queen' ? 'queen' : 'worker',
1272
+ connections: [],
1273
+ };
1274
+ // Determine domain and agent number
1275
+ let domain;
1276
+ let agentId;
1277
+ if (options.agentNumber) {
1278
+ // Use provided agent number to determine domain
1279
+ const result = await this.registerAgentWithDomain(agentData, options.agentNumber);
1280
+ agentId = result.agentId;
1281
+ domain = result.domain;
1282
+ }
1283
+ else if (options.domain) {
1284
+ // Use provided domain, assign next available number in that domain
1285
+ const config = this.domainConfigs.get(options.domain);
1286
+ const existingAgents = Array.from(this.agentDomainMap.entries())
1287
+ .filter(([, d]) => d === options.domain)
1288
+ .length;
1289
+ const nextNumber = config?.agentNumbers[existingAgents] || config?.agentNumbers[0] || 1;
1290
+ const result = await this.registerAgentWithDomain(agentData, nextNumber);
1291
+ agentId = result.agentId;
1292
+ domain = result.domain;
1293
+ }
1294
+ else {
1295
+ // Auto-assign to most appropriate domain based on type
1296
+ domain = this.agentTypeToDomain(options.type);
1297
+ agentId = await this.registerAgent(agentData);
1298
+ this.agentDomainMap.set(agentId, domain);
1299
+ }
1300
+ const duration = performance.now() - startTime;
1301
+ this.emitEvent('agent.joined', {
1302
+ agentId,
1303
+ type: options.type,
1304
+ domain,
1305
+ durationMs: duration,
1306
+ });
1307
+ return {
1308
+ agentId,
1309
+ domain,
1310
+ status: 'idle',
1311
+ spawned: true,
1312
+ };
1313
+ }
1314
+ /**
1315
+ * Terminate an agent (MCP-compatible alias for unregisterAgent)
1316
+ * Compatible with agentic-flow@alpha's agent terminate API
1317
+ *
1318
+ * @param agentId - Agent ID to terminate
1319
+ * @param options - Termination options
1320
+ * @returns Termination result
1321
+ */
1322
+ async terminateAgent(agentId, options) {
1323
+ const agent = this.state.agents.get(agentId);
1324
+ if (!agent) {
1325
+ return {
1326
+ terminated: false,
1327
+ agentId,
1328
+ reason: 'Agent not found',
1329
+ };
1330
+ }
1331
+ // If agent has active tasks and not forcing, wait or reassign
1332
+ let tasksReassigned = 0;
1333
+ if (agent.currentTask && !options?.force) {
1334
+ const gracePeriodMs = options?.gracePeriodMs || 5000;
1335
+ // Wait for grace period or force terminate
1336
+ const task = agent.currentTask;
1337
+ await new Promise(resolve => setTimeout(resolve, gracePeriodMs));
1338
+ // Check if task still running
1339
+ const currentAgent = this.state.agents.get(agentId);
1340
+ if (currentAgent?.currentTask?.id === task.id) {
1341
+ // Reassign the task
1342
+ await this.cancelTask(task.id);
1343
+ tasksReassigned = 1;
1344
+ }
1345
+ }
1346
+ // Remove from domain tracking
1347
+ this.agentDomainMap.delete(agentId);
1348
+ // Unregister the agent
1349
+ await this.unregisterAgent(agentId);
1350
+ this.emitEvent('agent.left', {
1351
+ agentId,
1352
+ reason: options?.reason || 'manual termination',
1353
+ tasksReassigned,
1354
+ });
1355
+ return {
1356
+ terminated: true,
1357
+ agentId,
1358
+ reason: options?.reason || 'manual termination',
1359
+ tasksReassigned,
1360
+ };
1361
+ }
1362
+ /**
1363
+ * Get agent status by ID (MCP-compatible)
1364
+ */
1365
+ async getAgentStatus(agentId) {
1366
+ const agent = this.state.agents.get(agentId);
1367
+ if (!agent) {
1368
+ return { found: false, agentId };
1369
+ }
1370
+ const domain = this.agentDomainMap.get(agentId);
1371
+ return {
1372
+ found: true,
1373
+ agentId,
1374
+ status: agent.status,
1375
+ domain,
1376
+ workload: agent.workload,
1377
+ health: agent.health,
1378
+ currentTask: agent.currentTask?.id,
1379
+ metrics: agent.metrics,
1380
+ };
1381
+ }
1382
+ /**
1383
+ * List all agents with optional filters (MCP-compatible)
1384
+ */
1385
+ listAgents(filters) {
1386
+ let agents = this.getAllAgents();
1387
+ if (filters?.status) {
1388
+ agents = agents.filter(a => a.status === filters.status);
1389
+ }
1390
+ if (filters?.type) {
1391
+ agents = agents.filter(a => a.type === filters.type);
1392
+ }
1393
+ if (filters?.available) {
1394
+ agents = agents.filter(a => a.status === 'idle');
1395
+ }
1396
+ if (filters?.domain) {
1397
+ agents = agents.filter(a => {
1398
+ const domain = this.agentDomainMap.get(a.id.id);
1399
+ return domain === filters.domain;
1400
+ });
1401
+ }
1402
+ return agents.map(a => ({
1403
+ agentId: a.id.id,
1404
+ name: a.name,
1405
+ type: a.type,
1406
+ status: a.status,
1407
+ domain: this.agentDomainMap.get(a.id.id),
1408
+ workload: a.workload,
1409
+ health: a.health,
1410
+ }));
1411
+ }
1412
+ // =============================================================================
1413
+ // Helper Methods for MCP API
1414
+ // =============================================================================
1415
+ createCapabilitiesFromList(capabilities) {
1416
+ return {
1417
+ codeGeneration: capabilities.includes('code-generation'),
1418
+ codeReview: capabilities.includes('code-review'),
1419
+ testing: capabilities.includes('testing'),
1420
+ documentation: capabilities.includes('documentation'),
1421
+ research: capabilities.includes('research'),
1422
+ analysis: capabilities.includes('analysis'),
1423
+ coordination: capabilities.includes('coordination'),
1424
+ languages: ['typescript', 'javascript', 'python'],
1425
+ frameworks: ['node', 'react', 'vitest'],
1426
+ domains: capabilities,
1427
+ tools: ['git', 'npm', 'editor', 'claude'],
1428
+ maxConcurrentTasks: 3,
1429
+ maxMemoryUsage: 512 * 1024 * 1024,
1430
+ maxExecutionTime: SWARM_CONSTANTS.DEFAULT_TASK_TIMEOUT_MS,
1431
+ reliability: 0.95,
1432
+ speed: 1.0,
1433
+ quality: 0.9,
1434
+ };
1435
+ }
1436
+ agentTypeToDomain(type) {
1437
+ const typeMapping = {
1438
+ queen: 'queen',
1439
+ coordinator: 'queen',
1440
+ security: 'security',
1441
+ architect: 'core',
1442
+ coder: 'core',
1443
+ developer: 'core',
1444
+ tester: 'support',
1445
+ reviewer: 'security',
1446
+ researcher: 'integration',
1447
+ analyst: 'core',
1448
+ optimizer: 'support',
1449
+ documenter: 'support',
1450
+ monitor: 'support',
1451
+ specialist: 'core',
1452
+ worker: 'core',
1453
+ };
1454
+ return typeMapping[type] || 'core';
1455
+ }
1456
+ }
1457
+ export function createUnifiedSwarmCoordinator(config) {
1458
+ return new UnifiedSwarmCoordinator(config);
1459
+ }
1460
+ //# sourceMappingURL=unified-coordinator.js.map