#!/usr/bin/env node /** * P0 补丁脚本 — 将冷启动防护 + 消歧接入 + 遥测发射写入 route-interceptor.js * * 用法: node scripts/patch-interceptor-p0.js * node scripts/patch-interceptor-p0.js --dry-run (仅预览不写入) * * 三处变更: * 1. runRouteEngine() 中插入消歧 + 冷启动 (归一化之前) * 2. runRouteEngine() return 附加元数据 * 3. writeRouteState() 中插入遥测发射 */ const fs = require('fs'); const path = require('path'); const dryRun = process.argv.includes('--dry-run'); const HOOK_FILE = path.join(__dirname, '..', 'hooks', 'route-interceptor.js'); if (!fs.existsSync(HOOK_FILE)) { console.error('错误: 找不到 route-interceptor.js'); process.exit(1); } let code = fs.readFileSync(HOOK_FILE, 'utf8'); let patchCount = 0; // === 补丁 1: 归一化之前插入消歧 + 冷启动 === // 使用正则匹配,兼容 \r\n 和 \n 换行 const PATCH1_RE = /( +\/\/ .*\r?\n const normalized = routeAnalyzer\.normalizeScores\(results\)\.slice\(0, 5\);\r?\n const recommendation = routeAnalyzer\.getRecommendation\(normalized\);)/; const PATCH1_REPLACEMENT = ` // v5.8: 冲突消歧 (加权投票 + specificity) let disambiguated = results; let firedRules = []; if (routeAnalyzer.applyDisambiguation) { try { const disambResult = routeAnalyzer.applyDisambiguation(results, prompt, index); disambiguated = disambResult.results || results; firedRules = disambResult.firedRules || []; } catch {} } // v5.8: 冷启动防护 (epsilon-greedy + 新技能 boost) let coldStartApplied = false; let coldStartSkills = []; const routeTelemetry = safeRequire(path.join(SCRIPTS_DIR, 'route-telemetry.js')); if (routeAnalyzer.applyColdStartBoost && routeTelemetry) { try { const routeStats = routeTelemetry.getSkillRouteStats(30); const { boostedSkills } = routeAnalyzer.applyColdStartBoost(disambiguated, routeStats); if (boostedSkills && boostedSkills.length > 0) { coldStartApplied = true; coldStartSkills = boostedSkills; disambiguated.sort((a, b) => b.score - a.score); } } catch {} } // 归一化 const normalized = routeAnalyzer.normalizeScores(disambiguated).slice(0, 5); const recommendation = routeAnalyzer.getRecommendation(normalized);`; if (PATCH1_RE.test(code)) { code = code.replace(PATCH1_RE, PATCH1_REPLACEMENT); patchCount++; console.log('✓ 补丁 1/3: 消歧 + 冷启动 已插入 runRouteEngine()'); } else if (code.includes('v5.8:')) { console.log('⊘ 补丁 1/3: 已存在,跳过'); } else { console.error('✗ 补丁 1/3: 找不到锚点,请检查 route-interceptor.js 是否已被修改'); } // === 补丁 2: runRouteEngine return 附加元数据 === const PATCH2_ANCHOR = ` return { primary, candidates, confidence, chain, composable };`; const PATCH2_REPLACEMENT = ` return { primary, candidates, confidence, chain, composable, _firedRules: firedRules || [], _coldStartApplied: coldStartApplied || false, _coldStartSkills: coldStartSkills || [], _startTs: Date.now(), };`; if (code.includes(PATCH2_ANCHOR)) { code = code.replace(PATCH2_ANCHOR, PATCH2_REPLACEMENT); patchCount++; console.log('✓ 补丁 2/3: return 元数据 已附加'); } else if (code.includes('_firedRules')) { console.log('⊘ 补丁 2/3: 已存在,跳过'); } else { console.error('✗ 补丁 2/3: 找不到锚点'); } // === 补丁 3: writeRouteState 中插入遥测发射 === const PATCH3_ANCHOR = ` // 追加到每日路由日志 appendRouteLog(prompt, routing, traceId); return state;`; const PATCH3_REPLACEMENT = ` // 追加到每日路由日志 appendRouteLog(prompt, routing, traceId); // v5.8: 发射路由遥测指标 try { const telemetry = require(path.join(SCRIPTS_DIR, 'route-telemetry.js')); if (telemetry.emitRouteMetric) { telemetry.emitRouteMetric({ queryLength: (prompt || '').split(/\\s+/).length, selectedSkill: routing.primary, topScore: routing.candidates?.[0]?.confidence || 0, gap12: (routing.candidates?.[0]?.confidence || 0) - (routing.candidates?.[1]?.confidence || 0), confidence: routing.confidence, rulesFired: routing._firedRules || [], coldStartApplied: routing._coldStartApplied || false, coldStartSkills: routing._coldStartSkills || [], latencyMs: Date.now() - (routing._startTs || Date.now()), experimentId: routing.experiment?.id || null, }); } } catch {} return state;`; if (code.includes(PATCH3_ANCHOR)) { code = code.replace(PATCH3_ANCHOR, PATCH3_REPLACEMENT); patchCount++; console.log('✓ 补丁 3/3: 遥测发射 已插入 writeRouteState()'); } else if (code.includes('v5.8: 发射路由遥测')) { console.log('⊘ 补丁 3/3: 已存在,跳过'); } else { console.error('✗ 补丁 3/3: 找不到锚点'); } // === 更新版本号 === if (code.includes("version: '5.6'")) { code = code.replace("version: '5.6'", "version: '5.8'"); console.log('✓ 版本号: 5.6 → 5.8'); } // === 写入 === if (patchCount === 0) { console.log('\n无需变更。'); process.exit(0); } if (dryRun) { console.log(`\n[dry-run] 将应用 ${patchCount} 个补丁,但未写入文件。`); process.exit(0); } // 备份原文件 const backupFile = HOOK_FILE + '.bak-' + new Date().toISOString().slice(0, 10); fs.copyFileSync(HOOK_FILE, backupFile); console.log(`\n备份: ${backupFile}`); fs.writeFileSync(HOOK_FILE, code); console.log(`已写入 ${patchCount} 个补丁到 route-interceptor.js`); console.log('完成 ✓');