// engine/ecosystem-absorber/knowledge-cache.ts — Reads/writes ecosystem capability cache
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
import { join } from 'node:path';
const CACHE_VERSION = '1';
const PRUNE_DAYS = 30;
const DATA_DIR = join(process.cwd(), 'data', 'ecosystem');
const CACHE_FILE = join(DATA_DIR, 'capabilities.json');
function emptyCache() {
    return { lastCrawled: {}, capabilities: [], version: CACHE_VERSION };
}
function ensureDir() {
    if (!existsSync(DATA_DIR)) {
        mkdirSync(DATA_DIR, { recursive: true });
    }
}
/**
 * Read the ecosystem cache from disk. Returns empty cache on any error.
 */
export function readCache() {
    try {
        if (!existsSync(CACHE_FILE)) {
            return emptyCache();
        }
        const raw = readFileSync(CACHE_FILE, 'utf-8');
        const parsed = JSON.parse(raw);
        return {
            lastCrawled: parsed.lastCrawled ?? {},
            capabilities: Array.isArray(parsed.capabilities) ? parsed.capabilities : [],
            version: parsed.version ?? CACHE_VERSION,
        };
    }
    catch {
        return emptyCache();
    }
}
/**
 * Write updated cache to disk. Silently ignores write errors.
 */
export function writeCache(cache) {
    try {
        ensureDir();
        writeFileSync(CACHE_FILE, JSON.stringify(cache, null, 2), 'utf-8');
    }
    catch {
        // Graceful degradation — do not throw
    }
}
/**
 * Merge new capabilities into existing cache, deduplicating by id.
 * Prunes capabilities older than PRUNE_DAYS days.
 */
export function mergeCapabilities(existing, incoming) {
    const cutoff = Date.now() - PRUNE_DAYS * 24 * 60 * 60 * 1000;
    const map = new Map();
    for (const cap of existing) {
        const ts = new Date(cap.discoveredAt).getTime();
        if (ts >= cutoff) {
            map.set(cap.id, cap);
        }
    }
    for (const cap of incoming) {
        map.set(cap.id, cap);
    }
    return Array.from(map.values());
}
/**
 * Check whether a source needs re-crawling given its TTL in hours.
 */
export function isCacheStale(lastCrawled, sourceId, intervalHours) {
    const last = lastCrawled[sourceId];
    if (!last) {
        return true;
    }
    const elapsed = (Date.now() - new Date(last).getTime()) / 3_600_000;
    return elapsed >= intervalHours;
}
/**
 * Update the lastCrawled timestamp for a source.
 */
export function markCrawled(lastCrawled, sourceId) {
    return { ...lastCrawled, [sourceId]: new Date().toISOString() };
}
//# sourceMappingURL=knowledge-cache.js.map