@integrity-labs/agt-cli 0.24.5 → 0.24.7

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.
@@ -8,7 +8,7 @@ import {
8
8
  parseDeliveryTarget,
9
9
  registerFramework,
10
10
  wrapScheduledTaskPrompt
11
- } from "./chunk-ECDTRQLA.js";
11
+ } from "./chunk-53TCAGCM.js";
12
12
 
13
13
  // ../../packages/core/dist/integrations/registry.js
14
14
  var INTEGRATION_REGISTRY = [
@@ -6710,4 +6710,4 @@ export {
6710
6710
  managerInstallSystemUnitCommand,
6711
6711
  managerUninstallSystemUnitCommand
6712
6712
  };
6713
- //# sourceMappingURL=chunk-QWMGMV4N.js.map
6713
+ //# sourceMappingURL=chunk-FK6BJWEC.js.map
@@ -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-JUJY46HW.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-XJYOPFIP.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-ZQAJOQPN.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-4F53C7RB.js.map
@@ -12,7 +12,7 @@ import {
12
12
  provisionOrientHook,
13
13
  provisionStopHook,
14
14
  requireHost
15
- } from "../chunk-QWMGMV4N.js";
15
+ } from "../chunk-FK6BJWEC.js";
16
16
  import {
17
17
  findTaskByTemplate,
18
18
  getProjectDir as getProjectDir2,
@@ -48,13 +48,15 @@ import {
48
48
  stopAllSessionsAndWait,
49
49
  stopPersistentSession,
50
50
  takeZombieDetection
51
- } from "../chunk-PNTLQKLO.js";
51
+ } from "../chunk-3A2PMQM4.js";
52
52
  import {
53
53
  KANBAN_CHECK_COMMAND,
54
54
  appendDmFooter,
55
+ attributeTranscriptUsageByRun,
55
56
  classifyOutput,
56
57
  extractFrontmatter,
57
58
  formatActorId,
59
+ formatRunMarker,
58
60
  getFramework,
59
61
  isEmptyTotals,
60
62
  isParseError,
@@ -66,7 +68,7 @@ import {
66
68
  resolveChannels,
67
69
  resolveDmTarget,
68
70
  wrapScheduledTaskPrompt
69
- } from "../chunk-ECDTRQLA.js";
71
+ } from "../chunk-53TCAGCM.js";
70
72
 
71
73
  // src/lib/manager-worker.ts
72
74
  import { createHash as createHash3 } from "crypto";
@@ -534,7 +536,7 @@ function reapMissingMcpSessions(args) {
534
536
  );
535
537
  }
536
538
  }
537
- stopSession(codeName);
539
+ stopSession(codeName, { activeKeys: active });
538
540
  return {
539
541
  missing,
540
542
  restarted: true,
@@ -572,6 +574,9 @@ function decideChannelRestart(input) {
572
574
  }
573
575
 
574
576
  // src/lib/restart-breaker.ts
577
+ function reaperRestartBreakerReason(activeKeys) {
578
+ return activeKeys.length >= 2 ? "mcp-presence-reaper" : void 0;
579
+ }
575
580
  var DEFAULT_MAX = 2;
576
581
  var DEFAULT_WINDOW_MS = 6e5;
577
582
  function readEnvNumber(name, fallback) {
@@ -754,6 +759,7 @@ async function maybeReportTokenUsage(args) {
754
759
  return;
755
760
  }
756
761
  const pending = [];
762
+ const pendingRuns = [];
757
763
  for (const name of dirEntries) {
758
764
  if (!name.endsWith(".jsonl")) continue;
759
765
  const sessionId = name.slice(0, -".jsonl".length);
@@ -797,6 +803,18 @@ async function maybeReportTokenUsage(args) {
797
803
  }
798
804
  });
799
805
  }
806
+ for (const r of attributeTranscriptUsageByRun(content).perRunModel) {
807
+ if (r.runId === null || isEmptyTotals(r.totals)) continue;
808
+ pendingRuns.push({
809
+ run_id: r.runId,
810
+ model: r.model,
811
+ input_tokens: r.totals.inputTokens,
812
+ output_tokens: r.totals.outputTokens,
813
+ cache_creation_tokens: r.totals.cacheCreationTokens,
814
+ cache_read_tokens: r.totals.cacheReadTokens,
815
+ last_observed_at: parsed.lastObservedAt
816
+ });
817
+ }
800
818
  if (![...parsed.byModel.values()].some((t) => !isEmptyTotals(t))) {
801
819
  files.set(sessionId, fp);
802
820
  }
@@ -823,6 +841,19 @@ async function maybeReportTokenUsage(args) {
823
841
  log2(`[token-usage] POST failed for '${codeName}': ${err.message}`);
824
842
  }
825
843
  }
