@integrity-labs/agt-cli 0.28.461 → 0.28.462
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
CHANGED
|
@@ -40,7 +40,7 @@ import {
|
|
|
40
40
|
success,
|
|
41
41
|
table,
|
|
42
42
|
warn
|
|
43
|
-
} from "../chunk-
|
|
43
|
+
} from "../chunk-UNDFX52P.js";
|
|
44
44
|
import {
|
|
45
45
|
AnchorSessionClient,
|
|
46
46
|
CHANNEL_REGISTRY,
|
|
@@ -4830,7 +4830,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4830
4830
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4831
4831
|
import chalk18 from "chalk";
|
|
4832
4832
|
import ora16 from "ora";
|
|
4833
|
-
var cliVersion = true ? "0.28.
|
|
4833
|
+
var cliVersion = true ? "0.28.462" : "dev";
|
|
4834
4834
|
async function fetchLatestVersion() {
|
|
4835
4835
|
const host2 = getHost();
|
|
4836
4836
|
if (!host2) return null;
|
|
@@ -6002,7 +6002,7 @@ function handleError(err) {
|
|
|
6002
6002
|
}
|
|
6003
6003
|
|
|
6004
6004
|
// src/bin/agt.ts
|
|
6005
|
-
var cliVersion2 = true ? "0.28.
|
|
6005
|
+
var cliVersion2 = true ? "0.28.462" : "dev";
|
|
6006
6006
|
var program = new Command();
|
|
6007
6007
|
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");
|
|
6008
6008
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -4911,7 +4911,7 @@ function requireHost() {
|
|
|
4911
4911
|
}
|
|
4912
4912
|
|
|
4913
4913
|
// src/lib/api-client.ts
|
|
4914
|
-
var agtCliVersion = true ? "0.28.
|
|
4914
|
+
var agtCliVersion = true ? "0.28.462" : "dev";
|
|
4915
4915
|
var lastConfigHash = null;
|
|
4916
4916
|
function setConfigHash(hash) {
|
|
4917
4917
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -5401,13 +5401,24 @@ function recordStaleRotation(codeName, serverKeys, now = Date.now) {
|
|
|
5401
5401
|
rotationTimestamps.set(rotationKey(codeName, key), ts);
|
|
5402
5402
|
}
|
|
5403
5403
|
}
|
|
5404
|
-
|
|
5404
|
+
var ROTATION_TRACKING_RETENTION_MS = 15 * 60 * 1e3;
|
|
5405
|
+
function classifyRotation(codeName, serverKey, graceMs, now = Date.now, retentionMs = ROTATION_TRACKING_RETENTION_MS) {
|
|
5405
5406
|
const k = rotationKey(codeName, serverKey);
|
|
5406
5407
|
const ts = rotationTimestamps.get(k);
|
|
5407
|
-
if (ts === void 0) return
|
|
5408
|
-
|
|
5408
|
+
if (ts === void 0) return "none";
|
|
5409
|
+
const age = now() - ts;
|
|
5410
|
+
if (age < graceMs) return "within-grace";
|
|
5411
|
+
if (age < retentionMs) return "expired";
|
|
5409
5412
|
rotationTimestamps.delete(k);
|
|
5410
|
-
return
|
|
5413
|
+
return "none";
|
|
5414
|
+
}
|
|
5415
|
+
function getRotationRecordedAt(codeName, serverKey) {
|
|
5416
|
+
return rotationTimestamps.get(rotationKey(codeName, serverKey));
|
|
5417
|
+
}
|
|
5418
|
+
function clearStaleRotation(codeName, serverKeys) {
|
|
5419
|
+
for (const key of serverKeys) {
|
|
5420
|
+
rotationTimestamps.delete(rotationKey(codeName, key));
|
|
5421
|
+
}
|
|
5411
5422
|
}
|
|
5412
5423
|
function parseEnvIntegrationsEntries(content) {
|
|
5413
5424
|
const entries = /* @__PURE__ */ new Map();
|
|
@@ -5706,6 +5717,9 @@ var BACKOFF_GIVE_UP_RESTARTS = 2 * MAX_PRESENCE_RESTART_ATTEMPTS;
|
|
|
5706
5717
|
var BACKOFF_STABLE_RESET_MS = 5 * 6e4;
|
|
5707
5718
|
var DEAD_CHANNEL_MS = 15 * 6e4;
|
|
5708
5719
|
var presenceReaperState = /* @__PURE__ */ new Map();
|
|
5720
|
+
var MAX_ROTATION_PROMPT_PROBES = 3;
|
|
5721
|
+
var ROTATION_PROMPT_PROBE_INTERVAL_MS = 3e4;
|
|
5722
|
+
var rotationStallState = /* @__PURE__ */ new Map();
|
|
5709
5723
|
function stateKey(codeName, serverKey) {
|
|
5710
5724
|
return `${codeName}\0${serverKey}`;
|
|
5711
5725
|
}
|
|
@@ -5718,6 +5732,7 @@ function clearPresenceReaperState(codeName) {
|
|
|
5718
5732
|
function clearPresenceReaperStateForKeys(codeName, keys) {
|
|
5719
5733
|
for (const key of keys) {
|
|
5720
5734
|
presenceReaperState.delete(stateKey(codeName, key));
|
|
5735
|
+
rotationStallState.delete(stateKey(codeName, key));
|
|
5721
5736
|
}
|
|
5722
5737
|
}
|
|
5723
5738
|
function givenUpMcpServerKeys(codeName) {
|
|
@@ -5763,6 +5778,14 @@ function reapMissingMcpSessions(args) {
|
|
|
5763
5778
|
rotationGraceMs = DEFAULT_ROTATION_GRACE_MS,
|
|
5764
5779
|
onGiveUp,
|
|
5765
5780
|
onRestart,
|
|
5781
|
+
// ENG-8225: unwired callbacks make the prompt-probe path a strict no-op —
|
|
5782
|
+
// `onRotationRespawnStalled` absent means "not armed", which falls through to
|
|
5783
|
+
// the pre-ENG-8225 restart. Legacy callers and tests are unchanged.
|
|
5784
|
+
onRotationRespawnStalled,
|
|
5785
|
+
onRotationRespawnGaveUp,
|
|
5786
|
+
onRotationRespawnOutcome,
|
|
5787
|
+
maxRotationPromptProbes = MAX_ROTATION_PROMPT_PROBES,
|
|
5788
|
+
rotationPromptProbeIntervalMs = ROTATION_PROMPT_PROBE_INTERVAL_MS,
|
|
5766
5789
|
// ENG-5932: defaults make quarantine a strict no-op (classify everything
|
|
5767
5790
|
// essential, mode off) so legacy callers/tests are unaffected.
|
|
5768
5791
|
classifyKey = () => "essential",
|
|
@@ -5807,19 +5830,112 @@ function reapMissingMcpSessions(args) {
|
|
|
5807
5830
|
const rows = parsePsRows(psOutput);
|
|
5808
5831
|
const missingRaw = findMissingMcpServers({ rows, codeName, mcpJson, inContainer: isolated });
|
|
5809
5832
|
const rotationGraced = [];
|
|
5833
|
+
const rotationProbeArmed = [];
|
|
5834
|
+
const rotationProbeWaiting = [];
|
|
5835
|
+
const rotationProbeExhausted = [];
|
|
5836
|
+
const rotationRespawnOutcomes = {};
|
|
5837
|
+
const recordRotationOutcome = (key, outcome) => {
|
|
5838
|
+
rotationRespawnOutcomes[key] = outcome;
|
|
5839
|
+
if (!onRotationRespawnOutcome) return;
|
|
5840
|
+
try {
|
|
5841
|
+
onRotationRespawnOutcome(codeName, key, outcome);
|
|
5842
|
+
} catch (err) {
|
|
5843
|
+
log(
|
|
5844
|
+
`[mcp-presence-reaper] onRotationRespawnOutcome callback threw for '${codeName}:${key}' (suppressed; reaper continues): ${err.message}`
|
|
5845
|
+
);
|
|
5846
|
+
}
|
|
5847
|
+
};
|
|
5810
5848
|
const missing = [];
|
|
5811
5849
|
for (const key of missingRaw) {
|
|
5812
|
-
|
|
5850
|
+
const rotation = classifyRotation(codeName, key, rotationGraceMs, now);
|
|
5851
|
+
if (rotation === "within-grace") {
|
|
5813
5852
|
rotationGraced.push(key);
|
|
5814
|
-
|
|
5853
|
+
continue;
|
|
5854
|
+
}
|
|
5855
|
+
if (rotation === "none") {
|
|
5856
|
+
rotationStallState.delete(stateKey(codeName, key));
|
|
5857
|
+
missing.push(key);
|
|
5858
|
+
continue;
|
|
5859
|
+
}
|
|
5860
|
+
const sk = stateKey(codeName, key);
|
|
5861
|
+
const rotationRecordedAt = getRotationRecordedAt(codeName, key) ?? now();
|
|
5862
|
+
const priorStall = rotationStallState.get(sk);
|
|
5863
|
+
const stall = priorStall && priorStall.rotationRecordedAt === rotationRecordedAt ? priorStall : {
|
|
5864
|
+
rotationRecordedAt,
|
|
5865
|
+
probeAttempts: 0,
|
|
5866
|
+
lastProbeAt: null,
|
|
5867
|
+
escalated: false
|
|
5868
|
+
};
|
|
5869
|
+
if (priorStall && priorStall !== stall) {
|
|
5870
|
+
log(
|
|
5871
|
+
`[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)`
|
|
5872
|
+
);
|
|
5873
|
+
}
|
|
5874
|
+
rotationStallState.set(sk, stall);
|
|
5875
|
+
if (stall.escalated) {
|
|
5815
5876
|
missing.push(key);
|
|
5877
|
+
continue;
|
|
5816
5878
|
}
|
|
5879
|
+
const spacingElapsed = stall.lastProbeAt === null || now() - stall.lastProbeAt >= rotationPromptProbeIntervalMs;
|
|
5880
|
+
if (!spacingElapsed) {
|
|
5881
|
+
rotationProbeWaiting.push(key);
|
|
5882
|
+
continue;
|
|
5883
|
+
}
|
|
5884
|
+
if (stall.probeAttempts >= maxRotationPromptProbes) {
|
|
5885
|
+
stall.escalated = true;
|
|
5886
|
+
rotationProbeExhausted.push(key);
|
|
5887
|
+
recordRotationOutcome(key, "never-respawned");
|
|
5888
|
+
log(
|
|
5889
|
+
`[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)`
|
|
5890
|
+
);
|
|
5891
|
+
if (onRotationRespawnGaveUp) {
|
|
5892
|
+
try {
|
|
5893
|
+
onRotationRespawnGaveUp(codeName, key, { attempts: stall.probeAttempts });
|
|
5894
|
+
} catch (err) {
|
|
5895
|
+
log(
|
|
5896
|
+
`[mcp-presence-reaper] onRotationRespawnGaveUp callback threw for '${codeName}:${key}' (suppressed; reaper continues): ${err.message}`
|
|
5897
|
+
);
|
|
5898
|
+
}
|
|
5899
|
+
}
|
|
5900
|
+
missing.push(key);
|
|
5901
|
+
continue;
|
|
5902
|
+
}
|
|
5903
|
+
const attempt = stall.probeAttempts + 1;
|
|
5904
|
+
let armed = false;
|
|
5905
|
+
if (onRotationRespawnStalled) {
|
|
5906
|
+
try {
|
|
5907
|
+
armed = onRotationRespawnStalled(codeName, key, {
|
|
5908
|
+
attempt,
|
|
5909
|
+
maxAttempts: maxRotationPromptProbes
|
|
5910
|
+
});
|
|
5911
|
+
} catch (err) {
|
|
5912
|
+
log(
|
|
5913
|
+
`[mcp-presence-reaper] onRotationRespawnStalled callback threw for '${codeName}:${key}' (suppressed; falling back to the pre-ENG-8225 restart path): ${err.message}`
|
|
5914
|
+
);
|
|
5915
|
+
armed = false;
|
|
5916
|
+
}
|
|
5917
|
+
}
|
|
5918
|
+
if (!armed) {
|
|
5919
|
+
missing.push(key);
|
|
5920
|
+
continue;
|
|
5921
|
+
}
|
|
5922
|
+
stall.probeAttempts = attempt;
|
|
5923
|
+
stall.lastProbeAt = now();
|
|
5924
|
+
rotationProbeArmed.push(key);
|
|
5925
|
+
log(
|
|
5926
|
+
`[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)`
|
|
5927
|
+
);
|
|
5817
5928
|
}
|
|
5818
5929
|
if (rotationGraced.length > 0) {
|
|
5819
5930
|
log(
|
|
5820
5931
|
`[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)`
|
|
5821
5932
|
);
|
|
5822
5933
|
}
|
|
5934
|
+
if (rotationProbeWaiting.length > 0) {
|
|
5935
|
+
log(
|
|
5936
|
+
`[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)`
|
|
5937
|
+
);
|
|
5938
|
+
}
|
|
5823
5939
|
const declared = mcpJson.mcpServers ?? {};
|
|
5824
5940
|
const liveKeys = /* @__PURE__ */ new Set();
|
|
5825
5941
|
for (const key of Object.keys(declared)) {
|
|
@@ -5827,6 +5943,24 @@ function reapMissingMcpSessions(args) {
|
|
|
5827
5943
|
if (typeof entry?.command !== "string") continue;
|
|
5828
5944
|
if (!missingRaw.includes(key)) liveKeys.add(key);
|
|
5829
5945
|
}
|
|
5946
|
+
for (const key of liveKeys) {
|
|
5947
|
+
const sk = stateKey(codeName, key);
|
|
5948
|
+
if (classifyRotation(codeName, key, rotationGraceMs, now) === "none") {
|
|
5949
|
+
rotationStallState.delete(sk);
|
|
5950
|
+
continue;
|
|
5951
|
+
}
|
|
5952
|
+
const stall = rotationStallState.get(sk);
|
|
5953
|
+
const viaProbe = (stall?.probeAttempts ?? 0) > 0;
|
|
5954
|
+
recordRotationOutcome(
|
|
5955
|
+
key,
|
|
5956
|
+
viaProbe ? "respawned-after-prompt-probe" : "respawned-on-tool-call"
|
|
5957
|
+
);
|
|
5958
|
+
log(
|
|
5959
|
+
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)`
|
|
5960
|
+
);
|
|
5961
|
+
clearStaleRotation(codeName, [key]);
|
|
5962
|
+
rotationStallState.delete(sk);
|
|
5963
|
+
}
|
|
5830
5964
|
for (const key of liveKeys) {
|
|
5831
5965
|
const state = presenceReaperState.get(stateKey(codeName, key));
|
|
5832
5966
|
if (state) {
|
|
@@ -5850,7 +5984,11 @@ function reapMissingMcpSessions(args) {
|
|
|
5850
5984
|
missing,
|
|
5851
5985
|
restarted: false,
|
|
5852
5986
|
reason: "healthy",
|
|
5853
|
-
rotationGraced: rotationGraced.length > 0 ? rotationGraced : void 0
|
|
5987
|
+
rotationGraced: rotationGraced.length > 0 ? rotationGraced : void 0,
|
|
5988
|
+
rotationProbeArmed: rotationProbeArmed.length > 0 ? rotationProbeArmed : void 0,
|
|
5989
|
+
rotationProbeWaiting: rotationProbeWaiting.length > 0 ? rotationProbeWaiting : void 0,
|
|
5990
|
+
rotationProbeExhausted: rotationProbeExhausted.length > 0 ? rotationProbeExhausted : void 0,
|
|
5991
|
+
rotationRespawnOutcomes: Object.keys(rotationRespawnOutcomes).length > 0 ? rotationRespawnOutcomes : void 0
|
|
5854
5992
|
};
|
|
5855
5993
|
}
|
|
5856
5994
|
const nowMs = now();
|
|
@@ -5978,6 +6116,10 @@ function reapMissingMcpSessions(args) {
|
|
|
5978
6116
|
givenUp,
|
|
5979
6117
|
backingOff: backingOff.length > 0 ? backingOff : void 0,
|
|
5980
6118
|
rotationGraced: rotationGraced.length > 0 ? rotationGraced : void 0,
|
|
6119
|
+
rotationProbeArmed: rotationProbeArmed.length > 0 ? rotationProbeArmed : void 0,
|
|
6120
|
+
rotationProbeWaiting: rotationProbeWaiting.length > 0 ? rotationProbeWaiting : void 0,
|
|
6121
|
+
rotationProbeExhausted: rotationProbeExhausted.length > 0 ? rotationProbeExhausted : void 0,
|
|
6122
|
+
rotationRespawnOutcomes: Object.keys(rotationRespawnOutcomes).length > 0 ? rotationRespawnOutcomes : void 0,
|
|
5981
6123
|
quarantined: quarantined.length > 0 ? quarantined : void 0,
|
|
5982
6124
|
wouldQuarantine: wouldQuarantine.length > 0 ? wouldQuarantine : void 0,
|
|
5983
6125
|
genuinelyDead: genuinelyDead.length > 0 ? genuinelyDead : void 0
|
|
@@ -6015,6 +6157,10 @@ function reapMissingMcpSessions(args) {
|
|
|
6015
6157
|
givenUp: givenUp.length > 0 ? givenUp : void 0,
|
|
6016
6158
|
backingOff: backingOff.length > 0 ? backingOff : void 0,
|
|
6017
6159
|
rotationGraced: rotationGraced.length > 0 ? rotationGraced : void 0,
|
|
6160
|
+
rotationProbeArmed: rotationProbeArmed.length > 0 ? rotationProbeArmed : void 0,
|
|
6161
|
+
rotationProbeWaiting: rotationProbeWaiting.length > 0 ? rotationProbeWaiting : void 0,
|
|
6162
|
+
rotationProbeExhausted: rotationProbeExhausted.length > 0 ? rotationProbeExhausted : void 0,
|
|
6163
|
+
rotationRespawnOutcomes: Object.keys(rotationRespawnOutcomes).length > 0 ? rotationRespawnOutcomes : void 0,
|
|
6018
6164
|
quarantined: quarantined.length > 0 ? quarantined : void 0,
|
|
6019
6165
|
wouldQuarantine: wouldQuarantine.length > 0 ? wouldQuarantine : void 0,
|
|
6020
6166
|
genuinelyDead: genuinelyDead.length > 0 ? genuinelyDead : void 0
|
|
@@ -7449,4 +7595,4 @@ export {
|
|
|
7449
7595
|
managerInstallSystemUnitCommand,
|
|
7450
7596
|
managerUninstallSystemUnitCommand
|
|
7451
7597
|
};
|
|
7452
|
-
//# sourceMappingURL=chunk-
|
|
7598
|
+
//# sourceMappingURL=chunk-UNDFX52P.js.map
|