@songsid/agend 2.1.0-beta.7 → 2.1.0-beta.8
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/context-guardian.d.ts +2 -0
- package/dist/context-guardian.js +10 -2
- package/dist/context-guardian.js.map +1 -1
- package/dist/daemon-entry.js +2 -1
- package/dist/daemon-entry.js.map +1 -1
- package/dist/daemon.d.ts +8 -1
- package/dist/daemon.js +51 -18
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +1 -0
- package/dist/fleet-manager.js +4 -0
- package/dist/fleet-manager.js.map +1 -1
- package/dist/instance-lifecycle.d.ts +1 -0
- package/dist/instance-lifecycle.js +12 -2
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/logger.js +5 -2
- package/dist/logger.js.map +1 -1
- package/dist/statusline-watcher.d.ts +1 -1
- package/dist/statusline-watcher.js +3 -2
- package/dist/statusline-watcher.js.map +1 -1
- package/dist/transcript-monitor.js +2 -0
- package/dist/transcript-monitor.js.map +1 -1
- package/package.json +1 -1
|
@@ -18,6 +18,8 @@ export declare class ContextGuardian extends EventEmitter {
|
|
|
18
18
|
private logger;
|
|
19
19
|
private statusFilePath;
|
|
20
20
|
private consecutiveReadFailures;
|
|
21
|
+
private watching;
|
|
22
|
+
private readonly onStatusFileChange;
|
|
21
23
|
constructor(_config: GuardianConfig, logger: Logger, statusFilePath: string);
|
|
22
24
|
startWatching(): void;
|
|
23
25
|
private readAndCheck;
|
package/dist/context-guardian.js
CHANGED
|
@@ -16,6 +16,8 @@ export class ContextGuardian extends EventEmitter {
|
|
|
16
16
|
logger;
|
|
17
17
|
statusFilePath;
|
|
18
18
|
consecutiveReadFailures = 0;
|
|
19
|
+
watching = false;
|
|
20
|
+
onStatusFileChange = () => this.readAndCheck();
|
|
19
21
|
constructor(_config, logger, statusFilePath) {
|
|
20
22
|
super();
|
|
21
23
|
this._config = _config;
|
|
@@ -23,8 +25,11 @@ export class ContextGuardian extends EventEmitter {
|
|
|
23
25
|
this.statusFilePath = statusFilePath;
|
|
24
26
|
}
|
|
25
27
|
startWatching() {
|
|
28
|
+
if (this.watching)
|
|
29
|
+
return;
|
|
30
|
+
this.watching = true;
|
|
26
31
|
this.logger.debug({ path: this.statusFilePath }, "Watching status line file");
|
|
27
|
-
watchFile(this.statusFilePath, { interval: 2000 },
|
|
32
|
+
watchFile(this.statusFilePath, { interval: 2000 }, this.onStatusFileChange);
|
|
28
33
|
}
|
|
29
34
|
readAndCheck() {
|
|
30
35
|
try {
|
|
@@ -67,7 +72,10 @@ export class ContextGuardian extends EventEmitter {
|
|
|
67
72
|
}
|
|
68
73
|
}
|
|
69
74
|
stop() {
|
|
70
|
-
|
|
75
|
+
if (!this.watching)
|
|
76
|
+
return;
|
|
77
|
+
unwatchFile(this.statusFilePath, this.onStatusFileChange);
|
|
78
|
+
this.watching = false;
|
|
71
79
|
}
|
|
72
80
|
}
|
|
73
81
|
//# sourceMappingURL=context-guardian.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"context-guardian.js","sourceRoot":"","sources":["../src/context-guardian.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAM3E;;;;;;;;;;GAUG;AACH,MAAM,OAAO,eAAgB,SAAQ,YAAY;
|
|
1
|
+
{"version":3,"file":"context-guardian.js","sourceRoot":"","sources":["../src/context-guardian.ts"],"names":[],"mappings":"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"}
|
package/dist/daemon-entry.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { Daemon } from "./daemon.js";
|
|
2
|
+
import { createLogger } from "./logger.js";
|
|
2
3
|
const args = process.argv.slice(2);
|
|
3
4
|
function getArg(name) {
|
|
4
5
|
const idx = args.indexOf(name);
|
|
@@ -15,7 +16,7 @@ catch (err) {
|
|
|
15
16
|
process.exit(1);
|
|
16
17
|
}
|
|
17
18
|
const topicMode = args.includes("--topic-mode");
|
|
18
|
-
const daemon = new Daemon(name, config, instanceDir, topicMode);
|
|
19
|
+
const daemon = new Daemon(name, config, instanceDir, topicMode, undefined, undefined, createLogger(config.log_level));
|
|
19
20
|
daemon.start().catch((err) => {
|
|
20
21
|
console.error("Daemon failed:", err);
|
|
21
22
|
process.exit(1);
|
package/dist/daemon-entry.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"daemon-entry.js","sourceRoot":"","sources":["../src/daemon-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"daemon-entry.js","sourceRoot":"","sources":["../src/daemon-entry.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEnC,SAAS,MAAM,CAAC,IAAY;IAC1B,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B,OAAO,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AACzC,CAAC;AAED,MAAM,IAAI,GAAG,MAAM,CAAC,YAAY,CAAC,CAAC;AAClC,MAAM,WAAW,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;AAC7C,IAAI,MAAsB,CAAC;AAC3B,IAAI,CAAC;IACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAC;AAC1C,CAAC;AAAC,OAAO,GAAG,EAAE,CAAC;IACb,OAAO,CAAC,KAAK,CAAC,kCAAmC,GAAa,CAAC,OAAO,EAAE,CAAC,CAAC;IAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC;AAED,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,cAAc,CAAC,CAAC;AAChD,MAAM,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,YAAY,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC;AAEtH,MAAM,CAAC,KAAK,EAAE,CAAC,KAAK,CAAC,CAAC,GAAG,EAAE,EAAE;IAC3B,OAAO,CAAC,KAAK,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;IACrC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC,CAAC;AAEH,MAAM,QAAQ,GAAG,KAAK,IAAI,EAAE;IAC1B,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;IACpB,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;AAClB,CAAC,CAAC;AACF,OAAO,CAAC,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;AAChC,OAAO,CAAC,EAAE,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC"}
|
package/dist/daemon.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { EventEmitter } from "node:events";
|
|
2
2
|
import type { InstanceConfig, RotationSnapshot } from "./types.js";
|
|
3
|
+
import type { Logger } from "./logger.js";
|
|
3
4
|
import { MessageBus } from "./channel/message-bus.js";
|
|
4
5
|
import type { CliBackend, InstanceState, InstanceStateSnapshot } from "./backend/types.js";
|
|
5
6
|
import { HangDetector } from "./hang-detector.js";
|
|
@@ -99,6 +100,8 @@ export declare class Daemon extends EventEmitter {
|
|
|
99
100
|
private lastBuiltInstructions;
|
|
100
101
|
private pasteQueueDepth;
|
|
101
102
|
private errorMonitorTimer;
|
|
103
|
+
/** Prevent in-flight monitor callbacks from re-arming after a pause. */
|
|
104
|
+
private runtimeMonitorsFrozen;
|
|
102
105
|
private errorWaitingForRecovery;
|
|
103
106
|
private errorDetectedAt;
|
|
104
107
|
/** Whether this instance is in an abnormal error state (auto-pause is normal). */
|
|
@@ -114,7 +117,7 @@ export declare class Daemon extends EventEmitter {
|
|
|
114
117
|
private static ERROR_COOLDOWN_MS;
|
|
115
118
|
private lastErrorCount;
|
|
116
119
|
private lastDetectedErrorType;
|
|
117
|
-
constructor(name: string, config: InstanceConfig, instanceDir: string, topicMode?: boolean, backend?: CliBackend | undefined, controlClient?: TmuxControlClient | undefined);
|
|
120
|
+
constructor(name: string, config: InstanceConfig, instanceDir: string, topicMode?: boolean, backend?: CliBackend | undefined, controlClient?: TmuxControlClient | undefined, rootLogger?: Logger);
|
|
118
121
|
start(): Promise<void>;
|
|
119
122
|
private startHealthCheck;
|
|
120
123
|
/**
|
|
@@ -142,6 +145,10 @@ export declare class Daemon extends EventEmitter {
|
|
|
142
145
|
/** Respawn the CLI in the preserved window and block until its prompt is ready. */
|
|
143
146
|
wake(timeoutMs?: number): Promise<void>;
|
|
144
147
|
private startInstanceStateMonitor;
|
|
148
|
+
/** Stop every runtime poller/watcher while preserving IPC and daemon state. */
|
|
149
|
+
private freezeRuntimeMonitors;
|
|
150
|
+
/** Restore the same monitor objects after wake without adding event listeners. */
|
|
151
|
+
private resumeRuntimeMonitors;
|
|
145
152
|
getMessageBus(): MessageBus;
|
|
146
153
|
private summarizeTool;
|
|
147
154
|
private addToolStatus;
|
package/dist/daemon.js
CHANGED
|
@@ -3,7 +3,6 @@ import { mkdirSync, writeFileSync, readFileSync, existsSync, unlinkSync, rmSync,
|
|
|
3
3
|
import { fileURLToPath } from "node:url";
|
|
4
4
|
import { createHash, randomBytes } from "node:crypto";
|
|
5
5
|
import { EventEmitter } from "node:events";
|
|
6
|
-
import { createLogger } from "./logger.js";
|
|
7
6
|
import { TmuxManager } from "./tmux-manager.js";
|
|
8
7
|
import { TranscriptMonitor } from "./transcript-monitor.js";
|
|
9
8
|
import { ContextGuardian } from "./context-guardian.js";
|
|
@@ -189,6 +188,8 @@ export class Daemon extends EventEmitter {
|
|
|
189
188
|
pasteQueueDepth = 0;
|
|
190
189
|
// PTY error pattern monitoring
|
|
191
190
|
errorMonitorTimer = null;
|
|
191
|
+
/** Prevent in-flight monitor callbacks from re-arming after a pause. */
|
|
192
|
+
runtimeMonitorsFrozen = false;
|
|
192
193
|
errorWaitingForRecovery = false; // true = error detected, waiting for ready pattern
|
|
193
194
|
errorDetectedAt = 0;
|
|
194
195
|
/** Whether this instance is in an abnormal error state (auto-pause is normal). */
|
|
@@ -215,7 +216,7 @@ export class Daemon extends EventEmitter {
|
|
|
215
216
|
// still registers as new (prevents the old hash-dedup's permanent suppression).
|
|
216
217
|
lastErrorCount = new Map();
|
|
217
218
|
lastDetectedErrorType = null;
|
|
218
|
-
constructor(name, config, instanceDir, topicMode = false, backend, controlClient) {
|
|
219
|
+
constructor(name, config, instanceDir, topicMode = false, backend, controlClient, rootLogger) {
|
|
219
220
|
super();
|
|
220
221
|
this.name = name;
|
|
221
222
|
this.config = config;
|
|
@@ -223,7 +224,9 @@ export class Daemon extends EventEmitter {
|
|
|
223
224
|
this.topicMode = topicMode;
|
|
224
225
|
this.backend = backend;
|
|
225
226
|
this.controlClient = controlClient;
|
|
226
|
-
|
|
227
|
+
if (!rootLogger)
|
|
228
|
+
throw new Error("Daemon requires a shared root logger");
|
|
229
|
+
this.logger = rootLogger.child({ instance: name }, { level: config.log_level });
|
|
227
230
|
this.tmuxSessionName = getTmuxSession();
|
|
228
231
|
this.messageBus = new MessageBus();
|
|
229
232
|
this.messageBus.setLogger(this.logger);
|
|
@@ -521,11 +524,18 @@ export class Daemon extends EventEmitter {
|
|
|
521
524
|
this.logger.info(`${this.name} ready`);
|
|
522
525
|
}
|
|
523
526
|
startHealthCheck() {
|
|
527
|
+
if (this.runtimeMonitorsFrozen || this.healthCheckTimer)
|
|
528
|
+
return;
|
|
524
529
|
const { max_retries, backoff, reset_after } = this.config.restart_policy;
|
|
525
530
|
if (max_retries <= 0)
|
|
526
531
|
return; // restart disabled
|
|
527
532
|
const scheduleNext = () => {
|
|
533
|
+
if (this.runtimeMonitorsFrozen || this.healthCheckTimer)
|
|
534
|
+
return;
|
|
528
535
|
this.healthCheckTimer = setTimeout(async () => {
|
|
536
|
+
this.healthCheckTimer = null;
|
|
537
|
+
if (this.runtimeMonitorsFrozen)
|
|
538
|
+
return;
|
|
529
539
|
// Instance directory removed externally (e.g. `rm -rf ~/.agend/instances/<name>`).
|
|
530
540
|
// Stop the loop permanently — otherwise every tick triggers a respawn, whose
|
|
531
541
|
// writeRotationSnapshot fails with ENOENT and gets caught as "Failed to respawn",
|
|
@@ -776,6 +786,8 @@ export class Daemon extends EventEmitter {
|
|
|
776
786
|
* (ready pattern visible), it goes back to monitoring for new errors.
|
|
777
787
|
*/
|
|
778
788
|
startErrorMonitor() {
|
|
789
|
+
if (this.runtimeMonitorsFrozen || this.errorMonitorTimer)
|
|
790
|
+
return;
|
|
779
791
|
const patterns = this.backend?.getErrorPatterns?.() ?? [];
|
|
780
792
|
const dialogs = this.backend?.getRuntimeDialogs?.() ?? [];
|
|
781
793
|
if (!patterns.length && !dialogs.length)
|
|
@@ -895,26 +907,13 @@ export class Daemon extends EventEmitter {
|
|
|
895
907
|
}
|
|
896
908
|
async stop() {
|
|
897
909
|
this.logger.info("Stopping daemon instance");
|
|
898
|
-
|
|
899
|
-
clearTimeout(this.healthCheckTimer);
|
|
900
|
-
this.healthCheckTimer = null;
|
|
901
|
-
}
|
|
902
|
-
if (this.errorMonitorTimer) {
|
|
903
|
-
clearInterval(this.errorMonitorTimer);
|
|
904
|
-
this.errorMonitorTimer = null;
|
|
905
|
-
}
|
|
906
|
-
if (this.instanceStateMonitorTimer) {
|
|
907
|
-
clearInterval(this.instanceStateMonitorTimer);
|
|
908
|
-
this.instanceStateMonitorTimer = null;
|
|
909
|
-
}
|
|
910
|
+
this.freezeRuntimeMonitors();
|
|
910
911
|
if (this.toolStatusDebounce) {
|
|
911
912
|
clearTimeout(this.toolStatusDebounce);
|
|
912
913
|
this.toolStatusDebounce = null;
|
|
913
914
|
}
|
|
914
915
|
this.pendingIpcRequests.clear();
|
|
915
916
|
this.hangDetector?.stop();
|
|
916
|
-
this.transcriptMonitor?.stop();
|
|
917
|
-
this.guardian?.stop();
|
|
918
917
|
if (this.adapter)
|
|
919
918
|
await this.adapter.stop();
|
|
920
919
|
// Notify MCP servers of graceful shutdown (prevents reconnect attempts)
|
|
@@ -1007,6 +1006,7 @@ export class Daemon extends EventEmitter {
|
|
|
1007
1006
|
}
|
|
1008
1007
|
this.pauseWakeState = "pausing";
|
|
1009
1008
|
this.healthCheckPaused = true;
|
|
1009
|
+
this.freezeRuntimeMonitors();
|
|
1010
1010
|
const transition = (async () => {
|
|
1011
1011
|
try {
|
|
1012
1012
|
this.saveSessionId();
|
|
@@ -1053,6 +1053,7 @@ export class Daemon extends EventEmitter {
|
|
|
1053
1053
|
this.pauseWakeState = "active";
|
|
1054
1054
|
this.healthCheckPaused = false;
|
|
1055
1055
|
this.pauseRequested = false;
|
|
1056
|
+
this.resumeRuntimeMonitors();
|
|
1056
1057
|
throw err;
|
|
1057
1058
|
}
|
|
1058
1059
|
})();
|
|
@@ -1105,6 +1106,7 @@ export class Daemon extends EventEmitter {
|
|
|
1105
1106
|
}
|
|
1106
1107
|
catch { }
|
|
1107
1108
|
this.transcriptMonitor?.resetOffset();
|
|
1109
|
+
this.resumeRuntimeMonitors();
|
|
1108
1110
|
this.logger.info("Instance auto-woke");
|
|
1109
1111
|
this.ipcServer?.broadcast({
|
|
1110
1112
|
type: "instance_state", instanceName: this.name, state: this.instanceState, pausedAt: null,
|
|
@@ -1124,7 +1126,7 @@ export class Daemon extends EventEmitter {
|
|
|
1124
1126
|
}
|
|
1125
1127
|
}
|
|
1126
1128
|
startInstanceStateMonitor() {
|
|
1127
|
-
if (!this.tmux || !this.backend || this.instanceStateMonitorTimer)
|
|
1129
|
+
if (this.runtimeMonitorsFrozen || !this.tmux || !this.backend || this.instanceStateMonitorTimer)
|
|
1128
1130
|
return;
|
|
1129
1131
|
const rawConfig = this.config.hang_detector;
|
|
1130
1132
|
const timeoutMinutes = rawConfig?.timeout_minutes;
|
|
@@ -1180,6 +1182,37 @@ export class Daemon extends EventEmitter {
|
|
|
1180
1182
|
void poll();
|
|
1181
1183
|
this.instanceStateMonitorTimer = setInterval(() => { void poll(); }, pollIntervalMs);
|
|
1182
1184
|
}
|
|
1185
|
+
/** Stop every runtime poller/watcher while preserving IPC and daemon state. */
|
|
1186
|
+
freezeRuntimeMonitors() {
|
|
1187
|
+
this.runtimeMonitorsFrozen = true;
|
|
1188
|
+
if (this.healthCheckTimer) {
|
|
1189
|
+
clearTimeout(this.healthCheckTimer);
|
|
1190
|
+
this.healthCheckTimer = null;
|
|
1191
|
+
}
|
|
1192
|
+
if (this.errorMonitorTimer) {
|
|
1193
|
+
clearInterval(this.errorMonitorTimer);
|
|
1194
|
+
this.errorMonitorTimer = null;
|
|
1195
|
+
}
|
|
1196
|
+
if (this.instanceStateMonitorTimer) {
|
|
1197
|
+
clearInterval(this.instanceStateMonitorTimer);
|
|
1198
|
+
this.instanceStateMonitorTimer = null;
|
|
1199
|
+
}
|
|
1200
|
+
this.transcriptMonitor?.stop();
|
|
1201
|
+
this.guardian?.stop();
|
|
1202
|
+
}
|
|
1203
|
+
/** Restore the same monitor objects after wake without adding event listeners. */
|
|
1204
|
+
resumeRuntimeMonitors() {
|
|
1205
|
+
if (!this.runtimeMonitorsFrozen)
|
|
1206
|
+
return;
|
|
1207
|
+
this.runtimeMonitorsFrozen = false;
|
|
1208
|
+
this.startHealthCheck();
|
|
1209
|
+
if (!this.config.lightweight) {
|
|
1210
|
+
this.transcriptMonitor?.startPolling();
|
|
1211
|
+
this.guardian?.startWatching();
|
|
1212
|
+
this.startErrorMonitor();
|
|
1213
|
+
}
|
|
1214
|
+
this.startInstanceStateMonitor();
|
|
1215
|
+
}
|
|
1183
1216
|
getMessageBus() {
|
|
1184
1217
|
return this.messageBus;
|
|
1185
1218
|
}
|