claude-flow 1.0.0
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.
- package/LICENSE +21 -0
- package/README.md +612 -0
- package/bin/claude-flow +0 -0
- package/bin/claude-flow-simple +0 -0
- package/bin/claude-flow-typecheck +0 -0
- package/deno.json +84 -0
- package/package.json +45 -0
- package/scripts/check-links.ts +274 -0
- package/scripts/check-performance-regression.ts +168 -0
- package/scripts/claude-sparc.sh +562 -0
- package/scripts/coverage-report.ts +692 -0
- package/scripts/demo-task-system.ts +224 -0
- package/scripts/install.js +72 -0
- package/scripts/test-batch-tasks.ts +29 -0
- package/scripts/test-coordination-features.ts +238 -0
- package/scripts/test-mcp.ts +251 -0
- package/scripts/test-runner.ts +571 -0
- package/scripts/validate-examples.ts +288 -0
- package/src/cli/cli-core.ts +273 -0
- package/src/cli/commands/agent.ts +83 -0
- package/src/cli/commands/config.ts +442 -0
- package/src/cli/commands/help.ts +765 -0
- package/src/cli/commands/index.ts +963 -0
- package/src/cli/commands/mcp.ts +191 -0
- package/src/cli/commands/memory.ts +74 -0
- package/src/cli/commands/monitor.ts +403 -0
- package/src/cli/commands/session.ts +595 -0
- package/src/cli/commands/start.ts +156 -0
- package/src/cli/commands/status.ts +345 -0
- package/src/cli/commands/task.ts +79 -0
- package/src/cli/commands/workflow.ts +763 -0
- package/src/cli/completion.ts +553 -0
- package/src/cli/formatter.ts +310 -0
- package/src/cli/index.ts +211 -0
- package/src/cli/main.ts +23 -0
- package/src/cli/repl.ts +1050 -0
- package/src/cli/simple-cli.js +211 -0
- package/src/cli/simple-cli.ts +211 -0
- package/src/coordination/README.md +400 -0
- package/src/coordination/advanced-scheduler.ts +487 -0
- package/src/coordination/circuit-breaker.ts +366 -0
- package/src/coordination/conflict-resolution.ts +490 -0
- package/src/coordination/dependency-graph.ts +475 -0
- package/src/coordination/index.ts +63 -0
- package/src/coordination/manager.ts +460 -0
- package/src/coordination/messaging.ts +290 -0
- package/src/coordination/metrics.ts +585 -0
- package/src/coordination/resources.ts +322 -0
- package/src/coordination/scheduler.ts +390 -0
- package/src/coordination/work-stealing.ts +224 -0
- package/src/core/config.ts +627 -0
- package/src/core/event-bus.ts +186 -0
- package/src/core/json-persistence.ts +183 -0
- package/src/core/logger.ts +262 -0
- package/src/core/orchestrator-fixed.ts +312 -0
- package/src/core/orchestrator.ts +1234 -0
- package/src/core/persistence.ts +276 -0
- package/src/mcp/auth.ts +438 -0
- package/src/mcp/claude-flow-tools.ts +1280 -0
- package/src/mcp/load-balancer.ts +510 -0
- package/src/mcp/router.ts +240 -0
- package/src/mcp/server.ts +548 -0
- package/src/mcp/session-manager.ts +418 -0
- package/src/mcp/tools.ts +180 -0
- package/src/mcp/transports/base.ts +21 -0
- package/src/mcp/transports/http.ts +457 -0
- package/src/mcp/transports/stdio.ts +254 -0
- package/src/memory/backends/base.ts +22 -0
- package/src/memory/backends/markdown.ts +283 -0
- package/src/memory/backends/sqlite.ts +329 -0
- package/src/memory/cache.ts +238 -0
- package/src/memory/indexer.ts +238 -0
- package/src/memory/manager.ts +572 -0
- package/src/terminal/adapters/base.ts +29 -0
- package/src/terminal/adapters/native.ts +504 -0
- package/src/terminal/adapters/vscode.ts +340 -0
- package/src/terminal/manager.ts +308 -0
- package/src/terminal/pool.ts +271 -0
- package/src/terminal/session.ts +250 -0
- package/src/terminal/vscode-bridge.ts +242 -0
- package/src/utils/errors.ts +231 -0
- package/src/utils/helpers.ts +476 -0
- package/src/utils/types.ts +493 -0
|
@@ -0,0 +1,224 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Work stealing algorithm for load balancing between agents
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { Task, AgentProfile } from '../utils/types.ts';
|
|
6
|
+
import { IEventBus } from '../core/event-bus.ts';
|
|
7
|
+
import { ILogger } from '../core/logger.ts';
|
|
8
|
+
|
|
9
|
+
export interface WorkStealingConfig {
|
|
10
|
+
enabled: boolean;
|
|
11
|
+
stealThreshold: number; // Min difference in task count to trigger stealing
|
|
12
|
+
maxStealBatch: number; // Max tasks to steal at once
|
|
13
|
+
stealInterval: number; // How often to check for steal opportunities (ms)
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface AgentWorkload {
|
|
17
|
+
agentId: string;
|
|
18
|
+
taskCount: number;
|
|
19
|
+
avgTaskDuration: number;
|
|
20
|
+
cpuUsage: number;
|
|
21
|
+
memoryUsage: number;
|
|
22
|
+
priority: number;
|
|
23
|
+
capabilities: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Work stealing coordinator for load balancing
|
|
28
|
+
*/
|
|
29
|
+
export class WorkStealingCoordinator {
|
|
30
|
+
private workloads = new Map<string, AgentWorkload>();
|
|
31
|
+
private stealInterval?: ReturnType<typeof setInterval>;
|
|
32
|
+
private taskDurations = new Map<string, number[]>(); // agentId -> task durations
|
|
33
|
+
|
|
34
|
+
constructor(
|
|
35
|
+
private config: WorkStealingConfig,
|
|
36
|
+
private eventBus: IEventBus,
|
|
37
|
+
private logger: ILogger,
|
|
38
|
+
) {}
|
|
39
|
+
|
|
40
|
+
async initialize(): Promise<void> {
|
|
41
|
+
if (!this.config.enabled) {
|
|
42
|
+
this.logger.info('Work stealing is disabled');
|
|
43
|
+
return;
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
this.logger.info('Initializing work stealing coordinator');
|
|
47
|
+
|
|
48
|
+
// Start periodic steal checks
|
|
49
|
+
this.stealInterval = setInterval(
|
|
50
|
+
() => this.checkAndSteal(),
|
|
51
|
+
this.config.stealInterval,
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
async shutdown(): Promise<void> {
|
|
56
|
+
if (this.stealInterval) {
|
|
57
|
+
clearInterval(this.stealInterval);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
this.workloads.clear();
|
|
61
|
+
this.taskDurations.clear();
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
updateAgentWorkload(agentId: string, workload: Partial<AgentWorkload>): void {
|
|
65
|
+
const existing = this.workloads.get(agentId) || {
|
|
66
|
+
agentId,
|
|
67
|
+
taskCount: 0,
|
|
68
|
+
avgTaskDuration: 0,
|
|
69
|
+
cpuUsage: 0,
|
|
70
|
+
memoryUsage: 0,
|
|
71
|
+
priority: 0,
|
|
72
|
+
capabilities: [],
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
this.workloads.set(agentId, { ...existing, ...workload });
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
recordTaskDuration(agentId: string, duration: number): void {
|
|
79
|
+
if (!this.taskDurations.has(agentId)) {
|
|
80
|
+
this.taskDurations.set(agentId, []);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const durations = this.taskDurations.get(agentId)!;
|
|
84
|
+
durations.push(duration);
|
|
85
|
+
|
|
86
|
+
// Keep only last 100 durations
|
|
87
|
+
if (durations.length > 100) {
|
|
88
|
+
durations.shift();
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Update average duration
|
|
92
|
+
const avg = durations.reduce((sum, d) => sum + d, 0) / durations.length;
|
|
93
|
+
this.updateAgentWorkload(agentId, { avgTaskDuration: avg });
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
async checkAndSteal(): Promise<void> {
|
|
97
|
+
const workloads = Array.from(this.workloads.values());
|
|
98
|
+
if (workloads.length < 2) {
|
|
99
|
+
return; // Need at least 2 agents
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
// Sort by task count (ascending)
|
|
103
|
+
workloads.sort((a, b) => a.taskCount - b.taskCount);
|
|
104
|
+
|
|
105
|
+
const minLoaded = workloads[0];
|
|
106
|
+
const maxLoaded = workloads[workloads.length - 1];
|
|
107
|
+
|
|
108
|
+
// Check if stealing is warranted
|
|
109
|
+
const difference = maxLoaded.taskCount - minLoaded.taskCount;
|
|
110
|
+
if (difference < this.config.stealThreshold) {
|
|
111
|
+
return; // Not enough imbalance
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Calculate how many tasks to steal
|
|
115
|
+
const tasksToSteal = Math.min(
|
|
116
|
+
Math.floor(difference / 2),
|
|
117
|
+
this.config.maxStealBatch,
|
|
118
|
+
);
|
|
119
|
+
|
|
120
|
+
this.logger.info('Initiating work stealing', {
|
|
121
|
+
from: maxLoaded.agentId,
|
|
122
|
+
to: minLoaded.agentId,
|
|
123
|
+
tasksToSteal,
|
|
124
|
+
difference,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Emit steal request event
|
|
128
|
+
this.eventBus.emit('workstealing:request', {
|
|
129
|
+
sourceAgent: maxLoaded.agentId,
|
|
130
|
+
targetAgent: minLoaded.agentId,
|
|
131
|
+
taskCount: tasksToSteal,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Find the best agent for a task based on capabilities and load
|
|
137
|
+
*/
|
|
138
|
+
findBestAgent(task: Task, agents: AgentProfile[]): string | null {
|
|
139
|
+
const candidates: Array<{
|
|
140
|
+
agentId: string;
|
|
141
|
+
score: number;
|
|
142
|
+
}> = [];
|
|
143
|
+
|
|
144
|
+
for (const agent of agents) {
|
|
145
|
+
const workload = this.workloads.get(agent.id);
|
|
146
|
+
if (!workload) {
|
|
147
|
+
continue;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Calculate score based on multiple factors
|
|
151
|
+
let score = 100;
|
|
152
|
+
|
|
153
|
+
// Factor 1: Task count (lower is better)
|
|
154
|
+
score -= workload.taskCount * 10;
|
|
155
|
+
|
|
156
|
+
// Factor 2: CPU usage (lower is better)
|
|
157
|
+
score -= workload.cpuUsage * 0.5;
|
|
158
|
+
|
|
159
|
+
// Factor 3: Memory usage (lower is better)
|
|
160
|
+
score -= workload.memoryUsage * 0.3;
|
|
161
|
+
|
|
162
|
+
// Factor 4: Agent priority (higher is better)
|
|
163
|
+
score += agent.priority * 5;
|
|
164
|
+
|
|
165
|
+
// Factor 5: Capability match
|
|
166
|
+
const taskType = task.type;
|
|
167
|
+
if (agent.capabilities.includes(taskType)) {
|
|
168
|
+
score += 20; // Bonus for capability match
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Factor 6: Average task duration (predictive load)
|
|
172
|
+
const predictedLoad = workload.avgTaskDuration * workload.taskCount;
|
|
173
|
+
score -= predictedLoad / 1000; // Convert to seconds
|
|
174
|
+
|
|
175
|
+
candidates.push({ agentId: agent.id, score });
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
if (candidates.length === 0) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// Sort by score (descending) and return best
|
|
183
|
+
candidates.sort((a, b) => b.score - a.score);
|
|
184
|
+
|
|
185
|
+
this.logger.debug('Agent selection scores', {
|
|
186
|
+
taskId: task.id,
|
|
187
|
+
candidates: candidates.slice(0, 5), // Top 5
|
|
188
|
+
});
|
|
189
|
+
|
|
190
|
+
return candidates[0].agentId;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
getWorkloadStats(): Record<string, unknown> {
|
|
194
|
+
const stats: Record<string, unknown> = {
|
|
195
|
+
totalAgents: this.workloads.size,
|
|
196
|
+
workloads: {},
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
let totalTasks = 0;
|
|
200
|
+
let minTasks = Infinity;
|
|
201
|
+
let maxTasks = 0;
|
|
202
|
+
|
|
203
|
+
for (const [agentId, workload] of this.workloads) {
|
|
204
|
+
totalTasks += workload.taskCount;
|
|
205
|
+
minTasks = Math.min(minTasks, workload.taskCount);
|
|
206
|
+
maxTasks = Math.max(maxTasks, workload.taskCount);
|
|
207
|
+
|
|
208
|
+
(stats.workloads as Record<string, unknown>)[agentId] = {
|
|
209
|
+
taskCount: workload.taskCount,
|
|
210
|
+
avgTaskDuration: workload.avgTaskDuration,
|
|
211
|
+
cpuUsage: workload.cpuUsage,
|
|
212
|
+
memoryUsage: workload.memoryUsage,
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
stats.totalTasks = totalTasks;
|
|
217
|
+
stats.avgTasksPerAgent = totalTasks / this.workloads.size;
|
|
218
|
+
stats.minTasks = minTasks === Infinity ? 0 : minTasks;
|
|
219
|
+
stats.maxTasks = maxTasks;
|
|
220
|
+
stats.imbalance = maxTasks - (minTasks === Infinity ? 0 : minTasks);
|
|
221
|
+
|
|
222
|
+
return stats;
|
|
223
|
+
}
|
|
224
|
+
}
|