bookworm-smart-assistant/scripts/user-overrides.js

171 lines
4.7 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* 逃生舱状态管理 (Phase 0)
*
* 管理 /force, /checks, /reset
*
* 状态文件: debug/user-overrides.json
* 自动过期: 1 小时匹配 session-memory.js MAX_SESSION_AGE
* /force: compliance-gate
* /checks off: /checks on /reset
*/
const fs = require('fs');
const path = require('path');
// 路径解析
let overridesPath, debugDir;
try {
const { PATHS } = require('./paths.config.js');
overridesPath = PATHS.userOverridesJson;
debugDir = PATHS.debugDir;
} catch {
const root = path.resolve(__dirname, '..');
debugDir = path.join(root, 'debug');
overridesPath = path.join(debugDir, 'user-overrides.json');
}
const MAX_AGE_MS = 60 * 60 * 1000; // 1 小时
// ─── 内部辅助 ─────────────────────────────────────────
function ensureDir() {
try {
if (!fs.existsSync(debugDir)) fs.mkdirSync(debugDir, { recursive: true });
} catch {}
}
/**
* 读取覆盖状态检查过期
* @returns {Object} overrides 状态
*/
function readState() {
try {
if (!fs.existsSync(overridesPath)) return null;
const raw = fs.readFileSync(overridesPath, 'utf8');
const state = JSON.parse(raw);
// 检查过期
if (state.expiresAt && new Date(state.expiresAt).getTime() < Date.now()) {
// 过期 → 清除文件
try { fs.unlinkSync(overridesPath); } catch {}
return null;
}
return state;
} catch {
return null;
}
}
/**
* 写入覆盖状态
* @param {Object} overrides - { force, checksOff, forceSkill }
*/
function writeState(overrides) {
ensureDir();
const now = new Date();
const state = {
createdAt: now.toISOString(),
expiresAt: new Date(now.getTime() + MAX_AGE_MS).toISOString(),
overrides: {
force: overrides.force || false,
checksOff: overrides.checksOff || false,
forceSkill: overrides.forceSkill || null,
},
};
fs.writeFileSync(overridesPath, JSON.stringify(state, null, 2) + '\n');
}
// ─── 公开 API ─────────────────────────────────────────
/**
* 设置 force 模式单次生效
* @param {string} [skillName] - 可选指定技能
*/
function setForce(skillName) {
const current = readState();
const overrides = current ? current.overrides : { force: false, checksOff: false, forceSkill: null };
overrides.force = true;
overrides.forceSkill = skillName || null;
writeState(overrides);
}
/**
* 设置 checks 开关
* @param {boolean} enabled - true=开启检查, false=关闭检查
*/
function setChecks(enabled) {
const current = readState();
const overrides = current ? current.overrides : { force: false, checksOff: false, forceSkill: null };
overrides.checksOff = !enabled;
writeState(overrides);
}
/**
* 重置所有覆盖
*/
function resetAll() {
try {
if (fs.existsSync(overridesPath)) fs.unlinkSync(overridesPath);
} catch {}
}
/**
* 检查 force 是否激活
* @returns {{ active: boolean, skill?: string }}
*/
function isForceActive() {
const state = readState();
if (!state || !state.overrides || !state.overrides.force) {
return { active: false };
}
return { active: true, skill: state.overrides.forceSkill || undefined };
}
/**
* 检查 checks 是否被关闭
* @returns {boolean}
*/
function isChecksDisabled() {
const state = readState();
if (!state || !state.overrides) return false;
return state.overrides.checksOff === true;
}
/**
* 清除 force 标志compliance-gate 放行后调用
*/
function clearForce() {
const state = readState();
if (!state || !state.overrides) return;
state.overrides.force = false;
state.overrides.forceSkill = null;
writeState(state.overrides);
}
// ─── 导出 ─────────────────────────────────────────────
module.exports = {
setForce,
setChecks,
resetAll,
isForceActive,
isChecksDisabled,
clearForce,
};
// CLI: 直接运行时打印当前状态
if (require.main === module) {
const state = readState();
console.log('=== User Overrides ===');
console.log(`Path: ${overridesPath}`);
if (!state) {
console.log('Status: No active overrides');
} else {
console.log(`Created: ${state.createdAt}`);
console.log(`Expires: ${state.expiresAt}`);
console.log(`Force: ${state.overrides.force ? 'ON' + (state.overrides.forceSkill ? ` (${state.overrides.forceSkill})` : '') : 'OFF'}`);
console.log(`Checks: ${state.overrides.checksOff ? 'DISABLED' : 'ENABLED'}`);
}
}