"use strict";
// SPDX-License-Identifier: AGPL-3.0-or-later
// Copyright (C) 2024-2026 Gracker (Chris)
// This file is part of SmartPerfetto. See LICENSE for details.
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
    var ownKeys = function(o) {
        ownKeys = Object.getOwnPropertyNames || function (o) {
            var ar = [];
            for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
            return ar;
        };
        return ownKeys(o);
    };
    return function (mod) {
        if (mod && mod.__esModule) return mod;
        var result = {};
        if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
        __setModuleDefault(result, mod);
        return result;
    };
})();
Object.defineProperty(exports, "__esModule", { value: true });
exports.CheckpointManager = void 0;
/**
 * SmartPerfetto Checkpoint Manager
 *
 * 检查点管理器，负责：
 * 1. 创建和保存检查点
 * 2. 恢复检查点
 * 3. 清理过期检查点
 */
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
// 默认检查点目录
const DEFAULT_CHECKPOINT_DIR = path.join(process.cwd(), 'agent-checkpoints');
// 检查点保留时间（默认 24 小时）
const DEFAULT_RETENTION_MS = 24 * 60 * 60 * 1000;
/**
 * 检查点管理器实现
 */
class CheckpointManager {
    constructor(config = {}) {
        this.config = {
            checkpointDir: config.checkpointDir || DEFAULT_CHECKPOINT_DIR,
            retentionMs: config.retentionMs || DEFAULT_RETENTION_MS,
            maxCheckpointsPerSession: config.maxCheckpointsPerSession || 10,
        };
        this.checkpointDir = this.config.checkpointDir;
        this.ensureDirectory();
    }
    // ==========================================================================
    // 检查点创建
    // ==========================================================================
    /**
     * 创建检查点
     */
    async createCheckpoint(sessionId, stageId, phase, stageResults, findings, additionalState) {
        const checkpointId = this.generateCheckpointId(sessionId, stageId);
        const checkpoint = {
            id: checkpointId,
            stageId,
            timestamp: Date.now(),
            phase,
            agentState: {
                query: additionalState?.query || '',
                traceId: additionalState?.traceId || '',
                intent: additionalState?.intent,
                plan: additionalState?.plan,
                expertResults: additionalState?.expertResults || [],
                iterationCount: additionalState?.iterationCount || 0,
                metadata: additionalState?.metadata || {},
            },
            stageResults,
            findings,
            canResume: true,
        };
        // 保存到磁盘
        await this.saveCheckpoint(sessionId, checkpoint);
        // 清理旧检查点
        await this.cleanupOldCheckpoints(sessionId);
        return checkpoint;
    }
    /**
     * 保存检查点到磁盘
     */
    async saveCheckpoint(sessionId, checkpoint) {
        const sessionDir = this.getSessionDir(sessionId);
        this.ensureDirectory(sessionDir);
        const filePath = path.join(sessionDir, `${checkpoint.id}.json`);
        await fs.promises.writeFile(filePath, JSON.stringify(checkpoint, null, 2), 'utf-8');
    }
    /**
     * 生成检查点 ID
     */
    generateCheckpointId(sessionId, stageId) {
        return `${sessionId}_${stageId}_${Date.now()}`;
    }
    // ==========================================================================
    // 检查点恢复
    // ==========================================================================
    /**
     * 加载检查点
     */
    async loadCheckpoint(sessionId, checkpointId) {
        const sessionDir = this.getSessionDir(sessionId);
        const filePath = path.join(sessionDir, `${checkpointId}.json`);
        try {
            const content = await fs.promises.readFile(filePath, 'utf-8');
            return JSON.parse(content);
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                return null;
            }
            throw error;
        }
    }
    /**
     * 获取会话的最新检查点
     */
    async getLatestCheckpoint(sessionId) {
        const checkpoints = await this.listCheckpoints(sessionId);
        if (checkpoints.length === 0) {
            return null;
        }
        // 按时间戳排序，返回最新的
        checkpoints.sort((a, b) => b.timestamp - a.timestamp);
        return checkpoints[0];
    }
    /**
     * 列出会话的所有检查点
     */
    async listCheckpoints(sessionId) {
        const sessionDir = this.getSessionDir(sessionId);
        try {
            const files = await fs.promises.readdir(sessionDir);
            const checkpoints = [];
            for (const file of files) {
                if (file.endsWith('.json')) {
                    const content = await fs.promises.readFile(path.join(sessionDir, file), 'utf-8');
                    checkpoints.push(JSON.parse(content));
                }
            }
            return checkpoints;
        }
        catch (error) {
            if (error.code === 'ENOENT') {
                return [];
            }
            throw error;
        }
    }
    /**
     * 获取检查点对应的阶段结果
     */
    async getStageResults(sessionId, checkpointId) {
        const checkpoint = await this.loadCheckpoint(sessionId, checkpointId);
        return checkpoint?.stageResults || [];
    }
    // ==========================================================================
    // 检查点清理
    // ==========================================================================
    /**
     * 清理旧检查点（保留最新的 N 个）
     */
    async cleanupOldCheckpoints(sessionId) {
        const checkpoints = await this.listCheckpoints(sessionId);
        if (checkpoints.length <= this.config.maxCheckpointsPerSession) {
            return;
        }
        // 按时间戳排序
        checkpoints.sort((a, b) => b.timestamp - a.timestamp);
        // 删除超过限制的检查点
        const toDelete = checkpoints.slice(this.config.maxCheckpointsPerSession);
        for (const checkpoint of toDelete) {
            await this.deleteCheckpoint(sessionId, checkpoint.id);
        }
    }
    /**
     * 删除检查点
     */
    async deleteCheckpoint(sessionId, checkpointId) {
        const sessionDir = this.getSessionDir(sessionId);
        const filePath = path.join(sessionDir, `${checkpointId}.json`);
        try {
            await fs.promises.unlink(filePath);
        }
        catch (error) {
            if (error.code !== 'ENOENT') {
                throw error;
            }
        }
    }
    /**
     * 清理会话的所有检查点
     */
    async clearSession(sessionId) {
        const sessionDir = this.getSessionDir(sessionId);
        try {
            await fs.promises.rm(sessionDir, { recursive: true, force: true });
        }
        catch (error) {
            if (error.code !== 'ENOENT') {
                throw error;
            }
        }
    }
    /**
     * 清理过期检查点
     */
    async cleanupExpired() {
        const now = Date.now();
        let deletedCount = 0;
        try {
            const sessions = await fs.promises.readdir(this.checkpointDir);
            for (const sessionId of sessions) {
                const checkpoints = await this.listCheckpoints(sessionId);
                for (const checkpoint of checkpoints) {
                    if (now - checkpoint.timestamp > this.config.retentionMs) {
                        await this.deleteCheckpoint(sessionId, checkpoint.id);
                        deletedCount++;
                    }
                }
                // 如果会话目录为空，删除它
                const remaining = await this.listCheckpoints(sessionId);
                if (remaining.length === 0) {
                    await this.clearSession(sessionId);
                }
            }
        }
        catch (error) {
            if (error.code !== 'ENOENT') {
                throw error;
            }
        }
        return deletedCount;
    }
    // ==========================================================================
    // 工具方法
    // ==========================================================================
    /**
     * 获取会话目录路径
     */
    getSessionDir(sessionId) {
        return path.join(this.checkpointDir, sessionId);
    }
    /**
     * 确保目录存在
     */
    ensureDirectory(dir) {
        const targetDir = dir || this.checkpointDir;
        if (!fs.existsSync(targetDir)) {
            fs.mkdirSync(targetDir, { recursive: true });
        }
    }
    /**
     * 检查会话是否有可恢复的检查点
     */
    async canResume(sessionId) {
        const latest = await this.getLatestCheckpoint(sessionId);
        return latest !== null && latest.canResume;
    }
    /**
     * 获取可恢复的会话列表
     */
    async listRecoverableSessions() {
        const sessions = [];
        try {
            const dirs = await fs.promises.readdir(this.checkpointDir);
            for (const dir of dirs) {
                const canResumeSession = await this.canResume(dir);
                if (canResumeSession) {
                    sessions.push(dir);
                }
            }
        }
        catch (error) {
            if (error.code !== 'ENOENT') {
                throw error;
            }
        }
        return sessions;
    }
    /**
     * 获取检查点统计信息
     */
    async getStats() {
        let totalCheckpoints = 0;
        let oldestCheckpoint = null;
        let newestCheckpoint = null;
        let totalSessions = 0;
        try {
            const sessions = await fs.promises.readdir(this.checkpointDir);
            totalSessions = sessions.length;
            for (const sessionId of sessions) {
                const checkpoints = await this.listCheckpoints(sessionId);
                totalCheckpoints += checkpoints.length;
                for (const checkpoint of checkpoints) {
                    if (oldestCheckpoint === null || checkpoint.timestamp < oldestCheckpoint) {
                        oldestCheckpoint = checkpoint.timestamp;
                    }
                    if (newestCheckpoint === null || checkpoint.timestamp > newestCheckpoint) {
                        newestCheckpoint = checkpoint.timestamp;
                    }
                }
            }
        }
        catch (error) {
            if (error.code !== 'ENOENT') {
                throw error;
            }
        }
        return {
            totalSessions,
            totalCheckpoints,
            oldestCheckpoint,
            newestCheckpoint,
        };
    }
}
exports.CheckpointManager = CheckpointManager;
exports.default = CheckpointManager;
//# sourceMappingURL=checkpointManager.js.map