@integrity-labs/agt-cli 0.28.379 → 0.28.381

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.
@@ -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-PGKQK5VU.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-FZF7EPUW.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-SJW25IRD.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-YF3ZEFKV.js.map
@@ -43,7 +43,7 @@ import {
43
43
  resolveEffectivePinRaw,
44
44
  safeWriteJsonAtomic,
45
45
  setConfigHash
46
- } from "../chunk-KODU4EUV.js";
46
+ } from "../chunk-TRTVQUQL.js";
47
47
  import {
48
48
  getProjectDir as getProjectDir2,
49
49
  getReadyTasks,
@@ -145,7 +145,7 @@ import {
145
145
  toOpencodeModel,
146
146
  transcriptActivityAgeSeconds,
147
147
  writeEgressAllowlist
148
- } from "../chunk-REVQSDNX.js";
148
+ } from "../chunk-EP6TURK5.js";
149
149
  import {
150
150
  reapOrphanChannelMcps
151
151
  } from "../chunk-XWVM4KPK.js";
@@ -287,6 +287,13 @@ function computeIntegrationsHash(integrations) {
287
287
  );
288
288
  return createHash2("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
289
289
  }
290
+ function computeCapabilitySurfaceHash(integrations) {
291
+ const payload = [...integrations].sort((a, b) => a.definition_id.localeCompare(b.definition_id)).map((i) => {
292
+ const caps = [...i.capabilities ?? []].sort((a, b) => a.id.localeCompare(b.id)).map((c) => `${c.id}:${c.access}`);
293
+ return `${i.definition_id}:${i.display_name ?? ""}:${JSON.stringify(caps)}`;
294
+ });
295
+ return createHash2("sha256").update(JSON.stringify(payload)).digest("hex").slice(0, 16);
296
+ }
290
297
 
291
298
  // src/lib/host-integration-mapping.ts
292
299
  function withResolvedRemoteMcp(integration) {
@@ -3810,6 +3817,18 @@ var agentState = {
3810
3817
  knownModels: /* @__PURE__ */ new Map(),
3811
3818
  knownTasksHashes: /* @__PURE__ */ new Map(),
3812
3819
  knownIntegrationHashes: /* @__PURE__ */ new Map(),
3820
+ /**
3821
+ * ENG-7946: hash of the integration CAPABILITY SURFACE (definition_id +
3822
+ * display_name + capabilities), updated each poll alongside
3823
+ * `knownIntegrationHashes`. The `integration-update` notice injected into
3824
+ * the agent's session is gated on THIS hash changing, not the full
3825
+ * credential+config hash — so token refreshes (which bump
3826
+ * `knownIntegrationHashes` via the `credentials` field) do not fire a
3827
+ * spurious notice. In-memory only: a manager restart clears it, and the
3828
+ * first-poll delta fires exactly one notice on startup, which is correct
3829
+ * (it reflects the true current surface).
3830
+ */
3831
+ knownCapabilitySurfaceHashes: /* @__PURE__ */ new Map(),
3813
3832
  /**
3814
3833
  * ENG-7812: the integration MEMBERSHIP (sorted `definition_id`s, credential/
3815
3834
  * config churn ignored) observed on the previous refresh. Diffed against the
@@ -3903,6 +3922,7 @@ function clearAgentState(agentId, codeName) {
3903
3922
  agentState.knownModels.delete(agentId);
3904
3923
  agentState.knownTasksHashes.delete(agentId);
3905
3924
  agentState.knownIntegrationHashes.delete(agentId);
3925
+ agentState.knownCapabilitySurfaceHashes.delete(agentId);
3906
3926
  agentState.knownIntegrationMembership.delete(agentId);
3907
3927
  agentState.knownManagedMcpHashes.delete(agentId);
3908
3928
  agentState.knownManagedMcpStructure.delete(agentId);
@@ -9100,7 +9120,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
9100
9120
  var lastVersionCheckAt = 0;
9101
9121
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
9102
9122
  var lastResponsivenessProbeAt = 0;
9103
- var agtCliVersion = true ? "0.28.379" : "dev";
9123
+ var agtCliVersion = true ? "0.28.381" : "dev";
9104
9124
  function resolveBrewPath(execFileSync2) {
9105
9125
  try {
9106
9126
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -10229,7 +10249,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
10229
10249
  if (codeNames.length === 0) return;
10230
10250
  void (async () => {
10231
10251
  try {
10232
- const { collectDiagnostics } = await import("../persistent-session-PGKQK5VU.js");
10252
+ const { collectDiagnostics } = await import("../persistent-session-FZF7EPUW.js");
10233
10253
  await api.post("/host/heartbeat", {
10234
10254
  host_id: hostId,
10235
10255
  agent_diagnostics: collectDiagnostics(codeNames)
@@ -10328,7 +10348,7 @@ async function pollCycle() {
10328
10348
  }
10329
10349
  try {
10330
10350
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
10331
- const { collectDiagnostics } = await import("../persistent-session-PGKQK5VU.js");
10351
+ const { collectDiagnostics } = await import("../persistent-session-FZF7EPUW.js");
10332
10352
  const diagCodeNames = [...agentState.persistentSessionAgents];
10333
10353
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames) : void 0;
10334
10354
  let tailscaleHostname;
@@ -10483,7 +10503,7 @@ async function pollCycle() {
10483
10503
  const {
10484
10504
  collectResponsivenessProbes,
10485
10505
  getResponsivenessIntervalMs
10486
- } = await import("../responsiveness-probe-T2VF5SVF.js");
10506
+ } = await import("../responsiveness-probe-JYF7XPI2.js");
10487
10507
  const probeIntervalMs = getResponsivenessIntervalMs();
10488
10508
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
10489
10509
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -10515,7 +10535,7 @@ async function pollCycle() {
10515
10535
  collectResponsivenessProbes,
10516
10536
  livePendingInboundOldestAgeSeconds,
10517
10537
  parkPendingInbound
10518
- } = await import("../responsiveness-probe-T2VF5SVF.js");
10538
+ } = await import("../responsiveness-probe-JYF7XPI2.js");
10519
10539
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-HYOOQV4A.js");
10520
10540
  const wedgeNow = /* @__PURE__ */ new Date();
10521
10541
  const liveAgents = agentState.persistentSessionAgents;
@@ -12128,17 +12148,22 @@ async function processAgent(agent, agentStates) {
12128
12148
  });
12129
12149
  }
