@integrity-labs/agt-cli 0.28.450 → 0.28.452
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-WOZINHUT.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.452" : "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.452" : "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) => {
|
|
@@ -4910,7 +4910,7 @@ function requireHost() {
|
|
|
4910
4910
|
}
|
|
4911
4911
|
|
|
4912
4912
|
// src/lib/api-client.ts
|
|
4913
|
-
var agtCliVersion = true ? "0.28.
|
|
4913
|
+
var agtCliVersion = true ? "0.28.452" : "dev";
|
|
4914
4914
|
var lastConfigHash = null;
|
|
4915
4915
|
function setConfigHash(hash) {
|
|
4916
4916
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -7411,4 +7411,4 @@ export {
|
|
|
7411
7411
|
managerInstallSystemUnitCommand,
|
|
7412
7412
|
managerUninstallSystemUnitCommand
|
|
7413
7413
|
};
|
|
7414
|
-
//# sourceMappingURL=chunk-
|
|
7414
|
+
//# sourceMappingURL=chunk-WOZINHUT.js.map
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
resolveEffectivePinRaw,
|
|
43
43
|
safeWriteJsonAtomic,
|
|
44
44
|
setConfigHash
|
|
45
|
-
} from "../chunk-
|
|
45
|
+
} from "../chunk-WOZINHUT.js";
|
|
46
46
|
import {
|
|
47
47
|
getProjectDir as getProjectDir2,
|
|
48
48
|
getReadyTasks,
|
|
@@ -841,6 +841,14 @@ function logClaudeMdCeilingTransition(codeName, report, log2) {
|
|
|
841
841
|
function reaperRestartBreakerReason(activeKeys) {
|
|
842
842
|
return activeKeys.length >= 2 ? "mcp-presence-reaper" : void 0;
|
|
843
843
|
}
|
|
844
|
+
var KNOWN_REASON_CLASS_MAP = {
|
|
845
|
+
crash: true,
|
|
846
|
+
provisioning: true,
|
|
847
|
+
"credential-rotation": true
|
|
848
|
+
};
|
|
849
|
+
var KNOWN_REASON_CLASSES = new Set(
|
|
850
|
+
Object.keys(KNOWN_REASON_CLASS_MAP)
|
|
851
|
+
);
|
|
844
852
|
var PROVISIONING_RELOAD_REASONS = /* @__PURE__ */ new Set([
|
|
845
853
|
"hot-reload-mcp",
|
|
846
854
|
"managed-mcp-churn",
|
|
@@ -897,6 +905,11 @@ function maxProvisioningBucket(events) {
|
|
|
897
905
|
}
|
|
898
906
|
return best;
|
|
899
907
|
}
|
|
908
|
+
function tripClass(trip) {
|
|
909
|
+
if (trip.trippedClass) return trip.trippedClass;
|
|
910
|
+
if (!Array.isArray(trip.eventsAtTrip) || trip.eventsAtTrip.length === 0) return "crash";
|
|
911
|
+
return trip.eventsAtTrip.every((e) => isProvisioningReloadReason(e.reason)) ? "provisioning" : "crash";
|
|
912
|
+
}
|
|
900
913
|
var DEFAULT_MAX = 2;
|
|
901
914
|
var DEFAULT_WINDOW_MS = 6e5;
|
|
902
915
|
var DEFAULT_PROVISIONING_MAX = 5;
|
|
@@ -1007,7 +1020,10 @@ var RestartBreaker = class {
|
|
|
1007
1020
|
const trip = {
|
|
1008
1021
|
trippedAt: at,
|
|
1009
1022
|
eventsAtTrip: [...tripEvents],
|
|
1010
|
-
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key)
|
|
1023
|
+
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key),
|
|
1024
|
+
// ENG-7577: persist the tripping class so the recovery path can gate on
|
|
1025
|
+
// it after a manager restart, without re-deriving it from prose.
|
|
1026
|
+
trippedClass
|
|
1011
1027
|
};
|
|
1012
1028
|
this.trips.set(codeName, trip);
|
|
1013
1029
|
this.events.delete(codeName);
|
|
@@ -1048,7 +1064,11 @@ var RestartBreaker = class {
|
|
|
1048
1064
|
if (!saved) return;
|
|
1049
1065
|
for (const [codeName, trip] of Object.entries(saved)) {
|
|
1050
1066
|
if (trip && typeof trip.trippedAt === "number" && Array.isArray(trip.eventsAtTrip)) {
|
|
1051
|
-
|
|
1067
|
+
const klass = trip.trippedClass;
|
|
1068
|
+
this.trips.set(
|
|
1069
|
+
codeName,
|
|
1070
|
+
klass === void 0 || KNOWN_REASON_CLASSES.has(klass) ? trip : { ...trip, trippedClass: void 0 }
|
|
1071
|
+
);
|
|
1052
1072
|
}
|
|
1053
1073
|
}
|
|
1054
1074
|
}
|
|
@@ -1275,6 +1295,9 @@ function decideAutoResume(opts) {
|
|
|
1275
1295
|
const { trip, marker, config: config2, now } = opts;
|
|
1276
1296
|
if (!config2.enabled) return { action: "skip", reason: "disabled" };
|
|
1277
1297
|
if (!trip) return { action: "skip", reason: "no-trip" };
|
|
1298
|
+
if (tripClass(trip) !== "provisioning") {
|
|
1299
|
+
return { action: "skip", reason: "class-not-eligible" };
|
|
1300
|
+
}
|
|
1278
1301
|
if (marker && now - marker.autoResumedAt < config2.backoffResetMs) {
|
|
1279
1302
|
return { action: "skip", reason: "already-auto-resumed" };
|
|
1280
1303
|
}
|
|
@@ -1296,6 +1319,28 @@ function hydrateAutoResumeMarkers(saved) {
|
|
|
1296
1319
|
return map;
|
|
1297
1320
|
}
|
|
1298
1321
|
|
|
1322
|
+
// src/lib/breaker-stale-trip.ts
|
|
1323
|
+
var DEFAULT_STALE_TRIP_SETTLE_MS = 12e4;
|
|
1324
|
+
var MIN_STALE_TRIP_SETTLE_MS = 1e3;
|
|
1325
|
+
function readStaleTripSettleMs() {
|
|
1326
|
+
return Math.max(
|
|
1327
|
+
MIN_STALE_TRIP_SETTLE_MS,
|
|
1328
|
+
readEnvNumber("AGT_RESTART_BREAKER_STALE_TRIP_SETTLE_MS", DEFAULT_STALE_TRIP_SETTLE_MS)
|
|
1329
|
+
);
|
|
1330
|
+
}
|
|
1331
|
+
function decideStaleTripClear(opts) {
|
|
1332
|
+
const { trip, agentStatus, killSwitched, settleMs, now } = opts;
|
|
1333
|
+
if (!trip) return { action: "hold", reason: "no-trip" };
|
|
1334
|
+
if (agentStatus !== "active" || killSwitched) {
|
|
1335
|
+
return { action: "hold", reason: "pause-in-force" };
|
|
1336
|
+
}
|
|
1337
|
+
const ageMs = now - trip.trippedAt;
|
|
1338
|
+
if (ageMs < settleMs) {
|
|
1339
|
+
return { action: "hold", reason: "settling", remainingMs: settleMs - ageMs };
|
|
1340
|
+
}
|
|
1341
|
+
return { action: "clear", ageMs };
|
|
1342
|
+
}
|
|
1343
|
+
|
|
1299
1344
|
// src/lib/resume-reconciler.ts
|
|
1300
1345
|
var DEFAULT_MIN_HEALTHY_CYCLES = 2;
|
|
1301
1346
|
var DEFAULT_BACKOFF_RESET_MS2 = 864e5;
|
|
@@ -1726,12 +1771,22 @@ var WINDOW_EXEMPT_RESTART_REASONS = /* @__PURE__ */ new Set([
|
|
|
1726
1771
|
"sender-policy-change",
|
|
1727
1772
|
"channel-mcp-down"
|
|
1728
1773
|
]);
|
|
1774
|
+
var RESTART_WINDOW_DEFER_ESCALATE_AFTER = 20;
|
|
1775
|
+
function shouldRelaxRestartWindowGate(deferStreak) {
|
|
1776
|
+
return deferStreak >= RESTART_WINDOW_DEFER_ESCALATE_AFTER;
|
|
1777
|
+
}
|
|
1778
|
+
function nextWindowDeferStreak(priorStreak, decision) {
|
|
1779
|
+
if (decision === "proceed") return 0;
|
|
1780
|
+
if (decision === "defer-window") return priorStreak + 1;
|
|
1781
|
+
return priorStreak;
|
|
1782
|
+
}
|
|
1729
1783
|
function isWindowExemptRestartReason(reason) {
|
|
1730
1784
|
return reason != null && WINDOW_EXEMPT_RESTART_REASONS.has(reason);
|
|
1731
1785
|
}
|
|
1732
1786
|
function decideRestartGate(opts) {
|
|
1733
1787
|
if (isMaintenanceWindowDisabled(opts.env)) return "proceed";
|
|
1734
|
-
|
|
1788
|
+
const windowAxisApplies = !opts.windowExempt && !shouldRelaxRestartWindowGate(opts.windowDeferStreak ?? 0);
|
|
1789
|
+
if (windowAxisApplies && opts.window && !isWithinMaintenanceWindow(opts.window, opts.now)) {
|
|
1735
1790
|
return "defer-window";
|
|
1736
1791
|
}
|
|
1737
1792
|
const paneThreshold = opts.idleThresholdSeconds ?? RESTART_IDLE_THRESHOLD_SECONDS;
|
|
@@ -8895,6 +8950,33 @@ function maybeReportCurrentTrip(codeName) {
|
|
|
8895
8950
|
log(`[circuit-breaker] Failed to report trip for '${codeName}' to API: ${err.message}`);
|
|
8896
8951
|
});
|
|
8897
8952
|
}
|
|
8953
|
+
function maybeClearStaleTrip(agent) {
|
|
8954
|
+
const codeName = agent.code_name;
|
|
8955
|
+
const trip = restartBreaker.getTrip(codeName);
|
|
8956
|
+
const decision = decideStaleTripClear({
|
|
8957
|
+
trip,
|
|
8958
|
+
agentStatus: agent.status,
|
|
8959
|
+
killSwitched: Boolean(agent.kill_switch),
|
|
8960
|
+
settleMs: readStaleTripSettleMs(),
|
|
8961
|
+
now: Date.now()
|
|
8962
|
+
});
|
|
8963
|
+
if (decision.action !== "clear") return;
|
|
8964
|
+
restartBreaker.clear(codeName);
|
|
8965
|
+
reportedTrips.delete(codeName);
|
|
8966
|
+
dependencyRecoveryLedger.clear(codeName);
|
|
8967
|
+
log(
|
|
8968
|
+
`[circuit-breaker] agent=${codeName} cleared STALE trip \u2014 authoritative status=active while a trip was held (age=${Math.round(decision.ageMs / 6e4)}min, trippedAt=${new Date(trip.trippedAt).toISOString()}); the pause this trip caused is no longer in force (ENG-7577)`
|
|
8969
|
+
);
|
|
8970
|
+
const marker = autoResumeMarkers.get(codeName);
|
|
8971
|
+
const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
|
|
8972
|
+
if (!isSelfResume) autoResumeMarkers.delete(codeName);
|
|
8973
|
+
state6 = {
|
|
8974
|
+
...state6,
|
|
8975
|
+
circuitBreakerTrips: restartBreaker.serialize(),
|
|
8976
|
+
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
8977
|
+
};
|
|
8978
|
+
send({ type: "state-update", state: state6 });
|
|
8979
|
+
}
|
|
8898
8980
|
var autoResumeMarkers = /* @__PURE__ */ new Map();
|
|
8899
8981
|
var autoResumeInFlight = /* @__PURE__ */ new Set();
|
|
8900
8982
|
var AUTO_RESUME_SELF_WINDOW_MS = 12e4;
|
|
@@ -8921,11 +9003,11 @@ function maybeAutoResume(agent) {
|
|
|
8921
9003
|
now: Date.now()
|
|
8922
9004
|
});
|
|
8923
9005
|
if (decision.action === "skip") {
|
|
8924
|
-
if ((decision.reason === "already-auto-resumed" || decision.reason === "not-quiet-yet") && trip) {
|
|
9006
|
+
if ((decision.reason === "already-auto-resumed" || decision.reason === "not-quiet-yet" || decision.reason === "class-not-eligible") && trip) {
|
|
8925
9007
|
const key = `${codeName}:${trip.trippedAt}`;
|
|
8926
9008
|
if (autoResumeLoggedSkips.get(key) !== decision.reason) {
|
|
8927
9009
|
autoResumeLoggedSkips.set(key, decision.reason);
|
|
8928
|
-
const detail = decision.reason === "not-quiet-yet" ? ` (~${Math.ceil((decision.remainingMs ?? 0) / 6e4)}min remaining)` : " \u2014 credit spent for this cycle; operator resume re-arms it";
|
|
9010
|
+
const detail = decision.reason === "not-quiet-yet" ? ` (~${Math.ceil((decision.remainingMs ?? 0) / 6e4)}min remaining)` : decision.reason === "class-not-eligible" ? ` class=${tripClass(trip)} \u2014 the blind quiet-timer only auto-recovers provisioning-reload trips; this one stays paused for an operator (ENG-7577)` : " \u2014 credit spent for this cycle; operator resume re-arms it";
|
|
8929
9011
|
log(`[auto-resume] agent=${codeName} decision=skip reason=${decision.reason}${detail} (ENG-6088)`);
|
|
8930
9012
|
}
|
|
8931
9013
|
}
|
|
@@ -9299,6 +9381,7 @@ function transcriptAgeSecondsFor(codeName) {
|
|
|
9299
9381
|
const sessionId = getSessionState(codeName)?.currentSessionId ?? null;
|
|
9300
9382
|
return transcriptActivityAgeSeconds(getProjectDir2(codeName), sessionId, /* @__PURE__ */ new Date());
|
|
9301
9383
|
}
|
|
9384
|
+
var restartGateDeferStreaks = /* @__PURE__ */ new Map();
|
|
9302
9385
|
function restartGateFor(codeName, reason) {
|
|
9303
9386
|
if (!isGateableRestartReason(reason)) return "bypass";
|
|
9304
9387
|
const tzInputs = agentRestartTimezoneInputs.get(codeName);
|
|
@@ -9311,16 +9394,28 @@ function restartGateFor(codeName, reason) {
|
|
|
9311
9394
|
tzInputs?.agentTimezoneExpiresAt ?? null
|
|
9312
9395
|
)
|
|
9313
9396
|
} : cachedMaintenanceWindow;
|
|
9314
|
-
|
|
9397
|
+
const streakKey = `${codeName}::${reason}`;
|
|
9398
|
+
const priorStreak = restartGateDeferStreaks.get(streakKey) ?? 0;
|
|
9399
|
+
const decision = decideRestartGate({
|
|
9315
9400
|
window: perAgentWindow,
|
|
9316
9401
|
// ENG-6491: channel adds (channel-set-change) skip the off-peak window but
|
|
9317
9402
|
// still defer-until-idle — they come online as soon as the agent is quiet.
|
|
9318
9403
|
windowExempt: isWindowExemptRestartReason(reason),
|
|
9404
|
+
windowDeferStreak: priorStreak,
|
|
9319
9405
|
paneLogAgeSeconds: paneLogAgeSecondsFor(codeName),
|
|
9320
9406
|
transcriptAgeSeconds: transcriptAgeSecondsFor(codeName),
|
|
9321
9407
|
inboundAgeSeconds: inboundAgeSecondsFor(codeName),
|
|
9322
9408
|
now: /* @__PURE__ */ new Date()
|
|
9323
9409
|
});
|
|
9410
|
+
const nextStreak = nextWindowDeferStreak(priorStreak, decision);
|
|
9411
|
+
if (nextStreak === 0) restartGateDeferStreaks.delete(streakKey);
|
|
9412
|
+
else restartGateDeferStreaks.set(streakKey, nextStreak);
|
|
9413
|
+
if (nextStreak === RESTART_WINDOW_DEFER_ESCALATE_AFTER && nextStreak !== priorStreak) {
|
|
9414
|
+
log(
|
|
9415
|
+
`[maintenance-window] '${codeName}': '${reason}' restart deferred ${nextStreak}\xD7 by the window \u2014 dropping the maintenance-window wait (ENG-8224). Still defer-until-idle: it will fire on the next quiet gap, never mid-turn.`
|
|
9416
|
+
);
|
|
9417
|
+
}
|
|
9418
|
+
return decision;
|
|
9324
9419
|
}
|
|
9325
9420
|
function isHostBusyForForcedUpdate(opts) {
|
|
9326
9421
|
const now = /* @__PURE__ */ new Date();
|
|
@@ -9787,7 +9882,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9787
9882
|
var lastVersionCheckAt = 0;
|
|
9788
9883
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9789
9884
|
var lastResponsivenessProbeAt = 0;
|
|
9790
|
-
var agtCliVersion = true ? "0.28.
|
|
9885
|
+
var agtCliVersion = true ? "0.28.452" : "dev";
|
|
9791
9886
|
function resolveBrewPath(execFileSync2) {
|
|
9792
9887
|
try {
|
|
9793
9888
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -11778,6 +11873,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11778
11873
|
const previousKnownStatus = agentState.knownStatuses.get(agent.agent_id);
|
|
11779
11874
|
agentState.agentDisplayNames.set(agent.code_name, agent.display_name);
|
|
11780
11875
|
agentState.codeNameToAgentId.set(agent.code_name, agent.agent_id);
|
|
11876
|
+
maybeClearStaleTrip(agent);
|
|
11781
11877
|
maybeReportCurrentTrip(agent.code_name);
|
|
11782
11878
|
if (agent.framework) {
|
|
11783
11879
|
agentFrameworkCache.set(agent.code_name, agent.framework);
|
|
@@ -11920,6 +12016,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11920
12016
|
if (previousStatus === "paused" && agent.status === "active" && restartBreaker.isTripped(agent.code_name)) {
|
|
11921
12017
|
restartBreaker.clear(agent.code_name);
|
|
11922
12018
|
reportedTrips.delete(agent.code_name);
|
|
12019
|
+
dependencyRecoveryLedger.clear(agent.code_name);
|
|
11923
12020
|
log(`[circuit-breaker] Cleared trip for '${agent.code_name}' on operator resume (paused \u2192 active)`);
|
|
11924
12021
|
}
|
|
11925
12022
|
if (previousStatus === "paused" && agent.status === "active") {
|