@integrity-labs/agt-cli 0.28.425 → 0.28.427

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 CHANGED
@@ -40,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-M3L6HOYG.js";
43
+ } from "../chunk-QXEUCIOC.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-PR3IJAMV.js";
73
+ } from "../chunk-NSG3PTR6.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.425" : "dev";
4832
+ var cliVersion = true ? "0.28.427" : "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.425" : "dev";
6004
+ var cliVersion2 = true ? "0.28.427" : "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) => {
@@ -8282,6 +8282,13 @@ var FLAG_REGISTRY = [
8282
8282
  defaultValue: false,
8283
8283
  envVar: "AGT_MODEL_API_ERROR_REPORTING_ENABLED"
8284
8284
  },
8285
+ {
8286
+ key: "claude-md-skills-index",
8287
+ description: `Manager injects the "## Available Skills" bullet list (one line per installed skill, name + frontmatter description) into the agent's project CLAUDE.md. Claude Code already surfaces installed skills to the model natively from .claude/skills/*/SKILL.md, so on current models the list is duplicated context - and an expensive one: it measured 12,045 chars across 29 skills on a prod agent, pushing project/CLAUDE.md to 51k against Claude Code's 40,000-char ceiling, past which the tail of the agent's own system prompt is silently truncated. OFF suppresses ONLY the skill bullets; the "Updating Integrations" guidance in the same managed block is real instruction and is always kept. Defaults ON (today's behaviour) - flip OFF per org to reclaim the headroom.`,
8288
+ flagType: "boolean",
8289
+ defaultValue: true,
8290
+ envVar: "AGT_CLAUDE_MD_SKILLS_INDEX_ENABLED"
8291
+ },
8285
8292
  {
8286
8293
  key: "wedge-transient-notice",
8287
8294
  description: 'When a wedge-respawn was preceded by a transient LLM-API error (529/429/503/500 that exhausted its retries and wedged the turn), the manager writes the ENG-6058 give-up signal tagged reason=transient_overload so the channel sweeps post a friendly "I hit a brief overload \u2014 please resend" notice instead of leaving the user in silence (ENG-7360, extends ENG-6861 to the retry-exhaustion + wedge path). Boolean gate; ships dark \u2014 channel-visible copy soaks per host before going wide.',
@@ -10444,8 +10451,150 @@ var TurnOutcomeTracker = class {
10444
10451
  }
10445
10452
  };
10446
10453
 
