claude-flow 3.5.81 → 3.5.83
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 +1 -1
- package/v3/@claude-flow/cli/dist/src/commands/daemon.js +59 -5
- package/v3/@claude-flow/cli/dist/src/commands/hooks.js +3 -3
- package/v3/@claude-flow/cli/dist/src/commands/init.js +5 -5
- package/v3/@claude-flow/cli/dist/src/commands/swarm.js +101 -4
- package/v3/@claude-flow/cli/dist/src/init/claudemd-generator.js +21 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/agent-tools.js +11 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/guidance-tools.js +1 -1
- package/v3/@claude-flow/cli/dist/src/mcp-tools/hooks-tools.js +43 -23
- package/v3/@claude-flow/cli/dist/src/mcp-tools/neural-tools.js +3 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/swarm-tools.js +10 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/system-tools.js +5 -3
- package/v3/@claude-flow/cli/dist/src/mcp-tools/task-tools.js +8 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/types.js +5 -1
- package/v3/@claude-flow/cli/dist/src/memory/memory-bridge.js +3 -1
- package/v3/@claude-flow/cli/dist/src/services/event-stream.d.ts +25 -0
- package/v3/@claude-flow/cli/dist/src/services/event-stream.js +27 -0
- package/v3/@claude-flow/cli/dist/src/services/index.d.ts +3 -0
- package/v3/@claude-flow/cli/dist/src/services/index.js +6 -0
- package/v3/@claude-flow/cli/dist/src/services/loop-worker-runner.d.ts +16 -0
- package/v3/@claude-flow/cli/dist/src/services/loop-worker-runner.js +34 -0
- package/v3/@claude-flow/cli/dist/src/services/runtime-capabilities.d.ts +22 -0
- package/v3/@claude-flow/cli/dist/src/services/runtime-capabilities.js +45 -0
- package/v3/@claude-flow/cli/dist/src/services/worker-daemon.js +4 -2
- package/v3/@claude-flow/cli/package.json +1 -1
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "claude-flow",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.83",
|
|
4
4
|
"description": "Ruflo - Enterprise AI agent orchestration for Claude Code. Deploy 60+ specialized agents in coordinated swarms with self-learning, fault-tolerant consensus, vector memory, and MCP integration",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"type": "module",
|
|
@@ -64,6 +64,15 @@ const startCommand = {
|
|
|
64
64
|
config.resourceThresholds = thresholds;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
67
|
+
// Detect Claude Code runtime — suggest native alternatives
|
|
68
|
+
if (!isDaemonProcess && (process.env.CLAUDE_CODE || !process.stdin.isTTY)) {
|
|
69
|
+
if (!quiet) {
|
|
70
|
+
output.printInfo('[NATIVE_AVAILABLE] Running inside Claude Code. Consider using:');
|
|
71
|
+
output.writeln(' /loop "Run workers" — for in-session periodic execution');
|
|
72
|
+
output.writeln(' CronCreate — for persistent background workers');
|
|
73
|
+
output.writeln(' Proceeding with daemon start as fallback...');
|
|
74
|
+
}
|
|
75
|
+
}
|
|
67
76
|
// Check if background daemon already running (skip if we ARE the daemon process)
|
|
68
77
|
if (!isDaemonProcess) {
|
|
69
78
|
const bgPid = getBackgroundDaemonPid(projectRoot);
|
|
@@ -628,6 +637,49 @@ const enableCommand = {
|
|
|
628
637
|
}
|
|
629
638
|
},
|
|
630
639
|
};
|
|
640
|
+
// Schedule subcommand - suggest native Claude Code alternatives for persistent scheduling
|
|
641
|
+
const scheduleCommand = {
|
|
642
|
+
name: 'schedule',
|
|
643
|
+
description: 'Schedule a worker for periodic execution (suggests native Claude Code primitives)',
|
|
644
|
+
options: [
|
|
645
|
+
{ name: 'worker', short: 'w', type: 'string', description: 'Worker type to schedule', required: true },
|
|
646
|
+
{ name: 'interval', short: 'i', type: 'string', description: 'Interval in minutes (e.g. 15)', required: true },
|
|
647
|
+
],
|
|
648
|
+
examples: [
|
|
649
|
+
{ command: 'claude-flow daemon schedule -w audit -i 30', description: 'Schedule audit worker every 30 minutes' },
|
|
650
|
+
{ command: 'claude-flow daemon schedule -w map -i 5', description: 'Schedule map worker every 5 minutes' },
|
|
651
|
+
],
|
|
652
|
+
action: async (ctx) => {
|
|
653
|
+
const worker = ctx.flags.worker;
|
|
654
|
+
const intervalStr = ctx.flags.interval;
|
|
655
|
+
if (!worker) {
|
|
656
|
+
output.printError('Worker type is required. Use --worker or -w flag.');
|
|
657
|
+
return { success: false, exitCode: 1 };
|
|
658
|
+
}
|
|
659
|
+
if (!intervalStr) {
|
|
660
|
+
output.printError('Interval is required. Use --interval or -i flag.');
|
|
661
|
+
return { success: false, exitCode: 1 };
|
|
662
|
+
}
|
|
663
|
+
const minutes = parseInt(intervalStr, 10);
|
|
664
|
+
if (isNaN(minutes) || minutes < 1 || minutes > 1440) {
|
|
665
|
+
output.printError('Interval must be a number between 1 and 1440 (minutes).');
|
|
666
|
+
return { success: false, exitCode: 1 };
|
|
667
|
+
}
|
|
668
|
+
// Convert minutes to cron expression
|
|
669
|
+
const cronExpr = minutes < 60
|
|
670
|
+
? `*/${minutes} * * * *`
|
|
671
|
+
: `0 */${Math.floor(minutes / 60)} * * *`;
|
|
672
|
+
output.writeln();
|
|
673
|
+
output.printBox([
|
|
674
|
+
`[CRON_SUGGESTION] To schedule this worker persistently:`,
|
|
675
|
+
`CronCreate("${worker}-worker", "${cronExpr}", "Run npx @claude-flow/cli hooks worker dispatch --trigger ${worker}")`,
|
|
676
|
+
``,
|
|
677
|
+
`For in-session periodic execution, use:`,
|
|
678
|
+
`/loop "Run ${worker} worker" (auto-paced with cache-aware delays)`,
|
|
679
|
+
].join('\n'), 'Schedule Worker');
|
|
680
|
+
return { success: true };
|
|
681
|
+
},
|
|
682
|
+
};
|
|
631
683
|
// Helper functions for time formatting
|
|
632
684
|
function formatTimeAgo(date) {
|
|
633
685
|
const seconds = Math.floor((Date.now() - date.getTime()) / 1000);
|
|
@@ -661,6 +713,7 @@ export const daemonCommand = {
|
|
|
661
713
|
statusCommand,
|
|
662
714
|
triggerCommand,
|
|
663
715
|
enableCommand,
|
|
716
|
+
scheduleCommand,
|
|
664
717
|
],
|
|
665
718
|
options: [],
|
|
666
719
|
examples: [
|
|
@@ -699,11 +752,12 @@ export const daemonCommand = {
|
|
|
699
752
|
output.writeln();
|
|
700
753
|
output.writeln(output.bold('Subcommands'));
|
|
701
754
|
output.printList([
|
|
702
|
-
`${output.highlight('start')}
|
|
703
|
-
`${output.highlight('stop')}
|
|
704
|
-
`${output.highlight('status')}
|
|
705
|
-
`${output.highlight('trigger')}
|
|
706
|
-
`${output.highlight('enable')}
|
|
755
|
+
`${output.highlight('start')} - Start the daemon`,
|
|
756
|
+
`${output.highlight('stop')} - Stop the daemon`,
|
|
757
|
+
`${output.highlight('status')} - Show daemon status`,
|
|
758
|
+
`${output.highlight('trigger')} - Manually run a worker`,
|
|
759
|
+
`${output.highlight('enable')} - Enable/disable a worker`,
|
|
760
|
+
`${output.highlight('schedule')} - Schedule periodic worker execution`,
|
|
707
761
|
]);
|
|
708
762
|
output.writeln();
|
|
709
763
|
output.writeln('Run "claude-flow daemon <subcommand> --help" for details');
|
|
@@ -3365,14 +3365,14 @@ const statuslineCommand = {
|
|
|
3365
3365
|
const isWindows = process.platform === 'win32';
|
|
3366
3366
|
try {
|
|
3367
3367
|
const psCmd = isWindows
|
|
3368
|
-
? 'tasklist /FI "IMAGENAME eq node.exe" 2>NUL |
|
|
3368
|
+
? 'tasklist /FI "IMAGENAME eq node.exe" /NH 2>NUL | find /c /v "" 2>NUL || echo 0'
|
|
3369
3369
|
: 'ps aux 2>/dev/null | grep -c agentic-flow || echo "0"';
|
|
3370
|
-
const ps = execSync(psCmd, { encoding: 'utf-8' });
|
|
3370
|
+
const ps = execSync(psCmd, { encoding: 'utf-8', timeout: 3000 });
|
|
3371
3371
|
activeAgents = Math.max(0, parseInt(ps.trim()) - 1);
|
|
3372
3372
|
coordinationActive = activeAgents > 0;
|
|
3373
3373
|
}
|
|
3374
3374
|
catch {
|
|
3375
|
-
//
|
|
3375
|
+
// ps/tasklist unavailable or timed out — report zero
|
|
3376
3376
|
}
|
|
3377
3377
|
return { activeAgents, maxAgents, coordinationActive };
|
|
3378
3378
|
}
|
|
@@ -344,13 +344,13 @@ const initAction = async (ctx) => {
|
|
|
344
344
|
}
|
|
345
345
|
}
|
|
346
346
|
if (!startDaemon && !startAll) {
|
|
347
|
-
|
|
347
|
+
const bin = (process.argv[1] || '').includes('ruflo') ? 'ruflo' : 'claude-flow';
|
|
348
348
|
output.writeln(output.bold('Next steps:'));
|
|
349
349
|
output.printList([
|
|
350
|
-
`Run ${output.highlight(
|
|
351
|
-
`Run ${output.highlight(
|
|
352
|
-
`Run ${output.highlight(
|
|
353
|
-
`Or use ${output.highlight(
|
|
350
|
+
`Run ${output.highlight(`${bin} daemon start`)} to start background workers`,
|
|
351
|
+
`Run ${output.highlight(`${bin} memory init`)} to initialize memory database`,
|
|
352
|
+
`Run ${output.highlight(`${bin} swarm init`)} to initialize a swarm`,
|
|
353
|
+
`Or use ${output.highlight(`${bin} init --start-all`)} to do all of the above`,
|
|
354
354
|
options.components.settings ? `Review ${output.highlight('.claude/settings.json')} for hook configurations` : '',
|
|
355
355
|
].filter(Boolean));
|
|
356
356
|
}
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
import { output } from '../output.js';
|
|
6
6
|
import { select, confirm } from '../prompt.js';
|
|
7
7
|
import { callMCPTool, MCPClientError } from '../mcp-client.js';
|
|
8
|
+
import { createRunId, emitEvent } from '../services/event-stream.js';
|
|
8
9
|
import * as fs from 'fs';
|
|
9
10
|
import * as path from 'path';
|
|
10
11
|
// Get dynamic swarm status from memory/session files
|
|
@@ -524,14 +525,72 @@ const startCommand = {
|
|
|
524
525
|
return { success: true, data: executionState };
|
|
525
526
|
}
|
|
526
527
|
};
|
|
528
|
+
// Shared polling loop used by `status --stream` and `watch`
|
|
529
|
+
function startStatusPoll(swarmId, runId, includeHealth) {
|
|
530
|
+
let prev = '';
|
|
531
|
+
const tick = () => {
|
|
532
|
+
const s = getSwarmStatus(swarmId);
|
|
533
|
+
const key = JSON.stringify(s);
|
|
534
|
+
if (key !== prev) {
|
|
535
|
+
prev = key;
|
|
536
|
+
emitEvent({
|
|
537
|
+
runId,
|
|
538
|
+
event: 'swarm_status',
|
|
539
|
+
agents: s.agents.total,
|
|
540
|
+
active: s.agents.active,
|
|
541
|
+
completed: s.tasks.completed,
|
|
542
|
+
pending: s.tasks.pending,
|
|
543
|
+
inProgress: s.tasks.inProgress,
|
|
544
|
+
progress: s.progress,
|
|
545
|
+
status: s.status,
|
|
546
|
+
});
|
|
547
|
+
}
|
|
548
|
+
if (includeHealth) {
|
|
549
|
+
emitEvent({
|
|
550
|
+
runId,
|
|
551
|
+
event: 'swarm_health',
|
|
552
|
+
memoryOk: s.hasActiveSwarm,
|
|
553
|
+
agentsTotal: s.agents.total,
|
|
554
|
+
agentsActive: s.agents.active,
|
|
555
|
+
successRate: s.metrics.successRate,
|
|
556
|
+
avgResponseTime: s.metrics.avgResponseTime,
|
|
557
|
+
elapsedTime: s.metrics.elapsedTime,
|
|
558
|
+
});
|
|
559
|
+
}
|
|
560
|
+
};
|
|
561
|
+
// Emit once immediately, then every 2 s
|
|
562
|
+
tick();
|
|
563
|
+
const timer = setInterval(tick, 2000);
|
|
564
|
+
const stop = () => { clearInterval(timer); };
|
|
565
|
+
return { stop };
|
|
566
|
+
}
|
|
527
567
|
// Swarm status
|
|
528
568
|
const statusCommand = {
|
|
529
569
|
name: 'status',
|
|
530
|
-
description: 'Show swarm status',
|
|
570
|
+
description: 'Show swarm status. Use --stream for live NDJSON output (pairs with Claude Code Monitor tool)',
|
|
571
|
+
options: [
|
|
572
|
+
{
|
|
573
|
+
name: 'stream',
|
|
574
|
+
description: 'Continuously emit NDJSON status events to stdout (use with Claude Code Monitor tool for live updates)',
|
|
575
|
+
type: 'boolean',
|
|
576
|
+
default: false
|
|
577
|
+
}
|
|
578
|
+
],
|
|
531
579
|
action: async (ctx) => {
|
|
532
580
|
const swarmId = ctx.args[0];
|
|
533
581
|
// Get dynamic status from actual swarm state files
|
|
534
582
|
const status = getSwarmStatus(swarmId);
|
|
583
|
+
// --stream: enter NDJSON polling mode instead of one-shot output
|
|
584
|
+
if (ctx.flags.stream) {
|
|
585
|
+
const runId = createRunId();
|
|
586
|
+
const { stop } = startStatusPoll(swarmId, runId, false);
|
|
587
|
+
await new Promise((resolve) => {
|
|
588
|
+
const onSig = () => { stop(); resolve(); };
|
|
589
|
+
process.once('SIGINT', onSig);
|
|
590
|
+
process.once('SIGTERM', onSig);
|
|
591
|
+
});
|
|
592
|
+
return { success: true };
|
|
593
|
+
}
|
|
535
594
|
if (ctx.flags.format === 'json') {
|
|
536
595
|
output.printJson(status);
|
|
537
596
|
return { success: true, data: status };
|
|
@@ -797,11 +856,48 @@ const coordinateCommand = {
|
|
|
797
856
|
return { success: true, data: { agents: v3Agents, count: agentCount } };
|
|
798
857
|
}
|
|
799
858
|
};
|
|
859
|
+
// Watch swarm (NDJSON event stream)
|
|
860
|
+
const watchCommand = {
|
|
861
|
+
name: 'watch',
|
|
862
|
+
description: 'Stream live swarm status as NDJSON events to stdout',
|
|
863
|
+
options: [
|
|
864
|
+
{
|
|
865
|
+
name: 'health',
|
|
866
|
+
description: 'Include periodic health-metric events',
|
|
867
|
+
type: 'boolean',
|
|
868
|
+
default: false
|
|
869
|
+
}
|
|
870
|
+
],
|
|
871
|
+
examples: [
|
|
872
|
+
{ command: 'claude-flow swarm watch', description: 'Stream NDJSON status events' },
|
|
873
|
+
{ command: 'claude-flow swarm watch --health', description: 'Include health metrics' }
|
|
874
|
+
],
|
|
875
|
+
action: async (ctx) => {
|
|
876
|
+
const swarmId = ctx.args[0];
|
|
877
|
+
const includeHealth = ctx.flags.health;
|
|
878
|
+
const runId = createRunId();
|
|
879
|
+
emitEvent({
|
|
880
|
+
runId,
|
|
881
|
+
event: 'watch_start',
|
|
882
|
+
swarmId: swarmId ?? null,
|
|
883
|
+
health: includeHealth,
|
|
884
|
+
});
|
|
885
|
+
const { stop } = startStatusPoll(swarmId, runId, includeHealth);
|
|
886
|
+
// Block until SIGINT / SIGTERM, then clean up
|
|
887
|
+
await new Promise((resolve) => {
|
|
888
|
+
const onSig = () => { stop(); resolve(); };
|
|
889
|
+
process.once('SIGINT', onSig);
|
|
890
|
+
process.once('SIGTERM', onSig);
|
|
891
|
+
});
|
|
892
|
+
emitEvent({ runId, event: 'watch_stop' });
|
|
893
|
+
return { success: true };
|
|
894
|
+
}
|
|
895
|
+
};
|
|
800
896
|
// Main swarm command
|
|
801
897
|
export const swarmCommand = {
|
|
802
898
|
name: 'swarm',
|
|
803
899
|
description: 'Swarm coordination commands',
|
|
804
|
-
subcommands: [initCommand, startCommand, statusCommand, stopCommand, scaleCommand, coordinateCommand],
|
|
900
|
+
subcommands: [initCommand, startCommand, statusCommand, stopCommand, scaleCommand, coordinateCommand, watchCommand],
|
|
805
901
|
options: [],
|
|
806
902
|
examples: [
|
|
807
903
|
{ command: 'claude-flow swarm init --v3-mode', description: 'Initialize V3 swarm' },
|
|
@@ -818,10 +914,11 @@ export const swarmCommand = {
|
|
|
818
914
|
output.printList([
|
|
819
915
|
`${output.highlight('init')} - Initialize a new swarm`,
|
|
820
916
|
`${output.highlight('start')} - Start swarm execution`,
|
|
821
|
-
`${output.highlight('status')} - Show swarm status`,
|
|
917
|
+
`${output.highlight('status')} - Show swarm status (--stream for live NDJSON)`,
|
|
822
918
|
`${output.highlight('stop')} - Stop swarm execution`,
|
|
823
919
|
`${output.highlight('scale')} - Scale swarm agent count`,
|
|
824
|
-
`${output.highlight('coordinate')} - V3 15-agent coordination
|
|
920
|
+
`${output.highlight('coordinate')} - V3 15-agent coordination`,
|
|
921
|
+
`${output.highlight('watch')} - Stream live NDJSON status events`
|
|
825
922
|
]);
|
|
826
923
|
return { success: true };
|
|
827
924
|
}
|
|
@@ -394,6 +394,22 @@ ToolSearch("hive consensus") → hive-mind_consensus, hive-mind_status
|
|
|
394
394
|
ToolSearch("+aidefence") → aidefence_scan, aidefence_is_safe, aidefence_has_pii
|
|
395
395
|
\`\`\``;
|
|
396
396
|
}
|
|
397
|
+
function nativeCapabilities() {
|
|
398
|
+
return `## Native Claude Code Capabilities (PREFER OVER MCP) — ADR-091
|
|
399
|
+
|
|
400
|
+
When running inside Claude Code, ALWAYS prefer native tools over MCP equivalents:
|
|
401
|
+
|
|
402
|
+
| Need | Use This | Not This |
|
|
403
|
+
|------|----------|----------|
|
|
404
|
+
| Periodic tasks | \`/loop\` with ScheduleWakeup (delay <270s for cache) | \`daemon start\` |
|
|
405
|
+
| Live monitoring | \`Monitor("npx @claude-flow/cli swarm watch --stream")\` | Polling \`swarm status\` |
|
|
406
|
+
| Background workers | \`CronCreate("audit", "*/15 * * * *", "...")\` | \`daemon start --background\` |
|
|
407
|
+
| Agent isolation | \`Task({ ..., isolation: "worktree" })\` | Shared worktree |
|
|
408
|
+
| Multi-agent comms | \`TeamCreate\` + \`SendMessage\` | Memory namespace coordination |
|
|
409
|
+
| Cross-session | \`PushNotification\` + \`RemoteTrigger\` | No equivalent |
|
|
410
|
+
|
|
411
|
+
MCP tool responses include hints: \`[LOOP_SUGGESTION]\`, \`[MONITOR_AVAILABLE]\`, \`[CRON_SUGGESTION]\`, \`[TEAM_SUGGESTION]\`, \`[WORKTREE_SUGGESTION]\` — follow them. In CI/headless, Ruflo falls back to daemon mode automatically.`;
|
|
412
|
+
}
|
|
397
413
|
function setupAndBoundary() {
|
|
398
414
|
return `## Quick Setup
|
|
399
415
|
|
|
@@ -422,6 +438,7 @@ npx @claude-flow/cli@latest doctor --fix
|
|
|
422
438
|
const TEMPLATE_SECTIONS = {
|
|
423
439
|
minimal: [
|
|
424
440
|
behavioralRules,
|
|
441
|
+
(_opts) => nativeCapabilities(),
|
|
425
442
|
fileOrganization,
|
|
426
443
|
projectArchitecture,
|
|
427
444
|
(_opts) => buildAndTest(),
|
|
@@ -434,6 +451,7 @@ const TEMPLATE_SECTIONS = {
|
|
|
434
451
|
],
|
|
435
452
|
standard: [
|
|
436
453
|
behavioralRules,
|
|
454
|
+
(_opts) => nativeCapabilities(),
|
|
437
455
|
fileOrganization,
|
|
438
456
|
projectArchitecture,
|
|
439
457
|
(_opts) => buildAndTest(),
|
|
@@ -450,6 +468,7 @@ const TEMPLATE_SECTIONS = {
|
|
|
450
468
|
],
|
|
451
469
|
full: [
|
|
452
470
|
behavioralRules,
|
|
471
|
+
(_opts) => nativeCapabilities(),
|
|
453
472
|
fileOrganization,
|
|
454
473
|
projectArchitecture,
|
|
455
474
|
(_opts) => buildAndTest(),
|
|
@@ -471,6 +490,7 @@ const TEMPLATE_SECTIONS = {
|
|
|
471
490
|
],
|
|
472
491
|
security: [
|
|
473
492
|
behavioralRules,
|
|
493
|
+
(_opts) => nativeCapabilities(),
|
|
474
494
|
fileOrganization,
|
|
475
495
|
projectArchitecture,
|
|
476
496
|
(_opts) => buildAndTest(),
|
|
@@ -486,6 +506,7 @@ const TEMPLATE_SECTIONS = {
|
|
|
486
506
|
],
|
|
487
507
|
performance: [
|
|
488
508
|
behavioralRules,
|
|
509
|
+
(_opts) => nativeCapabilities(),
|
|
489
510
|
fileOrganization,
|
|
490
511
|
projectArchitecture,
|
|
491
512
|
(_opts) => buildAndTest(),
|
|
@@ -211,6 +211,13 @@ export const agentTools = [
|
|
|
211
211
|
else if (routingResult.tier) {
|
|
212
212
|
response.tier = routingResult.tier;
|
|
213
213
|
}
|
|
214
|
+
// ADR-091 Phase 1: Native Claude Code capability suggestions
|
|
215
|
+
response.nativeIntegration = {
|
|
216
|
+
taskSuggestion: '[AGENT_NATIVE] For better isolation, spawn this agent via Claude Code Task tool: Task({ prompt: "...", subagent_type: "' + (input.agentType || 'coder') + '", isolation: "worktree" })',
|
|
217
|
+
isolationNote: agentType === 'coder' || agentType === 'reviewer'
|
|
218
|
+
? '[WORKTREE_SUGGESTION] This agent type modifies files. Use isolation: "worktree" to prevent conflicts.'
|
|
219
|
+
: undefined,
|
|
220
|
+
};
|
|
214
221
|
return response;
|
|
215
222
|
},
|
|
216
223
|
},
|
|
@@ -277,6 +284,10 @@ export const agentTools = [
|
|
|
277
284
|
createdAt: agent.createdAt,
|
|
278
285
|
domain: agent.domain,
|
|
279
286
|
lastResult: agent.lastResult || null,
|
|
287
|
+
// ADR-091 Phase 1: Native Claude Code capability suggestions
|
|
288
|
+
nativeIntegration: {
|
|
289
|
+
monitorSuggestion: '[MONITOR_AVAILABLE] For live agent updates: Monitor("npx @claude-flow/cli agent logs --stream")',
|
|
290
|
+
},
|
|
280
291
|
};
|
|
281
292
|
}
|
|
282
293
|
return {
|
|
@@ -65,7 +65,7 @@ const CAPABILITY_CATALOG = {
|
|
|
65
65
|
'memory-knowledge': {
|
|
66
66
|
name: 'Memory & Knowledge',
|
|
67
67
|
description: 'Persistent memory with HNSW vector search, AgentDB storage, and embeddings.',
|
|
68
|
-
tools: ['memory_store', 'memory_retrieve', 'memory_search', 'memory_list', 'memory_delete', 'memory_init', 'memory_export', '
|
|
68
|
+
tools: ['memory_store', 'memory_retrieve', 'memory_search', 'memory_list', 'memory_delete', 'memory_init', 'memory_export', 'memory_import_claude', 'memory_stats', 'memory_compact', 'memory_namespace'],
|
|
69
69
|
commands: ['memory store', 'memory retrieve', 'memory search', 'memory list', 'memory delete', 'memory init'],
|
|
70
70
|
agents: ['swarm-memory-manager', 'v3-memory-specialist'],
|
|
71
71
|
skills: ['v3-memory-unification', 'agentdb-advanced', 'agentdb-vector-search', 'agentdb-memory-patterns', 'agentdb-learning'],
|
|
@@ -1743,6 +1743,9 @@ export const hooksSessionStart = {
|
|
|
1743
1743
|
tasksRestored: sessionMemory?.restoredPatterns || 0,
|
|
1744
1744
|
memoryRestored: sessionMemory?.restoredPatterns || 0,
|
|
1745
1745
|
} : null,
|
|
1746
|
+
nativeCapabilities: {
|
|
1747
|
+
note: 'Claude Code native capabilities detected. Prefer /loop over daemon start, Monitor over polling, CronCreate over background processes.',
|
|
1748
|
+
},
|
|
1746
1749
|
};
|
|
1747
1750
|
},
|
|
1748
1751
|
};
|
|
@@ -2196,6 +2199,21 @@ export const hooksTrajectoryStart = {
|
|
|
2196
2199
|
startedAt,
|
|
2197
2200
|
};
|
|
2198
2201
|
activeTrajectories.set(trajectoryId, trajectory);
|
|
2202
|
+
// Persist pending trajectory to disk so it survives MCP restarts
|
|
2203
|
+
const storeFn = await getRealStoreFunction();
|
|
2204
|
+
if (storeFn) {
|
|
2205
|
+
try {
|
|
2206
|
+
await storeFn({
|
|
2207
|
+
key: `trajectory-pending-${trajectoryId}`,
|
|
2208
|
+
value: JSON.stringify(trajectory),
|
|
2209
|
+
namespace: 'trajectories',
|
|
2210
|
+
tags: [agent, 'pending', 'sona-trajectory'],
|
|
2211
|
+
});
|
|
2212
|
+
}
|
|
2213
|
+
catch {
|
|
2214
|
+
// Best-effort persistence — trajectory still lives in-memory
|
|
2215
|
+
}
|
|
2216
|
+
}
|
|
2199
2217
|
return {
|
|
2200
2218
|
trajectoryId,
|
|
2201
2219
|
task,
|
|
@@ -2607,8 +2625,19 @@ export const hooksIntelligenceStats = {
|
|
|
2607
2625
|
const moe = await getMoERouter();
|
|
2608
2626
|
const flash = await getFlashAttention();
|
|
2609
2627
|
const lora = await getLoRAAdapter();
|
|
2610
|
-
// Fallback to memory store for legacy data
|
|
2611
|
-
|
|
2628
|
+
// Fallback to memory store for legacy data (may not exist yet)
|
|
2629
|
+
let memoryStats;
|
|
2630
|
+
try {
|
|
2631
|
+
memoryStats = getIntelligenceStatsFromMemory();
|
|
2632
|
+
}
|
|
2633
|
+
catch {
|
|
2634
|
+
memoryStats = {
|
|
2635
|
+
trajectories: { total: 0, successful: 0 },
|
|
2636
|
+
patterns: { learned: 0, categories: {} },
|
|
2637
|
+
memory: { indexSize: 0, totalAccessCount: 0, memorySizeBytes: 0 },
|
|
2638
|
+
routing: { decisions: 0, avgConfidence: 0 },
|
|
2639
|
+
};
|
|
2640
|
+
}
|
|
2612
2641
|
// SONA stats from real implementation
|
|
2613
2642
|
let sonaStats = {
|
|
2614
2643
|
trajectoriesTotal: memoryStats.trajectories.total,
|
|
@@ -3304,26 +3333,7 @@ export const hooksWorkerDispatch = {
|
|
|
3304
3333
|
startedAt: new Date(),
|
|
3305
3334
|
};
|
|
3306
3335
|
activeWorkers.set(workerId, worker);
|
|
3307
|
-
|
|
3308
|
-
if (background) {
|
|
3309
|
-
setTimeout(() => {
|
|
3310
|
-
const w = activeWorkers.get(workerId);
|
|
3311
|
-
if (w) {
|
|
3312
|
-
w.progress = 50;
|
|
3313
|
-
w.phase = 'processing';
|
|
3314
|
-
}
|
|
3315
|
-
}, 500);
|
|
3316
|
-
setTimeout(() => {
|
|
3317
|
-
const w = activeWorkers.get(workerId);
|
|
3318
|
-
if (w) {
|
|
3319
|
-
w.progress = 100;
|
|
3320
|
-
w.phase = 'completed';
|
|
3321
|
-
w.status = 'completed';
|
|
3322
|
-
w.completedAt = new Date();
|
|
3323
|
-
}
|
|
3324
|
-
}, 1500);
|
|
3325
|
-
}
|
|
3326
|
-
else {
|
|
3336
|
+
if (!background) {
|
|
3327
3337
|
worker.progress = 100;
|
|
3328
3338
|
worker.phase = 'completed';
|
|
3329
3339
|
worker.status = 'completed';
|
|
@@ -3340,9 +3350,16 @@ export const hooksWorkerDispatch = {
|
|
|
3340
3350
|
estimatedDuration: config.estimatedDuration,
|
|
3341
3351
|
capabilities: config.capabilities,
|
|
3342
3352
|
},
|
|
3343
|
-
status: background ? '
|
|
3353
|
+
status: background ? 'scheduled' : 'completed',
|
|
3344
3354
|
background,
|
|
3355
|
+
note: background ? 'Worker scheduled. Use hooks_worker-status to check progress. Start the daemon (daemon start) for real background execution.' : undefined,
|
|
3345
3356
|
timestamp: new Date().toISOString(),
|
|
3357
|
+
nativeIntegration: {
|
|
3358
|
+
loopSuggestion: `[LOOP_SUGGESTION] This worker would benefit from /loop for periodic execution.\nRecommended: /loop "${trigger} worker"\nInterval: 270s (stays within cache window)`,
|
|
3359
|
+
suggestedDelay: 270,
|
|
3360
|
+
loopPrompt: `Run ${trigger} worker and check results`,
|
|
3361
|
+
cronSuggestion: `[CRON_SUGGESTION] For persistent background execution: CronCreate("${trigger}-worker", "*/15 * * * *", "Run ${trigger} worker")`,
|
|
3362
|
+
},
|
|
3346
3363
|
};
|
|
3347
3364
|
},
|
|
3348
3365
|
};
|
|
@@ -3400,6 +3417,9 @@ export const hooksWorkerStatus = {
|
|
|
3400
3417
|
completed: workers.filter(w => w.status === 'completed').length,
|
|
3401
3418
|
failed: workers.filter(w => w.status === 'failed').length,
|
|
3402
3419
|
},
|
|
3420
|
+
nativeIntegration: {
|
|
3421
|
+
monitorSuggestion: '[MONITOR_AVAILABLE] For live worker updates: Monitor("npx @claude-flow/cli hooks worker list --stream")',
|
|
3422
|
+
},
|
|
3403
3423
|
};
|
|
3404
3424
|
},
|
|
3405
3425
|
};
|
|
@@ -251,6 +251,9 @@ export const neuralTools = [
|
|
|
251
251
|
totalPatterns: Object.keys(store.patterns).length,
|
|
252
252
|
epochs,
|
|
253
253
|
trainedAt: model.trainedAt,
|
|
254
|
+
...(embeddingServiceName === 'hash-fallback' || embeddingServiceName === 'none' ? {
|
|
255
|
+
platformNote: 'ONNX embeddings not available — using hash-based fallback. Install @claude-flow/embeddings and run "embeddings init --download" for semantic search.',
|
|
256
|
+
} : {}),
|
|
254
257
|
};
|
|
255
258
|
},
|
|
256
259
|
},
|
|
@@ -109,6 +109,10 @@ export const swarmTools = [
|
|
|
109
109
|
initializedAt: now,
|
|
110
110
|
config: swarmState.config,
|
|
111
111
|
persisted: true,
|
|
112
|
+
nativeIntegration: {
|
|
113
|
+
teamSuggestion: '[TEAM_SUGGESTION] Create a Claude Code team for this swarm: TeamCreate({ team_name: "' + (input.name || 'swarm') + '", description: "Ruflo swarm coordination" })',
|
|
114
|
+
worktreeNote: '[WORKTREE_SUGGESTION] Spawn file-modifying agents with isolation: "worktree" to prevent conflicts',
|
|
115
|
+
},
|
|
112
116
|
};
|
|
113
117
|
},
|
|
114
118
|
},
|
|
@@ -168,6 +172,9 @@ export const swarmTools = [
|
|
|
168
172
|
createdAt: latest.createdAt,
|
|
169
173
|
updatedAt: latest.updatedAt,
|
|
170
174
|
totalSwarms: swarmIds.length,
|
|
175
|
+
nativeIntegration: {
|
|
176
|
+
monitorSuggestion: '[MONITOR_AVAILABLE] For live swarm updates: Monitor("npx @claude-flow/cli swarm watch --stream")',
|
|
177
|
+
},
|
|
171
178
|
};
|
|
172
179
|
},
|
|
173
180
|
},
|
|
@@ -312,6 +319,9 @@ export const swarmTools = [
|
|
|
312
319
|
agentCount: target.agents.length,
|
|
313
320
|
checks,
|
|
314
321
|
checkedAt: new Date().toISOString(),
|
|
322
|
+
nativeIntegration: {
|
|
323
|
+
monitorSuggestion: '[MONITOR_AVAILABLE] For continuous health monitoring: Monitor("npx @claude-flow/cli swarm watch --stream --health")',
|
|
324
|
+
},
|
|
315
325
|
};
|
|
316
326
|
},
|
|
317
327
|
},
|
|
@@ -284,11 +284,13 @@ export const systemTools = [
|
|
|
284
284
|
const metrics = loadMetrics();
|
|
285
285
|
const checks = [];
|
|
286
286
|
const projectCwd = getProjectCwd();
|
|
287
|
-
// Memory DB check — verify
|
|
287
|
+
// Memory DB check — verify any supported store file exists
|
|
288
288
|
{
|
|
289
289
|
const t0 = performance.now();
|
|
290
|
-
const
|
|
291
|
-
const
|
|
290
|
+
const legacyPath = join(projectCwd, '.claude-flow', 'memory', 'store.json');
|
|
291
|
+
const agentDbPath = join(projectCwd, '.claude-flow', 'memory', 'agentdb.sqlite');
|
|
292
|
+
const rvfPath = join(projectCwd, '.claude-flow', 'memory', 'store.rvf');
|
|
293
|
+
const memoryExists = existsSync(legacyPath) || existsSync(agentDbPath) || existsSync(rvfPath);
|
|
292
294
|
const elapsed = performance.now() - t0;
|
|
293
295
|
checks.push({
|
|
294
296
|
name: 'memory',
|
|
@@ -90,6 +90,10 @@ export const taskTools = [
|
|
|
90
90
|
createdAt: task.createdAt,
|
|
91
91
|
assignedTo: task.assignedTo,
|
|
92
92
|
tags: task.tags,
|
|
93
|
+
// ADR-091 Phase 1: Native Claude Code capability suggestions
|
|
94
|
+
nativeIntegration: {
|
|
95
|
+
nativeTaskNote: '[TASK_NATIVE] Claude Code has a native task system. Consider TaskCreate({ subject: "...", description: "..." }) for shared visibility across agents.',
|
|
96
|
+
},
|
|
93
97
|
};
|
|
94
98
|
},
|
|
95
99
|
},
|
|
@@ -246,6 +250,10 @@ export const taskTools = [
|
|
|
246
250
|
status: task.status,
|
|
247
251
|
completedAt: task.completedAt,
|
|
248
252
|
result: task.result,
|
|
253
|
+
// ADR-091 Phase 1: Native Claude Code capability suggestions
|
|
254
|
+
nativeIntegration: {
|
|
255
|
+
notifySuggestion: '[NOTIFY_SUGGESTION] For tasks spanning sessions, use PushNotification to alert when complete.',
|
|
256
|
+
},
|
|
249
257
|
};
|
|
250
258
|
}
|
|
251
259
|
return {
|
|
@@ -9,6 +9,10 @@
|
|
|
9
9
|
* where process.cwd() may resolve to '/') over the real process.cwd().
|
|
10
10
|
*/
|
|
11
11
|
export function getProjectCwd() {
|
|
12
|
-
|
|
12
|
+
const envCwd = process.env.CLAUDE_FLOW_CWD;
|
|
13
|
+
if (envCwd && envCwd !== '/' && envCwd !== process.env.HOME) {
|
|
14
|
+
return envCwd;
|
|
15
|
+
}
|
|
16
|
+
return process.cwd();
|
|
13
17
|
}
|
|
14
18
|
//# sourceMappingURL=types.js.map
|
|
@@ -78,13 +78,15 @@ async function getRegistry(dbPath) {
|
|
|
78
78
|
dbPath: dbPath || getDbPath(),
|
|
79
79
|
embeddingModel: 'Xenova/all-MiniLM-L6-v2',
|
|
80
80
|
dimension: 384,
|
|
81
|
+
vectorBackend: 'auto',
|
|
81
82
|
controllers: {
|
|
82
83
|
reasoningBank: true,
|
|
83
84
|
learningBridge: false,
|
|
84
85
|
tieredCache: true,
|
|
85
86
|
hierarchicalMemory: true,
|
|
86
87
|
memoryConsolidation: true,
|
|
87
|
-
memoryGraph: true,
|
|
88
|
+
memoryGraph: true,
|
|
89
|
+
vectorBackend: true,
|
|
88
90
|
},
|
|
89
91
|
});
|
|
90
92
|
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NDJSON Event Stream for CLI --stream mode
|
|
3
|
+
*
|
|
4
|
+
* Emits newline-delimited JSON events to stdout for consumption
|
|
5
|
+
* by Claude Code's Monitor tool. Each event includes schema versioning.
|
|
6
|
+
*
|
|
7
|
+
* @see ADR-091: NDJSON event streaming infrastructure
|
|
8
|
+
*/
|
|
9
|
+
export interface StreamEvent {
|
|
10
|
+
schema: 'ruflo.event.v1';
|
|
11
|
+
event: string;
|
|
12
|
+
runId: string;
|
|
13
|
+
agentId?: string;
|
|
14
|
+
ts: string;
|
|
15
|
+
[key: string]: unknown;
|
|
16
|
+
}
|
|
17
|
+
/** Generate a short unique run ID (e.g. run_m1abc_3f2a1b) */
|
|
18
|
+
export declare function createRunId(): string;
|
|
19
|
+
/** Write one NDJSON line to stdout with schema and timestamp auto-populated */
|
|
20
|
+
export declare function emitEvent(event: Omit<StreamEvent, 'schema' | 'ts'>): void;
|
|
21
|
+
/** Convenience wrapper that binds a runId to an emitter */
|
|
22
|
+
export declare function createEventEmitter(runId: string): {
|
|
23
|
+
emit(event: string, data?: Record<string, unknown>): void;
|
|
24
|
+
};
|
|
25
|
+
//# sourceMappingURL=event-stream.d.ts.map
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* NDJSON Event Stream for CLI --stream mode
|
|
3
|
+
*
|
|
4
|
+
* Emits newline-delimited JSON events to stdout for consumption
|
|
5
|
+
* by Claude Code's Monitor tool. Each event includes schema versioning.
|
|
6
|
+
*
|
|
7
|
+
* @see ADR-091: NDJSON event streaming infrastructure
|
|
8
|
+
*/
|
|
9
|
+
import { randomBytes } from 'crypto';
|
|
10
|
+
/** Generate a short unique run ID (e.g. run_m1abc_3f2a1b) */
|
|
11
|
+
export function createRunId() {
|
|
12
|
+
return `run_${Date.now().toString(36)}_${randomBytes(3).toString('hex')}`;
|
|
13
|
+
}
|
|
14
|
+
/** Write one NDJSON line to stdout with schema and timestamp auto-populated */
|
|
15
|
+
export function emitEvent(event) {
|
|
16
|
+
const full = Object.assign({ schema: 'ruflo.event.v1', ts: new Date().toISOString() }, event);
|
|
17
|
+
process.stdout.write(JSON.stringify(full) + '\n');
|
|
18
|
+
}
|
|
19
|
+
/** Convenience wrapper that binds a runId to an emitter */
|
|
20
|
+
export function createEventEmitter(runId) {
|
|
21
|
+
return {
|
|
22
|
+
emit(event, data) {
|
|
23
|
+
emitEvent({ runId, event, ...data });
|
|
24
|
+
},
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=event-stream.js.map
|
|
@@ -6,6 +6,9 @@ export { WorkerDaemon, getDaemon, startDaemon, stopDaemon, type WorkerType, } fr
|
|
|
6
6
|
export { HeadlessWorkerExecutor, HEADLESS_WORKER_TYPES, HEADLESS_WORKER_CONFIGS, LOCAL_WORKER_TYPES, LOCAL_WORKER_CONFIGS, ALL_WORKER_CONFIGS, isHeadlessWorker, isLocalWorker, getModelId, getWorkerConfig, type HeadlessWorkerType, type LocalWorkerType, type HeadlessWorkerConfig, type HeadlessExecutionResult, type HeadlessExecutorConfig, type HeadlessOptions, type PoolStatus, type SandboxMode, type ModelType, type OutputFormat, type ExecutionMode, type WorkerPriority, type WorkerConfig, } from './headless-worker-executor.js';
|
|
7
7
|
export { ContainerWorkerPool, type ContainerInfo, type ContainerPoolConfig, type ContainerExecutionOptions, type ContainerPoolStatus, type ContainerState, } from './container-worker-pool.js';
|
|
8
8
|
export { WorkerQueue, type QueueTask, type WorkerQueueConfig, type QueueStats, type WorkerRegistration, type TaskStatus, } from './worker-queue.js';
|
|
9
|
+
export { createRunId, emitEvent, createEventEmitter, type StreamEvent, } from './event-stream.js';
|
|
10
|
+
export { detectCapabilities, getRuntimeTier, getCacheWarmDelay, type RuntimeCapabilities, type RuntimeTier, } from './runtime-capabilities.js';
|
|
11
|
+
export { runLoopWorker, type LoopWorkerResult, } from './loop-worker-runner.js';
|
|
9
12
|
export type { default as WorkerDaemonType, DaemonConfig } from './worker-daemon.js';
|
|
10
13
|
export type { default as HeadlessWorkerExecutorType } from './headless-worker-executor.js';
|
|
11
14
|
export type { default as ContainerWorkerPoolType } from './container-worker-pool.js';
|
|
@@ -8,4 +8,10 @@ export { HeadlessWorkerExecutor, HEADLESS_WORKER_TYPES, HEADLESS_WORKER_CONFIGS,
|
|
|
8
8
|
export { ContainerWorkerPool, } from './container-worker-pool.js';
|
|
9
9
|
// Worker Queue (Phase 4)
|
|
10
10
|
export { WorkerQueue, } from './worker-queue.js';
|
|
11
|
+
// Event Stream (ADR-091)
|
|
12
|
+
export { createRunId, emitEvent, createEventEmitter, } from './event-stream.js';
|
|
13
|
+
// Runtime Capabilities (ADR-091)
|
|
14
|
+
export { detectCapabilities, getRuntimeTier, getCacheWarmDelay, } from './runtime-capabilities.js';
|
|
15
|
+
// Loop Worker Runner (ADR-091 Phase 2)
|
|
16
|
+
export { runLoopWorker, } from './loop-worker-runner.js';
|
|
11
17
|
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-091 Phase 2 -- Stateless Loop Worker Runner
|
|
3
|
+
*
|
|
4
|
+
* Designed for /loop execution: runs a single worker iteration and returns
|
|
5
|
+
* metadata that the caller can use with ScheduleWakeup.
|
|
6
|
+
*/
|
|
7
|
+
export interface LoopWorkerResult {
|
|
8
|
+
workerType: string;
|
|
9
|
+
success: boolean;
|
|
10
|
+
suggestedDelay: number;
|
|
11
|
+
reason: string;
|
|
12
|
+
loopPrompt: string;
|
|
13
|
+
metrics?: Record<string, unknown>;
|
|
14
|
+
}
|
|
15
|
+
export declare function runLoopWorker(workerType: string): Promise<LoopWorkerResult>;
|
|
16
|
+
//# sourceMappingURL=loop-worker-runner.d.ts.map
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-091 Phase 2 -- Stateless Loop Worker Runner
|
|
3
|
+
*
|
|
4
|
+
* Designed for /loop execution: runs a single worker iteration and returns
|
|
5
|
+
* metadata that the caller can use with ScheduleWakeup.
|
|
6
|
+
*/
|
|
7
|
+
import { execSync } from 'child_process';
|
|
8
|
+
import { getCacheWarmDelay } from './runtime-capabilities.js';
|
|
9
|
+
export async function runLoopWorker(workerType) {
|
|
10
|
+
const startMs = Date.now();
|
|
11
|
+
let success = false;
|
|
12
|
+
let reason = '';
|
|
13
|
+
try {
|
|
14
|
+
const safeWorkerType = workerType.replace(/[^a-zA-Z0-9_-]/g, '');
|
|
15
|
+
const stdout = execSync(`npx @claude-flow/cli hooks worker dispatch --trigger ${safeWorkerType}`, { encoding: 'utf-8', timeout: 120_000, stdio: ['ignore', 'pipe', 'pipe'] });
|
|
16
|
+
success = true;
|
|
17
|
+
reason = stdout.trim().slice(0, 200) || `${workerType} completed`;
|
|
18
|
+
}
|
|
19
|
+
catch (err) {
|
|
20
|
+
const msg = err instanceof Error ? err.message : String(err);
|
|
21
|
+
reason = `${workerType} failed: ${msg.slice(0, 200)}`;
|
|
22
|
+
}
|
|
23
|
+
const durationMs = Date.now() - startMs;
|
|
24
|
+
const suggestedDelay = getCacheWarmDelay();
|
|
25
|
+
return {
|
|
26
|
+
workerType,
|
|
27
|
+
success,
|
|
28
|
+
suggestedDelay,
|
|
29
|
+
reason,
|
|
30
|
+
loopPrompt: `Run ${workerType} worker and report results`,
|
|
31
|
+
metrics: { durationMs, timestamp: new Date().toISOString() },
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=loop-worker-runner.js.map
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-091 Phase 1 -- Runtime Capabilities Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects the host environment and exposes which execution primitives are
|
|
5
|
+
* available so that higher-level services can choose the right path:
|
|
6
|
+
* 1. claude-code-native -- full Claude Code tooling (loop, monitor, cron, teams)
|
|
7
|
+
* 2. mcp-fallback -- MCP transport active but native tools missing
|
|
8
|
+
* 3. ci-daemon -- headless / CI, use detached daemon
|
|
9
|
+
*/
|
|
10
|
+
export interface RuntimeCapabilities {
|
|
11
|
+
loop: boolean;
|
|
12
|
+
monitor: boolean;
|
|
13
|
+
cron: boolean;
|
|
14
|
+
teams: boolean;
|
|
15
|
+
worktreeIsolation: boolean;
|
|
16
|
+
pushNotification: boolean;
|
|
17
|
+
}
|
|
18
|
+
export type RuntimeTier = 'claude-code-native' | 'mcp-fallback' | 'ci-daemon';
|
|
19
|
+
export declare function detectCapabilities(): RuntimeCapabilities;
|
|
20
|
+
export declare function getRuntimeTier(): RuntimeTier;
|
|
21
|
+
export declare function getCacheWarmDelay(providerCacheTtlSeconds?: number): number;
|
|
22
|
+
//# sourceMappingURL=runtime-capabilities.d.ts.map
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADR-091 Phase 1 -- Runtime Capabilities Detection
|
|
3
|
+
*
|
|
4
|
+
* Detects the host environment and exposes which execution primitives are
|
|
5
|
+
* available so that higher-level services can choose the right path:
|
|
6
|
+
* 1. claude-code-native -- full Claude Code tooling (loop, monitor, cron, teams)
|
|
7
|
+
* 2. mcp-fallback -- MCP transport active but native tools missing
|
|
8
|
+
* 3. ci-daemon -- headless / CI, use detached daemon
|
|
9
|
+
*/
|
|
10
|
+
function isClaudeCodeNative() {
|
|
11
|
+
return !!(process.env.CLAUDE_CODE ||
|
|
12
|
+
process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS);
|
|
13
|
+
}
|
|
14
|
+
function isMcpTransportActive() {
|
|
15
|
+
return (!process.stdin.isTTY &&
|
|
16
|
+
process.env.CLAUDE_FLOW_MCP_TRANSPORT === 'stdio');
|
|
17
|
+
}
|
|
18
|
+
function isCiOrHeadless() {
|
|
19
|
+
return !!(process.env.CI || process.env.CLAUDE_FLOW_HEADLESS);
|
|
20
|
+
}
|
|
21
|
+
export function detectCapabilities() {
|
|
22
|
+
const native = isClaudeCodeNative();
|
|
23
|
+
const teamsEnabled = !!process.env.CLAUDE_CODE_EXPERIMENTAL_AGENT_TEAMS;
|
|
24
|
+
return {
|
|
25
|
+
loop: native,
|
|
26
|
+
monitor: native,
|
|
27
|
+
cron: native,
|
|
28
|
+
teams: native && teamsEnabled,
|
|
29
|
+
worktreeIsolation: native,
|
|
30
|
+
pushNotification: native,
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
export function getRuntimeTier() {
|
|
34
|
+
if (isClaudeCodeNative())
|
|
35
|
+
return 'claude-code-native';
|
|
36
|
+
if (isMcpTransportActive())
|
|
37
|
+
return 'mcp-fallback';
|
|
38
|
+
if (isCiOrHeadless())
|
|
39
|
+
return 'ci-daemon';
|
|
40
|
+
return 'mcp-fallback';
|
|
41
|
+
}
|
|
42
|
+
export function getCacheWarmDelay(providerCacheTtlSeconds) {
|
|
43
|
+
return Math.min(270, (providerCacheTtlSeconds ?? 300) * 0.9);
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=runtime-capabilities.js.map
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* - testgaps: Test coverage analysis (20 min interval)
|
|
11
11
|
*/
|
|
12
12
|
import { EventEmitter } from 'events';
|
|
13
|
-
import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, unlinkSync } from 'fs';
|
|
13
|
+
import { existsSync, mkdirSync, writeFileSync, readFileSync, appendFileSync, unlinkSync, renameSync } from 'fs';
|
|
14
14
|
import { cpus } from 'os';
|
|
15
15
|
import { join } from 'path';
|
|
16
16
|
import { HeadlessWorkerExecutor, isHeadlessWorker, } from './headless-worker-executor.js';
|
|
@@ -903,7 +903,9 @@ export class WorkerDaemon extends EventEmitter {
|
|
|
903
903
|
savedAt: new Date().toISOString(),
|
|
904
904
|
};
|
|
905
905
|
try {
|
|
906
|
-
|
|
906
|
+
const tmpFile = this.config.stateFile + '.tmp';
|
|
907
|
+
writeFileSync(tmpFile, JSON.stringify(state, null, 2));
|
|
908
|
+
renameSync(tmpFile, this.config.stateFile);
|
|
907
909
|
}
|
|
908
910
|
catch (error) {
|
|
909
911
|
this.log('error', `Failed to save state: ${error}`);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@claude-flow/cli",
|
|
3
|
-
"version": "3.5.
|
|
3
|
+
"version": "3.5.83",
|
|
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",
|