@integrity-labs/agt-cli 0.28.451 → 0.28.453
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 +4 -4
- package/dist/{chunk-ESZRW7A3.js → chunk-3NJHNIO3.js} +31 -9
- package/dist/chunk-3NJHNIO3.js.map +1 -0
- package/dist/{chunk-MY5HPJUW.js → chunk-HYKSLRTJ.js} +3 -3
- package/dist/{claude-pair-runtime-RCH4LKDE.js → claude-pair-runtime-NRKOKQYR.js} +2 -2
- package/dist/lib/manager-worker.js +164 -23
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +25 -8
- package/dist/mcp/origami.js +25 -8
- package/dist/mcp/slack-channel.js +25 -8
- package/dist/mcp/telegram-channel.js +25 -8
- package/dist/{persistent-session-7HZXY56P.js → persistent-session-X5N7UFEF.js} +2 -2
- package/dist/{responsiveness-probe-AIA7ZEBW.js → responsiveness-probe-OAZ55KPC.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-ESZRW7A3.js.map +0 -1
- /package/dist/{chunk-MY5HPJUW.js.map → chunk-HYKSLRTJ.js.map} +0 -0
- /package/dist/{claude-pair-runtime-RCH4LKDE.js.map → claude-pair-runtime-NRKOKQYR.js.map} +0 -0
- /package/dist/{persistent-session-7HZXY56P.js.map → persistent-session-X5N7UFEF.js.map} +0 -0
- /package/dist/{responsiveness-probe-AIA7ZEBW.js.map → responsiveness-probe-OAZ55KPC.js.map} +0 -0
|
@@ -29,7 +29,7 @@ import {
|
|
|
29
29
|
resolveConnectivityProbe,
|
|
30
30
|
worseConnectivityOutcome,
|
|
31
31
|
wrapScheduledTaskPrompt
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-3NJHNIO3.js";
|
|
33
33
|
import {
|
|
34
34
|
parsePsRows
|
|
35
35
|
} from "./chunk-XWVM4KPK.js";
|
|
@@ -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.453" : "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-HYKSLRTJ.js.map
|
|
@@ -100,7 +100,7 @@ async function spawnPairSession(session) {
|
|
|
100
100
|
return { ok: true };
|
|
101
101
|
} catch {
|
|
102
102
|
}
|
|
103
|
-
const { resolveClaudeBinary } = await import("./persistent-session-
|
|
103
|
+
const { resolveClaudeBinary } = await import("./persistent-session-X5N7UFEF.js");
|
|
104
104
|
const claudeBin = resolveClaudeBinary();
|
|
105
105
|
const pairEnv = {
|
|
106
106
|
...process.env,
|
|
@@ -373,4 +373,4 @@ export {
|
|
|
373
373
|
startClaudePair,
|
|
374
374
|
submitClaudePairCode
|
|
375
375
|
};
|
|
376
|
-
//# sourceMappingURL=claude-pair-runtime-
|
|
376
|
+
//# sourceMappingURL=claude-pair-runtime-NRKOKQYR.js.map
|
|
@@ -42,7 +42,7 @@ import {
|
|
|
42
42
|
resolveEffectivePinRaw,
|
|
43
43
|
safeWriteJsonAtomic,
|
|
44
44
|
setConfigHash
|
|
45
|
-
} from "../chunk-
|
|
45
|
+
} from "../chunk-HYKSLRTJ.js";
|
|
46
46
|
import {
|
|
47
47
|
getProjectDir as getProjectDir2,
|
|
48
48
|
getReadyTasks,
|
|
@@ -53,6 +53,7 @@ import {
|
|
|
53
53
|
import {
|
|
54
54
|
ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
|
|
55
55
|
AnchorSessionClient,
|
|
56
|
+
BIND_FAILURE_QUARANTINE_THRESHOLD,
|
|
56
57
|
CLAUDE_MD_MAX_CHARS,
|
|
57
58
|
CONVERSATION_FAILURE_CATEGORIES,
|
|
58
59
|
DEFAULT_FRAMEWORK,
|
|
@@ -63,6 +64,9 @@ import {
|
|
|
63
64
|
KANBAN_CHECK_COMMAND,
|
|
64
65
|
KANBAN_NUDGE_ACTIONABLE_STATUSES,
|
|
65
66
|
MAX_AVATAR_ENV_URL_BYTES,
|
|
67
|
+
MIN_PROVISIONING_MAX_FOR_QUARANTINE_ORDERING,
|
|
68
|
+
RESTART_BREAKER_PROVISIONING_MAX,
|
|
69
|
+
RESTART_BREAKER_PROVISIONING_WINDOW_MS,
|
|
66
70
|
SCHEDULED_TURN_MARKER_FILENAME,
|
|
67
71
|
SUPPRESS_SENTINEL,
|
|
68
72
|
StreamEncoder,
|
|
@@ -160,7 +164,7 @@ import {
|
|
|
160
164
|
toOpencodeModel,
|
|
161
165
|
transcriptActivityAgeSeconds,
|
|
162
166
|
writeEgressAllowlist
|
|
163
|
-
} from "../chunk-
|
|
167
|
+
} from "../chunk-3NJHNIO3.js";
|
|
164
168
|
import {
|
|
165
169
|
reapOrphanChannelMcps
|
|
166
170
|
} from "../chunk-XWVM4KPK.js";
|
|
@@ -841,10 +845,27 @@ function logClaudeMdCeilingTransition(codeName, report, log2) {
|
|
|
841
845
|
function reaperRestartBreakerReason(activeKeys) {
|
|
842
846
|
return activeKeys.length >= 2 ? "mcp-presence-reaper" : void 0;
|
|
843
847
|
}
|
|
848
|
+
var KNOWN_REASON_CLASS_MAP = {
|
|
849
|
+
crash: true,
|
|
850
|
+
provisioning: true,
|
|
851
|
+
"credential-rotation": true,
|
|
852
|
+
// ENG-8215: the self-healing class (bind-remediation - the manager's OWN
|
|
853
|
+
// repair attempts, which must never count toward a trip). Adding it here is
|
|
854
|
+
// forced by the Record type, which is exactly why that shape was chosen over
|
|
855
|
+
// a Set literal (ENG-7577, CodeRabbit on #3861) - a new union member cannot
|
|
856
|
+
// be silently omitted from the rehydration allowlist.
|
|
857
|
+
"self-healing": true
|
|
858
|
+
};
|
|
859
|
+
var KNOWN_REASON_CLASSES = new Set(
|
|
860
|
+
Object.keys(KNOWN_REASON_CLASS_MAP)
|
|
861
|
+
);
|
|
844
862
|
var PROVISIONING_RELOAD_REASONS = /* @__PURE__ */ new Set([
|
|
845
863
|
"hot-reload-mcp",
|
|
846
864
|
"managed-mcp-churn",
|
|
847
|
-
|
|
865
|
+
// ENG-8215: 'bind-remediation' MOVED OUT of this set into SELF_HEALING_REASONS.
|
|
866
|
+
// It is the manager repairing itself, not a config reload, and counting it
|
|
867
|
+
// meant the harder the platform tried to fix an agent the more certain it
|
|
868
|
+
// became that it should give up. Deliberately NOT re-added here.
|
|
848
869
|
// ENG-7576: the dashboard integration-add stop itself - the first restart of
|
|
849
870
|
// the very burst this class exists for, previously uncounted entirely.
|
|
850
871
|
"integration-change",
|
|
@@ -868,21 +889,35 @@ var CREDENTIAL_ROTATION_REASONS = /* @__PURE__ */ new Set([
|
|
|
868
889
|
function isCredentialRotationReason(reason) {
|
|
869
890
|
return CREDENTIAL_ROTATION_REASONS.has(reason);
|
|
870
891
|
}
|
|
892
|
+
var SELF_HEALING_REASONS = /* @__PURE__ */ new Set([
|
|
893
|
+
"bind-remediation"
|
|
894
|
+
]);
|
|
895
|
+
function isSelfHealingReason(reason) {
|
|
896
|
+
return SELF_HEALING_REASONS.has(reason);
|
|
897
|
+
}
|
|
871
898
|
function restartReasonClass(reason) {
|
|
872
899
|
if (isCredentialRotationReason(reason)) return "credential-rotation";
|
|
900
|
+
if (isSelfHealingReason(reason)) return "self-healing";
|
|
873
901
|
return isProvisioningReloadReason(reason) ? "provisioning" : "crash";
|
|
874
902
|
}
|
|
875
903
|
function countByClass(events) {
|
|
876
904
|
let crash = 0;
|
|
877
905
|
let provisioning = 0;
|
|
878
906
|
let credentialRotation = 0;
|
|
907
|
+
let selfHealing = 0;
|
|
879
908
|
for (const e of events) {
|
|
880
909
|
const klass = restartReasonClass(e.reason);
|
|
881
910
|
if (klass === "provisioning") provisioning += 1;
|
|
882
911
|
else if (klass === "credential-rotation") credentialRotation += 1;
|
|
912
|
+
else if (klass === "self-healing") selfHealing += 1;
|
|
883
913
|
else crash += 1;
|
|
884
914
|
}
|
|
885
|
-
return {
|
|
915
|
+
return {
|
|
916
|
+
crash,
|
|
917
|
+
provisioning,
|
|
918
|
+
"credential-rotation": credentialRotation,
|
|
919
|
+
"self-healing": selfHealing
|
|
920
|
+
};
|
|
886
921
|
}
|
|
887
922
|
function maxProvisioningBucket(events) {
|
|
888
923
|
const buckets = /* @__PURE__ */ new Map();
|
|
@@ -897,10 +932,15 @@ function maxProvisioningBucket(events) {
|
|
|
897
932
|
}
|
|
898
933
|
return best;
|
|
899
934
|
}
|
|
935
|
+
function tripClass(trip) {
|
|
936
|
+
if (trip.trippedClass) return trip.trippedClass;
|
|
937
|
+
if (!Array.isArray(trip.eventsAtTrip) || trip.eventsAtTrip.length === 0) return "crash";
|
|
938
|
+
return trip.eventsAtTrip.every((e) => isProvisioningReloadReason(e.reason)) ? "provisioning" : "crash";
|
|
939
|
+
}
|
|
900
940
|
var DEFAULT_MAX = 2;
|
|
901
941
|
var DEFAULT_WINDOW_MS = 6e5;
|
|
902
|
-
var DEFAULT_PROVISIONING_MAX =
|
|
903
|
-
var DEFAULT_PROVISIONING_WINDOW_MS =
|
|
942
|
+
var DEFAULT_PROVISIONING_MAX = RESTART_BREAKER_PROVISIONING_MAX;
|
|
943
|
+
var DEFAULT_PROVISIONING_WINDOW_MS = RESTART_BREAKER_PROVISIONING_WINDOW_MS;
|
|
904
944
|
function readEnvNumber(name, fallback) {
|
|
905
945
|
const raw = process.env[name];
|
|
906
946
|
if (!raw) return fallback;
|
|
@@ -910,6 +950,11 @@ function readEnvNumber(name, fallback) {
|
|
|
910
950
|
var RestartBreaker = class {
|
|
911
951
|
max;
|
|
912
952
|
windowMs;
|
|
953
|
+
/**
|
|
954
|
+
* ENG-8215: NOT readonly - the constructor may clamp it upward to preserve the
|
|
955
|
+
* quarantine-fires-first ordering against a runtime override. Never mutated
|
|
956
|
+
* after construction.
|
|
957
|
+
*/
|
|
913
958
|
provisioningMax;
|
|
914
959
|
provisioningWindowMs;
|
|
915
960
|
/** Longest window either tally needs — how long the events log must retain. */
|
|
@@ -917,6 +962,13 @@ var RestartBreaker = class {
|
|
|
917
962
|
now;
|
|
918
963
|
events = /* @__PURE__ */ new Map();
|
|
919
964
|
trips = /* @__PURE__ */ new Map();
|
|
965
|
+
/**
|
|
966
|
+
* ENG-8215: set when a supplied `provisioningMax` was raised to keep MCP
|
|
967
|
+
* quarantine ahead of the breaker. Read once by the manager at construction so
|
|
968
|
+
* an overridden-and-clamped value is visible in manager.log rather than
|
|
969
|
+
* silently discarded.
|
|
970
|
+
*/
|
|
971
|
+
quarantineOrderingClamped;
|
|
920
972
|
constructor(opts = {}) {
|
|
921
973
|
this.max = opts.max ?? readEnvNumber("AGT_RESTART_BREAKER_MAX", DEFAULT_MAX);
|
|
922
974
|
this.windowMs = opts.windowMs ?? readEnvNumber("AGT_RESTART_BREAKER_WINDOW_MS", DEFAULT_WINDOW_MS);
|
|
@@ -932,11 +984,27 @@ var RestartBreaker = class {
|
|
|
932
984
|
if (!Number.isFinite(this.provisioningMax) || this.provisioningMax < 1) {
|
|
933
985
|
throw new Error("restart-breaker provisioningMax must be a finite number >= 1");
|
|
934
986
|
}
|
|
987
|
+
if (this.provisioningMax < MIN_PROVISIONING_MAX_FOR_QUARANTINE_ORDERING) {
|
|
988
|
+
this.quarantineOrderingClamped = {
|
|
989
|
+
requested: this.provisioningMax,
|
|
990
|
+
applied: MIN_PROVISIONING_MAX_FOR_QUARANTINE_ORDERING,
|
|
991
|
+
quarantineThreshold: BIND_FAILURE_QUARANTINE_THRESHOLD
|
|
992
|
+
};
|
|
993
|
+
this.provisioningMax = MIN_PROVISIONING_MAX_FOR_QUARANTINE_ORDERING;
|
|
994
|
+
}
|
|
935
995
|
if (!Number.isFinite(this.provisioningWindowMs) || this.provisioningWindowMs < 1e3) {
|
|
936
996
|
throw new Error("restart-breaker provisioningWindowMs must be a finite number >= 1000");
|
|
937
997
|
}
|
|
938
998
|
this.retentionMs = Math.max(this.windowMs, this.provisioningWindowMs);
|
|
939
999
|
}
|
|
1000
|
+
/**
|
|
1001
|
+
* ENG-8215: the clamp record, if the configured provisioning max had to be
|
|
1002
|
+
* raised to keep MCP quarantine ahead of the breaker. `undefined` when the
|
|
1003
|
+
* configured value already satisfied the ordering.
|
|
1004
|
+
*/
|
|
1005
|
+
getQuarantineOrderingClamp() {
|
|
1006
|
+
return this.quarantineOrderingClamped;
|
|
1007
|
+
}
|
|
940
1008
|
/** True if this agent's breaker is currently tripped (manager must skip spawn). */
|
|
941
1009
|
isTripped(codeName) {
|
|
942
1010
|
return this.trips.has(codeName);
|
|
@@ -982,11 +1050,15 @@ var RestartBreaker = class {
|
|
|
982
1050
|
const credRotCount = prior.filter(
|
|
983
1051
|
(e) => e.at >= at - this.provisioningWindowMs && isCredentialRotationReason(e.reason)
|
|
984
1052
|
).length;
|
|
1053
|
+
const selfHealCount = prior.filter(
|
|
1054
|
+
(e) => e.at >= at - this.provisioningWindowMs && isSelfHealingReason(e.reason)
|
|
1055
|
+
).length;
|
|
985
1056
|
const windowCount = prior.filter((e) => e.at >= at - this.windowMs).length;
|
|
986
1057
|
const classCounts = {
|
|
987
1058
|
crash: crashCount,
|
|
988
1059
|
provisioning: provEvents.length,
|
|
989
|
-
"credential-rotation": credRotCount
|
|
1060
|
+
"credential-rotation": credRotCount,
|
|
1061
|
+
"self-healing": selfHealCount
|
|
990
1062
|
};
|
|
991
1063
|
const provBucket = maxProvisioningBucket(provEvents);
|
|
992
1064
|
let trippedClass;
|
|
@@ -1007,7 +1079,10 @@ var RestartBreaker = class {
|
|
|
1007
1079
|
const trip = {
|
|
1008
1080
|
trippedAt: at,
|
|
1009
1081
|
eventsAtTrip: [...tripEvents],
|
|
1010
|
-
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key)
|
|
1082
|
+
statusMessage: formatStatusMessage(tripEvents, tripWindowMs, trippedClass, provBucket.key),
|
|
1083
|
+
// ENG-7577: persist the tripping class so the recovery path can gate on
|
|
1084
|
+
// it after a manager restart, without re-deriving it from prose.
|
|
1085
|
+
trippedClass
|
|
1011
1086
|
};
|
|
1012
1087
|
this.trips.set(codeName, trip);
|
|
1013
1088
|
this.events.delete(codeName);
|
|
@@ -1048,7 +1123,11 @@ var RestartBreaker = class {
|
|
|
1048
1123
|
if (!saved) return;
|
|
1049
1124
|
for (const [codeName, trip] of Object.entries(saved)) {
|
|
1050
1125
|
if (trip && typeof trip.trippedAt === "number" && Array.isArray(trip.eventsAtTrip)) {
|
|
1051
|
-
|
|
1126
|
+
const klass = trip.trippedClass;
|
|
1127
|
+
this.trips.set(
|
|
1128
|
+
codeName,
|
|
1129
|
+
klass === void 0 || KNOWN_REASON_CLASSES.has(klass) ? trip : { ...trip, trippedClass: void 0 }
|
|
1130
|
+
);
|
|
1052
1131
|
}
|
|
1053
1132
|
}
|
|
1054
1133
|
}
|
|
@@ -1275,6 +1354,9 @@ function decideAutoResume(opts) {
|
|
|
1275
1354
|
const { trip, marker, config: config2, now } = opts;
|
|
1276
1355
|
if (!config2.enabled) return { action: "skip", reason: "disabled" };
|
|
1277
1356
|
if (!trip) return { action: "skip", reason: "no-trip" };
|
|
1357
|
+
if (tripClass(trip) !== "provisioning") {
|
|
1358
|
+
return { action: "skip", reason: "class-not-eligible" };
|
|
1359
|
+
}
|
|
1278
1360
|
if (marker && now - marker.autoResumedAt < config2.backoffResetMs) {
|
|
1279
1361
|
return { action: "skip", reason: "already-auto-resumed" };
|
|
1280
1362
|
}
|
|
@@ -1296,6 +1378,28 @@ function hydrateAutoResumeMarkers(saved) {
|
|
|
1296
1378
|
return map;
|
|
1297
1379
|
}
|
|
1298
1380
|
|
|
1381
|
+
// src/lib/breaker-stale-trip.ts
|
|
1382
|
+
var DEFAULT_STALE_TRIP_SETTLE_MS = 12e4;
|
|
1383
|
+
var MIN_STALE_TRIP_SETTLE_MS = 1e3;
|
|
1384
|
+
function readStaleTripSettleMs() {
|
|
1385
|
+
return Math.max(
|
|
1386
|
+
MIN_STALE_TRIP_SETTLE_MS,
|
|
1387
|
+
readEnvNumber("AGT_RESTART_BREAKER_STALE_TRIP_SETTLE_MS", DEFAULT_STALE_TRIP_SETTLE_MS)
|
|
1388
|
+
);
|
|
1389
|
+
}
|
|
1390
|
+
function decideStaleTripClear(opts) {
|
|
1391
|
+
const { trip, agentStatus, killSwitched, settleMs, now } = opts;
|
|
1392
|
+
if (!trip) return { action: "hold", reason: "no-trip" };
|
|
1393
|
+
if (agentStatus !== "active" || killSwitched) {
|
|
1394
|
+
return { action: "hold", reason: "pause-in-force" };
|
|
1395
|
+
}
|
|
1396
|
+
const ageMs = now - trip.trippedAt;
|
|
1397
|
+
if (ageMs < settleMs) {
|
|
1398
|
+
return { action: "hold", reason: "settling", remainingMs: settleMs - ageMs };
|
|
1399
|
+
}
|
|
1400
|
+
return { action: "clear", ageMs };
|
|
1401
|
+
}
|
|
1402
|
+
|
|
1299
1403
|
// src/lib/resume-reconciler.ts
|
|
1300
1404
|
var DEFAULT_MIN_HEALTHY_CYCLES = 2;
|
|
1301
1405
|
var DEFAULT_BACKOFF_RESET_MS2 = 864e5;
|
|
@@ -8818,9 +8922,17 @@ var pendingSessionRestarts = /* @__PURE__ */ new Map();
|
|
|
8818
8922
|
var lastRestartWasExternal = /* @__PURE__ */ new Map();
|
|
8819
8923
|
var pendingRestartVerifications = /* @__PURE__ */ new Map();
|
|
8820
8924
|
var restartBreaker = new RestartBreaker();
|
|
8925
|
+
{
|
|
8926
|
+
const clamp = restartBreaker.getQuarantineOrderingClamp();
|
|
8927
|
+
if (clamp) {
|
|
8928
|
+
log(
|
|
8929
|
+
`[circuit-breaker] provisioningMax=${clamp.requested} would trip before MCP quarantine (threshold=${clamp.quarantineThreshold}); raised to ${clamp.applied} so a failing integration is isolated before the whole agent is paused (ENG-8215)`
|
|
8930
|
+
);
|
|
8931
|
+
}
|
|
8932
|
+
}
|
|
8821
8933
|
var reportedTrips = /* @__PURE__ */ new Map();
|
|
8822
|
-
var
|
|
8823
|
-
var
|
|
8934
|
+
var RESTART_BREAKER_PROVISIONING_MAX2 = readEnvNumber("AGT_RESTART_BREAKER_PROVISIONING_MAX", 5);
|
|
8935
|
+
var RESTART_BREAKER_PROVISIONING_WINDOW_MS2 = readEnvNumber(
|
|
8824
8936
|
"AGT_RESTART_BREAKER_PROVISIONING_WINDOW_MS",
|
|
8825
8937
|
18e5
|
|
8826
8938
|
);
|
|
@@ -8865,13 +8977,13 @@ function recordRestartForBreaker(codeName, reason) {
|
|
|
8865
8977
|
let integrationKey;
|
|
8866
8978
|
if (isProvisioningReloadReason(reason)) {
|
|
8867
8979
|
const attribution = agentState.provisioningAttribution.get(codeName);
|
|
8868
|
-
if (attribution && Date.now() - attribution.at <=
|
|
8980
|
+
if (attribution && Date.now() - attribution.at <= RESTART_BREAKER_PROVISIONING_WINDOW_MS2) {
|
|
8869
8981
|
integrationKey = attribution.key;
|
|
8870
8982
|
}
|
|
8871
8983
|
}
|
|
8872
8984
|
const result = restartBreaker.record(codeName, reason, integrationKey);
|
|
8873
8985
|
if (!result.tripped || !result.trip) {
|
|
8874
|
-
if (isProvisioningReloadReason(reason) && result.maxProvisioningBucket >=
|
|
8986
|
+
if (isProvisioningReloadReason(reason) && result.maxProvisioningBucket >= RESTART_BREAKER_PROVISIONING_MAX2) {
|
|
8875
8987
|
const culprit = result.maxProvisioningBucketKey ? ` [${result.maxProvisioningBucketKey}]` : "";
|
|
8876
8988
|
log(
|
|
8877
8989
|
`[restart-breaker] agent=${codeName} provisioning-reload churn at the trip bar: ${result.maxProvisioningBucket} restarts for one integration${culprit} in window (reason=${reason}); one more will auto-pause the agent; that integration is likely churning (ENG-7560, ENG-7812)`
|
|
@@ -8905,6 +9017,33 @@ function maybeReportCurrentTrip(codeName) {
|
|
|
8905
9017
|
log(`[circuit-breaker] Failed to report trip for '${codeName}' to API: ${err.message}`);
|
|
8906
9018
|
});
|
|
8907
9019
|
}
|
|
9020
|
+
function maybeClearStaleTrip(agent) {
|
|
9021
|
+
const codeName = agent.code_name;
|
|
9022
|
+
const trip = restartBreaker.getTrip(codeName);
|
|
9023
|
+
const decision = decideStaleTripClear({
|
|
9024
|
+
trip,
|
|
9025
|
+
agentStatus: agent.status,
|
|
9026
|
+
killSwitched: Boolean(agent.kill_switch),
|
|
9027
|
+
settleMs: readStaleTripSettleMs(),
|
|
9028
|
+
now: Date.now()
|
|
9029
|
+
});
|
|
9030
|
+
if (decision.action !== "clear") return;
|
|
9031
|
+
restartBreaker.clear(codeName);
|
|
9032
|
+
reportedTrips.delete(codeName);
|
|
9033
|
+
dependencyRecoveryLedger.clear(codeName);
|
|
9034
|
+
log(
|
|
9035
|
+
`[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)`
|
|
9036
|
+
);
|
|
9037
|
+
const marker = autoResumeMarkers.get(codeName);
|
|
9038
|
+
const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
|
|
9039
|
+
if (!isSelfResume) autoResumeMarkers.delete(codeName);
|
|
9040
|
+
state6 = {
|
|
9041
|
+
...state6,
|
|
9042
|
+
circuitBreakerTrips: restartBreaker.serialize(),
|
|
9043
|
+
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
9044
|
+
};
|
|
9045
|
+
send({ type: "state-update", state: state6 });
|
|
9046
|
+
}
|
|
8908
9047
|
var autoResumeMarkers = /* @__PURE__ */ new Map();
|
|
8909
9048
|
var autoResumeInFlight = /* @__PURE__ */ new Set();
|
|
8910
9049
|
var AUTO_RESUME_SELF_WINDOW_MS = 12e4;
|
|
@@ -8931,11 +9070,11 @@ function maybeAutoResume(agent) {
|
|
|
8931
9070
|
now: Date.now()
|
|
8932
9071
|
});
|
|
8933
9072
|
if (decision.action === "skip") {
|
|
8934
|
-
if ((decision.reason === "already-auto-resumed" || decision.reason === "not-quiet-yet") && trip) {
|
|
9073
|
+
if ((decision.reason === "already-auto-resumed" || decision.reason === "not-quiet-yet" || decision.reason === "class-not-eligible") && trip) {
|
|
8935
9074
|
const key = `${codeName}:${trip.trippedAt}`;
|
|
8936
9075
|
if (autoResumeLoggedSkips.get(key) !== decision.reason) {
|
|
8937
9076
|
autoResumeLoggedSkips.set(key, decision.reason);
|
|
8938
|
-
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";
|
|
9077
|
+
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";
|
|
8939
9078
|
log(`[auto-resume] agent=${codeName} decision=skip reason=${decision.reason}${detail} (ENG-6088)`);
|
|
8940
9079
|
}
|
|
8941
9080
|
}
|
|
@@ -9810,7 +9949,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
|
|
|
9810
9949
|
var lastVersionCheckAt = 0;
|
|
9811
9950
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
9812
9951
|
var lastResponsivenessProbeAt = 0;
|
|
9813
|
-
var agtCliVersion = true ? "0.28.
|
|
9952
|
+
var agtCliVersion = true ? "0.28.453" : "dev";
|
|
9814
9953
|
function resolveBrewPath(execFileSync2) {
|
|
9815
9954
|
try {
|
|
9816
9955
|
const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -10971,7 +11110,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
|
|
|
10971
11110
|
if (codeNames.length === 0) return;
|
|
10972
11111
|
void (async () => {
|
|
10973
11112
|
try {
|
|
10974
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
11113
|
+
const { collectDiagnostics } = await import("../persistent-session-X5N7UFEF.js");
|
|
10975
11114
|
await api.post("/host/heartbeat", {
|
|
10976
11115
|
host_id: hostId,
|
|
10977
11116
|
agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -11078,7 +11217,7 @@ async function pollCycle() {
|
|
|
11078
11217
|
}
|
|
11079
11218
|
try {
|
|
11080
11219
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
11081
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
11220
|
+
const { collectDiagnostics } = await import("../persistent-session-X5N7UFEF.js");
|
|
11082
11221
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
11083
11222
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor) : void 0;
|
|
11084
11223
|
let tailscaleHostname;
|
|
@@ -11192,7 +11331,7 @@ async function pollCycle() {
|
|
|
11192
11331
|
collectResponsivenessProbes,
|
|
11193
11332
|
collectPanelessActivityProbes,
|
|
11194
11333
|
getResponsivenessIntervalMs
|
|
11195
|
-
} = await import("../responsiveness-probe-
|
|
11334
|
+
} = await import("../responsiveness-probe-OAZ55KPC.js");
|
|
11196
11335
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
11197
11336
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
11198
11337
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
@@ -11256,7 +11395,7 @@ async function pollCycle() {
|
|
|
11256
11395
|
collectResponsivenessProbes,
|
|
11257
11396
|
livePendingInboundOldestAgeSeconds,
|
|
11258
11397
|
parkPendingInbound
|
|
11259
|
-
} = await import("../responsiveness-probe-
|
|
11398
|
+
} = await import("../responsiveness-probe-OAZ55KPC.js");
|
|
11260
11399
|
const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
|
|
11261
11400
|
const wedgeNow = /* @__PURE__ */ new Date();
|
|
11262
11401
|
const liveAgents = agentState.persistentSessionAgents;
|
|
@@ -11801,6 +11940,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11801
11940
|
const previousKnownStatus = agentState.knownStatuses.get(agent.agent_id);
|
|
11802
11941
|
agentState.agentDisplayNames.set(agent.code_name, agent.display_name);
|
|
11803
11942
|
agentState.codeNameToAgentId.set(agent.code_name, agent.agent_id);
|
|
11943
|
+
maybeClearStaleTrip(agent);
|
|
11804
11944
|
maybeReportCurrentTrip(agent.code_name);
|
|
11805
11945
|
if (agent.framework) {
|
|
11806
11946
|
agentFrameworkCache.set(agent.code_name, agent.framework);
|
|
@@ -11943,6 +12083,7 @@ async function processAgent(agent, agentStates) {
|
|
|
11943
12083
|
if (previousStatus === "paused" && agent.status === "active" && restartBreaker.isTripped(agent.code_name)) {
|
|
11944
12084
|
restartBreaker.clear(agent.code_name);
|
|
11945
12085
|
reportedTrips.delete(agent.code_name);
|
|
12086
|
+
dependencyRecoveryLedger.clear(agent.code_name);
|
|
11946
12087
|
log(`[circuit-breaker] Cleared trip for '${agent.code_name}' on operator resume (paused \u2192 active)`);
|
|
11947
12088
|
}
|
|
11948
12089
|
if (previousStatus === "paused" && agent.status === "active") {
|
|
@@ -14626,7 +14767,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
|
|
|
14626
14767
|
void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
|
|
14627
14768
|
void (async () => {
|
|
14628
14769
|
try {
|
|
14629
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14770
|
+
const { collectDiagnostics } = await import("../persistent-session-X5N7UFEF.js");
|
|
14630
14771
|
await api.post("/host/heartbeat", {
|
|
14631
14772
|
host_id: hostId,
|
|
14632
14773
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -14676,7 +14817,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
|
|
|
14676
14817
|
}
|
|
14677
14818
|
try {
|
|
14678
14819
|
const hostId = await getHostId();
|
|
14679
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
14820
|
+
const { collectDiagnostics } = await import("../persistent-session-X5N7UFEF.js");
|
|
14680
14821
|
await api.post("/host/heartbeat", {
|
|
14681
14822
|
host_id: hostId,
|
|
14682
14823
|
agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor)
|
|
@@ -15129,7 +15270,7 @@ async function processClaudePairSessions(agents) {
|
|
|
15129
15270
|
killPairSession,
|
|
15130
15271
|
pairTmuxSession,
|
|
15131
15272
|
finalizeClaudePairOnboarding
|
|
15132
|
-
} = await import("../claude-pair-runtime-
|
|
15273
|
+
} = await import("../claude-pair-runtime-NRKOKQYR.js");
|
|
15133
15274
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
15134
15275
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
15135
15276
|
const killed = await killPairSession(pairTmuxSession(pairId));
|