@integrity-labs/agt-cli 0.27.113 → 0.27.115
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 +3 -3
- package/dist/{chunk-UHG6DSOX.js → chunk-EOMWSV4B.js} +1 -1
- package/dist/{chunk-RN3OMHW7.js → chunk-IUN5LBTQ.js} +11 -1
- package/dist/chunk-IUN5LBTQ.js.map +1 -0
- package/dist/{claude-pair-runtime-KVJ4U436.js → claude-pair-runtime-UX7GWW3O.js} +2 -2
- package/dist/lib/manager-worker.js +130 -8
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-E6YLH6TX.js → persistent-session-PIR45QFL.js} +4 -2
- package/dist/{responsiveness-probe-TDHX6JKG.js → responsiveness-probe-FLQZ7E5H.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-RN3OMHW7.js.map +0 -1
- /package/dist/{chunk-UHG6DSOX.js.map → chunk-EOMWSV4B.js.map} +0 -0
- /package/dist/{claude-pair-runtime-KVJ4U436.js.map → claude-pair-runtime-UX7GWW3O.js.map} +0 -0
- /package/dist/{persistent-session-E6YLH6TX.js.map → persistent-session-PIR45QFL.js.map} +0 -0
- /package/dist/{responsiveness-probe-TDHX6JKG.js.map → responsiveness-probe-FLQZ7E5H.js.map} +0 -0
|
@@ -17,7 +17,7 @@ import {
|
|
|
17
17
|
provisionStopHook,
|
|
18
18
|
requireHost,
|
|
19
19
|
safeWriteJsonAtomic
|
|
20
|
-
} from "../chunk-
|
|
20
|
+
} from "../chunk-EOMWSV4B.js";
|
|
21
21
|
import {
|
|
22
22
|
getProjectDir as getProjectDir2,
|
|
23
23
|
getReadyTasks,
|
|
@@ -47,6 +47,7 @@ import {
|
|
|
47
47
|
readPaneLogTail,
|
|
48
48
|
resetRestartCount,
|
|
49
49
|
resolveClaudeBinary,
|
|
50
|
+
rotateSessionForWedge,
|
|
50
51
|
sanitizeMcpJson,
|
|
51
52
|
sendToAgent,
|
|
52
53
|
sessionTranscriptDir,
|
|
@@ -55,7 +56,7 @@ import {
|
|
|
55
56
|
stopPersistentSession,
|
|
56
57
|
takeWatchdogGiveUpCount,
|
|
57
58
|
takeZombieDetection
|
|
58
|
-
} from "../chunk-
|
|
59
|
+
} from "../chunk-IUN5LBTQ.js";
|
|
59
60
|
import {
|
|
60
61
|
KANBAN_CHECK_COMMAND,
|
|
61
62
|
SUPPRESS_SENTINEL,
|
|
@@ -3076,6 +3077,53 @@ function clearAgentState(agentId, codeName) {
|
|
|
3076
3077
|
return channelCacheMutated;
|
|
3077
3078
|
}
|
|
3078
3079
|
|
|
3080
|
+
// src/lib/wedge-detection.ts
|
|
3081
|
+
var DEFAULTS = {
|
|
3082
|
+
inboundWaitSeconds: 120,
|
|
3083
|
+
inboundHardWaitSeconds: 300,
|
|
3084
|
+
paneStaleSeconds: 120,
|
|
3085
|
+
minCycles: 3
|
|
3086
|
+
};
|
|
3087
|
+
function parseMode(raw) {
|
|
3088
|
+
const v = (raw ?? "").trim().toLowerCase();
|
|
3089
|
+
return v === "shadow" || v === "enforce" ? v : "off";
|
|
3090
|
+
}
|
|
3091
|
+
function parsePositiveInt(raw, fallback, floor) {
|
|
3092
|
+
const n = raw ? Number.parseInt(raw, 10) : NaN;
|
|
3093
|
+
return Number.isInteger(n) && n >= floor ? n : fallback;
|
|
3094
|
+
}
|
|
3095
|
+
function resolveWedgeConfig(env = process.env) {
|
|
3096
|
+
const inboundWaitSeconds = parsePositiveInt(
|
|
3097
|
+
env.AGT_WEDGE_INBOUND_WAIT_SECONDS,
|
|
3098
|
+
DEFAULTS.inboundWaitSeconds,
|
|
3099
|
+
30
|
|
3100
|
+
);
|
|
3101
|
+
const inboundHardWaitSeconds = Math.max(
|
|
3102
|
+
inboundWaitSeconds,
|
|
3103
|
+
parsePositiveInt(env.AGT_WEDGE_INBOUND_HARD_WAIT_SECONDS, DEFAULTS.inboundHardWaitSeconds, 30)
|
|
3104
|
+
);
|
|
3105
|
+
return {
|
|
3106
|
+
mode: parseMode(env.AGT_WEDGE_RESTART_MODE),
|
|
3107
|
+
inboundWaitSeconds,
|
|
3108
|
+
inboundHardWaitSeconds,
|
|
3109
|
+
paneStaleSeconds: parsePositiveInt(env.AGT_WEDGE_PANE_STALE_SECONDS, DEFAULTS.paneStaleSeconds, 30),
|
|
3110
|
+
minCycles: parsePositiveInt(env.AGT_WEDGE_MIN_CYCLES, DEFAULTS.minCycles, 2)
|
|
3111
|
+
};
|
|
3112
|
+
}
|
|
3113
|
+
function isWedgeCandidateCycle(signals, config2) {
|
|
3114
|
+
const inboundAge = signals.pendingInboundOldestAgeSeconds;
|
|
3115
|
+
if (inboundAge === null) return false;
|
|
3116
|
+
if (inboundAge < config2.inboundWaitSeconds) return false;
|
|
3117
|
+
if (inboundAge >= config2.inboundHardWaitSeconds) return true;
|
|
3118
|
+
const paneAge = signals.paneActivityAgeSeconds;
|
|
3119
|
+
const paneAdvancing = paneAge !== null && paneAge < config2.paneStaleSeconds;
|
|
3120
|
+
return !paneAdvancing;
|
|
3121
|
+
}
|
|
3122
|
+
function decideWedgeRestart(input, config2) {
|
|
3123
|
+
if (!isWedgeCandidateCycle(input, config2)) return "none";
|
|
3124
|
+
return input.consecutiveWedgeCycles >= config2.minCycles ? "wedged" : "none";
|
|
3125
|
+
}
|
|
3126
|
+
|
|
3079
3127
|
// src/lib/restart-flags.ts
|
|
3080
3128
|
import { existsSync as existsSync4, mkdirSync as mkdirSync3, readdirSync as readdirSync3, readFileSync as readFileSync8, renameSync as renameSync2, rmSync, writeFileSync as writeFileSync3 } from "fs";
|
|
3081
3129
|
import { homedir as homedir3 } from "os";
|
|
@@ -3789,6 +3837,7 @@ var autoResumeInFlight = /* @__PURE__ */ new Set();
|
|
|
3789
3837
|
var AUTO_RESUME_SELF_WINDOW_MS = 12e4;
|
|
3790
3838
|
var autoResumeLoggedSkips = /* @__PURE__ */ new Map();
|
|
3791
3839
|
var autoResumeStandDowns = /* @__PURE__ */ new Set();
|
|
3840
|
+
var killPausedCodeNames = /* @__PURE__ */ new Set();
|
|
3792
3841
|
function maybeAutoResume(agent) {
|
|
3793
3842
|
const codeName = agent.code_name;
|
|
3794
3843
|
if (autoResumeInFlight.has(codeName)) return;
|
|
@@ -3875,6 +3924,7 @@ function cancelPendingSessionRestart(codeName) {
|
|
|
3875
3924
|
}
|
|
3876
3925
|
var RESTART_DEFER_RECHECK_MS = 6e4;
|
|
3877
3926
|
var lastInboundMs = /* @__PURE__ */ new Map();
|
|
3927
|
+
var consecutiveWedgeCycles = /* @__PURE__ */ new Map();
|
|
3878
3928
|
function noteInbound(codeName) {
|
|
3879
3929
|
lastInboundMs.set(codeName, Date.now());
|
|
3880
3930
|
}
|
|
@@ -4173,7 +4223,7 @@ var cachedMaintenanceWindow = null;
|
|
|
4173
4223
|
var lastVersionCheckAt = 0;
|
|
4174
4224
|
var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
|
|
4175
4225
|
var lastResponsivenessProbeAt = 0;
|
|
4176
|
-
var agtCliVersion = true ? "0.27.
|
|
4226
|
+
var agtCliVersion = true ? "0.27.115" : "dev";
|
|
4177
4227
|
function resolveBrewPath(execFileSync4) {
|
|
4178
4228
|
try {
|
|
4179
4229
|
const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
|
|
@@ -5366,7 +5416,7 @@ async function pollCycle() {
|
|
|
5366
5416
|
}
|
|
5367
5417
|
try {
|
|
5368
5418
|
const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
|
|
5369
|
-
const { collectDiagnostics } = await import("../persistent-session-
|
|
5419
|
+
const { collectDiagnostics } = await import("../persistent-session-PIR45QFL.js");
|
|
5370
5420
|
const diagCodeNames = [...agentState.persistentSessionAgents];
|
|
5371
5421
|
const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
|
|
5372
5422
|
let tailscaleHostname;
|
|
@@ -5453,12 +5503,12 @@ async function pollCycle() {
|
|
|
5453
5503
|
const {
|
|
5454
5504
|
collectResponsivenessProbes,
|
|
5455
5505
|
getResponsivenessIntervalMs
|
|
5456
|
-
} = await import("../responsiveness-probe-
|
|
5506
|
+
} = await import("../responsiveness-probe-FLQZ7E5H.js");
|
|
5457
5507
|
const probeIntervalMs = getResponsivenessIntervalMs();
|
|
5458
5508
|
if (now - lastResponsivenessProbeAt > probeIntervalMs) {
|
|
5459
5509
|
const probeCodeNames = [...agentState.persistentSessionAgents];
|
|
5460
5510
|
if (probeCodeNames.length > 0) {
|
|
5461
|
-
const { takeAcpxExecFailureCount, creditAcpxExecFailureCount } = await import("../persistent-session-
|
|
5511
|
+
const { takeAcpxExecFailureCount, creditAcpxExecFailureCount } = await import("../persistent-session-PIR45QFL.js");
|
|
5462
5512
|
const drainedGiveUps = /* @__PURE__ */ new Map();
|
|
5463
5513
|
const drainedAcpxFailures = /* @__PURE__ */ new Map();
|
|
5464
5514
|
const probes = collectResponsivenessProbes(probeCodeNames).map((p) => {
|
|
@@ -5485,6 +5535,58 @@ async function pollCycle() {
|
|
|
5485
5535
|
} catch (err) {
|
|
5486
5536
|
log(`[responsiveness-probe] collection failed: ${err.message}`);
|
|
5487
5537
|
}
|
|
5538
|
+
try {
|
|
5539
|
+
const wedgeConfig = resolveWedgeConfig();
|
|
5540
|
+
if (wedgeConfig.mode !== "off") {
|
|
5541
|
+
const { collectResponsivenessProbes } = await import("../responsiveness-probe-FLQZ7E5H.js");
|
|
5542
|
+
const liveAgents = agentState.persistentSessionAgents;
|
|
5543
|
+
for (const tracked of consecutiveWedgeCycles.keys()) {
|
|
5544
|
+
if (!liveAgents.has(tracked)) consecutiveWedgeCycles.delete(tracked);
|
|
5545
|
+
}
|
|
5546
|
+
for (const probe of collectResponsivenessProbes([...liveAgents])) {
|
|
5547
|
+
const codeName = probe.code_name;
|
|
5548
|
+
if (!isSessionHealthy(codeName)) {
|
|
5549
|
+
consecutiveWedgeCycles.delete(codeName);
|
|
5550
|
+
continue;
|
|
5551
|
+
}
|
|
5552
|
+
const signals = {
|
|
5553
|
+
paneActivityAgeSeconds: probe.pane_activity_age_seconds,
|
|
5554
|
+
pendingInboundOldestAgeSeconds: probe.pending_inbound_oldest_age_seconds ?? null
|
|
5555
|
+
};
|
|
5556
|
+
if (!isWedgeCandidateCycle(signals, wedgeConfig)) {
|
|
5557
|
+
consecutiveWedgeCycles.delete(codeName);
|
|
5558
|
+
continue;
|
|
5559
|
+
}
|
|
5560
|
+
const streak = (consecutiveWedgeCycles.get(codeName) ?? 0) + 1;
|
|
5561
|
+
consecutiveWedgeCycles.set(codeName, streak);
|
|
5562
|
+
if (decideWedgeRestart({ ...signals, consecutiveWedgeCycles: streak }, wedgeConfig) !== "wedged") {
|
|
5563
|
+
continue;
|
|
5564
|
+
}
|
|
5565
|
+
const detail = `agent=${codeName} paneAge=${signals.paneActivityAgeSeconds}s inboundAge=${signals.pendingInboundOldestAgeSeconds}s cycles=${streak}`;
|
|
5566
|
+
if (wedgeConfig.mode === "shadow") {
|
|
5567
|
+
if (streak === wedgeConfig.minCycles) {
|
|
5568
|
+
log(`[wedge] SHADOW would force-fresh respawn ${detail}`);
|
|
5569
|
+
}
|
|
5570
|
+
continue;
|
|
5571
|
+
}
|
|
5572
|
+
try {
|
|
5573
|
+
const newId = rotateSessionForWedge(codeName);
|
|
5574
|
+
try {
|
|
5575
|
+
const { execSync: es } = await import("child_process");
|
|
5576
|
+
es(`tmux kill-session -t agt-${codeName} 2>/dev/null`, { stdio: "ignore" });
|
|
5577
|
+
} catch {
|
|
5578
|
+
}
|
|
5579
|
+
stopPersistentSessionAndForgetMcpBaseline(codeName);
|
|
5580
|
+
consecutiveWedgeCycles.delete(codeName);
|
|
5581
|
+
log(`[wedge] forced fresh respawn ${detail} \u2192 new session ${newId} (transcript preserved)`);
|
|
5582
|
+
} catch (err) {
|
|
5583
|
+
log(`[wedge] force-fresh respawn failed for ${codeName}: ${err.message}`);
|
|
5584
|
+
}
|
|
5585
|
+
}
|
|
5586
|
+
}
|
|
5587
|
+
} catch (err) {
|
|
5588
|
+
log(`[wedge] detection failed: ${err.message}`);
|
|
5589
|
+
}
|
|
5488
5590
|
try {
|
|
5489
5591
|
const { scrapeMcpFailedBannerCount } = await import("../pane-mcp-banner-scraper-JA437JIB.js");
|
|
5490
5592
|
const observations = [];
|
|
@@ -5818,6 +5920,16 @@ async function processAgent(agent, agentStates) {
|
|
|
5818
5920
|
if (previousKnownStatus !== agent.status) {
|
|
5819
5921
|
log(`Agent '${agent.code_name}' is ${agent.status}, skipping provisioning`);
|
|
5820
5922
|
}
|
|
5923
|
+
if (agent.kill_switch) {
|
|
5924
|
+
killPausedCodeNames.add(agent.code_name);
|
|
5925
|
+
if (previousKnownStatus !== agent.status) {
|
|
5926
|
+
log(
|
|
5927
|
+
`[kill-switch] '${agent.code_name}' halted by ${agent.kill_switch.scope ?? "unknown"} kill switch` + (agent.kill_switch.reason ? ` (reason: ${agent.kill_switch.reason})` : "") + ` source=${agent.kill_switch.source ?? "unknown"}`
|
|
5928
|
+
);
|
|
5929
|
+
}
|
|
5930
|
+
} else if (killPausedCodeNames.delete(agent.code_name)) {
|
|
5931
|
+
log(`[kill-switch] '${agent.code_name}' kill switch cleared while still ${agent.status} (no resume \u2014 paused for another reason)`);
|
|
5932
|
+
}
|
|
5821
5933
|
await stopGatewayIfRunning(agent.code_name, adapter);
|
|
5822
5934
|
stopPersistentSessionAndForgetMcpBaseline(agent.code_name);
|
|
5823
5935
|
try {
|
|
@@ -5826,7 +5938,7 @@ async function processAgent(agent, agentStates) {
|
|
|
5826
5938
|
log(`Killed tmux session for paused agent '${agent.code_name}'`);
|
|
5827
5939
|
} catch {
|
|
5828
5940
|
}
|
|
5829
|
-
if (agent.status === "paused") {
|
|
5941
|
+
if (agent.status === "paused" && !agent.kill_switch) {
|
|
5830
5942
|
maybeAutoResume(agent);
|
|
5831
5943
|
}
|
|
5832
5944
|
agentStates.push({
|
|
@@ -5932,6 +6044,16 @@ async function processAgent(agent, agentStates) {
|
|
|
5932
6044
|
log(`[auto-resume] Cleared auto-resume marker for '${agent.code_name}' on operator resume \u2014 credit re-armed (ENG-6088)`);
|
|
5933
6045
|
}
|
|
5934
6046
|
}
|
|
6047
|
+
if (previousStatus === "paused" && agent.status === "active" && killPausedCodeNames.delete(agent.code_name)) {
|
|
6048
|
+
log(`[kill-switch] '${agent.code_name}' kill switch cleared \u2014 resuming session`);
|
|
6049
|
+
void injectMessage(
|
|
6050
|
+
agent.code_name,
|
|
6051
|
+
"system",
|
|
6052
|
+
"The kill switch that halted you has been cleared. Your session is resuming.",
|
|
6053
|
+
{ task_name: "kill-switch-resume" },
|
|
6054
|
+
log
|
|
6055
|
+
).catch(() => false);
|
|
6056
|
+
}
|
|
5935
6057
|
let channelCacheMutated = false;
|
|
5936
6058
|
for (const key of agentState.knownChannelConfigHashes.keys()) {
|
|
5937
6059
|
if (key.startsWith(`${agent.agent_id}:`)) {
|
|
@@ -9834,7 +9956,7 @@ async function processClaudePairSessions(agents) {
|
|
|
9834
9956
|
killPairSession,
|
|
9835
9957
|
pairTmuxSession,
|
|
9836
9958
|
finalizeClaudePairOnboarding
|
|
9837
|
-
} = await import("../claude-pair-runtime-
|
|
9959
|
+
} = await import("../claude-pair-runtime-UX7GWW3O.js");
|
|
9838
9960
|
for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
|
|
9839
9961
|
log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
|
|
9840
9962
|
const killed = await killPairSession(pairTmuxSession(pairId));
|