/** * AIBOT 长连接传输壳(无业务)。 * * 本文件职责: * - 当 WECOM_AIBOT_ENABLED=true 时启动「帧循环」占位(默认只心跳日志,不连真 Bot SDK) * - 收到已规范化的入站帧时转发到同进程 forwardToAgent(由 server.cjs 注入) * * 禁止:写工单/六态/Graph;并存期勿与现网 8813 双连同一 Bot。 * 正式 SDK 接入:替换 startLongConnectionLoop 内的 connect 段,保持只做传输。 */ "use strict"; /** * @param {object} opts * @param {boolean} opts.enabled * @param {(payloadText: string) => Promise} opts.forwardToAgent * @param {() => boolean} [opts.shouldStop] */ function startLongConnectionLoop(opts) { const enabled = !!opts.enabled; const forwardToAgent = opts.forwardToAgent; const shouldStop = opts.shouldStop || (() => false); if (!enabled) { // eslint-disable-next-line no-console console.log("[aibot-long-connection] 未启用(WECOM_AIBOT_ENABLED=false),跳过帧循环壳"); return { stop: () => {} }; } // eslint-disable-next-line no-console console.warn( "[aibot-long-connection] 帧循环壳已启动:当前不连企微 Bot SDK,仅心跳;" + "请确认现网桥已停,避免双连" ); let timer = null; const tick = () => { if (shouldStop()) { return; } // 心跳:证明传输壳在跑;无帧可转发 // eslint-disable-next-line no-console console.log("[aibot-long-connection] heartbeat shell (no SDK frame)"); }; timer = setInterval(tick, 60000); tick(); return { stop: () => { if (timer) { clearInterval(timer); timer = null; } }, /** * 测试注入:模拟 SDK 收到一帧已解析 JSON,只做转发。 * @param {object|string} frame */ injectFrameForTest: async (frame) => { const text = typeof frame === "string" ? frame : JSON.stringify(frame); return forwardToAgent(text); }, }; } module.exports = { startLongConnectionLoop };