- VERSION file as authoritative version source - export.mjs reads VERSION with package.json fallback - bw-ota.ps1 DryRun mode for safe testing - auto-setup.ps1 bumped to v3.2.0 (Phase 8 OTA)
94 lines
2.7 KiB
JavaScript
94 lines
2.7 KiB
JavaScript
#!/usr/bin/env node
|
|
/**
|
|
* UserPromptSubmit Hook: 统一提交派遣器 (v6.2 M3)
|
|
*
|
|
* 合并 2 个 UserPromptSubmit 钩子为单进程,减少 ~50ms 串行开销:
|
|
* 1. security-startup-guard (同步, <5ms, fail-open)
|
|
* 2. route-interceptor-bundle (异步, 路由引擎, fail-open)
|
|
*
|
|
* 读取 stdin 一次:
|
|
* - security-startup-guard 的 runGuard() 不需要 stdin 数据 (仅检查 lockfile + settings)
|
|
* - route-interceptor-bundle 作为子进程接收 stdin 数据 (保留其 timeout 逻辑)
|
|
*
|
|
* 退出码: 0 (始终放行, UserPromptSubmit 不阻断)
|
|
*/
|
|
|
|
'use strict';
|
|
|
|
const { spawn } = require('child_process');
|
|
const path = require('path');
|
|
|
|
const HOOKS_DIR = __dirname;
|
|
|
|
function main() {
|
|
let rawInput = '';
|
|
process.stdin.setEncoding('utf8');
|
|
process.stdin.on('data', (chunk) => {
|
|
rawInput += chunk;
|
|
if (rawInput.length > 256 * 1024) {
|
|
// 输入过大,直接退出
|
|
process.exit(0);
|
|
}
|
|
});
|
|
process.stdin.on('end', () => {
|
|
// --- 阶段 1: security-startup-guard (同步, fail-open) ---
|
|
try {
|
|
const guard = require('./security-startup-guard.js');
|
|
if (guard && guard.runGuard) {
|
|
guard.runGuard();
|
|
}
|
|
} catch {}
|
|
|
|
// --- 阶段 2: route-interceptor-bundle (子进程, 保留独立 timeout) ---
|
|
const bundlePath = path.join(HOOKS_DIR, 'route-interceptor-bundle.js');
|
|
const hookTimingMs = Date.now(); // [P3-6] 计时起点
|
|
try {
|
|
const child = spawn('node', [bundlePath], {
|
|
stdio: ['pipe', 'pipe', 'pipe'],
|
|
timeout: 3000,
|
|
});
|
|
|
|
let stdout = '';
|
|
let stderr = '';
|
|
child.stdout.on('data', (d) => { stdout += d; });
|
|
child.stderr.on('data', (d) => { stderr += d; });
|
|
|
|
child.on('close', () => {
|
|
// [P3-6] 记录路由耗时
|
|
try {
|
|
const elapsed = Date.now() - hookTimingMs;
|
|
const timingPath = path.join(HOOKS_DIR, '..', 'debug', 'hook-timing.jsonl');
|
|
const entry = JSON.stringify({ ts: new Date().toISOString(), hook: 'route-interceptor-bundle', elapsed }) + '\n';
|
|
require('fs').appendFileSync(timingPath, entry);
|
|
} catch {}
|
|
// 转发 route-interceptor-bundle 的 stdout (含 additionalContext)
|
|
if (stdout) {
|
|
process.stdout.write(stdout);
|
|
}
|
|
if (stderr) {
|
|
process.stderr.write(stderr);
|
|
}
|
|
process.exit(0);
|
|
});
|
|
|
|
child.on('error', () => {
|
|
process.exit(0); // fail-open
|
|
});
|
|
|
|
// 将 stdin 数据传递给子进程
|
|
child.stdin.write(rawInput);
|
|
child.stdin.end();
|
|
} catch {
|
|
process.exit(0); // fail-open
|
|
}
|
|
});
|
|
}
|
|
|
|
if (typeof module !== 'undefined') {
|
|
module.exports = { main };
|
|
}
|
|
|
|
if (require.main === module) {
|
|
main();
|
|
}
|