#!/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(); }