UNPKG

automagik-genie

Version:

Self-evolving AI agent orchestration framework with Model Context Protocol support

164 lines (163 loc) 6.46 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports._internals = void 0; exports.loadTasks = loadTasks; exports.saveTasks = saveTasks; const fs_1 = __importDefault(require("fs")); const executor_registry_1 = require("./lib/executor-registry"); function loadTasks(paths = {}, config = {}, defaults = {}, callbacks = {}) { const storePath = paths.tasksFile; let store; if (storePath && fs_1.default.existsSync(storePath)) { store = normalizeTaskStore(readJson(storePath, callbacks), callbacks); } else { store = { version: 4, sessions: {} }; } const defaultExecutor = resolveDefaultExecutor(config, defaults); return migrateTaskEntries(store, defaultExecutor); } function saveTasks(paths = {}, store) { const target = paths.tasksFile; if (!target) return; const payload = JSON.stringify(store, null, 2); fs_1.default.writeFileSync(target, payload); } function readJson(filePath, callbacks) { const content = fs_1.default.readFileSync(filePath, 'utf8'); if (!content.trim().length) return {}; try { return JSON.parse(content); } catch (error) { const message = error instanceof Error ? error.message : String(error); callbacks.onWarning?.(`Could not parse JSON from ${filePath}: ${message}`); return {}; } } function normalizeTaskStore(data, callbacks = {}) { if (!data || typeof data !== 'object') { return { version: 4, sessions: {} }; } const incoming = data; // Version 4 format (sessions keyed by attemptId/UUID) - current if (incoming.version === 4 && incoming.sessions) { return { version: 4, sessions: incoming.sessions }; } // Version 3 or earlier - MIGRATE to v4 // Rationale: Preserve user's ability to resume/stop/view existing tasks // Key change: Use attemptId (from v3's sessionId field) as the v4 key if (incoming.version && incoming.version < 4) { const sessions = {}; let migratedCount = 0; // v3 sessions were keyed by friendly name, need to rekey by attemptId Object.entries(incoming.sessions || {}).forEach(([_friendlyName, entry]) => { if (!entry || typeof entry !== 'object') return; // v3 stored attemptId in the 'sessionId' field const attemptId = entry.sessionId; if (!attemptId || typeof attemptId !== 'string') return; // Migrate to v4 format (taskId/projectId will be undefined for migrated sessions) sessions[attemptId] = { agent: entry.agent, // taskId and projectId omitted (not available in v3) preset: entry.preset, mode: entry.mode, executor: entry.executor, executorVariant: entry.executorVariant, model: entry.model, status: entry.status, created: entry.created, lastUsed: entry.lastUsed, lastPrompt: entry.lastPrompt, forgeUrl: entry.forgeUrl, background: entry.background }; migratedCount++; }); callbacks.onWarning?.(`Migrated ${migratedCount} task(s) from v${incoming.version} to v4. ` + `Tasks can be viewed/resumed/stopped using their IDs. ` + `Some metadata (taskId/projectId) may be incomplete for migrated tasks.`); return { version: 4, sessions }; } // No version number - treat as v2 and migrate if (!incoming.version && incoming.sessions) { const sessions = {}; let migratedCount = 0; // v2 sessions were keyed by taskId (attemptId), already in correct format Object.entries(incoming.sessions).forEach(([attemptId, entry]) => { if (!entry || typeof entry !== 'object') return; // v2 already used attemptId as key, just need to copy fields sessions[attemptId] = { agent: entry.agent, // taskId and projectId omitted (not available in v2) preset: entry.preset, mode: entry.mode, executor: entry.executor, executorVariant: entry.executorVariant, model: entry.model, status: entry.status, created: entry.created, lastUsed: entry.lastUsed, lastPrompt: entry.lastPrompt, forgeUrl: entry.forgeUrl, background: entry.background }; migratedCount++; }); callbacks.onWarning?.(`Migrated ${migratedCount} task(s) from v2 to v4. ` + `Tasks can be viewed/resumed/stopped using their IDs. ` + `Some metadata (taskId/projectId) may be incomplete for migrated tasks.`); return { version: 4, sessions }; } // Empty or malformed return { version: 4, sessions: {} }; } function migrateTaskEntries(store, defaultExecutor) { const result = { version: store.version ?? 4, sessions: { ...store.sessions } }; // Migrate session entries (apply defaults) Object.entries(result.sessions || {}).forEach(([attemptId, entry]) => { if (!entry || typeof entry !== 'object') return; if (!entry.mode && entry.preset) result.sessions[attemptId].mode = entry.preset; if (!entry.preset && entry.mode) result.sessions[attemptId].preset = entry.mode; const normalized = entry.executor ? (0, executor_registry_1.normalizeExecutorKey)(entry.executor) : undefined; result.sessions[attemptId].executor = normalized ?? defaultExecutor; }); return result; } function resolveDefaultExecutor(config = {}, defaults = {}) { return (0, executor_registry_1.normalizeExecutorKeyOrDefault)(config.defaults?.executor ?? defaults.defaults?.executor ?? executor_registry_1.DEFAULT_EXECUTOR_KEY, executor_registry_1.DEFAULT_EXECUTOR_KEY); } exports._internals = { readJson, normalizeTaskStore, migrateTaskEntries, resolveDefaultExecutor };