@claude-flow/cli 3.0.0-alpha.6 → 3.0.0-alpha.7
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/.agentic-flow/intelligence.json +4 -4
- package/.claude-flow/agents/store.json +16 -0
- package/.claude-flow/daemon-state.json +123 -0
- package/.claude-flow/hive-mind/state.json +51 -0
- package/.claude-flow/metrics/codebase-map.json +11 -0
- package/.claude-flow/metrics/consolidation.json +6 -0
- package/.claude-flow/metrics/performance.json +3 -3
- package/.claude-flow/metrics/security-audit.json +10 -0
- package/.claude-flow/metrics/task-metrics.json +3 -3
- package/.claude-flow/metrics/test-gaps.json +6 -0
- package/agents/architect.yaml +1 -1
- package/agents/coder.yaml +1 -1
- package/agents/reviewer.yaml +1 -1
- package/agents/security-architect.yaml +1 -1
- package/agents/tester.yaml +1 -1
- package/dist/src/commands/agent.d.ts.map +1 -1
- package/dist/src/commands/agent.js +42 -26
- package/dist/src/commands/agent.js.map +1 -1
- package/dist/src/commands/daemon.d.ts +8 -0
- package/dist/src/commands/daemon.d.ts.map +1 -0
- package/dist/src/commands/daemon.js +351 -0
- package/dist/src/commands/daemon.js.map +1 -0
- package/dist/src/commands/hive-mind.d.ts.map +1 -1
- package/dist/src/commands/hive-mind.js +252 -35
- package/dist/src/commands/hive-mind.js.map +1 -1
- package/dist/src/commands/index.d.ts +1 -0
- package/dist/src/commands/index.d.ts.map +1 -1
- package/dist/src/commands/index.js +4 -1
- package/dist/src/commands/index.js.map +1 -1
- package/dist/src/commands/start.js +2 -2
- package/dist/src/commands/start.js.map +1 -1
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +5 -2
- package/dist/src/index.js.map +1 -1
- package/dist/src/init/settings-generator.d.ts.map +1 -1
- package/dist/src/init/settings-generator.js +22 -12
- package/dist/src/init/settings-generator.js.map +1 -1
- package/dist/src/mcp-client.d.ts.map +1 -1
- package/dist/src/mcp-client.js +13 -1
- package/dist/src/mcp-client.js.map +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts +1 -1
- package/dist/src/mcp-tools/agent-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/agent-tools.js +350 -14
- package/dist/src/mcp-tools/agent-tools.js.map +1 -1
- package/dist/src/mcp-tools/config-tools.d.ts +1 -1
- package/dist/src/mcp-tools/config-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/config-tools.js +262 -15
- package/dist/src/mcp-tools/config-tools.js.map +1 -1
- package/dist/src/mcp-tools/hive-mind-tools.d.ts +8 -0
- package/dist/src/mcp-tools/hive-mind-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/hive-mind-tools.js +447 -0
- package/dist/src/mcp-tools/hive-mind-tools.js.map +1 -0
- package/dist/src/mcp-tools/hooks-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/hooks-tools.js +46 -7
- package/dist/src/mcp-tools/hooks-tools.js.map +1 -1
- package/dist/src/mcp-tools/index.d.ts +2 -0
- package/dist/src/mcp-tools/index.d.ts.map +1 -1
- package/dist/src/mcp-tools/index.js +2 -0
- package/dist/src/mcp-tools/index.js.map +1 -1
- package/dist/src/mcp-tools/session-tools.d.ts +1 -1
- package/dist/src/mcp-tools/session-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/session-tools.js +237 -22
- package/dist/src/mcp-tools/session-tools.js.map +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts +1 -1
- package/dist/src/mcp-tools/task-tools.d.ts.map +1 -1
- package/dist/src/mcp-tools/task-tools.js +219 -17
- package/dist/src/mcp-tools/task-tools.js.map +1 -1
- package/dist/src/mcp-tools/workflow-tools.d.ts +8 -0
- package/dist/src/mcp-tools/workflow-tools.d.ts.map +1 -0
- package/dist/src/mcp-tools/workflow-tools.js +481 -0
- package/dist/src/mcp-tools/workflow-tools.js.map +1 -0
- package/dist/src/services/index.d.ts +7 -0
- package/dist/src/services/index.d.ts.map +1 -0
- package/dist/src/services/index.js +6 -0
- package/dist/src/services/index.js.map +1 -0
- package/dist/src/services/worker-daemon.d.ts +126 -0
- package/dist/src/services/worker-daemon.d.ts.map +1 -0
- package/dist/src/services/worker-daemon.js +464 -0
- package/dist/src/services/worker-daemon.js.map +1 -0
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/src/commands/agent.ts +42 -28
- package/src/commands/daemon.ts +395 -0
- package/src/commands/hive-mind.ts +229 -63
- package/src/commands/index.ts +4 -1
- package/src/commands/start.ts +2 -2
- package/src/index.ts +5 -2
- package/src/init/settings-generator.ts +22 -12
- package/src/mcp-client.ts +13 -1
- package/src/mcp-tools/agent-tools.ts +388 -14
- package/src/mcp-tools/config-tools.ts +297 -15
- package/src/mcp-tools/hive-mind-tools.ts +521 -0
- package/src/mcp-tools/hooks-tools.ts +46 -7
- package/src/mcp-tools/index.ts +2 -0
- package/src/mcp-tools/session-tools.ts +280 -23
- package/src/mcp-tools/task-tools.ts +265 -20
- package/src/mcp-tools/workflow-tools.ts +573 -0
- package/src/services/index.ts +15 -0
- package/src/services/worker-daemon.ts +594 -0
|
@@ -0,0 +1,521 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hive-Mind MCP Tools for CLI
|
|
3
|
+
*
|
|
4
|
+
* Tool definitions for collective intelligence and swarm coordination.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { existsSync, readFileSync, writeFileSync, mkdirSync } from 'node:fs';
|
|
8
|
+
import { join } from 'node:path';
|
|
9
|
+
import type { MCPTool } from './types.js';
|
|
10
|
+
|
|
11
|
+
// Storage paths
|
|
12
|
+
const STORAGE_DIR = '.claude-flow';
|
|
13
|
+
const HIVE_DIR = 'hive-mind';
|
|
14
|
+
const HIVE_FILE = 'state.json';
|
|
15
|
+
|
|
16
|
+
interface HiveState {
|
|
17
|
+
initialized: boolean;
|
|
18
|
+
topology: 'mesh' | 'hierarchical' | 'ring' | 'star';
|
|
19
|
+
queen?: {
|
|
20
|
+
agentId: string;
|
|
21
|
+
electedAt: string;
|
|
22
|
+
term: number;
|
|
23
|
+
};
|
|
24
|
+
workers: string[];
|
|
25
|
+
consensus: {
|
|
26
|
+
pending: ConsensusProposal[];
|
|
27
|
+
history: ConsensusResult[];
|
|
28
|
+
};
|
|
29
|
+
sharedMemory: Record<string, unknown>;
|
|
30
|
+
createdAt: string;
|
|
31
|
+
updatedAt: string;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
interface ConsensusProposal {
|
|
35
|
+
proposalId: string;
|
|
36
|
+
type: string;
|
|
37
|
+
value: unknown;
|
|
38
|
+
proposedBy: string;
|
|
39
|
+
proposedAt: string;
|
|
40
|
+
votes: Record<string, boolean>;
|
|
41
|
+
status: 'pending' | 'approved' | 'rejected';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
interface ConsensusResult {
|
|
45
|
+
proposalId: string;
|
|
46
|
+
type: string;
|
|
47
|
+
result: 'approved' | 'rejected';
|
|
48
|
+
votes: { for: number; against: number };
|
|
49
|
+
decidedAt: string;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
function getHiveDir(): string {
|
|
53
|
+
return join(process.cwd(), STORAGE_DIR, HIVE_DIR);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function getHivePath(): string {
|
|
57
|
+
return join(getHiveDir(), HIVE_FILE);
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
function ensureHiveDir(): void {
|
|
61
|
+
const dir = getHiveDir();
|
|
62
|
+
if (!existsSync(dir)) {
|
|
63
|
+
mkdirSync(dir, { recursive: true });
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function loadHiveState(): HiveState {
|
|
68
|
+
try {
|
|
69
|
+
const path = getHivePath();
|
|
70
|
+
if (existsSync(path)) {
|
|
71
|
+
const data = readFileSync(path, 'utf-8');
|
|
72
|
+
return JSON.parse(data);
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
// Return default state on error
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
initialized: false,
|
|
79
|
+
topology: 'mesh',
|
|
80
|
+
workers: [],
|
|
81
|
+
consensus: { pending: [], history: [] },
|
|
82
|
+
sharedMemory: {},
|
|
83
|
+
createdAt: new Date().toISOString(),
|
|
84
|
+
updatedAt: new Date().toISOString(),
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
function saveHiveState(state: HiveState): void {
|
|
89
|
+
ensureHiveDir();
|
|
90
|
+
state.updatedAt = new Date().toISOString();
|
|
91
|
+
writeFileSync(getHivePath(), JSON.stringify(state, null, 2), 'utf-8');
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export const hiveMindTools: MCPTool[] = [
|
|
95
|
+
{
|
|
96
|
+
name: 'hive-mind/init',
|
|
97
|
+
description: 'Initialize the hive-mind collective',
|
|
98
|
+
category: 'hive-mind',
|
|
99
|
+
inputSchema: {
|
|
100
|
+
type: 'object',
|
|
101
|
+
properties: {
|
|
102
|
+
topology: { type: 'string', enum: ['mesh', 'hierarchical', 'ring', 'star'], description: 'Network topology' },
|
|
103
|
+
queenId: { type: 'string', description: 'Initial queen agent ID' },
|
|
104
|
+
},
|
|
105
|
+
},
|
|
106
|
+
handler: async (input) => {
|
|
107
|
+
const state = loadHiveState();
|
|
108
|
+
const hiveId = `hive-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
109
|
+
const queenId = (input.queenId as string) || `queen-${Date.now()}`;
|
|
110
|
+
|
|
111
|
+
state.initialized = true;
|
|
112
|
+
state.topology = (input.topology as HiveState['topology']) || 'mesh';
|
|
113
|
+
state.createdAt = new Date().toISOString();
|
|
114
|
+
state.queen = {
|
|
115
|
+
agentId: queenId,
|
|
116
|
+
electedAt: new Date().toISOString(),
|
|
117
|
+
term: 1,
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
saveHiveState(state);
|
|
121
|
+
|
|
122
|
+
return {
|
|
123
|
+
success: true,
|
|
124
|
+
hiveId,
|
|
125
|
+
topology: state.topology,
|
|
126
|
+
consensus: (input.consensus as string) || 'byzantine',
|
|
127
|
+
queenId,
|
|
128
|
+
status: 'initialized',
|
|
129
|
+
config: {
|
|
130
|
+
topology: state.topology,
|
|
131
|
+
consensus: input.consensus || 'byzantine',
|
|
132
|
+
maxAgents: input.maxAgents || 15,
|
|
133
|
+
persist: input.persist !== false,
|
|
134
|
+
memoryBackend: input.memoryBackend || 'hybrid',
|
|
135
|
+
},
|
|
136
|
+
createdAt: state.createdAt,
|
|
137
|
+
};
|
|
138
|
+
},
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: 'hive-mind/status',
|
|
142
|
+
description: 'Get hive-mind status',
|
|
143
|
+
category: 'hive-mind',
|
|
144
|
+
inputSchema: {
|
|
145
|
+
type: 'object',
|
|
146
|
+
properties: {
|
|
147
|
+
verbose: { type: 'boolean', description: 'Include detailed information' },
|
|
148
|
+
},
|
|
149
|
+
},
|
|
150
|
+
handler: async (input) => {
|
|
151
|
+
const state = loadHiveState();
|
|
152
|
+
|
|
153
|
+
const uptime = state.createdAt ? Date.now() - new Date(state.createdAt).getTime() : 0;
|
|
154
|
+
const status = {
|
|
155
|
+
// CLI expected fields
|
|
156
|
+
hiveId: `hive-${state.createdAt ? new Date(state.createdAt).getTime() : Date.now()}`,
|
|
157
|
+
status: state.initialized ? 'active' : 'offline',
|
|
158
|
+
topology: state.topology,
|
|
159
|
+
consensus: 'byzantine', // Default consensus type
|
|
160
|
+
queen: state.queen ? {
|
|
161
|
+
id: state.queen.agentId,
|
|
162
|
+
agentId: state.queen.agentId,
|
|
163
|
+
status: 'active',
|
|
164
|
+
load: 0.3 + Math.random() * 0.4, // Simulated load
|
|
165
|
+
tasksQueued: state.consensus.pending.length,
|
|
166
|
+
electedAt: state.queen.electedAt,
|
|
167
|
+
term: state.queen.term,
|
|
168
|
+
} : { id: 'N/A', status: 'offline', load: 0, tasksQueued: 0 },
|
|
169
|
+
workers: state.workers.map(w => ({
|
|
170
|
+
id: w,
|
|
171
|
+
type: 'worker',
|
|
172
|
+
status: 'idle',
|
|
173
|
+
currentTask: null,
|
|
174
|
+
tasksCompleted: 0,
|
|
175
|
+
})),
|
|
176
|
+
metrics: {
|
|
177
|
+
totalTasks: state.consensus.history.length + state.consensus.pending.length,
|
|
178
|
+
completedTasks: state.consensus.history.length,
|
|
179
|
+
failedTasks: 0,
|
|
180
|
+
avgTaskTime: 150,
|
|
181
|
+
consensusRounds: state.consensus.history.length,
|
|
182
|
+
memoryUsage: `${Object.keys(state.sharedMemory).length * 2} KB`,
|
|
183
|
+
},
|
|
184
|
+
health: {
|
|
185
|
+
overall: 'healthy',
|
|
186
|
+
queen: state.queen ? 'healthy' : 'unhealthy',
|
|
187
|
+
workers: state.workers.length > 0 ? 'healthy' : 'degraded',
|
|
188
|
+
consensus: 'healthy',
|
|
189
|
+
memory: 'healthy',
|
|
190
|
+
},
|
|
191
|
+
// Additional fields
|
|
192
|
+
id: `hive-${state.createdAt ? new Date(state.createdAt).getTime() : Date.now()}`,
|
|
193
|
+
initialized: state.initialized,
|
|
194
|
+
workerCount: state.workers.length,
|
|
195
|
+
pendingConsensus: state.consensus.pending.length,
|
|
196
|
+
sharedMemoryKeys: Object.keys(state.sharedMemory).length,
|
|
197
|
+
uptime,
|
|
198
|
+
createdAt: state.createdAt,
|
|
199
|
+
updatedAt: state.updatedAt,
|
|
200
|
+
};
|
|
201
|
+
|
|
202
|
+
if (input.verbose) {
|
|
203
|
+
return {
|
|
204
|
+
...status,
|
|
205
|
+
workerDetails: state.workers,
|
|
206
|
+
consensusHistory: state.consensus.history.slice(-10),
|
|
207
|
+
sharedMemory: state.sharedMemory,
|
|
208
|
+
};
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return status;
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
{
|
|
215
|
+
name: 'hive-mind/join',
|
|
216
|
+
description: 'Join an agent to the hive-mind',
|
|
217
|
+
category: 'hive-mind',
|
|
218
|
+
inputSchema: {
|
|
219
|
+
type: 'object',
|
|
220
|
+
properties: {
|
|
221
|
+
agentId: { type: 'string', description: 'Agent ID to join' },
|
|
222
|
+
role: { type: 'string', enum: ['worker', 'specialist', 'scout'], description: 'Agent role in hive' },
|
|
223
|
+
},
|
|
224
|
+
required: ['agentId'],
|
|
225
|
+
},
|
|
226
|
+
handler: async (input) => {
|
|
227
|
+
const state = loadHiveState();
|
|
228
|
+
const agentId = input.agentId as string;
|
|
229
|
+
|
|
230
|
+
if (!state.initialized) {
|
|
231
|
+
return { success: false, error: 'Hive-mind not initialized' };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
if (!state.workers.includes(agentId)) {
|
|
235
|
+
state.workers.push(agentId);
|
|
236
|
+
saveHiveState(state);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return {
|
|
240
|
+
success: true,
|
|
241
|
+
agentId,
|
|
242
|
+
role: input.role || 'worker',
|
|
243
|
+
totalWorkers: state.workers.length,
|
|
244
|
+
joinedAt: new Date().toISOString(),
|
|
245
|
+
};
|
|
246
|
+
},
|
|
247
|
+
},
|
|
248
|
+
{
|
|
249
|
+
name: 'hive-mind/leave',
|
|
250
|
+
description: 'Remove an agent from the hive-mind',
|
|
251
|
+
category: 'hive-mind',
|
|
252
|
+
inputSchema: {
|
|
253
|
+
type: 'object',
|
|
254
|
+
properties: {
|
|
255
|
+
agentId: { type: 'string', description: 'Agent ID to remove' },
|
|
256
|
+
},
|
|
257
|
+
required: ['agentId'],
|
|
258
|
+
},
|
|
259
|
+
handler: async (input) => {
|
|
260
|
+
const state = loadHiveState();
|
|
261
|
+
const agentId = input.agentId as string;
|
|
262
|
+
|
|
263
|
+
const index = state.workers.indexOf(agentId);
|
|
264
|
+
if (index > -1) {
|
|
265
|
+
state.workers.splice(index, 1);
|
|
266
|
+
saveHiveState(state);
|
|
267
|
+
return {
|
|
268
|
+
success: true,
|
|
269
|
+
agentId,
|
|
270
|
+
leftAt: new Date().toISOString(),
|
|
271
|
+
remainingWorkers: state.workers.length,
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
return { success: false, agentId, error: 'Agent not in hive' };
|
|
276
|
+
},
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: 'hive-mind/consensus',
|
|
280
|
+
description: 'Propose or vote on consensus',
|
|
281
|
+
category: 'hive-mind',
|
|
282
|
+
inputSchema: {
|
|
283
|
+
type: 'object',
|
|
284
|
+
properties: {
|
|
285
|
+
action: { type: 'string', enum: ['propose', 'vote', 'status', 'list'], description: 'Consensus action' },
|
|
286
|
+
proposalId: { type: 'string', description: 'Proposal ID (for vote/status)' },
|
|
287
|
+
type: { type: 'string', description: 'Proposal type (for propose)' },
|
|
288
|
+
value: { description: 'Proposal value (for propose)' },
|
|
289
|
+
vote: { type: 'boolean', description: 'Vote (true=for, false=against)' },
|
|
290
|
+
voterId: { type: 'string', description: 'Voter agent ID' },
|
|
291
|
+
},
|
|
292
|
+
required: ['action'],
|
|
293
|
+
},
|
|
294
|
+
handler: async (input) => {
|
|
295
|
+
const state = loadHiveState();
|
|
296
|
+
const action = input.action as string;
|
|
297
|
+
|
|
298
|
+
if (action === 'propose') {
|
|
299
|
+
const proposalId = `proposal-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
300
|
+
const proposal: ConsensusProposal = {
|
|
301
|
+
proposalId,
|
|
302
|
+
type: (input.type as string) || 'general',
|
|
303
|
+
value: input.value,
|
|
304
|
+
proposedBy: (input.voterId as string) || 'system',
|
|
305
|
+
proposedAt: new Date().toISOString(),
|
|
306
|
+
votes: {},
|
|
307
|
+
status: 'pending',
|
|
308
|
+
};
|
|
309
|
+
|
|
310
|
+
state.consensus.pending.push(proposal);
|
|
311
|
+
saveHiveState(state);
|
|
312
|
+
|
|
313
|
+
return {
|
|
314
|
+
action,
|
|
315
|
+
proposalId,
|
|
316
|
+
type: proposal.type,
|
|
317
|
+
status: 'pending',
|
|
318
|
+
requiredVotes: Math.ceil(state.workers.length / 2) + 1,
|
|
319
|
+
};
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
if (action === 'vote') {
|
|
323
|
+
const proposal = state.consensus.pending.find(p => p.proposalId === input.proposalId);
|
|
324
|
+
if (!proposal) {
|
|
325
|
+
return { action, error: 'Proposal not found' };
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
const voterId = input.voterId as string;
|
|
329
|
+
proposal.votes[voterId] = input.vote as boolean;
|
|
330
|
+
|
|
331
|
+
// Check if we have majority
|
|
332
|
+
const votesFor = Object.values(proposal.votes).filter(v => v).length;
|
|
333
|
+
const votesAgainst = Object.values(proposal.votes).filter(v => !v).length;
|
|
334
|
+
const majority = Math.ceil(state.workers.length / 2) + 1;
|
|
335
|
+
|
|
336
|
+
if (votesFor >= majority) {
|
|
337
|
+
proposal.status = 'approved';
|
|
338
|
+
state.consensus.history.push({
|
|
339
|
+
proposalId: proposal.proposalId,
|
|
340
|
+
type: proposal.type,
|
|
341
|
+
result: 'approved',
|
|
342
|
+
votes: { for: votesFor, against: votesAgainst },
|
|
343
|
+
decidedAt: new Date().toISOString(),
|
|
344
|
+
});
|
|
345
|
+
state.consensus.pending = state.consensus.pending.filter(p => p.proposalId !== proposal.proposalId);
|
|
346
|
+
} else if (votesAgainst >= majority) {
|
|
347
|
+
proposal.status = 'rejected';
|
|
348
|
+
state.consensus.history.push({
|
|
349
|
+
proposalId: proposal.proposalId,
|
|
350
|
+
type: proposal.type,
|
|
351
|
+
result: 'rejected',
|
|
352
|
+
votes: { for: votesFor, against: votesAgainst },
|
|
353
|
+
decidedAt: new Date().toISOString(),
|
|
354
|
+
});
|
|
355
|
+
state.consensus.pending = state.consensus.pending.filter(p => p.proposalId !== proposal.proposalId);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
saveHiveState(state);
|
|
359
|
+
|
|
360
|
+
return {
|
|
361
|
+
action,
|
|
362
|
+
proposalId: proposal.proposalId,
|
|
363
|
+
voterId,
|
|
364
|
+
vote: input.vote,
|
|
365
|
+
votesFor,
|
|
366
|
+
votesAgainst,
|
|
367
|
+
status: proposal.status,
|
|
368
|
+
};
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
if (action === 'status') {
|
|
372
|
+
const proposal = state.consensus.pending.find(p => p.proposalId === input.proposalId);
|
|
373
|
+
if (!proposal) {
|
|
374
|
+
// Check history
|
|
375
|
+
const historical = state.consensus.history.find(h => h.proposalId === input.proposalId);
|
|
376
|
+
if (historical) {
|
|
377
|
+
return { action, ...historical, historical: true };
|
|
378
|
+
}
|
|
379
|
+
return { action, error: 'Proposal not found' };
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
const votesFor = Object.values(proposal.votes).filter(v => v).length;
|
|
383
|
+
const votesAgainst = Object.values(proposal.votes).filter(v => !v).length;
|
|
384
|
+
|
|
385
|
+
return {
|
|
386
|
+
action,
|
|
387
|
+
proposalId: proposal.proposalId,
|
|
388
|
+
type: proposal.type,
|
|
389
|
+
status: proposal.status,
|
|
390
|
+
votesFor,
|
|
391
|
+
votesAgainst,
|
|
392
|
+
totalVotes: Object.keys(proposal.votes).length,
|
|
393
|
+
requiredMajority: Math.ceil(state.workers.length / 2) + 1,
|
|
394
|
+
};
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
if (action === 'list') {
|
|
398
|
+
return {
|
|
399
|
+
action,
|
|
400
|
+
pending: state.consensus.pending.map(p => ({
|
|
401
|
+
proposalId: p.proposalId,
|
|
402
|
+
type: p.type,
|
|
403
|
+
proposedAt: p.proposedAt,
|
|
404
|
+
totalVotes: Object.keys(p.votes).length,
|
|
405
|
+
})),
|
|
406
|
+
recentHistory: state.consensus.history.slice(-5),
|
|
407
|
+
};
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
return { action, error: 'Unknown action' };
|
|
411
|
+
},
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
name: 'hive-mind/broadcast',
|
|
415
|
+
description: 'Broadcast message to all workers',
|
|
416
|
+
category: 'hive-mind',
|
|
417
|
+
inputSchema: {
|
|
418
|
+
type: 'object',
|
|
419
|
+
properties: {
|
|
420
|
+
message: { type: 'string', description: 'Message to broadcast' },
|
|
421
|
+
priority: { type: 'string', enum: ['low', 'normal', 'high', 'critical'], description: 'Message priority' },
|
|
422
|
+
fromId: { type: 'string', description: 'Sender agent ID' },
|
|
423
|
+
},
|
|
424
|
+
required: ['message'],
|
|
425
|
+
},
|
|
426
|
+
handler: async (input) => {
|
|
427
|
+
const state = loadHiveState();
|
|
428
|
+
|
|
429
|
+
if (!state.initialized) {
|
|
430
|
+
return { success: false, error: 'Hive-mind not initialized' };
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
const messageId = `msg-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`;
|
|
434
|
+
|
|
435
|
+
// Store in shared memory
|
|
436
|
+
const messages = (state.sharedMemory.broadcasts as Array<unknown>) || [];
|
|
437
|
+
messages.push({
|
|
438
|
+
messageId,
|
|
439
|
+
message: input.message,
|
|
440
|
+
priority: input.priority || 'normal',
|
|
441
|
+
fromId: input.fromId || 'system',
|
|
442
|
+
timestamp: new Date().toISOString(),
|
|
443
|
+
});
|
|
444
|
+
|
|
445
|
+
// Keep only last 100 broadcasts
|
|
446
|
+
state.sharedMemory.broadcasts = messages.slice(-100);
|
|
447
|
+
saveHiveState(state);
|
|
448
|
+
|
|
449
|
+
return {
|
|
450
|
+
success: true,
|
|
451
|
+
messageId,
|
|
452
|
+
recipients: state.workers.length,
|
|
453
|
+
priority: input.priority || 'normal',
|
|
454
|
+
broadcastAt: new Date().toISOString(),
|
|
455
|
+
};
|
|
456
|
+
},
|
|
457
|
+
},
|
|
458
|
+
{
|
|
459
|
+
name: 'hive-mind/memory',
|
|
460
|
+
description: 'Access hive shared memory',
|
|
461
|
+
category: 'hive-mind',
|
|
462
|
+
inputSchema: {
|
|
463
|
+
type: 'object',
|
|
464
|
+
properties: {
|
|
465
|
+
action: { type: 'string', enum: ['get', 'set', 'delete', 'list'], description: 'Memory action' },
|
|
466
|
+
key: { type: 'string', description: 'Memory key' },
|
|
467
|
+
value: { description: 'Value to store (for set)' },
|
|
468
|
+
},
|
|
469
|
+
required: ['action'],
|
|
470
|
+
},
|
|
471
|
+
handler: async (input) => {
|
|
472
|
+
const state = loadHiveState();
|
|
473
|
+
const action = input.action as string;
|
|
474
|
+
const key = input.key as string;
|
|
475
|
+
|
|
476
|
+
if (action === 'get') {
|
|
477
|
+
if (!key) return { action, error: 'Key required' };
|
|
478
|
+
return {
|
|
479
|
+
action,
|
|
480
|
+
key,
|
|
481
|
+
value: state.sharedMemory[key],
|
|
482
|
+
exists: key in state.sharedMemory,
|
|
483
|
+
};
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
if (action === 'set') {
|
|
487
|
+
if (!key) return { action, error: 'Key required' };
|
|
488
|
+
state.sharedMemory[key] = input.value;
|
|
489
|
+
saveHiveState(state);
|
|
490
|
+
return {
|
|
491
|
+
action,
|
|
492
|
+
key,
|
|
493
|
+
success: true,
|
|
494
|
+
updatedAt: new Date().toISOString(),
|
|
495
|
+
};
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
if (action === 'delete') {
|
|
499
|
+
if (!key) return { action, error: 'Key required' };
|
|
500
|
+
const existed = key in state.sharedMemory;
|
|
501
|
+
delete state.sharedMemory[key];
|
|
502
|
+
saveHiveState(state);
|
|
503
|
+
return {
|
|
504
|
+
action,
|
|
505
|
+
key,
|
|
506
|
+
deleted: existed,
|
|
507
|
+
};
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
if (action === 'list') {
|
|
511
|
+
return {
|
|
512
|
+
action,
|
|
513
|
+
keys: Object.keys(state.sharedMemory),
|
|
514
|
+
count: Object.keys(state.sharedMemory).length,
|
|
515
|
+
};
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
return { action, error: 'Unknown action' };
|
|
519
|
+
},
|
|
520
|
+
},
|
|
521
|
+
];
|
|
@@ -536,7 +536,7 @@ export const hooksPretrain: MCPTool = {
|
|
|
536
536
|
const depth = (params.depth as string) || 'medium';
|
|
537
537
|
const startTime = Date.now();
|
|
538
538
|
|
|
539
|
-
//
|
|
539
|
+
// Scale analysis results by depth level
|
|
540
540
|
const multiplier = depth === 'deep' ? 3 : depth === 'shallow' ? 1 : 2;
|
|
541
541
|
|
|
542
542
|
return {
|
|
@@ -683,20 +683,42 @@ export const hooksTransfer: MCPTool = {
|
|
|
683
683
|
},
|
|
684
684
|
};
|
|
685
685
|
|
|
686
|
-
// Session start hook
|
|
686
|
+
// Session start hook - auto-starts daemon
|
|
687
687
|
export const hooksSessionStart: MCPTool = {
|
|
688
688
|
name: 'hooks/session-start',
|
|
689
|
-
description: 'Initialize a new session',
|
|
689
|
+
description: 'Initialize a new session and auto-start daemon',
|
|
690
690
|
inputSchema: {
|
|
691
691
|
type: 'object',
|
|
692
692
|
properties: {
|
|
693
693
|
sessionId: { type: 'string', description: 'Optional session ID' },
|
|
694
694
|
restoreLatest: { type: 'boolean', description: 'Restore latest session state' },
|
|
695
|
+
startDaemon: { type: 'boolean', description: 'Auto-start worker daemon (default: true)' },
|
|
695
696
|
},
|
|
696
697
|
},
|
|
697
698
|
handler: async (params: Record<string, unknown>) => {
|
|
698
699
|
const sessionId = (params.sessionId as string) || `session-${Date.now()}`;
|
|
699
700
|
const restoreLatest = params.restoreLatest as boolean;
|
|
701
|
+
const shouldStartDaemon = params.startDaemon !== false;
|
|
702
|
+
|
|
703
|
+
// Auto-start daemon if enabled
|
|
704
|
+
let daemonStatus: { started: boolean; pid?: number; error?: string } = { started: false };
|
|
705
|
+
if (shouldStartDaemon) {
|
|
706
|
+
try {
|
|
707
|
+
// Dynamic import to avoid circular dependencies
|
|
708
|
+
const { startDaemon } = await import('../services/worker-daemon.js');
|
|
709
|
+
const daemon = await startDaemon(process.cwd());
|
|
710
|
+
const status = daemon.getStatus();
|
|
711
|
+
daemonStatus = {
|
|
712
|
+
started: true,
|
|
713
|
+
pid: status.pid,
|
|
714
|
+
};
|
|
715
|
+
} catch (error) {
|
|
716
|
+
daemonStatus = {
|
|
717
|
+
started: false,
|
|
718
|
+
error: error instanceof Error ? error.message : String(error),
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
}
|
|
700
722
|
|
|
701
723
|
return {
|
|
702
724
|
sessionId,
|
|
@@ -706,7 +728,9 @@ export const hooksSessionStart: MCPTool = {
|
|
|
706
728
|
intelligenceEnabled: true,
|
|
707
729
|
hooksEnabled: true,
|
|
708
730
|
memoryPersistence: true,
|
|
731
|
+
daemonEnabled: shouldStartDaemon,
|
|
709
732
|
},
|
|
733
|
+
daemon: daemonStatus,
|
|
710
734
|
previousSession: restoreLatest ? {
|
|
711
735
|
id: `session-${Date.now() - 86400000}`,
|
|
712
736
|
tasksRestored: 3,
|
|
@@ -716,25 +740,40 @@ export const hooksSessionStart: MCPTool = {
|
|
|
716
740
|
},
|
|
717
741
|
};
|
|
718
742
|
|
|
719
|
-
// Session end hook
|
|
743
|
+
// Session end hook - stops daemon
|
|
720
744
|
export const hooksSessionEnd: MCPTool = {
|
|
721
745
|
name: 'hooks/session-end',
|
|
722
|
-
description: 'End current session and persist state',
|
|
746
|
+
description: 'End current session, stop daemon, and persist state',
|
|
723
747
|
inputSchema: {
|
|
724
748
|
type: 'object',
|
|
725
749
|
properties: {
|
|
726
750
|
saveState: { type: 'boolean', description: 'Save session state' },
|
|
727
751
|
exportMetrics: { type: 'boolean', description: 'Export session metrics' },
|
|
752
|
+
stopDaemon: { type: 'boolean', description: 'Stop worker daemon (default: true)' },
|
|
728
753
|
},
|
|
729
754
|
},
|
|
730
755
|
handler: async (params: Record<string, unknown>) => {
|
|
731
756
|
const saveState = params.saveState !== false;
|
|
757
|
+
const shouldStopDaemon = params.stopDaemon !== false;
|
|
732
758
|
const sessionId = `session-${Date.now() - 3600000}`; // Default session (1 hour ago)
|
|
733
759
|
|
|
760
|
+
// Stop daemon if enabled
|
|
761
|
+
let daemonStopped = false;
|
|
762
|
+
if (shouldStopDaemon) {
|
|
763
|
+
try {
|
|
764
|
+
const { stopDaemon } = await import('../services/worker-daemon.js');
|
|
765
|
+
await stopDaemon();
|
|
766
|
+
daemonStopped = true;
|
|
767
|
+
} catch {
|
|
768
|
+
// Daemon may not be running
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
|
|
734
772
|
return {
|
|
735
773
|
sessionId,
|
|
736
774
|
duration: 3600000, // 1 hour in ms
|
|
737
775
|
statePath: saveState ? `.claude/sessions/${sessionId}.json` : undefined,
|
|
776
|
+
daemon: { stopped: daemonStopped },
|
|
738
777
|
summary: {
|
|
739
778
|
tasksExecuted: 12,
|
|
740
779
|
tasksSucceeded: 10,
|
|
@@ -1598,7 +1637,7 @@ export const hooksWorkerDispatch: MCPTool = {
|
|
|
1598
1637
|
|
|
1599
1638
|
activeWorkers.set(workerId, worker);
|
|
1600
1639
|
|
|
1601
|
-
//
|
|
1640
|
+
// Update worker progress in background
|
|
1602
1641
|
if (background) {
|
|
1603
1642
|
setTimeout(() => {
|
|
1604
1643
|
const w = activeWorkers.get(workerId);
|
|
@@ -1745,7 +1784,7 @@ export const hooksWorkerDetect: MCPTool = {
|
|
|
1745
1784
|
});
|
|
1746
1785
|
dispatched.push(workerId);
|
|
1747
1786
|
|
|
1748
|
-
//
|
|
1787
|
+
// Mark worker completion after processing
|
|
1749
1788
|
setTimeout(() => {
|
|
1750
1789
|
const w = activeWorkers.get(workerId);
|
|
1751
1790
|
if (w) {
|
package/src/mcp-tools/index.ts
CHANGED
|
@@ -12,3 +12,5 @@ export { configTools } from './config-tools.js';
|
|
|
12
12
|
export { hooksTools } from './hooks-tools.js';
|
|
13
13
|
export { taskTools } from './task-tools.js';
|
|
14
14
|
export { sessionTools } from './session-tools.js';
|
|
15
|
+
export { hiveMindTools } from './hive-mind-tools.js';
|
|
16
|
+
export { workflowTools } from './workflow-tools.js';
|