@songsid/agend 2.1.1-beta.15 → 2.1.1-beta.17
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/channel/ipc-timeouts.d.ts +40 -0
- package/dist/channel/ipc-timeouts.js +58 -0
- package/dist/channel/ipc-timeouts.js.map +1 -0
- package/dist/channel/mcp-server.js +5 -4
- package/dist/channel/mcp-server.js.map +1 -1
- package/dist/cli.js +8 -2
- package/dist/cli.js.map +1 -1
- package/dist/daemon.d.ts +13 -0
- package/dist/daemon.js +32 -9
- package/dist/daemon.js.map +1 -1
- package/dist/fleet-manager.d.ts +32 -0
- package/dist/fleet-manager.js +120 -14
- package/dist/fleet-manager.js.map +1 -1
- package/dist/instance-lifecycle.js +9 -0
- package/dist/instance-lifecycle.js.map +1 -1
- package/dist/outbound-handlers.d.ts +7 -0
- package/dist/outbound-handlers.js +62 -4
- package/dist/outbound-handlers.js.map +1 -1
- package/dist/topic-commands.d.ts +15 -2
- package/dist/topic-commands.js +62 -12
- package/dist/topic-commands.js.map +1 -1
- package/package.json +1 -1
package/dist/daemon.js
CHANGED
|
@@ -10,6 +10,7 @@ import { TmuxManager, resolveTmuxLogicalSize } from "./tmux-manager.js";
|
|
|
10
10
|
import { TranscriptMonitor } from "./transcript-monitor.js";
|
|
11
11
|
import { ContextGuardian } from "./context-guardian.js";
|
|
12
12
|
import { IpcServer } from "./channel/ipc-bridge.js";
|
|
13
|
+
import { daemonBudgetMs } from "./channel/ipc-timeouts.js";
|
|
13
14
|
import { MessageBus } from "./channel/message-bus.js";
|
|
14
15
|
import { shellQuote } from "./backend/types.js";
|
|
15
16
|
import { getTmuxSession } from "./config.js";
|
|
@@ -848,6 +849,7 @@ export class Daemon extends EventEmitter {
|
|
|
848
849
|
this.logger.warn({ instanceDir: this.instanceDir }, "Instance directory missing — stopping health check");
|
|
849
850
|
this.healthCheckPaused = true;
|
|
850
851
|
this.healthCheckTimer = null;
|
|
852
|
+
this.emitSupervisionEnded("instance directory was removed from disk", "Recreate the instance, or delete it from fleet.yaml.");
|
|
851
853
|
return;
|
|
852
854
|
}
|
|
853
855
|
if (!this.tmux || this.spawning || this.healthCheckPaused || Daemon.tmuxServerPaused) {
|
|
@@ -898,6 +900,7 @@ export class Daemon extends EventEmitter {
|
|
|
898
900
|
this.logger.info("CLI exited normally (code 0) — pausing health check");
|
|
899
901
|
await this.tmux.killWindow();
|
|
900
902
|
this.healthCheckPaused = true;
|
|
903
|
+
this.emitSupervisionEnded("the CLI exited normally (code 0)", "Nothing crashed — start it again when you need it.");
|
|
901
904
|
return;
|
|
902
905
|
}
|
|
903
906
|
this.setProcessStatus("crashed");
|
|
@@ -1007,6 +1010,7 @@ export class Daemon extends EventEmitter {
|
|
|
1007
1010
|
if (max_retries <= 0) {
|
|
1008
1011
|
this.healthCheckPaused = true;
|
|
1009
1012
|
this.logger.warn(`${cliLabel} window died — automatic restart is disabled`);
|
|
1013
|
+
this.emitSupervisionEnded("the CLI died and automatic restart is disabled (restart_policy.max_retries is 0)", "Start it manually, or raise max_retries in fleet.yaml.");
|
|
1010
1014
|
return;
|
|
1011
1015
|
}
|
|
1012
1016
|
// Detect rapid crash: sliding window — 3+ crashes in 5 minutes
|
|
@@ -1036,6 +1040,8 @@ export class Daemon extends EventEmitter {
|
|
|
1036
1040
|
this.lastCrashAt = Date.now();
|
|
1037
1041
|
if (this.crashCount > max_retries) {
|
|
1038
1042
|
this.logger.error({ crashCount: this.crashCount, maxRetries: max_retries }, "Max crash retries exceeded — not respawning");
|
|
1043
|
+
this.healthCheckPaused = true;
|
|
1044
|
+
this.emitSupervisionEnded(`it crashed ${this.crashCount} times, exceeding restart_policy.max_retries (${max_retries})`, "Check the logs for the cause, then restart it.");
|
|
1039
1045
|
return; // don't schedule next — given up
|
|
1040
1046
|
}
|
|
1041
1047
|
// Calculate backoff delay
|
|
@@ -1119,6 +1125,21 @@ export class Daemon extends EventEmitter {
|
|
|
1119
1125
|
* A dead remain-on-exit pane still contains the old ready prompt, so allowing
|
|
1120
1126
|
* the pane monitor to capture it would re-create a false idle state.
|
|
1121
1127
|
*/
|
|
1128
|
+
/**
|
|
1129
|
+
* Announce that this instance is no longer being supervised.
|
|
1130
|
+
*
|
|
1131
|
+
* Four health-check exits set `healthCheckPaused = true` and returned without
|
|
1132
|
+
* telling anyone: a clean CLI exit, `max_retries <= 0`, crash retries exhausted,
|
|
1133
|
+
* and the instance directory being deleted. Only the crash-LOOP case emitted an
|
|
1134
|
+
* event, so a fleet could quietly contain a dead instance that still looked fine
|
|
1135
|
+
* on the dashboard — while messages routed to it queued or failed with a bare ❌.
|
|
1136
|
+
*
|
|
1137
|
+
* `crash_loop` already had this treatment; this is the same bridge for the other
|
|
1138
|
+
* four, carrying a human-readable cause and the operator's next step.
|
|
1139
|
+
*/
|
|
1140
|
+
emitSupervisionEnded(reason, remedy) {
|
|
1141
|
+
this.emit("supervision_ended", { name: this.name, reason, remedy });
|
|
1142
|
+
}
|
|
1122
1143
|
setProcessStatus(status) {
|
|
1123
1144
|
if (this.processStatus === status)
|
|
1124
1145
|
return;
|
|
@@ -2236,8 +2257,8 @@ export class Daemon extends EventEmitter {
|
|
|
2236
2257
|
});
|
|
2237
2258
|
const timeout = setTimeout(() => {
|
|
2238
2259
|
this.pendingIpcRequests.delete(fleetReqId);
|
|
2239
|
-
respond(null,
|
|
2240
|
-
},
|
|
2260
|
+
respond(null, `Task operation timed out after ${daemonBudgetMs(tool) / 1000}s`);
|
|
2261
|
+
}, daemonBudgetMs(tool));
|
|
2241
2262
|
this.pendingIpcRequests.set(fleetReqId, (respMsg) => {
|
|
2242
2263
|
clearTimeout(timeout);
|
|
2243
2264
|
respond(respMsg.result, respMsg.error);
|
|
@@ -2259,8 +2280,8 @@ export class Daemon extends EventEmitter {
|
|
|
2259
2280
|
});
|
|
2260
2281
|
const timeout = setTimeout(() => {
|
|
2261
2282
|
this.pendingIpcRequests.delete(fleetReqId);
|
|
2262
|
-
respond(null,
|
|
2263
|
-
},
|
|
2283
|
+
respond(null, `Decision operation timed out after ${daemonBudgetMs(tool) / 1000}s`);
|
|
2284
|
+
}, daemonBudgetMs(tool));
|
|
2264
2285
|
this.pendingIpcRequests.set(fleetReqId, (respMsg) => {
|
|
2265
2286
|
clearTimeout(timeout);
|
|
2266
2287
|
respond(respMsg.result, respMsg.error);
|
|
@@ -2286,8 +2307,8 @@ export class Daemon extends EventEmitter {
|
|
|
2286
2307
|
// Wait for fleet_schedule_response via pending request map
|
|
2287
2308
|
const timeout = setTimeout(() => {
|
|
2288
2309
|
this.pendingIpcRequests.delete(fleetReqId);
|
|
2289
|
-
respond(null,
|
|
2290
|
-
},
|
|
2310
|
+
respond(null, `Schedule operation timed out after ${daemonBudgetMs(tool) / 1000}s`);
|
|
2311
|
+
}, daemonBudgetMs(tool));
|
|
2291
2312
|
this.pendingIpcRequests.set(fleetReqId, (respMsg) => {
|
|
2292
2313
|
clearTimeout(timeout);
|
|
2293
2314
|
respond(respMsg.result, respMsg.error);
|
|
@@ -2308,7 +2329,9 @@ export class Daemon extends EventEmitter {
|
|
|
2308
2329
|
fleetRequestId: fleetReqId,
|
|
2309
2330
|
senderSessionName,
|
|
2310
2331
|
});
|
|
2311
|
-
|
|
2332
|
+
// Shared table, so delete_instance and the deployment tools get the same
|
|
2333
|
+
// budget here as the MCP client expects (the ad-hoc list omitted them).
|
|
2334
|
+
const crossTimeoutMs = daemonBudgetMs(tool);
|
|
2312
2335
|
const timeout = setTimeout(() => {
|
|
2313
2336
|
this.pendingIpcRequests.delete(fleetReqId);
|
|
2314
2337
|
respond(null, `Cross-instance operation timed out after ${crossTimeoutMs / 1000}s`);
|
|
@@ -2351,8 +2374,8 @@ export class Daemon extends EventEmitter {
|
|
|
2351
2374
|
this.ipcServer?.broadcast({ type: "fleet_outbound", tool, args, fleetRequestId: fleetReqId });
|
|
2352
2375
|
const timeout = setTimeout(() => {
|
|
2353
2376
|
this.pendingIpcRequests.delete(outboundKey);
|
|
2354
|
-
respond(null,
|
|
2355
|
-
},
|
|
2377
|
+
respond(null, `Fleet outbound timed out after ${daemonBudgetMs(tool) / 1000}s`);
|
|
2378
|
+
}, daemonBudgetMs(tool));
|
|
2356
2379
|
this.pendingIpcRequests.set(outboundKey, (respMsg) => {
|
|
2357
2380
|
clearTimeout(timeout);
|
|
2358
2381
|
respond(respMsg.result, respMsg.error);
|