844
+ for (let i = 0; i < pendingRuns.length; i += MAX_ENTRIES_PER_POST) {
845
+ const batch = pendingRuns.slice(i, i + MAX_ENTRIES_PER_POST);
846
+ try {
847
+ await api2.post("/host/run-token-usage", {
848
+ agent_id: agentId,
849
+ framework: "claude-code",
850
+ source: "transcript_jsonl",
851
+ entries: batch
852
+ });
853
+ } catch (err) {
854
+ log2(`[token-usage] run-usage POST failed for '${codeName}': ${err.message}`);
855
+ }
856
+ }
826
857
  if (reported > 0) {
827
858
  log2(`[token-usage] reported ${reported} entr${reported === 1 ? "y" : "ies"} for '${codeName}'`);
828
859
  }
@@ -2663,6 +2694,7 @@ function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason) {
2663
2694
  stopPersistentSession(codeName, log);
2664
2695
  runningMcpHashes.delete(codeName);
2665
2696
  runningMcpServerKeys.delete(codeName);
2697
+ closeInjectedRunIfOpen(codeName, "cancelled", `session stopped (${breakerReason ?? "deprovision"})`);
2666
2698
  if (breakerReason) {
2667
2699
  recordRestartForBreaker(codeName, breakerReason);
2668
2700
  }
@@ -2806,7 +2838,7 @@ var cachedFrameworkVersion = null;
2806
2838
  var lastVersionCheckAt = 0;
2807
2839
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
2808
2840
  var lastResponsivenessProbeAt = 0;
2809
- var agtCliVersion = true ? "0.24.5" : "dev";
2841
+ var agtCliVersion = true ? "0.24.7" : "dev";
2810
2842
  function resolveBrewPath(execFileSync4) {
2811
2843
  try {
2812
2844
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -3765,7 +3797,7 @@ async function pollCycle() {
3765
3797
  }
3766
3798
  try {
3767
3799
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
3768
- const { collectDiagnostics } = await import("../persistent-session-JUJY46HW.js");
3800
+ const { collectDiagnostics } = await import("../persistent-session-XJYOPFIP.js");
3769
3801
  const diagCodeNames = [...persistentSessionAgents];
3770
3802
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
3771
3803
  let tailscaleHostname;
@@ -3816,7 +3848,7 @@ async function pollCycle() {
3816
3848
  const {
3817
3849
  collectResponsivenessProbes,
3818
3850
  getResponsivenessIntervalMs
3819
- } = await import("../responsiveness-probe-XOEC7J5D.js");
3851
+ } = await import("../responsiveness-probe-EWZNGMTX.js");
3820
3852
  const probeIntervalMs = getResponsivenessIntervalMs();
3821
3853
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
3822
3854
  const probeCodeNames = [...persistentSessionAgents];
@@ -5092,7 +5124,9 @@ async function processAgent(agent, agentStates) {
5092
5124
  const actionableCount = hybridBoard.filter(
5093
5125
  (i) => HYBRID_ACTIONABLE_STATUSES.has(i.status)
5094
5126
  ).length;
5095
- void maybeInjectKanbanCheck(agent.code_name, actionableCount);
5127
+ void maybeInjectKanbanCheck(agent.code_name, agent.agent_id, actionableCount);
5128
+ } else {
5129
+ closeInjectedRunIfOpen(agent.code_name, "completed", "kanban board drained");
5096
5130
  }
5097
5131
  }
5098
5132
  if (agentFw === "claude-code" && sessionMode === "persistent") {
@@ -5149,12 +5183,17 @@ async function processAgent(agent, agentStates) {
5149
5183
  codeName: agent.code_name,
5150
5184
  mcpJson: mcpJsonParsed,
5151
5185
  sessionStartedAt: sess?.startedAt ?? null,
5152
- // ENG-5441: mcp-presence-reaper-driven restart counts against
5153
- // the breaker. Each declared MCP has its own ENG-5279 give-up
5154
- // cap (~3 cycles per server), but a thrashing collection of
5155
- // MCPs can still rotate restarts of the whole session. The
5156
- // breaker catches the rotating case the per-MCP cap can't see.
5157
- stopSession: (codeName) => stopPersistentSessionAndForgetMcpBaseline(codeName, "mcp-presence-reaper"),
5186
+ // ENG-5441 / ENG-5547: a mcp-presence-reaper restart counts against
5187
+ // the agent-wide breaker ONLY when several distinct MCP servers are
5188
+ // missing at once a thrashing collection that rotates restarts of
5189
+ // the whole session, which the per-MCP cap can't see. A restart
5190
+ // driven by a SINGLE persistently-failing server is left to that
5191
+ // server's own ENG-5279 give-up cap ( marked unhealthy via onGiveUp
5192
+ // → dropped from the next .mcp.json), so one bad integration is
5193
+ // isolated and the agent keeps running degraded instead of being
5194
+ // paused wholesale. reaperRestartBreakerReason() encodes that
5195
+ // single-vs-multi decision; undefined means "restart, don't count".
5196
+ stopSession: (codeName, ctx) => stopPersistentSessionAndForgetMcpBaseline(codeName, reaperRestartBreakerReason(ctx.activeKeys)),
5158
5197
  // ENG-5292: when the reaper gives up on a managed MCP (cap from
5159
5198
  // ENG-5279 + state-preservation from ENG-5285 both said "this
5160
5199
  // MCP keeps failing after 3 restart cycles"), mark the matching
@@ -6670,13 +6709,23 @@ function hasHybridActionableItems(items) {
6670
6709
  return items.some((item) => HYBRID_ACTIONABLE_STATUSES.has(item.status));
6671
6710
  }
6672
6711
  var lastKanbanInjectAt = /* @__PURE__ */ new Map();
6712
+ var openInjectedRunByCode = /* @__PURE__ */ new Map();
6713
+ function isSlashCommand(command) {
6714
+ return command.trimStart().startsWith("/");
6715
+ }
6716
+ function closeInjectedRunIfOpen(codeName, outcome, outcomeMessage) {
6717
+ const runId = openInjectedRunByCode.get(codeName);
6718
+ if (!runId) return;
6719
+ openInjectedRunByCode.delete(codeName);
6720
+ void finishRun(runId, outcome, { outcomeMessage });
6721
+ }
6673
6722
  var KANBAN_HYBRID_DEBOUNCE_MS = (() => {
6674
6723
  const raw = process.env["AGT_KANBAN_HYBRID_DEBOUNCE_SECONDS"];
6675
6724
  const parsed = raw ? parseInt(raw, 10) : NaN;
6676
6725
  if (Number.isFinite(parsed) && parsed > 0) return Math.max(parsed, 10) * 1e3;
6677
6726
  return 6e4;
6678
6727
  })();
6679
- async function maybeInjectKanbanCheck(codeName, actionableCount) {
6728
+ async function maybeInjectKanbanCheck(codeName, agentId, actionableCount) {
6680
6729
  const lastAt = lastKanbanInjectAt.get(codeName) ?? 0;
6681
6730
  if (Date.now() - lastAt < KANBAN_HYBRID_DEBOUNCE_MS) {
6682
6731
  return;
@@ -6695,13 +6744,30 @@ async function maybeInjectKanbanCheck(codeName, actionableCount) {
6695
6744
  lastKanbanInjectAt.delete(codeName);
6696
6745
  return;
6697
6746
  }
6698
- const sent = sendToAgent(tmuxSession, KANBAN_CHECK_COMMAND);
6699
- if (sent) {
6747
+ closeInjectedRunIfOpen(codeName, "completed", "kanban inject superseded by next inject");
6748
+ const { run_id } = await startRun({
6749
+ agent_id: agentId,
6750
+ source_type: "kanban",
6751
+ metadata: { injected: "kanban-check", actionable_count: actionableCount }
6752
+ });
6753
+ let delivered;
6754
+ if (isSlashCommand(KANBAN_CHECK_COMMAND)) {
6755
+ delivered = sendToAgent(tmuxSession, KANBAN_CHECK_COMMAND);
6756
+ } else {
6757
+ const content = run_id ? `${KANBAN_CHECK_COMMAND}
6758
+ ${formatRunMarker(run_id)}` : KANBAN_CHECK_COMMAND;
6759
+ delivered = await injectMessage(codeName, "system", content, void 0, log);
6760
+ }
6761
+ if (delivered) {
6762
+ if (run_id) openInjectedRunByCode.set(codeName, run_id);
6700
6763
  log(
6701
- `[manager-worker] Injected kanban check for '${codeName}' (${actionableCount} actionable items)`
6764
+ `[manager-worker] Injected kanban check for '${codeName}' (${actionableCount} actionable items)${run_id ? ` run_id=${run_id}` : ""}`
6702
6765
  );
6703
6766
  } else {
6704
- log(`[manager-worker] kanban inject failed (tmux send) for '${codeName}'`);
6767
+ if (run_id) {
6768
+ void finishRun(run_id, "failed", { outcomeMessage: "kanban inject delivery failed" });
6769
+ }
6770
+ log(`[manager-worker] kanban inject failed for '${codeName}'`);
6705
6771
  }
6706
6772
  }
6707
6773
  function warnOnConflictingKanbanModes() {
@@ -7553,7 +7619,7 @@ async function processClaudePairSessions(agents) {
7553
7619
  killPairSession,
7554
7620
  pairTmuxSession,
7555
7621
  finalizeClaudePairOnboarding
7556
- } = await import("../claude-pair-runtime-ZQAJOQPN.js");
7622
+ } = await import("../claude-pair-runtime-4F53C7RB.js");
7557
7623
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
7558
7624
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
7559
7625
  const killed = await killPairSession(pairTmuxSession(pairId));