@eminent337/aery 0.1.75 → 0.1.76

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.
@@ -72,6 +72,14 @@ class ExpandableText extends Text {
72
72
  this.setText(expanded ? this.getExpandedText() : this.getCollapsedText());
73
73
  }
74
74
  }
75
+ const DEAD_TERMINAL_ERROR_CODES = new Set(["EIO", "EPIPE", "ENOTCONN"]);
76
+ function isDeadTerminalError(error) {
77
+ if (!error || typeof error !== "object" || !("code" in error)) {
78
+ return false;
79
+ }
80
+ const code = error.code;
81
+ return code !== undefined && DEAD_TERMINAL_ERROR_CODES.has(code);
82
+ }
75
83
  const ANTHROPIC_SUBSCRIPTION_AUTH_WARNING = "Anthropic subscription auth is active. Third-party harness usage draws from extra usage and is billed per token, not your Claude plan limits. Manage extra usage at https://claude.ai/settings/usage.";
76
84
  function isAnthropicSubscriptionAuthKey(apiKey) {
77
85
  return typeof apiKey === "string" && apiKey.startsWith("sk-ant-oat");
@@ -2693,6 +2701,14 @@ export class InteractiveMode {
2693
2701
  await this.runtimeHost.dispose();
2694
2702
  process.exit(0);
2695
2703
  }
2704
+ emergencyTerminalExit() {
2705
+ this.isShuttingDown = true;
2706
+ this.unregisterSignalHandlers();
2707
+ killTrackedDetachedChildren();
2708
+ // The terminal is gone. Do not run normal shutdown because TUI and
2709
+ // extension cleanup can write restore sequences and re-trigger EIO.
2710
+ process.exit(129);
2711
+ }
2696
2712
  /**
2697
2713
  * Check if shutdown was requested and perform shutdown if so.
2698
2714
  */
@@ -2709,12 +2725,25 @@ export class InteractiveMode {
2709
2725
  }
2710
2726
  for (const signal of signals) {
2711
2727
  const handler = () => {
2728
+ if (signal === "SIGHUP") {
2729
+ this.emergencyTerminalExit();
2730
+ }
2712
2731
  killTrackedDetachedChildren();
2713
2732
  void this.shutdown();
2714
2733
  };
2715
- process.on(signal, handler);
2734
+ process.prependListener(signal, handler);
2716
2735
  this.signalCleanupHandlers.push(() => process.off(signal, handler));
2717
2736
  }
2737
+ const terminalErrorHandler = (error) => {
2738
+ if (isDeadTerminalError(error)) {
2739
+ this.emergencyTerminalExit();
2740
+ }
2741
+ throw error;
2742
+ };
2743
+ process.stdout.on("error", terminalErrorHandler);
2744
+ process.stderr.on("error", terminalErrorHandler);
2745
+ this.signalCleanupHandlers.push(() => process.stdout.off("error", terminalErrorHandler));
2746
+ this.signalCleanupHandlers.push(() => process.stderr.off("error", terminalErrorHandler));
2718
2747
  }
2719
2748
  unregisterSignalHandlers() {
2720
2749
  for (const cleanup of this.signalCleanupHandlers) {