@integrity-labs/agt-cli 0.19.19 → 0.19.21

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.
@@ -22,7 +22,7 @@ import {
22
22
  resolveChannels,
23
23
  resolveDmTarget,
24
24
  wrapScheduledTaskPrompt
25
- } from "../chunk-WQJL6EGC.js";
25
+ } from "../chunk-5WDQ5G5M.js";
26
26
  import {
27
27
  findTaskByTemplate,
28
28
  getProjectDir,
@@ -1811,18 +1811,41 @@ var config = null;
1811
1811
  var running = false;
1812
1812
  var pollTimer = null;
1813
1813
  var PANE_TAIL_PREVIEW_LINES = 5;
1814
- function extractCharterTelegramPeers(rawContent) {
1814
+ function extractCharterTelegramPeers(rawContent, gateContext) {
1815
1815
  if (!rawContent || rawContent.length === 0) return [];
1816
1816
  try {
1817
1817
  const parsed = extractFrontmatter(rawContent);
1818
1818
  const frontmatter = parsed.frontmatter;
1819
1819
  const peers = frontmatter?.multi_agent?.telegram_peers;
1820
1820
  if (!peers || !Array.isArray(peers)) return [];
1821
+ const teamBotIds = new Set(gateContext?.teamPeerBotIds ?? []);
1822
+ const grants = gateContext?.crossTeamGrants ?? [];
1823
+ const intraOrg = gateContext?.crossTeamPeerIntraOrg ?? "unrestricted";
1824
+ const now = (gateContext?.now ?? (() => /* @__PURE__ */ new Date()))();
1821
1825
  const out = [];
1822
1826
  for (const p of peers) {
1823
- if (p && typeof p === "object" && typeof p.code_name === "string" && typeof p.bot_id === "number" && Number.isInteger(p.bot_id) && p.bot_id > 0) {
1824
- out.push({ code_name: p.code_name, bot_id: p.bot_id, agent_id: "" });
1827
+ if (!p || typeof p !== "object" || typeof p.code_name !== "string" || typeof p.bot_id !== "number" || !Number.isInteger(p.bot_id) || p.bot_id <= 0) {
1828
+ continue;
1829
+ }
1830
+ const grantId = typeof p.cross_team_grant_id === "string" && p.cross_team_grant_id.length > 0 ? p.cross_team_grant_id : null;
1831
+ let gate = null;
1832
+ if (gateContext === void 0) {
1833
+ gate = "same_team";
1834
+ } else if (teamBotIds.has(p.bot_id)) {
1835
+ gate = "same_team";
1836
+ } else if (grantId) {
1837
+ const grant = grants.find((g) => g.grant_id === grantId);
1838
+ if (grant && !grant.revoked_at && (!grant.expires_at || new Date(grant.expires_at) > now) && grant.granted_agent_bot_id === p.bot_id) {
1839
+ gate = `grant:${grantId}`;
1840
+ } else {
1841
+ gate = null;
1842
+ }
1843
+ } else if (intraOrg === "unrestricted") {
1844
+ gate = "intra_org_unrestricted";
1845
+ } else {
1846
+ gate = null;
1825
1847
  }
1848
+ out.push({ code_name: p.code_name, bot_id: p.bot_id, agent_id: "", gate_path: gate });
1826
1849
  }
1827
1850
  return out;
1828
1851
  } catch {
@@ -1968,7 +1991,7 @@ function clearAgentCaches(agentId, codeName) {
1968
1991
  var cachedFrameworkVersion = null;
1969
1992
  var lastVersionCheckAt = 0;
1970
1993
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
1971
- var agtCliVersion = true ? "0.19.19" : "dev";
1994
+ var agtCliVersion = true ? "0.19.21" : "dev";
1972
1995
  function resolveBrewPath(execFileSync3) {
1973
1996
  try {
1974
1997
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -2920,6 +2943,22 @@ async function pollCycle() {
2920
2943
  }
2921
2944
  const data = await api.post("/host/agents", { host_id: hostId });
2922
2945
  const agents = data.agents ?? [];
2946
+ const restartAcks = /* @__PURE__ */ new Map();
2947
+ for (const agent of agents) {
2948
+ const requested = agent.restart_requested_at ?? null;
2949
+ if (!requested) continue;
2950
+ const prev = state.agents.find((a) => a.agentId === agent.agent_id);
2951
+ const lastProcessed = prev?.lastRestartProcessedAt ?? null;
2952
+ if (lastProcessed && Date.parse(lastProcessed) >= Date.parse(requested)) continue;
2953
+ log(`[restart] Dashboard requested restart for '${agent.code_name}' at ${requested}`);
2954
+ try {
2955
+ const { execSync: es } = await import("child_process");
2956
+ es(`tmux kill-session -t agt-${agent.code_name} 2>/dev/null`, { stdio: "ignore" });
2957
+ } catch {
2958
+ }
2959
+ stopPersistentSessionAndForgetMcpBaseline(agent.code_name);
2960
+ restartAcks.set(agent.agent_id, requested);
2961
+ }
2923
2962
  const frameworksThisCycle = new Set(agents.map((a) => a.framework).filter(Boolean));
2924
2963
  for (const fw of frameworksThisCycle) {
2925
2964
  await ensureFrameworkBinary(fw);
@@ -2954,6 +2993,18 @@ async function pollCycle() {
2954
2993
  }
2955
2994
  }
2956
2995
  }
2996
+ if (restartAcks.size > 0) {
2997
+ for (const ack of agentStates) {
2998
+ const requested = restartAcks.get(ack.agentId);
2999
+ if (requested) ack.lastRestartProcessedAt = requested;
3000
+ }
3001
+ try {
3002
+ const ackedState = { ...state, agents: agentStates };
3003
+ writeFileSync3(getStateFile(), JSON.stringify(ackedState, null, 2));
3004
+ } catch (err) {
3005
+ log(`[restart] failed to persist ack immediately: ${err.message}`);
3006
+ }
3007
+ }
2957
3008
  try {
2958
3009
  for (const [channelId, codeNames] of activeChannels) {
2959
3010
  for (const codeName of codeNames) {
@@ -3447,13 +3498,30 @@ async function processAgent(agent, agentStates) {
3447
3498
  activeChannels.set(channelId, /* @__PURE__ */ new Set());
3448
3499
  }
3449
3500
  activeChannels.get(channelId).add(agent.code_name);
3450
- const teamSettingsForHash = channelId === "telegram" ? {
3451
- telegram_peer_disabled: Boolean(
3452
- refreshData.team?.settings?.["telegram_peer_disabled"] ?? false
3453
- )
3454
- } : null;
3455
- const peersForHash = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "") : null;
3456
- const configHash = createHash2("sha256").update(canonicalJson({ config: entry.config, team: teamSettingsForHash, peers: peersForHash })).digest("hex");
3501
+ const teamSettings = refreshData.team?.settings;
3502
+ const peerDisabledMode = (() => {
3503
+ const next = teamSettings?.["peer_disabled"];
3504
+ if (next === "off" || next === "cross_team_only" || next === "all") return next;
3505
+ return teamSettings?.["telegram_peer_disabled"] === true ? "all" : "off";
3506
+ })();
3507
+ const teamSettingsForHash = channelId === "telegram" || channelId === "slack" ? { peer_disabled: peerDisabledMode } : null;
3508
+ const crossTeamData = refreshData;
3509
+ const refreshHasCrossTeamFields = Array.isArray(crossTeamData.team_peer_bot_ids);
3510
+ const gateContext = refreshHasCrossTeamFields ? {
3511
+ teamPeerBotIds: crossTeamData.team_peer_bot_ids ?? [],
3512
+ crossTeamGrants: crossTeamData.cross_team_grants?.inbound ?? [],
3513
+ crossTeamPeerIntraOrg: crossTeamData.organization?.cross_team_peer_intra_org ?? "unrestricted"
3514
+ } : void 0;
3515
+ const peersForHash = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "", gateContext) : null;
3516
+ const CHANNEL_WRITE_VERSION = 2;
3517
+ const configHash = createHash2("sha256").update(
3518
+ canonicalJson({
3519
+ writeVersion: CHANNEL_WRITE_VERSION,
3520
+ config: entry.config,
3521
+ team: teamSettingsForHash,
3522
+ peers: peersForHash
3523
+ })
3524
+ ).digest("hex");
3457
3525
  const cacheKey = `${agent.agent_id}:${channelId}`;
3458
3526
  let onDiskPresent = true;
3459
3527
  try {
@@ -3473,15 +3541,14 @@ async function processAgent(agent, agentStates) {
3473
3541
  }
3474
3542
  try {
3475
3543
  const sessionMode2 = refreshData.agent.session_mode;
3476
- const telegramPeerDisabled = channelId === "telegram" ? Boolean(
3477
- refreshData.team?.settings?.["telegram_peer_disabled"] ?? false
3478
- ) : void 0;
3479
- const telegramPeers = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "") : void 0;
3544
+ const peerDisabled = channelId === "telegram" || channelId === "slack" ? peerDisabledMode : void 0;
3545
+ const telegramPeerDisabled = channelId === "telegram" ? peerDisabledMode === "all" : void 0;
3546
+ const telegramPeers = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "", gateContext) : void 0;
3480
3547
  frameworkAdapter.writeChannelCredentials(
3481
3548
  agent.code_name,
3482
3549
  channelId,
3483
3550
  entry.config,
3484
- { sessionMode: sessionMode2, agentId: agent.agent_id, telegramPeerDisabled, telegramPeers }
3551
+ { sessionMode: sessionMode2, agentId: agent.agent_id, telegramPeerDisabled, peerDisabled, telegramPeers }
3485
3552
  );
3486
3553
  knownChannelConfigHashes.set(cacheKey, configHash);
3487
3554
  saveChannelHashCache2();
@@ -6711,6 +6778,19 @@ async function stopPolling(opts = {}) {
6711
6778
  }
6712
6779
  function startManager(opts) {
6713
6780
  config = opts;
6781
+ try {
6782
+ const stateFile = getStateFile();
6783
+ if (existsSync3(stateFile)) {
6784
+ const raw = readFileSync3(stateFile, "utf-8");
6785
+ const parsed = JSON.parse(raw);
6786
+ if (Array.isArray(parsed.agents)) {
6787
+ state.agents = parsed.agents;
6788
+ log(`[startup] rehydrated ${state.agents.length} agent state(s) from ${stateFile}`);
6789
+ }
6790
+ }
6791
+ } catch (err) {
6792
+ log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
6793
+ }
6714
6794
  log(
6715
6795
  `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join4(homedir3(), ".augmented", "manager.log")}`
6716
6796
  );
@@ -6879,6 +6959,7 @@ process.on("disconnect", () => {
6879
6959
  });
6880
6960
  export {
6881
6961
  ChildProcessError,
6962
+ extractCharterTelegramPeers,
6882
6963
  markAgentForFreshMemorySync,
6883
6964
  startManager,
6884
6965
  stopManager