@eminent337/aery 0.1.71 → 0.1.73

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");
@@ -678,15 +686,30 @@ export class InteractiveMode {
678
686
  "damage-control",
679
687
  "provider-profiles",
680
688
  "model-failover",
689
+ "web-search",
690
+ "web-fetch",
691
+ "commands",
692
+ "hooks",
693
+ "circuit-breaker",
694
+ "auto-router",
695
+ "memory-include",
681
696
  "aery-header",
682
697
  "aery-footer",
698
+ "multi-agent",
699
+ "agent-chain",
700
+ "agent-teams",
683
701
  "help",
702
+ "default-agents",
703
+ "aery-doctor",
704
+ "aery-team",
705
+ ["subagent", "subagent/index"],
684
706
  ];
685
707
  if (existsSync(settingsPath)) {
686
708
  const settings = JSON.parse(readFileSync(settingsPath, "utf-8"));
687
709
  const existing = new Set(settings.extensions || []);
688
710
  for (const ext of CORE) {
689
- const p = join(repoPath, "core", `${ext}.ts`);
711
+ const [_name, filePath] = Array.isArray(ext) ? ext : [ext, ext];
712
+ const p = join(repoPath, "core", `${filePath}.ts`);
690
713
  if (existsSync(p) && !existing.has(p)) {
691
714
  settings.extensions = settings.extensions || [];
692
715
  settings.extensions.push(p);
@@ -2678,6 +2701,14 @@ export class InteractiveMode {
2678
2701
  await this.runtimeHost.dispose();
2679
2702
  process.exit(0);
2680
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
+ }
2681
2712
  /**
2682
2713
  * Check if shutdown was requested and perform shutdown if so.
2683
2714
  */
@@ -2694,12 +2725,25 @@ export class InteractiveMode {
2694
2725
  }
2695
2726
  for (const signal of signals) {
2696
2727
  const handler = () => {
2728
+ if (signal === "SIGHUP") {
2729
+ this.emergencyTerminalExit();
2730
+ }
2697
2731
  killTrackedDetachedChildren();
2698
2732
  void this.shutdown();
2699
2733
  };
2700
- process.on(signal, handler);
2734
+ process.prependListener(signal, handler);
2701
2735
  this.signalCleanupHandlers.push(() => process.off(signal, handler));
2702
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));
2703
2747
  }
2704
2748
  unregisterSignalHandlers() {
2705
2749
  for (const cleanup of this.signalCleanupHandlers) {