@songsid/agend 2.1.4-beta.26 → 2.1.4-beta.28

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/dist/daemon.js CHANGED
@@ -9,6 +9,7 @@ import { clearPausedMarker, writePausedMarker } from "./pause-marker.js";
9
9
  import { TmuxManager, resolveTmuxLogicalSize } from "./tmux-manager.js";
10
10
  import { TranscriptMonitor } from "./transcript-monitor.js";
11
11
  import { createTranscriptSource } from "./transcript-sources.js";
12
+ import { LOGIN_FLOWS } from "./login-flows.js";
12
13
  import { ProgressAccumulator, summarizeProgress } from "./tool-progress.js";
13
14
  import { ContextGuardian } from "./context-guardian.js";
14
15
  import { IpcServer } from "./channel/ipc-bridge.js";
@@ -773,6 +774,8 @@ export class Daemon extends EventEmitter {
773
774
  * instance is still auth-broken and must not resume raising alarms.
774
775
  */
775
776
  authFailureUnresolved = false;
777
+ /** One login-screen auth report per spawn — the screen persists across polls. */
778
+ loginScreenReported = false;
776
779
  /**
777
780
  * Let the next pause() proceed from a stuck pane. Set only for the auth-deferred
778
781
  * pause — see the pausePending consumption site for why waiting for idle there
@@ -1241,9 +1244,13 @@ export class Daemon extends EventEmitter {
1241
1244
  return;
1242
1245
  this.mcpDeathNotifiedForPid = status.pid;
1243
1246
  this.lastMcpDeathNotifiedAt = Date.now();
1244
- const autoRestart = this.config.mcp_auto_restart !== false;
1245
- this.logger.error({ pid: status.pid, autoRestart }, "MCP server process is gone — instance has no agend tools");
1246
- this.emit("mcp_died", { name: this.name, pid: status.pid, autoRestart });
1247
+ // An auth-broken CLI cannot keep an MCP server alive, and restarting it
1248
+ // only loops back to the sign-in screen — hold the auto-restart until a
1249
+ // re-login (which restarts the instance and replaces this daemon anyway).
1250
+ const authSuspected = this.authFailureUnresolved;
1251
+ const autoRestart = this.config.mcp_auto_restart !== false && !authSuspected;
1252
+ this.logger.error({ pid: status.pid, autoRestart, authSuspected }, "MCP server process is gone — instance has no agend tools");
1253
+ this.emit("mcp_died", { name: this.name, pid: status.pid, autoRestart, authSuspected });
1247
1254
  if (autoRestart)
1248
1255
  this.armMcpRestartWhenIdle();
1249
1256
  }
@@ -2156,6 +2163,7 @@ export class Daemon extends EventEmitter {
2156
2163
  // auth pause — otherwise the instance would pause again the moment it idles.
2157
2164
  this.pausePending = false;
2158
2165
  this.authFailureUnresolved = false;
2166
+ this.loginScreenReported = false;
2159
2167
  if (this.pauseWakeState === "active")
2160
2168
  return;
2161
2169
  if (this.pauseWakeState === "pausing")
@@ -3683,7 +3691,10 @@ export class Daemon extends EventEmitter {
3683
3691
  }
3684
3692
  /** Build config object for the CLI backend */
3685
3693
  buildBackendConfig() {
3686
- const isCliMode = this.config.agent_mode === "cli" || (this.config.agent_mode == null && this.config.backend === "antigravity");
3694
+ // Antigravity 1.1.17 has no per-workspace MCP config, but its global MCP
3695
+ // children inherit the CLI process environment. The backend installs one
3696
+ // environment-selecting launcher, so MCP is now the safe default here too.
3697
+ const isCliMode = this.config.agent_mode === "cli";
3687
3698
  const sockPath = join(this.instanceDir, "channel.sock");
3688
3699
  let serverJs = join(__dirname, "channel", "mcp-server.js");
3689
3700
  if (!existsSync(serverJs)) {
@@ -4169,6 +4180,24 @@ export class Daemon extends EventEmitter {
4169
4180
  // CLI is ready (pattern defined by each backend)
4170
4181
  if (this.backend.getReadyPattern().test(pane))
4171
4182
  return true;
4183
+ // A CLI parked at its own sign-in screen is an AUTH incident: no dialog
4184
+ // key can dismiss it and no ready pattern will ever appear. Report it as
4185
+ // an auth error (the lifecycle double-checks with the token-free probe)
4186
+ // instead of letting it decay into crash/hang/MCP-died noise, and stop
4187
+ // the retry loop — only re-login (see /login) ends this state.
4188
+ const loginScreen = LOGIN_FLOWS[this.config.backend ?? "claude-code"]?.loginScreenPattern;
4189
+ if (loginScreen?.test(pane) && !this.loginScreenReported) {
4190
+ this.loginScreenReported = true;
4191
+ this.authFailureUnresolved = true;
4192
+ this.logger.warn({ backend: this.config.backend }, "CLI is waiting at its sign-in screen — reporting auth error");
4193
+ this.emit("pty_error", {
4194
+ name: this.name,
4195
+ type: "auth_error",
4196
+ action: "pause",
4197
+ message: "CLI is waiting at its sign-in screen — credentials are missing or expired",
4198
+ });
4199
+ return true;
4200
+ }
4172
4201
  // Fatal: command not found (must match full phrase to avoid false positives
4173
4202
  // like Kiro's "agent X not found, using default")
4174
4203
  if (/command not found|: not found$/m.test(pane))