@sethdouglasford/claude-flow
Version:
Claude Code Flow - Advanced AI-powered development workflows with SPARC methodology
186 lines • 7.06 kB
JavaScript
/**
* Persistence layer for Claude-Flow using SQLite
*/
import Database from "better-sqlite3";
import { join } from "path";
import { mkdir } from "fs/promises";
export class PersistenceManager {
db;
dbPath;
constructor(dataDir = "./memory") {
this.dbPath = join(dataDir, "claude-flow.db");
}
async initialize() {
// Ensure directory exists
await mkdir(join(this.dbPath, ".."), { recursive: true });
// Open database
this.db = new Database(this.dbPath);
// Create tables if they don't exist
this.createTables();
}
createTables() {
// Agents table
this.db.exec(`
CREATE TABLE IF NOT EXISTS agents (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
name TEXT NOT NULL,
status TEXT NOT NULL,
capabilities TEXT NOT NULL,
system_prompt TEXT NOT NULL,
max_concurrent_tasks INTEGER NOT NULL,
priority INTEGER NOT NULL,
created_at INTEGER NOT NULL
)
`);
// Tasks table
this.db.exec(`
CREATE TABLE IF NOT EXISTS tasks (
id TEXT PRIMARY KEY,
type TEXT NOT NULL,
description TEXT NOT NULL,
status TEXT NOT NULL,
priority INTEGER NOT NULL,
dependencies TEXT NOT NULL,
metadata TEXT NOT NULL,
assigned_agent TEXT,
progress INTEGER DEFAULT 0,
error TEXT,
created_at INTEGER NOT NULL,
completed_at INTEGER
)
`);
// Sessions table for terminal sessions
this.db.exec(`
CREATE TABLE IF NOT EXISTS sessions (
id TEXT PRIMARY KEY,
agent_id TEXT NOT NULL,
terminal_id TEXT NOT NULL,
status TEXT NOT NULL,
created_at INTEGER NOT NULL,
FOREIGN KEY (agent_id) REFERENCES agents(id)
)
`);
}
// Agent operations
saveAgent(agent) {
const stmt = this.db.prepare(`INSERT OR REPLACE INTO agents
(id, type, name, status, capabilities, system_prompt, max_concurrent_tasks, priority, created_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`);
stmt.run(agent.id, agent.type, agent.name, agent.status, agent.capabilities, agent.systemPrompt, agent.maxConcurrentTasks, agent.priority, agent.createdAt);
}
getAgent(id) {
const stmt = this.db.prepare("SELECT * FROM agents WHERE id = ?");
const row = stmt.get(id);
if (!row)
return null;
return {
id: row.id,
type: row.type,
name: row.name,
status: row.status,
capabilities: row.capabilities,
systemPrompt: row.system_prompt,
maxConcurrentTasks: row.max_concurrent_tasks,
priority: row.priority,
createdAt: row.created_at,
};
}
async getActiveAgents() {
const stmt = this.db.prepare("SELECT * FROM agents WHERE status IN ('active', 'idle') ORDER BY created_at DESC");
const rows = stmt.all();
return rows.map(row => ({
id: row.id,
type: row.type,
name: row.name,
status: row.status,
capabilities: row.capabilities,
systemPrompt: row.system_prompt,
maxConcurrentTasks: row.max_concurrent_tasks,
priority: row.priority,
createdAt: row.created_at,
}));
}
async updateAgentStatus(id, status) {
const stmt = this.db.prepare("UPDATE agents SET status = ? WHERE id = ?");
stmt.run(status, id);
}
// Task operations
async saveTask(task) {
const stmt = this.db.prepare(`INSERT OR REPLACE INTO tasks
(id, type, description, status, priority, dependencies, metadata, assigned_agent, progress, error, created_at, completed_at)
VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`);
stmt.run(task.id, task.type, task.description, task.status, task.priority, task.dependencies, task.metadata, task.assignedAgent || null, task.progress, task.error || null, task.createdAt, task.completedAt || null);
}
async getTask(id) {
const stmt = this.db.prepare("SELECT * FROM tasks WHERE id = ?");
const row = stmt.get(id);
if (!row)
return null;
return {
id: row.id,
type: row.type,
description: row.description,
status: row.status,
priority: row.priority,
dependencies: row.dependencies,
metadata: row.metadata,
assignedAgent: row.assigned_agent || undefined,
progress: row.progress,
error: row.error || undefined,
createdAt: row.created_at,
completedAt: row.completed_at || undefined,
};
}
async getActiveTasks() {
const stmt = this.db.prepare("SELECT * FROM tasks WHERE status IN ('pending', 'in_progress', 'assigned') ORDER BY priority DESC, created_at ASC");
const rows = stmt.all();
return rows.map(row => ({
id: row.id,
type: row.type,
description: row.description,
status: row.status,
priority: row.priority,
dependencies: row.dependencies,
metadata: row.metadata,
assignedAgent: row.assigned_agent || undefined,
progress: row.progress,
error: row.error || undefined,
createdAt: row.created_at,
completedAt: row.completed_at || undefined,
}));
}
async updateTaskStatus(id, status, assignedAgent) {
if (assignedAgent) {
const stmt = this.db.prepare("UPDATE tasks SET status = ?, assigned_agent = ? WHERE id = ?");
stmt.run(status, assignedAgent, id);
}
else {
const stmt = this.db.prepare("UPDATE tasks SET status = ? WHERE id = ?");
stmt.run(status, id);
}
}
async updateTaskProgress(id, progress) {
const stmt = this.db.prepare("UPDATE tasks SET progress = ? WHERE id = ?");
stmt.run(progress, id);
}
// Statistics
async getStats() {
const totalAgents = this.db.prepare("SELECT COUNT(*) as count FROM agents").get();
const activeAgents = this.db.prepare("SELECT COUNT(*) as count FROM agents WHERE status IN ('active', 'idle')").get();
const totalTasks = this.db.prepare("SELECT COUNT(*) as count FROM tasks").get();
const pendingTasks = this.db.prepare("SELECT COUNT(*) as count FROM tasks WHERE status IN ('pending', 'in_progress', 'assigned')").get();
const completedTasks = this.db.prepare("SELECT COUNT(*) as count FROM tasks WHERE status = 'completed'").get();
return {
totalAgents: totalAgents.count,
activeAgents: activeAgents.count,
totalTasks: totalTasks.count,
pendingTasks: pendingTasks.count,
completedTasks: completedTasks.count,
};
}
close() {
this.db.close();
}
}
//# sourceMappingURL=persistence.js.map