openzca 0.1.19 → 0.1.21

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.
Files changed (2) hide show
  1. package/dist/cli.js +79 -4
  2. package/package.json +1 -1
package/dist/cli.js CHANGED
@@ -820,6 +820,66 @@ function isListenerAlreadyStarted(error) {
820
820
  function toErrorText(error) {
821
821
  return error instanceof Error ? error.message : String(error);
822
822
  }
823
+ var SHUTDOWN_CALLBACKS = /* @__PURE__ */ new Set();
824
+ var shutdownSignalReceived = null;
825
+ var shutdownRunning = false;
826
+ function signalExitCode(signal) {
827
+ if (signal === "SIGINT") return 130;
828
+ if (signal === "SIGTERM") return 143;
829
+ return 1;
830
+ }
831
+ function registerShutdownCallback(callback) {
832
+ SHUTDOWN_CALLBACKS.add(callback);
833
+ return () => {
834
+ SHUTDOWN_CALLBACKS.delete(callback);
835
+ };
836
+ }
837
+ async function runShutdownCallbacks(signal) {
838
+ if (shutdownRunning) return;
839
+ shutdownRunning = true;
840
+ const callbacks = Array.from(SHUTDOWN_CALLBACKS);
841
+ SHUTDOWN_CALLBACKS.clear();
842
+ writeDebugLine(
843
+ "process.signal",
844
+ {
845
+ signal,
846
+ callbackCount: callbacks.length
847
+ },
848
+ void 0
849
+ );
850
+ for (const callback of callbacks) {
851
+ try {
852
+ await Promise.resolve(callback());
853
+ } catch (error) {
854
+ writeDebugLine(
855
+ "process.signal.callback_error",
856
+ {
857
+ signal,
858
+ message: toErrorText(error)
859
+ },
860
+ void 0
861
+ );
862
+ }
863
+ }
864
+ }
865
+ function installSignalHandler(signal) {
866
+ process.on(signal, () => {
867
+ if (shutdownSignalReceived) return;
868
+ shutdownSignalReceived = signal;
869
+ const exitCode = signalExitCode(signal);
870
+ const forceExitMs = parsePositiveIntFromEnv("OPENZCA_SIGNAL_FORCE_EXIT_MS", 1500);
871
+ const forceTimer = setTimeout(() => {
872
+ process.exit(exitCode);
873
+ }, forceExitMs);
874
+ forceTimer.unref();
875
+ void runShutdownCallbacks(signal).finally(() => {
876
+ clearTimeout(forceTimer);
877
+ process.exit(exitCode);
878
+ });
879
+ });
880
+ }
881
+ installSignalHandler("SIGINT");
882
+ installSignalHandler("SIGTERM");
823
883
  async function withTimeout(task, timeoutMs, message) {
824
884
  let timeoutId;
825
885
  try {
@@ -848,8 +908,14 @@ async function stopUploadListenerSafely(api, command, waitClosedMs = 1500) {
848
908
  api.listener.on("closed", onClosed);
849
909
  timeoutId = setTimeout(finish, waitClosedMs);
850
910
  try {
851
- api.listener.stop();
852
- writeDebugLine("msg.upload.listener.stop", void 0, command);
911
+ const internalWs = api.listener.ws;
912
+ if (internalWs && typeof internalWs.close === "function") {
913
+ internalWs.close(1e3);
914
+ writeDebugLine("msg.upload.listener.stop.ws_close", void 0, command);
915
+ } else {
916
+ api.listener.stop();
917
+ writeDebugLine("msg.upload.listener.stop", void 0, command);
918
+ }
853
919
  } catch {
854
920
  finish();
855
921
  }
@@ -865,6 +931,9 @@ async function withUploadListener(api, command, task) {
865
931
  12e4
866
932
  );
867
933
  let startedHere = false;
934
+ const unregisterSignalCleanup = registerShutdownCallback(async () => {
935
+ await stopUploadListenerSafely(api, command);
936
+ });
868
937
  const sinkError = (error) => {
869
938
  writeDebugLine(
870
939
  "msg.upload.listener.error",
@@ -955,6 +1024,7 @@ async function withUploadListener(api, command, task) {
955
1024
  if (startedHere) {
956
1025
  await stopUploadListenerSafely(api, command);
957
1026
  }
1027
+ unregisterSignalCleanup();
958
1028
  api.listener.off("error", sinkError);
959
1029
  api.listener.off("closed", sinkClosed);
960
1030
  }
@@ -3252,6 +3322,8 @@ ${replyContextText}` : replyContextText;
3252
3322
  let recycleForceExitTimer = null;
3253
3323
  let heartbeatTimer = null;
3254
3324
  let recyclePendingExit = false;
3325
+ let unregisterShutdown = () => {
3326
+ };
3255
3327
  const finish = () => {
3256
3328
  if (settled) return;
3257
3329
  settled = true;
@@ -3267,6 +3339,9 @@ ${replyContextText}` : replyContextText;
3267
3339
  clearInterval(heartbeatTimer);
3268
3340
  heartbeatTimer = null;
3269
3341
  }
3342
+ unregisterShutdown();
3343
+ unregisterShutdown = () => {
3344
+ };
3270
3345
  resolve();
3271
3346
  };
3272
3347
  api.listener.on("closed", (code, reason) => {
@@ -3289,13 +3364,14 @@ ${replyContextText}` : replyContextText;
3289
3364
  finish();
3290
3365
  }
3291
3366
  });
3292
- const onSigint = () => {
3367
+ const onSignal = () => {
3293
3368
  try {
3294
3369
  api.listener.stop();
3295
3370
  } catch {
3296
3371
  }
3297
3372
  finish();
3298
3373
  };
3374
+ unregisterShutdown = registerShutdownCallback(onSignal);
3299
3375
  if (lifecycleEventsEnabled && heartbeatMs > 0) {
3300
3376
  heartbeatTimer = setInterval(() => {
3301
3377
  emitLifecycle("heartbeat");
@@ -3330,7 +3406,6 @@ ${replyContextText}` : replyContextText;
3330
3406
  finish();
3331
3407
  }, recycleMs);
3332
3408
  }
3333
- process.once("SIGINT", onSigint);
3334
3409
  api.listener.start({ retryOnClose: supervised ? false : Boolean(opts.keepAlive) });
3335
3410
  });
3336
3411
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "openzca",
3
- "version": "0.1.19",
3
+ "version": "0.1.21",
4
4
  "description": "Open-source zca-compatible CLI to integrate Zalo with OpenClaw",
5
5
  "type": "module",
6
6
  "bin": {