bookworm-smart-assistant/scripts/patches/patch-r5-merge-matcher.js

62 lines
2.0 KiB
JavaScript
Raw Permalink Normal View History

#!/usr/bin/env node
/**
* patch-r5-merge-matcher.js · 2026-04-26
* 合并 agent-isolation-gate.js 3 个独立 PreToolUse 注册 (Bash/Write/Edit)
* 为单一 matcher 'Bash|Write|Edit', 减少 hook 启动开销 3x 1x
*
* Idempotent: 检测合并后的单一条目存在则跳过
* 操作 settings.json AST (JSON.parse), 不用文本替换防破坏
*/
'use strict';
const fs = require('fs');
const path = require('path');
const SETTINGS = path.join(process.env.HOME || process.env.USERPROFILE || 'C:/Users/leesu', '.claude', 'settings.json');
const GATE_CMD = 'node C:/Users/leesu/.claude/hooks/agent-isolation-gate.js';
const MERGED_MATCHER = 'Bash|Write|Edit';
try {
const raw = fs.readFileSync(SETTINGS, 'utf8');
const cfg = JSON.parse(raw);
const pre = (cfg.hooks && cfg.hooks.PreToolUse) || [];
// 找出 agent-isolation-gate 相关条目
const gateIdx = [];
pre.forEach((entry, i) => {
const cmds = (entry.hooks || []).map(h => h.command || '');
if (cmds.some(c => c.includes('agent-isolation-gate.js'))) gateIdx.push(i);
});
if (gateIdx.length === 0) {
console.error('[r5-merge] no agent-isolation-gate entries found, abort');
process.exit(1);
}
if (gateIdx.length === 1 && pre[gateIdx[0]].matcher === MERGED_MATCHER) {
console.log('[r5-merge] already applied, skip');
process.exit(0);
}
fs.writeFileSync(SETTINGS + '.bak.r5merge.' + Date.now(), raw, 'utf8');
// 删除所有旧条目, 在第一个位置插入合并条目
const merged = {
matcher: MERGED_MATCHER,
hooks: [{
type: 'command',
command: GATE_CMD,
timeout: 1500
}]
};
// 倒序删除
const sortedDesc = [...gateIdx].sort((a, b) => b - a);
const insertAt = gateIdx[0];
for (const i of sortedDesc) pre.splice(i, 1);
pre.splice(insertAt, 0, merged);
fs.writeFileSync(SETTINGS, JSON.stringify(cfg, null, 2), 'utf8');
console.log('[r5-merge] applied (merged ' + gateIdx.length + ' entries → 1)');
} catch (e) {
console.error('[r5-merge] error:', e.message);
process.exit(1);
}