@integrity-labs/agt-cli 0.27.107 → 0.27.109
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-DFQ2EOHB.js → chunk-D2EJL2KI.js} +2 -2
- package/dist/{chunk-HR5T2RQF.js → chunk-I3YS5WFV.js} +3 -1
- package/dist/chunk-I3YS5WFV.js.map +1 -0
- package/dist/{chunk-KBN7SNAV.js → chunk-OATXUUQB.js} +2 -2
- package/dist/{chunk-BP4D3ZPJ.js → chunk-Z3YQYO43.js} +16 -3
- package/dist/{chunk-BP4D3ZPJ.js.map → chunk-Z3YQYO43.js.map} +1 -1
- package/dist/{claude-pair-runtime-AI37D2CT.js → claude-pair-runtime-DS7675XI.js} +2 -2
- package/dist/{claude-scheduler-EM24LTGV.js → claude-scheduler-FATCLHDM.js} +2 -2
- package/dist/lib/manager-worker.js +145 -13
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-HGR5D4DJ.js → persistent-session-3ZWAGNNO.js} +3 -3
- package/dist/{responsiveness-probe-FS376EVY.js → responsiveness-probe-EGXJFJBW.js} +3 -3
- package/package.json +1 -1
- package/dist/chunk-HR5T2RQF.js.map +0 -1
- /package/dist/{chunk-DFQ2EOHB.js.map → chunk-D2EJL2KI.js.map} +0 -0
- /package/dist/{chunk-KBN7SNAV.js.map → chunk-OATXUUQB.js.map} +0 -0
- /package/dist/{claude-pair-runtime-AI37D2CT.js.map → claude-pair-runtime-DS7675XI.js.map} +0 -0
- /package/dist/{claude-scheduler-EM24LTGV.js.map → claude-scheduler-FATCLHDM.js.map} +0 -0
- /package/dist/{persistent-session-HGR5D4DJ.js.map → persistent-session-3ZWAGNNO.js.map} +0 -0
- /package/dist/{responsiveness-probe-FS376EVY.js.map → responsiveness-probe-EGXJFJBW.js.map} +0 -0
|
@@ -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-3ZWAGNNO.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-DS7675XI.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
markTaskFired,
|
|
8
8
|
saveSchedulerState,
|
|
9
9
|
syncTasksToScheduler
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-I3YS5WFV.js";
|
|
11
11
|
export {
|
|
12
12
|
computeNextFire,
|
|
13
13
|
findTaskByTemplate,
|
|
@@ -18,4 +18,4 @@ export {
|
|
|
18
18
|
saveSchedulerState,
|
|
19
19
|
syncTasksToScheduler
|
|
20
20
|
};
|
|
21
|
-
//# sourceMappingURL=claude-scheduler-
|
|
21
|
+
//# sourceMappingURL=claude-scheduler-FATCLHDM.js.map
|
|
@@ -17,14 +17,14 @@ import {
|
|
|
17
17
|
provisionStopHook,
|
|
18
18
|
requireHost,
|
|
19
19
|
safeWriteJsonAtomic
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-OATXUUQB.js";
|
|
21
21
|
import {
|
|
22
22
|
getProjectDir as getProjectDir2,
|
|
23
23
|
getReadyTasks,
|
|
24
24
|
loadSchedulerState,
|
|
25
25
|
markTaskFired,
|
|
26
26
|
syncTasksToScheduler
|
|
27
|
-
} from "../chunk-
|
|
27
|
+
} from "../chunk-I3YS5WFV.js";
|
|
28
28
|
import {
|
|
29
29
|
buildAllowedTools,
|
|
30
30
|
checkChannelInputs,
|
|
@@ -55,7 +55,7 @@ import {
|
|
|
55
55
|
stopPersistentSession,
|
|
56
56
|
takeWatchdogGiveUpCount,
|
|
57
57
|
takeZombieDetection
|
|
58
|
-
} from "../chunk-
|
|
58
|
+
} from "../chunk-D2EJL2KI.js";
|
|
59
59
|
import {
|
|
60
60
|
KANBAN_CHECK_COMMAND,
|
|
61
61
|
SUPPRESS_SENTINEL,
|
|
@@ -79,7 +79,7 @@ import {
|
|
|
79
79
|
resolveConnectivityProbe,
|
|
80
80
|
resolveDmTarget,
|
|
81
81
|
wrapScheduledTaskPrompt
|
|
82
|
-
} from "../chunk-
|
|
82
|
+
} from "../chunk-Z3YQYO43.js";
|
|
83
83
|
import {
|
|
84
84
|
parsePsRows,
|
|
85
85
|
reapOrphanChannelMcps
|
|
@@ -968,6 +968,42 @@ function formatStatusMessage(events, windowMs) {
|
|
|
968
968
|
return `Circuit breaker tripped: ${events.length} restarts in ${windowLabel} (${breakdown}); most recent=${last.reason} at ${new Date(last.at).toISOString()}`;
|
|
969
969
|
}
|
|
970
970
|
|
|
971
|
+
// src/lib/auto-resume.ts
|
|
972
|
+
var DEFAULT_QUIET_MS = 18e5;
|
|
973
|
+
var DEFAULT_BACKOFF_RESET_MS = 864e5;
|
|
974
|
+
function readAutoResumeConfig(env = process.env) {
|
|
975
|
+
const raw = (env["AGT_AUTO_RESUME_ENABLED"] ?? "").trim().toLowerCase();
|
|
976
|
+
return {
|
|
977
|
+
enabled: raw === "1" || raw === "true" || raw === "yes" || raw === "on",
|
|
978
|
+
quietMs: readEnvNumber("AGT_AUTO_RESUME_QUIET_MS", DEFAULT_QUIET_MS),
|
|
979
|
+
backoffResetMs: readEnvNumber("AGT_AUTO_RESUME_BACKOFF_RESET_MS", DEFAULT_BACKOFF_RESET_MS)
|
|
980
|
+
};
|
|
981
|
+
}
|
|
982
|
+
function decideAutoResume(opts) {
|
|
983
|
+
const { trip, marker, config: config2, now } = opts;
|
|
984
|
+
if (!config2.enabled) return { action: "skip", reason: "disabled" };
|
|
985
|
+
if (!trip) return { action: "skip", reason: "no-trip" };
|
|
986
|
+
if (marker && now - marker.autoResumedAt < config2.backoffResetMs) {
|
|
987
|
+
return { action: "skip", reason: "already-auto-resumed" };
|
|
988
|
+
}
|
|
989
|
+
const lastEventAt = trip.eventsAtTrip.length > 0 ? Math.max(trip.trippedAt, ...trip.eventsAtTrip.map((e) => e.at)) : trip.trippedAt;
|
|
990
|
+
const quietFor = now - lastEventAt;
|
|
991
|
+
if (quietFor < config2.quietMs) {
|
|
992
|
+
return { action: "skip", reason: "not-quiet-yet", remainingMs: config2.quietMs - quietFor };
|
|
993
|
+
}
|
|
994
|
+
return { action: "resume", quietMs: quietFor };
|
|
995
|
+
}
|
|
996
|
+
function hydrateAutoResumeMarkers(saved) {
|
|
997
|
+
const map = /* @__PURE__ */ new Map();
|
|
998
|
+
if (!saved) return map;
|
|
999
|
+
for (const [codeName, rec] of Object.entries(saved)) {
|
|
1000
|
+
if (rec && typeof rec.trippedAt === "number" && typeof rec.autoResumedAt === "number") {
|
|
1001
|
+
map.set(codeName, rec);
|
|
1002
|
+
}
|
|
1003
|
+
}
|
|
1004
|
+
return map;
|
|
1005
|
+
}
|
|
1006
|
+
|
|
971
1007
|
// src/lib/model-change-respawn.ts
|
|
972
1008
|
function shouldRespawnForModelChange(input) {
|
|
973
1009
|
const { previousModel, primaryModel, framework, sessionHealthy } = input;
|
|
@@ -3730,6 +3766,64 @@ function maybeReportCurrentTrip(codeName) {
|
|
|
3730
3766
|
log(`[circuit-breaker] Failed to report trip for '${codeName}' to API: ${err.message}`);
|
|
3731
3767
|
});
|
|
3732
3768
|
}
|
|
3769
|
+
var autoResumeMarkers = /* @__PURE__ */ new Map();
|
|
3770
|
+
var autoResumeInFlight = /* @__PURE__ */ new Set();
|
|
3771
|
+
var AUTO_RESUME_SELF_WINDOW_MS = 12e4;
|
|
3772
|
+
var autoResumeLoggedSkips = /* @__PURE__ */ new Map();
|
|
3773
|
+
var autoResumeStandDowns = /* @__PURE__ */ new Set();
|
|
3774
|
+
function maybeAutoResume(agent) {
|
|
3775
|
+
const codeName = agent.code_name;
|
|
3776
|
+
if (autoResumeInFlight.has(codeName)) return;
|
|
3777
|
+
const trip = restartBreaker.getTrip(codeName);
|
|
3778
|
+
if (trip && autoResumeStandDowns.has(`${codeName}:${trip.trippedAt}`)) return;
|
|
3779
|
+
const decision = decideAutoResume({
|
|
3780
|
+
trip,
|
|
3781
|
+
marker: autoResumeMarkers.get(codeName),
|
|
3782
|
+
config: readAutoResumeConfig(),
|
|
3783
|
+
now: Date.now()
|
|
3784
|
+
});
|
|
3785
|
+
if (decision.action === "skip") {
|
|
3786
|
+
if ((decision.reason === "already-auto-resumed" || decision.reason === "not-quiet-yet") && trip) {
|
|
3787
|
+
const key = `${codeName}:${trip.trippedAt}`;
|
|
3788
|
+
if (autoResumeLoggedSkips.get(key) !== decision.reason) {
|
|
3789
|
+
autoResumeLoggedSkips.set(key, decision.reason);
|
|
3790
|
+
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";
|
|
3791
|
+
log(`[auto-resume] agent=${codeName} decision=skip reason=${decision.reason}${detail} (ENG-6088)`);
|
|
3792
|
+
}
|
|
3793
|
+
}
|
|
3794
|
+
return;
|
|
3795
|
+
}
|
|
3796
|
+
const trippedAt = trip.trippedAt;
|
|
3797
|
+
log(
|
|
3798
|
+
`[auto-resume] agent=${codeName} decision=resume quiet=${Math.round(decision.quietMs / 6e4)}min trippedAt=${new Date(trippedAt).toISOString()} (ENG-6088)`
|
|
3799
|
+
);
|
|
3800
|
+
autoResumeInFlight.add(codeName);
|
|
3801
|
+
api.post("/host/circuit-breaker/auto-resume", {
|
|
3802
|
+
agent_id: agent.agent_id,
|
|
3803
|
+
quiet_ms: decision.quietMs,
|
|
3804
|
+
tripped_at: new Date(trippedAt).toISOString()
|
|
3805
|
+
}).then((res) => {
|
|
3806
|
+
autoResumeInFlight.delete(codeName);
|
|
3807
|
+
if (res.resumed) {
|
|
3808
|
+
autoResumeMarkers.set(codeName, { trippedAt, autoResumedAt: Date.now() });
|
|
3809
|
+
restartBreaker.clear(codeName);
|
|
3810
|
+
reportedTrips.delete(codeName);
|
|
3811
|
+
state5 = {
|
|
3812
|
+
...state5,
|
|
3813
|
+
circuitBreakerTrips: restartBreaker.serialize(),
|
|
3814
|
+
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
3815
|
+
};
|
|
3816
|
+
send({ type: "state-update", state: state5 });
|
|
3817
|
+
log(`[auto-resume] agent=${codeName} resumed \u2014 re-trip within backoff window will stay paused (ENG-6088)`);
|
|
3818
|
+
} else {
|
|
3819
|
+
autoResumeStandDowns.add(`${codeName}:${trippedAt}`);
|
|
3820
|
+
log(`[auto-resume] agent=${codeName} not applied (reason=${res.reason ?? "unknown"}) \u2014 standing down for this trip (ENG-6088)`);
|
|
3821
|
+
}
|
|
3822
|
+
}).catch((err) => {
|
|
3823
|
+
autoResumeInFlight.delete(codeName);
|
|
3824
|
+
log(`[auto-resume] agent=${codeName} POST failed (will retry next poll): ${err.message}`);
|
|
3825
|
+
});
|
|
3826
|
+
}
|
|
3733
3827
|
function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-reload-mcp") {
|
|
3734
3828
|
const existing = pendingSessionRestarts.get(codeName);
|
|
3735
3829
|
if (existing) {
|
|
@@ -4039,7 +4133,7 @@ var cachedMaintenanceWindow = null;
|
|
|
4039
4133
|
var lastVersionCheckAt = 0;
|
|
4040
4134
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
4041
4135
|
var lastResponsivenessProbeAt = 0;
|
|
4042
|
-
var agtCliVersion = true ? "0.27.
|
|
4136
|
+
var agtCliVersion = true ? "0.27.109" : "dev";
|
|
4043
4137
|
function resolveBrewPath(execFileSync4) {
|
|
4044
4138
|
try {
|
|
4045
4139
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -5232,7 +5326,7 @@ async function pollCycle() {
|
|
|
5232
5326
|
}
|
|
5233
5327
|
try {
|
|
5234
5328
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
5235
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
5329
|
+
const { collectDiagnostics } = await import("../persistent-session-3ZWAGNNO.js");
|
|
5236
5330
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
5237
5331
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
5238
5332
|
let tailscaleHostname;
|
|
@@ -5319,12 +5413,12 @@ async function pollCycle() {
|
|
|
5319
5413
|
const {
|
|
5320
5414
|
collectResponsivenessProbes,
|
|
5321
5415
|
getResponsivenessIntervalMs
|
|
5322
|
-
} = await import("../responsiveness-probe-
|
|
5416
|
+
} = await import("../responsiveness-probe-EGXJFJBW.js");
|
|
5323
5417
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
5324
5418
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
5325
5419
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
5326
5420
|
if (probeCodeNames.length > 0) {
|
|
5327
|
-
const { takeAcpxExecFailureCount, creditAcpxExecFailureCount } = await import("../persistent-session-
|
|
5421
|
+
const { takeAcpxExecFailureCount, creditAcpxExecFailureCount } = await import("../persistent-session-3ZWAGNNO.js");
|
|
5328
5422
|
const drainedGiveUps = /* @__PURE__ */ new Map();
|
|
5329
5423
|
const drainedAcpxFailures = /* @__PURE__ */ new Map();
|
|
5330
5424
|
const probes = collectResponsivenessProbes(probeCodeNames).map((p) => {
|
|
@@ -5615,7 +5709,9 @@ async function pollCycle() {
|
|
|
5615
5709
|
// ENG-5441: serialise trip state on every poll so manager restarts
|
|
5616
5710
|
// never silently clear a tripped breaker. Cheap — only tripped
|
|
5617
5711
|
// entries are stored, and the typical state is zero entries.
|
|
5618
|
-
circuitBreakerTrips: restartBreaker.serialize()
|
|
5712
|
+
circuitBreakerTrips: restartBreaker.serialize(),
|
|
5713
|
+
// ENG-6088: spent auto-resume credits survive manager restarts too.
|
|
5714
|
+
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
5619
5715
|
};
|
|
5620
5716
|
if (consecutivePollFailures > 0) {
|
|
5621
5717
|
log(`[poll-backoff] recovered after ${consecutivePollFailures} failure(s), resuming normal interval`);
|
|
@@ -5690,6 +5786,9 @@ async function processAgent(agent, agentStates) {
|
|
|
5690
5786
|
log(`Killed tmux session for paused agent '${agent.code_name}'`);
|
|
5691
5787
|
} catch {
|
|
5692
5788
|
}
|
|
5789
|
+
if (agent.status === "paused") {
|
|
5790
|
+
maybeAutoResume(agent);
|
|
5791
|
+
}
|
|
5693
5792
|
agentStates.push({
|
|
5694
5793
|
agentId: agent.agent_id,
|
|
5695
5794
|
codeName: agent.code_name,
|
|
@@ -5781,6 +5880,18 @@ async function processAgent(agent, agentStates) {
|
|
|
5781
5880
|
reportedTrips.delete(agent.code_name);
|
|
5782
5881
|
log(`[circuit-breaker] Cleared trip for '${agent.code_name}' on operator resume (paused \u2192 active)`);
|
|
5783
5882
|
}
|
|
5883
|
+
if (previousStatus === "paused" && agent.status === "active") {
|
|
5884
|
+
const marker = autoResumeMarkers.get(agent.code_name);
|
|
5885
|
+
const isSelfResume = marker !== void 0 && Date.now() - marker.autoResumedAt < AUTO_RESUME_SELF_WINDOW_MS;
|
|
5886
|
+
if (!isSelfResume && autoResumeMarkers.delete(agent.code_name)) {
|
|
5887
|
+
state5 = {
|
|
5888
|
+
...state5,
|
|
5889
|
+
circuitBreakerAutoResumes: Object.fromEntries(autoResumeMarkers.entries())
|
|
5890
|
+
};
|
|
5891
|
+
send({ type: "state-update", state: state5 });
|
|
5892
|
+
log(`[auto-resume] Cleared auto-resume marker for '${agent.code_name}' on operator resume \u2014 credit re-armed (ENG-6088)`);
|
|
5893
|
+
}
|
|
5894
|
+
}
|
|
5784
5895
|
let channelCacheMutated = false;
|
|
5785
5896
|
for (const key of agentState.knownChannelConfigHashes.keys()) {
|
|
5786
5897
|
if (key.startsWith(`${agent.agent_id}:`)) {
|
|
@@ -7645,6 +7756,20 @@ async function deliverScheduledCardResult(codeName, agentId, cardId) {
|
|
|
7645
7756
|
markScheduledCardDeliveryComplete(cardId);
|
|
7646
7757
|
return "terminal";
|
|
7647
7758
|
}
|
|
7759
|
+
const deliveryPolicy = task.deliveryPolicy ?? "always";
|
|
7760
|
+
if (deliveryPolicy === "never" || deliveryPolicy === "conditional" && card.suppress_delivery !== false) {
|
|
7761
|
+
log(
|
|
7762
|
+
`[scheduled-kanban] Suppressed by delivery_policy=${deliveryPolicy} for card ${cardId} (task '${task.name}') on '${codeName}' \u2014 result recorded on the card only (tombstone)`
|
|
7763
|
+
);
|
|
7764
|
+
if (task.deliveryMode === "announce" && task.deliveryTo) {
|
|
7765
|
+
await reportDeliveryStatus(agentId, task.taskId, {
|
|
7766
|
+
status: "skipped",
|
|
7767
|
+
error_code: "SUPPRESSED_BY_POLICY"
|
|
7768
|
+
});
|
|
7769
|
+
}
|
|
7770
|
+
markScheduledCardDeliveryComplete(cardId);
|
|
7771
|
+
return "delivered";
|
|
7772
|
+
}
|
|
7648
7773
|
if (card.suppress_delivery === true) {
|
|
7649
7774
|
log(`[scheduled-kanban] Suppressing delivery (structured flag) for card ${cardId} (task '${task.name}') on '${codeName}' \u2014 result recorded on the card only`);
|
|
7650
7775
|
if (task.deliveryMode === "announce" && task.deliveryTo) {
|
|
@@ -7710,9 +7835,11 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt) {
|
|
|
7710
7835
|
if (run_id) void finishRun(run_id, "failed", { outcomeMessage: "kanban materialise incomplete", completeKanbanItemId: kanban_item_id });
|
|
7711
7836
|
return false;
|
|
7712
7837
|
}
|
|
7838
|
+
const suppressionTeaching = (task.deliveryPolicy ?? "always") === "conditional" ? `THIS task is CONDITIONAL: quiet runs stay SILENT automatically. Write your findings on the card and mark it done \u2014 if nothing met the user's criteria, NOTHING will be sent (no flag needed). If something DID meet the criteria and the user must be told, call kanban_done with suppress_delivery: false \u2014 that explicit assert is the ONLY way this result reaches the user.
|
|
7839
|
+
` : `If \u2014 and ONLY if \u2014 the task description contains explicit opt-out wording the user typed (e.g. "DO NOT notify me unless urgent", "only if X", "stay silent unless \u2026") and that condition is NOT met this run, call kanban_done with suppress_delivery: true \u2014 your result stays on the card but will NOT be messaged to the user. That is how you honor the user's do-not-notify instruction: a "nothing urgent" result without the flag would still be DELIVERED as a message. A report with zero items is only a valid deliverable when the task asks for a digest WITHOUT opt-out wording \u2014 when in doubt, deliver.
|
|
7840
|
+
`;
|
|
7713
7841
|
const nudge = `You have a new scheduled task on your kanban board: id=${kanban_item_id} title=${JSON.stringify(task.name)}. Call kanban_move("${kanban_item_id}", "in_progress"), do the work described on the card, then write the finished result onto the card and mark it done. Do NOT send, post, or message the result to anyone yourself \u2014 the result you write on the card IS the message that will be delivered to the user; delivery happens automatically from the card.
|
|
7714
|
-
|
|
7715
|
-
` + formatRunMarker(run_id);
|
|
7842
|
+
` + suppressionTeaching + formatRunMarker(run_id);
|
|
7716
7843
|
let injectStatus;
|
|
7717
7844
|
try {
|
|
7718
7845
|
injectStatus = await injectMessageWithStatus(codeName, "task", nudge, { task_name: "scheduled-task" }, log);
|
|
@@ -8608,7 +8735,7 @@ ${escapeXml(msg.content)}
|
|
|
8608
8735
|
return;
|
|
8609
8736
|
}
|
|
8610
8737
|
log(`[direct-chat] One-shot spawn for '${agent.codeName}' (msg=${msg.id}; host in-flight=${directChatSpawnGate.hostInFlight}, queued=${directChatSpawnGate.queuedCount})`);
|
|
8611
|
-
const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-
|
|
8738
|
+
const { getProjectDir: ccProjectDir } = await import("../claude-scheduler-FATCLHDM.js");
|
|
8612
8739
|
const projDir = ccProjectDir(agent.codeName);
|
|
8613
8740
|
const mcpConfigPath = join8(projDir, ".mcp.json");
|
|
8614
8741
|
const serverNames = [];
|
|
@@ -9679,7 +9806,7 @@ async function processClaudePairSessions(agents) {
|
|
|
9679
9806
|
killPairSession,
|
|
9680
9807
|
pairTmuxSession,
|
|
9681
9808
|
finalizeClaudePairOnboarding
|
|
9682
|
-
} = await import("../claude-pair-runtime-
|
|
9809
|
+
} = await import("../claude-pair-runtime-DS7675XI.js");
|
|
9683
9810
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
9684
9811
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
9685
9812
|
const killed = await killPairSession(pairTmuxSession(pairId));
|
|
@@ -10305,6 +10432,11 @@ function startManager(opts) {
|
|
|
10305
10432
|
const n = Object.keys(parsed.circuitBreakerTrips).length;
|
|
10306
10433
|
if (n > 0) log(`[startup] rehydrated ${n} circuit-breaker trip(s) \u2014 agents will remain paused until manually resumed`);
|
|
10307
10434
|
}
|
|
10435
|
+
if (parsed.circuitBreakerAutoResumes && typeof parsed.circuitBreakerAutoResumes === "object") {
|
|
10436
|
+
autoResumeMarkers = hydrateAutoResumeMarkers(parsed.circuitBreakerAutoResumes);
|
|
10437
|
+
const n = autoResumeMarkers.size;
|
|
10438
|
+
if (n > 0) log(`[startup] rehydrated ${n} auto-resume marker(s) (ENG-6088)`);
|
|
10439
|
+
}
|
|
10308
10440
|
}
|
|
10309
10441
|
} catch (err) {
|
|
10310
10442
|
log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
|