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,366 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Circuit breaker pattern for fault tolerance
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import { ILogger } from '../core/logger.ts';
|
|
6
|
+
import { IEventBus } from '../core/event-bus.ts';
|
|
7
|
+
|
|
8
|
+
export interface CircuitBreakerConfig {
|
|
9
|
+
failureThreshold: number; // Number of failures before opening
|
|
10
|
+
successThreshold: number; // Number of successes before closing
|
|
11
|
+
timeout: number; // Time in ms before attempting to close
|
|
12
|
+
halfOpenLimit: number; // Max requests in half-open state
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export enum CircuitState {
|
|
16
|
+
CLOSED = 'closed',
|
|
17
|
+
OPEN = 'open',
|
|
18
|
+
HALF_OPEN = 'half-open',
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export interface CircuitBreakerMetrics {
|
|
22
|
+
state: CircuitState;
|
|
23
|
+
failures: number;
|
|
24
|
+
successes: number;
|
|
25
|
+
lastFailureTime?: Date;
|
|
26
|
+
lastSuccessTime?: Date;
|
|
27
|
+
totalRequests: number;
|
|
28
|
+
rejectedRequests: number;
|
|
29
|
+
halfOpenRequests: number;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Circuit breaker for protecting against cascading failures
|
|
34
|
+
*/
|
|
35
|
+
export class CircuitBreaker {
|
|
36
|
+
private state: CircuitState = CircuitState.CLOSED;
|
|
37
|
+
private failures = 0;
|
|
38
|
+
private successes = 0;
|
|
39
|
+
private lastFailureTime?: Date;
|
|
40
|
+
private lastSuccessTime?: Date;
|
|
41
|
+
private nextAttempt?: Date;
|
|
42
|
+
private halfOpenRequests = 0;
|
|
43
|
+
private totalRequests = 0;
|
|
44
|
+
private rejectedRequests = 0;
|
|
45
|
+
|
|
46
|
+
constructor(
|
|
47
|
+
private name: string,
|
|
48
|
+
private config: CircuitBreakerConfig,
|
|
49
|
+
private logger: ILogger,
|
|
50
|
+
private eventBus?: IEventBus,
|
|
51
|
+
) {}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Execute a function with circuit breaker protection
|
|
55
|
+
*/
|
|
56
|
+
async execute<T>(fn: () => Promise<T>): Promise<T> {
|
|
57
|
+
this.totalRequests++;
|
|
58
|
+
|
|
59
|
+
// Check if we should execute
|
|
60
|
+
if (!this.canExecute()) {
|
|
61
|
+
this.rejectedRequests++;
|
|
62
|
+
const error = new Error(`Circuit breaker '${this.name}' is OPEN`);
|
|
63
|
+
this.logStateChange('Request rejected');
|
|
64
|
+
throw error;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
try {
|
|
68
|
+
// Execute the function
|
|
69
|
+
const result = await fn();
|
|
70
|
+
|
|
71
|
+
// Record success
|
|
72
|
+
this.onSuccess();
|
|
73
|
+
|
|
74
|
+
return result;
|
|
75
|
+
} catch (error) {
|
|
76
|
+
// Record failure
|
|
77
|
+
this.onFailure();
|
|
78
|
+
|
|
79
|
+
throw error;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Check if execution is allowed
|
|
85
|
+
*/
|
|
86
|
+
private canExecute(): boolean {
|
|
87
|
+
switch (this.state) {
|
|
88
|
+
case CircuitState.CLOSED:
|
|
89
|
+
return true;
|
|
90
|
+
|
|
91
|
+
case CircuitState.OPEN:
|
|
92
|
+
// Check if we should transition to half-open
|
|
93
|
+
if (this.nextAttempt && new Date() >= this.nextAttempt) {
|
|
94
|
+
this.transitionTo(CircuitState.HALF_OPEN);
|
|
95
|
+
return true;
|
|
96
|
+
}
|
|
97
|
+
return false;
|
|
98
|
+
|
|
99
|
+
case CircuitState.HALF_OPEN:
|
|
100
|
+
// Allow limited requests in half-open state
|
|
101
|
+
return this.halfOpenRequests < this.config.halfOpenLimit;
|
|
102
|
+
|
|
103
|
+
default:
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Handle successful execution
|
|
110
|
+
*/
|
|
111
|
+
private onSuccess(): void {
|
|
112
|
+
this.lastSuccessTime = new Date();
|
|
113
|
+
|
|
114
|
+
switch (this.state) {
|
|
115
|
+
case CircuitState.CLOSED:
|
|
116
|
+
this.failures = 0; // Reset failure count
|
|
117
|
+
break;
|
|
118
|
+
|
|
119
|
+
case CircuitState.HALF_OPEN:
|
|
120
|
+
this.successes++;
|
|
121
|
+
this.halfOpenRequests++;
|
|
122
|
+
|
|
123
|
+
// Check if we should close the circuit
|
|
124
|
+
if (this.successes >= this.config.successThreshold) {
|
|
125
|
+
this.transitionTo(CircuitState.CLOSED);
|
|
126
|
+
}
|
|
127
|
+
break;
|
|
128
|
+
|
|
129
|
+
case CircuitState.OPEN:
|
|
130
|
+
// Shouldn't happen, but handle gracefully
|
|
131
|
+
this.transitionTo(CircuitState.HALF_OPEN);
|
|
132
|
+
break;
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Handle failed execution
|
|
138
|
+
*/
|
|
139
|
+
private onFailure(): void {
|
|
140
|
+
this.lastFailureTime = new Date();
|
|
141
|
+
|
|
142
|
+
switch (this.state) {
|
|
143
|
+
case CircuitState.CLOSED:
|
|
144
|
+
this.failures++;
|
|
145
|
+
|
|
146
|
+
// Check if we should open the circuit
|
|
147
|
+
if (this.failures >= this.config.failureThreshold) {
|
|
148
|
+
this.transitionTo(CircuitState.OPEN);
|
|
149
|
+
}
|
|
150
|
+
break;
|
|
151
|
+
|
|
152
|
+
case CircuitState.HALF_OPEN:
|
|
153
|
+
// Single failure in half-open state reopens the circuit
|
|
154
|
+
this.transitionTo(CircuitState.OPEN);
|
|
155
|
+
break;
|
|
156
|
+
|
|
157
|
+
case CircuitState.OPEN:
|
|
158
|
+
// Already open, update next attempt time
|
|
159
|
+
this.nextAttempt = new Date(Date.now() + this.config.timeout);
|
|
160
|
+
break;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Transition to a new state
|
|
166
|
+
*/
|
|
167
|
+
private transitionTo(newState: CircuitState): void {
|
|
168
|
+
const oldState = this.state;
|
|
169
|
+
this.state = newState;
|
|
170
|
+
|
|
171
|
+
this.logger.info(`Circuit breaker '${this.name}' state change`, {
|
|
172
|
+
from: oldState,
|
|
173
|
+
to: newState,
|
|
174
|
+
failures: this.failures,
|
|
175
|
+
successes: this.successes,
|
|
176
|
+
});
|
|
177
|
+
|
|
178
|
+
// Reset counters based on new state
|
|
179
|
+
switch (newState) {
|
|
180
|
+
case CircuitState.CLOSED:
|
|
181
|
+
this.failures = 0;
|
|
182
|
+
this.successes = 0;
|
|
183
|
+
this.halfOpenRequests = 0;
|
|
184
|
+
delete this.nextAttempt;
|
|
185
|
+
break;
|
|
186
|
+
|
|
187
|
+
case CircuitState.OPEN:
|
|
188
|
+
this.successes = 0;
|
|
189
|
+
this.halfOpenRequests = 0;
|
|
190
|
+
this.nextAttempt = new Date(Date.now() + this.config.timeout);
|
|
191
|
+
break;
|
|
192
|
+
|
|
193
|
+
case CircuitState.HALF_OPEN:
|
|
194
|
+
this.successes = 0;
|
|
195
|
+
this.failures = 0;
|
|
196
|
+
this.halfOpenRequests = 0;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Emit state change event
|
|
201
|
+
if (this.eventBus) {
|
|
202
|
+
this.eventBus.emit('circuitbreaker:state-change', {
|
|
203
|
+
name: this.name,
|
|
204
|
+
from: oldState,
|
|
205
|
+
to: newState,
|
|
206
|
+
metrics: this.getMetrics(),
|
|
207
|
+
});
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* Force the circuit to a specific state
|
|
213
|
+
*/
|
|
214
|
+
forceState(state: CircuitState): void {
|
|
215
|
+
this.logger.warn(`Forcing circuit breaker '${this.name}' to state`, { state });
|
|
216
|
+
this.transitionTo(state);
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
/**
|
|
220
|
+
* Get current state
|
|
221
|
+
*/
|
|
222
|
+
getState(): CircuitState {
|
|
223
|
+
return this.state;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
/**
|
|
227
|
+
* Get circuit breaker metrics
|
|
228
|
+
*/
|
|
229
|
+
getMetrics(): CircuitBreakerMetrics {
|
|
230
|
+
const metrics: CircuitBreakerMetrics = {
|
|
231
|
+
state: this.state,
|
|
232
|
+
failures: this.failures,
|
|
233
|
+
successes: this.successes,
|
|
234
|
+
totalRequests: this.totalRequests,
|
|
235
|
+
rejectedRequests: this.rejectedRequests,
|
|
236
|
+
halfOpenRequests: this.halfOpenRequests,
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
if (this.lastFailureTime !== undefined) {
|
|
240
|
+
metrics.lastFailureTime = this.lastFailureTime;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
if (this.lastSuccessTime !== undefined) {
|
|
244
|
+
metrics.lastSuccessTime = this.lastSuccessTime;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
return metrics;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
/**
|
|
251
|
+
* Reset the circuit breaker
|
|
252
|
+
*/
|
|
253
|
+
reset(): void {
|
|
254
|
+
this.logger.info(`Resetting circuit breaker '${this.name}'`);
|
|
255
|
+
this.state = CircuitState.CLOSED;
|
|
256
|
+
this.failures = 0;
|
|
257
|
+
this.successes = 0;
|
|
258
|
+
delete this.lastFailureTime;
|
|
259
|
+
delete this.lastSuccessTime;
|
|
260
|
+
delete this.nextAttempt;
|
|
261
|
+
this.halfOpenRequests = 0;
|
|
262
|
+
this.totalRequests = 0;
|
|
263
|
+
this.rejectedRequests = 0;
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Log state change with consistent format
|
|
268
|
+
*/
|
|
269
|
+
private logStateChange(message: string): void {
|
|
270
|
+
this.logger.debug(`Circuit breaker '${this.name}': ${message}`, {
|
|
271
|
+
state: this.state,
|
|
272
|
+
failures: this.failures,
|
|
273
|
+
successes: this.successes,
|
|
274
|
+
nextAttempt: this.nextAttempt,
|
|
275
|
+
});
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Manager for multiple circuit breakers
|
|
281
|
+
*/
|
|
282
|
+
export class CircuitBreakerManager {
|
|
283
|
+
private breakers = new Map<string, CircuitBreaker>();
|
|
284
|
+
|
|
285
|
+
constructor(
|
|
286
|
+
private defaultConfig: CircuitBreakerConfig,
|
|
287
|
+
private logger: ILogger,
|
|
288
|
+
private eventBus?: IEventBus,
|
|
289
|
+
) {}
|
|
290
|
+
|
|
291
|
+
/**
|
|
292
|
+
* Get or create a circuit breaker
|
|
293
|
+
*/
|
|
294
|
+
getBreaker(name: string, config?: Partial<CircuitBreakerConfig>): CircuitBreaker {
|
|
295
|
+
let breaker = this.breakers.get(name);
|
|
296
|
+
|
|
297
|
+
if (!breaker) {
|
|
298
|
+
const finalConfig = { ...this.defaultConfig, ...config };
|
|
299
|
+
breaker = new CircuitBreaker(name, finalConfig, this.logger, this.eventBus);
|
|
300
|
+
this.breakers.set(name, breaker);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
return breaker;
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
/**
|
|
307
|
+
* Execute with circuit breaker
|
|
308
|
+
*/
|
|
309
|
+
async execute<T>(
|
|
310
|
+
name: string,
|
|
311
|
+
fn: () => Promise<T>,
|
|
312
|
+
config?: Partial<CircuitBreakerConfig>,
|
|
313
|
+
): Promise<T> {
|
|
314
|
+
const breaker = this.getBreaker(name, config);
|
|
315
|
+
return breaker.execute(fn);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
/**
|
|
319
|
+
* Get all circuit breakers
|
|
320
|
+
*/
|
|
321
|
+
getAllBreakers(): Map<string, CircuitBreaker> {
|
|
322
|
+
return new Map(this.breakers);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
/**
|
|
326
|
+
* Get metrics for all breakers
|
|
327
|
+
*/
|
|
328
|
+
getAllMetrics(): Record<string, CircuitBreakerMetrics> {
|
|
329
|
+
const metrics: Record<string, CircuitBreakerMetrics> = {};
|
|
330
|
+
|
|
331
|
+
for (const [name, breaker] of this.breakers) {
|
|
332
|
+
metrics[name] = breaker.getMetrics();
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
return metrics;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
/**
|
|
339
|
+
* Reset a specific breaker
|
|
340
|
+
*/
|
|
341
|
+
resetBreaker(name: string): void {
|
|
342
|
+
const breaker = this.breakers.get(name);
|
|
343
|
+
if (breaker) {
|
|
344
|
+
breaker.reset();
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
/**
|
|
349
|
+
* Reset all breakers
|
|
350
|
+
*/
|
|
351
|
+
resetAll(): void {
|
|
352
|
+
for (const breaker of this.breakers.values()) {
|
|
353
|
+
breaker.reset();
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
|
|
357
|
+
/**
|
|
358
|
+
* Force a breaker to a specific state
|
|
359
|
+
*/
|
|
360
|
+
forceState(name: string, state: CircuitState): void {
|
|
361
|
+
const breaker = this.breakers.get(name);
|
|
362
|
+
if (breaker) {
|
|
363
|
+
breaker.forceState(state);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
}
|