@coclaw/openclaw-coclaw 0.12.1 → 0.12.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/realtime-bridge.js +11 -1
- package/src/webrtc/ndc-preloader.js +22 -2
package/package.json
CHANGED
package/src/realtime-bridge.js
CHANGED
|
@@ -1033,12 +1033,22 @@ export async function restartRealtimeBridge(opts) {
|
|
|
1033
1033
|
await singleton.start(opts);
|
|
1034
1034
|
}
|
|
1035
1035
|
|
|
1036
|
-
|
|
1036
|
+
/**
|
|
1037
|
+
* @param {object} [opts]
|
|
1038
|
+
* @param {boolean} [opts.forceCleanup] - 调用 ndc cleanup() 释放 native TSFN(仅测试用)。
|
|
1039
|
+
* 生产环境不调用:cleanup() 会 join native threads(无活跃 PC 时通常 sub-second,
|
|
1040
|
+
* 但 worst-case 阻塞 10s),且 gateway 通过 process.exit() 退出无需依赖事件循环排空。
|
|
1041
|
+
*/
|
|
1042
|
+
export async function stopRealtimeBridge({ forceCleanup = false } = {}) {
|
|
1037
1043
|
if (!singleton) {
|
|
1038
1044
|
return;
|
|
1039
1045
|
}
|
|
1046
|
+
const cleanupFn = forceCleanup ? singleton.__ndcCleanup : null;
|
|
1040
1047
|
await singleton.stop();
|
|
1041
1048
|
singleton = null; // 置 null 后须通过 restartRealtimeBridge 重建
|
|
1049
|
+
if (typeof cleanupFn === 'function') {
|
|
1050
|
+
try { cleanupFn(); } catch { /* c8 ignore next -- cleanup 失败不影响 stop 结果 */ }
|
|
1051
|
+
}
|
|
1042
1052
|
}
|
|
1043
1053
|
|
|
1044
1054
|
export async function waitForSessionsReady() {
|
|
@@ -181,11 +181,31 @@ export async function preloadNdc(deps = {}) {
|
|
|
181
181
|
return weriftFallback(dynamicImport, log, importTimeout);
|
|
182
182
|
}
|
|
183
183
|
|
|
184
|
+
// 注册 libdatachannel 内部日志回调(Warning 级别),
|
|
185
|
+
// 用于捕获 ICE/DTLS/SCTP 层断连原因。
|
|
186
|
+
// initLogger 是进程全局单例,调用一次即可(cleanup 不会被调用,logger 全程有效)。
|
|
187
|
+
// callback 通过 TSFN 投递到 JS 主线程,Warning 级别正常运行时零输出。
|
|
188
|
+
const initLogger = ndc.initLogger ?? ndc.default?.initLogger;
|
|
189
|
+
if (typeof initLogger === 'function') {
|
|
190
|
+
try {
|
|
191
|
+
initLogger('Warning', (level, message) => {
|
|
192
|
+
try {
|
|
193
|
+
const msg = typeof message === 'string' ? message.replace(/\n/g, '\\n') : message;
|
|
194
|
+
log(`ndc.native level=${level} ${msg}`);
|
|
195
|
+
} catch { /* 不让任何异常传播到 native 层 */ }
|
|
196
|
+
});
|
|
197
|
+
log('ndc.logger-registered level=Warning');
|
|
198
|
+
} catch (err) {
|
|
199
|
+
// initLogger 失败不影响 ndc 正常使用
|
|
200
|
+
log(`ndc.logger-failed error=${err.message}`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
184
204
|
// 重要:调用方在不再需要 node-datachannel 时(如 bridge stop),必须调用 cleanup()。
|
|
185
205
|
// node-datachannel 内部使用 ThreadSafeCallback 维持 native threads,不调用 cleanup()
|
|
186
206
|
// 会阻止 Node 进程正常退出(上游 issue #366)。
|
|
187
|
-
//
|
|
188
|
-
//
|
|
207
|
+
// 当前 RealtimeBridge.stop() 不调用 cleanup()(阻塞 10s+),native threads 保持活跃供复用。
|
|
208
|
+
// 进程退出时 OS 会回收所有资源。
|
|
189
209
|
log(`ndc.loaded platform=${platformKey}`);
|
|
190
210
|
return { PeerConnection: wrapNdcCredentials(RTCPeerConnection), cleanup, impl: 'ndc' };
|
|
191
211
|
} catch (err) {
|