bookworm-smart-assistant/scripts/patches/patch-route-interceptor-failopen.js

86 lines
3.3 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* Patch: route-interceptor-bundle.js require fail-open
* 原因: 旧版部署缺少 scripts/route-engine.js 等文件时,
* require 导致整个 UserPromptSubmit hook 崩溃 (MODULE_NOT_FOUND)
* 修复: 包裹 try-catch, 模块缺失时降级为 [BWR:skip]
*/
'use strict';
const fs = require('fs');
const path = require('path');
const TARGET = path.join(__dirname, '..', '..', 'hooks', 'route-interceptor-bundle.js');
const SENTINEL = '_routingReady';
if (!fs.existsSync(TARGET)) {
console.log('[patch] route-interceptor-bundle.js 不存在, 跳过');
process.exit(0);
}
let code = fs.readFileSync(TARGET, 'utf8');
if (code.includes(SENTINEL)) {
console.log('[patch] 已包含 fail-open 保护, 跳过');
process.exit(0);
}
// 备份
const bak = TARGET + '.bak.' + Date.now();
fs.writeFileSync(bak, code);
const OLD = `const { safeAppendJsonl } = require('./lib/safe-append.js');
const readStdin = require('./lib/read-stdin.js');
// === P3-1 BUNDLE: preload routing deps ===
// Phase 0 宪法合规拆分: 核心逻辑提取到独立模块
const { runRouteEngine, loadSkillsIndex, safeRequire: _engineRequire } = require('../scripts/route-engine.js');
const { buildBWRDirective, MUST_INVOKE_EXEMPT_INTENTS: _EXEMPT } = require('../scripts/bwr-builder.js');
const { writeRouteState: _writeRouteState } = require('../scripts/route-state.js');`;
const NEW = `let safeAppendJsonl;
try { ({ safeAppendJsonl } = require('./lib/safe-append.js')); } catch { safeAppendJsonl = () => {}; }
let readStdin;
try { readStdin = require('./lib/read-stdin.js'); } catch { readStdin = () => Promise.resolve(''); }
// === P3-1 BUNDLE: preload routing deps (fail-open: 模块缺失时降级为空路由) ===
let runRouteEngine, loadSkillsIndex, _engineRequire;
let buildBWRDirective, _EXEMPT;
let _writeRouteState;
let _routingReady = true;
try {
({ runRouteEngine, loadSkillsIndex, safeRequire: _engineRequire } = require('../scripts/route-engine.js'));
({ buildBWRDirective, MUST_INVOKE_EXEMPT_INTENTS: _EXEMPT } = require('../scripts/bwr-builder.js'));
({ writeRouteState: _writeRouteState } = require('../scripts/route-state.js'));
} catch (e) {
_routingReady = false;
runRouteEngine = () => ({ skill: null, confidence: 0, candidates: [] });
loadSkillsIndex = () => [];
_engineRequire = () => null;
buildBWRDirective = () => '[BWR:skip] routing modules unavailable';
_EXEMPT = [];
_writeRouteState = () => {};
process.stderr.write('[route-interceptor] WARN: routing modules not found, degraded to skip mode: ' + (e.message || '') + '\\n');
}`;
// 规范化换行符再匹配
const codeNorm = code.replace(/\r\n/g, '\n');
const oldNorm = OLD.replace(/\r\n/g, '\n');
if (!codeNorm.includes(oldNorm)) {
console.error('[patch] 找不到目标代码块, 可能已被修改');
process.exit(1);
}
// 保留原文件换行风格
const eol = code.includes('\r\n') ? '\r\n' : '\n';
const newAdapted = NEW.replace(/\n/g, eol);
code = code.replace(OLD.replace(/\n/g, eol), newAdapted);
if (code === fs.readFileSync(TARGET, 'utf8')) {
// fallback: 用规范化后的内容替换
code = codeNorm.replace(oldNorm, NEW);
}
fs.writeFileSync(TARGET, code);
console.log('[patch] route-interceptor-bundle.js → fail-open 保护已注入');
console.log('[patch] 备份:', bak);