- VERSION file as authoritative version source - export.mjs reads VERSION with package.json fallback - bw-ota.ps1 DryRun mode for safe testing - auto-setup.ps1 bumped to v3.2.0 (Phase 8 OTA)
52 lines
1.5 KiB
JavaScript
52 lines
1.5 KiB
JavaScript
/**
|
|
* session-once.js — 会话级执行去重 (P0-2)
|
|
* 依赖 session-start-restore.js 维护的 .session-restored 文件获取 session_id
|
|
* 标志文件: session-state/.session-once.json { hookName: sessionId }
|
|
* 原子写: tmp+rename 防多窗口竞态
|
|
*/
|
|
'use strict';
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
|
|
let CLAUDE_ROOT;
|
|
try { CLAUDE_ROOT = require('./root.js'); } catch { CLAUDE_ROOT = path.resolve(__dirname, '..', '..'); }
|
|
|
|
const STATE_DIR = path.join(CLAUDE_ROOT, 'session-state');
|
|
const FLAGS_PATH = path.join(STATE_DIR, '.session-once.json');
|
|
const SESSION_FILE = path.join(STATE_DIR, '.session-restored');
|
|
|
|
function getCurrentSessionId() {
|
|
try { return fs.readFileSync(SESSION_FILE, 'utf8').trim() || ''; }
|
|
catch { return ''; }
|
|
}
|
|
|
|
function loadFlags() {
|
|
try { return JSON.parse(fs.readFileSync(FLAGS_PATH, 'utf8')) || {}; }
|
|
catch { return {}; }
|
|
}
|
|
|
|
function saveFlags(flags) {
|
|
try {
|
|
if (!fs.existsSync(STATE_DIR)) fs.mkdirSync(STATE_DIR, { recursive: true });
|
|
const tmp = FLAGS_PATH + '.tmp.' + process.pid;
|
|
fs.writeFileSync(tmp, JSON.stringify(flags), 'utf8');
|
|
fs.renameSync(tmp, FLAGS_PATH);
|
|
} catch {}
|
|
}
|
|
|
|
function hasRun(hookName) {
|
|
const sid = getCurrentSessionId();
|
|
if (!sid) return false;
|
|
return loadFlags()[hookName] === sid;
|
|
}
|
|
|
|
function markRun(hookName) {
|
|
const sid = getCurrentSessionId();
|
|
if (!sid) return;
|
|
const flags = loadFlags();
|
|
flags[hookName] = sid;
|
|
saveFlags(flags);
|
|
}
|
|
|
|
module.exports = { hasRun, markRun, getCurrentSessionId };
|