import fs from 'fs/promises'; import path from 'path'; import { env } from '../config/env'; import { logger } from '../utils/logger'; import { AgentError } from '../middleware/error-handler'; interface SlugEntry { basePath: string; composeProject: string; registeredAt: string; } type Registry = Record; const registryPath = () => path.join(env.AGENT_DATA_DIR, 'registry.json'); let cache: Registry | null = null; async function loadRegistry(): Promise { if (cache) return cache; try { const data = await fs.readFile(registryPath(), 'utf-8'); cache = JSON.parse(data) as Registry; return cache; } catch { cache = {}; return cache; } } async function saveRegistry(registry: Registry): Promise { await fs.mkdir(env.AGENT_DATA_DIR, { recursive: true }); await fs.writeFile(registryPath(), JSON.stringify(registry, null, 2), 'utf-8'); cache = registry; } export async function registerSlug(slug: string, basePath: string, composeProject: string): Promise { const registry = await loadRegistry(); registry[slug] = { basePath, composeProject, registeredAt: new Date().toISOString(), }; await saveRegistry(registry); logger.info(`[registry] Registered slug ${slug} → ${basePath} (project: ${composeProject})`); } export async function unregisterSlug(slug: string): Promise { const registry = await loadRegistry(); if (!registry[slug]) { throw new AgentError(404, `Slug ${slug} not registered`); } delete registry[slug]; await saveRegistry(registry); logger.info(`[registry] Unregistered slug ${slug}`); } export async function getSlugEntry(slug: string): Promise { const registry = await loadRegistry(); const entry = registry[slug]; if (!entry) { throw new AgentError(404, `Slug ${slug} not registered`, 'SLUG_NOT_FOUND'); } return entry; } export async function listSlugs(): Promise> { return loadRegistry(); }