@integrity-labs/agt-cli 0.28.664 → 0.28.666

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-DFGQKEVY.js";
43
+ } from "../chunk-P7UIFZQO.js";
44
44
  import {
45
45
  readDirectChatSessionState
46
46
  } from "../chunk-EX5XJEGF.js";
@@ -4909,7 +4909,7 @@ import { execFileSync, execSync } from "child_process";
4909
4909
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4910
4910
  import chalk18 from "chalk";
4911
4911
  import ora16 from "ora";
4912
- var cliVersion = true ? "0.28.664" : "dev";
4912
+ var cliVersion = true ? "0.28.666" : "dev";
4913
4913
  async function fetchLatestVersion() {
4914
4914
  const host2 = getHost();
4915
4915
  if (!host2) return null;
@@ -6089,7 +6089,7 @@ function handleError(err) {
6089
6089
  }
6090
6090
 
6091
6091
  // src/bin/agt.ts
6092
- var cliVersion2 = true ? "0.28.664" : "dev";
6092
+ var cliVersion2 = true ? "0.28.666" : "dev";
6093
6093
  var program = new Command();
6094
6094
  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");
6095
6095
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -6342,7 +6342,7 @@ function exchangeFailureKind(err) {
6342
6342
  }
6343
6343
 
6344
6344
  // src/lib/api-client.ts
6345
- var agtCliVersion = true ? "0.28.664" : "dev";
6345
+ var agtCliVersion = true ? "0.28.666" : "dev";
6346
6346
  var lastConfigHash = null;
6347
6347
  function setConfigHash(hash) {
6348
6348
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -10084,4 +10084,4 @@ export {
10084
10084
  managerInstallSystemUnitCommand,
10085
10085
  managerUninstallSystemUnitCommand
10086
10086
  };
10087
- //# sourceMappingURL=chunk-DFGQKEVY.js.map
10087
+ //# sourceMappingURL=chunk-P7UIFZQO.js.map
@@ -55,7 +55,7 @@ import {
55
55
  safeWriteJsonAtomic,
56
56
  setConfigHash,
57
57
  tripClass
58
- } from "../chunk-DFGQKEVY.js";
58
+ } from "../chunk-P7UIFZQO.js";
59
59
  import {
60
60
  getProjectDir as getProjectDir2,
61
61
  getReadyTasks,
@@ -10651,7 +10651,7 @@ function stopRealtimeIntegrationContext() {
10651
10651
  integrationContextChannel = null;
10652
10652
  }
10653
10653
  function startRealtimeTokenRotation(config2) {
10654
- const { agentIds, onTokenRotated, onSubscriptionLost, log: log2 } = config2;
10654
+ const { agentIds, onTokenRotated, onSubscriptionLost, onSubscribed, log: log2 } = config2;
10655
10655
  if (agentIds.length === 0) return;
10656
10656
  stopRealtimeTokenRotation();
10657
10657
  const epoch = ++tokenRotationEpoch;
@@ -10677,7 +10677,9 @@ function startRealtimeTokenRotation(config2) {
10677
10677
  if (status === "CLOSED" || status === "CHANNEL_ERROR" || status === "TIMED_OUT") {
10678
10678
  log2(`[realtime] Token rotation channel for agent ${agentId}: ${status}`);
10679
10679
  onSubscriptionLost?.(agentId, status);
10680
+ return;
10680
10681
  }
10682
+ if (status === "SUBSCRIBED") onSubscribed?.(agentId);
10681
10683
  });
10682
10684
  tokenRotationChannels.push(channel);
10683
10685
  }
@@ -12219,6 +12221,7 @@ function resolveAgentFramework(codeName) {
12219
12221
  function clearAgentCaches(agentId, codeName) {
12220
12222
  const channelCacheMutated = clearAgentState(agentId, codeName);
12221
12223
  agentChannelTokens.delete(codeName);
12224
+ forgetRealtimeRebindState(agentId);
12222
12225
  forgetChannelSyncState(agentId);
12223
12226
  sharedBusyBuckets.reset(codeName);
12224
12227
  stopOpencodeSlackIngest(codeName, log);
@@ -12253,7 +12256,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
12253
12256
  var lastVersionCheckAt = 0;
12254
12257
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
12255
12258
  var lastResponsivenessProbeAt = 0;
12256
- var agtCliVersion = true ? "0.28.664" : "dev";
12259
+ var agtCliVersion = true ? "0.28.666" : "dev";
12257
12260
  function resolveBrewPath(execFileSync3) {
12258
12261
  try {
12259
12262
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -13820,6 +13823,19 @@ async function pollCycleInner() {
13820
13823
  // close a resolved alert on the edge. Omitting it when empty would make
13821
13824
  // "recovered" and "this CLI is too old to report" the same wire value.
13822
13825
  channel_sync_stuck: stuckChannelSyncs(channelSyncFailures, Date.now()),
13826
+ // ENG-9265: agents whose realtime token-rotation subscription has been
13827
+ // failing to bind for longer than the stuck threshold. Same contract as
13828
+ // the field above — ALWAYS sent, including as an empty array, because
13829
+ // that is what lets the API close a resolved alert on the edge. An
13830
+ // absent field means an older CLI that cannot report; an empty one is
13831
+ // the affirmative all-clear.
13832
+ //
13833
+ // This is the ask that matters most on the ticket. A manager churning
13834
+ // subscriptions every tick for half an hour produced NO signal of its
13835
+ // own; the only alert was the host going silent, by which point four
13836
+ // customer agents had been dark for three minutes. Bounding the retry
13837
+ // without this would fix the CPU and leave the blindness.
13838
+ realtime_rebind_stuck: stuckRealtimeRebinds(realtimeRebindFailures, Date.now()),
13823
13839
  // ENG-6251: capability advertisement — the flags schema version this
13824
13840
  // CLI compiled with, so the admin UI can show flip reach across a
13825
13841
  // mixed-CLI fleet (an older CLI sends an older fingerprint).
@@ -17643,6 +17659,69 @@ var realtimeStarted = false;
17643
17659
  var realtimeDriftStarted = false;
17644
17660
  var realtimeKanbanStarted = false;
17645
17661
  var subscribedIntegrationContextAgentIds = /* @__PURE__ */ new Set();
17662
+ var realtimeRebindFailures = /* @__PURE__ */ new Map();
17663
+ var REALTIME_REBIND_FREE_ATTEMPTS = 2;
17664
+ var REALTIME_REBIND_MAX_BACKOFF_MS = 5 * 6e4;
17665
+ var REALTIME_REBIND_STUCK_AFTER_MS = 5 * 6e4;
17666
+ var REALTIME_REBIND_IN_FLIGHT_GRACE_MS = 15e3;
17667
+ function realtimeRebindBackoffMs(attempts) {
17668
+ if (attempts <= REALTIME_REBIND_FREE_ATTEMPTS) return 0;
17669
+ const step = attempts - REALTIME_REBIND_FREE_ATTEMPTS;
17670
+ return Math.min(1e4 * 2 ** (step - 1), REALTIME_REBIND_MAX_BACKOFF_MS);
17671
+ }
17672
+ function recordRealtimeRebindFailure(failures, agentId, status, now) {
17673
+ const prior = failures.get(agentId);
17674
+ const attempts = (prior?.attempts ?? 0) + 1;
17675
+ const next = {
17676
+ attempts,
17677
+ since: prior?.since ?? now,
17678
+ lastStatus: status,
17679
+ loggedAtAttempt: prior?.loggedAtAttempt ?? 0,
17680
+ nextAttemptAt: now + realtimeRebindBackoffMs(attempts)
17681
+ };
17682
+ failures.set(agentId, next);
17683
+ return next;
17684
+ }
17685
+ function realtimeRebindDue(failures, now) {
17686
+ for (const state8 of failures.values()) if (now >= state8.nextAttemptAt) return true;
17687
+ return false;
17688
+ }
17689
+ function stuckRealtimeRebinds(failures, now, thresholdMs = REALTIME_REBIND_STUCK_AFTER_MS) {
17690
+ const out = [];
17691
+ for (const [agentId, state8] of failures) {
17692
+ const stuckForMs = now - state8.since;
17693
+ if (stuckForMs < thresholdMs) continue;
17694
+ out.push({
17695
+ agent_id: agentId,
17696
+ attempts: state8.attempts,
17697
+ stuck_for_seconds: Math.floor(stuckForMs / 1e3),
17698
+ status: state8.lastStatus
17699
+ });
17700
+ }
17701
+ out.sort((a, b) => b.stuck_for_seconds - a.stuck_for_seconds);
17702
+ return out;
17703
+ }
17704
+ function forgetRealtimeRebindState(agentId) {
17705
+ realtimeRebindFailures.delete(agentId);
17706
+ }
17707
+ function pruneRealtimeRebindState(failures, liveAgentIds) {
17708
+ const live = liveAgentIds instanceof Set ? liveAgentIds : new Set(liveAgentIds);
17709
+ let dropped = 0;
17710
+ for (const agentId of [...failures.keys()]) {
17711
+ if (!live.has(agentId)) {
17712
+ failures.delete(agentId);
17713
+ dropped++;
17714
+ }
17715
+ }
17716
+ return dropped;
17717
+ }
17718
+ function holdRealtimeRebindInFlight(failures, agentIds, now, graceMs = REALTIME_REBIND_IN_FLIGHT_GRACE_MS) {
17719
+ const until = now + graceMs;
17720
+ for (const agentId of agentIds) {
17721
+ const state8 = failures.get(agentId);
17722
+ if (state8) state8.nextAttemptAt = Math.max(state8.nextAttemptAt, until);
17723
+ }
17724
+ }
17646
17725
  var realtimeAssignStarted = false;
17647
17726
  var realtimeConfigStarted = false;
17648
17727
  var realtimeSubscribedAgentIds = /* @__PURE__ */ new Set();
@@ -18008,6 +18087,12 @@ function activeAgentIdSetsEqual(current, previous) {
18008
18087
  }
18009
18088
  function ensureRealtimeIntegrationContextStarted(agentStates) {
18010
18089
  const activeAgentIds = agentStates.filter((a) => a.status === "active").map((a) => a.agentId);
18090
+ if (realtimeRebindFailures.size > 0) {
18091
+ const dropped = pruneRealtimeRebindState(realtimeRebindFailures, activeAgentIds);
18092
+ if (dropped > 0) {
18093
+ log(`[realtime] Dropped ${dropped} token-rotation rebind streak(s) for no-longer-active agent(s) (ENG-9265)`);
18094
+ }
18095
+ }
18011
18096
  if (activeAgentIds.length === 0) {
18012
18097
  if (subscribedIntegrationContextAgentIds.size > 0) {
18013
18098
  stopRealtimeIntegrationContext();
@@ -18017,6 +18102,9 @@ function ensureRealtimeIntegrationContextStarted(agentStates) {
18017
18102
  }
18018
18103
  return;
18019
18104
  }
18105
+ if (realtimeRebindFailures.size > 0 && realtimeRebindDue(realtimeRebindFailures, Date.now()) && subscribedIntegrationContextAgentIds.size > 0) {
18106
+ subscribedIntegrationContextAgentIds = /* @__PURE__ */ new Set();
18107
+ }
18020
18108
  if (activeAgentIdSetsEqual(activeAgentIds, subscribedIntegrationContextAgentIds)) return;
18021
18109
  const apiKey = process.env["AGT_API_KEY"];
18022
18110
  if (!apiKey) return;
@@ -18027,6 +18115,9 @@ function ensureRealtimeIntegrationContextStarted(agentStates) {
18027
18115
  }
18028
18116
  const targetSet = new Set(activeAgentIds);
18029
18117
  subscribedIntegrationContextAgentIds = targetSet;
18118
+ if (realtimeRebindFailures.size > 0) {
18119
+ holdRealtimeRebindInFlight(realtimeRebindFailures, targetSet, Date.now());
18120
+ }
18030
18121
  void exchangeApiKey(apiKey).then((exchange) => {
18031
18122
  if (subscribedIntegrationContextAgentIds !== targetSet) return;
18032
18123
  if (!exchange.supabaseUrl || !exchange.supabaseAnonKey) {
@@ -18061,9 +18152,31 @@ function ensureRealtimeIntegrationContextStarted(agentStates) {
18061
18152
  `integration token rotated for agent ${agentId} (integration ${event.integration_id}, ${event.definition_id})`
18062
18153
  );
18063
18154
  },
18155
+ onSubscribed: (agentId) => {
18156
+ const ended = realtimeRebindFailures.get(agentId);
18157
+ if (!ended) return;
18158
+ realtimeRebindFailures.delete(agentId);
18159
+ const stuckForSeconds = Math.floor((Date.now() - ended.since) / 1e3);
18160
+ log(
18161
+ `[realtime] Token rotation subscription for agent ${agentId} recovered after ${ended.attempts} failed attempt(s) over ${stuckForSeconds}s (ENG-9265)`
18162
+ );
18163
+ },
18064
18164
  onSubscriptionLost: (agentId, status) => {
18065
- log(`[realtime] Token rotation subscription lost for agent ${agentId} (${status}) \u2014 will rebind next tick`);
18066
- subscribedIntegrationContextAgentIds = /* @__PURE__ */ new Set();
18165
+ const state8 = recordRealtimeRebindFailure(
18166
+ realtimeRebindFailures,
18167
+ agentId,
18168
+ status,
18169
+ Date.now()
18170
+ );
18171
+ const waitMs = realtimeRebindBackoffMs(state8.attempts);
18172
+ if (state8.attempts === 1 || state8.attempts > state8.loggedAtAttempt) {
18173
+ state8.loggedAtAttempt = state8.attempts;
18174
+ const stuckForSeconds = Math.floor((Date.now() - state8.since) / 1e3);
18175
+ log(
18176
+ `[realtime] Token rotation subscription lost for agent ${agentId} (${status}) \u2014 attempt ${state8.attempts}, stuck ${stuckForSeconds}s, next rebind in ${Math.round(waitMs / 1e3)}s (ENG-9265)`
18177
+ );
18178
+ }
18179
+ if (waitMs === 0) subscribedIntegrationContextAgentIds = /* @__PURE__ */ new Set();
18067
18180
  },
18068
18181
  log
18069
18182
  });
@@ -19432,6 +19545,10 @@ export {
19432
19545
  DAY_ROLLOVER_FORCE_GRACE_MIN,
19433
19546
  DAY_ROLLOVER_INBOUND_DEFER_MAX_MIN,
19434
19547
  DAY_ROLLOVER_INBOUND_GRACE_SEC,
19548
+ REALTIME_REBIND_FREE_ATTEMPTS,
19549
+ REALTIME_REBIND_IN_FLIGHT_GRACE_MS,
19550
+ REALTIME_REBIND_MAX_BACKOFF_MS,
19551
+ REALTIME_REBIND_STUCK_AFTER_MS,
19435
19552
  UntrustworthyToolkitResponseError,
19436
19553
  applyRestartAcks,
19437
19554
  cancelKanbanNoticeOnDrain,
@@ -19451,7 +19568,9 @@ export {
19451
19568
  extractCharterTelegramPeers,
19452
19569
  fetchManagedToolkits,
19453
19570
  forgetChannelSyncState,
19571
+ forgetRealtimeRebindState,
19454
19572
  hasRevokedResiduals,
19573
+ holdRealtimeRebindInFlight,
19455
19574
  inboundHoldMinutes,
19456
19575
  isOlderSemverTuple,
19457
19576
  isPrereleaseVersion,
@@ -19459,7 +19578,11 @@ export {
19459
19578
  maybeInjectKanbanCheck,
19460
19579
  maybeProbeClaudeRuntimeAuth,
19461
19580
  maybeUpgradeClaudeCode,
19581
+ pruneRealtimeRebindState,
19582
+ realtimeRebindBackoffMs,
19583
+ realtimeRebindDue,
19462
19584
  recordChannelSyncFailure,
19585
+ recordRealtimeRebindFailure,
19463
19586
  refreshSkillsIndexInClaudeMd,
19464
19587
  reorderRestartedFirst,
19465
19588
  resolveManagedMcpServerId,
@@ -19474,6 +19597,7 @@ export {
19474
19597
  startManager,
19475
19598
  stopManager,
19476
19599
  stuckChannelSyncs,
19600
+ stuckRealtimeRebinds,
19477
19601
  supersededRuntimeImageIds
19478
19602
  };
19479
19603
  //# sourceMappingURL=manager-worker.js.map