claude-flow 2.0.0-alpha.62 → 2.0.0-alpha.64
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/commands/analysis/COMMAND_COMPLIANCE_REPORT.md +54 -0
- package/.claude/commands/analysis/token-efficiency.md +2 -1
- package/.claude/commands/automation/self-healing.md +47 -2
- package/.claude/commands/automation/session-memory.md +39 -10
- package/.claude/commands/automation/smart-agents.md +36 -8
- package/.claude/commands/github/code-review-swarm.md +80 -15
- package/.claude/commands/github/github-modes.md +14 -14
- package/.claude/commands/github/issue-tracker.md +19 -16
- package/.claude/commands/github/multi-repo-swarm.md +114 -16
- package/.claude/commands/github/pr-manager.md +5 -4
- package/.claude/commands/github/project-board-sync.md +38 -5
- package/.claude/commands/github/release-manager.md +19 -19
- package/.claude/commands/github/release-swarm.md +102 -13
- package/.claude/commands/github/repo-architect.md +6 -6
- package/.claude/commands/github/swarm-issue.md +139 -17
- package/.claude/commands/github/swarm-pr.md +49 -15
- package/.claude/commands/github/sync-coordinator.md +33 -33
- package/.claude/commands/github/workflow-automation.md +37 -10
- package/.claude/commands/hooks/overview.md +2 -2
- package/.claude/commands/hooks/setup.md +7 -7
- package/.claude/commands/memory/neural.md +10 -5
- package/.claude/commands/memory/usage.md +9 -5
- package/.claude/commands/monitoring/agents.md +7 -5
- package/.claude/commands/monitoring/status.md +8 -5
- package/.claude/commands/optimization/auto-topology.md +13 -1
- package/.claude/commands/optimization/parallel-execution.md +7 -1
- package/.claude/commands/sparc/analyzer.md +28 -2
- package/.claude/commands/sparc/architect.md +27 -1
- package/.claude/commands/sparc/batch-executor.md +27 -1
- package/.claude/commands/sparc/coder.md +27 -1
- package/.claude/commands/sparc/debugger.md +27 -1
- package/.claude/commands/sparc/designer.md +27 -1
- package/.claude/commands/sparc/documenter.md +27 -1
- package/.claude/commands/sparc/innovator.md +27 -1
- package/.claude/commands/sparc/memory-manager.md +27 -1
- package/.claude/commands/sparc/optimizer.md +27 -1
- package/.claude/commands/sparc/orchestrator.md +106 -2
- package/.claude/commands/sparc/researcher.md +27 -1
- package/.claude/commands/sparc/reviewer.md +27 -1
- package/.claude/commands/sparc/sparc-modes.md +137 -5
- package/.claude/commands/sparc/swarm-coordinator.md +27 -1
- package/.claude/commands/sparc/tdd.md +27 -1
- package/.claude/commands/sparc/tester.md +27 -1
- package/.claude/commands/sparc/workflow-manager.md +27 -1
- package/.claude/commands/swarm/analysis.md +82 -5
- package/.claude/commands/swarm/development.md +83 -6
- package/.claude/commands/swarm/examples.md +141 -3
- package/.claude/commands/swarm/maintenance.md +92 -8
- package/.claude/commands/swarm/optimization.md +107 -9
- package/.claude/commands/swarm/research.md +126 -8
- package/.claude/commands/swarm/testing.md +121 -9
- package/.claude/commands/training/neural-patterns.md +27 -2
- package/.claude/commands/training/specialization.md +13 -3
- package/.claude/commands/workflows/development.md +43 -4
- package/.claude/commands/workflows/research.md +26 -2
- package/CHANGELOG.md +34 -0
- package/README.md +8 -0
- package/bin/claude-flow +1 -1
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.d.ts +66 -0
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.d.ts.map +1 -1
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.js +220 -2
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.js.map +1 -1
- package/dist/cli/simple-commands/hive-mind.d.ts.map +1 -1
- package/dist/cli/simple-commands/hive-mind.js +83 -5
- package/dist/cli/simple-commands/hive-mind.js.map +1 -1
- package/dist/memory/fallback-store.d.ts +1 -0
- package/dist/memory/fallback-store.d.ts.map +1 -1
- package/dist/memory/fallback-store.js +25 -3
- package/dist/memory/fallback-store.js.map +1 -1
- package/dist/memory/sqlite-store.d.ts +34 -0
- package/dist/memory/sqlite-store.d.ts.map +1 -0
- package/dist/memory/sqlite-store.js +2 -3
- package/dist/memory/sqlite-store.js.map +1 -1
- package/dist/memory/sqlite-wrapper.d.ts +38 -0
- package/dist/memory/sqlite-wrapper.d.ts.map +1 -0
- package/dist/memory/sqlite-wrapper.js +157 -0
- package/dist/memory/sqlite-wrapper.js.map +1 -0
- package/package.json +1 -1
- package/src/api/claude-api-errors.ts +248 -0
- package/src/api/claude-client-enhanced.ts +616 -0
- package/src/api/claude-client.ts +282 -14
- package/src/cli/help-text.js +4 -3
- package/src/cli/simple-cli.js +1 -1
- package/src/cli/simple-commands/coordination.js +73 -49
- package/src/cli/simple-commands/hive-mind/auto-save-middleware.js +6 -6
- package/src/cli/simple-commands/hive-mind/mcp-wrapper.js +327 -8
- package/src/cli/simple-commands/hive-mind/session-manager.js +330 -108
- package/src/cli/simple-commands/hive-mind.js +192 -11
- package/src/cli/simple-commands/init/claude-commands/optimized-slash-commands.js +53 -28
- package/src/cli/simple-commands/init/claude-commands/slash-commands.js +36 -14
- package/src/cli/simple-commands/init/claude-commands/sparc-commands.js +107 -30
- package/src/cli/simple-commands/init/copy-revised-templates.js +175 -0
- package/src/cli/simple-commands/init/index.js +156 -235
- package/src/cli/simple-commands/init/template-copier.js +583 -0
- package/src/cli/simple-commands/init/templates/claude-flow-universal +1 -1
- package/src/cli/simple-commands/init/templates/coordination.md +16 -0
- package/src/cli/simple-commands/init/templates/memory-bank.md +16 -0
- package/src/cli/simple-commands/init/templates/settings.json.enhanced +35 -0
- package/src/cli/simple-commands/init/templates/sparc-modes.js +634 -23
- package/src/hive-mind/core/DatabaseManager.ts +75 -16
- package/src/memory/backends/sqlite.ts +21 -3
- package/src/memory/fallback-store.js +35 -3
- package/src/memory/sqlite-store.js +2 -3
- package/src/memory/sqlite-wrapper.js +173 -0
|
@@ -3,25 +3,77 @@
|
|
|
3
3
|
* Handles session persistence and resume functionality for swarms
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
import Database from 'better-sqlite3';
|
|
7
6
|
import path from 'path';
|
|
8
7
|
import { existsSync, mkdirSync } from 'fs';
|
|
9
8
|
import { readFile, writeFile } from 'fs/promises';
|
|
10
9
|
import chalk from 'chalk';
|
|
11
10
|
import { cwd } from '../../node-compat.js';
|
|
11
|
+
import { createDatabase, isSQLiteAvailable, isWindows } from '../../../memory/sqlite-wrapper.js';
|
|
12
12
|
|
|
13
13
|
export class HiveMindSessionManager {
|
|
14
14
|
constructor(hiveMindDir = null) {
|
|
15
15
|
this.hiveMindDir = hiveMindDir || path.join(cwd(), '.hive-mind');
|
|
16
16
|
this.sessionsDir = path.join(this.hiveMindDir, 'sessions');
|
|
17
17
|
this.dbPath = path.join(this.hiveMindDir, 'hive.db');
|
|
18
|
+
this.db = null;
|
|
19
|
+
this.isInMemory = false;
|
|
20
|
+
this.memoryStore = null;
|
|
18
21
|
|
|
19
22
|
// Ensure directories exist
|
|
20
23
|
this.ensureDirectories();
|
|
21
24
|
|
|
22
25
|
// Initialize database connection
|
|
23
|
-
this.
|
|
24
|
-
|
|
26
|
+
this.initializeDatabase();
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Initialize database with fallback support
|
|
31
|
+
*/
|
|
32
|
+
async initializeDatabase() {
|
|
33
|
+
try {
|
|
34
|
+
const sqliteAvailable = await isSQLiteAvailable();
|
|
35
|
+
|
|
36
|
+
if (!sqliteAvailable) {
|
|
37
|
+
console.warn('SQLite not available, using in-memory session storage');
|
|
38
|
+
this.initializeInMemoryFallback();
|
|
39
|
+
return;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
this.db = await createDatabase(this.dbPath);
|
|
43
|
+
this.initializeSchema();
|
|
44
|
+
} catch (error) {
|
|
45
|
+
console.error('Failed to create SQLite database:', error.message);
|
|
46
|
+
console.warn('Falling back to in-memory session storage');
|
|
47
|
+
this.initializeInMemoryFallback();
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Ensure database is initialized before use
|
|
53
|
+
*/
|
|
54
|
+
async ensureInitialized() {
|
|
55
|
+
if (this.db === null && !this.isInMemory) {
|
|
56
|
+
await this.initializeDatabase();
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Initialize in-memory fallback for session storage
|
|
62
|
+
*/
|
|
63
|
+
initializeInMemoryFallback() {
|
|
64
|
+
this.isInMemory = true;
|
|
65
|
+
this.memoryStore = {
|
|
66
|
+
sessions: new Map(),
|
|
67
|
+
checkpoints: new Map(),
|
|
68
|
+
logs: new Map()
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
if (isWindows()) {
|
|
72
|
+
console.info(`
|
|
73
|
+
Note: Session data will not persist between runs on Windows without SQLite.
|
|
74
|
+
To enable persistence, see: https://github.com/ruvnet/claude-code-flow/docs/windows-installation.md
|
|
75
|
+
`);
|
|
76
|
+
}
|
|
25
77
|
}
|
|
26
78
|
|
|
27
79
|
/**
|
|
@@ -110,18 +162,38 @@ export class HiveMindSessionManager {
|
|
|
110
162
|
/**
|
|
111
163
|
* Create a new session for a swarm
|
|
112
164
|
*/
|
|
113
|
-
createSession(swarmId, swarmName, objective, metadata = {}) {
|
|
165
|
+
async createSession(swarmId, swarmName, objective, metadata = {}) {
|
|
166
|
+
await this.ensureInitialized();
|
|
167
|
+
|
|
114
168
|
const sessionId = `session-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
115
169
|
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
170
|
+
if (this.isInMemory) {
|
|
171
|
+
// Use in-memory storage
|
|
172
|
+
const sessionData = {
|
|
173
|
+
id: sessionId,
|
|
174
|
+
swarm_id: swarmId,
|
|
175
|
+
swarm_name: swarmName,
|
|
176
|
+
objective,
|
|
177
|
+
status: 'active',
|
|
178
|
+
created_at: new Date().toISOString(),
|
|
179
|
+
updated_at: new Date().toISOString(),
|
|
180
|
+
metadata: JSON.stringify(metadata),
|
|
181
|
+
parent_pid: process.pid,
|
|
182
|
+
child_pids: '[]'
|
|
183
|
+
};
|
|
184
|
+
this.memoryStore.sessions.set(sessionId, sessionData);
|
|
185
|
+
} else {
|
|
186
|
+
// Use SQLite
|
|
187
|
+
const stmt = this.db.prepare(`
|
|
188
|
+
INSERT INTO sessions (id, swarm_id, swarm_name, objective, metadata, parent_pid)
|
|
189
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
190
|
+
`);
|
|
191
|
+
|
|
192
|
+
stmt.run(sessionId, swarmId, swarmName, objective, JSON.stringify(metadata), process.pid);
|
|
193
|
+
}
|
|
122
194
|
|
|
123
195
|
// Log session creation
|
|
124
|
-
this.logSessionEvent(sessionId, 'info', 'Session created', null, {
|
|
196
|
+
await this.logSessionEvent(sessionId, 'info', 'Session created', null, {
|
|
125
197
|
swarmId,
|
|
126
198
|
swarmName,
|
|
127
199
|
objective,
|
|
@@ -135,24 +207,49 @@ export class HiveMindSessionManager {
|
|
|
135
207
|
* Save session checkpoint
|
|
136
208
|
*/
|
|
137
209
|
async saveCheckpoint(sessionId, checkpointName, checkpointData) {
|
|
210
|
+
await this.ensureInitialized();
|
|
211
|
+
|
|
138
212
|
const checkpointId = `checkpoint-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
139
213
|
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
214
|
+
if (this.isInMemory) {
|
|
215
|
+
// Use in-memory storage
|
|
216
|
+
const checkpointEntry = {
|
|
217
|
+
id: checkpointId,
|
|
218
|
+
session_id: sessionId,
|
|
219
|
+
checkpoint_name: checkpointName,
|
|
220
|
+
checkpoint_data: JSON.stringify(checkpointData),
|
|
221
|
+
created_at: new Date().toISOString()
|
|
222
|
+
};
|
|
223
|
+
|
|
224
|
+
if (!this.memoryStore.checkpoints.has(sessionId)) {
|
|
225
|
+
this.memoryStore.checkpoints.set(sessionId, []);
|
|
226
|
+
}
|
|
227
|
+
this.memoryStore.checkpoints.get(sessionId).push(checkpointEntry);
|
|
228
|
+
|
|
229
|
+
// Update session data
|
|
230
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
231
|
+
if (session) {
|
|
232
|
+
session.checkpoint_data = JSON.stringify(checkpointData);
|
|
233
|
+
session.updated_at = new Date().toISOString();
|
|
234
|
+
}
|
|
235
|
+
} else {
|
|
236
|
+
// Save to database
|
|
237
|
+
const stmt = this.db.prepare(`
|
|
238
|
+
INSERT INTO session_checkpoints (id, session_id, checkpoint_name, checkpoint_data)
|
|
239
|
+
VALUES (?, ?, ?, ?)
|
|
240
|
+
`);
|
|
241
|
+
|
|
242
|
+
stmt.run(checkpointId, sessionId, checkpointName, JSON.stringify(checkpointData));
|
|
243
|
+
|
|
244
|
+
// Update session checkpoint data and timestamp
|
|
245
|
+
const updateStmt = this.db.prepare(`
|
|
246
|
+
UPDATE sessions
|
|
247
|
+
SET checkpoint_data = ?, updated_at = CURRENT_TIMESTAMP
|
|
248
|
+
WHERE id = ?
|
|
249
|
+
`);
|
|
250
|
+
|
|
251
|
+
updateStmt.run(JSON.stringify(checkpointData), sessionId);
|
|
252
|
+
}
|
|
156
253
|
|
|
157
254
|
// Save checkpoint file for backup
|
|
158
255
|
const checkpointFile = path.join(this.sessionsDir, `${sessionId}-${checkpointName}.json`);
|
|
@@ -171,7 +268,7 @@ export class HiveMindSessionManager {
|
|
|
171
268
|
),
|
|
172
269
|
);
|
|
173
270
|
|
|
174
|
-
this.logSessionEvent(sessionId, 'info', `Checkpoint saved: ${checkpointName}`, null, {
|
|
271
|
+
await this.logSessionEvent(sessionId, 'info', `Checkpoint saved: ${checkpointName}`, null, {
|
|
175
272
|
checkpointId,
|
|
176
273
|
});
|
|
177
274
|
|
|
@@ -181,38 +278,91 @@ export class HiveMindSessionManager {
|
|
|
181
278
|
/**
|
|
182
279
|
* Get active sessions
|
|
183
280
|
*/
|
|
184
|
-
getActiveSessions() {
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
281
|
+
async getActiveSessions() {
|
|
282
|
+
await this.ensureInitialized();
|
|
283
|
+
|
|
284
|
+
if (this.isInMemory) {
|
|
285
|
+
// Use in-memory storage
|
|
286
|
+
const sessions = [];
|
|
287
|
+
for (const [sessionId, session] of this.memoryStore.sessions) {
|
|
288
|
+
if (session.status === 'active' || session.status === 'paused') {
|
|
289
|
+
sessions.push({
|
|
290
|
+
...session,
|
|
291
|
+
metadata: session.metadata ? JSON.parse(session.metadata) : {},
|
|
292
|
+
checkpoint_data: session.checkpoint_data ? JSON.parse(session.checkpoint_data) : null,
|
|
293
|
+
agent_count: 0, // Not tracked in memory mode
|
|
294
|
+
task_count: 0, // Not tracked in memory mode
|
|
295
|
+
completed_tasks: 0, // Not tracked in memory mode
|
|
296
|
+
completion_percentage: 0
|
|
297
|
+
});
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
return sessions.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));
|
|
301
|
+
} else {
|
|
302
|
+
// Use SQLite
|
|
303
|
+
const stmt = this.db.prepare(`
|
|
304
|
+
SELECT s.*,
|
|
305
|
+
COUNT(DISTINCT a.id) as agent_count,
|
|
306
|
+
COUNT(DISTINCT t.id) as task_count,
|
|
307
|
+
SUM(CASE WHEN t.status = 'completed' THEN 1 ELSE 0 END) as completed_tasks
|
|
308
|
+
FROM sessions s
|
|
309
|
+
LEFT JOIN agents a ON s.swarm_id = a.swarm_id
|
|
310
|
+
LEFT JOIN tasks t ON s.swarm_id = t.swarm_id
|
|
311
|
+
WHERE s.status = 'active' OR s.status = 'paused'
|
|
312
|
+
GROUP BY s.id
|
|
313
|
+
ORDER BY s.updated_at DESC
|
|
314
|
+
`);
|
|
315
|
+
|
|
316
|
+
const sessions = stmt.all();
|
|
317
|
+
|
|
318
|
+
// Parse JSON fields
|
|
319
|
+
return sessions.map((session) => ({
|
|
320
|
+
...session,
|
|
321
|
+
metadata: session.metadata ? JSON.parse(session.metadata) : {},
|
|
322
|
+
checkpoint_data: session.checkpoint_data ? JSON.parse(session.checkpoint_data) : null,
|
|
323
|
+
completion_percentage:
|
|
324
|
+
session.task_count > 0
|
|
325
|
+
? Math.round((session.completed_tasks / session.task_count) * 100)
|
|
326
|
+
: 0,
|
|
327
|
+
}));
|
|
328
|
+
}
|
|
210
329
|
}
|
|
211
330
|
|
|
212
331
|
/**
|
|
213
332
|
* Get session by ID with full details
|
|
214
333
|
*/
|
|
215
|
-
getSession(sessionId) {
|
|
334
|
+
async getSession(sessionId) {
|
|
335
|
+
await this.ensureInitialized();
|
|
336
|
+
|
|
337
|
+
if (this.isInMemory) {
|
|
338
|
+
// Use in-memory storage
|
|
339
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
340
|
+
if (!session) {
|
|
341
|
+
return null;
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Return simplified session data for in-memory mode
|
|
345
|
+
return {
|
|
346
|
+
...session,
|
|
347
|
+
metadata: session.metadata ? JSON.parse(session.metadata) : {},
|
|
348
|
+
checkpoint_data: session.checkpoint_data ? JSON.parse(session.checkpoint_data) : null,
|
|
349
|
+
swarm: null, // Not available in memory mode
|
|
350
|
+
agents: [], // Not available in memory mode
|
|
351
|
+
tasks: [], // Not available in memory mode
|
|
352
|
+
checkpoints: this.memoryStore.checkpoints.get(sessionId) || [],
|
|
353
|
+
recentLogs: this.memoryStore.logs.get(sessionId) || [],
|
|
354
|
+
statistics: {
|
|
355
|
+
totalAgents: 0,
|
|
356
|
+
activeAgents: 0,
|
|
357
|
+
totalTasks: 0,
|
|
358
|
+
completedTasks: 0,
|
|
359
|
+
pendingTasks: 0,
|
|
360
|
+
inProgressTasks: 0,
|
|
361
|
+
completionPercentage: session.completion_percentage || 0,
|
|
362
|
+
},
|
|
363
|
+
};
|
|
364
|
+
}
|
|
365
|
+
|
|
216
366
|
const session = this.db
|
|
217
367
|
.prepare(
|
|
218
368
|
`
|
|
@@ -307,28 +457,45 @@ export class HiveMindSessionManager {
|
|
|
307
457
|
/**
|
|
308
458
|
* Pause a session
|
|
309
459
|
*/
|
|
310
|
-
pauseSession(sessionId) {
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
const result = stmt.run(sessionId);
|
|
318
|
-
|
|
319
|
-
if (result.changes > 0) {
|
|
320
|
-
this.logSessionEvent(sessionId, 'info', 'Session paused');
|
|
321
|
-
|
|
322
|
-
// Update swarm status
|
|
323
|
-
const session = this.db.prepare('SELECT swarm_id FROM sessions WHERE id = ?').get(sessionId);
|
|
460
|
+
async pauseSession(sessionId) {
|
|
461
|
+
await this.ensureInitialized();
|
|
462
|
+
|
|
463
|
+
if (this.isInMemory) {
|
|
464
|
+
// Use in-memory storage
|
|
465
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
324
466
|
if (session) {
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
467
|
+
session.status = 'paused';
|
|
468
|
+
session.paused_at = new Date().toISOString();
|
|
469
|
+
session.updated_at = new Date().toISOString();
|
|
470
|
+
|
|
471
|
+
await this.logSessionEvent(sessionId, 'info', 'Session paused');
|
|
472
|
+
return true;
|
|
473
|
+
}
|
|
474
|
+
return false;
|
|
475
|
+
} else {
|
|
476
|
+
// Use SQLite
|
|
477
|
+
const stmt = this.db.prepare(`
|
|
478
|
+
UPDATE sessions
|
|
479
|
+
SET status = 'paused', paused_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP
|
|
480
|
+
WHERE id = ?
|
|
481
|
+
`);
|
|
482
|
+
|
|
483
|
+
const result = stmt.run(sessionId);
|
|
484
|
+
|
|
485
|
+
if (result.changes > 0) {
|
|
486
|
+
await this.logSessionEvent(sessionId, 'info', 'Session paused');
|
|
487
|
+
|
|
488
|
+
// Update swarm status
|
|
489
|
+
const session = this.db.prepare('SELECT swarm_id FROM sessions WHERE id = ?').get(sessionId);
|
|
490
|
+
if (session) {
|
|
491
|
+
this.db
|
|
492
|
+
.prepare('UPDATE swarms SET status = ? WHERE id = ?')
|
|
493
|
+
.run('paused', session.swarm_id);
|
|
494
|
+
}
|
|
328
495
|
}
|
|
329
|
-
}
|
|
330
496
|
|
|
331
|
-
|
|
497
|
+
return result.changes > 0;
|
|
498
|
+
}
|
|
332
499
|
}
|
|
333
500
|
|
|
334
501
|
/**
|
|
@@ -452,13 +619,35 @@ export class HiveMindSessionManager {
|
|
|
452
619
|
/**
|
|
453
620
|
* Log session event
|
|
454
621
|
*/
|
|
455
|
-
logSessionEvent(sessionId, logLevel, message, agentId = null, data = null) {
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
622
|
+
async logSessionEvent(sessionId, logLevel, message, agentId = null, data = null) {
|
|
623
|
+
await this.ensureInitialized();
|
|
624
|
+
|
|
625
|
+
if (this.isInMemory) {
|
|
626
|
+
// Use in-memory storage for logs
|
|
627
|
+
const logId = `log-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
628
|
+
const logEntry = {
|
|
629
|
+
id: logId,
|
|
630
|
+
session_id: sessionId,
|
|
631
|
+
timestamp: new Date().toISOString(),
|
|
632
|
+
log_level: logLevel,
|
|
633
|
+
message,
|
|
634
|
+
agent_id: agentId,
|
|
635
|
+
data: data ? JSON.stringify(data) : null
|
|
636
|
+
};
|
|
637
|
+
|
|
638
|
+
if (!this.memoryStore.logs.has(sessionId)) {
|
|
639
|
+
this.memoryStore.logs.set(sessionId, []);
|
|
640
|
+
}
|
|
641
|
+
this.memoryStore.logs.get(sessionId).push(logEntry);
|
|
642
|
+
} else {
|
|
643
|
+
// Use SQLite
|
|
644
|
+
const stmt = this.db.prepare(`
|
|
645
|
+
INSERT INTO session_logs (session_id, log_level, message, agent_id, data)
|
|
646
|
+
VALUES (?, ?, ?, ?, ?)
|
|
647
|
+
`);
|
|
648
|
+
|
|
649
|
+
stmt.run(sessionId, logLevel, message, agentId, data ? JSON.stringify(data) : null);
|
|
650
|
+
}
|
|
462
651
|
}
|
|
463
652
|
|
|
464
653
|
/**
|
|
@@ -483,14 +672,26 @@ export class HiveMindSessionManager {
|
|
|
483
672
|
/**
|
|
484
673
|
* Update session progress
|
|
485
674
|
*/
|
|
486
|
-
updateSessionProgress(sessionId, completionPercentage) {
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
675
|
+
async updateSessionProgress(sessionId, completionPercentage) {
|
|
676
|
+
await this.ensureInitialized();
|
|
677
|
+
|
|
678
|
+
if (this.isInMemory) {
|
|
679
|
+
// Use in-memory storage
|
|
680
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
681
|
+
if (session) {
|
|
682
|
+
session.completion_percentage = completionPercentage;
|
|
683
|
+
session.updated_at = new Date().toISOString();
|
|
684
|
+
}
|
|
685
|
+
} else {
|
|
686
|
+
// Use SQLite
|
|
687
|
+
const stmt = this.db.prepare(`
|
|
688
|
+
UPDATE sessions
|
|
689
|
+
SET completion_percentage = ?, updated_at = CURRENT_TIMESTAMP
|
|
690
|
+
WHERE id = ?
|
|
691
|
+
`);
|
|
692
|
+
|
|
693
|
+
stmt.run(completionPercentage, sessionId);
|
|
694
|
+
}
|
|
494
695
|
}
|
|
495
696
|
|
|
496
697
|
/**
|
|
@@ -652,33 +853,42 @@ export class HiveMindSessionManager {
|
|
|
652
853
|
/**
|
|
653
854
|
* Get all child PIDs for a session
|
|
654
855
|
*/
|
|
655
|
-
getChildPids(sessionId) {
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
659
|
-
|
|
856
|
+
async getChildPids(sessionId) {
|
|
857
|
+
await this.ensureInitialized();
|
|
858
|
+
|
|
859
|
+
if (this.isInMemory) {
|
|
860
|
+
// Use in-memory storage
|
|
861
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
862
|
+
if (!session || !session.child_pids) return [];
|
|
863
|
+
return JSON.parse(session.child_pids);
|
|
864
|
+
} else {
|
|
865
|
+
// Use SQLite
|
|
866
|
+
const session = this.db.prepare('SELECT child_pids FROM sessions WHERE id = ?').get(sessionId);
|
|
867
|
+
if (!session || !session.child_pids) return [];
|
|
868
|
+
return JSON.parse(session.child_pids);
|
|
869
|
+
}
|
|
660
870
|
}
|
|
661
871
|
|
|
662
872
|
/**
|
|
663
873
|
* Stop a session and terminate all child processes
|
|
664
874
|
*/
|
|
665
875
|
async stopSession(sessionId) {
|
|
666
|
-
const session = this.getSession(sessionId);
|
|
876
|
+
const session = await this.getSession(sessionId);
|
|
667
877
|
if (!session) {
|
|
668
878
|
throw new Error(`Session ${sessionId} not found`);
|
|
669
879
|
}
|
|
670
880
|
|
|
671
881
|
// Get child PIDs
|
|
672
|
-
const childPids = this.getChildPids(sessionId);
|
|
882
|
+
const childPids = await this.getChildPids(sessionId);
|
|
673
883
|
|
|
674
884
|
// Terminate child processes
|
|
675
885
|
for (const pid of childPids) {
|
|
676
886
|
try {
|
|
677
887
|
process.kill(pid, 'SIGTERM');
|
|
678
|
-
this.logSessionEvent(sessionId, 'info', 'Child process terminated', null, { pid });
|
|
888
|
+
await this.logSessionEvent(sessionId, 'info', 'Child process terminated', null, { pid });
|
|
679
889
|
} catch (err) {
|
|
680
890
|
// Process might already be dead
|
|
681
|
-
this.logSessionEvent(sessionId, 'warning', 'Failed to terminate child process', null, {
|
|
891
|
+
await this.logSessionEvent(sessionId, 'warning', 'Failed to terminate child process', null, {
|
|
682
892
|
pid,
|
|
683
893
|
error: err.message,
|
|
684
894
|
});
|
|
@@ -686,18 +896,28 @@ export class HiveMindSessionManager {
|
|
|
686
896
|
}
|
|
687
897
|
|
|
688
898
|
// Update session status
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
692
|
-
|
|
693
|
-
|
|
899
|
+
if (this.isInMemory) {
|
|
900
|
+
// Use in-memory storage
|
|
901
|
+
const sessionData = this.memoryStore.sessions.get(sessionId);
|
|
902
|
+
if (sessionData) {
|
|
903
|
+
sessionData.status = 'stopped';
|
|
904
|
+
sessionData.updated_at = new Date().toISOString();
|
|
905
|
+
}
|
|
906
|
+
} else {
|
|
907
|
+
// Use SQLite
|
|
908
|
+
const stmt = this.db.prepare(`
|
|
909
|
+
UPDATE sessions
|
|
910
|
+
SET status = 'stopped', updated_at = CURRENT_TIMESTAMP
|
|
911
|
+
WHERE id = ?
|
|
912
|
+
`);
|
|
694
913
|
|
|
695
|
-
|
|
914
|
+
stmt.run(sessionId);
|
|
696
915
|
|
|
697
|
-
|
|
698
|
-
|
|
916
|
+
// Update swarm status
|
|
917
|
+
this.db.prepare('UPDATE swarms SET status = ? WHERE id = ?').run('stopped', session.swarm_id);
|
|
918
|
+
}
|
|
699
919
|
|
|
700
|
-
this.logSessionEvent(sessionId, 'info', 'Session stopped');
|
|
920
|
+
await this.logSessionEvent(sessionId, 'info', 'Session stopped');
|
|
701
921
|
|
|
702
922
|
return true;
|
|
703
923
|
}
|
|
@@ -766,7 +986,9 @@ export class HiveMindSessionManager {
|
|
|
766
986
|
* Clean up and close database connection
|
|
767
987
|
*/
|
|
768
988
|
close() {
|
|
769
|
-
this.db.
|
|
989
|
+
if (this.db && !this.isInMemory) {
|
|
990
|
+
this.db.close();
|
|
991
|
+
}
|
|
770
992
|
}
|
|
771
993
|
}
|
|
772
994
|
|