10454
+ // src/lib/busy-bucket-ledger.ts
10455
+ var BUCKET_MS = 6e4;
10456
+ var MAX_ACCRUAL_SPAN_MS = 10 * 6e4;
10457
+ var MAX_RETAINED_BUCKETS = 240;
10458
+ var BILL_WHOLE_MINUTES = true;
10459
+ var MIN_BILLABLE_MS = 100;
10460
+ function bucketStartMs(atMs) {
10461
+ return Math.floor(atMs / BUCKET_MS) * BUCKET_MS;
10462
+ }
10463
+ var BusyBucketLedger = class {
10464
+ state = /* @__PURE__ */ new Map();
10465
+ entry(codeName) {
10466
+ let cur = this.state.get(codeName);
10467
+ if (!cur) {
10468
+ cur = { buckets: /* @__PURE__ */ new Map(), openSince: null };
10469
+ this.state.set(codeName, cur);
10470
+ }
10471
+ return cur;
10472
+ }
10473
+ /**
10474
+ * Credit occupancy for the span [fromMs, toMs), splitting it across every
10475
+ * minute bucket it covers. Safe to call with any ordering — a reversed or
10476
+ * zero-length span is a no-op rather than a negative credit.
10477
+ */
10478
+ accrueSpan(codeName, fromMs, toMs) {
10479
+ if (!Number.isFinite(fromMs) || !Number.isFinite(toMs)) return;
10480
+ if (toMs <= fromMs) return;
10481
+ const start = Math.max(fromMs, toMs - MAX_ACCRUAL_SPAN_MS);
10482
+ const led = this.entry(codeName);
10483
+ for (let b = bucketStartMs(start); b < toMs; b += BUCKET_MS) {
10484
+ const overlap = Math.min(toMs, b + BUCKET_MS) - Math.max(start, b);
10485
+ if (overlap <= 0) continue;
10486
+ const prev = led.buckets.get(b) ?? 0;
10487
+ led.buckets.set(b, Math.min(BUCKET_MS, prev + overlap));
10488
+ }
10489
+ this.evict(led);
10490
+ }
10491
+ /** The agent started doing work. Idempotent while already occupied. */
10492
+ open(codeName, atMs) {
10493
+ const led = this.entry(codeName);
10494
+ if (led.openSince == null) led.openSince = atMs;
10495
+ }
10496
+ /**
10497
+ * Accrue everything owed up to `nowMs` WITHOUT ending the occupancy. This is
10498
+ * what makes a long turn fill every bucket it spans: each probe pass ticks,
10499
+ * banking the elapsed slice and moving the watermark forward.
10500
+ */
10501
+ tick(codeName, nowMs) {
10502
+ const led = this.state.get(codeName);
10503
+ if (!led || led.openSince == null) return;
10504
+ if (nowMs <= led.openSince) return;
10505
+ this.accrueSpan(codeName, led.openSince, nowMs);
10506
+ led.openSince = nowMs;
10507
+ }
10508
+ /** The agent stopped doing work. Banks the final slice. */
10509
+ close(codeName, atMs) {
10510
+ const led = this.state.get(codeName);
10511
+ if (!led || led.openSince == null) return;
10512
+ this.accrueSpan(codeName, led.openSince, atMs);
10513
+ led.openSince = null;
10514
+ }
10515
+ /**
10516
+ * Take every CLOSED bucket for reporting, removing it from the ledger.
10517
+ *
10518
+ * Only closed buckets — a bucket whose minute has not yet elapsed is still
10519
+ * accruing, and reporting it early would send a partial value that the next
10520
+ * drain would have to correct. The open bucket stays and is drained once it
10521
+ * closes.
10522
+ *
10523
+ * DESTRUCTIVE, deliberately: this is the same read-and-reset contract as the
10524
+ * watchdog give-up counters, and it carries the same obligation — the caller
10525
+ * MUST `credit()` the result back if the POST fails, or a transient 5xx
10526
+ * permanently deletes billable occupancy that cannot be reconstructed.
10527
+ */
10528
+ drainClosed(codeName, nowMs) {
10529
+ const led = this.state.get(codeName);
10530
+ if (!led) return [];
10531
+ this.tick(codeName, nowMs);
10532
+ const openBucket = bucketStartMs(nowMs);
10533
+ const out = [];
10534
+ for (const [b, ms] of [...led.buckets].sort((x, y) => x[0] - y[0])) {
10535
+ if (b >= openBucket) continue;
10536
+ led.buckets.delete(b);
10537
+ if (ms < MIN_BILLABLE_MS) continue;
10538
+ const seconds = BILL_WHOLE_MINUTES ? 60 : Math.min(60, Math.ceil(ms / 1e3));
10539
+ out.push({ bucket: new Date(b).toISOString(), seconds });
10540
+ }
10541
+ return out;
10542
+ }
10543
+ /**
10544
+ * Put drained buckets back after a failed POST. Merges rather than replaces,
10545
+ * so occupancy accrued since the drain is preserved.
10546
+ */
10547
+ credit(codeName, buckets) {
10548
+ if (buckets.length === 0) return;
10549
+ const led = this.entry(codeName);
10550
+ for (const b of buckets) {
10551
+ const at = Date.parse(b.bucket);
10552
+ if (!Number.isFinite(at)) continue;
10553
+ const key = bucketStartMs(at);
10554
+ const prev = led.buckets.get(key) ?? 0;
10555
+ led.buckets.set(key, Math.min(BUCKET_MS, prev + b.seconds * 1e3));
10556
+ }
10557
+ this.evict(led);
10558
+ }
10559
+ /** Agents currently holding reportable state. */
10560
+ trackedAgents() {
10561
+ return [...this.state.keys()];
10562
+ }
10563
+ /**
10564
+ * Drop everything for an agent. Called from the same teardown that resets
10565
+ * turn health, so a fresh session is not born holding the dead one's
10566
+ * occupancy.
10567
+ */
10568
+ reset(codeName) {
10569
+ this.state.delete(codeName);
10570
+ }
10571
+ evict(led) {
10572
+ if (led.buckets.size <= MAX_RETAINED_BUCKETS) return;
10573
+ const ordered = [...led.buckets.keys()].sort((a, b) => a - b);
10574
+ for (const k of ordered.slice(0, led.buckets.size - MAX_RETAINED_BUCKETS)) {
10575
+ led.buckets.delete(k);
10576
+ }
10577
+ }
10578
+ };
10579
+ var sharedBusyBuckets = new BusyBucketLedger();
10580
+
10447
10581
  // src/lib/opencode-activity-tracker.ts
