@integrity-labs/agt-cli 0.28.636 → 0.28.638
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/bin/agt.js +5 -5
- package/dist/{chunk-KIOTRBOI.js → chunk-LCKKFDCR.js} +156 -41
- package/dist/chunk-LCKKFDCR.js.map +1 -0
- package/dist/{chunk-O4ADFO57.js → chunk-MAZUBHNT.js} +5 -1
- package/dist/chunk-MAZUBHNT.js.map +1 -0
- package/dist/{chunk-4HVSMJFM.js → chunk-MRQ2GRTN.js} +2 -2
- package/dist/{claude-pair-runtime-TROVZ3M5.js → claude-pair-runtime-EZUIIJYB.js} +2 -2
- package/dist/lib/manager-worker.js +60 -55
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-7UX2BZMT.js → persistent-session-NMGMDXTO.js} +3 -3
- package/dist/{responsiveness-probe-BQCFTEK5.js → responsiveness-probe-ZUFKGLDN.js} +3 -3
- package/dist/{session-auth-dead-TV2M6AFN.js → session-auth-dead-TDWEX7R5.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-KIOTRBOI.js.map +0 -1
- package/dist/chunk-O4ADFO57.js.map +0 -1
- /package/dist/{chunk-4HVSMJFM.js.map → chunk-MRQ2GRTN.js.map} +0 -0
- /package/dist/{claude-pair-runtime-TROVZ3M5.js.map → claude-pair-runtime-EZUIIJYB.js.map} +0 -0
- /package/dist/{persistent-session-7UX2BZMT.js.map → persistent-session-NMGMDXTO.js.map} +0 -0
- /package/dist/{responsiveness-probe-BQCFTEK5.js.map → responsiveness-probe-ZUFKGLDN.js.map} +0 -0
- /package/dist/{session-auth-dead-TV2M6AFN.js.map → session-auth-dead-TDWEX7R5.js.map} +0 -0
package/dist/bin/agt.js
CHANGED
|
@@ -40,10 +40,10 @@ import {
|
|
|
40
40
|
success,
|
|
41
41
|
table,
|
|
42
42
|
warn
|
|
43
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-LCKKFDCR.js";
|
|
44
44
|
import {
|
|
45
45
|
readDirectChatSessionState
|
|
46
|
-
} from "../chunk-
|
|
46
|
+
} from "../chunk-MRQ2GRTN.js";
|
|
47
47
|
import {
|
|
48
48
|
AnchorSessionClient,
|
|
49
49
|
CHANNEL_REGISTRY,
|
|
@@ -73,7 +73,7 @@ import {
|
|
|
73
73
|
requiredMcpWildcard,
|
|
74
74
|
resolveChannels,
|
|
75
75
|
serializeManifestForSlackCli
|
|
76
|
-
} from "../chunk-
|
|
76
|
+
} from "../chunk-MAZUBHNT.js";
|
|
77
77
|
import "../chunk-XWVM4KPK.js";
|
|
78
78
|
|
|
79
79
|
// src/bin/agt.ts
|
|
@@ -4909,7 +4909,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4909
4909
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4910
4910
|
import chalk18 from "chalk";
|
|
4911
4911
|
import ora16 from "ora";
|
|
4912
|
-
var cliVersion = true ? "0.28.
|
|
4912
|
+
var cliVersion = true ? "0.28.638" : "dev";
|
|
4913
4913
|
async function fetchLatestVersion() {
|
|
4914
4914
|
const host2 = getHost();
|
|
4915
4915
|
if (!host2) return null;
|
|
@@ -6089,7 +6089,7 @@ function handleError(err) {
|
|
|
6089
6089
|
}
|
|
6090
6090
|
|
|
6091
6091
|
// src/bin/agt.ts
|
|
6092
|
-
var cliVersion2 = true ? "0.28.
|
|
6092
|
+
var cliVersion2 = true ? "0.28.638" : "dev";
|
|
6093
6093
|
var program = new Command();
|
|
6094
6094
|
program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
|
|
6095
6095
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -6,8 +6,9 @@ import {
|
|
|
6
6
|
buildRemoteMcpEntry,
|
|
7
7
|
expandTemplateVars,
|
|
8
8
|
isolationMode,
|
|
9
|
+
log,
|
|
9
10
|
parseEnvIntegrations
|
|
10
|
-
} from "./chunk-
|
|
11
|
+
} from "./chunk-MRQ2GRTN.js";
|
|
11
12
|
import {
|
|
12
13
|
BIND_FAILURE_QUARANTINE_THRESHOLD,
|
|
13
14
|
INTEGRATIONS_SECTION_END,
|
|
@@ -21,6 +22,8 @@ import {
|
|
|
21
22
|
RESTART_BREAKER_OPERATOR_MAX,
|
|
22
23
|
RESTART_BREAKER_PROVISIONING_MAX,
|
|
23
24
|
RESTART_BREAKER_PROVISIONING_WINDOW_MS,
|
|
25
|
+
RESTART_BREAKER_SCHEDULED_MAX,
|
|
26
|
+
RESTART_BREAKER_SCHEDULED_WINDOW_MS,
|
|
24
27
|
SCRATCH_RETENTION_DAYS,
|
|
25
28
|
SLACK_SOCKET_STATE_FILENAME,
|
|
26
29
|
bestConnectivityEvidence,
|
|
@@ -52,7 +55,7 @@ import {
|
|
|
52
55
|
resolveConnectivityProbe,
|
|
53
56
|
worseConnectivityOutcome,
|
|
54
57
|
wrapScheduledTaskPrompt
|
|
55
|
-
} from "./chunk-
|
|
58
|
+
} from "./chunk-MAZUBHNT.js";
|
|
56
59
|
import {
|
|
57
60
|
parsePsRows
|
|
58
61
|
} from "./chunk-XWVM4KPK.js";
|
|
@@ -1535,7 +1538,7 @@ function getAgentDir(codeName) {
|
|
|
1535
1538
|
return resolveRealAgentPath(join2(getHomeDir(), ".augmented", codeName));
|
|
1536
1539
|
}
|
|
1537
1540
|
var migratedCodeNames = /* @__PURE__ */ new Set();
|
|
1538
|
-
function migrateLegacyClaudecodeDir(codeName,
|
|
1541
|
+
function migrateLegacyClaudecodeDir(codeName, log2) {
|
|
1539
1542
|
assertValidCodeName(codeName);
|
|
1540
1543
|
if (migratedCodeNames.has(codeName))
|
|
1541
1544
|
return;
|
|
@@ -1546,7 +1549,7 @@ function migrateLegacyClaudecodeDir(codeName, log) {
|
|
|
1546
1549
|
}
|
|
1547
1550
|
const newRoot = getAgentDir(codeName);
|
|
1548
1551
|
const emit = (msg) => {
|
|
1549
|
-
|
|
1552
|
+
log2?.(msg);
|
|
1550
1553
|
};
|
|
1551
1554
|
try {
|
|
1552
1555
|
const walkAndMigrate = (srcDir, destDir) => {
|
|
@@ -6070,7 +6073,7 @@ function exchangeFailureKind(err) {
|
|
|
6070
6073
|
}
|
|
6071
6074
|
|
|
6072
6075
|
// src/lib/api-client.ts
|
|
6073
|
-
var agtCliVersion = true ? "0.28.
|
|
6076
|
+
var agtCliVersion = true ? "0.28.638" : "dev";
|
|
6074
6077
|
var lastConfigHash = null;
|
|
6075
6078
|
function setConfigHash(hash) {
|
|
6076
6079
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -6884,7 +6887,7 @@ function findMcpChildrenForAgent(args) {
|
|
|
6884
6887
|
return matched;
|
|
6885
6888
|
}
|
|
6886
6889
|
function reapStaleMcpChildren(args) {
|
|
6887
|
-
const { log, codeName, serverKeys, mcpJson, graceMs = 5e3, isolated = false } = args;
|
|
6890
|
+
const { log: log2, codeName, serverKeys, mcpJson, graceMs = 5e3, isolated = false } = args;
|
|
6888
6891
|
if (serverKeys.length === 0) return [];
|
|
6889
6892
|
const runPs = args.runPs ?? (isolated ? () => execFileSync("docker", ["exec", `agt-${codeName}`, "ps", "-eo", "pid,ppid,args"], {
|
|
6890
6893
|
encoding: "utf-8",
|
|
@@ -6927,7 +6930,7 @@ function reapStaleMcpChildren(args) {
|
|
|
6927
6930
|
try {
|
|
6928
6931
|
psOutput = runPs();
|
|
6929
6932
|
} catch (err) {
|
|
6930
|
-
|
|
6933
|
+
log2(`[stale-mcp-reaper] ps invocation failed for '${codeName}': ${err.message} \u2014 skipping reap`);
|
|
6931
6934
|
return [];
|
|
6932
6935
|
}
|
|
6933
6936
|
const rows = parsePsRows(psOutput);
|
|
@@ -6939,7 +6942,7 @@ function reapStaleMcpChildren(args) {
|
|
|
6939
6942
|
const pkgMatch = argv.match(/(@[a-z0-9_-]+\/[a-z0-9_-]+|[a-z0-9_-]+-mcp-server|[a-z0-9_-]+-mcp\b)/i);
|
|
6940
6943
|
return pkgMatch ? `${pkgMatch[1]} (pid ${pid})` : `pid ${pid}`;
|
|
6941
6944
|
};
|
|
6942
|
-
|
|
6945
|
+
log2(
|
|
6943
6946
|
`[stale-mcp-reaper] '${codeName}': rotating ${targets.length} stale MCP child(ren) for [${serverKeys.join(", ")}]: ${targets.map(describe).join(", ")}`
|
|
6944
6947
|
);
|
|
6945
6948
|
for (const pid of targets) {
|
|
@@ -6961,7 +6964,7 @@ function reapStaleMcpChildren(args) {
|
|
|
6961
6964
|
try {
|
|
6962
6965
|
freshPsOutput = runPs();
|
|
6963
6966
|
} catch (err) {
|
|
6964
|
-
|
|
6967
|
+
log2(`[stale-mcp-reaper] '${codeName}': fresh ps for SIGKILL re-verify failed: ${err.message} \u2014 skipping SIGKILL pass`);
|
|
6965
6968
|
return;
|
|
6966
6969
|
}
|
|
6967
6970
|
const stillOwned = new Set(
|
|
@@ -6975,14 +6978,14 @@ function reapStaleMcpChildren(args) {
|
|
|
6975
6978
|
);
|
|
6976
6979
|
const stragglers = targets.filter((pid) => isAlive(pid) && stillOwned.has(pid));
|
|
6977
6980
|
if (stragglers.length === 0) return;
|
|
6978
|
-
|
|
6981
|
+
log2(
|
|
6979
6982
|
`[stale-mcp-reaper] '${codeName}': ${stragglers.length} child(ren) survived SIGTERM; sending SIGKILL: ${stragglers.map(describe).join(", ")}`
|
|
6980
6983
|
);
|
|
6981
6984
|
for (const pid of stragglers) {
|
|
6982
6985
|
killProcess(pid, "SIGKILL");
|
|
6983
6986
|
}
|
|
6984
6987
|
} catch (err) {
|
|
6985
|
-
|
|
6988
|
+
log2(`[stale-mcp-reaper] '${codeName}': error in SIGKILL pass: ${err.message}`);
|
|
6986
6989
|
}
|
|
6987
6990
|
}, graceMs).unref();
|
|
6988
6991
|
return targets;
|
|
@@ -7051,7 +7054,7 @@ function findMissingMcpServers(args) {
|
|
|
7051
7054
|
}
|
|
7052
7055
|
function reapMissingMcpSessions(args) {
|
|
7053
7056
|
const {
|
|
7054
|
-
log,
|
|
7057
|
+
log: log2,
|
|
7055
7058
|
codeName,
|
|
7056
7059
|
mcpJson,
|
|
7057
7060
|
sessionStartedAt,
|
|
@@ -7107,7 +7110,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7107
7110
|
try {
|
|
7108
7111
|
psOutput = runPs();
|
|
7109
7112
|
} catch (err) {
|
|
7110
|
-
|
|
7113
|
+
log2(`[mcp-presence-reaper] ps invocation failed for '${codeName}': ${err.message} \u2014 skipping`);
|
|
7111
7114
|
return { missing: [], restarted: false, reason: "healthy" };
|
|
7112
7115
|
}
|
|
7113
7116
|
const rows = parsePsRows(psOutput);
|
|
@@ -7123,7 +7126,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7123
7126
|
try {
|
|
7124
7127
|
onRotationRespawnOutcome(codeName, key, outcome);
|
|
7125
7128
|
} catch (err) {
|
|
7126
|
-
|
|
7129
|
+
log2(
|
|
7127
7130
|
`[mcp-presence-reaper] onRotationRespawnOutcome callback threw for '${codeName}:${key}' (suppressed; reaper continues): ${err.message}`
|
|
7128
7131
|
);
|
|
7129
7132
|
}
|
|
@@ -7150,7 +7153,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7150
7153
|
escalated: false
|
|
7151
7154
|
};
|
|
7152
7155
|
if (priorStall && priorStall !== stall) {
|
|
7153
|
-
|
|
7156
|
+
log2(
|
|
7154
7157
|
`[mcp-presence-reaper] '${codeName}:${key}' discarding stall state from a previous rotation (rotation=${priorStall.rotationRecordedAt}, probes=${priorStall.probeAttempts}, escalated=${priorStall.escalated}) \u2014 this is a NEW rotation (rotation=${rotationRecordedAt}) and gets a full prompt-probe budget (ENG-8225)`
|
|
7155
7158
|
);
|
|
7156
7159
|
}
|
|
@@ -7168,14 +7171,14 @@ function reapMissingMcpSessions(args) {
|
|
|
7168
7171
|
stall.escalated = true;
|
|
7169
7172
|
rotationProbeExhausted.push(key);
|
|
7170
7173
|
recordRotationOutcome(key, "never-respawned");
|
|
7171
|
-
|
|
7174
|
+
log2(
|
|
7172
7175
|
`[mcp-presence-reaper] '${codeName}:${key}' rotation outcome=never-respawned \u2014 child SIGTERM'd by stale-mcp-reaper never returned after ${stall.probeAttempts} prompt bind-probe(s); escalating (integration marked unhealthy + reaper_action alert) and releasing to the normal restart path (ENG-8225)`
|
|
7173
7176
|
);
|
|
7174
7177
|
if (onRotationRespawnGaveUp) {
|
|
7175
7178
|
try {
|
|
7176
7179
|
onRotationRespawnGaveUp(codeName, key, { attempts: stall.probeAttempts });
|
|
7177
7180
|
} catch (err) {
|
|
7178
|
-
|
|
7181
|
+
log2(
|
|
7179
7182
|
`[mcp-presence-reaper] onRotationRespawnGaveUp callback threw for '${codeName}:${key}' (suppressed; reaper continues): ${err.message}`
|
|
7180
7183
|
);
|
|
7181
7184
|
}
|
|
@@ -7192,7 +7195,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7192
7195
|
maxAttempts: maxRotationPromptProbes
|
|
7193
7196
|
});
|
|
7194
7197
|
} catch (err) {
|
|
7195
|
-
|
|
7198
|
+
log2(
|
|
7196
7199
|
`[mcp-presence-reaper] onRotationRespawnStalled callback threw for '${codeName}:${key}' (suppressed; falling back to the pre-ENG-8225 restart path): ${err.message}`
|
|
7197
7200
|
);
|
|
7198
7201
|
armed = false;
|
|
@@ -7205,17 +7208,17 @@ function reapMissingMcpSessions(args) {
|
|
|
7205
7208
|
stall.probeAttempts = attempt;
|
|
7206
7209
|
stall.lastProbeAt = now();
|
|
7207
7210
|
rotationProbeArmed.push(key);
|
|
7208
|
-
|
|
7211
|
+
log2(
|
|
7209
7212
|
`[mcp-presence-reaper] '${codeName}:${key}' rotation grace expired (${rotationGraceMs}ms) with no live child and no tool call to respawn it \u2014 armed prompt bind-probe ${attempt}/${maxRotationPromptProbes} (ENG-7429) instead of restarting the session (ENG-8225)`
|
|
7210
7213
|
);
|
|
7211
7214
|
}
|
|
7212
7215
|
if (rotationGraced.length > 0) {
|
|
7213
|
-
|
|
7216
|
+
log2(
|
|
7214
7217
|
`[mcp-presence-reaper] '${codeName}': skipping [${rotationGraced.join(", ")}] within rotation grace window (${rotationGraceMs}ms) \u2014 child(ren) just SIGTERM'd by stale-mcp-reaper, awaiting respawn on next tool call (ENG-5344)`
|
|
7215
7218
|
);
|
|
7216
7219
|
}
|
|
7217
7220
|
if (rotationProbeWaiting.length > 0) {
|
|
7218
|
-
|
|
7221
|
+
log2(
|
|
7219
7222
|
`[mcp-presence-reaper] '${codeName}': skipping [${rotationProbeWaiting.join(", ")}] \u2014 prompt bind-probe already armed for the stalled rotation, waiting out the ${rotationPromptProbeIntervalMs}ms re-arm interval (ENG-8225)`
|
|
7220
7223
|
);
|
|
7221
7224
|
}
|
|
@@ -7238,7 +7241,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7238
7241
|
key,
|
|
7239
7242
|
viaProbe ? "respawned-after-prompt-probe" : "respawned-on-tool-call"
|
|
7240
7243
|
);
|
|
7241
|
-
|
|
7244
|
+
log2(
|
|
7242
7245
|
viaProbe ? `[mcp-presence-reaper] '${codeName}:${key}' rotation outcome=respawned-after-prompt-probe \u2014 child is live again after ${stall?.probeAttempts} prompt bind-probe(s)${stall?.escalated ? " (recovered AFTER escalation \u2014 the earlier never-respawned verdict stands for that window)" : ""}, no session restart needed (ENG-8225)` : `[mcp-presence-reaper] '${codeName}:${key}' rotation outcome=respawned-on-tool-call \u2014 child returned on the agent's own next tool call, ENG-5344's assumption held (ENG-8225)`
|
|
7243
7246
|
);
|
|
7244
7247
|
clearStaleRotation(codeName, [key]);
|
|
@@ -7306,7 +7309,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7306
7309
|
genuinelyDead.push(key);
|
|
7307
7310
|
if (currentGenerationExternallyStarted && !state.deadChannelLogged) {
|
|
7308
7311
|
state.deadChannelLogged = true;
|
|
7309
|
-
|
|
7312
|
+
log2(
|
|
7310
7313
|
`[mcp-presence-reaper] '${codeName}:${key}' continuously missing ${Math.round((nowMs - state.continuouslyMissingSince) / 6e4)}m (> ${Math.round(deadChannelMs / 6e4)}m) \u2014 genuinely dead, overriding storm-awareness so it can reach give-up/quarantine instead of churning (ENG-8062)`
|
|
7311
7314
|
);
|
|
7312
7315
|
}
|
|
@@ -7332,7 +7335,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7332
7335
|
state.gaveUp = true;
|
|
7333
7336
|
if (!state.gaveUpLogged) {
|
|
7334
7337
|
const cause = overAttemptsCap ? `${MAX_PRESENCE_RESTART_ATTEMPTS} consecutive failed restarts \u2014 declared but never recovers (likely orphaned config; see ENG-5279)` : `${restartsInWindow} restarts within ${Math.round(BACKOFF_WINDOW_MS / 6e4)}m \u2014 persistently flapping (crash-loop; ENG-6480)`;
|
|
7335
|
-
|
|
7338
|
+
log2(
|
|
7336
7339
|
`[mcp-presence-reaper] giving up on '${codeName}:${key}' after ${cause}`
|
|
7337
7340
|
);
|
|
7338
7341
|
state.gaveUpLogged = true;
|
|
@@ -7340,7 +7343,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7340
7343
|
try {
|
|
7341
7344
|
onGiveUp(codeName, key);
|
|
7342
7345
|
} catch (err) {
|
|
7343
|
-
|
|
7346
|
+
log2(
|
|
7344
7347
|
`[mcp-presence-reaper] onGiveUp callback threw for '${codeName}:${key}' (suppressed; reaper continues): ${err.message}`
|
|
7345
7348
|
);
|
|
7346
7349
|
}
|
|
@@ -7352,21 +7355,21 @@ function reapMissingMcpSessions(args) {
|
|
|
7352
7355
|
state.quarantineLogged = true;
|
|
7353
7356
|
if (quarantineMode === "enforce") {
|
|
7354
7357
|
quarantined.push(key);
|
|
7355
|
-
|
|
7358
|
+
log2(
|
|
7356
7359
|
`[mcp-presence-reaper] QUARANTINE '${codeName}:${key}' \u2014 optional channel dead past restart budget + ${quarantineDwellMs}ms dwell; dropping from provisioned set so the dead channel stops restarting the whole session (ENG-5932)`
|
|
7357
7360
|
);
|
|
7358
7361
|
if (onQuarantine) {
|
|
7359
7362
|
try {
|
|
7360
7363
|
onQuarantine(codeName, key);
|
|
7361
7364
|
} catch (err) {
|
|
7362
|
-
|
|
7365
|
+
log2(
|
|
7363
7366
|
`[mcp-presence-reaper] onQuarantine callback threw for '${codeName}:${key}' (suppressed; reaper continues): ${err.message}`
|
|
7364
7367
|
);
|
|
7365
7368
|
}
|
|
7366
7369
|
}
|
|
7367
7370
|
} else {
|
|
7368
7371
|
wouldQuarantine.push(key);
|
|
7369
|
-
|
|
7372
|
+
log2(
|
|
7370
7373
|
`[mcp-presence-reaper] SHADOW would-quarantine '${codeName}:${key}' \u2014 optional channel dead past restart budget + ${quarantineDwellMs}ms dwell; no action taken (ENG-5932 shadow mode)`
|
|
7371
7374
|
);
|
|
7372
7375
|
}
|
|
@@ -7388,7 +7391,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7388
7391
|
if (active.length === 0) {
|
|
7389
7392
|
const reason = backingOff.length > 0 ? "backoff" : "all-keys-over-cap";
|
|
7390
7393
|
if (backingOff.length > 0) {
|
|
7391
|
-
|
|
7394
|
+
log2(
|
|
7392
7395
|
`[mcp-presence-reaper] '${codeName}': holding off restart for [${backingOff.join(", ")}] \u2014 escalating backoff interval not yet elapsed (ENG-6480)${givenUp.length > 0 ? ` (given up: [${givenUp.join(", ")}])` : ""}`
|
|
7393
7396
|
);
|
|
7394
7397
|
}
|
|
@@ -7409,7 +7412,7 @@ function reapMissingMcpSessions(args) {
|
|
|
7409
7412
|
};
|
|
7410
7413
|
}
|
|
7411
7414
|
const givenUpSuffix = givenUp.length > 0 ? ` (skipping over-cap: [${givenUp.join(", ")}])` : "";
|
|
7412
|
-
|
|
7415
|
+
log2(
|
|
7413
7416
|
`[mcp-presence-reaper] '${codeName}': declared MCP(s) [${active.join(", ")}] have no live children \u2014 restarting session${givenUpSuffix}`
|
|
7414
7417
|
);
|
|
7415
7418
|
if (onRestart) {
|
|
@@ -7417,13 +7420,13 @@ function reapMissingMcpSessions(args) {
|
|
|
7417
7420
|
const maybePromise = onRestart(codeName, { activeKeys: active, givenUpKeys: givenUp });
|
|
7418
7421
|
if (maybePromise && typeof maybePromise.then === "function") {
|
|
7419
7422
|
void maybePromise.then(void 0, (err) => {
|
|
7420
|
-
|
|
7423
|
+
log2(
|
|
7421
7424
|
`[mcp-presence-reaper] onRestart callback rejected for '${codeName}' (suppressed; restart proceeds): ${err.message}`
|
|
7422
7425
|
);
|
|
7423
7426
|
});
|
|
7424
7427
|
}
|
|
7425
7428
|
} catch (err) {
|
|
7426
|
-
|
|
7429
|
+
log2(
|
|
7427
7430
|
`[mcp-presence-reaper] onRestart callback threw for '${codeName}' (suppressed; restart proceeds): ${err.message}`
|
|
7428
7431
|
);
|
|
7429
7432
|
}
|
|
@@ -7466,7 +7469,12 @@ var KNOWN_REASON_CLASS_MAP = {
|
|
|
7466
7469
|
// forced by the Record type, which is exactly why that shape was chosen over
|
|
7467
7470
|
// a Set literal (ENG-7577, CodeRabbit on #3861) - a new union member cannot
|
|
7468
7471
|
// be silently omitted from the rehydration allowlist.
|
|
7469
|
-
"self-healing": true
|
|
7472
|
+
"self-healing": true,
|
|
7473
|
+
// ENG-9138: the platform-scheduled class. Same Record-not-Set reasoning: the
|
|
7474
|
+
// compiler forces every new class into this allowlist, so a `trippedClass`
|
|
7475
|
+
// rehydrated from manager-state.json can never name a class this build does
|
|
7476
|
+
// not know about.
|
|
7477
|
+
scheduled: true
|
|
7470
7478
|
};
|
|
7471
7479
|
var KNOWN_REASON_CLASSES = new Set(
|
|
7472
7480
|
Object.keys(KNOWN_REASON_CLASS_MAP)
|
|
@@ -7507,6 +7515,12 @@ var SELF_HEALING_REASONS = /* @__PURE__ */ new Set([
|
|
|
7507
7515
|
function isSelfHealingReason(reason) {
|
|
7508
7516
|
return SELF_HEALING_REASONS.has(reason);
|
|
7509
7517
|
}
|
|
7518
|
+
var SCHEDULED_REASONS = /* @__PURE__ */ new Set([
|
|
7519
|
+
"day-rollover"
|
|
7520
|
+
]);
|
|
7521
|
+
function isScheduledRestartReason(reason) {
|
|
7522
|
+
return SCHEDULED_REASONS.has(reason);
|
|
7523
|
+
}
|
|
7510
7524
|
var OPERATOR_CONFIG_REASONS = /* @__PURE__ */ new Set([
|
|
7511
7525
|
"operator-integration-change"
|
|
7512
7526
|
]);
|
|
@@ -7520,6 +7534,7 @@ function restartReasonClass(reason) {
|
|
|
7520
7534
|
if (isCredentialRotationReason(reason)) return "credential-rotation";
|
|
7521
7535
|
if (isSelfHealingReason(reason)) return "self-healing";
|
|
7522
7536
|
if (isOperatorConfigReason(reason)) return "operator-config";
|
|
7537
|
+
if (isScheduledRestartReason(reason)) return "scheduled";
|
|
7523
7538
|
return isProvisioningReloadReason(reason) ? "provisioning" : "crash";
|
|
7524
7539
|
}
|
|
7525
7540
|
function countByClass(events) {
|
|
@@ -7528,12 +7543,14 @@ function countByClass(events) {
|
|
|
7528
7543
|
let credentialRotation = 0;
|
|
7529
7544
|
let selfHealing = 0;
|
|
7530
7545
|
let operatorConfig = 0;
|
|
7546
|
+
let scheduled = 0;
|
|
7531
7547
|
for (const e of events) {
|
|
7532
7548
|
const klass = restartReasonClass(e.reason);
|
|
7533
7549
|
if (klass === "provisioning") provisioning += 1;
|
|
7534
7550
|
else if (klass === "credential-rotation") credentialRotation += 1;
|
|
7535
7551
|
else if (klass === "self-healing") selfHealing += 1;
|
|
7536
7552
|
else if (klass === "operator-config") operatorConfig += 1;
|
|
7553
|
+
else if (klass === "scheduled") scheduled += 1;
|
|
7537
7554
|
else crash += 1;
|
|
7538
7555
|
}
|
|
7539
7556
|
return {
|
|
@@ -7541,7 +7558,8 @@ function countByClass(events) {
|
|
|
7541
7558
|
provisioning,
|
|
7542
7559
|
"credential-rotation": credentialRotation,
|
|
7543
7560
|
"self-healing": selfHealing,
|
|
7544
|
-
"operator-config": operatorConfig
|
|
7561
|
+
"operator-config": operatorConfig,
|
|
7562
|
+
scheduled
|
|
7545
7563
|
};
|
|
7546
7564
|
}
|
|
7547
7565
|
function maxProvisioningBucket(events) {
|
|
@@ -7571,6 +7589,8 @@ var DEFAULT_WINDOW_MS = 6e5;
|
|
|
7571
7589
|
var DEFAULT_PROVISIONING_MAX = RESTART_BREAKER_PROVISIONING_MAX;
|
|
7572
7590
|
var DEFAULT_PROVISIONING_WINDOW_MS = RESTART_BREAKER_PROVISIONING_WINDOW_MS;
|
|
7573
7591
|
var DEFAULT_OPERATOR_MAX = RESTART_BREAKER_OPERATOR_MAX;
|
|
7592
|
+
var DEFAULT_SCHEDULED_MAX = RESTART_BREAKER_SCHEDULED_MAX;
|
|
7593
|
+
var DEFAULT_SCHEDULED_WINDOW_MS = RESTART_BREAKER_SCHEDULED_WINDOW_MS;
|
|
7574
7594
|
function readEnvNumber(name, fallback) {
|
|
7575
7595
|
const raw = process.env[name];
|
|
7576
7596
|
if (!raw) return fallback;
|
|
@@ -7598,7 +7618,15 @@ var RestartBreaker = class {
|
|
|
7598
7618
|
* env var without the other cannot invert the two tallies.
|
|
7599
7619
|
*/
|
|
7600
7620
|
operatorMax;
|
|
7601
|
-
/**
|
|
7621
|
+
/**
|
|
7622
|
+
* ENG-9138: the scheduled class's LOOP bar. Readonly and deliberately NOT
|
|
7623
|
+
* floored against any other tally: it gates a REPORT, not a pause, so it
|
|
7624
|
+
* cannot invert anything the way operatorMax/provisioningMax can.
|
|
7625
|
+
*/
|
|
7626
|
+
scheduledMax;
|
|
7627
|
+
/** ENG-9138: sliding window for the scheduled tally. */
|
|
7628
|
+
scheduledWindowMs;
|
|
7629
|
+
/** Longest window any tally needs — how long the events log must retain. */
|
|
7602
7630
|
retentionMs;
|
|
7603
7631
|
now;
|
|
7604
7632
|
/** ENG-7891 slice 5b: code_name → durable runtime key (agent_id when id-keyed). Identity on the legacy fleet. */
|
|
@@ -7624,6 +7652,8 @@ var RestartBreaker = class {
|
|
|
7624
7652
|
this.provisioningMax = opts.provisioningMax ?? readEnvNumber("AGT_RESTART_BREAKER_PROVISIONING_MAX", DEFAULT_PROVISIONING_MAX);
|
|
7625
7653
|
this.provisioningWindowMs = opts.provisioningWindowMs ?? readEnvNumber("AGT_RESTART_BREAKER_PROVISIONING_WINDOW_MS", DEFAULT_PROVISIONING_WINDOW_MS);
|
|
7626
7654
|
this.operatorMax = opts.operatorMax ?? readEnvNumber("AGT_RESTART_BREAKER_OPERATOR_MAX", DEFAULT_OPERATOR_MAX);
|
|
7655
|
+
this.scheduledMax = opts.scheduledMax ?? readEnvNumber("AGT_RESTART_BREAKER_SCHEDULED_MAX", DEFAULT_SCHEDULED_MAX);
|
|
7656
|
+
this.scheduledWindowMs = opts.scheduledWindowMs ?? readEnvNumber("AGT_RESTART_BREAKER_SCHEDULED_WINDOW_MS", DEFAULT_SCHEDULED_WINDOW_MS);
|
|
7627
7657
|
this.now = opts.now ?? Date.now;
|
|
7628
7658
|
this.runtimeKey = opts.runtimeKey ?? ((codeName) => codeName);
|
|
7629
7659
|
this.agentCreatedAt = opts.agentCreatedAt ?? (() => void 0);
|
|
@@ -7665,7 +7695,7 @@ var RestartBreaker = class {
|
|
|
7665
7695
|
if (this.newAgentGraceCeiling < minimumGraceCeiling) {
|
|
7666
7696
|
this.newAgentGraceCeiling = minimumGraceCeiling;
|
|
7667
7697
|
}
|
|
7668
|
-
this.retentionMs = Math.max(this.windowMs, this.provisioningWindowMs);
|
|
7698
|
+
this.retentionMs = Math.max(this.windowMs, this.provisioningWindowMs, this.scheduledWindowMs);
|
|
7669
7699
|
}
|
|
7670
7700
|
/**
|
|
7671
7701
|
* ENG-8215: the clamp record, if the configured provisioning max had to be
|
|
@@ -7754,14 +7784,23 @@ var RestartBreaker = class {
|
|
|
7754
7784
|
const operatorEvents = prior.filter(
|
|
7755
7785
|
(e) => e.at >= at - this.provisioningWindowMs && isOperatorConfigReason(e.reason)
|
|
7756
7786
|
);
|
|
7787
|
+
const scheduledEvents = prior.filter(
|
|
7788
|
+
(e) => e.at >= at - this.scheduledWindowMs && isScheduledRestartReason(e.reason)
|
|
7789
|
+
);
|
|
7757
7790
|
const windowCount = prior.filter((e) => e.at >= at - this.windowMs).length;
|
|
7758
7791
|
const classCounts = {
|
|
7759
7792
|
crash: crashCount,
|
|
7760
7793
|
provisioning: provEvents.length,
|
|
7761
7794
|
"credential-rotation": credRotCount,
|
|
7762
7795
|
"self-healing": selfHealCount,
|
|
7763
|
-
"operator-config": operatorEvents.length
|
|
7796
|
+
"operator-config": operatorEvents.length,
|
|
7797
|
+
scheduled: scheduledEvents.length
|
|
7764
7798
|
};
|
|
7799
|
+
const scheduledLoop = scheduledEvents.length > this.scheduledMax ? {
|
|
7800
|
+
count: scheduledEvents.length,
|
|
7801
|
+
windowMs: this.scheduledWindowMs,
|
|
7802
|
+
reason: scheduledEvents[scheduledEvents.length - 1].reason
|
|
7803
|
+
} : void 0;
|
|
7765
7804
|
const provBucket = maxProvisioningBucket(provEvents);
|
|
7766
7805
|
const operatorBucket = maxBucketWhere(operatorEvents, isOperatorConfigReason);
|
|
7767
7806
|
const createdAt = this.newAgentGraceMs > 0 ? this.agentCreatedAt(codeName) : void 0;
|
|
@@ -7821,7 +7860,9 @@ var RestartBreaker = class {
|
|
|
7821
7860
|
trippedClass,
|
|
7822
7861
|
maxProvisioningBucket: provBucket.count,
|
|
7823
7862
|
maxProvisioningBucketKey: provBucket.key,
|
|
7824
|
-
...graceCeilingExceeded ? { newAgentGraceCeilingExceeded: true } : {}
|
|
7863
|
+
...graceCeilingExceeded ? { newAgentGraceCeilingExceeded: true } : {},
|
|
7864
|
+
// ENG-9138: a co-occurring rollover loop still reports on a real trip.
|
|
7865
|
+
...scheduledLoop ? { scheduledLoop } : {}
|
|
7825
7866
|
};
|
|
7826
7867
|
}
|
|
7827
7868
|
const suppressedOperator = operatorBucket.count > this.operatorMax;
|
|
@@ -7833,6 +7874,7 @@ var RestartBreaker = class {
|
|
|
7833
7874
|
classCounts,
|
|
7834
7875
|
maxProvisioningBucket: provBucket.count,
|
|
7835
7876
|
maxProvisioningBucketKey: provBucket.key,
|
|
7877
|
+
...scheduledLoop ? { scheduledLoop } : {},
|
|
7836
7878
|
...newAgentGraceActive ? {
|
|
7837
7879
|
newAgentGraceSuppressedTrip: wouldHaveTripped,
|
|
7838
7880
|
...newAgentGraceExpiresAt !== void 0 ? { newAgentGraceExpiresAt } : {},
|
|
@@ -8820,6 +8862,63 @@ function provision(input, frameworkId = "claude-code") {
|
|
|
8820
8862
|
};
|
|
8821
8863
|
}
|
|
8822
8864
|
|
|
8865
|
+
// src/lib/startup-telemetry.ts
|
|
8866
|
+
var SLOW_STARTUP_WARN_MS = 6e4;
|
|
8867
|
+
function shouldWarnSlowStartup(elapsedMs, opts = {}) {
|
|
8868
|
+
if (!Number.isFinite(elapsedMs) || elapsedMs < 0) return false;
|
|
8869
|
+
const threshold = opts.thresholdMs ?? SLOW_STARTUP_WARN_MS;
|
|
8870
|
+
if (!Number.isFinite(threshold) || threshold < 0) return false;
|
|
8871
|
+
return elapsedMs >= threshold;
|
|
8872
|
+
}
|
|
8873
|
+
function formatStartupElapsed(elapsedMs) {
|
|
8874
|
+
if (!Number.isFinite(elapsedMs) || elapsedMs < 0) return "unknown";
|
|
8875
|
+
const seconds = elapsedMs / 1e3;
|
|
8876
|
+
if (seconds < 60) return `${seconds.toFixed(1)}s`;
|
|
8877
|
+
return `${seconds.toFixed(1)}s (${(seconds / 60).toFixed(1)} min)`;
|
|
8878
|
+
}
|
|
8879
|
+
function describeStartupCompletion(elapsedMs, opts = {}) {
|
|
8880
|
+
const elapsed = formatStartupElapsed(elapsedMs);
|
|
8881
|
+
if (!shouldWarnSlowStartup(elapsedMs, opts)) {
|
|
8882
|
+
return { warn: false, message: `[startup] ready in ${elapsed}` };
|
|
8883
|
+
}
|
|
8884
|
+
const threshold = opts.thresholdMs ?? SLOW_STARTUP_WARN_MS;
|
|
8885
|
+
return {
|
|
8886
|
+
warn: true,
|
|
8887
|
+
message: `[startup] SLOW BOOT \u2014 ready in ${elapsed}, over the ${formatStartupElapsed(threshold)} threshold. MCP bundles are deployed during startup, so agents spawning in this window can come up with no MCP tools (ENG-9129). Check for a build/install running on the host.`
|
|
8888
|
+
};
|
|
8889
|
+
}
|
|
8890
|
+
var SLOW_MODULE_LOAD_WARN_MS = 1e4;
|
|
8891
|
+
function describeWorkerModuleLoad(elapsedMs, opts = {}) {
|
|
8892
|
+
const elapsed = formatStartupElapsed(elapsedMs);
|
|
8893
|
+
const threshold = opts.thresholdMs ?? SLOW_MODULE_LOAD_WARN_MS;
|
|
8894
|
+
if (!shouldWarnSlowStartup(elapsedMs, { thresholdMs: threshold })) {
|
|
8895
|
+
return { warn: false, message: `[startup] worker module loaded in ${elapsed}` };
|
|
8896
|
+
}
|
|
8897
|
+
return {
|
|
8898
|
+
warn: true,
|
|
8899
|
+
message: `[startup] SLOW MODULE LOAD \u2014 worker module took ${elapsed} to import, over the ${formatStartupElapsed(threshold)} threshold. The manager had already written its pidfile and reported itself started, so it looked healthy for this whole window while doing nothing \u2014 and MCP bundles are deployed after this point, so agents spawning meanwhile come up with no MCP tools (ENG-9129). Check for a build, install or filesystem rebuild running on the host.`
|
|
8900
|
+
};
|
|
8901
|
+
}
|
|
8902
|
+
function describeRejection(err) {
|
|
8903
|
+
if (err instanceof Error) return err.stack ?? err.message;
|
|
8904
|
+
if (typeof err === "object" && err !== null) {
|
|
8905
|
+
try {
|
|
8906
|
+
const json = JSON.stringify(err);
|
|
8907
|
+
if (json && json !== "{}") return json;
|
|
8908
|
+
} catch {
|
|
8909
|
+
}
|
|
8910
|
+
}
|
|
8911
|
+
try {
|
|
8912
|
+
return String(err);
|
|
8913
|
+
} catch {
|
|
8914
|
+
return `<unprintable ${typeof err} rejection>`;
|
|
8915
|
+
}
|
|
8916
|
+
}
|
|
8917
|
+
function describeWorkerModuleFailure(err) {
|
|
8918
|
+
const detail = describeRejection(err);
|
|
8919
|
+
return `[startup] FATAL \u2014 the manager worker module failed to load, so this process will never poll. The pidfile it already wrote would otherwise make it look like a healthy manager forever (ENG-9129). Exiting so the supervisor can react. Cause: ${detail}`;
|
|
8920
|
+
}
|
|
8921
|
+
|
|
8823
8922
|
// src/lib/self-update-pin.ts
|
|
8824
8923
|
function isValidPinVersion(v) {
|
|
8825
8924
|
return PIN_VERSION_RE.test(v);
|
|
@@ -8905,15 +9004,23 @@ function findOtherManagerPids(pgrepImpl = defaultPgrep, selfPid = process.pid) {
|
|
|
8905
9004
|
let out;
|
|
8906
9005
|
try {
|
|
8907
9006
|
out = pgrepImpl();
|
|
8908
|
-
} catch {
|
|
9007
|
+
} catch (err) {
|
|
9008
|
+
const signal = err?.signal;
|
|
9009
|
+
if (signal) {
|
|
9010
|
+
log(
|
|
9011
|
+
`[startup] duplicate-manager scan timed out after ${PGREP_SCAN_TIMEOUT_MS}ms (killed by ${signal}) \u2014 proceeding without it, since the pidfile check is the primary guard. A process-table read this slow means the host is heavily loaded, which is also when a boot is most likely to stall (ENG-9129).`
|
|
9012
|
+
);
|
|
9013
|
+
}
|
|
8909
9014
|
return [];
|
|
8910
9015
|
}
|
|
8911
9016
|
return out.split("\n").map((line) => parseInt(line.trim(), 10)).filter((pid) => !isNaN(pid) && pid !== selfPid);
|
|
8912
9017
|
}
|
|
9018
|
+
var PGREP_SCAN_TIMEOUT_MS = 1e4;
|
|
8913
9019
|
function defaultPgrep() {
|
|
8914
9020
|
return execFileSync3("pgrep", ["-f", "agt manager start"], {
|
|
8915
9021
|
encoding: "utf-8",
|
|
8916
|
-
stdio: ["ignore", "pipe", "ignore"]
|
|
9022
|
+
stdio: ["ignore", "pipe", "ignore"],
|
|
9023
|
+
timeout: PGREP_SCAN_TIMEOUT_MS
|
|
8917
9024
|
});
|
|
8918
9025
|
}
|
|
8919
9026
|
function readStateFile(configDir) {
|
|
@@ -8989,11 +9096,18 @@ function startWatchdog(opts) {
|
|
|
8989
9096
|
);
|
|
8990
9097
|
}
|
|
8991
9098
|
writePidFile(configDir, process.pid);
|
|
9099
|
+
const moduleLoadStartedAt = process.uptime() * 1e3;
|
|
9100
|
+
log("[startup] loading worker module \u2014 nothing polls, logs or deploys MCP bundles until this resolves");
|
|
8992
9101
|
void import("./lib/manager-worker.js").then(({ startManager }) => {
|
|
9102
|
+
const { message } = describeWorkerModuleLoad(process.uptime() * 1e3 - moduleLoadStartedAt);
|
|
9103
|
+
log(message);
|
|
8993
9104
|
startManager({
|
|
8994
9105
|
intervalMs: opts.intervalMs,
|
|
8995
9106
|
configDir
|
|
8996
9107
|
});
|
|
9108
|
+
}).catch((err) => {
|
|
9109
|
+
log(describeWorkerModuleFailure(err));
|
|
9110
|
+
process.exit(1);
|
|
8997
9111
|
});
|
|
8998
9112
|
process.on("exit", () => {
|
|
8999
9113
|
removePidFile(configDir);
|
|
@@ -9682,6 +9796,7 @@ export {
|
|
|
9682
9796
|
buildConnectivityProbeDeps,
|
|
9683
9797
|
gatherSessionToolBindProbe,
|
|
9684
9798
|
provision,
|
|
9799
|
+
describeStartupCompletion,
|
|
9685
9800
|
executeConnectivityProbe,
|
|
9686
9801
|
isValidPinVersion,
|
|
9687
9802
|
resolveEffectivePinRaw,
|
|
@@ -9699,4 +9814,4 @@ export {
|
|
|
9699
9814
|
managerInstallSystemUnitCommand,
|
|
9700
9815
|
managerUninstallSystemUnitCommand
|
|
9701
9816
|
};
|
|
9702
|
-
//# sourceMappingURL=chunk-
|
|
9817
|
+
//# sourceMappingURL=chunk-LCKKFDCR.js.map
|