claude-flow
Version:
Enterprise-grade AI agent orchestration with ruv-swarm integration (Alpha Release)
183 lines (158 loc) • 4.72 kB
text/typescript
import { getErrorMessage } from '../utils/error-handler.js';
/**
* JSON-based persistence layer for Claude-Flow
*/
import { join } from "path";
import { mkdir, access, readFile, writeFile } from "fs/promises";
export interface PersistedAgent {
id: string;
type: string;
name: string;
status: string;
capabilities: string[];
systemPrompt: string;
maxConcurrentTasks: number;
priority: number;
createdAt: number;
}
export interface PersistedTask {
id: string;
type: string;
description: string;
status: string;
priority: number;
dependencies: string[];
metadata: Record<string, unknown>;
assignedAgent?: string;
progress: number;
error?: string;
createdAt: number;
completedAt?: number;
}
interface PersistenceData {
agents: PersistedAgent[];
tasks: PersistedTask[];
lastUpdated: number;
}
export class JsonPersistenceManager {
private dataPath: string;
private data: PersistenceData;
constructor(dataDir: string = "./memory") {
this.dataPath = join(dataDir, "claude-flow-data.json");
this.data = {
agents: [],
tasks: [],
lastUpdated: Date.now(),
};
}
async initialize(): Promise<void> {
// Ensure directory exists
await mkdir(join(this.dataPath, ".."), { recursive: true });
// Load existing data if available
try {
await access(this.dataPath);
const content = await readFile(this.dataPath, "utf-8");
this.data = JSON.parse(content);
} catch (error) {
// File doesn't exist or can't be read, keep default empty data
console.error("Failed to load persistence data:", error);
}
}
private async save(): Promise<void> {
this.data.lastUpdated = Date.now();
await writeFile(this.dataPath, JSON.stringify(this.data, null, 2));
}
// Agent operations
async saveAgent(agent: PersistedAgent): Promise<void> {
// Remove existing agent if updating
this.data.agents = this.data.agents.filter(a => a.id !== agent.id);
this.data.agents.push(agent);
await this.save();
}
async getAgent(id: string): Promise<PersistedAgent | null> {
return this.data.agents.find(a => a.id === id) || null;
}
async getActiveAgents(): Promise<PersistedAgent[]> {
return this.data.agents.filter(a => a.status === 'active' || a.status === 'idle');
}
async getAllAgents(): Promise<PersistedAgent[]> {
return this.data.agents;
}
async updateAgentStatus(id: string, status: string): Promise<void> {
const agent = this.data.agents.find(a => a.id === id);
if (agent) {
agent.status = status;
await this.save();
}
}
// Task operations
async saveTask(task: PersistedTask): Promise<void> {
// Remove existing task if updating
this.data.tasks = this.data.tasks.filter(t => t.id !== task.id);
this.data.tasks.push(task);
await this.save();
}
async getTask(id: string): Promise<PersistedTask | null> {
return this.data.tasks.find(t => t.id === id) || null;
}
async getActiveTasks(): Promise<PersistedTask[]> {
return this.data.tasks.filter(t =>
t.status === 'pending' ||
t.status === 'in_progress' ||
t.status === 'assigned'
);
}
async getAllTasks(): Promise<PersistedTask[]> {
return this.data.tasks;
}
async updateTaskStatus(id: string, status: string, assignedAgent?: string): Promise<void> {
const task = this.data.tasks.find(t => t.id === id);
if (task) {
task.status = status;
if (assignedAgent !== undefined) {
task.assignedAgent = assignedAgent;
}
if (status === 'completed') {
task.completedAt = Date.now();
}
await this.save();
}
}
async updateTaskProgress(id: string, progress: number): Promise<void> {
const task = this.data.tasks.find(t => t.id === id);
if (task) {
task.progress = progress;
await this.save();
}
}
// Statistics
async getStats(): Promise<{
totalAgents: number;
activeAgents: number;
totalTasks: number;
pendingTasks: number;
completedTasks: number;
}> {
const activeAgents = this.data.agents.filter(a =>
a.status === 'active' || a.status === 'idle'
).length;
const pendingTasks = this.data.tasks.filter(t =>
t.status === 'pending' ||
t.status === 'in_progress' ||
t.status === 'assigned'
).length;
const completedTasks = this.data.tasks.filter(t =>
t.status === 'completed'
).length;
return {
totalAgents: this.data.agents.length,
activeAgents,
totalTasks: this.data.tasks.length,
pendingTasks,
completedTasks,
};
}
close(): void {
// No-op for JSON persistence
}
}