@songsid/agend 2.1.2 → 2.1.3-beta.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/dist/daemon.js CHANGED
@@ -1145,7 +1145,6 @@ export class Daemon extends EventEmitter {
1145
1145
  this.emitSupervisionEnded("the CLI exited normally (code 0)", "Nothing crashed — start it again when you need it.");
1146
1146
  return;
1147
1147
  }
1148
- this.setProcessStatus("crashed");
1149
1148
  // Distinguish tmux server crash from single window crash.
1150
1149
  // nullReason records *why* getPaneStatus returned null (for diagnosing
1151
1150
  // whether this was a real window loss or a transient query failure).
@@ -1182,8 +1181,17 @@ export class Daemon extends EventEmitter {
1182
1181
  nullReason = "no_window";
1183
1182
  try {
1184
1183
  const windows = await TmuxManager.listWindows(this.tmuxSessionName);
1184
+ const currentWindowId = this.tmux.getWindowId();
1185
+ if (windows.some(w => w.id === currentWindowId)) {
1186
+ // The exact window still exists, so `list-panes` was the query
1187
+ // that glitched. Keep the process/state intact and retry on
1188
+ // the next health tick instead of killing a live Kiro TUI.
1189
+ this.logger.warn({ windowId: currentWindowId }, `${cliLabel} pane status unavailable but window is present — deferring crash recovery`);
1190
+ scheduleNext();
1191
+ return;
1192
+ }
1185
1193
  if (windows.some(w => w.name === this.name))
1186
- nullReason = "window_present_query_glitch";
1194
+ nullReason = "same_name_other_window";
1187
1195
  }
1188
1196
  catch {
1189
1197
  nullReason = "query_error";
@@ -1194,6 +1202,7 @@ export class Daemon extends EventEmitter {
1194
1202
  else {
1195
1203
  this.logger.warn({ exitCode }, `${cliLabel} process exited`);
1196
1204
  }
1205
+ this.setProcessStatus("crashed");
1197
1206
  // Capture last output before killing. Best-effort even when the pane is
1198
1207
  // gone (paneStatus null) — gives the crash record something to diagnose
1199
1208
  // from instead of an empty lastOutput.
@@ -2433,17 +2442,23 @@ export class Daemon extends EventEmitter {
2433
2442
  await new Promise(r => setTimeout(r, enterSettleMs));
2434
2443
  let enterAt = Date.now();
2435
2444
  await this.tmux.sendSpecialKey("Enter");
2436
- // Kiro may expose its ready prompt before its final startup redraw. If
2437
- // that redraw swallows Enter, the redraw's own output makes the normal
2438
- // busy confirmation return true and suppresses the conditional retry.
2439
- // Kiro has no native input queue, so one defensive retry on the first
2440
- // post-ready delivery is safe and cannot mutate a queued turn.
2441
- if (enterSettleMs > NORMAL_ENTER_SETTLE_MS
2442
- && this.backend?.requiresFirstDeliveryEnterRetry?.() === true) {
2445
+ // Kiro's legacy TUI can swallow Enter while it is still processing a large
2446
+ // paste not only during the post-ready redraw (#479): on slower hosts it
2447
+ // happens on ordinary deliveries too (v2.1.2 stable, WSL2 + tmux 3.4).
2448
+ // The busy confirmation below cannot be trusted to catch that: it accepts
2449
+ // ANY output after Enter, and the paste's own late render satisfies it, so
2450
+ // the message is confirmed ✅ while the text sits unsubmitted. Kiro has no
2451
+ // native input queue and a bare Enter is a no-op both at an empty prompt
2452
+ // and during generation (both verified live on kiro-cli 2.16.1), so the
2453
+ // defensive retry runs on EVERY delivery — which is also what the legacy
2454
+ // pasteText path has always done for queue-less backends. enterAt is
2455
+ // re-baselined to the second Enter so leftover paste-render output between
2456
+ // the two cannot be what "confirms" the submission.
2457
+ if (this.backend?.requiresDeliveryEnterRetry?.() === true) {
2443
2458
  await new Promise(r => setTimeout(r, 1_000));
2444
2459
  enterAt = Date.now();
2445
2460
  await this.tmux.sendSpecialKey("Enter");
2446
- this.logger.debug("First delivery after ready sent defensive Enter retry");
2461
+ this.logger.debug("Sent defensive Enter retry (queue-less TUI can swallow the first)");
2447
2462
  }
2448
2463
  if (status)
2449
2464
  this.emit("message_delivered", status); // 👀