@songsid/agend 2.0.12-beta.9 → 2.1.0-beta.1
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/README.md +1 -0
- package/dist/backend/kiro.js +1 -1
- package/dist/backend/kiro.js.map +1 -1
- package/dist/backend/types.d.ts +18 -1
- package/dist/backend/types.js.map +1 -1
- package/dist/daemon.d.ts +29 -1
- package/dist/daemon.js +158 -7
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-context.d.ts +5 -0
- package/dist/fleet-manager.d.ts +13 -0
- package/dist/fleet-manager.js +82 -9
- package/dist/fleet-manager.js.map +1 -1
- package/dist/instance-lifecycle.js +1 -1
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/topic-commands.js +12 -0
- package/dist/topic-commands.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -4,6 +4,7 @@
|
|
|
4
4
|
<strong>Run a fleet of AI coding agents from your phone.</strong>
|
|
5
5
|
</p>
|
|
6
6
|
<p align="center">
|
|
7
|
+
<a href="https://songsid.github.io/AgEnD"><img src="https://img.shields.io/badge/Website-songsid.github.io/AgEnD-blue" alt="Website"></a>
|
|
7
8
|
<a href="https://www.npmjs.com/package/@songsid/agend"><img src="https://img.shields.io/npm/v/@songsid/agend" alt="npm"></a>
|
|
8
9
|
<a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-blue.svg" alt="License: MIT"></a>
|
|
9
10
|
<a href="https://nodejs.org"><img src="https://img.shields.io/badge/Node.js-%3E%3D%2020-green.svg" alt="Node.js >= 20"></a>
|
package/dist/backend/kiro.js
CHANGED
|
@@ -95,7 +95,7 @@ export class KiroBackend {
|
|
|
95
95
|
getErrorPatterns() {
|
|
96
96
|
return [
|
|
97
97
|
{ pattern: /having trouble responding/i, type: "rate_limit", action: "notify", message: "Rate limit (having trouble responding)" },
|
|
98
|
-
{ pattern: /Response timed out/i, type: "
|
|
98
|
+
{ pattern: /Response timed out/i, type: "timeout", action: "notify", message: "Kiro response timed out (generation too long) — please try again", skipCooldown: true, skipRecoveryWait: true },
|
|
99
99
|
];
|
|
100
100
|
}
|
|
101
101
|
getStartupDialogs() {
|
package/dist/backend/kiro.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"kiro.js","sourceRoot":"","sources":["../../src/backend/kiro.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"kiro.js","sourceRoot":"","sources":["../../src/backend/kiro.ts"],"names":[],"mappings":"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"}
|
package/dist/backend/types.d.ts
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/** Observable execution state derived from the active CLI pane. */
|
|
2
|
+
export type InstanceState = "idle" | "working" | "stuck";
|
|
3
|
+
/** Point-in-time state returned by the daemon's IPC state query. */
|
|
4
|
+
export interface InstanceStateSnapshot {
|
|
5
|
+
state: InstanceState;
|
|
6
|
+
/** Milliseconds since the pane content last changed. */
|
|
7
|
+
unchangedForMs: number;
|
|
8
|
+
/** Unix timestamp of the most recent successful pane observation. */
|
|
9
|
+
observedAt: number;
|
|
10
|
+
/** Unix timestamp of the most recent state transition. */
|
|
11
|
+
stateChangedAt: number;
|
|
12
|
+
}
|
|
1
13
|
export interface McpServerEntry {
|
|
2
14
|
command: string;
|
|
3
15
|
args: string[];
|
|
@@ -22,7 +34,7 @@ export interface CliBackendConfig {
|
|
|
22
34
|
/** Action to take when an error pattern is detected in PTY output. */
|
|
23
35
|
export type ErrorActionType = "notify" | "failover" | "restart" | "pause";
|
|
24
36
|
/** Categorizes detected errors for logging and response. */
|
|
25
|
-
export type ErrorType = "rate_limit" | "auth_error" | "crash" | "network" | "quota";
|
|
37
|
+
export type ErrorType = "rate_limit" | "auth_error" | "crash" | "network" | "quota" | "timeout";
|
|
26
38
|
export interface ErrorPattern {
|
|
27
39
|
pattern: RegExp;
|
|
28
40
|
type: ErrorType;
|
|
@@ -32,6 +44,11 @@ export interface ErrorPattern {
|
|
|
32
44
|
/** Skip the 5-min per-type notification cooldown so every occurrence notifies
|
|
33
45
|
* (e.g. Kiro "Response timed out" — each timeout should reach the user). */
|
|
34
46
|
skipCooldown?: boolean;
|
|
47
|
+
/** Don't enter the "waiting for recovery" state after this error. Use for
|
|
48
|
+
* self-recovering errors (e.g. a timeout — the CLI is back at its prompt
|
|
49
|
+
* immediately) whose backend ready-pattern only matches the startup banner,
|
|
50
|
+
* so waiting would block ALL future error detection forever. */
|
|
51
|
+
skipRecoveryWait?: boolean;
|
|
35
52
|
}
|
|
36
53
|
/** A dialog that may appear at runtime and needs auto-dismissal via key sequences. */
|
|
37
54
|
export interface RuntimeDialog {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backend/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/backend/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AA0IlD;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAY;IACxC,IAAI,CAAC;QACH,OAAO,YAAY,CAAC,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IACrE,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC,CAAC,wBAAwB;IACvC,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,aAAa,GAAG,qBAAqB,CAAC;AAC5C,MAAM,UAAU,aAAa,CAAC,KAAa;IACzC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,uBAAuB,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,iBAAiB,aAAa,EAAE,CAAC,CAAC;IAChG,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,0GAA0G;AAC1G,MAAM,sBAAsB,GAA2B;IACrD,aAAa,EAAE,4CAA4C;IAC3D,UAAU,EAAE,8BAA8B;IAC1C,OAAO,EAAE,wBAAwB;IACjC,YAAY,EAAE,UAAU;IACxB,UAAU,EAAE,GAAG,EAAG,iDAAiD;IACnE,aAAa,EAAE,GAAG,EAAG,kFAAkF;CACxG,CAAC;AAEF,kEAAkE;AAClE,MAAM,UAAU,iBAAiB,CAAC,WAAmB,EAAE,KAAa;IAClE,MAAM,OAAO,GAAG,sBAAsB,CAAC,WAAW,CAAC,CAAC;IACpD,IAAI,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC,CAAC,iCAAiC;IAC5D,OAAO,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,mBAAmB,CAAC,WAAmB,EAAE,KAAa;IACpE,IAAI,CAAC,iBAAiB,CAAC,WAAW,EAAE,KAAK,CAAC,EAAE,CAAC;QAC3C,OAAO,CAAC,IAAI,CAAC,kBAAkB,KAAK,uCAAuC,WAAW,0BAA0B,CAAC,CAAC;IACpH,CAAC;AACH,CAAC;AAED,mFAAmF;AACnF,MAAM,UAAU,UAAU,CAAC,CAAS;IAClC,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,CAAC;AACzC,CAAC"}
|
package/dist/daemon.d.ts
CHANGED
|
@@ -1,9 +1,30 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import type { InstanceConfig, RotationSnapshot } from "./types.js";
|
|
3
3
|
import { MessageBus } from "./channel/message-bus.js";
|
|
4
|
-
import type { CliBackend } from "./backend/types.js";
|
|
4
|
+
import type { CliBackend, InstanceState, InstanceStateSnapshot } from "./backend/types.js";
|
|
5
5
|
import { HangDetector } from "./hang-detector.js";
|
|
6
6
|
import type { TmuxControlClient } from "./tmux-control.js";
|
|
7
|
+
export declare const DEFAULT_STUCK_TIMEOUT_MS: number;
|
|
8
|
+
export declare const DEFAULT_STATE_POLL_INTERVAL_MS = 5000;
|
|
9
|
+
/**
|
|
10
|
+
* Headless state machine for pane-based execution state detection.
|
|
11
|
+
*
|
|
12
|
+
* Pane motion wins over a ready match because several backends keep their ready
|
|
13
|
+
* marker in a persistent header/footer while generating. A stable ready pane is
|
|
14
|
+
* idle; changing content is working; stable non-ready content eventually sticks.
|
|
15
|
+
*/
|
|
16
|
+
export declare class PaneStateMachine {
|
|
17
|
+
private readonly stuckTimeoutMs;
|
|
18
|
+
private readonly readyPattern;
|
|
19
|
+
private lastPaneHash;
|
|
20
|
+
private lastPaneChangeAt;
|
|
21
|
+
private lastObservedAt;
|
|
22
|
+
private stateChangedAt;
|
|
23
|
+
private currentState;
|
|
24
|
+
constructor(readyPattern: RegExp, stuckTimeoutMs?: number, now?: number);
|
|
25
|
+
observe(pane: string, now?: number): InstanceStateSnapshot;
|
|
26
|
+
snapshot(now?: number): InstanceStateSnapshot;
|
|
27
|
+
}
|
|
7
28
|
export declare class Daemon extends EventEmitter {
|
|
8
29
|
private name;
|
|
9
30
|
private config;
|
|
@@ -45,6 +66,10 @@ export declare class Daemon extends EventEmitter {
|
|
|
45
66
|
private rotationStartedAt;
|
|
46
67
|
private preRotationContextPct;
|
|
47
68
|
private hangDetector;
|
|
69
|
+
private instanceState;
|
|
70
|
+
private instanceStateMachine;
|
|
71
|
+
private instanceStateMonitorTimer;
|
|
72
|
+
private statePollInFlight;
|
|
48
73
|
private modelOverride;
|
|
49
74
|
private recentUserMessages;
|
|
50
75
|
private recentEvents;
|
|
@@ -90,6 +115,9 @@ export declare class Daemon extends EventEmitter {
|
|
|
90
115
|
sendEscape(): Promise<void>;
|
|
91
116
|
stop(): Promise<void>;
|
|
92
117
|
getHangDetector(): HangDetector | null;
|
|
118
|
+
getInstanceState(): InstanceState;
|
|
119
|
+
getInstanceStateSnapshot(): InstanceStateSnapshot;
|
|
120
|
+
private startInstanceStateMonitor;
|
|
93
121
|
getMessageBus(): MessageBus;
|
|
94
122
|
private summarizeTool;
|
|
95
123
|
private addToolStatus;
|
package/dist/daemon.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { join, dirname, basename, resolve } from "node:path";
|
|
2
2
|
import { mkdirSync, writeFileSync, readFileSync, existsSync, unlinkSync, rmSync, appendFileSync, statSync, chmodSync } from "node:fs";
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
|
-
import { randomBytes } from "node:crypto";
|
|
4
|
+
import { createHash, randomBytes } from "node:crypto";
|
|
5
5
|
import { EventEmitter } from "node:events";
|
|
6
6
|
import { createLogger } from "./logger.js";
|
|
7
7
|
import { TmuxManager } from "./tmux-manager.js";
|
|
@@ -21,6 +21,66 @@ const CROSS_INSTANCE_TOOLS = new Set(["send_to_instance", "list_instances", "sta
|
|
|
21
21
|
const SCHEDULE_TOOLS = new Set(["create_schedule", "list_schedules", "update_schedule", "delete_schedule"]);
|
|
22
22
|
const DECISION_TOOLS = new Set(["post_decision", "list_decisions", "update_decision"]);
|
|
23
23
|
const TASK_TOOL = "task";
|
|
24
|
+
export const DEFAULT_STUCK_TIMEOUT_MS = 10 * 60_000;
|
|
25
|
+
export const DEFAULT_STATE_POLL_INTERVAL_MS = 5_000;
|
|
26
|
+
/**
|
|
27
|
+
* Headless state machine for pane-based execution state detection.
|
|
28
|
+
*
|
|
29
|
+
* Pane motion wins over a ready match because several backends keep their ready
|
|
30
|
+
* marker in a persistent header/footer while generating. A stable ready pane is
|
|
31
|
+
* idle; changing content is working; stable non-ready content eventually sticks.
|
|
32
|
+
*/
|
|
33
|
+
export class PaneStateMachine {
|
|
34
|
+
stuckTimeoutMs;
|
|
35
|
+
readyPattern;
|
|
36
|
+
lastPaneHash = null;
|
|
37
|
+
lastPaneChangeAt;
|
|
38
|
+
lastObservedAt;
|
|
39
|
+
stateChangedAt;
|
|
40
|
+
currentState = "idle";
|
|
41
|
+
constructor(readyPattern, stuckTimeoutMs = DEFAULT_STUCK_TIMEOUT_MS, now = Date.now()) {
|
|
42
|
+
this.stuckTimeoutMs = stuckTimeoutMs;
|
|
43
|
+
// Stateful g/y regexes mutate lastIndex and can alternate true/false across
|
|
44
|
+
// polls. State detection must be deterministic for identical pane content.
|
|
45
|
+
this.readyPattern = new RegExp(readyPattern.source, readyPattern.flags.replace(/[gy]/g, ""));
|
|
46
|
+
this.lastPaneChangeAt = now;
|
|
47
|
+
this.lastObservedAt = now;
|
|
48
|
+
this.stateChangedAt = now;
|
|
49
|
+
}
|
|
50
|
+
observe(pane, now = Date.now()) {
|
|
51
|
+
const paneHash = createHash("sha256").update(pane).digest("hex");
|
|
52
|
+
const firstObservation = this.lastPaneHash === null;
|
|
53
|
+
const paneChanged = this.lastPaneHash !== paneHash;
|
|
54
|
+
if (paneChanged) {
|
|
55
|
+
this.lastPaneHash = paneHash;
|
|
56
|
+
this.lastPaneChangeAt = now;
|
|
57
|
+
}
|
|
58
|
+
this.lastObservedAt = now;
|
|
59
|
+
const ready = this.readyPattern.test(pane);
|
|
60
|
+
const nextState = firstObservation
|
|
61
|
+
? ready ? "idle" : "working"
|
|
62
|
+
: paneChanged
|
|
63
|
+
? "working"
|
|
64
|
+
: ready
|
|
65
|
+
? "idle"
|
|
66
|
+
: now - this.lastPaneChangeAt >= this.stuckTimeoutMs
|
|
67
|
+
? "stuck"
|
|
68
|
+
: "working";
|
|
69
|
+
if (nextState !== this.currentState) {
|
|
70
|
+
this.currentState = nextState;
|
|
71
|
+
this.stateChangedAt = now;
|
|
72
|
+
}
|
|
73
|
+
return this.snapshot(now);
|
|
74
|
+
}
|
|
75
|
+
snapshot(now = Date.now()) {
|
|
76
|
+
return {
|
|
77
|
+
state: this.currentState,
|
|
78
|
+
unchangedForMs: Math.max(0, now - this.lastPaneChangeAt),
|
|
79
|
+
observedAt: this.lastObservedAt,
|
|
80
|
+
stateChangedAt: this.stateChangedAt,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
}
|
|
24
84
|
export class Daemon extends EventEmitter {
|
|
25
85
|
name;
|
|
26
86
|
config;
|
|
@@ -68,6 +128,10 @@ export class Daemon extends EventEmitter {
|
|
|
68
128
|
rotationStartedAt = 0;
|
|
69
129
|
preRotationContextPct = 0;
|
|
70
130
|
hangDetector = null;
|
|
131
|
+
instanceState = "idle";
|
|
132
|
+
instanceStateMachine = null;
|
|
133
|
+
instanceStateMonitorTimer = null;
|
|
134
|
+
statePollInFlight = false;
|
|
71
135
|
// Model failover: override model on next spawn when rate-limited
|
|
72
136
|
modelOverride;
|
|
73
137
|
// Context rotation v3: ring buffers for daemon-side snapshot
|
|
@@ -252,6 +316,15 @@ export class Daemon extends EventEmitter {
|
|
|
252
316
|
// Fleet manager sent us the messageId for our tool status message
|
|
253
317
|
this.toolStatusMessageId = msg.messageId;
|
|
254
318
|
}
|
|
319
|
+
else if (msg.type === "query_instance_state") {
|
|
320
|
+
const snapshot = this.getInstanceStateSnapshot();
|
|
321
|
+
this.ipcServer?.send(socket, {
|
|
322
|
+
type: "instance_state_response",
|
|
323
|
+
requestId: msg.requestId,
|
|
324
|
+
instanceName: this.name,
|
|
325
|
+
...snapshot,
|
|
326
|
+
});
|
|
327
|
+
}
|
|
255
328
|
});
|
|
256
329
|
// 2. Tmux — ensure session, create window if not alive
|
|
257
330
|
await TmuxManager.ensureSession(this.tmuxSessionName);
|
|
@@ -356,9 +429,13 @@ export class Daemon extends EventEmitter {
|
|
|
356
429
|
this.recordRecentEvent({ type: "assistant_text", preview: text.slice(0, 100) });
|
|
357
430
|
});
|
|
358
431
|
this.transcriptMonitor.startPolling();
|
|
359
|
-
//
|
|
360
|
-
|
|
361
|
-
|
|
432
|
+
// HangDetector remains the fleet-manager notification event bridge. Its
|
|
433
|
+
// legacy silence timer is intentionally not started: pane state transitions
|
|
434
|
+
// below are now the sole source of hang events.
|
|
435
|
+
const hangConfig = this.config.hang_detector;
|
|
436
|
+
if (hangConfig?.enabled !== false) {
|
|
437
|
+
this.hangDetector = new HangDetector(hangConfig?.timeout_minutes ?? 10);
|
|
438
|
+
}
|
|
362
439
|
// 8. Context guardian
|
|
363
440
|
const statusFile = join(this.instanceDir, "statusline.json");
|
|
364
441
|
this.guardian = new ContextGuardian(this.config.context_guardian, this.logger, statusFile);
|
|
@@ -382,6 +459,7 @@ export class Daemon extends EventEmitter {
|
|
|
382
459
|
if (!this.config.lightweight) {
|
|
383
460
|
this.startErrorMonitor();
|
|
384
461
|
}
|
|
462
|
+
this.startInstanceStateMonitor();
|
|
385
463
|
this.logger.info(`${this.name} ready`);
|
|
386
464
|
}
|
|
387
465
|
startHealthCheck() {
|
|
@@ -719,9 +797,16 @@ export class Daemon extends EventEmitter {
|
|
|
719
797
|
break;
|
|
720
798
|
}
|
|
721
799
|
this.lastErrorCount.set(ep.type, count);
|
|
722
|
-
this.
|
|
723
|
-
|
|
724
|
-
|
|
800
|
+
// skipRecoveryWait: this error self-recovers (e.g. a timeout — Kiro is
|
|
801
|
+
// back at its prompt immediately). Its ready-pattern only matches the
|
|
802
|
+
// startup banner, so entering "waiting for recovery" would never clear
|
|
803
|
+
// and would block ALL future error detection. Just absorb the baseline
|
|
804
|
+
// (done above) and keep monitoring so the next occurrence still fires.
|
|
805
|
+
if (!ep.skipRecoveryWait) {
|
|
806
|
+
this.errorWaitingForRecovery = true;
|
|
807
|
+
this.errorDetectedAt = Date.now();
|
|
808
|
+
this.lastDetectedErrorType = ep.type;
|
|
809
|
+
}
|
|
725
810
|
this.lastErrorNotifiedAt.set(ep.type, Date.now());
|
|
726
811
|
if (ep.action === "failover")
|
|
727
812
|
this.lastFailoverAt = Date.now();
|
|
@@ -754,6 +839,10 @@ export class Daemon extends EventEmitter {
|
|
|
754
839
|
clearInterval(this.errorMonitorTimer);
|
|
755
840
|
this.errorMonitorTimer = null;
|
|
756
841
|
}
|
|
842
|
+
if (this.instanceStateMonitorTimer) {
|
|
843
|
+
clearInterval(this.instanceStateMonitorTimer);
|
|
844
|
+
this.instanceStateMonitorTimer = null;
|
|
845
|
+
}
|
|
757
846
|
if (this.toolStatusDebounce) {
|
|
758
847
|
clearTimeout(this.toolStatusDebounce);
|
|
759
848
|
this.toolStatusDebounce = null;
|
|
@@ -824,6 +913,68 @@ export class Daemon extends EventEmitter {
|
|
|
824
913
|
getHangDetector() {
|
|
825
914
|
return this.hangDetector;
|
|
826
915
|
}
|
|
916
|
+
getInstanceState() {
|
|
917
|
+
return this.instanceState;
|
|
918
|
+
}
|
|
919
|
+
getInstanceStateSnapshot() {
|
|
920
|
+
return this.instanceStateMachine?.snapshot() ?? {
|
|
921
|
+
state: this.instanceState,
|
|
922
|
+
unchangedForMs: 0,
|
|
923
|
+
observedAt: Date.now(),
|
|
924
|
+
stateChangedAt: Date.now(),
|
|
925
|
+
};
|
|
926
|
+
}
|
|
927
|
+
startInstanceStateMonitor() {
|
|
928
|
+
if (!this.tmux || !this.backend || this.instanceStateMonitorTimer)
|
|
929
|
+
return;
|
|
930
|
+
const rawConfig = this.config.hang_detector;
|
|
931
|
+
const timeoutMinutes = rawConfig?.timeout_minutes;
|
|
932
|
+
const stuckTimeoutMs = typeof timeoutMinutes === "number" && timeoutMinutes > 0
|
|
933
|
+
? timeoutMinutes * 60_000
|
|
934
|
+
: DEFAULT_STUCK_TIMEOUT_MS;
|
|
935
|
+
const pollIntervalMs = typeof rawConfig?.poll_interval_ms === "number" && rawConfig.poll_interval_ms > 0
|
|
936
|
+
? rawConfig.poll_interval_ms
|
|
937
|
+
: DEFAULT_STATE_POLL_INTERVAL_MS;
|
|
938
|
+
this.instanceStateMachine = new PaneStateMachine(this.backend.getReadyPattern(), stuckTimeoutMs);
|
|
939
|
+
const poll = async () => {
|
|
940
|
+
if (!this.tmux || this.spawning || this.statePollInFlight)
|
|
941
|
+
return;
|
|
942
|
+
this.statePollInFlight = true;
|
|
943
|
+
try {
|
|
944
|
+
const paneStatus = await this.tmux.getPaneStatus();
|
|
945
|
+
if (!paneStatus?.alive)
|
|
946
|
+
return;
|
|
947
|
+
const pane = await this.tmux.capturePane();
|
|
948
|
+
const previous = this.instanceState;
|
|
949
|
+
const snapshot = this.instanceStateMachine.observe(pane);
|
|
950
|
+
this.instanceState = snapshot.state;
|
|
951
|
+
if (snapshot.state !== previous) {
|
|
952
|
+
this.logger.info({
|
|
953
|
+
previousState: previous,
|
|
954
|
+
state: snapshot.state,
|
|
955
|
+
unchangedForMs: snapshot.unchangedForMs,
|
|
956
|
+
}, "Instance execution state changed");
|
|
957
|
+
this.emit("instance_state", { name: this.name, ...snapshot });
|
|
958
|
+
this.ipcServer?.broadcast({ type: "instance_state", instanceName: this.name, ...snapshot });
|
|
959
|
+
// Emit exactly once per transition into stuck. Further notifications
|
|
960
|
+
// require observable progress (working) or a ready prompt (idle) first.
|
|
961
|
+
if (snapshot.state === "stuck") {
|
|
962
|
+
this.hangDetector?.emit("hang");
|
|
963
|
+
}
|
|
964
|
+
}
|
|
965
|
+
}
|
|
966
|
+
catch (err) {
|
|
967
|
+
// A pane can disappear between status and capture during restart. Keep
|
|
968
|
+
// the last known state and retry on the next poll.
|
|
969
|
+
this.logger.debug({ err: err.message }, "Instance state poll failed");
|
|
970
|
+
}
|
|
971
|
+
finally {
|
|
972
|
+
this.statePollInFlight = false;
|
|
973
|
+
}
|
|
974
|
+
};
|
|
975
|
+
void poll();
|
|
976
|
+
this.instanceStateMonitorTimer = setInterval(() => { void poll(); }, pollIntervalMs);
|
|
977
|
+
}
|
|
827
978
|
getMessageBus() {
|
|
828
979
|
return this.messageBus;
|
|
829
980
|
}
|