Files
AI_spine/lib/run-artifacts.mjs
T
2026-09-17 17:44:24 +08:00

35 lines
1.8 KiB
JavaScript

import {existsSync, mkdirSync, readdirSync, readFileSync, writeFileSync} from 'node:fs';
import path from 'node:path';
import {sha256} from './images.mjs';
import {redact} from '../providers/http.mjs';
export function jsonFile(file, value, secret = '') {
writeFileSync(file, `${redact(JSON.stringify(value, null, 2), secret)}\n`, 'utf8');
}
export function prepareRun(outDir, fingerprint, resume) {
const out = path.resolve(outDir);
const manifestPath = path.join(out, 'manifest.json');
if (existsSync(out) && readdirSync(out).length) {
if (!resume) throw new Error(`输出目录非空,请使用新目录或 --resume:${out}`);
if (!existsSync(manifestPath)) throw new Error('无法复用:目录没有 manifest.json');
const previous = JSON.parse(readFileSync(manifestPath, 'utf8'));
if (previous.fingerprint !== fingerprint) throw new Error('无法复用:模型、配置、输入或代码版本变化,请使用新的输出目录');
if (previous.status !== 'completed') throw new Error('上次任务没有完整结束,请保留诊断文件并使用新目录重跑');
for (const [name, hash] of Object.entries(previous.artifact_hashes || {})) {
const file = path.join(out, name);
if (!existsSync(file) || sha256(readFileSync(file)) !== hash) throw new Error(`缓存产物缺失或被修改:${name}`);
}
if (!Object.keys(previous.artifact_hashes || {}).length) throw new Error('缓存缺少产物校验记录');
return {out, manifestPath, reused: true};
}
mkdirSync(out, {recursive: true});
return {out, manifestPath, reused: false};
}
export function finishRun(run, manifest, artifacts, secret) {
manifest.artifact_hashes = Object.fromEntries(artifacts.map((name) => [name, sha256(readFileSync(path.join(run.out, name)))]));
manifest.status = 'completed';
jsonFile(run.manifestPath, manifest, secret);
}