monomind 1.17.0 → 1.17.2
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/.claude/agents/engineering/engineering-security-engineer.md +1 -1
- package/.claude/commands/mastermind/_repeat.md +4 -0
- package/.claude/commands/mastermind/master.md +52 -1
- package/.claude/scheduled_tasks.lock +1 -1
- package/.claude/skills/mastermind/_repeat.md +2 -0
- package/package.json +1 -1
- package/packages/@monomind/cli/.claude/agents/engineering/engineering-security-engineer.md +1 -1
- package/packages/@monomind/cli/.claude/commands/mastermind/_repeat.md +4 -0
- package/packages/@monomind/cli/.claude/commands/mastermind/master.md +52 -1
- package/packages/@monomind/cli/.claude/skills/mastermind/_repeat.md +2 -0
- package/packages/@monomind/cli/dist/src/__tests__/browse-analyzer.test.js +42 -59
- package/packages/@monomind/cli/dist/src/agents/registry-builder.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/agents/registry-builder.js +22 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/server.js +18 -0
- package/packages/@monomind/cli/dist/src/browser/dashboard/ui.html +37 -125
- package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.d.ts +17 -0
- package/packages/@monomind/cli/dist/src/commands/agent-lifecycle.js +320 -0
- package/packages/@monomind/cli/dist/src/commands/agent-ops.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/agent-ops.js +329 -0
- package/packages/@monomind/cli/dist/src/commands/agent.js +5 -907
- package/packages/@monomind/cli/dist/src/commands/analyze-ast.d.ts +26 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-ast.js +284 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-boundaries.js +295 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-diff.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-diff.js +395 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-graph.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-graph.js +304 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-imports.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-imports.js +287 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-symbols.d.ts +14 -0
- package/packages/@monomind/cli/dist/src/commands/analyze-symbols.js +302 -0
- package/packages/@monomind/cli/dist/src/commands/analyze.d.ts +38 -0
- package/packages/@monomind/cli/dist/src/commands/analyze.js +12 -1827
- package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.d.ts +26 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-env-checks.js +189 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.d.ts +20 -0
- package/packages/@monomind/cli/dist/src/commands/doctor-project-checks.js +432 -0
- package/packages/@monomind/cli/dist/src/commands/doctor.js +54 -943
- package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.d.ts +11 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-comms.js +242 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.d.ts +35 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-helpers.js +203 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-ops.js +233 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.d.ts +12 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind-spawn.js +274 -0
- package/packages/@monomind/cli/dist/src/commands/hive-mind.js +10 -1129
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.d.ts +4 -4
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-commands.js +19 -819
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-gaps.js +334 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/hooks-coverage-routing.js +399 -0
- package/packages/@monomind/cli/dist/src/commands/init-subcommands.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/init-subcommands.js +156 -0
- package/packages/@monomind/cli/dist/src/commands/init-upgrade.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/init-upgrade.js +203 -0
- package/packages/@monomind/cli/dist/src/commands/init-wizard.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/init-wizard.js +246 -0
- package/packages/@monomind/cli/dist/src/commands/init.js +6 -623
- package/packages/@monomind/cli/dist/src/commands/memory-admin.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/commands/memory-admin.js +433 -0
- package/packages/@monomind/cli/dist/src/commands/memory-crud.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/memory-crud.js +342 -0
- package/packages/@monomind/cli/dist/src/commands/memory-list.d.ts +10 -0
- package/packages/@monomind/cli/dist/src/commands/memory-list.js +321 -0
- package/packages/@monomind/cli/dist/src/commands/memory-transfer.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/memory-transfer.js +372 -0
- package/packages/@monomind/cli/dist/src/commands/memory.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/memory.js +10 -1441
- package/packages/@monomind/cli/dist/src/commands/neural-core.d.ts +8 -0
- package/packages/@monomind/cli/dist/src/commands/neural-core.js +274 -0
- package/packages/@monomind/cli/dist/src/commands/neural-optimize.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/neural-optimize.js +332 -0
- package/packages/@monomind/cli/dist/src/commands/neural-registry.d.ts +7 -0
- package/packages/@monomind/cli/dist/src/commands/neural-registry.js +290 -0
- package/packages/@monomind/cli/dist/src/commands/neural.js +3 -974
- package/packages/@monomind/cli/dist/src/commands/platforms.js +327 -7
- package/packages/@monomind/cli/dist/src/commands/security-cve.d.ts +6 -0
- package/packages/@monomind/cli/dist/src/commands/security-cve.js +310 -0
- package/packages/@monomind/cli/dist/src/commands/security-misc.d.ts +9 -0
- package/packages/@monomind/cli/dist/src/commands/security-misc.js +293 -0
- package/packages/@monomind/cli/dist/src/commands/security-scan.d.ts +18 -0
- package/packages/@monomind/cli/dist/src/commands/security-scan.js +328 -0
- package/packages/@monomind/cli/dist/src/commands/security.js +3 -958
- package/packages/@monomind/cli/dist/src/commands/session.js +1 -1
- package/packages/@monomind/cli/dist/src/commands/swarm.js +23 -17
- package/packages/@monomind/cli/dist/src/index.js +8 -37
- package/packages/@monomind/cli/dist/src/mcp-tools/swarm-tools.js +77 -0
- package/packages/@monomind/cli/dist/src/parser.js +11 -6
- package/packages/@monomind/cli/dist/src/routing/llm-caller.js +1 -2
- package/packages/@monomind/cli/package.json +2 -3
- package/packages/@monomind/cli/scripts/understand-analyze.mjs +1 -1
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive Mind operational subcommands — status, task, optimize-memory
|
|
3
|
+
*/
|
|
4
|
+
import { output } from '../output.js';
|
|
5
|
+
import { input } from '../prompt.js';
|
|
6
|
+
import { callMCPTool, MCPClientError } from '../mcp-client.js';
|
|
7
|
+
import { MAX_TASK_DESC_LEN, formatAgentStatus, formatHiveStatus, formatHealth, formatPriority, } from './hive-mind-helpers.js';
|
|
8
|
+
export const statusCommand = {
|
|
9
|
+
name: 'status',
|
|
10
|
+
description: 'Show hive mind status',
|
|
11
|
+
options: [
|
|
12
|
+
{ name: 'detailed', short: 'd', description: 'Show detailed metrics', type: 'boolean', default: false },
|
|
13
|
+
{ name: 'watch', short: 'w', description: 'Watch for changes', type: 'boolean', default: false }
|
|
14
|
+
],
|
|
15
|
+
action: async (ctx) => {
|
|
16
|
+
const detailed = ctx.flags.detailed;
|
|
17
|
+
try {
|
|
18
|
+
const result = await callMCPTool('hive-mind_status', {
|
|
19
|
+
includeMetrics: detailed,
|
|
20
|
+
includeWorkers: true,
|
|
21
|
+
});
|
|
22
|
+
if (ctx.flags.format === 'json') {
|
|
23
|
+
output.printJson(result);
|
|
24
|
+
return { success: true, data: result };
|
|
25
|
+
}
|
|
26
|
+
const flexResult = result;
|
|
27
|
+
const hiveId = result.hiveId ?? flexResult.id ?? 'default';
|
|
28
|
+
const status = result.status ?? (flexResult.initialized ? 'running' : 'stopped');
|
|
29
|
+
const queen = result.queen ?? { id: 'N/A', status: 'unknown', load: 0, tasksQueued: 0 };
|
|
30
|
+
const flexQueen = queen;
|
|
31
|
+
const queenId = typeof queen === 'object' ? (queen.id ?? flexQueen.agentId ?? 'N/A') : String(queen);
|
|
32
|
+
const queenLoad = typeof queen === 'object' ? (queen.load ?? 0) : 0;
|
|
33
|
+
const queenTasks = typeof queen === 'object' ? (queen.tasksQueued ?? 0) : 0;
|
|
34
|
+
const queenStatus = typeof queen === 'object' ? (queen.status ?? 'active') : 'active';
|
|
35
|
+
output.writeln();
|
|
36
|
+
output.printBox([
|
|
37
|
+
`Hive ID: ${hiveId}`,
|
|
38
|
+
`Status: ${formatHiveStatus(String(status))}`,
|
|
39
|
+
`Topology: ${result.topology ?? 'mesh'}`,
|
|
40
|
+
`Consensus: ${result.consensus ?? 'byzantine'}`,
|
|
41
|
+
'',
|
|
42
|
+
`Queen: ${queenId}`,
|
|
43
|
+
` Status: ${formatAgentStatus(queenStatus)}`,
|
|
44
|
+
` Load: ${(queenLoad * 100).toFixed(1)}%`,
|
|
45
|
+
` Queued Tasks: ${queenTasks}`
|
|
46
|
+
].join('\n'), 'Hive Mind Status');
|
|
47
|
+
const workers = result.workers ?? [];
|
|
48
|
+
const workerData = Array.isArray(workers) ? workers.map(w => {
|
|
49
|
+
if (typeof w === 'string') {
|
|
50
|
+
return { id: w, type: 'worker', status: 'idle', currentTask: '-', tasksCompleted: 0 };
|
|
51
|
+
}
|
|
52
|
+
const flexWorker = w;
|
|
53
|
+
return {
|
|
54
|
+
id: w.id ?? flexWorker.agentId ?? 'unknown',
|
|
55
|
+
type: w.type ?? flexWorker.agentType ?? 'worker',
|
|
56
|
+
status: w.status ?? 'idle',
|
|
57
|
+
currentTask: w.currentTask ?? '-',
|
|
58
|
+
tasksCompleted: w.tasksCompleted ?? 0
|
|
59
|
+
};
|
|
60
|
+
}) : [];
|
|
61
|
+
output.writeln();
|
|
62
|
+
output.writeln(output.bold('Worker Agents'));
|
|
63
|
+
if (workerData.length === 0) {
|
|
64
|
+
output.printInfo('No workers in hive. Use "monomind hive-mind spawn" to add workers.');
|
|
65
|
+
}
|
|
66
|
+
else {
|
|
67
|
+
output.printTable({
|
|
68
|
+
columns: [
|
|
69
|
+
{ key: 'id', header: 'ID', width: 20 },
|
|
70
|
+
{ key: 'type', header: 'Type', width: 12 },
|
|
71
|
+
{ key: 'status', header: 'Status', width: 10, format: formatAgentStatus },
|
|
72
|
+
{ key: 'currentTask', header: 'Current Task', width: 20, format: (v) => String(v || '-') },
|
|
73
|
+
{ key: 'tasksCompleted', header: 'Completed', width: 10, align: 'right' }
|
|
74
|
+
],
|
|
75
|
+
data: workerData
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
if (detailed) {
|
|
79
|
+
const metrics = result.metrics ?? { totalTasks: 0, completedTasks: 0, failedTasks: 0, avgTaskTime: 0, consensusRounds: 0, memoryUsage: '0 MB' };
|
|
80
|
+
output.writeln();
|
|
81
|
+
output.writeln(output.bold('Metrics'));
|
|
82
|
+
output.printTable({
|
|
83
|
+
columns: [
|
|
84
|
+
{ key: 'metric', header: 'Metric', width: 20 },
|
|
85
|
+
{ key: 'value', header: 'Value', width: 15, align: 'right' }
|
|
86
|
+
],
|
|
87
|
+
data: [
|
|
88
|
+
{ metric: 'Total Tasks', value: metrics.totalTasks ?? 0 },
|
|
89
|
+
{ metric: 'Completed', value: metrics.completedTasks ?? 0 },
|
|
90
|
+
{ metric: 'Failed', value: metrics.failedTasks ?? 0 },
|
|
91
|
+
{ metric: 'Avg Task Time', value: `${(metrics.avgTaskTime ?? 0).toFixed(1)}ms` },
|
|
92
|
+
{ metric: 'Consensus Rounds', value: metrics.consensusRounds ?? 0 },
|
|
93
|
+
{ metric: 'Memory Usage', value: metrics.memoryUsage ?? '0 MB' }
|
|
94
|
+
]
|
|
95
|
+
});
|
|
96
|
+
const health = result.health ?? { overall: 'healthy', queen: 'healthy', workers: 'healthy', consensus: 'healthy', memory: 'healthy' };
|
|
97
|
+
output.writeln();
|
|
98
|
+
output.writeln(output.bold('Health'));
|
|
99
|
+
output.printList([
|
|
100
|
+
`Overall: ${formatHealth(health.overall ?? 'healthy')}`,
|
|
101
|
+
`Queen: ${formatHealth(health.queen ?? 'healthy')}`,
|
|
102
|
+
`Workers: ${formatHealth(health.workers ?? 'healthy')}`,
|
|
103
|
+
`Consensus: ${formatHealth(health.consensus ?? 'healthy')}`,
|
|
104
|
+
`Memory: ${formatHealth(health.memory ?? 'healthy')}`
|
|
105
|
+
]);
|
|
106
|
+
}
|
|
107
|
+
return { success: true, data: result };
|
|
108
|
+
}
|
|
109
|
+
catch (error) {
|
|
110
|
+
if (error instanceof MCPClientError) {
|
|
111
|
+
output.printError(`Status error: ${error.message}`);
|
|
112
|
+
}
|
|
113
|
+
else {
|
|
114
|
+
output.printError(`Unexpected error: ${String(error)}`);
|
|
115
|
+
}
|
|
116
|
+
return { success: false, exitCode: 1 };
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
export const taskCommand = {
|
|
121
|
+
name: 'task',
|
|
122
|
+
description: 'Submit tasks to the hive',
|
|
123
|
+
options: [
|
|
124
|
+
{ name: 'description', short: 'd', description: 'Task description', type: 'string' },
|
|
125
|
+
{ name: 'priority', short: 'p', description: 'Task priority', type: 'string', choices: ['low', 'normal', 'high', 'critical'], default: 'normal' },
|
|
126
|
+
{ name: 'require-consensus', short: 'c', description: 'Require consensus for completion', type: 'boolean', default: false },
|
|
127
|
+
{ name: 'timeout', description: 'Task timeout in seconds', type: 'number', default: 300 }
|
|
128
|
+
],
|
|
129
|
+
examples: [
|
|
130
|
+
{ command: 'monomind hive-mind task -d "Implement auth module"', description: 'Submit task' },
|
|
131
|
+
{ command: 'monomind hive-mind task -d "Security review" -p critical -c', description: 'Critical task with consensus' }
|
|
132
|
+
],
|
|
133
|
+
action: async (ctx) => {
|
|
134
|
+
let description = (ctx.flags.description || ctx.args.join(' ')).slice(0, MAX_TASK_DESC_LEN);
|
|
135
|
+
if (!description && ctx.interactive) {
|
|
136
|
+
description = await input({
|
|
137
|
+
message: 'Task description:',
|
|
138
|
+
validate: (v) => v.length > 0 || 'Description is required'
|
|
139
|
+
});
|
|
140
|
+
description = description.slice(0, MAX_TASK_DESC_LEN);
|
|
141
|
+
}
|
|
142
|
+
if (!description) {
|
|
143
|
+
output.printError('Task description is required');
|
|
144
|
+
return { success: false, exitCode: 1 };
|
|
145
|
+
}
|
|
146
|
+
const priority = ctx.flags.priority;
|
|
147
|
+
const requireConsensus = ctx.flags['require-consensus'];
|
|
148
|
+
const timeout = ctx.flags.timeout;
|
|
149
|
+
output.printInfo('Submitting task to hive...');
|
|
150
|
+
try {
|
|
151
|
+
const result = await callMCPTool('hive-mind_task', { description, priority, requireConsensus, timeout });
|
|
152
|
+
if (ctx.flags.format === 'json') {
|
|
153
|
+
output.printJson(result);
|
|
154
|
+
return { success: true, data: result };
|
|
155
|
+
}
|
|
156
|
+
output.writeln();
|
|
157
|
+
output.printBox([
|
|
158
|
+
`Task ID: ${result.taskId}`,
|
|
159
|
+
`Status: ${formatAgentStatus(result.status)}`,
|
|
160
|
+
`Priority: ${formatPriority(priority)}`,
|
|
161
|
+
`Assigned: ${result.assignedTo.join(', ')}`,
|
|
162
|
+
`Consensus: ${result.requiresConsensus ? 'Yes' : 'No'}`,
|
|
163
|
+
`Est. Time: ${result.estimatedTime}`
|
|
164
|
+
].join('\n'), 'Task Submitted');
|
|
165
|
+
output.writeln();
|
|
166
|
+
output.printSuccess('Task submitted to hive');
|
|
167
|
+
output.writeln(output.dim(` Track with: monomind hive-mind task-status ${result.taskId}`));
|
|
168
|
+
return { success: true, data: result };
|
|
169
|
+
}
|
|
170
|
+
catch (error) {
|
|
171
|
+
if (error instanceof MCPClientError) {
|
|
172
|
+
output.printError(`Task submission error: ${error.message}`);
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
output.printError(`Unexpected error: ${String(error)}`);
|
|
176
|
+
}
|
|
177
|
+
return { success: false, exitCode: 1 };
|
|
178
|
+
}
|
|
179
|
+
}
|
|
180
|
+
};
|
|
181
|
+
export const optimizeMemoryCommand = {
|
|
182
|
+
name: 'optimize-memory',
|
|
183
|
+
description: 'Optimize hive memory and patterns',
|
|
184
|
+
options: [
|
|
185
|
+
{ name: 'aggressive', short: 'a', description: 'Aggressive optimization', type: 'boolean', default: false },
|
|
186
|
+
{ name: 'threshold', description: 'Quality threshold for pattern retention', type: 'number', default: 0.7 }
|
|
187
|
+
],
|
|
188
|
+
action: async (ctx) => {
|
|
189
|
+
const aggressive = ctx.flags.aggressive;
|
|
190
|
+
const threshold = ctx.flags.threshold;
|
|
191
|
+
output.printInfo('Optimizing hive memory...');
|
|
192
|
+
const spinner = output.createSpinner({ text: 'Analyzing patterns...', spinner: 'dots' });
|
|
193
|
+
spinner.start();
|
|
194
|
+
try {
|
|
195
|
+
const result = await callMCPTool('hive-mind_optimize-memory', { aggressive, qualityThreshold: threshold });
|
|
196
|
+
spinner.succeed('Memory optimized');
|
|
197
|
+
if (ctx.flags.format === 'json') {
|
|
198
|
+
output.printJson(result);
|
|
199
|
+
return { success: true, data: result };
|
|
200
|
+
}
|
|
201
|
+
output.writeln();
|
|
202
|
+
output.printTable({
|
|
203
|
+
columns: [
|
|
204
|
+
{ key: 'metric', header: 'Metric', width: 20 },
|
|
205
|
+
{ key: 'before', header: 'Before', width: 15, align: 'right' },
|
|
206
|
+
{ key: 'after', header: 'After', width: 15, align: 'right' }
|
|
207
|
+
],
|
|
208
|
+
data: [
|
|
209
|
+
{ metric: 'Patterns', before: result.before.patterns, after: result.after.patterns },
|
|
210
|
+
{ metric: 'Memory', before: result.before.memory, after: result.after.memory }
|
|
211
|
+
]
|
|
212
|
+
});
|
|
213
|
+
output.writeln();
|
|
214
|
+
output.printList([
|
|
215
|
+
`Patterns removed: ${result.removed}`,
|
|
216
|
+
`Patterns consolidated: ${result.consolidated}`,
|
|
217
|
+
`Optimization time: ${result.timeMs}ms`
|
|
218
|
+
]);
|
|
219
|
+
return { success: true, data: result };
|
|
220
|
+
}
|
|
221
|
+
catch (error) {
|
|
222
|
+
spinner.fail('Optimization failed');
|
|
223
|
+
if (error instanceof MCPClientError) {
|
|
224
|
+
output.printError(`Optimization error: ${error.message}`);
|
|
225
|
+
}
|
|
226
|
+
else {
|
|
227
|
+
output.printError(`Unexpected error: ${String(error)}`);
|
|
228
|
+
}
|
|
229
|
+
return { success: false, exitCode: 1 };
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
};
|
|
233
|
+
//# sourceMappingURL=hive-mind-ops.js.map
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive Mind spawn infrastructure — spawnClaudeCodeInstance and spawnCommand
|
|
3
|
+
*/
|
|
4
|
+
import type { Command } from '../types.js';
|
|
5
|
+
import { type HiveWorker } from './hive-mind-helpers.js';
|
|
6
|
+
export declare function spawnClaudeCodeInstance(swarmId: string, swarmName: string, objective: string, workers: HiveWorker[], flags: Record<string, unknown>): Promise<{
|
|
7
|
+
success: boolean;
|
|
8
|
+
promptFile?: string;
|
|
9
|
+
error?: string;
|
|
10
|
+
}>;
|
|
11
|
+
export declare const spawnCommand: Command;
|
|
12
|
+
//# sourceMappingURL=hive-mind-spawn.d.ts.map
|
|
@@ -0,0 +1,274 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive Mind spawn infrastructure — spawnClaudeCodeInstance and spawnCommand
|
|
3
|
+
*/
|
|
4
|
+
import { output } from '../output.js';
|
|
5
|
+
import { input } from '../prompt.js';
|
|
6
|
+
import { callMCPTool, MCPClientError } from '../mcp-client.js';
|
|
7
|
+
import { spawn as childSpawn, execSync } from 'child_process';
|
|
8
|
+
import { mkdir, writeFile } from 'fs/promises';
|
|
9
|
+
import { join, resolve as resolvePath, sep } from 'path';
|
|
10
|
+
import { MAX_OBJECTIVE_LEN, groupWorkersByType, generateHiveMindPrompt, formatAgentStatus, } from './hive-mind-helpers.js';
|
|
11
|
+
export async function spawnClaudeCodeInstance(swarmId, swarmName, objective, workers, flags) {
|
|
12
|
+
output.writeln();
|
|
13
|
+
output.writeln(output.bold('🚀 Launching Claude Code with Hive Mind Coordination'));
|
|
14
|
+
output.writeln(output.dim('─'.repeat(60)));
|
|
15
|
+
const spinner = output.createSpinner({ text: 'Preparing Hive Mind coordination prompt...', spinner: 'dots' });
|
|
16
|
+
spinner.start();
|
|
17
|
+
try {
|
|
18
|
+
const workerGroups = groupWorkersByType(workers);
|
|
19
|
+
const hiveMindPrompt = generateHiveMindPrompt(swarmId, swarmName, objective, workers, workerGroups, flags);
|
|
20
|
+
spinner.succeed('Hive Mind coordination prompt ready!');
|
|
21
|
+
output.writeln();
|
|
22
|
+
output.writeln(output.bold('🧠 Hive Mind Configuration'));
|
|
23
|
+
output.writeln(output.dim('─'.repeat(60)));
|
|
24
|
+
output.printList([
|
|
25
|
+
`Swarm ID: ${output.highlight(swarmId)}`,
|
|
26
|
+
`Objective: ${output.highlight(objective)}`,
|
|
27
|
+
`Queen Type: ${output.highlight(flags.queenType || 'strategic')}`,
|
|
28
|
+
`Worker Count: ${output.highlight(String(workers.length))}`,
|
|
29
|
+
`Worker Types: ${output.highlight(Object.keys(workerGroups).join(', '))}`,
|
|
30
|
+
`Consensus: ${output.highlight(flags.consensus || 'byzantine')}`,
|
|
31
|
+
`MCP Tools: ${output.success('Full Monomind integration enabled')}`
|
|
32
|
+
]);
|
|
33
|
+
// Ensure sessions directory exists, anchored to cwd to prevent traversal
|
|
34
|
+
const baseDir = resolvePath(process.cwd());
|
|
35
|
+
const sessionsDir = resolvePath(baseDir, '.hive-mind', 'sessions');
|
|
36
|
+
if (!sessionsDir.startsWith(baseDir + sep) && sessionsDir !== baseDir) {
|
|
37
|
+
throw new Error('Sessions directory path traversal detected');
|
|
38
|
+
}
|
|
39
|
+
await mkdir(sessionsDir, { recursive: true });
|
|
40
|
+
const safeSwarmId = swarmId.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
41
|
+
const promptFile = join(sessionsDir, `hive-mind-prompt-${safeSwarmId}.txt`);
|
|
42
|
+
if (!resolvePath(promptFile).startsWith(sessionsDir + sep)) {
|
|
43
|
+
throw new Error('Prompt file path traversal detected');
|
|
44
|
+
}
|
|
45
|
+
await writeFile(promptFile, hiveMindPrompt, 'utf8');
|
|
46
|
+
output.writeln();
|
|
47
|
+
output.printSuccess(`Hive Mind prompt saved to: ${promptFile}`);
|
|
48
|
+
let claudeAvailable = false;
|
|
49
|
+
try {
|
|
50
|
+
execSync('which claude', { stdio: 'ignore' });
|
|
51
|
+
claudeAvailable = true;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
output.writeln();
|
|
55
|
+
output.printWarning('Claude Code CLI not found in PATH');
|
|
56
|
+
output.writeln(output.dim('Install it with: npm install -g @anthropic-ai/claude-code'));
|
|
57
|
+
output.writeln(output.dim('Falling back to displaying instructions...'));
|
|
58
|
+
}
|
|
59
|
+
const dryRun = flags.dryRun || flags['dry-run'];
|
|
60
|
+
if (claudeAvailable && !dryRun) {
|
|
61
|
+
const claudeArgs = [];
|
|
62
|
+
const isNonInteractive = flags['non-interactive'] || flags.nonInteractive;
|
|
63
|
+
if (isNonInteractive) {
|
|
64
|
+
claudeArgs.push('-p');
|
|
65
|
+
claudeArgs.push('--output-format', 'stream-json');
|
|
66
|
+
claudeArgs.push('--verbose');
|
|
67
|
+
output.printInfo('Running in non-interactive mode');
|
|
68
|
+
}
|
|
69
|
+
const skipPermissions = flags['dangerously-skip-permissions'] === true && !flags['no-auto-permissions'];
|
|
70
|
+
if (skipPermissions) {
|
|
71
|
+
claudeArgs.push('--dangerously-skip-permissions');
|
|
72
|
+
output.writeln(output.warning('WARNING: Running with --dangerously-skip-permissions: all file and shell operations will execute without prompts.'));
|
|
73
|
+
}
|
|
74
|
+
claudeArgs.push('--');
|
|
75
|
+
claudeArgs.push(hiveMindPrompt);
|
|
76
|
+
output.writeln();
|
|
77
|
+
output.printInfo('Launching Claude Code...');
|
|
78
|
+
output.writeln(output.dim('Press Ctrl+C to pause the session'));
|
|
79
|
+
const claudeProcess = childSpawn('claude', claudeArgs, {
|
|
80
|
+
stdio: 'inherit',
|
|
81
|
+
shell: false,
|
|
82
|
+
});
|
|
83
|
+
let isExiting = false;
|
|
84
|
+
const sigintHandler = () => {
|
|
85
|
+
if (isExiting)
|
|
86
|
+
return;
|
|
87
|
+
isExiting = true;
|
|
88
|
+
output.writeln();
|
|
89
|
+
output.writeln();
|
|
90
|
+
output.printWarning('Pausing session and terminating Claude Code...');
|
|
91
|
+
if (claudeProcess && !claudeProcess.killed) {
|
|
92
|
+
claudeProcess.kill('SIGTERM');
|
|
93
|
+
}
|
|
94
|
+
output.writeln();
|
|
95
|
+
output.printSuccess('Session paused');
|
|
96
|
+
output.writeln(output.dim(`Prompt file saved at: ${promptFile}`));
|
|
97
|
+
output.writeln(output.dim('To resume, run claude with the saved prompt file'));
|
|
98
|
+
process.exit(0);
|
|
99
|
+
};
|
|
100
|
+
process.on('SIGINT', sigintHandler);
|
|
101
|
+
process.on('SIGTERM', sigintHandler);
|
|
102
|
+
claudeProcess.on('exit', (code) => {
|
|
103
|
+
process.removeListener('SIGINT', sigintHandler);
|
|
104
|
+
process.removeListener('SIGTERM', sigintHandler);
|
|
105
|
+
if (code === 0) {
|
|
106
|
+
output.writeln();
|
|
107
|
+
output.printSuccess('Claude Code completed successfully');
|
|
108
|
+
}
|
|
109
|
+
else if (code !== null) {
|
|
110
|
+
output.writeln();
|
|
111
|
+
output.printError(`Claude Code exited with code ${code}`);
|
|
112
|
+
}
|
|
113
|
+
});
|
|
114
|
+
output.writeln();
|
|
115
|
+
output.printSuccess('Claude Code launched with Hive Mind coordination');
|
|
116
|
+
output.printInfo('The Queen coordinator will orchestrate all worker agents');
|
|
117
|
+
output.writeln(output.dim(`Prompt file saved at: ${promptFile}`));
|
|
118
|
+
return { success: true, promptFile };
|
|
119
|
+
}
|
|
120
|
+
else if (dryRun) {
|
|
121
|
+
output.writeln();
|
|
122
|
+
output.printInfo('Dry run - would execute Claude Code with prompt:');
|
|
123
|
+
output.writeln(output.dim(`Prompt length: ${hiveMindPrompt.length} characters`));
|
|
124
|
+
output.writeln();
|
|
125
|
+
output.writeln(output.dim('First 500 characters of prompt:'));
|
|
126
|
+
output.writeln(output.highlight(hiveMindPrompt.substring(0, 500) + '...'));
|
|
127
|
+
output.writeln();
|
|
128
|
+
output.writeln(output.dim(`Full prompt saved to: ${promptFile}`));
|
|
129
|
+
return { success: true, promptFile };
|
|
130
|
+
}
|
|
131
|
+
else {
|
|
132
|
+
output.writeln();
|
|
133
|
+
output.writeln(output.bold('📋 Manual Execution Instructions:'));
|
|
134
|
+
output.writeln(output.dim('─'.repeat(50)));
|
|
135
|
+
output.printList([
|
|
136
|
+
'Install Claude Code: npm install -g @anthropic-ai/claude-code',
|
|
137
|
+
`Run with saved prompt: claude < ${promptFile}`,
|
|
138
|
+
`Or copy manually: cat ${promptFile} | claude`,
|
|
139
|
+
`With auto-permissions: claude --dangerously-skip-permissions < ${promptFile}`
|
|
140
|
+
]);
|
|
141
|
+
return { success: true, promptFile };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
catch (error) {
|
|
145
|
+
spinner.fail('Failed to prepare Claude Code coordination');
|
|
146
|
+
const errorMessage = error instanceof Error ? error.message : String(error);
|
|
147
|
+
output.printError(`Error: ${errorMessage}`);
|
|
148
|
+
try {
|
|
149
|
+
const safeSwarmIdFallback = swarmId.replace(/[^a-zA-Z0-9_-]/g, '_');
|
|
150
|
+
const fallbackDir = resolvePath(process.cwd());
|
|
151
|
+
const promptFile = join(fallbackDir, `hive-mind-prompt-${safeSwarmIdFallback}-fallback.txt`);
|
|
152
|
+
if (!resolvePath(promptFile).startsWith(fallbackDir + sep)) {
|
|
153
|
+
throw new Error('Fallback path traversal');
|
|
154
|
+
}
|
|
155
|
+
const workerGroups = groupWorkersByType(workers);
|
|
156
|
+
const hiveMindPrompt = generateHiveMindPrompt(swarmId, swarmName, objective, workers, workerGroups, flags);
|
|
157
|
+
await writeFile(promptFile, hiveMindPrompt, 'utf8');
|
|
158
|
+
output.writeln();
|
|
159
|
+
output.printSuccess(`Prompt saved to: ${promptFile}`);
|
|
160
|
+
output.writeln(output.dim('You can run Claude Code manually with the saved prompt'));
|
|
161
|
+
return { success: false, promptFile, error: errorMessage };
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return { success: false, error: errorMessage };
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export const spawnCommand = {
|
|
169
|
+
name: 'spawn',
|
|
170
|
+
description: 'Spawn worker agents into the hive (use --claude to launch Claude Code)',
|
|
171
|
+
options: [
|
|
172
|
+
{ name: 'count', short: 'n', description: 'Number of workers to spawn', type: 'number', default: 1 },
|
|
173
|
+
{ name: 'role', short: 'r', description: 'Worker role (worker, specialist, scout)', type: 'string', choices: ['worker', 'specialist', 'scout'], default: 'worker' },
|
|
174
|
+
{ name: 'type', short: 't', description: 'Agent type', type: 'string', default: 'worker' },
|
|
175
|
+
{ name: 'prefix', short: 'p', description: 'Prefix for worker IDs', type: 'string', default: 'hive-worker' },
|
|
176
|
+
{ name: 'claude', description: 'Launch Claude Code with hive-mind coordination prompt', type: 'boolean', default: false },
|
|
177
|
+
{ name: 'objective', short: 'o', description: 'Objective for the hive mind (used with --claude)', type: 'string' },
|
|
178
|
+
{ name: 'dangerously-skip-permissions', description: 'Skip permission prompts in Claude Code (use with caution)', type: 'boolean', default: false },
|
|
179
|
+
{ name: 'no-auto-permissions', description: 'Disable automatic permission skipping', type: 'boolean', default: false },
|
|
180
|
+
{ name: 'dry-run', description: 'Show what would be done without launching Claude Code', type: 'boolean', default: false },
|
|
181
|
+
{ name: 'non-interactive', description: 'Run Claude Code in non-interactive mode', type: 'boolean', default: false }
|
|
182
|
+
],
|
|
183
|
+
examples: [
|
|
184
|
+
{ command: 'monomind hive-mind spawn -n 5', description: 'Spawn 5 workers' },
|
|
185
|
+
{ command: 'monomind hive-mind spawn -n 3 -r specialist', description: 'Spawn 3 specialists' },
|
|
186
|
+
{ command: 'monomind hive-mind spawn -t coder -p my-coder', description: 'Spawn coder with custom prefix' },
|
|
187
|
+
{ command: 'monomind hive-mind spawn --claude -o "Build a REST API"', description: 'Launch Claude Code with objective' },
|
|
188
|
+
{ command: 'monomind hive-mind spawn -n 5 --claude -o "Research AI patterns"', description: 'Spawn workers and launch Claude Code' }
|
|
189
|
+
],
|
|
190
|
+
action: async (ctx) => {
|
|
191
|
+
const rawCount = ctx.flags.count || 1;
|
|
192
|
+
const count = Number.isFinite(rawCount) ? Math.max(1, Math.min(rawCount, 50)) : 1;
|
|
193
|
+
const role = ctx.flags.role || 'worker';
|
|
194
|
+
const agentType = ctx.flags.type || 'worker';
|
|
195
|
+
const prefix = ctx.flags.prefix || 'hive-worker';
|
|
196
|
+
const launchClaude = ctx.flags.claude;
|
|
197
|
+
let objective = (ctx.flags.objective || ctx.args.join(' ')).slice(0, MAX_OBJECTIVE_LEN);
|
|
198
|
+
output.printInfo(`Spawning ${count} ${role} agent(s)...`);
|
|
199
|
+
try {
|
|
200
|
+
const result = await callMCPTool('hive-mind_spawn', { count, role, agentType, prefix });
|
|
201
|
+
if (!result.success) {
|
|
202
|
+
output.printError(result.error || 'Failed to spawn workers');
|
|
203
|
+
return { success: false, exitCode: 1 };
|
|
204
|
+
}
|
|
205
|
+
if (ctx.flags.format === 'json' && !launchClaude) {
|
|
206
|
+
output.printJson(result);
|
|
207
|
+
return { success: true, data: result };
|
|
208
|
+
}
|
|
209
|
+
output.writeln();
|
|
210
|
+
const displayData = (result.workers || []).map(w => ({
|
|
211
|
+
id: w.agentId,
|
|
212
|
+
role: w.role,
|
|
213
|
+
status: 'idle',
|
|
214
|
+
joinedAt: new Date(w.joinedAt).toLocaleTimeString()
|
|
215
|
+
}));
|
|
216
|
+
output.printTable({
|
|
217
|
+
columns: [
|
|
218
|
+
{ key: 'id', header: 'Agent ID', width: 30 },
|
|
219
|
+
{ key: 'role', header: 'Role', width: 12 },
|
|
220
|
+
{ key: 'status', header: 'Status', width: 10, format: formatAgentStatus },
|
|
221
|
+
{ key: 'joinedAt', header: 'Joined', width: 12 }
|
|
222
|
+
],
|
|
223
|
+
data: displayData
|
|
224
|
+
});
|
|
225
|
+
output.writeln();
|
|
226
|
+
output.printSuccess(`Spawned ${result.spawned} agent(s)`);
|
|
227
|
+
output.writeln(output.dim(` Total workers in hive: ${result.totalWorkers}`));
|
|
228
|
+
if (launchClaude) {
|
|
229
|
+
if (!objective && ctx.interactive) {
|
|
230
|
+
objective = await input({
|
|
231
|
+
message: 'Enter the objective for the hive mind:',
|
|
232
|
+
validate: (v) => v.length > 0 || 'Objective is required when using --claude'
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
if (!objective) {
|
|
236
|
+
output.writeln();
|
|
237
|
+
output.printWarning('No objective provided. Using default objective.');
|
|
238
|
+
objective = 'Coordinate the hive mind workers to complete tasks efficiently.';
|
|
239
|
+
}
|
|
240
|
+
let swarmId = result.hiveId || 'default';
|
|
241
|
+
const swarmName = 'Hive Mind Swarm';
|
|
242
|
+
try {
|
|
243
|
+
const statusResult = await callMCPTool('hive-mind_status', { includeWorkers: false });
|
|
244
|
+
swarmId = statusResult.hiveId || swarmId;
|
|
245
|
+
}
|
|
246
|
+
catch {
|
|
247
|
+
// Use defaults if status call fails
|
|
248
|
+
}
|
|
249
|
+
const workers = (result.workers || []).map(w => ({
|
|
250
|
+
agentId: w.agentId,
|
|
251
|
+
role: w.role,
|
|
252
|
+
type: agentType,
|
|
253
|
+
joinedAt: w.joinedAt
|
|
254
|
+
}));
|
|
255
|
+
const claudeResult = await spawnClaudeCodeInstance(swarmId, swarmName, objective, workers, ctx.flags);
|
|
256
|
+
if (!claudeResult.success) {
|
|
257
|
+
return { success: false, exitCode: 1, data: { spawn: result, claude: claudeResult } };
|
|
258
|
+
}
|
|
259
|
+
return { success: true, data: { spawn: result, claude: claudeResult } };
|
|
260
|
+
}
|
|
261
|
+
return { success: true, data: result };
|
|
262
|
+
}
|
|
263
|
+
catch (error) {
|
|
264
|
+
if (error instanceof MCPClientError) {
|
|
265
|
+
output.printError(`Spawn error: ${error.message}`);
|
|
266
|
+
}
|
|
267
|
+
else {
|
|
268
|
+
output.printError(`Unexpected error: ${String(error)}`);
|
|
269
|
+
}
|
|
270
|
+
return { success: false, exitCode: 1 };
|
|
271
|
+
}
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
//# sourceMappingURL=hive-mind-spawn.js.map
|