/** * 崩溃/异常终止时通过 Gateway API 发送邮件通知用户。 * * 约束同 pi-mail-bridge/lib/crash-notify.mjs: * - 不依赖外部库,只用 Node 内置 http * - 所有错误静默 * - 只在崩溃路径调用 */ const http = require('http'); const GATEWAY_URL = process.env.AGENTMAIL_GATEWAY_URL || 'http://127.0.0.1:8180'; const AGENT_NAME = process.env.AGENTMAIL_AGENT_NAME || 'opencode'; const AGENT_KEY = process.env.AGENTMAIL_AGENT_KEY || ''; function notifyCrash(reason, err) { if (!AGENT_KEY) return; const body = JSON.stringify({ to: 'jianf@', subject: `[${AGENT_NAME}] 桥进程异常终止`, body: [ `**${AGENT_NAME}** 桥进程遇到未处理异常,已终止。`, '', `**原因**:${reason}`, err ? `**错误信息**:${err.message || String(err)}` : '', err?.stack ? `\n**堆栈**(首 500 字):\n\`\`\`\n${err.stack.slice(0, 500)}\n\`\`\`` : '', '', `**自动重启**:systemd 将在 10 秒内自动拉起。`, `如果反复崩溃,请检查日志:`, `- \`journalctl -u ${AGENT_NAME}-serve -n 50 --no-pager\``, ].filter(Boolean).join('\n'), }); const parsed = new URL(`${GATEWAY_URL}/api/v1/agent/send`); const req = http.request({ hostname: parsed.hostname, port: parsed.port || 80, path: parsed.pathname, method: 'POST', headers: { 'Content-Type': 'application/json', 'X-API-Key': AGENT_KEY, 'Content-Length': Buffer.byteLength(body), }, timeout: 5000, }, () => {}); req.on('error', () => {}); req.on('timeout', () => { req.destroy(); }); req.write(body); req.end(); } module.exports = { notifyCrash };