@integrity-labs/agt-cli 0.28.416 → 0.28.418
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-73XZ5UZO.js → chunk-4OLSHG7F.js} +10 -10
- package/dist/chunk-4OLSHG7F.js.map +1 -0
- package/dist/{chunk-QZUKHEMO.js → chunk-IE7ZJKF3.js} +89 -4
- package/dist/chunk-IE7ZJKF3.js.map +1 -0
- package/dist/{claude-pair-runtime-BMYJSZIZ.js → claude-pair-runtime-CYJFIF2Z.js} +2 -2
- package/dist/lib/manager-worker.js +21 -11
- package/dist/lib/manager-worker.js.map +1 -1
- package/dist/mcp/direct-chat-channel.js +17 -2
- package/dist/mcp/origami.js +17 -2
- package/dist/mcp/slack-channel.js +17 -2
- package/dist/mcp/telegram-channel.js +17 -2
- package/dist/{persistent-session-EDUFOS36.js → persistent-session-B7E5ZX2C.js} +2 -2
- package/dist/{responsiveness-probe-SVTUFKX5.js → responsiveness-probe-NQIEWYTJ.js} +54 -29
- package/dist/responsiveness-probe-NQIEWYTJ.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-73XZ5UZO.js.map +0 -1
- package/dist/chunk-QZUKHEMO.js.map +0 -1
- package/dist/responsiveness-probe-SVTUFKX5.js.map +0 -1
- /package/dist/{claude-pair-runtime-BMYJSZIZ.js.map → claude-pair-runtime-CYJFIF2Z.js.map} +0 -0
- /package/dist/{persistent-session-EDUFOS36.js.map → persistent-session-B7E5ZX2C.js.map} +0 -0
|
@@ -8054,9 +8054,9 @@ var FLAG_REGISTRY = [
|
|
|
8054
8054
|
},
|
|
8055
8055
|
{
|
|
8056
8056
|
key: "compaction-notice",
|
|
8057
|
-
description: 'Compaction courtesy notice (ENG-7339): when a managed Claude Code session compacts its context, the persistent session pauses and stops replying for a stretch, which looks identical to a dead agent from the channel. When ON, the generated PreCompact hook finds the conversation the user is actively on (the last <channel ...> tag in the transcript) and drops a notice into the matching <channel>-notice-outbox; the channel MCP server (alive while the Claude process compacts) posts a short "reorganizing my memory, back shortly" line. The notice path never clears the pending-inbound marker, so the genuine reply the agent still owes after compaction is unaffected. No active channel tag \u21D2 silent (idle agents never broadcast).
|
|
8057
|
+
description: 'Compaction courtesy notice (ENG-7339): when a managed Claude Code session compacts its context, the persistent session pauses and stops replying for a stretch, which looks identical to a dead agent from the channel. When ON, the generated PreCompact hook finds the conversation the user is actively on (the last <channel ...> tag in the transcript) and drops a notice into the matching <channel>-notice-outbox; the channel MCP server (alive while the Claude process compacts) posts a short "reorganizing my memory, back shortly" line. The notice path never clears the pending-inbound marker, so the genuine reply the agent still owes after compaction is unaffected. No active channel tag \u21D2 silent (idle agents never broadcast). Default ON (ENG-8040: introduced dark on 2026-07-23 via ENG-7339, never activated in prod; Brad Bond reported Sherlock went silent mid-compaction with no notice). Set AGT_COMPACTION_NOTICE_ENABLED=false or override via the Feature Flags admin page to disable per-host. When OFF the hook writes nothing and the consumer drops any stray notice unsent.',
|
|
8058
8058
|
flagType: "boolean",
|
|
8059
|
-
defaultValue:
|
|
8059
|
+
defaultValue: true,
|
|
8060
8060
|
envVar: "AGT_COMPACTION_NOTICE_ENABLED"
|
|
8061
8061
|
},
|
|
8062
8062
|
{
|
|
@@ -8230,6 +8230,21 @@ var FLAG_REGISTRY = [
|
|
|
8230
8230
|
// AGT_CONV_EVAL_BACKEND keeps that value until the env var is retired.
|
|
8231
8231
|
envVar: "AGT_CONV_EVAL_BACKEND"
|
|
8232
8232
|
},
|
|
8233
|
+
{
|
|
8234
|
+
key: "synthetic-probe-enabled",
|
|
8235
|
+
description: 'Global gate for the agent synthetic-liveness cron (ENG-8074). When OFF, the cron exits after reading the flag \u2014 no probes sent, no metrics emitted, no CloudWatch alarms fired, near-zero DB footprint. Ships dark (OFF) because the probe cron was generating false positives (probe_timeout on angie for 7+ days while healthy, ENG-8048) and had open cron_invocation_errors alarms (since 2026-07-23). Flip ON per-environment via the admin Feature Flags page once the reliability issues are resolved. The existing AUGMENTED_SYNTHETIC_PROBE_ENABLED env var is the declared envVar for this flag (ADR-0022): set it to "true"/"1" to force-enable (env takes precedence over the DB stage value), or "false"/"0" to force-disable without a DB lookup. Evaluated as a global stage value by the central cron (no per-org targeting). Boolean gate.',
|
|
8236
|
+
flagType: "boolean",
|
|
8237
|
+
// Safe/dark default: false = probe off. This encodes the ENG-8074 intent (disable
|
|
8238
|
+
// in prod until reliability issues are resolved) and is the fail-safe direction for
|
|
8239
|
+
// a flag-DB read error — a hiccup degrades to keeping the cron dormant rather than
|
|
8240
|
+
// silently re-arming a broken probe fleet-wide.
|
|
8241
|
+
// The env var AUGMENTED_SYNTHETIC_PROBE_ENABLED was the pre-flag emergency kill switch
|
|
8242
|
+
// (read as `!== 'false'`, so unset = probe ON). The flag inverts this: unset env var
|
|
8243
|
+
// now resolves to the flag default (OFF). Set AUGMENTED_SYNTHETIC_PROBE_ENABLED=true to
|
|
8244
|
+
// explicitly re-arm the probe via env, or flip the flag ON from the admin UI.
|
|
8245
|
+
defaultValue: false,
|
|
8246
|
+
envVar: "AUGMENTED_SYNTHETIC_PROBE_ENABLED"
|
|
8247
|
+
},
|
|
8233
8248
|
{
|
|
8234
8249
|
key: "synthetic-probe-on-metered-hosts",
|
|
8235
8250
|
description: "Synthetic liveness probing of OpenRouter-metered agents (ENG-7235). On a host whose claude_auth_mode='openrouter' every model call is per-token cost, so the hourly synthetic probe (a full inbound\u2192session\u2192model\u2192outbound round-trip whose only output is a probe_ack) is real spend for zero deliverable - unlike a Max-subscription host where it is effectively free. When OFF (default) the synthetic-probe cron skips OpenRouter-mode agents entirely; their liveness falls back to the zero-token signals (pane-activity ENG-5399 + manager heartbeat + inbound-loop liveness ENG-5614). When ON, metered agents are probed like every other agent (the pre-ENG-7235 behaviour) - the explicit opt-in for an operator who wants the end-to-end check and accepts the cost. Subscription / api_key hosts are unaffected either way. Evaluated as a global stage value by the central cron (no per-org targeting in v1). Boolean gate.",
|
|
@@ -10295,12 +10310,66 @@ var TurnOutcomeTracker = class {
|
|
|
10295
10310
|
}
|
|
10296
10311
|
};
|
|
10297
10312
|
|
|
10313
|
+
// src/lib/opencode-activity-tracker.ts
|
|
10314
|
+
var OpencodeActivityTracker = class {
|
|
10315
|
+
state = /* @__PURE__ */ new Map();
|
|
10316
|
+
entry(codeName) {
|
|
10317
|
+
let cur = this.state.get(codeName);
|
|
10318
|
+
if (!cur) {
|
|
10319
|
+
cur = { inFlight: 0, lastActiveAt: null };
|
|
10320
|
+
this.state.set(codeName, cur);
|
|
10321
|
+
}
|
|
10322
|
+
return cur;
|
|
10323
|
+
}
|
|
10324
|
+
/** A turn has been dispatched to the serve. Call BEFORE awaiting it. */
|
|
10325
|
+
beginTurn(codeName) {
|
|
10326
|
+
this.entry(codeName).inFlight += 1;
|
|
10327
|
+
}
|
|
10328
|
+
/**
|
|
10329
|
+
* A dispatched turn has resolved. Call in a `finally`, so a throw cannot
|
|
10330
|
+
* strand the agent permanently "busy" — a leaked in-flight count would pin
|
|
10331
|
+
* the age at 0 forever and bill the agent around the clock.
|
|
10332
|
+
*
|
|
10333
|
+
* `counted` is false for a gate decline: it occupied the agent for the
|
|
10334
|
+
* microseconds the gate took, and nothing more.
|
|
10335
|
+
*/
|
|
10336
|
+
endTurn(codeName, counted, now = Date.now()) {
|
|
10337
|
+
const cur = this.entry(codeName);
|
|
10338
|
+
cur.inFlight = Math.max(0, cur.inFlight - 1);
|
|
10339
|
+
if (counted) cur.lastActiveAt = now;
|
|
10340
|
+
}
|
|
10341
|
+
/**
|
|
10342
|
+
* Seconds since this agent was last doing work, or null if it never has been
|
|
10343
|
+
* in this manager generation.
|
|
10344
|
+
*
|
|
10345
|
+
* 0 while any turn is in flight — see the interval rationale above. Null is
|
|
10346
|
+
* "no signal", NOT "idle": the API omits the field entirely so a mixed-version
|
|
10347
|
+
* fleet cannot have a silent old CLI read as a busy agent (or vice versa).
|
|
10348
|
+
*/
|
|
10349
|
+
activityAgeSeconds(codeName, now = Date.now()) {
|
|
10350
|
+
const cur = this.state.get(codeName);
|
|
10351
|
+
if (!cur) return null;
|
|
10352
|
+
if (cur.inFlight > 0) return 0;
|
|
10353
|
+
if (cur.lastActiveAt == null) return null;
|
|
10354
|
+
return Math.max(0, Math.floor((now - cur.lastActiveAt) / 1e3));
|
|
10355
|
+
}
|
|
10356
|
+
/**
|
|
10357
|
+
* Drop all state for an agent, so a fresh serve is not born holding the dead
|
|
10358
|
+
* one's in-flight count. Called from the same teardown path that resets turn
|
|
10359
|
+
* health.
|
|
10360
|
+
*/
|
|
10361
|
+
reset(codeName) {
|
|
10362
|
+
this.state.delete(codeName);
|
|
10363
|
+
}
|
|
10364
|
+
};
|
|
10365
|
+
|
|
10298
10366
|
// src/lib/opencode-session.ts
|
|
10299
10367
|
var OPENCODE_BIN = process.env["AGT_OPENCODE_BIN"]?.trim() || "opencode";
|
|
10300
10368
|
var OPENCODE_RUN_TIMEOUT_MS = Number(process.env["AGT_OPENCODE_RUN_TIMEOUT_MS"]) || 18e4;
|
|
10301
10369
|
var sessions = /* @__PURE__ */ new Map();
|
|
10302
10370
|
var loggers = /* @__PURE__ */ new Map();
|
|
10303
10371
|
var turnOutcomeTracker = new TurnOutcomeTracker();
|
|
10372
|
+
var activityTracker = new OpencodeActivityTracker();
|
|
10304
10373
|
var bridges = /* @__PURE__ */ new Map();
|
|
10305
10374
|
function opencodeTmuxSession(codeName) {
|
|
10306
10375
|
return `agt-oc-${codeName}`;
|
|
@@ -10641,18 +10710,28 @@ async function injectOpencodeMessage(codeName, msg, opts = {}) {
|
|
|
10641
10710
|
return { status: "declined", reason: "server_not_running" };
|
|
10642
10711
|
}
|
|
10643
10712
|
const bridge = getBridge(codeName, session.port, session.password);
|
|
10713
|
+
activityTracker.beginTurn(codeName);
|
|
10714
|
+
let occupied = true;
|
|
10644
10715
|
try {
|
|
10645
10716
|
const result = await bridge.handleInbound(msg, { gate: opts.gate, awaitReply: opts.awaitReply });
|
|
10646
10717
|
const outcome = result.status === "declined" ? "declined" : result.status === "replied" && result.reply ? "replied" : opts.awaitReply === false ? "admitted" : "no_reply";
|
|
10718
|
+
occupied = outcome !== "declined";
|
|
10647
10719
|
noteOpencodeTurnOutcome(codeName, outcome, session);
|
|
10648
10720
|
return result;
|
|
10649
10721
|
} catch (err) {
|
|
10650
10722
|
noteOpencodeTurnOutcome(codeName, "failed", session);
|
|
10651
10723
|
throw err;
|
|
10724
|
+
} finally {
|
|
10725
|
+
if (isLiveOpencodeSession(codeName, session)) {
|
|
10726
|
+
activityTracker.endTurn(codeName, occupied);
|
|
10727
|
+
}
|
|
10652
10728
|
}
|
|
10653
10729
|
}
|
|
10730
|
+
function isLiveOpencodeSession(codeName, startedOn) {
|
|
10731
|
+
return sessions.get(codeName) === startedOn && startedOn.status === "running";
|
|
10732
|
+
}
|
|
10654
10733
|
function noteOpencodeTurnOutcome(codeName, outcome, startedOn) {
|
|
10655
|
-
if (
|
|
10734
|
+
if (!isLiveOpencodeSession(codeName, startedOn)) return;
|
|
10656
10735
|
const { health, shouldWarn, recovered } = turnOutcomeTracker.record(codeName, outcome);
|
|
10657
10736
|
const log2 = loggers.get(codeName);
|
|
10658
10737
|
if (!log2) return;
|
|
@@ -10748,6 +10827,7 @@ function stopOpencodeSession(codeName, log2) {
|
|
|
10748
10827
|
stopTranscriptRefresher(codeName);
|
|
10749
10828
|
bridges.delete(codeName);
|
|
10750
10829
|
turnOutcomeTracker.reset(codeName);
|
|
10830
|
+
activityTracker.reset(codeName);
|
|
10751
10831
|
loggers.delete(codeName);
|
|
10752
10832
|
const session = sessions.get(codeName);
|
|
10753
10833
|
if (session) {
|
|
@@ -10762,6 +10842,9 @@ function getOpencodeSessionState(codeName) {
|
|
|
10762
10842
|
function getOpencodeTurnHealth(codeName) {
|
|
10763
10843
|
return turnOutcomeTracker.get(codeName);
|
|
10764
10844
|
}
|
|
10845
|
+
function getOpencodeActivityAgeSeconds(codeName, now = Date.now()) {
|
|
10846
|
+
return activityTracker.activityAgeSeconds(codeName, now);
|
|
10847
|
+
}
|
|
10765
10848
|
function stripUndefined(env2) {
|
|
10766
10849
|
const out = {};
|
|
10767
10850
|
for (const [k, v] of Object.entries(env2)) if (v !== void 0) out[k] = v;
|
|
@@ -12558,6 +12641,8 @@ export {
|
|
|
12558
12641
|
injectOpencodeMessage,
|
|
12559
12642
|
stopOpencodeSession,
|
|
12560
12643
|
getOpencodeSessionState,
|
|
12644
|
+
getOpencodeTurnHealth,
|
|
12645
|
+
getOpencodeActivityAgeSeconds,
|
|
12561
12646
|
sessionTranscriptDir,
|
|
12562
12647
|
transcriptActivityAgeSeconds,
|
|
12563
12648
|
subagentActivityAgeSeconds,
|
|
@@ -12606,4 +12691,4 @@ export {
|
|
|
12606
12691
|
stopAllSessionsAndWait,
|
|
12607
12692
|
getProjectDir
|
|
12608
12693
|
};
|
|
12609
|
-
//# sourceMappingURL=chunk-
|
|
12694
|
+
//# sourceMappingURL=chunk-IE7ZJKF3.js.map
|