bookworm-smart-assistant/hooks/subagent-route-injector.js

106 lines
3.2 KiB
JavaScript
Raw Normal View History

#!/usr/bin/env node
/**
* SubagentStart Hook: Agent 路由上下文注入 (v5.2 Neural Gateway)
*
* 将父级路由信息注入子 Agent 上下文
* 确保子 Agent 感知当前路由决策
*
* stdin: { session_id, hook_event_name: "SubagentStart" }
* stdout: JSON { hookSpecificOutput: { additionalContext } }
* 退出码: 始终 0
*/
const fs = require('fs');
const path = require('path');
const readStdin = require('./lib/read-stdin.js');
const STATE_EXPIRY_MS = 5 * 60 * 1000; // 5 分钟过期
const CLAUDE_ROOT = require('./lib/root.js');
const DEBUG_DIR = path.join(CLAUDE_ROOT, 'debug');
const STATE_FILE = path.join(DEBUG_DIR, 'route-state-current.json');
/**
* 加载路由状态 (含过期检查)
* @returns {Object|null}
*/
function loadRouteState() {
try {
if (!fs.existsSync(STATE_FILE)) return null;
const state = JSON.parse(fs.readFileSync(STATE_FILE, 'utf8'));
// 过期检查
if (state.ts) {
const tsMs = new Date(state.ts).getTime();
if (isNaN(tsMs)) return null;
const age = Date.now() - tsMs;
if (age > STATE_EXPIRY_MS) return null;
}
return state;
} catch {
return null;
}
}
// === 主流程 ===
function main() {
readStdin({ maxSize: 128 * 1024 }).then(input => {
// 读取路由状态
const state = loadRouteState();
if (!state) {
// 无状态或已过期 → 静默放行
process.exit(0);
return;
}
const primary = state.routing?.primary || 'developer-expert';
const confidence = state.routing?.confidence || 0;
const complexity = state.intent?.complexity || 'medium';
const intents = (state.intent?.intents || []).join(',');
const chain = (state.routing?.chain || []).join(' → ');
let ctx = `[BWR 子Agent上下文] 父级路由: ${primary}, 置信度: ${(confidence * 100).toFixed(0)}%`;
ctx += `, 复杂度: ${complexity}, 意图: ${intents}`;
if (chain) {
ctx += `, 技能链: ${chain}`;
}
// --- v6.6: Context Anchors Lite + 重读纪律 ---
// 安全设计: 只注入路径提示, Agent 自行用 Read 工具获取 (经过 block-sensitive-reads)
try {
const anchorsFile = path.join(CLAUDE_ROOT, "context-anchors.json");
if (fs.existsSync(anchorsFile)) {
const anchors = JSON.parse(fs.readFileSync(anchorsFile, "utf8"));
const files = (anchors.files || []).slice(0, 10);
if (files.length > 0) {
ctx += String.fromCharCode(10)+"[CONTEXT_ANCHOR] 上下文锚点文件 (请用 Read 工具重读): " + files.join(", ");
}
}
} catch {}
ctx += String.fromCharCode(10)+"[重读纪律] 你是 fresh 实例。不要假设之前的 Agent 做了什么,从当前代码状态独立判断。";
const output = {
hookSpecificOutput: {
hookEventName: 'SubagentStart',
additionalContext: ctx,
},
};
process.stdout.write(JSON.stringify(output));
process.exit(0);
}).catch(() => process.exit(0));
}
// 模块导出 (供测试)
if (typeof module !== 'undefined') {
module.exports = { loadRouteState, CLAUDE_ROOT: require("./lib/root.js") };
}
if (require.main === module) {
main();
}