#!/usr/bin/env node 'use strict'; // 质量告警:读 bridge_ai_metrics,阈值超限时发邮件。建议 cron 每 15-30 分钟跑一次。 // 用法: node scripts/quality-alert.js [hours] [--dry-run] const fs = require('fs'); const path = require('path'); const { loadConfig } = require('../bridge/src/config'); const { createMetrics } = require('../bridge/src/metrics'); const { evaluateQuality } = require('../bridge/src/quality'); const { sendMail } = require('../bridge/src/smtp'); const ROOT = path.resolve(__dirname, '..'); const env = {}; for (const line of fs.readFileSync(path.join(ROOT, '.env'), 'utf8').split('\n')) { if (!line.includes('=') || line.trim().startsWith('#')) continue; const i = line.indexOf('='); env[line.slice(0, i).trim()] = line.slice(i + 1).trim(); } const password = encodeURIComponent(env.POSTGRES_PASSWORD || ''); env.PG_URL = process.env.QUALITY_PG_URL || `postgres://crmnew:${password}@127.0.0.1:5440/bridge`; const cfg = loadConfig({ ...process.env, ...env }); const hours = Number(process.argv[2]) || 1; const dryRun = process.argv.includes('--dry-run'); (async () => { const metrics = createMetrics(cfg); const report = await metrics.report(hours); const result = evaluateQuality(report.summary); if (result.skipped) { console.log(JSON.stringify({ skipped: true, reason: result.reason, summary: report.summary })); await metrics.pool.end(); return; } if (!result.alerts.length) { console.log(JSON.stringify({ ok: true, summary: report.summary })); await metrics.pool.end(); return; } const text = [ `Yehwang bridge AI 质量告警(最近 ${hours} 小时)`, '', ...result.alerts.map((a) => `- ${a.message}`), '', 'summary: ' + JSON.stringify(report.summary), 'tools: ' + JSON.stringify(report.tools), ].join('\n'); console.log(text); if (dryRun) { console.log('[dry-run] not sending email'); } else if (cfg.smtpHost && cfg.smtpUser && cfg.smtpPass) { const to = env.ALERT_EMAIL_TO || cfg.smtpUser; await sendMail( { host: cfg.smtpHost, port: cfg.smtpPort, user: cfg.smtpUser, pass: cfg.smtpPass, from: cfg.smtpFrom }, { to, subject: 'Yehwang bridge AI 质量告警', text } ); console.log(`[alert] email sent to ${to}`); } else { console.error('[alert] SMTP not configured; alert only logged'); } await metrics.pool.end(); })().catch((err) => { console.error('[quality-alert]', err.message); process.exit(1); });