10448
10582
  var OpencodeActivityTracker = class {
10583
+ /**
10584
+ * ENG-8116: the same lifecycle also drives the duration ledger. opencode is
10585
+ * the runtime that can measure occupancy EXACTLY — beginTurn/endTurn bracket
10586
+ * real work — so the spans go straight in rather than being inferred from a
10587
+ * file mtime the way Claude Code's have to be.
10588
+ *
10589
+ * Kept inside this class deliberately, rather than having callers poke both:
10590
+ * the lifecycle discipline that makes occupancy correct (the `finally`, the
10591
+ * live-session guard) already lives at one call site, and a second one to
10592
+ * keep in sync is exactly how a leaked in-flight count would bill an idle
10593
+ * agent around the clock.
10594
+ */
10595
+ constructor(ledger = sharedBusyBuckets) {
10596
+ this.ledger = ledger;
10597
+ }
10449
10598
  state = /* @__PURE__ */ new Map();
10450
10599
  entry(codeName) {
10451
10600
  let cur = this.state.get(codeName);
@@ -10456,8 +10605,9 @@ var OpencodeActivityTracker = class {
10456
10605
  return cur;
10457
10606
  }
10458
10607
  /** A turn has been dispatched to the serve. Call BEFORE awaiting it. */
10459
- beginTurn(codeName) {
10608
+ beginTurn(codeName, now = Date.now()) {
10460
10609
  this.entry(codeName).inFlight += 1;
10610
+ this.ledger.open(codeName, now);
10461
10611
  }
10462
10612
  /**
10463
10613
  * A dispatched turn has resolved. Call in a `finally`, so a throw cannot
@@ -10471,6 +10621,7 @@ var OpencodeActivityTracker = class {
10471
10621
  const cur = this.entry(codeName);
10472
10622
  cur.inFlight = Math.max(0, cur.inFlight - 1);
10473
10623
  if (counted) cur.lastActiveAt = now;
10624
+ if (cur.inFlight === 0) this.ledger.close(codeName, now);
10474
10625
  }
10475
10626
  /**
10476
10627
  * Seconds since this agent was last doing work, or null if it never has been
@@ -10494,6 +10645,7 @@ var OpencodeActivityTracker = class {
10494
10645
  */
10495
10646
  reset(codeName) {
10496
10647
  this.state.delete(codeName);
10648
+ this.ledger.reset(codeName);
10497
10649
  }
10498
10650
  };
10499
10651
 
@@ -12768,6 +12920,7 @@ export {
12768
12920
  sha256,
12769
12921
  hashFile,
12770
12922
  execFilePromiseLong,
12923
+ sharedBusyBuckets,
12771
12924
  readProvisionedOpencodeModel,
12772
12925
  startOpencodeSession,
12773
12926
  readOpencodePaneLogTail,
@@ -12825,4 +12978,4 @@ export {
12825
12978
  stopAllSessionsAndWait,
12826
12979
  getProjectDir
12827
12980
  };
12828
- //# sourceMappingURL=chunk-PR3IJAMV.js.map
12981
+ //# sourceMappingURL=chunk-NSG3PTR6.js.map