claude-flow 3.59.2 → 3.59.4
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/package.json
CHANGED
|
@@ -369,11 +369,23 @@ if (isHarness) {
|
|
|
369
369
|
const { CLI } = await import('../dist/src/index.js');
|
|
370
370
|
const cli = new CLI();
|
|
371
371
|
cli.run()
|
|
372
|
-
.then(() => {
|
|
373
|
-
// #1552:
|
|
374
|
-
//
|
|
375
|
-
//
|
|
376
|
-
|
|
372
|
+
.then(async () => {
|
|
373
|
+
// #1552: one-shot commands can leave the memory ControllerRegistry's
|
|
374
|
+
// database handles and timers alive. Close them before relying on the
|
|
375
|
+
// event loop to drain.
|
|
376
|
+
//
|
|
377
|
+
// #3226: calling process.exit(0) here used to race that teardown and
|
|
378
|
+
// intermittently abort on Windows with a libuv UV_HANDLE_CLOSING
|
|
379
|
+
// assertion *after* the command had printed a successful result. Set
|
|
380
|
+
// the exit status and let the loop drain instead.
|
|
381
|
+
if (process.exitCode === undefined) process.exitCode = 0;
|
|
382
|
+
try {
|
|
383
|
+
const { shutdownBridge } = await import('../dist/src/memory/memory-bridge.js');
|
|
384
|
+
if (typeof shutdownBridge === 'function') await shutdownBridge();
|
|
385
|
+
} catch {
|
|
386
|
+
// Cleanup is best-effort: it must never turn a successful command into
|
|
387
|
+
// a failure. Commands that do not use memory simply have nothing to do.
|
|
388
|
+
}
|
|
377
389
|
})
|
|
378
390
|
.catch((error) => {
|
|
379
391
|
console.error('Fatal error:', error.message);
|
|
@@ -361,6 +361,24 @@ export const hiveMindTools = [
|
|
|
361
361
|
description: 'Consensus strategy. Default: raft (anti-drift). Use byzantine for f<n/3 fault tolerance.',
|
|
362
362
|
},
|
|
363
363
|
queenId: { type: 'string', description: 'Initial queen agent ID' },
|
|
364
|
+
maxAgents: {
|
|
365
|
+
type: 'number',
|
|
366
|
+
minimum: 1,
|
|
367
|
+
maximum: 1000,
|
|
368
|
+
default: 15,
|
|
369
|
+
description: 'Maximum number of agents the hive may contain (default: 15)',
|
|
370
|
+
},
|
|
371
|
+
memoryBackend: {
|
|
372
|
+
type: 'string',
|
|
373
|
+
enum: ['agentdb', 'sqlite', 'hybrid'],
|
|
374
|
+
default: 'hybrid',
|
|
375
|
+
description: 'Memory backend requested for this hive (default: hybrid)',
|
|
376
|
+
},
|
|
377
|
+
persist: {
|
|
378
|
+
type: 'boolean',
|
|
379
|
+
default: true,
|
|
380
|
+
description: 'Persist hive state to .claude-flow/hive-mind/state.json. Set false for an ephemeral init that writes no durable state.',
|
|
381
|
+
},
|
|
364
382
|
bootstrapSecret: { type: 'string', description: 'Operator secret (RUFLO_HIVE_BOOTSTRAP_SECRET or .claude-flow/hive-mind/bootstrap.secret). Only needed by remote/HTTP callers; local stdio/CLI callers omit it. See ADR-476.' },
|
|
365
383
|
},
|
|
366
384
|
},
|
|
@@ -372,16 +390,32 @@ export const hiveMindTools = [
|
|
|
372
390
|
if (bootstrapError) {
|
|
373
391
|
return { success: false, error: bootstrapError };
|
|
374
392
|
}
|
|
375
|
-
//
|
|
376
|
-
//
|
|
377
|
-
//
|
|
378
|
-
if (
|
|
379
|
-
|
|
393
|
+
// Validate the advertised init contract before creating any durable
|
|
394
|
+
// state (the operator secret is a filesystem write, so it must come
|
|
395
|
+
// after every input check).
|
|
396
|
+
if (input.persist !== undefined && typeof input.persist !== 'boolean') {
|
|
397
|
+
return { success: false, error: 'persist must be a boolean' };
|
|
398
|
+
}
|
|
399
|
+
const persist = input.persist !== false;
|
|
400
|
+
const maxAgents = input.maxAgents === undefined ? 15 : Number(input.maxAgents);
|
|
401
|
+
if (!Number.isInteger(maxAgents) || maxAgents < 1 || maxAgents > 1000) {
|
|
402
|
+
return { success: false, error: 'maxAgents must be an integer between 1 and 1000' };
|
|
403
|
+
}
|
|
404
|
+
const memoryBackend = input.memoryBackend === undefined ? 'hybrid' : String(input.memoryBackend);
|
|
405
|
+
if (memoryBackend !== 'agentdb' && memoryBackend !== 'sqlite' && memoryBackend !== 'hybrid') {
|
|
406
|
+
return { success: false, error: 'memoryBackend must be one of: agentdb, sqlite, hybrid' };
|
|
407
|
+
}
|
|
380
408
|
if (input.queenId) {
|
|
381
409
|
const v = validateIdentifier(input.queenId, 'queenId');
|
|
382
410
|
if (!v.valid)
|
|
383
411
|
return { success: false, error: v.error };
|
|
384
412
|
}
|
|
413
|
+
// Local first init materialises the 0600 operator secret so a later
|
|
414
|
+
// remote/HTTP deployment has something to be told out of band. The
|
|
415
|
+
// value is never returned. An ephemeral init (persist:false) must not
|
|
416
|
+
// write it either.
|
|
417
|
+
if (persist && classifyCaller(context) === 'local')
|
|
418
|
+
ensureBootstrapSecret();
|
|
385
419
|
const state = loadHiveState();
|
|
386
420
|
const hiveId = `hive-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
387
421
|
const queenId = input.queenId || `queen-${Date.now()}`;
|
|
@@ -389,6 +423,9 @@ export const hiveMindTools = [
|
|
|
389
423
|
state.initialized = true;
|
|
390
424
|
state.topology = input.topology || 'mesh';
|
|
391
425
|
state.consensusStrategy = requestedConsensus;
|
|
426
|
+
state.maxAgents = maxAgents;
|
|
427
|
+
state.memoryBackend = memoryBackend;
|
|
428
|
+
state.persist = persist;
|
|
392
429
|
state.createdAt = new Date().toISOString();
|
|
393
430
|
state.queen = {
|
|
394
431
|
agentId: queenId,
|
|
@@ -403,7 +440,8 @@ export const hiveMindTools = [
|
|
|
403
440
|
if (!state.hiveToken) {
|
|
404
441
|
state.hiveToken = randomBytes(32).toString('hex');
|
|
405
442
|
}
|
|
406
|
-
|
|
443
|
+
if (persist)
|
|
444
|
+
saveHiveState(state);
|
|
407
445
|
return {
|
|
408
446
|
success: true,
|
|
409
447
|
hiveId,
|
|
@@ -411,6 +449,7 @@ export const hiveMindTools = [
|
|
|
411
449
|
consensus: state.consensusStrategy,
|
|
412
450
|
queenId,
|
|
413
451
|
status: 'initialized',
|
|
452
|
+
persisted: persist,
|
|
414
453
|
// Deliberately NOT echoing state.hiveToken here (even though this
|
|
415
454
|
// call is itself now bootstrap-secret-gated): the CLI never reads
|
|
416
455
|
// it off this response (it uses getHiveTokenForCli()'s direct
|
|
@@ -419,9 +458,9 @@ export const hiveMindTools = [
|
|
|
419
458
|
config: {
|
|
420
459
|
topology: state.topology,
|
|
421
460
|
consensus: state.consensusStrategy,
|
|
422
|
-
maxAgents
|
|
423
|
-
persist
|
|
424
|
-
memoryBackend
|
|
461
|
+
maxAgents,
|
|
462
|
+
persist,
|
|
463
|
+
memoryBackend,
|
|
425
464
|
},
|
|
426
465
|
createdAt: state.createdAt,
|
|
427
466
|
};
|
|
@@ -468,8 +507,10 @@ export const hiveMindTools = [
|
|
|
468
507
|
hiveId: `hive-${state.createdAt ? new Date(state.createdAt).getTime() : Date.now()}`,
|
|
469
508
|
status: state.initialized ? 'active' : 'offline',
|
|
470
509
|
topology: state.topology,
|
|
471
|
-
// ADR-093 F3: surface the persisted strategy instead of a hardcoded
|
|
472
|
-
|
|
510
|
+
// ADR-093 F3: surface the persisted strategy instead of a hardcoded
|
|
511
|
+
// "byzantine". Init's documented default is raft, so legacy state
|
|
512
|
+
// without the field must not drift to a different protocol.
|
|
513
|
+
consensus: state.consensusStrategy ?? 'raft',
|
|
473
514
|
queen: state.queen ? {
|
|
474
515
|
id: state.queen.agentId,
|
|
475
516
|
agentId: state.queen.agentId,
|
|
@@ -508,6 +549,8 @@ export const hiveMindTools = [
|
|
|
508
549
|
// Additional fields
|
|
509
550
|
id: `hive-${state.createdAt ? new Date(state.createdAt).getTime() : Date.now()}`,
|
|
510
551
|
initialized: state.initialized,
|
|
552
|
+
maxAgents: state.maxAgents ?? 15,
|
|
553
|
+
memoryBackend: state.memoryBackend ?? 'hybrid',
|
|
511
554
|
workerCount: state.workers.length,
|
|
512
555
|
pendingConsensus: state.consensus.pending.length,
|
|
513
556
|
sharedMemoryKeys: Object.keys(state.sharedMemory).length,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.59.
|
|
3
|
+
"version": "3.59.4",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"description": "Ruflo CLI - Enterprise AI agent orchestration with 60+ specialized agents, swarm coordination, MCP server, self-learning hooks, and vector memory for Claude Code",
|
|
6
6
|
"main": "dist/src/index.js",
|