@integrity-labs/agt-cli 0.28.410 → 0.28.412
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-QZEA7FWB.js → chunk-5ES25OE6.js} +3 -3
- package/dist/{chunk-YLLK4G3B.js → chunk-QZUKHEMO.js} +107 -3
- package/dist/chunk-QZUKHEMO.js.map +1 -0
- package/dist/{claude-pair-runtime-XGPENQB7.js → claude-pair-runtime-BMYJSZIZ.js} +2 -2
- package/dist/lib/manager-worker.js +15 -12
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/{persistent-session-W5QSIM7F.js → persistent-session-EDUFOS36.js} +2 -2
- package/dist/{responsiveness-probe-B7XCQQN4.js → responsiveness-probe-SVTUFKX5.js} +2 -2
- package/package.json +1 -1
- package/dist/chunk-YLLK4G3B.js.map +0 -1
- /package/dist/{chunk-QZEA7FWB.js.map → chunk-5ES25OE6.js.map} +0 -0
- /package/dist/{claude-pair-runtime-XGPENQB7.js.map → claude-pair-runtime-BMYJSZIZ.js.map} +0 -0
- /package/dist/{persistent-session-W5QSIM7F.js.map → persistent-session-EDUFOS36.js.map} +0 -0
- /package/dist/{responsiveness-probe-B7XCQQN4.js.map → responsiveness-probe-SVTUFKX5.js.map} +0 -0
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-5ES25OE6.js";
|
|
44
44
|
import {
|
|
45
45
|
AnchorSessionClient,
|
|
46
46
|
CHANNEL_REGISTRY,
|
|
@@ -70,7 +70,7 @@ import {
|
|
|
70
70
|
renderTemplate,
|
|
71
71
|
resolveChannels,
|
|
72
72
|
serializeManifestForSlackCli
|
|
73
|
-
} from "../chunk-
|
|
73
|
+
} from "../chunk-QZUKHEMO.js";
|
|
74
74
|
import "../chunk-XWVM4KPK.js";
|
|
75
75
|
|
|
76
76
|
// src/bin/agt.ts
|
|
@@ -4829,7 +4829,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4829
4829
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4830
4830
|
import chalk18 from "chalk";
|
|
4831
4831
|
import ora16 from "ora";
|
|
4832
|
-
var cliVersion = true ? "0.28.
|
|
4832
|
+
var cliVersion = true ? "0.28.412" : "dev";
|
|
4833
4833
|
async function fetchLatestVersion() {
|
|
4834
4834
|
const host2 = getHost();
|
|
4835
4835
|
if (!host2) return null;
|
|
@@ -6001,7 +6001,7 @@ function handleError(err) {
|
|
|
6001
6001
|
}
|
|
6002
6002
|
|
|
6003
6003
|
// src/bin/agt.ts
|
|
6004
|
-
var cliVersion2 = true ? "0.28.
|
|
6004
|
+
var cliVersion2 = true ? "0.28.412" : "dev";
|
|
6005
6005
|
var program = new Command();
|
|
6006
6006
|
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");
|
|
6007
6007
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -25,7 +25,7 @@ import {
|
|
|
25
25
|
resolveConnectivityProbe,
|
|
26
26
|
worseConnectivityOutcome,
|
|
27
27
|
wrapScheduledTaskPrompt
|
|
28
|
-
} from "./chunk-
|
|
28
|
+
} from "./chunk-QZUKHEMO.js";
|
|
29
29
|
import {
|
|
30
30
|
parsePsRows
|
|
31
31
|
} from "./chunk-XWVM4KPK.js";
|
|
@@ -6247,7 +6247,7 @@ function requireHost() {
|
|
|
6247
6247
|
}
|
|
6248
6248
|
|
|
6249
6249
|
// src/lib/api-client.ts
|
|
6250
|
-
var agtCliVersion = true ? "0.28.
|
|
6250
|
+
var agtCliVersion = true ? "0.28.412" : "dev";
|
|
6251
6251
|
var lastConfigHash = null;
|
|
6252
6252
|
function setConfigHash(hash) {
|
|
6253
6253
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -8751,4 +8751,4 @@ export {
|
|
|
8751
8751
|
managerInstallSystemUnitCommand,
|
|
8752
8752
|
managerUninstallSystemUnitCommand
|
|
8753
8753
|
};
|
|
8754
|
-
//# sourceMappingURL=chunk-
|
|
8754
|
+
//# sourceMappingURL=chunk-5ES25OE6.js.map
|
|
@@ -10242,10 +10242,65 @@ async function execFilePromiseLong(cmd, args, opts) {
|
|
|
10242
10242
|
});
|
|
10243
10243
|
}
|
|
10244
10244
|
|
|
10245
|
+
// src/lib/turn-outcome-tracker.ts
|
|
10246
|
+
function isFailure(outcome) {
|
|
10247
|
+
return outcome === "no_reply" || outcome === "failed";
|
|
10248
|
+
}
|
|
10249
|
+
function emptyHealth() {
|
|
10250
|
+
return { lastOutcome: null, lastRepliedAt: null, lastAttemptAt: null, consecutiveFailures: 0 };
|
|
10251
|
+
}
|
|
10252
|
+
var DEFAULT_TURN_FAILURE_WARN_THRESHOLD = 3;
|
|
10253
|
+
var TurnOutcomeTracker = class {
|
|
10254
|
+
health = /* @__PURE__ */ new Map();
|
|
10255
|
+
warned = /* @__PURE__ */ new Set();
|
|
10256
|
+
threshold;
|
|
10257
|
+
constructor(threshold = DEFAULT_TURN_FAILURE_WARN_THRESHOLD) {
|
|
10258
|
+
if (!Number.isInteger(threshold) || threshold < 1) {
|
|
10259
|
+
throw new Error(`turn-outcome threshold must be an integer >= 1 (got ${threshold})`);
|
|
10260
|
+
}
|
|
10261
|
+
this.threshold = threshold;
|
|
10262
|
+
}
|
|
10263
|
+
/** Record one observed turn outcome for one agent. */
|
|
10264
|
+
record(codeName, outcome, now = Date.now()) {
|
|
10265
|
+
const current = this.health.get(codeName) ?? emptyHealth();
|
|
10266
|
+
const next = {
|
|
10267
|
+
lastOutcome: outcome,
|
|
10268
|
+
lastAttemptAt: now,
|
|
10269
|
+
lastRepliedAt: outcome === "replied" ? now : current.lastRepliedAt,
|
|
10270
|
+
// Only a real reply clears the streak. A `declined` or a fire-and-forget
|
|
10271
|
+
// `admitted` leaves it exactly where it was: neither proves the agent can
|
|
10272
|
+
// answer, so neither should be able to mask an ongoing wedge.
|
|
10273
|
+
consecutiveFailures: isFailure(outcome) ? current.consecutiveFailures + 1 : outcome === "replied" ? 0 : current.consecutiveFailures
|
|
10274
|
+
};
|
|
10275
|
+
this.health.set(codeName, next);
|
|
10276
|
+
if (outcome === "replied") {
|
|
10277
|
+
const wasWarned = this.warned.delete(codeName);
|
|
10278
|
+
return { health: next, shouldWarn: false, recovered: wasWarned };
|
|
10279
|
+
}
|
|
10280
|
+
const crossed = next.consecutiveFailures >= this.threshold && !this.warned.has(codeName);
|
|
10281
|
+
if (crossed) this.warned.add(codeName);
|
|
10282
|
+
return { health: next, shouldWarn: crossed, recovered: false };
|
|
10283
|
+
}
|
|
10284
|
+
/** Current turn health for an agent, or null if no turn has been observed. */
|
|
10285
|
+
get(codeName) {
|
|
10286
|
+
return this.health.get(codeName) ?? null;
|
|
10287
|
+
}
|
|
10288
|
+
/**
|
|
10289
|
+
* Drop all state for an agent. Called when its serve is torn down, so a fresh
|
|
10290
|
+
* serve is not born already carrying the dead one's failure streak.
|
|
10291
|
+
*/
|
|
10292
|
+
reset(codeName) {
|
|
10293
|
+
this.health.delete(codeName);
|
|
10294
|
+
this.warned.delete(codeName);
|
|
10295
|
+
}
|
|
10296
|
+
};
|
|
10297
|
+
|
|
10245
10298
|
// src/lib/opencode-session.ts
|
|
10246
10299
|
var OPENCODE_BIN = process.env["AGT_OPENCODE_BIN"]?.trim() || "opencode";
|
|
10247
10300
|
var OPENCODE_RUN_TIMEOUT_MS = Number(process.env["AGT_OPENCODE_RUN_TIMEOUT_MS"]) || 18e4;
|
|
10248
10301
|
var sessions = /* @__PURE__ */ new Map();
|
|
10302
|
+
var loggers = /* @__PURE__ */ new Map();
|
|
10303
|
+
var turnOutcomeTracker = new TurnOutcomeTracker();
|
|
10249
10304
|
var bridges = /* @__PURE__ */ new Map();
|
|
10250
10305
|
function opencodeTmuxSession(codeName) {
|
|
10251
10306
|
return `agt-oc-${codeName}`;
|
|
@@ -10425,7 +10480,19 @@ function findFreePort() {
|
|
|
10425
10480
|
}
|
|
10426
10481
|
async function startOpencodeSession(config) {
|
|
10427
10482
|
const { codeName, log: log2 } = config;
|
|
10483
|
+
loggers.set(codeName, log2);
|
|
10428
10484
|
const existing = sessions.get(codeName);
|
|
10485
|
+
if (existing && existing.status === "running" && !isOpencodeSessionHealthy(codeName)) {
|
|
10486
|
+
log2(
|
|
10487
|
+
`[opencode-session] '${codeName}' stopped out-of-band (tmux session gone, in-memory state pinned to port ${existing.port ?? "?"}) \u2014 respawning on a fresh port (ENG-7995)`
|
|
10488
|
+
);
|
|
10489
|
+
existing.status = "crashed";
|
|
10490
|
+
existing.restartCount++;
|
|
10491
|
+
existing.port = null;
|
|
10492
|
+
existing.password = null;
|
|
10493
|
+
bridges.delete(codeName);
|
|
10494
|
+
stopTranscriptRefresher(codeName);
|
|
10495
|
+
}
|
|
10429
10496
|
if (existing && existing.status === "running") return existing;
|
|
10430
10497
|
const restartCount = existing?.restartCount ?? 0;
|
|
10431
10498
|
if (existing?.status === "crashed" && existing.startedAt) {
|
|
@@ -10574,7 +10641,29 @@ async function injectOpencodeMessage(codeName, msg, opts = {}) {
|
|
|
10574
10641
|
return { status: "declined", reason: "server_not_running" };
|
|
10575
10642
|
}
|
|
10576
10643
|
const bridge = getBridge(codeName, session.port, session.password);
|
|
10577
|
-
|
|
10644
|
+
try {
|
|
10645
|
+
const result = await bridge.handleInbound(msg, { gate: opts.gate, awaitReply: opts.awaitReply });
|
|
10646
|
+
const outcome = result.status === "declined" ? "declined" : result.status === "replied" && result.reply ? "replied" : opts.awaitReply === false ? "admitted" : "no_reply";
|
|
10647
|
+
noteOpencodeTurnOutcome(codeName, outcome, session);
|
|
10648
|
+
return result;
|
|
10649
|
+
} catch (err) {
|
|
10650
|
+
noteOpencodeTurnOutcome(codeName, "failed", session);
|
|
10651
|
+
throw err;
|
|
10652
|
+
}
|
|
10653
|
+
}
|
|
10654
|
+
function noteOpencodeTurnOutcome(codeName, outcome, startedOn) {
|
|
10655
|
+
if (sessions.get(codeName) !== startedOn || startedOn.status !== "running") return;
|
|
10656
|
+
const { health, shouldWarn, recovered } = turnOutcomeTracker.record(codeName, outcome);
|
|
10657
|
+
const log2 = loggers.get(codeName);
|
|
10658
|
+
if (!log2) return;
|
|
10659
|
+
if (shouldWarn) {
|
|
10660
|
+
const lastOk = health.lastRepliedAt ? `${Math.round((Date.now() - health.lastRepliedAt) / 1e3)}s ago` : "never";
|
|
10661
|
+
log2(
|
|
10662
|
+
`[turn-health] WARN: '${codeName}' has ${health.consecutiveFailures} consecutive turns with no reply (last successful turn: ${lastOk}; serve process alive=${isOpencodeSessionHealthy(codeName)}) \u2014 the serve is up but not completing turns (ENG-7996)`
|
|
10663
|
+
);
|
|
10664
|
+
} else if (recovered) {
|
|
10665
|
+
log2(`[turn-health] '${codeName}' completed a turn again after a no-reply streak (ENG-7996)`);
|
|
10666
|
+
}
|
|
10578
10667
|
}
|
|
10579
10668
|
function getBridge(codeName, port, password) {
|
|
10580
10669
|
const cached = bridges.get(codeName);
|
|
@@ -10658,6 +10747,8 @@ function stopOpencodeSession(codeName, log2) {
|
|
|
10658
10747
|
}
|
|
10659
10748
|
stopTranscriptRefresher(codeName);
|
|
10660
10749
|
bridges.delete(codeName);
|
|
10750
|
+
turnOutcomeTracker.reset(codeName);
|
|
10751
|
+
loggers.delete(codeName);
|
|
10661
10752
|
const session = sessions.get(codeName);
|
|
10662
10753
|
if (session) {
|
|
10663
10754
|
session.status = "stopped";
|
|
@@ -10668,6 +10759,9 @@ function stopOpencodeSession(codeName, log2) {
|
|
|
10668
10759
|
function getOpencodeSessionState(codeName) {
|
|
10669
10760
|
return sessions.get(codeName) ?? null;
|
|
10670
10761
|
}
|
|
10762
|
+
function getOpencodeTurnHealth(codeName) {
|
|
10763
|
+
return turnOutcomeTracker.get(codeName);
|
|
10764
|
+
}
|
|
10671
10765
|
function stripUndefined(env2) {
|
|
10672
10766
|
const out = {};
|
|
10673
10767
|
for (const [k, v] of Object.entries(env2)) if (v !== void 0) out[k] = v;
|
|
@@ -12254,6 +12348,7 @@ function collectDiagnostics(codeNames, quarantineEntriesFor) {
|
|
|
12254
12348
|
if (oc) {
|
|
12255
12349
|
const serveAlive = isOpencodeSessionHealthy(codeName);
|
|
12256
12350
|
const status = serveAlive ? oc.status : oc.status === "running" ? "crashed" : oc.status;
|
|
12351
|
+
const turn = getOpencodeTurnHealth(codeName);
|
|
12257
12352
|
return {
|
|
12258
12353
|
codeName,
|
|
12259
12354
|
framework: "opencode",
|
|
@@ -12267,7 +12362,15 @@ function collectDiagnostics(codeNames, quarantineEntriesFor) {
|
|
|
12267
12362
|
launchArgs: null,
|
|
12268
12363
|
channelStatus: null,
|
|
12269
12364
|
isolated: isolationMode(codeName) === "docker",
|
|
12270
|
-
quarantinedChannels
|
|
12365
|
+
quarantinedChannels,
|
|
12366
|
+
...turn ? {
|
|
12367
|
+
turnHealth: {
|
|
12368
|
+
lastOutcome: turn.lastOutcome,
|
|
12369
|
+
lastRepliedAt: turn.lastRepliedAt ? new Date(turn.lastRepliedAt).toISOString() : null,
|
|
12370
|
+
lastAttemptAt: turn.lastAttemptAt ? new Date(turn.lastAttemptAt).toISOString() : null,
|
|
12371
|
+
consecutiveFailures: turn.consecutiveFailures
|
|
12372
|
+
}
|
|
12373
|
+
} : {}
|
|
12271
12374
|
};
|
|
12272
12375
|
}
|
|
12273
12376
|
const session = sessions2.get(codeName);
|
|
@@ -12454,6 +12557,7 @@ export {
|
|
|
12454
12557
|
isOpencodeSessionHealthy,
|
|
12455
12558
|
injectOpencodeMessage,
|
|
12456
12559
|
stopOpencodeSession,
|
|
12560
|
+
getOpencodeSessionState,
|
|
12457
12561
|
sessionTranscriptDir,
|
|
12458
12562
|
transcriptActivityAgeSeconds,
|
|
12459
12563
|
subagentActivityAgeSeconds,
|
|
@@ -12502,4 +12606,4 @@ export {
|
|
|
12502
12606
|
stopAllSessionsAndWait,
|
|
12503
12607
|
getProjectDir
|
|
12504
12608
|
};
|
|
12505
|
-
//# sourceMappingURL=chunk-
|
|
12609
|
+
//# sourceMappingURL=chunk-QZUKHEMO.js.map
|