bookworm-smart-assistant/hooks/lib/session-once.js
Bookworm Admin b7a8e29d21 release: v6.7.0 - OTA E2E test release
- 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)
2026-04-27 17:59:44 +08:00

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 };