@integrity-labs/agt-cli 0.28.765 → 0.28.767

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-3OBDKYWF.js");
103
+ const { resolveClaudeBinary } = await import("./persistent-session-XPJ6YZEE.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-U6WDTNK3.js.map
376
+ //# sourceMappingURL=claude-pair-runtime-ZKEI6HFO.js.map
@@ -58,7 +58,7 @@ import {
58
58
  safeWriteJsonAtomic,
59
59
  setConfigHash,
60
60
  tripClass
61
- } from "../chunk-EWH4J63B.js";
61
+ } from "../chunk-WWOUMYOV.js";
62
62
  import {
63
63
  getProjectDir as getProjectDir2,
64
64
  getReadyTasks,
@@ -120,7 +120,7 @@ import {
120
120
  takeZombieDetection,
121
121
  toOpencodeModel,
122
122
  writeEgressAllowlist
123
- } from "../chunk-LVBINNTQ.js";
123
+ } from "../chunk-TMBYNXY2.js";
124
124
  import {
125
125
  ACCOUNT_ENFORCEMENT_MARKER_FILENAME,
126
126
  AnchorSessionClient,
@@ -246,6 +246,49 @@ import { join as join41, dirname as dirname10, delimiter as pathDelimiter } from
246
246
  import { homedir as homedir17 } from "os";
247
247
  import { fileURLToPath } from "url";
248
248
 
249
+ // ../../packages/core/dist/provisioning/channel-policy-env.js
250
+ var TELEGRAM_RESTART_ON_CHANGE_ENV_KEYS = [
251
+ /** Who may talk to the agent — and, at four MCP call sites, who it may send to. */
252
+ "TELEGRAM_ALLOWED_CHATS",
253
+ /** Drops every group / supergroup / channel message. A containment control. */
254
+ "TELEGRAM_PRIVATE_CHATS_ONLY",
255
+ /** Peer kill switch. A switch whose purpose is stopping something promptly. */
256
+ "PEER_DISABLED",
257
+ /** Derived boolean mirror of the same switch, kept for the rollout. */
258
+ "TELEGRAM_PEER_DISABLED"
259
+ ];
260
+ function telegramPolicyEnvBasis(env) {
261
+ const parts = [];
262
+ for (const key of [...TELEGRAM_RESTART_ON_CHANGE_ENV_KEYS].sort()) {
263
+ const raw = env[key];
264
+ if (raw === void 0)
265
+ continue;
266
+ const value = key === "TELEGRAM_ALLOWED_CHATS" ? [...new Set(raw.split(",").map((v) => v.trim()).filter((v) => v.length > 0))].sort().join(",") : raw.trim();
267
+ parts.push(`${key}=${value}`);
268
+ }
269
+ return parts.join("\n");
270
+ }
271
+ function telegramPolicyEnvFromInputs(config2, opts) {
272
+ const env = {};
273
+ const allowedChats = config2["allowed_chats"];
274
+ if (Array.isArray(allowedChats)) {
275
+ const ids = allowedChats.map((v) => typeof v === "string" || typeof v === "number" ? String(v).trim() : "").filter((v) => v.length > 0);
276
+ if (ids.length > 0)
277
+ env["TELEGRAM_ALLOWED_CHATS"] = ids.join(",");
278
+ }
279
+ if (config2["private_chats_only"] === true)
280
+ env["TELEGRAM_PRIVATE_CHATS_ONLY"] = "1";
281
+ const mode = opts?.peerDisabledMode;
282
+ if (mode && mode !== "off")
283
+ env["PEER_DISABLED"] = mode;
284
+ if (mode === "all")
285
+ env["TELEGRAM_PEER_DISABLED"] = "true";
286
+ return env;
287
+ }
288
+ function isTelegramPolicyRestrictive(env) {
289
+ return telegramPolicyEnvBasis(env).length > 0;
290
+ }
291
+
249
292
  // src/lib/single-flight.ts
250
293
  function createSingleFlight(task, opts = {}) {
251
294
  let running2 = false;
@@ -5993,12 +6036,23 @@ import { existsSync as existsSync10, readFileSync as readFileSync21 } from "fs";
5993
6036
  import { join as join27 } from "path";
5994
6037
  var BASELINE_FILENAME = "sender-policy-baseline.json";
5995
6038
  var SENDER_POLICY_BASELINE_VERSION = 1;
5996
- var BASELINE_CONCERNS = ["senderPolicy", "slackBehaviour", "msteamsBehaviour"];
6039
+ var BASELINE_CONCERNS = [
6040
+ "senderPolicy",
6041
+ "slackBehaviour",
6042
+ "msteamsBehaviour",
6043
+ // ENG-9802: the telegram chat policy (allowlist / private-chats-only / peer
6044
+ // kill switch). Same shape and same reason as senderPolicy — the MCP child
6045
+ // reads it once at boot, so a change has to be delivered by a respawn, and
6046
+ // the baseline has to survive a manager restart or every deploy would look
6047
+ // like a first poll and respawn the fleet (ENG-7771).
6048
+ "telegramPolicy"
6049
+ ];
5997
6050
  function createDeliveryBaselineMaps() {
5998
6051
  return {
5999
6052
  senderPolicy: /* @__PURE__ */ new Map(),
6000
6053
  slackBehaviour: /* @__PURE__ */ new Map(),
6001
- msteamsBehaviour: /* @__PURE__ */ new Map()
6054
+ msteamsBehaviour: /* @__PURE__ */ new Map(),
6055
+ telegramPolicy: /* @__PURE__ */ new Map()
6002
6056
  };
6003
6057
  }
6004
6058
  function getSenderPolicyBaselineFile(configDir) {
@@ -6575,6 +6629,8 @@ var agentState = {
6575
6629
  * (they read SLACK_SENDER_POLICY / MSTEAMS_SENDER_POLICY only at boot).
6576
6630
  */
6577
6631
  knownSenderPolicyHashes: /* @__PURE__ */ new Map(),
6632
+ /** ENG-9802: per-agent telegram chat-policy hash (allowlist / private-chats-only / peer kill switch). */
6633
+ knownTelegramPolicyHashes: /* @__PURE__ */ new Map(),
6578
6634
  /**
6579
6635
  * ENG-6024: hash of the Teams behaviour subset (thread_auto_follow,
6580
6636
  * channel_response_mode, adaptive_cards_enabled/_ask_user_enabled) from the
@@ -6662,6 +6718,7 @@ function clearAgentState(agentId, codeName) {
6662
6718
  agentState.knownManagedMcpHashes.delete(agentId);
6663
6719
  agentState.knownManagedMcpStructure.delete(agentId);
6664
6720
  agentState.knownSenderPolicyHashes.delete(agentId);
6721
+ agentState.knownTelegramPolicyHashes.delete(agentId);
6665
6722
  agentState.knownMsTeamsBehaviourHashes.delete(agentId);
6666
6723
  agentState.knownSlackBehaviourHashes.delete(agentId);
6667
6724
  agentState.knownGlobalSkillIds.delete(agentId);
@@ -12659,6 +12716,11 @@ function scheduleSessionRestart(codeName, delayMs, reason, breakerReason = "hot-
12659
12716
  baselineAgentId,
12660
12717
  agentState.knownMsTeamsBehaviourHashes.get(baselineAgentId)
12661
12718
  );
12719
+ persistDeliveryBaselineEntry(
12720
+ "telegramPolicy",
12721
+ baselineAgentId,
12722
+ agentState.knownTelegramPolicyHashes.get(baselineAgentId)
12723
+ );
12662
12724
  }
12663
12725
  }
12664
12726
  runningMcpHashes.delete(codeName);
@@ -12808,7 +12870,7 @@ var pendingDayRolloverReset = /* @__PURE__ */ new Set();
12808
12870
  var dayRolloverInboundHold = /* @__PURE__ */ new Map();
12809
12871
  var INBOUND_HOLD_EPISODE_GAP_MS = 12e4;
12810
12872
  async function channelInboundActivityAgeSecondsFor(codeName) {
12811
- const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-ULIAXSCT.js");
12873
+ const { newestPendingInboundActivityMtimeMs } = await import("../responsiveness-probe-T7VDLDM7.js");
12812
12874
  const newest = newestPendingInboundActivityMtimeMs(dirname10(paneLogPath(codeName)));
12813
12875
  if (newest === null) return null;
12814
12876
  return Math.max(0, Math.floor((Date.now() - newest) / 1e3));
@@ -13468,7 +13530,7 @@ var agentRestartTimezoneInputs = /* @__PURE__ */ new Map();
13468
13530
  var lastVersionCheckAt = 0;
13469
13531
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
13470
13532
  var lastResponsivenessProbeAt = 0;
13471
- var agtCliVersion = true ? "0.28.765" : "dev";
13533
+ var agtCliVersion = true ? "0.28.767" : "dev";
13472
13534
  function resolveBrewPath(execFileSync2) {
13473
13535
  try {
13474
13536
  const out = execFileSync2("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -14723,6 +14785,9 @@ function loadSenderPolicyBaseline2() {
14723
14785
  for (const [agentId, hash] of persistedDeliveryBaseline.msteamsBehaviour) {
14724
14786
  agentState.knownMsTeamsBehaviourHashes.set(agentId, hash);
14725
14787
  }
14788
+ for (const [agentId, hash] of persistedDeliveryBaseline.telegramPolicy) {
14789
+ agentState.knownTelegramPolicyHashes.set(agentId, hash);
14790
+ }
14726
14791
  }
14727
14792
  var deliveryBaselineDirty = false;
14728
14793
  function saveDeliveryBaseline() {
@@ -15009,7 +15074,7 @@ function flushRestartedAgentDiagnostics(hostId, codeNames) {
15009
15074
  if (codeNames.length === 0) return;
15010
15075
  void (async () => {
15011
15076
  try {
15012
- const { collectDiagnostics } = await import("../persistent-session-3OBDKYWF.js");
15077
+ const { collectDiagnostics } = await import("../persistent-session-XPJ6YZEE.js");
15013
15078
  await api.post("/host/heartbeat", {
15014
15079
  host_id: hostId,
15015
15080
  agent_diagnostics: collectDiagnostics(codeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -15150,7 +15215,7 @@ async function pollCycleInner() {
15150
15215
  }
15151
15216
  try {
15152
15217
  const { detectHostSecurity } = await import("../host-security-6PDFG7F5.js");
15153
- const { collectDiagnostics } = await import("../persistent-session-3OBDKYWF.js");
15218
+ const { collectDiagnostics } = await import("../persistent-session-XPJ6YZEE.js");
15154
15219
  const diagCodeNames = [...agentState.persistentSessionAgents];
15155
15220
  const agentDiagnostics = diagCodeNames.length > 0 ? collectDiagnostics(diagCodeNames, quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor) : void 0;
15156
15221
  let tailscaleHostname;
@@ -15319,7 +15384,7 @@ async function pollCycleInner() {
15319
15384
  collectPanelessActivityProbes,
15320
15385
  getResponsivenessIntervalMs,
15321
15386
  occupancyQualificationClassifications
15322
- } = await import("../responsiveness-probe-ULIAXSCT.js");
15387
+ } = await import("../responsiveness-probe-T7VDLDM7.js");
15323
15388
  const probeIntervalMs = getResponsivenessIntervalMs();
15324
15389
  if (now - lastResponsivenessProbeAt > probeIntervalMs) {
15325
15390
  const probeCodeNames = [...agentState.persistentSessionAgents];
@@ -15429,7 +15494,7 @@ async function pollCycleInner() {
15429
15494
  collectResponsivenessProbes,
15430
15495
  livePendingInboundOldestAgeSeconds,
15431
15496
  parkPendingInbound
15432
- } = await import("../responsiveness-probe-ULIAXSCT.js");
15497
+ } = await import("../responsiveness-probe-T7VDLDM7.js");
15433
15498
  const { getProjectDir: wedgeProjectDir } = await import("../scheduler-engine-NDP36U7O.js");
15434
15499
  const wedgeNow = /* @__PURE__ */ new Date();
15435
15500
  const liveAgents = agentState.persistentSessionAgents;
@@ -16491,6 +16556,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
16491
16556
  const known = agentState.knownVersions.get(agent.agent_id);
16492
16557
  let lastProvisionAt = state8.agents.find((a) => a.agentId === agent.agent_id)?.lastProvisionAt ?? null;
16493
16558
  const quarantinedChannels = channelQuarantineStore().getQuarantinedKeys(agent.code_name);
16559
+ let telegramPolicyEnvForRestart;
16494
16560
  const currentChannelIds = setWithout(
16495
16561
  launchableChannelIds(refreshData.channel_configs),
16496
16562
  quarantinedChannels
@@ -16805,6 +16871,12 @@ async function processAgent(agent, agentStates, managedToolkits) {
16805
16871
  if (next === "off" || next === "cross_team_only" || next === "all") return next;
16806
16872
  return teamSettings?.["telegram_peer_disabled"] === true ? "all" : "off";
16807
16873
  })();
16874
+ if (channelId === "telegram") {
16875
+ telegramPolicyEnvForRestart = telegramPolicyEnvFromInputs(
16876
+ entry.config,
16877
+ { peerDisabledMode }
16878
+ );
16879
+ }
16808
16880
  const agentTimezone = (() => {
16809
16881
  const tz = teamSettings?.["timezone"];
16810
16882
  return typeof tz === "string" && tz.trim() !== "" ? tz.trim() : void 0;
@@ -17092,6 +17164,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
17092
17164
  persistDeliveryBaselineEntry("senderPolicy", agent.agent_id, senderPolicyHash);
17093
17165
  }
17094
17166
  let msteamsBehaviourRestartScheduled = false;
17167
+ let slackBehaviourRestartScheduled = false;
17095
17168
  if (currentChannelIds.has("msteams")) {
17096
17169
  const msteamsEntry = refreshData.channel_configs?.["msteams"];
17097
17170
  const behaviourSubset = extractMsTeamsBehaviourSubset(
@@ -17194,6 +17267,7 @@ async function processAgent(agent, agentStates, managedToolkits) {
17194
17267
  "channel-behaviour-change"
17195
17268
  );
17196
17269
  }
17270
+ if (slackBehaviourDecision.restart) slackBehaviourRestartScheduled = true;
17197
17271
  agentState.knownSlackBehaviourHashes.set(agent.agent_id, slackBehaviourHash);
17198
17272
  const hasLiveSlackBehaviourConsumer = spSessionHealthy && spSessionMode === "persistent" && spFramework === "claude-code";
17199
17273
  if (!hasLiveSlackBehaviourConsumer) {
@@ -17205,6 +17279,59 @@ async function processAgent(agent, agentStates, managedToolkits) {
17205
17279
  agentState.knownSlackBehaviourHashes.delete(agent.agent_id);
17206
17280
  removeDeliveryBaselineEntry("slackBehaviour", agent.agent_id);
17207
17281
  }
17282
+ if (currentChannelIds.has("telegram")) {
17283
+ const telegramPolicyEnv = telegramPolicyEnvForRestart ?? {};
17284
+ const telegramPolicyHash = createHash20("sha256").update(telegramPolicyEnvBasis(telegramPolicyEnv)).digest("hex");
17285
+ const prevTelegramPolicyHash = agentState.knownTelegramPolicyHashes.get(agent.agent_id);
17286
+ const telegramPolicyRestrictive = isTelegramPolicyRestrictive(telegramPolicyEnv);
17287
+ const telegramPolicyDecision = decideSenderPolicyRestart({
17288
+ previousHash: prevTelegramPolicyHash,
17289
+ currentPolicyRestrictive: telegramPolicyRestrictive,
17290
+ currentHash: telegramPolicyHash,
17291
+ sessionMode: spSessionMode,
17292
+ framework: spFramework,
17293
+ sessionHealthy: spSessionHealthy,
17294
+ // Any earlier restart scheduled this tick already respawns the MCP
17295
+ // children with the freshly-written env.
17296
+ channelSetRestartAlreadyScheduled: channelSetRestartScheduled || senderPolicyDecision.restart || msteamsBehaviourRestartScheduled || slackBehaviourRestartScheduled
17297
+ });
17298
+ if (telegramPolicyDecision.restart) {
17299
+ const isTelegramVerifyRestart = telegramPolicyDecision.firstPoll;
17300
+ log(
17301
+ isTelegramVerifyRestart ? `[hot-reload] telegram chat-policy delivery baseline unknown for '${agent.code_name}' with a policy set (\u2192 ${telegramPolicyHash.slice(0, 8)}) \u2014 restarting session to guarantee enforcement (fail closed, ENG-9802)` : `[hot-reload] telegram chat policy changed for '${agent.code_name}' (${prevTelegramPolicyHash?.slice(0, 8) ?? "first"} \u2192 ${telegramPolicyHash.slice(0, 8)}) \u2014 restarting session`
17302
+ );
17303
+ const telegramNotice = isTelegramVerifyRestart ? "Your manager was updated and needs to restart your session to make sure your configured Telegram chat policy is enforced by the channel MCP server." : "Your Telegram chat policy has been updated. Restarting session shortly so the channel MCP server picks up the new allowlist.";
17304
+ const telegramDelivered = await injectMessage(
17305
+ agent.code_name,
17306
+ "system",
17307
+ telegramNotice + BACK_ONLINE_GREETING_GUIDANCE,
17308
+ { task_name: "telegram-policy-update" },
17309
+ log
17310
+ ).catch(() => false);
17311
+ const telegramDelay = telegramDelivered ? 8e3 : 3e3;
17312
+ if (!telegramDelivered) {
17313
+ log(
17314
+ `[hot-reload] Inject notification unconfirmed for '${agent.code_name}' \u2014 proceeding with shorter delay`
17315
+ );
17316
+ }
17317
+ scheduleSessionRestart(
17318
+ agent.code_name,
17319
+ telegramDelay,
17320
+ isTelegramVerifyRestart ? "telegram chat-policy verify (unknown baseline)" : "telegram chat-policy change",
17321
+ "telegram-policy-change"
17322
+ );
17323
+ }
17324
+ agentState.knownTelegramPolicyHashes.set(agent.agent_id, telegramPolicyHash);
17325
+ const hasLiveTelegramPolicyConsumer = spSessionHealthy && spSessionMode === "persistent" && spFramework === "claude-code";
17326
+ if (!hasLiveTelegramPolicyConsumer) {
17327
+ persistDeliveryBaselineEntry("telegramPolicy", agent.agent_id, telegramPolicyHash);
17328
+ } else if (telegramPolicyDecision.firstPoll && !telegramPolicyRestrictive) {
17329
+ persistDeliveryBaselineEntry("telegramPolicy", agent.agent_id, telegramPolicyHash);
17330
+ }
17331
+ } else {
17332
+ agentState.knownTelegramPolicyHashes.delete(agent.agent_id);
17333
+ removeDeliveryBaselineEntry("telegramPolicy", agent.agent_id);
17334
+ }
17208
17335
  }
17209
17336
  const agentSessionMode = refreshData.agent.session_mode;
17210
17337
  if (agentSessionMode === "persistent" && (agentFrameworkCache.get(agent.code_name) ?? DEFAULT_FRAMEWORK) === "claude-code") {
@@ -19563,7 +19690,7 @@ async function handleRestartDoorbell(agentId, requestedAt, restartReason) {
19563
19690
  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}`));
19564
19691
  void (async () => {
19565
19692
  try {
19566
- const { collectDiagnostics } = await import("../persistent-session-3OBDKYWF.js");
19693
+ const { collectDiagnostics } = await import("../persistent-session-XPJ6YZEE.js");
19567
19694
  await api.post("/host/heartbeat", {
19568
19695
  host_id: hostId,
19569
19696
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -19609,7 +19736,7 @@ async function respawnAgentAfterMcpStop(codeName, reason) {
19609
19736
  }
19610
19737
  try {
19611
19738
  const hostId = await getHostId();
19612
- const { collectDiagnostics } = await import("../persistent-session-3OBDKYWF.js");
19739
+ const { collectDiagnostics } = await import("../persistent-session-XPJ6YZEE.js");
19613
19740
  await api.post("/host/heartbeat", {
19614
19741
  host_id: hostId,
19615
19742
  agent_diagnostics: collectDiagnostics([codeName], quarantineEntriesFor, claudeMdSizeFor, spawnOutcomeForDiagnostics, pidPressureFor, forwardedToolsFor)
@@ -20245,7 +20372,7 @@ async function processClaudePairSessions(agents) {
20245
20372
  killPairSession,
20246
20373
  pairTmuxSession,
20247
20374
  finalizeClaudePairOnboarding
20248
- } = await import("../claude-pair-runtime-U6WDTNK3.js");
20375
+ } = await import("../claude-pair-runtime-ZKEI6HFO.js");
20249
20376
  for (const pairId of pendingResp.cancelled_pair_ids ?? []) {
20250
20377
  log(`[claude-pair] sweeping orphan tmux session for pair ${pairId.slice(0, 8)}`);
20251
20378
  const killed = await killPairSession(pairTmuxSession(pairId));