@integrity-labs/agt-cli 0.19.18 → 0.19.20

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-WTFROCJ3.js";
25
+ } from "../chunk-IWFXAB4O.js";
26
26
  import {
27
27
  findTaskByTemplate,
28
28
  getProjectDir,
@@ -1811,6 +1811,47 @@ 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, gateContext) {
1815
+ if (!rawContent || rawContent.length === 0) return [];
1816
+ try {
1817
+ const parsed = extractFrontmatter(rawContent);
1818
+ const frontmatter = parsed.frontmatter;
1819
+ const peers = frontmatter?.multi_agent?.telegram_peers;
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()))();
1825
+ const out = [];
1826
+ for (const p of peers) {
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;
1847
+ }
1848
+ out.push({ code_name: p.code_name, bot_id: p.bot_id, agent_id: "", gate_path: gate });
1849
+ }
1850
+ return out;
1851
+ } catch {
1852
+ return [];
1853
+ }
1854
+ }
1814
1855
  function truncateForLog(s) {
1815
1856
  const lines = s.split("\n").filter((l) => l.length > 0);
1816
1857
  return lines.slice(-PANE_TAIL_PREVIEW_LINES).map((l) => ` | ${l}`).join("\n");
@@ -1950,7 +1991,7 @@ function clearAgentCaches(agentId, codeName) {
1950
1991
  var cachedFrameworkVersion = null;
1951
1992
  var lastVersionCheckAt = 0;
1952
1993
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
1953
- var agtCliVersion = true ? "0.19.18" : "dev";
1994
+ var agtCliVersion = true ? "0.19.20" : "dev";
1954
1995
  function resolveBrewPath(execFileSync3) {
1955
1996
  try {
1956
1997
  const out = execFileSync3("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -2902,6 +2943,22 @@ async function pollCycle() {
2902
2943
  }
2903
2944
  const data = await api.post("/host/agents", { host_id: hostId });
2904
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
+ }
2905
2962
  const frameworksThisCycle = new Set(agents.map((a) => a.framework).filter(Boolean));
2906
2963
  for (const fw of frameworksThisCycle) {
2907
2964
  await ensureFrameworkBinary(fw);
@@ -2936,6 +2993,18 @@ async function pollCycle() {
2936
2993
  }
2937
2994
  }
2938
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
+ }
2939
3008
  try {
2940
3009
  for (const [channelId, codeNames] of activeChannels) {
2941
3010
  for (const codeName of codeNames) {
@@ -3429,7 +3498,22 @@ async function processAgent(agent, agentStates) {
3429
3498
  activeChannels.set(channelId, /* @__PURE__ */ new Set());
3430
3499
  }
3431
3500
  activeChannels.get(channelId).add(agent.code_name);
3432
- const configHash = createHash2("sha256").update(canonicalJson(entry.config)).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 configHash = createHash2("sha256").update(canonicalJson({ config: entry.config, team: teamSettingsForHash, peers: peersForHash })).digest("hex");
3433
3517
  const cacheKey = `${agent.agent_id}:${channelId}`;
3434
3518
  let onDiskPresent = true;
3435
3519
  try {
@@ -3449,7 +3533,15 @@ async function processAgent(agent, agentStates) {
3449
3533
  }
3450
3534
  try {
3451
3535
  const sessionMode2 = refreshData.agent.session_mode;
3452
- frameworkAdapter.writeChannelCredentials(agent.code_name, channelId, entry.config, { sessionMode: sessionMode2, agentId: agent.agent_id });
3536
+ const peerDisabled = channelId === "telegram" || channelId === "slack" ? peerDisabledMode : void 0;
3537
+ const telegramPeerDisabled = channelId === "telegram" ? peerDisabledMode === "all" : void 0;
3538
+ const telegramPeers = channelId === "telegram" ? extractCharterTelegramPeers(refreshData.charter?.raw_content ?? "", gateContext) : void 0;
3539
+ frameworkAdapter.writeChannelCredentials(
3540
+ agent.code_name,
3541
+ channelId,
3542
+ entry.config,
3543
+ { sessionMode: sessionMode2, agentId: agent.agent_id, telegramPeerDisabled, peerDisabled, telegramPeers }
3544
+ );
3453
3545
  knownChannelConfigHashes.set(cacheKey, configHash);
3454
3546
  saveChannelHashCache2();
3455
3547
  log(`Channel credentials written for '${agent.code_name}/${channelId}' (reason=${reason}, hash=${configHash.slice(0, 8)}${prevHash ? `, prev=${prevHash.slice(0, 8)}` : ""})`);
@@ -3600,7 +3692,7 @@ async function processAgent(agent, agentStates) {
3600
3692
  preWriteEnv = void 0;
3601
3693
  }
3602
3694
  if (frameworkAdapter.writeIntegrations) {
3603
- frameworkAdapter.writeIntegrations(agent.code_name, integrations);
3695
+ frameworkAdapter.writeIntegrations(agent.code_name, integrations, agent.agent_id);
3604
3696
  }
3605
3697
  log(`Integrations provisioned for '${agent.code_name}' (${integrations.length} integration(s))`);
3606
3698
  const fw = agentFrameworkCache.get(agent.code_name) ?? "openclaw";
@@ -6678,6 +6770,19 @@ async function stopPolling(opts = {}) {
6678
6770
  }
6679
6771
  function startManager(opts) {
6680
6772
  config = opts;
6773
+ try {
6774
+ const stateFile = getStateFile();
6775
+ if (existsSync3(stateFile)) {
6776
+ const raw = readFileSync3(stateFile, "utf-8");
6777
+ const parsed = JSON.parse(raw);
6778
+ if (Array.isArray(parsed.agents)) {
6779
+ state.agents = parsed.agents;
6780
+ log(`[startup] rehydrated ${state.agents.length} agent state(s) from ${stateFile}`);
6781
+ }
6782
+ }
6783
+ } catch (err) {
6784
+ log(`[startup] state rehydration failed (continuing with empty state): ${err.message}`);
6785
+ }
6681
6786
  log(
6682
6787
  `[startup] worker pid=${process.pid} ppid=${process.ppid} node=${process.version} log=${join4(homedir3(), ".augmented", "manager.log")}`
6683
6788
  );
@@ -6846,6 +6951,7 @@ process.on("disconnect", () => {
6846
6951
  });
6847
6952
  export {
6848
6953
  ChildProcessError,
6954
+ extractCharterTelegramPeers,
6849
6955
  markAgentForFreshMemorySync,
6850
6956
  startManager,
6851
6957
  stopManager