@integrity-labs/agt-cli 0.27.98 → 0.27.100

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.
@@ -1,5 +1,6 @@
1
1
  import {
2
2
  ApiError,
3
+ CHANNEL_SECRET_ENV_KEYS,
3
4
  INTEGRATIONS_SECTION_END,
4
5
  INTEGRATIONS_SECTION_START,
5
6
  SUPERVISOR_RESTART_EXIT_CODE,
@@ -16,7 +17,7 @@ import {
16
17
  provisionStopHook,
17
18
  requireHost,
18
19
  safeWriteJsonAtomic
19
- } from "../chunk-S265L5AN.js";
20
+ } from "../chunk-DV3OH45P.js";
20
21
  import {
21
22
  getProjectDir as getProjectDir2,
22
23
  getReadyTasks,
@@ -114,6 +115,12 @@ function managedMcpStructureHash(entries) {
114
115
  const basis = entries.slice().sort((a, b) => a.serverId.localeCompare(b.serverId)).map((e) => `${e.serverId}|${Object.keys(e.headers ?? {}).sort().join(",")}`).join("\n");
115
116
  return createHash("sha256").update(basis).digest("hex").slice(0, 16);
116
117
  }
118
+ function channelSecretValueHash(envEntries, channelSecretKeys) {
119
+ if (!envEntries) return null;
120
+ const basis = channelSecretKeys.slice().sort().filter((k) => Object.prototype.hasOwnProperty.call(envEntries, k)).map((k) => `${k}=${envEntries[k]}`).join("\n");
121
+ if (basis.length === 0) return null;
122
+ return createHash("sha256").update(basis).digest("hex").slice(0, 16);
123
+ }
117
124
 
118
125
  // src/lib/integration-hash.ts
119
126
  import { createHash as createHash2 } from "crypto";
@@ -3780,6 +3787,7 @@ function restartGateFor(codeName, breakerReason) {
3780
3787
  }
3781
3788
  var runningMcpHashes = /* @__PURE__ */ new Map();
3782
3789
  var runningMcpServerKeys = /* @__PURE__ */ new Map();
3790
+ var runningChannelSecretHashes = /* @__PURE__ */ new Map();
3783
3791
  function projectMcpHash(_codeName, projectDir) {
3784
3792
  try {
3785
3793
  const raw = readFileSync9(join8(projectDir, ".mcp.json"), "utf-8");
@@ -3865,6 +3873,7 @@ function stopPersistentSessionAndForgetMcpBaseline(codeName, breakerReason) {
3865
3873
  stopPersistentSession(codeName, log);
3866
3874
  runningMcpHashes.delete(codeName);
3867
3875
  runningMcpServerKeys.delete(codeName);
3876
+ runningChannelSecretHashes.delete(codeName);
3868
3877
  closeInjectedRunIfOpen(codeName, "cancelled", `session stopped (${breakerReason ?? "deprovision"})`);
3869
3878
  closeScheduledRunsForCode(codeName, "cancelled", `session stopped (${breakerReason ?? "deprovision"})`);
3870
3879
  if (breakerReason) {
@@ -3933,6 +3942,35 @@ function checkMcpConfigDriftAndScheduleRestart(codeName, projectDir) {
3933
3942
  }
3934
3943
  }
3935
3944
  }
3945
+ function projectChannelSecretHash(projectDir) {
3946
+ try {
3947
+ const entries = parseEnvIntegrations(
3948
+ readFileSync9(join8(projectDir, ".env.integrations"), "utf-8")
3949
+ );
3950
+ return channelSecretValueHash(entries, CHANNEL_SECRET_ENV_KEYS);
3951
+ } catch {
3952
+ return null;
3953
+ }
3954
+ }
3955
+ function checkChannelSecretDriftAndScheduleRestart(codeName, projectDir) {
3956
+ const currentHash = projectChannelSecretHash(projectDir);
3957
+ const action = decideMcpDriftAction(currentHash, runningChannelSecretHashes.get(codeName));
3958
+ switch (action.kind) {
3959
+ case "no-config":
3960
+ case "no-drift":
3961
+ return;
3962
+ case "baseline":
3963
+ runningChannelSecretHashes.set(codeName, action.hash);
3964
+ return;
3965
+ case "drift":
3966
+ log(
3967
+ `[hot-reload] channel credential rotated for '${codeName}' (${action.previous} \u2192 ${action.current}) \u2014 respawning to load the new token (ENG-6062)`
3968
+ );
3969
+ scheduleSessionRestart(codeName, 0, "channel credential rotation (ENG-6062)");
3970
+ runningChannelSecretHashes.delete(codeName);
3971
+ return;
3972
+ }
3973
+ }
3936
3974
  var managedToolkitIdByAgentAndServerId = /* @__PURE__ */ new Map();
3937
3975
  function managedToolkitMapKey(agentId, serverId) {
3938
3976
  return `${agentId}\0${serverId}`;
@@ -3996,7 +4034,7 @@ var cachedMaintenanceWindow = null;
3996
4034
  var lastVersionCheckAt = 0;
3997
4035
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
3998
4036
  var lastResponsivenessProbeAt = 0;
3999
- var agtCliVersion = true ? "0.27.98" : "dev";
4037
+ var agtCliVersion = true ? "0.27.100" : "dev";
4000
4038
  function resolveBrewPath(execFileSync4) {
4001
4039
  try {
4002
4040
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -6857,6 +6895,13 @@ async function processAgent(agent, agentStates) {
6857
6895
  } catch (err) {
6858
6896
  log(`[hot-reload] .mcp.json drift check failed for '${agent.code_name}': ${err.message}`);
6859
6897
  }
6898
+ if (channelConfigConverged) {
6899
+ try {
6900
+ checkChannelSecretDriftAndScheduleRestart(agent.code_name, getProjectDir(agent.code_name));
6901
+ } catch (err) {
6902
+ log(`[hot-reload] channel-secret drift check failed for '${agent.code_name}': ${err.message}`);
6903
+ }
6904
+ }
6860
6905
  try {
6861
6906
  const sess = getSessionState(agent.code_name);
6862
6907
  let mcpJsonParsed = null;
@@ -7430,6 +7475,19 @@ async function syncAndCheckClaudeScheduler(agent, tasks, boardItems, refreshData
7430
7475
  });
7431
7476
  }
7432
7477
  }
7478
+ function deriveScheduledTaskNotify(task) {
7479
+ if (task.deliveryChannel !== "msteams") return {};
7480
+ const to = task.deliveryTo;
7481
+ let conversationId = null;
7482
+ if (typeof to === "string" && to.trim().length > 0) {
7483
+ conversationId = to.trim();
7484
+ } else if (to && typeof to === "object") {
7485
+ const cid = to.conversation_id;
7486
+ if (typeof cid === "string" && cid.trim().length > 0) conversationId = cid.trim();
7487
+ }
7488
+ if (!conversationId) return {};
7489
+ return { notify_channel: "msteams", notify_to: conversationId };
7490
+ }
7433
7491
  async function startRun(opts) {
7434
7492
  try {
7435
7493
  const res = await api.post(
@@ -7598,7 +7656,8 @@ async function routeScheduledTaskViaKanban(codeName, agentId, task, prompt) {
7598
7656
  title: task.name,
7599
7657
  description: prompt,
7600
7658
  priority: 2,
7601
- initial_status: "todo"
7659
+ initial_status: "todo",
7660
+ ...deriveScheduledTaskNotify(task)
7602
7661
  }
7603
7662
  });
7604
7663
  if (!run_id || !kanban_item_id) {
@@ -7707,7 +7766,7 @@ async function executeAndProcessClaudeTask(codeName, agentId, task, prompt) {
7707
7766
  source_type: "scheduled_task",
7708
7767
  source_ref: task.taskId,
7709
7768
  metadata: { template_id: task.templateId, name: task.name },
7710
- materialize_kanban: { title: task.name, priority: 2 }
7769
+ materialize_kanban: { title: task.name, priority: 2, ...deriveScheduledTaskNotify(task) }
7711
7770
  });
7712
7771
  runId = startResult.run_id;
7713
7772
  kanbanItemId = startResult.kanban_item_id;
@@ -10460,6 +10519,7 @@ export {
10460
10519
  claudeManagedSettingsPath,
10461
10520
  deliverScheduledCardResult,
10462
10521
  deliverScheduledTaskOutput,
10522
+ deriveScheduledTaskNotify,
10463
10523
  ensureClaudeManagedSettings,
10464
10524
  extractCharterSlackPeers,
10465
10525
  extractCharterTelegramPeers,