claude-flow 3.5.82 → 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/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/hooks-tools.js +12 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/swarm-tools.js +10 -0
- package/v3/@claude-flow/cli/dist/src/mcp-tools/task-tools.js +8 -0
- 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/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');
|
|
@@ -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 {
|
|
@@ -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
|
};
|
|
@@ -3351,6 +3354,12 @@ export const hooksWorkerDispatch = {
|
|
|
3351
3354
|
background,
|
|
3352
3355
|
note: background ? 'Worker scheduled. Use hooks_worker-status to check progress. Start the daemon (daemon start) for real background execution.' : undefined,
|
|
3353
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
|
+
},
|
|
3354
3363
|
};
|
|
3355
3364
|
},
|
|
3356
3365
|
};
|
|
@@ -3408,6 +3417,9 @@ export const hooksWorkerStatus = {
|
|
|
3408
3417
|
completed: workers.filter(w => w.status === 'completed').length,
|
|
3409
3418
|
failed: workers.filter(w => w.status === 'failed').length,
|
|
3410
3419
|
},
|
|
3420
|
+
nativeIntegration: {
|
|
3421
|
+
monitorSuggestion: '[MONITOR_AVAILABLE] For live worker updates: Monitor("npx @claude-flow/cli hooks worker list --stream")',
|
|
3422
|
+
},
|
|
3411
3423
|
};
|
|
3412
3424
|
},
|
|
3413
3425
|
};
|
|
@@ -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
|
},
|
|
@@ -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 {
|
|
@@ -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
|
|
@@ -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",
|