Files
Agents-Orchestrator/src/store/db.js
Frederico Castro 2f7a9d4c56 Implementação completa de funcionalidades pendentes
- Settings persistentes (modelo padrão, workdir, max concurrent)
- Import/export de agentes via JSON
- Agendamentos persistentes com restore no startup
- Edição de agendamentos e tarefas existentes
- Filtros e busca em todas as seções
- Isolamento de WebSocket por clientId
- Autenticação via AUTH_TOKEN e CORS configurável
- Graceful shutdown com cancelamento de execuções
- Correção: --max-tokens removido (flag inválida do CLI)
- Correção: pipeline agora verifica exit code e propaga erros
- Correção: streaming de output em pipelines via WebSocket
- Permission mode bypassPermissions como padrão
- Página de configurações do sistema
- Contagem diária de execuções no dashboard
- Histórico de execuções recentes
2026-02-26 01:24:51 -03:00

141 lines
3.9 KiB
JavaScript

import { readFileSync, writeFileSync, existsSync, mkdirSync, statSync } from 'fs';
import { dirname } from 'path';
import { fileURLToPath } from 'url';
import { v4 as uuidv4 } from 'uuid';
const __dirname = dirname(fileURLToPath(import.meta.url));
const DATA_DIR = `${__dirname}/../../data`;
const AGENTS_FILE = `${DATA_DIR}/agents.json`;
const TASKS_FILE = `${DATA_DIR}/tasks.json`;
const PIPELINES_FILE = `${DATA_DIR}/pipelines.json`;
const SCHEDULES_FILE = `${DATA_DIR}/schedules.json`;
const SETTINGS_FILE = `${DATA_DIR}/settings.json`;
const DEFAULT_SETTINGS = {
defaultModel: 'claude-sonnet-4-6',
defaultWorkdir: '',
maxConcurrent: 5,
};
const writeLocks = new Map();
const fileCache = new Map();
function ensureDataDir() {
if (!existsSync(DATA_DIR)) {
mkdirSync(DATA_DIR, { recursive: true });
}
}
function getCacheMtime(filePath) {
const cached = fileCache.get(filePath);
if (!cached) return null;
return cached.mtime;
}
function loadFile(filePath, defaultValue = []) {
ensureDataDir();
if (!existsSync(filePath)) {
writeFileSync(filePath, JSON.stringify(defaultValue, null, 2), 'utf8');
fileCache.set(filePath, { data: defaultValue, mtime: Date.now() });
return JSON.parse(JSON.stringify(defaultValue));
}
try {
const stat = statSync(filePath);
const mtime = stat.mtimeMs;
const cached = fileCache.get(filePath);
if (cached && cached.mtime === mtime) {
return JSON.parse(JSON.stringify(cached.data));
}
const data = JSON.parse(readFileSync(filePath, 'utf8'));
fileCache.set(filePath, { data, mtime });
return JSON.parse(JSON.stringify(data));
} catch {
return JSON.parse(JSON.stringify(defaultValue));
}
}
function saveFile(filePath, data) {
ensureDataDir();
const prev = writeLocks.get(filePath) || Promise.resolve();
const next = prev.then(() => {
writeFileSync(filePath, JSON.stringify(data, null, 2), 'utf8');
const stat = statSync(filePath);
fileCache.set(filePath, { data: JSON.parse(JSON.stringify(data)), mtime: stat.mtimeMs });
}).catch(() => {});
writeLocks.set(filePath, next);
return next;
}
function createStore(filePath) {
return {
load: () => loadFile(filePath),
save: (data) => saveFile(filePath, data),
getAll: () => loadFile(filePath),
getById: (id) => {
const items = loadFile(filePath);
return items.find((item) => item.id === id) || null;
},
create: (data) => {
const items = loadFile(filePath);
const newItem = {
id: uuidv4(),
...data,
created_at: new Date().toISOString(),
updated_at: new Date().toISOString(),
};
items.push(newItem);
saveFile(filePath, items);
return newItem;
},
update: (id, data) => {
const items = loadFile(filePath);
const index = items.findIndex((item) => item.id === id);
if (index === -1) return null;
items[index] = {
...items[index],
...data,
id,
updated_at: new Date().toISOString(),
};
saveFile(filePath, items);
return items[index];
},
delete: (id) => {
const items = loadFile(filePath);
const index = items.findIndex((item) => item.id === id);
if (index === -1) return false;
items.splice(index, 1);
saveFile(filePath, items);
return true;
},
};
}
function createSettingsStore(filePath) {
return {
get: () => loadFile(filePath, DEFAULT_SETTINGS),
save: (data) => {
const current = loadFile(filePath, DEFAULT_SETTINGS);
const merged = { ...current, ...data };
saveFile(filePath, merged);
return merged;
},
};
}
export const agentsStore = createStore(AGENTS_FILE);
export const tasksStore = createStore(TASKS_FILE);
export const pipelinesStore = createStore(PIPELINES_FILE);
export const schedulesStore = createStore(SCHEDULES_FILE);
export const settingsStore = createSettingsStore(SETTINGS_FILE);