@integrity-labs/agt-cli 0.27.25 → 0.27.26

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.
package/dist/bin/agt.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  success,
28
28
  table,
29
29
  warn
30
- } from "../chunk-GI73VOGA.js";
30
+ } from "../chunk-S53Y2M2Q.js";
31
31
  import {
32
32
  CHANNEL_REGISTRY,
33
33
  DEPLOYMENT_TEMPLATES,
@@ -4643,7 +4643,7 @@ import { execFileSync, execSync } from "child_process";
4643
4643
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4644
4644
  import chalk18 from "chalk";
4645
4645
  import ora16 from "ora";
4646
- var cliVersion = true ? "0.27.25" : "dev";
4646
+ var cliVersion = true ? "0.27.26" : "dev";
4647
4647
  async function fetchLatestVersion() {
4648
4648
  const host2 = getHost();
4649
4649
  if (!host2) return null;
@@ -5175,7 +5175,7 @@ function handleError(err) {
5175
5175
  }
5176
5176
 
5177
5177
  // src/bin/agt.ts
5178
- var cliVersion2 = true ? "0.27.25" : "dev";
5178
+ var cliVersion2 = true ? "0.27.26" : "dev";
5179
5179
  var program = new Command();
5180
5180
  program.name("agt").description("Augmented CLI \u2014 agent provisioning and management").version(cliVersion2).option("--json", "Emit machine-readable JSON output (suppress spinners and colors)").option("--skip-update-check", "Skip the automatic update check on startup");
5181
5181
  program.hook("preAction", (thisCommand) => {
@@ -6945,4 +6945,4 @@ export {
6945
6945
  managerInstallSystemUnitCommand,
6946
6946
  managerUninstallSystemUnitCommand
6947
6947
  };
6948
- //# sourceMappingURL=chunk-GI73VOGA.js.map
6948
+ //# sourceMappingURL=chunk-S53Y2M2Q.js.map
@@ -15,7 +15,7 @@ import {
15
15
  provisionOrientHook,
16
16
  provisionStopHook,
17
17
  requireHost
18
- } from "../chunk-GI73VOGA.js";
18
+ } from "../chunk-S53Y2M2Q.js";
19
19
  import {
20
20
  getProjectDir as getProjectDir2,
21
21
  getReadyTasks,
@@ -3208,7 +3208,7 @@ var cachedFrameworkVersion = null;
3208
3208
  var lastVersionCheckAt = 0;
3209
3209
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
3210
3210
  var lastResponsivenessProbeAt = 0;
3211
- var agtCliVersion = true ? "0.27.25" : "dev";
3211
+ var agtCliVersion = true ? "0.27.26" : "dev";
3212
3212
  function resolveBrewPath(execFileSync4) {
3213
3213
  try {
3214
3214
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
@@ -14261,6 +14261,56 @@ function decideSenderPolicyForward(evt, policy) {
14261
14261
  return decideModeForward(evt, policy);
14262
14262
  }
14263
14263
 
14264
+ // src/sender-policy-decline.ts
14265
+ function classifySlackPolicyBlock(evt, policy) {
14266
+ if (policy.internalOnly && (!policy.homeTeamId || evt.team !== policy.homeTeamId)) {
14267
+ return "internal_only";
14268
+ }
14269
+ switch (policy.mode) {
14270
+ case "manager_only":
14271
+ return "mode_manager_only";
14272
+ case "team_agents_only":
14273
+ return "mode_team_agents_only";
14274
+ case "agents_only":
14275
+ return "mode_agents_only";
14276
+ case "all":
14277
+ return "internal_only";
14278
+ }
14279
+ }
14280
+ function politeDeclineCopy(reason) {
14281
+ switch (reason) {
14282
+ case "internal_only":
14283
+ return "Sorry, I can only respond to people inside our organisation. This conversation appears to be from outside.";
14284
+ case "mode_manager_only":
14285
+ return "Sorry, I only respond to my manager in this channel.";
14286
+ case "mode_team_agents_only":
14287
+ return "Sorry, I only respond to agents on my team in this channel.";
14288
+ case "mode_agents_only":
14289
+ return "Sorry, I only respond to other agents in this channel.";
14290
+ }
14291
+ }
14292
+ function decideDeclineReply(input) {
14293
+ const last = input.cache.get(input.key);
14294
+ if (last !== void 0) {
14295
+ const elapsed = input.now - last;
14296
+ if (elapsed < input.cooldownMs) {
14297
+ return { reply: false, remainingMs: input.cooldownMs - elapsed };
14298
+ }
14299
+ }
14300
+ input.cache.set(input.key, input.now);
14301
+ return { reply: true };
14302
+ }
14303
+ function declineCacheKey(channelId, senderId, reason) {
14304
+ return `${channelId}|${senderId}|${reason}`;
14305
+ }
14306
+ function readDeclineCooldownMs(envVarName, defaultSeconds = 1800) {
14307
+ const raw = process.env[envVarName];
14308
+ if (!raw) return defaultSeconds * 1e3;
14309
+ const parsed = Number(raw);
14310
+ if (!Number.isFinite(parsed) || parsed < 0) return defaultSeconds * 1e3;
14311
+ return parsed * 1e3;
14312
+ }
14313
+
14264
14314
  // src/ack-reaction.ts
14265
14315
  import { readdirSync, readFileSync } from "fs";
14266
14316
  import { join } from "path";
@@ -15557,6 +15607,58 @@ var SLACK_SENDER_POLICY = (() => {
15557
15607
  }
15558
15608
  throw new Error(`Invalid SLACK_SENDER_POLICY=${JSON.stringify(process.env.SLACK_SENDER_POLICY)}`);
15559
15609
  })();
15610
+ var SLACK_POLICY_DECLINE_CACHE = /* @__PURE__ */ new Map();
15611
+ var SLACK_POLICY_DECLINE_COOLDOWN_MS = readDeclineCooldownMs(
15612
+ "SLACK_SENDER_POLICY_REPLY_COOLDOWN_SEC"
15613
+ );
15614
+ async function maybeSendSenderPolicyDecline(args) {
15615
+ if (!BOT_TOKEN) return;
15616
+ if (!args.channel || !args.senderId) return;
15617
+ const key2 = declineCacheKey(args.channel, args.senderId, args.subReason);
15618
+ const decision = decideDeclineReply({
15619
+ cache: SLACK_POLICY_DECLINE_CACHE,
15620
+ key: key2,
15621
+ cooldownMs: SLACK_POLICY_DECLINE_COOLDOWN_MS,
15622
+ now: Date.now()
15623
+ });
15624
+ if (!decision.reply) {
15625
+ process.stderr.write(
15626
+ `slack-channel(${AGENT_CODE_NAME}): decline suppressed by cooldown (channel=${redactSlackId(args.channel)}, sender=${redactSlackId(args.senderId)}, reason=${args.subReason}, remaining=${decision.remainingMs}ms)
15627
+ `
15628
+ );
15629
+ return;
15630
+ }
15631
+ const text = politeDeclineCopy(args.subReason);
15632
+ const controller = new AbortController();
15633
+ const timeoutId = setTimeout(() => controller.abort(), 1e4);
15634
+ try {
15635
+ const res = await fetch("https://slack.com/api/chat.postMessage", {
15636
+ method: "POST",
15637
+ signal: controller.signal,
15638
+ headers: {
15639
+ "Content-Type": "application/json",
15640
+ Authorization: `Bearer ${BOT_TOKEN}`
15641
+ },
15642
+ body: JSON.stringify({
15643
+ channel: args.channel,
15644
+ text,
15645
+ // Reply in-thread if the inbound was a thread message — keeps
15646
+ // the decline next to the message that caused it. For top-level
15647
+ // posts (DMs / channel root) omit thread_ts and post inline.
15648
+ ...args.threadTs ? { thread_ts: args.threadTs } : {}
15649
+ })
15650
+ });
15651
+ const data = await res.json();
15652
+ if (!data.ok) {
15653
+ process.stderr.write(
15654
+ `slack-channel(${AGENT_CODE_NAME}): decline post failed: ${data.error ?? "unknown"}
15655
+ `
15656
+ );
15657
+ }
15658
+ } finally {
15659
+ clearTimeout(timeoutId);
15660
+ }
15661
+ }
15560
15662
  var BLOCK_KIT_ENABLED = process.env.SLACK_BLOCK_KIT_ENABLED === "true";
15561
15663
  var BLOCK_KIT_ASK_USER_ENABLED = process.env.SLACK_BLOCK_KIT_ASK_USER_ENABLED === "true";
15562
15664
  var BLOCK_KIT_DISABLED = process.env.SLACK_BLOCK_KIT_DISABLED === "true";
@@ -17807,8 +17909,27 @@ async function connectSocketMode() {
17807
17909
  }
17808
17910
  const senderPolicyDecision = decideSenderPolicyForward(evt, SLACK_SENDER_POLICY);
17809
17911
  if (!senderPolicyDecision.forward) {
17810
- process.stderr.write(`slack-channel: dropped message event (reason=sender_policy, mode=${SLACK_SENDER_POLICY.mode}, ts=${evt.ts ?? "n/a"})
17912
+ const subReason = classifySlackPolicyBlock(evt, SLACK_SENDER_POLICY);
17913
+ process.stderr.write(`slack-channel: dropped message event (reason=sender_policy, sub=${subReason}, mode=${SLACK_SENDER_POLICY.mode}, ts=${evt.ts ?? "n/a"})
17811
17914
  `);
17915
+ await maybeSendSenderPolicyDecline({
17916
+ channel: evt.channel,
17917
+ senderId: evt.user,
17918
+ // CR on PR #1623: top-level posts (DMs, channel root messages)
17919
+ // arrive with no `thread_ts` and MUST decline inline, not in a
17920
+ // new thread off the inbound message. The `?? evt.ts` fallback
17921
+ // forced every root message into a thread reply — exactly the
17922
+ // case the helper's "omit thread_ts when undefined" branch was
17923
+ // meant to handle. Pass through as-is: in-thread for thread
17924
+ // replies (thread_ts present), inline for everything else.
17925
+ threadTs: evt.thread_ts,
17926
+ subReason
17927
+ }).catch((err) => {
17928
+ process.stderr.write(
17929
+ `slack-channel(${AGENT_CODE_NAME}): decline reply failed: ${err.message}
17930
+ `
17931
+ );
17932
+ });
17812
17933
  return;
17813
17934
  }
17814
17935
  recordActivity("inbound");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.27.25",
3
+ "version": "0.27.26",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {