pack
This commit is contained in:
232
agent-system/storage/memory-store.ts
Normal file
232
agent-system/storage/memory-store.ts
Normal file
@@ -0,0 +1,232 @@
|
||||
/**
|
||||
* Agent Storage Module
|
||||
*
|
||||
* Persistent storage for agent state, conversations, and results.
|
||||
* Uses filesystem for persistence.
|
||||
*/
|
||||
|
||||
import { writeFileSync, readFileSync, existsSync, mkdirSync, readdirSync, unlinkSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const STORAGE_DIR = join(process.cwd(), '.agent-storage');
|
||||
|
||||
export interface StoredConversation {
|
||||
id: string;
|
||||
agentId: string;
|
||||
messages: Array<{
|
||||
role: 'user' | 'assistant' | 'system';
|
||||
content: string;
|
||||
timestamp: string;
|
||||
}>;
|
||||
metadata?: Record<string, unknown>;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
export interface StoredTask {
|
||||
id: string;
|
||||
type: string;
|
||||
status: string;
|
||||
input: unknown;
|
||||
output?: unknown;
|
||||
error?: string;
|
||||
createdAt: string;
|
||||
completedAt?: string;
|
||||
}
|
||||
|
||||
export interface StoredAgentState {
|
||||
id: string;
|
||||
name: string;
|
||||
type: string;
|
||||
status: string;
|
||||
memory: Record<string, unknown>;
|
||||
createdAt: string;
|
||||
updatedAt: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* AgentStorage - Persistent storage for agents
|
||||
*/
|
||||
export class AgentStorage {
|
||||
private baseDir: string;
|
||||
|
||||
constructor(baseDir: string = STORAGE_DIR) {
|
||||
this.baseDir = baseDir;
|
||||
this.ensureDirectory();
|
||||
}
|
||||
|
||||
/**
|
||||
* Ensure storage directory exists
|
||||
*/
|
||||
private ensureDirectory(): void {
|
||||
if (!existsSync(this.baseDir)) {
|
||||
mkdirSync(this.baseDir, { recursive: true });
|
||||
}
|
||||
|
||||
const subdirs = ['conversations', 'tasks', 'agents'];
|
||||
for (const subdir of subdirs) {
|
||||
const dir = join(this.baseDir, subdir);
|
||||
if (!existsSync(dir)) {
|
||||
mkdirSync(dir, { recursive: true });
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a conversation
|
||||
*/
|
||||
saveConversation(conversation: StoredConversation): void {
|
||||
const path = join(this.baseDir, 'conversations', `${conversation.id}.json`);
|
||||
writeFileSync(path, JSON.stringify(conversation, null, 2), 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a conversation
|
||||
*/
|
||||
loadConversation(id: string): StoredConversation | null {
|
||||
try {
|
||||
const path = join(this.baseDir, 'conversations', `${id}.json`);
|
||||
if (!existsSync(path)) return null;
|
||||
return JSON.parse(readFileSync(path, 'utf-8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all conversations
|
||||
*/
|
||||
listConversations(agentId?: string): StoredConversation[] {
|
||||
const dir = join(this.baseDir, 'conversations');
|
||||
if (!existsSync(dir)) return [];
|
||||
|
||||
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
||||
|
||||
return files.map(file => {
|
||||
const content = readFileSync(join(dir, file), 'utf-8');
|
||||
return JSON.parse(content) as StoredConversation;
|
||||
}).filter(conv => !agentId || conv.agentId === agentId);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a conversation
|
||||
*/
|
||||
deleteConversation(id: string): boolean {
|
||||
try {
|
||||
const path = join(this.baseDir, 'conversations', `${id}.json`);
|
||||
if (existsSync(path)) {
|
||||
unlinkSync(path);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save a task
|
||||
*/
|
||||
saveTask(task: StoredTask): void {
|
||||
const path = join(this.baseDir, 'tasks', `${task.id}.json`);
|
||||
writeFileSync(path, JSON.stringify(task, null, 2), 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a task
|
||||
*/
|
||||
loadTask(id: string): StoredTask | null {
|
||||
try {
|
||||
const path = join(this.baseDir, 'tasks', `${id}.json`);
|
||||
if (!existsSync(path)) return null;
|
||||
return JSON.parse(readFileSync(path, 'utf-8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all tasks
|
||||
*/
|
||||
listTasks(status?: string): StoredTask[] {
|
||||
const dir = join(this.baseDir, 'tasks');
|
||||
if (!existsSync(dir)) return [];
|
||||
|
||||
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
||||
|
||||
return files.map(file => {
|
||||
const content = readFileSync(join(dir, file), 'utf-8');
|
||||
return JSON.parse(content) as StoredTask;
|
||||
}).filter(task => !status || task.status === status);
|
||||
}
|
||||
|
||||
/**
|
||||
* Save agent state
|
||||
*/
|
||||
saveAgentState(state: StoredAgentState): void {
|
||||
const path = join(this.baseDir, 'agents', `${state.id}.json`);
|
||||
writeFileSync(path, JSON.stringify(state, null, 2), 'utf-8');
|
||||
}
|
||||
|
||||
/**
|
||||
* Load agent state
|
||||
*/
|
||||
loadAgentState(id: string): StoredAgentState | null {
|
||||
try {
|
||||
const path = join(this.baseDir, 'agents', `${id}.json`);
|
||||
if (!existsSync(path)) return null;
|
||||
return JSON.parse(readFileSync(path, 'utf-8'));
|
||||
} catch {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* List all agent states
|
||||
*/
|
||||
listAgentStates(): StoredAgentState[] {
|
||||
const dir = join(this.baseDir, 'agents');
|
||||
if (!existsSync(dir)) return [];
|
||||
|
||||
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
||||
|
||||
return files.map(file => {
|
||||
const content = readFileSync(join(dir, file), 'utf-8');
|
||||
return JSON.parse(content) as StoredAgentState;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear all storage
|
||||
*/
|
||||
clearAll(): void {
|
||||
const subdirs = ['conversations', 'tasks', 'agents'];
|
||||
for (const subdir of subdirs) {
|
||||
const dir = join(this.baseDir, subdir);
|
||||
if (existsSync(dir)) {
|
||||
const files = readdirSync(dir).filter(f => f.endsWith('.json'));
|
||||
for (const file of files) {
|
||||
unlinkSync(join(dir, file));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get storage stats
|
||||
*/
|
||||
getStats(): {
|
||||
conversations: number;
|
||||
tasks: number;
|
||||
agents: number;
|
||||
} {
|
||||
return {
|
||||
conversations: this.listConversations().length,
|
||||
tasks: this.listTasks().length,
|
||||
agents: this.listAgentStates().length
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// Default storage instance
|
||||
export const defaultStorage = new AgentStorage();
|
||||
Reference in New Issue
Block a user