aegis-bridge 2.12.1 → 2.12.3
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/session.js +14 -2
- package/dist/tmux.js +11 -1
- package/package.json +1 -1
package/dist/session.js
CHANGED
|
@@ -759,9 +759,21 @@ export class SessionManager {
|
|
|
759
759
|
const windowHealth = await this.tmux.getWindowHealth(session.windowId);
|
|
760
760
|
if (!windowHealth.windowExists)
|
|
761
761
|
return false;
|
|
762
|
-
// Pane exit
|
|
763
|
-
|
|
762
|
+
// Pane exit: give CC a grace period to finish after last prompt.
|
|
763
|
+
// CC exits after processing (normal), but paneDead fires BEFORE work is fully recorded.
|
|
764
|
+
// If paneDead just fired and session was recently active, wait before marking dead.
|
|
765
|
+
// This gives CC time to finish writing results before Aegis closes the session.
|
|
766
|
+
if (windowHealth.paneDead && session.status !== 'idle') {
|
|
767
|
+
const msSinceActivity = Date.now() - (session.lastActivity || session.createdAt);
|
|
768
|
+
const GRACE_PERIOD_MS = 5000; // 5 seconds — enough for CC to finish and write results
|
|
769
|
+
if (msSinceActivity < GRACE_PERIOD_MS) {
|
|
770
|
+
// Pane just died right after activity — likely CC is finishing up.
|
|
771
|
+
// Don't mark dead yet — give it 5 seconds to complete.
|
|
772
|
+
return true;
|
|
773
|
+
}
|
|
774
|
+
// Grace period expired — CC has had time to finish. If pane is still dead, it's really dead.
|
|
764
775
|
return false;
|
|
776
|
+
}
|
|
765
777
|
// Verify the process inside the pane is still alive
|
|
766
778
|
const panePid = await this.tmux.listPanePid(session.windowId);
|
|
767
779
|
if (panePid !== null && !this.tmux.isPidAlive(panePid))
|
package/dist/tmux.js
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
import { execFile } from 'node:child_process';
|
|
8
8
|
import { promisify } from 'node:util';
|
|
9
9
|
import { readdir, rename as fsRename, mkdir, stat } from 'node:fs/promises';
|
|
10
|
-
import { existsSync } from 'node:fs';
|
|
10
|
+
import { existsSync, readFileSync } from 'node:fs';
|
|
11
11
|
import { join } from 'node:path';
|
|
12
12
|
import { homedir, tmpdir } from 'node:os';
|
|
13
13
|
import { randomBytes } from 'node:crypto';
|
|
@@ -496,7 +496,17 @@ export class TmuxManager {
|
|
|
496
496
|
/** Issue #69: Check if a PID is alive using kill -0. */
|
|
497
497
|
isPidAlive(pid) {
|
|
498
498
|
try {
|
|
499
|
+
// First check: does process exist?
|
|
499
500
|
process.kill(pid, 0);
|
|
501
|
+
// Second check: is it a zombie? (zombies still exist but are dead)
|
|
502
|
+
// Read /proc/<pid>/stat synchronously — state is 3rd field
|
|
503
|
+
try {
|
|
504
|
+
const stat = readFileSync(`/proc/${pid}/stat`, 'utf8');
|
|
505
|
+
const match = stat.match(/^\d+ \([^)]+\) ([A-Z])/);
|
|
506
|
+
if (match && match[1] === 'Z')
|
|
507
|
+
return false; // Zombie = dead
|
|
508
|
+
}
|
|
509
|
+
catch { /* /proc check failed — process might have exited */ }
|
|
500
510
|
return true;
|
|
501
511
|
}
|
|
502
512
|
catch { /* ESRCH — process does not exist */
|