claude-flow 2.0.0-alpha.63 → 2.0.0-alpha.65
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/CHANGELOG.md +52 -0
- package/bin/claude-flow +1 -1
- package/dist/api/claude-api-errors.d.ts +115 -0
- package/dist/api/claude-api-errors.d.ts.map +1 -0
- package/dist/api/claude-api-errors.js +198 -0
- package/dist/api/claude-api-errors.js.map +1 -0
- package/dist/api/claude-client-enhanced.d.ts +109 -0
- package/dist/api/claude-client-enhanced.d.ts.map +1 -0
- package/dist/api/claude-client-enhanced.js +479 -0
- package/dist/api/claude-client-enhanced.js.map +1 -0
- package/dist/api/claude-client.d.ts +42 -0
- package/dist/api/claude-client.d.ts.map +1 -1
- package/dist/api/claude-client.js +217 -14
- package/dist/api/claude-client.js.map +1 -1
- package/dist/cli/commands/hive-mind/pause.d.ts.map +1 -1
- package/dist/cli/commands/hive-mind/pause.js +6 -5
- package/dist/cli/commands/hive-mind/pause.js.map +1 -1
- package/dist/cli/commands/hive-mind/ps.js.map +1 -1
- package/dist/cli/commands/hive-mind/resume.d.ts.map +1 -1
- package/dist/cli/commands/hive-mind/resume.js +4 -3
- package/dist/cli/commands/hive-mind/resume.js.map +1 -1
- package/dist/cli/commands/hive-mind/stop.js.map +1 -1
- package/dist/cli/repl.d.ts.map +1 -1
- package/dist/cli/repl.js +44 -22
- package/dist/cli/repl.js.map +1 -1
- package/dist/cli/simple-cli.js +4 -3
- package/dist/cli/simple-cli.js.map +1 -1
- package/dist/cli/simple-commands/coordination.js +60 -40
- package/dist/cli/simple-commands/coordination.js.map +1 -1
- package/dist/cli/simple-commands/hive-mind/auto-save-middleware.d.ts +3 -4
- package/dist/cli/simple-commands/hive-mind/auto-save-middleware.d.ts.map +1 -1
- package/dist/cli/simple-commands/hive-mind/auto-save-middleware.js +6 -6
- package/dist/cli/simple-commands/hive-mind/auto-save-middleware.js.map +1 -1
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.d.ts +1 -1
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.d.ts.map +1 -1
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.js +64 -7
- package/dist/cli/simple-commands/hive-mind/mcp-wrapper.js.map +1 -1
- package/dist/cli/simple-commands/hive-mind/session-manager.d.ts +139 -0
- package/dist/cli/simple-commands/hive-mind/session-manager.d.ts.map +1 -0
- package/dist/cli/simple-commands/hive-mind/session-manager.js +308 -95
- package/dist/cli/simple-commands/hive-mind/session-manager.js.map +1 -1
- package/dist/cli/simple-commands/hive-mind.d.ts.map +1 -1
- package/dist/cli/simple-commands/hive-mind.js +88 -10
- package/dist/cli/simple-commands/hive-mind.js.map +1 -1
- package/dist/cli/simple-commands/init/claude-commands/optimized-slash-commands.d.ts.map +1 -1
- package/dist/cli/simple-commands/init/claude-commands/optimized-slash-commands.js +45 -22
- package/dist/cli/simple-commands/init/claude-commands/optimized-slash-commands.js.map +1 -1
- package/dist/cli/simple-commands/init/claude-commands/slash-commands.d.ts.map +1 -1
- package/dist/cli/simple-commands/init/claude-commands/slash-commands.js +34 -13
- package/dist/cli/simple-commands/init/claude-commands/slash-commands.js.map +1 -1
- package/dist/cli/simple-commands/init/claude-commands/sparc-commands.d.ts.map +1 -1
- package/dist/cli/simple-commands/init/claude-commands/sparc-commands.js +107 -30
- package/dist/cli/simple-commands/init/claude-commands/sparc-commands.js.map +1 -1
- package/dist/cli/simple-commands/init/copy-revised-templates.d.ts +29 -0
- package/dist/cli/simple-commands/init/copy-revised-templates.d.ts.map +1 -0
- package/dist/cli/simple-commands/init/copy-revised-templates.js +159 -0
- package/dist/cli/simple-commands/init/copy-revised-templates.js.map +1 -0
- package/dist/cli/simple-commands/init/index.d.ts.map +1 -1
- package/dist/cli/simple-commands/init/index.js +139 -196
- package/dist/cli/simple-commands/init/index.js.map +1 -1
- package/dist/cli/simple-commands/init/template-copier.d.ts +27 -0
- package/dist/cli/simple-commands/init/template-copier.d.ts.map +1 -0
- package/dist/cli/simple-commands/init/template-copier.js +510 -0
- package/dist/cli/simple-commands/init/template-copier.js.map +1 -0
- package/dist/cli/simple-commands/init/templates/sparc-modes.d.ts.map +1 -1
- package/dist/cli/simple-commands/init/templates/sparc-modes.js +634 -23
- package/dist/cli/simple-commands/init/templates/sparc-modes.js.map +1 -1
- package/dist/cli/simple-orchestrator.d.ts.map +1 -1
- package/dist/cli/simple-orchestrator.js +2 -1
- package/dist/cli/simple-orchestrator.js.map +1 -1
- package/dist/cli/ui/compatible-ui.js +1 -1
- package/dist/cli/ui/compatible-ui.js.map +1 -1
- package/dist/cli/ui/index.d.ts.map +1 -1
- package/dist/cli/ui/index.js +4 -2
- package/dist/cli/ui/index.js.map +1 -1
- package/dist/cli/utils/environment-detector.d.ts +5 -0
- package/dist/cli/utils/environment-detector.d.ts.map +1 -1
- package/dist/cli/utils/environment-detector.js.map +1 -1
- package/dist/core/logger.d.ts +2 -0
- package/dist/core/logger.d.ts.map +1 -1
- package/dist/core/logger.js +3 -0
- package/dist/core/logger.js.map +1 -1
- package/dist/hive-mind/core/DatabaseManager.d.ts +6 -0
- package/dist/hive-mind/core/DatabaseManager.d.ts.map +1 -1
- package/dist/hive-mind/core/DatabaseManager.js +66 -15
- package/dist/hive-mind/core/DatabaseManager.js.map +1 -1
- package/dist/memory/backends/sqlite.d.ts +1 -0
- package/dist/memory/backends/sqlite.d.ts.map +1 -1
- package/dist/memory/backends/sqlite.js +17 -2
- package/dist/memory/backends/sqlite.js.map +1 -1
- package/package.json +1 -1
- package/src/cli/commands/hive-mind/pause.ts +6 -5
- package/src/cli/commands/hive-mind/ps.ts +4 -4
- package/src/cli/commands/hive-mind/resume.ts +4 -3
- package/src/cli/commands/hive-mind/stop.ts +1 -1
- package/src/cli/help-text.js +2 -2
- package/src/cli/repl.ts +44 -22
- package/src/cli/simple-cli.js +1 -1
- package/src/cli/simple-cli.ts +11 -10
- package/src/cli/simple-commands/init/index.js +1 -0
- package/src/cli/simple-commands/init/templates/claude-flow-universal +1 -1
- package/src/cli/simple-orchestrator.ts +2 -1
- package/src/cli/ui/compatible-ui.ts +1 -1
- package/src/cli/ui/index.ts +4 -2
- package/src/cli/utils/environment-detector.ts +2 -2
- package/src/core/logger.ts +5 -0
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
export class HiveMindSessionManager {
|
|
2
|
+
constructor(hiveMindDir?: null);
|
|
3
|
+
hiveMindDir: string;
|
|
4
|
+
sessionsDir: string;
|
|
5
|
+
dbPath: string;
|
|
6
|
+
db: any;
|
|
7
|
+
isInMemory: boolean;
|
|
8
|
+
memoryStore: {
|
|
9
|
+
sessions: Map<any, any>;
|
|
10
|
+
checkpoints: Map<any, any>;
|
|
11
|
+
logs: Map<any, any>;
|
|
12
|
+
} | null;
|
|
13
|
+
/**
|
|
14
|
+
* Initialize database with fallback support
|
|
15
|
+
*/
|
|
16
|
+
initializeDatabase(): Promise<void>;
|
|
17
|
+
/**
|
|
18
|
+
* Ensure database is initialized before use
|
|
19
|
+
*/
|
|
20
|
+
ensureInitialized(): Promise<void>;
|
|
21
|
+
/**
|
|
22
|
+
* Initialize in-memory fallback for session storage
|
|
23
|
+
*/
|
|
24
|
+
initializeInMemoryFallback(): void;
|
|
25
|
+
/**
|
|
26
|
+
* Ensure required directories exist
|
|
27
|
+
*/
|
|
28
|
+
ensureDirectories(): void;
|
|
29
|
+
/**
|
|
30
|
+
* Initialize database schema for sessions
|
|
31
|
+
*/
|
|
32
|
+
initializeSchema(): void;
|
|
33
|
+
/**
|
|
34
|
+
* Run database migrations
|
|
35
|
+
*/
|
|
36
|
+
runMigrations(): void;
|
|
37
|
+
/**
|
|
38
|
+
* Create a new session for a swarm
|
|
39
|
+
*/
|
|
40
|
+
createSession(swarmId: any, swarmName: any, objective: any, metadata?: {}): Promise<string>;
|
|
41
|
+
/**
|
|
42
|
+
* Save session checkpoint
|
|
43
|
+
*/
|
|
44
|
+
saveCheckpoint(sessionId: any, checkpointName: any, checkpointData: any): Promise<string>;
|
|
45
|
+
/**
|
|
46
|
+
* Get active sessions
|
|
47
|
+
*/
|
|
48
|
+
getActiveSessions(): Promise<any>;
|
|
49
|
+
/**
|
|
50
|
+
* Get session by ID with full details
|
|
51
|
+
*/
|
|
52
|
+
getSession(sessionId: any): Promise<any>;
|
|
53
|
+
/**
|
|
54
|
+
* Pause a session
|
|
55
|
+
*/
|
|
56
|
+
pauseSession(sessionId: any): Promise<boolean>;
|
|
57
|
+
/**
|
|
58
|
+
* Resume any previous session (paused, stopped, or inactive)
|
|
59
|
+
*/
|
|
60
|
+
resumeSession(sessionId: any): Promise<any>;
|
|
61
|
+
/**
|
|
62
|
+
* Mark session as completed
|
|
63
|
+
*/
|
|
64
|
+
completeSession(sessionId: any): boolean;
|
|
65
|
+
/**
|
|
66
|
+
* Archive old sessions
|
|
67
|
+
*/
|
|
68
|
+
archiveSessions(daysOld?: number): Promise<any>;
|
|
69
|
+
/**
|
|
70
|
+
* Log session event
|
|
71
|
+
*/
|
|
72
|
+
logSessionEvent(sessionId: any, logLevel: any, message: any, agentId?: null, data?: null): Promise<void>;
|
|
73
|
+
/**
|
|
74
|
+
* Get session logs
|
|
75
|
+
*/
|
|
76
|
+
getSessionLogs(sessionId: any, limit?: number, offset?: number): any;
|
|
77
|
+
/**
|
|
78
|
+
* Update session progress
|
|
79
|
+
*/
|
|
80
|
+
updateSessionProgress(sessionId: any, completionPercentage: any): Promise<void>;
|
|
81
|
+
/**
|
|
82
|
+
* Generate session summary
|
|
83
|
+
*/
|
|
84
|
+
generateSessionSummary(sessionId: any): {
|
|
85
|
+
sessionId: any;
|
|
86
|
+
swarmName: any;
|
|
87
|
+
objective: any;
|
|
88
|
+
status: any;
|
|
89
|
+
duration: number;
|
|
90
|
+
statistics: any;
|
|
91
|
+
tasksByType: any;
|
|
92
|
+
checkpointCount: any;
|
|
93
|
+
lastCheckpoint: any;
|
|
94
|
+
timeline: {
|
|
95
|
+
created: any;
|
|
96
|
+
lastUpdated: any;
|
|
97
|
+
paused: any;
|
|
98
|
+
resumed: any;
|
|
99
|
+
};
|
|
100
|
+
} | null;
|
|
101
|
+
/**
|
|
102
|
+
* Export session data
|
|
103
|
+
*/
|
|
104
|
+
exportSession(sessionId: any, exportPath?: null): Promise<string>;
|
|
105
|
+
/**
|
|
106
|
+
* Import session data
|
|
107
|
+
*/
|
|
108
|
+
importSession(importPath: any): Promise<string>;
|
|
109
|
+
/**
|
|
110
|
+
* Add a child process PID to session
|
|
111
|
+
*/
|
|
112
|
+
addChildPid(sessionId: any, pid: any): boolean;
|
|
113
|
+
/**
|
|
114
|
+
* Remove a child process PID from session
|
|
115
|
+
*/
|
|
116
|
+
removeChildPid(sessionId: any, pid: any): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Get all child PIDs for a session
|
|
119
|
+
*/
|
|
120
|
+
getChildPids(sessionId: any): Promise<any>;
|
|
121
|
+
/**
|
|
122
|
+
* Stop a session and terminate all child processes
|
|
123
|
+
*/
|
|
124
|
+
stopSession(sessionId: any): Promise<boolean>;
|
|
125
|
+
/**
|
|
126
|
+
* Get active sessions with process information
|
|
127
|
+
*/
|
|
128
|
+
getActiveSessionsWithProcessInfo(): any;
|
|
129
|
+
/**
|
|
130
|
+
* Clean up orphaned processes
|
|
131
|
+
*/
|
|
132
|
+
cleanupOrphanedProcesses(): number;
|
|
133
|
+
/**
|
|
134
|
+
* Clean up and close database connection
|
|
135
|
+
*/
|
|
136
|
+
close(): void;
|
|
137
|
+
}
|
|
138
|
+
export default HiveMindSessionManager;
|
|
139
|
+
//# sourceMappingURL=session-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"session-manager.d.ts","sourceRoot":"","sources":["../../../../src/cli/simple-commands/hive-mind/session-manager.js"],"names":[],"mappings":"AAYA;IACE,gCAaC;IAZC,oBAAgE;IAChE,oBAA0D;IAC1D,eAAoD;IACpD,QAAc;IACd,oBAAuB;IACvB;;;;aAAuB;IASzB;;OAEG;IACH,oCAiBC;IAED;;OAEG;IACH,mCAIC;IAED;;OAEG;IACH,mCAcC;IAED;;OAEG;IACH,0BAOC;IAED;;OAEG;IACH,yBA0CC;IAED;;OAEG;IACH,sBAmBC;IAED;;OAEG;IACH,4FAuCC;IAED;;OAEG;IACH,0FAmEC;IAED;;OAEG;IACH,kCAgDC;IAED;;OAEG;IACH,yCAyHC;IAED;;OAEG;IACH,+CAuCC;IAED;;OAEG;IACH,4CAkDC;IAED;;OAEG;IACH,yCAsBC;IAED;;OAEG;IACH,gDA+BC;IAED;;OAEG;IACH,yGA6BC;IAED;;OAEG;IACH,qEAcC;IAED;;OAEG;IACH,gFAoBC;IAED;;OAEG;IACH;;;;;;;;;;;;;;;;aAgDC;IAED;;OAEG;IACH,kEAYC;IAED;;OAEG;IACH,gDAgCC;IAED;;OAEG;IACH,+CAmBC;IAED;;OAEG;IACH,kDAoBC;IAED;;OAEG;IACH,2CAcC;IAED;;OAEG;IACH,8CAgDC;IAED;;OAEG;IACH,wCAyBC;IAED;;OAEG;IACH,mCAyBC;IAED;;OAEG;IACH,cAIC;CACF"}
|
|
@@ -2,22 +2,69 @@
|
|
|
2
2
|
* Hive Mind Session Manager
|
|
3
3
|
* Handles session persistence and resume functionality for swarms
|
|
4
4
|
*/
|
|
5
|
-
import Database from 'better-sqlite3';
|
|
6
5
|
import path from 'path';
|
|
7
6
|
import { existsSync, mkdirSync } from 'fs';
|
|
8
7
|
import { readFile, writeFile } from 'fs/promises';
|
|
9
8
|
import chalk from 'chalk';
|
|
10
9
|
import { cwd } from '../../node-compat.js';
|
|
10
|
+
import { createDatabase, isSQLiteAvailable, isWindows } from '../../../memory/sqlite-wrapper.js';
|
|
11
11
|
export class HiveMindSessionManager {
|
|
12
12
|
constructor(hiveMindDir = null) {
|
|
13
13
|
this.hiveMindDir = hiveMindDir || path.join(cwd(), '.hive-mind');
|
|
14
14
|
this.sessionsDir = path.join(this.hiveMindDir, 'sessions');
|
|
15
15
|
this.dbPath = path.join(this.hiveMindDir, 'hive.db');
|
|
16
|
+
this.db = null;
|
|
17
|
+
this.isInMemory = false;
|
|
18
|
+
this.memoryStore = null;
|
|
16
19
|
// Ensure directories exist
|
|
17
20
|
this.ensureDirectories();
|
|
18
21
|
// Initialize database connection
|
|
19
|
-
this.
|
|
20
|
-
|
|
22
|
+
this.initializeDatabase();
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Initialize database with fallback support
|
|
26
|
+
*/
|
|
27
|
+
async initializeDatabase() {
|
|
28
|
+
try {
|
|
29
|
+
const sqliteAvailable = await isSQLiteAvailable();
|
|
30
|
+
if (!sqliteAvailable) {
|
|
31
|
+
console.warn('SQLite not available, using in-memory session storage');
|
|
32
|
+
this.initializeInMemoryFallback();
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
this.db = await createDatabase(this.dbPath);
|
|
36
|
+
this.initializeSchema();
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
console.error('Failed to create SQLite database:', error.message);
|
|
40
|
+
console.warn('Falling back to in-memory session storage');
|
|
41
|
+
this.initializeInMemoryFallback();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Ensure database is initialized before use
|
|
46
|
+
*/
|
|
47
|
+
async ensureInitialized() {
|
|
48
|
+
if (this.db === null && !this.isInMemory) {
|
|
49
|
+
await this.initializeDatabase();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Initialize in-memory fallback for session storage
|
|
54
|
+
*/
|
|
55
|
+
initializeInMemoryFallback() {
|
|
56
|
+
this.isInMemory = true;
|
|
57
|
+
this.memoryStore = {
|
|
58
|
+
sessions: new Map(),
|
|
59
|
+
checkpoints: new Map(),
|
|
60
|
+
logs: new Map()
|
|
61
|
+
};
|
|
62
|
+
if (isWindows()) {
|
|
63
|
+
console.info(`
|
|
64
|
+
Note: Session data will not persist between runs on Windows without SQLite.
|
|
65
|
+
To enable persistence, see: https://github.com/ruvnet/claude-code-flow/docs/windows-installation.md
|
|
66
|
+
`);
|
|
67
|
+
}
|
|
21
68
|
}
|
|
22
69
|
/**
|
|
23
70
|
* Ensure required directories exist
|
|
@@ -100,15 +147,35 @@ export class HiveMindSessionManager {
|
|
|
100
147
|
/**
|
|
101
148
|
* Create a new session for a swarm
|
|
102
149
|
*/
|
|
103
|
-
createSession(swarmId, swarmName, objective, metadata = {}) {
|
|
150
|
+
async createSession(swarmId, swarmName, objective, metadata = {}) {
|
|
151
|
+
await this.ensureInitialized();
|
|
104
152
|
const sessionId = `session-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
153
|
+
if (this.isInMemory) {
|
|
154
|
+
// Use in-memory storage
|
|
155
|
+
const sessionData = {
|
|
156
|
+
id: sessionId,
|
|
157
|
+
swarm_id: swarmId,
|
|
158
|
+
swarm_name: swarmName,
|
|
159
|
+
objective,
|
|
160
|
+
status: 'active',
|
|
161
|
+
created_at: new Date().toISOString(),
|
|
162
|
+
updated_at: new Date().toISOString(),
|
|
163
|
+
metadata: JSON.stringify(metadata),
|
|
164
|
+
parent_pid: process.pid,
|
|
165
|
+
child_pids: '[]'
|
|
166
|
+
};
|
|
167
|
+
this.memoryStore.sessions.set(sessionId, sessionData);
|
|
168
|
+
}
|
|
169
|
+
else {
|
|
170
|
+
// Use SQLite
|
|
171
|
+
const stmt = this.db.prepare(`
|
|
172
|
+
INSERT INTO sessions (id, swarm_id, swarm_name, objective, metadata, parent_pid)
|
|
173
|
+
VALUES (?, ?, ?, ?, ?, ?)
|
|
174
|
+
`);
|
|
175
|
+
stmt.run(sessionId, swarmId, swarmName, objective, JSON.stringify(metadata), process.pid);
|
|
176
|
+
}
|
|
110
177
|
// Log session creation
|
|
111
|
-
this.logSessionEvent(sessionId, 'info', 'Session created', null, {
|
|
178
|
+
await this.logSessionEvent(sessionId, 'info', 'Session created', null, {
|
|
112
179
|
swarmId,
|
|
113
180
|
swarmName,
|
|
114
181
|
objective,
|
|
@@ -120,20 +187,43 @@ export class HiveMindSessionManager {
|
|
|
120
187
|
* Save session checkpoint
|
|
121
188
|
*/
|
|
122
189
|
async saveCheckpoint(sessionId, checkpointName, checkpointData) {
|
|
190
|
+
await this.ensureInitialized();
|
|
123
191
|
const checkpointId = `checkpoint-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
192
|
+
if (this.isInMemory) {
|
|
193
|
+
// Use in-memory storage
|
|
194
|
+
const checkpointEntry = {
|
|
195
|
+
id: checkpointId,
|
|
196
|
+
session_id: sessionId,
|
|
197
|
+
checkpoint_name: checkpointName,
|
|
198
|
+
checkpoint_data: JSON.stringify(checkpointData),
|
|
199
|
+
created_at: new Date().toISOString()
|
|
200
|
+
};
|
|
201
|
+
if (!this.memoryStore.checkpoints.has(sessionId)) {
|
|
202
|
+
this.memoryStore.checkpoints.set(sessionId, []);
|
|
203
|
+
}
|
|
204
|
+
this.memoryStore.checkpoints.get(sessionId).push(checkpointEntry);
|
|
205
|
+
// Update session data
|
|
206
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
207
|
+
if (session) {
|
|
208
|
+
session.checkpoint_data = JSON.stringify(checkpointData);
|
|
209
|
+
session.updated_at = new Date().toISOString();
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
else {
|
|
213
|
+
// Save to database
|
|
214
|
+
const stmt = this.db.prepare(`
|
|
215
|
+
INSERT INTO session_checkpoints (id, session_id, checkpoint_name, checkpoint_data)
|
|
216
|
+
VALUES (?, ?, ?, ?)
|
|
217
|
+
`);
|
|
218
|
+
stmt.run(checkpointId, sessionId, checkpointName, JSON.stringify(checkpointData));
|
|
219
|
+
// Update session checkpoint data and timestamp
|
|
220
|
+
const updateStmt = this.db.prepare(`
|
|
221
|
+
UPDATE sessions
|
|
222
|
+
SET checkpoint_data = ?, updated_at = CURRENT_TIMESTAMP
|
|
223
|
+
WHERE id = ?
|
|
224
|
+
`);
|
|
225
|
+
updateStmt.run(JSON.stringify(checkpointData), sessionId);
|
|
226
|
+
}
|
|
137
227
|
// Save checkpoint file for backup
|
|
138
228
|
const checkpointFile = path.join(this.sessionsDir, `${sessionId}-${checkpointName}.json`);
|
|
139
229
|
await writeFile(checkpointFile, JSON.stringify({
|
|
@@ -143,7 +233,7 @@ export class HiveMindSessionManager {
|
|
|
143
233
|
timestamp: new Date().toISOString(),
|
|
144
234
|
data: checkpointData,
|
|
145
235
|
}, null, 2));
|
|
146
|
-
this.logSessionEvent(sessionId, 'info', `Checkpoint saved: ${checkpointName}`, null, {
|
|
236
|
+
await this.logSessionEvent(sessionId, 'info', `Checkpoint saved: ${checkpointName}`, null, {
|
|
147
237
|
checkpointId,
|
|
148
238
|
});
|
|
149
239
|
return checkpointId;
|
|
@@ -151,34 +241,84 @@ export class HiveMindSessionManager {
|
|
|
151
241
|
/**
|
|
152
242
|
* Get active sessions
|
|
153
243
|
*/
|
|
154
|
-
getActiveSessions() {
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
244
|
+
async getActiveSessions() {
|
|
245
|
+
await this.ensureInitialized();
|
|
246
|
+
if (this.isInMemory) {
|
|
247
|
+
// Use in-memory storage
|
|
248
|
+
const sessions = [];
|
|
249
|
+
for (const [sessionId, session] of this.memoryStore.sessions) {
|
|
250
|
+
if (session.status === 'active' || session.status === 'paused') {
|
|
251
|
+
sessions.push({
|
|
252
|
+
...session,
|
|
253
|
+
metadata: session.metadata ? JSON.parse(session.metadata) : {},
|
|
254
|
+
checkpoint_data: session.checkpoint_data ? JSON.parse(session.checkpoint_data) : null,
|
|
255
|
+
agent_count: 0, // Not tracked in memory mode
|
|
256
|
+
task_count: 0, // Not tracked in memory mode
|
|
257
|
+
completed_tasks: 0, // Not tracked in memory mode
|
|
258
|
+
completion_percentage: 0
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
return sessions.sort((a, b) => new Date(b.updated_at) - new Date(a.updated_at));
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
// Use SQLite
|
|
266
|
+
const stmt = this.db.prepare(`
|
|
267
|
+
SELECT s.*,
|
|
268
|
+
COUNT(DISTINCT a.id) as agent_count,
|
|
269
|
+
COUNT(DISTINCT t.id) as task_count,
|
|
270
|
+
SUM(CASE WHEN t.status = 'completed' THEN 1 ELSE 0 END) as completed_tasks
|
|
271
|
+
FROM sessions s
|
|
272
|
+
LEFT JOIN agents a ON s.swarm_id = a.swarm_id
|
|
273
|
+
LEFT JOIN tasks t ON s.swarm_id = t.swarm_id
|
|
274
|
+
WHERE s.status = 'active' OR s.status = 'paused'
|
|
275
|
+
GROUP BY s.id
|
|
276
|
+
ORDER BY s.updated_at DESC
|
|
277
|
+
`);
|
|
278
|
+
const sessions = stmt.all();
|
|
279
|
+
// Parse JSON fields
|
|
280
|
+
return sessions.map((session) => ({
|
|
281
|
+
...session,
|
|
282
|
+
metadata: session.metadata ? JSON.parse(session.metadata) : {},
|
|
283
|
+
checkpoint_data: session.checkpoint_data ? JSON.parse(session.checkpoint_data) : null,
|
|
284
|
+
completion_percentage: session.task_count > 0
|
|
285
|
+
? Math.round((session.completed_tasks / session.task_count) * 100)
|
|
286
|
+
: 0,
|
|
287
|
+
}));
|
|
288
|
+
}
|
|
177
289
|
}
|
|
178
290
|
/**
|
|
179
291
|
* Get session by ID with full details
|
|
180
292
|
*/
|
|
181
|
-
getSession(sessionId) {
|
|
293
|
+
async getSession(sessionId) {
|
|
294
|
+
await this.ensureInitialized();
|
|
295
|
+
if (this.isInMemory) {
|
|
296
|
+
// Use in-memory storage
|
|
297
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
298
|
+
if (!session) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
// Return simplified session data for in-memory mode
|
|
302
|
+
return {
|
|
303
|
+
...session,
|
|
304
|
+
metadata: session.metadata ? JSON.parse(session.metadata) : {},
|
|
305
|
+
checkpoint_data: session.checkpoint_data ? JSON.parse(session.checkpoint_data) : null,
|
|
306
|
+
swarm: null, // Not available in memory mode
|
|
307
|
+
agents: [], // Not available in memory mode
|
|
308
|
+
tasks: [], // Not available in memory mode
|
|
309
|
+
checkpoints: this.memoryStore.checkpoints.get(sessionId) || [],
|
|
310
|
+
recentLogs: this.memoryStore.logs.get(sessionId) || [],
|
|
311
|
+
statistics: {
|
|
312
|
+
totalAgents: 0,
|
|
313
|
+
activeAgents: 0,
|
|
314
|
+
totalTasks: 0,
|
|
315
|
+
completedTasks: 0,
|
|
316
|
+
pendingTasks: 0,
|
|
317
|
+
inProgressTasks: 0,
|
|
318
|
+
completionPercentage: session.completion_percentage || 0,
|
|
319
|
+
},
|
|
320
|
+
};
|
|
321
|
+
}
|
|
182
322
|
const session = this.db
|
|
183
323
|
.prepare(`
|
|
184
324
|
SELECT * FROM sessions WHERE id = ?
|
|
@@ -250,24 +390,40 @@ export class HiveMindSessionManager {
|
|
|
250
390
|
/**
|
|
251
391
|
* Pause a session
|
|
252
392
|
*/
|
|
253
|
-
pauseSession(sessionId) {
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
`);
|
|
259
|
-
const result = stmt.run(sessionId);
|
|
260
|
-
if (result.changes > 0) {
|
|
261
|
-
this.logSessionEvent(sessionId, 'info', 'Session paused');
|
|
262
|
-
// Update swarm status
|
|
263
|
-
const session = this.db.prepare('SELECT swarm_id FROM sessions WHERE id = ?').get(sessionId);
|
|
393
|
+
async pauseSession(sessionId) {
|
|
394
|
+
await this.ensureInitialized();
|
|
395
|
+
if (this.isInMemory) {
|
|
396
|
+
// Use in-memory storage
|
|
397
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
264
398
|
if (session) {
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
399
|
+
session.status = 'paused';
|
|
400
|
+
session.paused_at = new Date().toISOString();
|
|
401
|
+
session.updated_at = new Date().toISOString();
|
|
402
|
+
await this.logSessionEvent(sessionId, 'info', 'Session paused');
|
|
403
|
+
return true;
|
|
268
404
|
}
|
|
405
|
+
return false;
|
|
406
|
+
}
|
|
407
|
+
else {
|
|
408
|
+
// Use SQLite
|
|
409
|
+
const stmt = this.db.prepare(`
|
|
410
|
+
UPDATE sessions
|
|
411
|
+
SET status = 'paused', paused_at = CURRENT_TIMESTAMP, updated_at = CURRENT_TIMESTAMP
|
|
412
|
+
WHERE id = ?
|
|
413
|
+
`);
|
|
414
|
+
const result = stmt.run(sessionId);
|
|
415
|
+
if (result.changes > 0) {
|
|
416
|
+
await this.logSessionEvent(sessionId, 'info', 'Session paused');
|
|
417
|
+
// Update swarm status
|
|
418
|
+
const session = this.db.prepare('SELECT swarm_id FROM sessions WHERE id = ?').get(sessionId);
|
|
419
|
+
if (session) {
|
|
420
|
+
this.db
|
|
421
|
+
.prepare('UPDATE swarms SET status = ? WHERE id = ?')
|
|
422
|
+
.run('paused', session.swarm_id);
|
|
423
|
+
}
|
|
424
|
+
}
|
|
425
|
+
return result.changes > 0;
|
|
269
426
|
}
|
|
270
|
-
return result.changes > 0;
|
|
271
427
|
}
|
|
272
428
|
/**
|
|
273
429
|
* Resume any previous session (paused, stopped, or inactive)
|
|
@@ -360,12 +516,33 @@ export class HiveMindSessionManager {
|
|
|
360
516
|
/**
|
|
361
517
|
* Log session event
|
|
362
518
|
*/
|
|
363
|
-
logSessionEvent(sessionId, logLevel, message, agentId = null, data = null) {
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
519
|
+
async logSessionEvent(sessionId, logLevel, message, agentId = null, data = null) {
|
|
520
|
+
await this.ensureInitialized();
|
|
521
|
+
if (this.isInMemory) {
|
|
522
|
+
// Use in-memory storage for logs
|
|
523
|
+
const logId = `log-${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;
|
|
524
|
+
const logEntry = {
|
|
525
|
+
id: logId,
|
|
526
|
+
session_id: sessionId,
|
|
527
|
+
timestamp: new Date().toISOString(),
|
|
528
|
+
log_level: logLevel,
|
|
529
|
+
message,
|
|
530
|
+
agent_id: agentId,
|
|
531
|
+
data: data ? JSON.stringify(data) : null
|
|
532
|
+
};
|
|
533
|
+
if (!this.memoryStore.logs.has(sessionId)) {
|
|
534
|
+
this.memoryStore.logs.set(sessionId, []);
|
|
535
|
+
}
|
|
536
|
+
this.memoryStore.logs.get(sessionId).push(logEntry);
|
|
537
|
+
}
|
|
538
|
+
else {
|
|
539
|
+
// Use SQLite
|
|
540
|
+
const stmt = this.db.prepare(`
|
|
541
|
+
INSERT INTO session_logs (session_id, log_level, message, agent_id, data)
|
|
542
|
+
VALUES (?, ?, ?, ?, ?)
|
|
543
|
+
`);
|
|
544
|
+
stmt.run(sessionId, logLevel, message, agentId, data ? JSON.stringify(data) : null);
|
|
545
|
+
}
|
|
369
546
|
}
|
|
370
547
|
/**
|
|
371
548
|
* Get session logs
|
|
@@ -386,13 +563,25 @@ export class HiveMindSessionManager {
|
|
|
386
563
|
/**
|
|
387
564
|
* Update session progress
|
|
388
565
|
*/
|
|
389
|
-
updateSessionProgress(sessionId, completionPercentage) {
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
566
|
+
async updateSessionProgress(sessionId, completionPercentage) {
|
|
567
|
+
await this.ensureInitialized();
|
|
568
|
+
if (this.isInMemory) {
|
|
569
|
+
// Use in-memory storage
|
|
570
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
571
|
+
if (session) {
|
|
572
|
+
session.completion_percentage = completionPercentage;
|
|
573
|
+
session.updated_at = new Date().toISOString();
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
else {
|
|
577
|
+
// Use SQLite
|
|
578
|
+
const stmt = this.db.prepare(`
|
|
579
|
+
UPDATE sessions
|
|
580
|
+
SET completion_percentage = ?, updated_at = CURRENT_TIMESTAMP
|
|
581
|
+
WHERE id = ?
|
|
582
|
+
`);
|
|
583
|
+
stmt.run(completionPercentage, sessionId);
|
|
584
|
+
}
|
|
396
585
|
}
|
|
397
586
|
/**
|
|
398
587
|
* Generate session summary
|
|
@@ -514,46 +703,68 @@ export class HiveMindSessionManager {
|
|
|
514
703
|
/**
|
|
515
704
|
* Get all child PIDs for a session
|
|
516
705
|
*/
|
|
517
|
-
getChildPids(sessionId) {
|
|
518
|
-
|
|
519
|
-
if (
|
|
520
|
-
|
|
521
|
-
|
|
706
|
+
async getChildPids(sessionId) {
|
|
707
|
+
await this.ensureInitialized();
|
|
708
|
+
if (this.isInMemory) {
|
|
709
|
+
// Use in-memory storage
|
|
710
|
+
const session = this.memoryStore.sessions.get(sessionId);
|
|
711
|
+
if (!session || !session.child_pids)
|
|
712
|
+
return [];
|
|
713
|
+
return JSON.parse(session.child_pids);
|
|
714
|
+
}
|
|
715
|
+
else {
|
|
716
|
+
// Use SQLite
|
|
717
|
+
const session = this.db.prepare('SELECT child_pids FROM sessions WHERE id = ?').get(sessionId);
|
|
718
|
+
if (!session || !session.child_pids)
|
|
719
|
+
return [];
|
|
720
|
+
return JSON.parse(session.child_pids);
|
|
721
|
+
}
|
|
522
722
|
}
|
|
523
723
|
/**
|
|
524
724
|
* Stop a session and terminate all child processes
|
|
525
725
|
*/
|
|
526
726
|
async stopSession(sessionId) {
|
|
527
|
-
const session = this.getSession(sessionId);
|
|
727
|
+
const session = await this.getSession(sessionId);
|
|
528
728
|
if (!session) {
|
|
529
729
|
throw new Error(`Session ${sessionId} not found`);
|
|
530
730
|
}
|
|
531
731
|
// Get child PIDs
|
|
532
|
-
const childPids = this.getChildPids(sessionId);
|
|
732
|
+
const childPids = await this.getChildPids(sessionId);
|
|
533
733
|
// Terminate child processes
|
|
534
734
|
for (const pid of childPids) {
|
|
535
735
|
try {
|
|
536
736
|
process.kill(pid, 'SIGTERM');
|
|
537
|
-
this.logSessionEvent(sessionId, 'info', 'Child process terminated', null, { pid });
|
|
737
|
+
await this.logSessionEvent(sessionId, 'info', 'Child process terminated', null, { pid });
|
|
538
738
|
}
|
|
539
739
|
catch (err) {
|
|
540
740
|
// Process might already be dead
|
|
541
|
-
this.logSessionEvent(sessionId, 'warning', 'Failed to terminate child process', null, {
|
|
741
|
+
await this.logSessionEvent(sessionId, 'warning', 'Failed to terminate child process', null, {
|
|
542
742
|
pid,
|
|
543
743
|
error: err.message,
|
|
544
744
|
});
|
|
545
745
|
}
|
|
546
746
|
}
|
|
547
747
|
// Update session status
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
748
|
+
if (this.isInMemory) {
|
|
749
|
+
// Use in-memory storage
|
|
750
|
+
const sessionData = this.memoryStore.sessions.get(sessionId);
|
|
751
|
+
if (sessionData) {
|
|
752
|
+
sessionData.status = 'stopped';
|
|
753
|
+
sessionData.updated_at = new Date().toISOString();
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
else {
|
|
757
|
+
// Use SQLite
|
|
758
|
+
const stmt = this.db.prepare(`
|
|
759
|
+
UPDATE sessions
|
|
760
|
+
SET status = 'stopped', updated_at = CURRENT_TIMESTAMP
|
|
761
|
+
WHERE id = ?
|
|
762
|
+
`);
|
|
763
|
+
stmt.run(sessionId);
|
|
764
|
+
// Update swarm status
|
|
765
|
+
this.db.prepare('UPDATE swarms SET status = ? WHERE id = ?').run('stopped', session.swarm_id);
|
|
766
|
+
}
|
|
767
|
+
await this.logSessionEvent(sessionId, 'info', 'Session stopped');
|
|
557
768
|
return true;
|
|
558
769
|
}
|
|
559
770
|
/**
|
|
@@ -612,7 +823,9 @@ export class HiveMindSessionManager {
|
|
|
612
823
|
* Clean up and close database connection
|
|
613
824
|
*/
|
|
614
825
|
close() {
|
|
615
|
-
this.db.
|
|
826
|
+
if (this.db && !this.isInMemory) {
|
|
827
|
+
this.db.close();
|
|
828
|
+
}
|
|
616
829
|
}
|
|
617
830
|
}
|
|
618
831
|
// Export for use in other modules
|