#!/usr/bin/env node /** * pre-agent-gate.js — Agent 派遣前置门 (P1, 2026-04-19) * PRE_AGENT_GATE_P1 * * PreToolUse(Task) 钩子 — general-purpose + 轻量查询 → 建议改用 explore agent。 * fail-open: exit 0 始终, 不阻断派遣。 */ 'use strict'; const fs = require('fs'); const path = require('path'); const LIGHTWEIGHT_KEYWORDS = [ /\\bfind\\b/i, /\\blocate\\b/i, /\\bsearch\\b/i, /\\blist\\b/i, /\\bwhich\\b/i, /\\bwhere\\s+is\\b/i, /\\blook\\s+up\\b/i, /\\bgrep\\b/i, /查找/, /搜索/, /定位/, /列出/, /哪里/, /哪个文件/, ]; const SHORT_PROMPT_THRESHOLD = 200; function getLogPath() { try { const root = require('./lib/root.js'); return path.join(root, 'debug', 'pre-agent-gate.jsonl'); } catch { return path.join(__dirname, '..', 'debug', 'pre-agent-gate.jsonl'); } } function readStdinSync() { try { const raw = fs.readFileSync(0, 'utf8'); return JSON.parse(raw); } catch { return null; } } function isLightweight(prompt) { if (!prompt || typeof prompt !== 'string') return false; if (prompt.length < SHORT_PROMPT_THRESHOLD) return true; return LIGHTWEIGHT_KEYWORDS.some(re => re.test(prompt)); } function logEvent(record) { try { fs.appendFileSync(getLogPath(), JSON.stringify(record) + '\n'); } catch {} } function main() { const input = readStdinSync(); if (!input || !input.tool_input) { process.exit(0); } const ti = input.tool_input || {}; const subagentType = ti.subagent_type || ''; const prompt = ti.prompt || ''; const description = ti.description || ''; const record = { ts: new Date().toISOString(), sessionId: input.session_id || '', subagent_type: subagentType, promptLen: prompt.length, description, hint: false, }; if (subagentType !== 'general-purpose') { logEvent(record); process.exit(0); } if (!isLightweight(prompt)) { logEvent(record); process.exit(0); } record.hint = true; logEvent(record); const hint = '[pre-agent-gate] 检测到轻量查询使用 general-purpose agent。' + '建议改用 explore agent (haiku 模型, 成本约 1/5)。' + '若确需 general-purpose 请忽略此提示。'; const out = { hookSpecificOutput: { hookEventName: 'PreToolUse', additionalContext: hint, }, }; process.stdout.write(JSON.stringify(out)); process.exit(0); } main();