12130
12150
  agentState.knownIntegrationMembership.set(agent.agent_id, currentIntIds);
12151
+ const capSurfaceHash = computeCapabilitySurfaceHash(integrations);
12152
+ const prevCapSurfaceHash = agentState.knownCapabilitySurfaceHashes.get(agent.agent_id);
12153
+ const capSurfaceNames = integrations.map((i) => i.display_name || i.definition_id).join(", ");
12154
+ const intMembership = membershipSignature(integrations.map((i) => i.definition_id));
12155
+ const intFlap = mcpFlapDampener.record(agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
12156
+ if (intFlap.onset) {
12157
+ log(
12158
+ `[mcp-flap-dampener] integration set for '${agent.code_name}' is FLAPPING (${intFlap.tier} tier: ${intFlap.transitions} transitions / ${intFlap.distinctStates} states in window) - suppressing integration-update notices until it settles (ENG-6123, ENG-6512)`
12159
+ );
12160
+ recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
12161
+ }
12162
+ let reapNote = "";
12163
+ let rotationHandled = true;
12131
12164
  if (integrations.length > 0) {
12132
12165
  const intHash = computeIntegrationsHash(integrations);
12133
12166
  const prevIntHash = agentState.knownIntegrationHashes.get(agent.agent_id);
12134
- const intMembership = membershipSignature(integrations.map((i) => i.definition_id));
12135
- const intFlap = mcpFlapDampener.record(agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
12136
- if (intFlap.onset) {
12137
- log(
12138
- `[mcp-flap-dampener] integration set for '${agent.code_name}' is FLAPPING (${intFlap.tier} tier: ${intFlap.transitions} transitions / ${intFlap.distinctStates} states in window) \u2014 suppressing integration-update notices until it settles (ENG-6123, ENG-6512)`
12139
- );
12140
- recordConfigChurnEvent(agent.agent_id, agent.code_name, FLAP_CHANNEL_INTEGRATIONS, intMembership);
12141
- }
12142
12167
  if (intHash !== prevIntHash) {
12143
12168
  const projectDir = join21(homedir10(), ".augmented", agent.code_name, "project");
12144
12169
  const envIntPath = join21(projectDir, ".env.integrations");
@@ -12159,7 +12184,6 @@ async function processAgent(agent, agentStates) {
12159
12184
  );
12160
12185
  stopOpencodeSession(agent.code_name, log);
12161
12186
  }
12162
- let rotationHandled = true;
12163
12187
  if (fw === "claude-code" && isSessionHealthy(agent.code_name)) {
12164
12188
  try {
12165
12189
  const projectMcpPath = join21(projectDir, ".mcp.json");
@@ -12186,18 +12210,11 @@ async function processAgent(agent, agentStates) {
12186
12210
  const rotatedOnlyVars = new Set(envDiff.rotated);
12187
12211
  const envRespawnReason = respawnVars.length > 0 && respawnVars.every((v) => rotatedOnlyVars.has(v)) ? "credential-rotation" : "hot-reload-mcp";
12188
12212
  const needsRespawn = respawnVars.length > 0 && !intFlap.flapping;
12189
- const names = integrations.map((i) => i.display_name || i.definition_id).join(", ");
12190
12213
  const reconnectNote = affectedServerKeys.length > 0 ? ` The MCP servers that depend on rotating credentials (${affectedServerKeys.join(", ")}) have been signalled to reconnect.` : "";
12191
12214
  const restartNote = needsRespawn ? " Your session will restart shortly to apply the change (ENG-7510)." : "";
12192
- const reapNote = `${reconnectNote}${restartNote}`;
12193
- if (intFlap.flapping) {
12194
- log(`[mcp-flap-dampener] suppressed integration-update notice for '${agent.code_name}' (set flapping, ENG-6123): ${names}`);
12195
- } else {
12196
- injectMessage(agent.code_name, "system", `Your integrations have been refreshed. You have access to: ${names}.${reapNote}`, {
12197
- task_name: "integration-update"
12198
- }, log).catch(() => {
12199
- });
12200
- log(`[hot-reload] Notified '${agent.code_name}' about integration update: ${names} (reaped ${affectedServerKeys.length} stale MCP server(s))`);
12215
+ reapNote = `${reconnectNote}${restartNote}`;
12216
+ if (!intFlap.flapping && capSurfaceHash === prevCapSurfaceHash) {
12217
+ log(`[hot-reload] Suppressed integration-update notice for '${agent.code_name}' - capability surface unchanged (credential/config rotation only, ENG-7946): ${capSurfaceNames}`);
12201
12218
  }
12202
12219
  if (needsRespawn) {
12203
12220
  scheduleSessionRestart(
@@ -12220,6 +12237,18 @@ async function processAgent(agent, agentStates) {
12220
12237
  }
12221
12238
  }
12222
12239
  }
12240
+ if (capSurfaceHash !== prevCapSurfaceHash && rotationHandled) {
12241
+ if (intFlap.flapping) {
12242
+ log(`[mcp-flap-dampener] suppressed integration-update notice for '${agent.code_name}' (set flapping, ENG-6123): ${capSurfaceNames}`);
12243
+ } else {
12244
+ injectMessage(agent.code_name, "system", `Your integrations have been refreshed. You have access to: ${capSurfaceNames}.${reapNote}`, {
12245
+ task_name: "integration-update"
12246
+ }, log).catch(() => {
12247
+ });
12248
+ log(`[hot-reload] Notified '${agent.code_name}' about integration update: ${capSurfaceNames}`);
12249
+ }
12250
+ agentState.knownCapabilitySurfaceHashes.set(agent.agent_id, capSurfaceHash);
12251
+ }
12223
12252
  const fwForMcp = agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK;
12224
12253
  if (frameworkAdapter.writeMcpServer) {
12225
12254
  try {
@@ -13701,7 +13730,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
13701
13730
  void api.post("/host/restart-ack", { host_id: hostId, agent_id: agentId, restart_requested_at: requestedAt }).catch((err) => log(`[restart-lane] ack failed for '${codeName}': ${err.message}`));
13702
13731
  void (async () => {
13703
13732
  try {
13704
- const { collectDiagnostics } = await import("../persistent-session-PGKQK5VU.js");
13733
+ const { collectDiagnostics } = await import("../persistent-session-FZF7EPUW.js");
13705
13734
  await api.post("/host/heartbeat", {
13706
13735
  host_id: hostId,
13707
13736
  agent_diagnostics: collectDiagnostics([codeName])
@@ -13751,7 +13780,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
13751
13780
  }
13752
13781
  try {
13753
13782
  const hostId = await getHostId();
13754
- const { collectDiagnostics } = await import("../persistent-session-PGKQK5VU.js");
13783
+ const { collectDiagnostics } = await import("../persistent-session-FZF7EPUW.js");
13755
13784
  await api.post("/host/heartbeat", {
13756
13785
  host_id: hostId,
13757
13786
  agent_diagnostics: collectDiagnostics([codeName])
@@ -14204,7 +14233,7 @@ async function processClaudePairSessions(agents) {
14204
14233
  killPairSession,
14205
14234
  pairTmuxSession,
14206
14235
  finalizeClaudePairOnboarding
14207
- } = await import("../claude-pair-runtime-SJW25IRD.js");
14236
+ } = await import("../claude-pair-runtime-YF3ZEFKV.js");
14208
14237
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
14209
14238
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
14210
14239
  const killed = await killPairSession(pairTmuxSession(pairId));