UNPKG

autosnippet

Version:

Extract code patterns into a knowledge base for AI coding assistants

79 lines (78 loc) 2.85 kB
/** * checkpoint.js — Bootstrap 断点续传 (Checkpoint) 存储/恢复 * * 在维度级粒度保存/加载/清理执行进度,支持意外中断后恢复。 * * 调用方: * - orchestrator.js (内部 Agent) — AI pipeline 每个维度完成后保存 * - dimension-complete.js (外部 Agent) — 外部 Agent 通知维度完成时保存 * - bootstrap.js — clearCheckpoints() 全量重建前清理 * * @module pipeline/checkpoint */ import fs from 'node:fs/promises'; import path from 'node:path'; import Logger from '#infra/logging/Logger.js'; import pathGuard from '#shared/PathGuard.js'; const logger = Logger.getInstance(); const CHECKPOINT_TTL_MS = 3600_000; // 1小时内有效 /** * 保存维度级 checkpoint * @param result 维度执行结果 * @param [digest] DimensionDigest */ export async function saveDimensionCheckpoint(projectRoot, sessionId, dimId, result, digest = null) { try { const checkpointDir = path.join(projectRoot, '.autosnippet', 'bootstrap-checkpoint'); await fs.mkdir(checkpointDir, { recursive: true }); await fs.writeFile(path.join(checkpointDir, `${dimId}.json`), JSON.stringify({ dimId, sessionId, ...result, digest, completedAt: Date.now() })); } catch (err) { logger.warn(`[Bootstrap-v3] checkpoint save failed for "${dimId}": ${err instanceof Error ? err.message : String(err)}`); } } /** * 加载有效的 checkpoints * @returns dimId → checkpoint data */ export async function loadCheckpoints(projectRoot) { const checkpoints = new Map(); try { const checkpointDir = path.join(projectRoot, '.autosnippet', 'bootstrap-checkpoint'); const files = await fs.readdir(checkpointDir).catch(() => []); const now = Date.now(); for (const file of files) { if (!file.endsWith('.json')) { continue; } try { const content = await fs.readFile(path.join(checkpointDir, file), 'utf-8'); const data = JSON.parse(content); if (data.completedAt && now - data.completedAt < CHECKPOINT_TTL_MS) { checkpoints.set(data.dimId, data); } } catch { /* skip corrupt checkpoint */ } } } catch { /* checkpoint dir doesn't exist */ } return checkpoints; } /** 清理 checkpoint 目录 */ export async function clearCheckpoints(projectRoot) { try { const checkpointDir = path.join(projectRoot, '.autosnippet', 'bootstrap-checkpoint'); pathGuard.assertSafe(checkpointDir); await fs.rm(checkpointDir, { recursive: true, force: true }); } catch (err) { if (err?.name === 'PathGuardError') { throw err; } /* ignore other errors */ } }