@integrity-labs/agt-cli 0.27.88 → 0.27.90

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/mcp/index.js CHANGED
@@ -21061,8 +21061,11 @@ var DeliveryTargetSchema = external_exports.union([
21061
21061
  channel_id: external_exports.string().optional(),
21062
21062
  chat_id: external_exports.string().optional(),
21063
21063
  conversation_id: external_exports.string().optional(),
21064
- service_url: external_exports.string().optional()
21065
- }).describe("Post to a Slack channel, Telegram chat, or Microsoft Teams conversation. Provide channel_id for Slack, chat_id for Telegram, or conversation_id + service_url for Teams."),
21064
+ service_url: external_exports.string().optional(),
21065
+ thread_ts: external_exports.string().nullable().optional().describe(
21066
+ `Slack only (ENG-6038). The originating thread's thread_ts when the user asked for the result back in the thread the request came from ("report back here" inside a thread) \u2014 take it from the inbound message's <channel> envelope. Pass null to mean 'top-level on purpose' (e.g. the user said "post it to the channel" \u2014 null also suppresses server-side thread auto-injection on one-time tasks). Omit only when the request didn't come from a thread.`
21067
+ )
21068
+ }).describe("Post to a Slack channel, Telegram chat, or Microsoft Teams conversation. Provide channel_id for Slack, chat_id for Telegram, or conversation_id + service_url for Teams. For Slack, thread_ts optionally threads the delivery under the originating conversation."),
21066
21069
  external_exports.object({
21067
21070
  kind: external_exports.literal("dm"),
21068
21071
  person_id: external_exports.string().uuid(),
@@ -21737,7 +21740,7 @@ server.tool(
21737
21740
  prompt: external_exports.string().describe("What to do when the task fires"),
21738
21741
  delivery_channel: external_exports.string().optional().describe('Channel platform to deliver results to (e.g. "slack", "telegram"). Default: "slack" if available.'),
21739
21742
  delivery_to: DeliveryTargetSchema.optional().describe(
21740
- "Where the task output should be delivered. Structured object: either { kind: 'channel', provider, channel_id? | chat_id? } to post to a Slack channel / Telegram chat, or { kind: 'dm', person_id, follow_reports_to, medium } to DM a person. For 'reply to the channel this request came from', pass the incoming message's channel_id. For 'DM my manager', use follow_reports_to=true with the agent's current reports_to person_id. Legacy string forms ('channel:<id>', 'chat:<id>', 'slack_user:<id>') are rejected server-side \u2014 use the structured form."
21743
+ "Where the task output should be delivered. Structured object: either { kind: 'channel', provider, channel_id? | chat_id? } to post to a Slack channel / Telegram chat, or { kind: 'dm', person_id, follow_reports_to, medium } to DM a person. For 'reply to the channel this request came from', pass the incoming message's channel_id. For 'report back HERE' said inside a Slack thread, also pass thread_ts from the inbound envelope so the result lands in that thread; if the user wants the channel top-level despite asking from a thread, pass thread_ts: null. For 'DM my manager', use follow_reports_to=true with the agent's current reports_to person_id. Legacy string forms ('channel:<id>', 'chat:<id>', 'slack_user:<id>') are rejected server-side \u2014 use the structured form."
21741
21744
  ),
21742
21745
  delivery_mode: external_exports.enum(["announce", "none"]).optional().describe('Delivery mode: "announce" sends output to delivery_channel, "none" suppresses. Default: "announce".')
21743
21746
  },
@@ -21810,7 +21813,7 @@ server.tool(
21810
21813
  'Where results are delivered (e.g. "slack", "telegram", "email")'
21811
21814
  ),
21812
21815
  delivery_to: DeliveryTargetSchema.optional().describe(
21813
- "Structured delivery target (see schedule_create description for shape). Pass null-equivalent by omitting the field; pass a new structured target to change routing."
21816
+ "Structured delivery target (see schedule_create description for shape). Pass null-equivalent by omitting the field; pass a new structured target to change routing. delivery_to is replaced wholesale: to STOP a task threading into a Slack conversation ('post it to the channel instead'), pass the channel target again WITHOUT thread_ts; to start threading, include thread_ts."
21814
21817
  ),
21815
21818
  enabled: external_exports.boolean().optional().describe(
21816
21819
  "Set to false to pause the schedule without deleting it"
@@ -14628,7 +14628,8 @@ var DEFAULT_MAX_CHARS = 3900;
14628
14628
  var REFLOW_COLS = 80;
14629
14629
  function formatPaneSnapshot(opts) {
14630
14630
  const maxChars = opts.maxChars ?? DEFAULT_MAX_CHARS;
14631
- const header = opts.status.kind === "live" ? `\u{1F50E} Live pane tail for \`${opts.codeName}\` \u2014 captured ${opts.capturedAtLabel} \xB7 updates ~3s \xB7 expires in ${formatCountdown(opts.status.secondsRemaining)}` : `\u{1F50E} Pane tail for \`${opts.codeName}\` \u2014 captured ${opts.capturedAtLabel} \xB7 *expired* \u2014 run \`/debug\` to restart`;
14631
+ const commandName = opts.commandName ?? "/debug";
14632
+ const header = opts.status.kind === "live" ? `\u{1F50E} Live pane tail for \`${opts.codeName}\` \u2014 captured ${opts.capturedAtLabel} \xB7 updates ~3s \xB7 expires in ${formatCountdown(opts.status.secondsRemaining)}` : `\u{1F50E} Pane tail for \`${opts.codeName}\` \u2014 captured ${opts.capturedAtLabel} \xB7 *expired* \u2014 run \`${commandName}\` to restart`;
14632
14633
  const fenceOverhead = header.length + "\n```\n".length + "\n```".length + 16;
14633
14634
  const contentBudget = Math.max(0, maxChars - fenceOverhead);
14634
14635
  const lines = reflowLines(sanitizeForCodeBlock(opts.text), REFLOW_COLS);
@@ -15817,6 +15818,16 @@ function readLockHolder(path) {
15817
15818
  var BOT_TOKEN = process.env.SLACK_BOT_TOKEN;
15818
15819
  var APP_TOKEN = process.env.SLACK_APP_TOKEN;
15819
15820
  var AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME ?? null;
15821
+ var SLACK_COMMAND_MAX_LENGTH = 32;
15822
+ function agentSlashCommand(base) {
15823
+ const codeName = AGENT_CODE_NAME?.trim().toLowerCase();
15824
+ if (!codeName || !/^[a-z0-9]+(?:-[a-z0-9]+)*$/.test(codeName)) return base;
15825
+ const suffixed = `${base}-${codeName}`;
15826
+ return suffixed.length > SLACK_COMMAND_MAX_LENGTH ? base : suffixed;
15827
+ }
15828
+ function matchesAgentCommand(command, base) {
15829
+ return command === base || command === agentSlashCommand(base);
15830
+ }
15820
15831
  var AGT_HOST = process.env.AGT_HOST ?? null;
15821
15832
  var AGT_API_KEY = process.env.AGT_API_KEY ?? null;
15822
15833
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID ?? null;
@@ -16485,13 +16496,13 @@ function buildSlackHelpMessage(codeName) {
16485
16496
  return [
16486
16497
  `\u{1F916} *Available commands for \`${codeName}\`*`,
16487
16498
  "",
16488
- "All commands are real Slack slash commands (autocomplete via `/`). For backward compatibility, `/help` and `/restart` can also be typed as plain messages in any channel where the bot is present:",
16499
+ "All commands are real Slack slash commands (autocomplete via `/`). For backward compatibility, `/help` and the restart command can also be typed as plain messages in any channel where the bot is present:",
16489
16500
  "\u2022 `/help` \u2014 show this help",
16490
- "\u2022 `/restart` \u2014 restart this agent",
16491
- "\u2022 `/agent-status` \u2014 report whether this agent is online + last activity",
16501
+ `\u2022 \`${agentSlashCommand("/restart")}\` \u2014 restart this agent`,
16502
+ `\u2022 \`${agentSlashCommand("/agent-status")}\` \u2014 report whether this agent is online + last activity`,
16492
16503
  "\u2022 `/kill` \u2014 silence all agents in this thread for 6h (use as a thread reply)",
16493
16504
  "\u2022 `/unkill` \u2014 clear a kill (use as a thread reply)",
16494
- "\u2022 `/debug` \u2014 live tail of this agent's terminal pane (DM only, allowlisted users; works while the channel process is alive \u2014 a wedged host still needs SSM diagnostics)"
16505
+ `\u2022 \`${agentSlashCommand("/investigate")}\` \u2014 live tail of this agent's terminal pane (DM only, allowlisted users; works while the channel process is alive \u2014 a wedged host still needs SSM diagnostics)`
16495
16506
  ].join("\n");
16496
16507
  }
16497
16508
  var lastActivityAt = null;
@@ -16670,7 +16681,9 @@ async function runDebugTailLoop(opts) {
16670
16681
  text: last.body,
16671
16682
  source: last.source,
16672
16683
  capturedAtLabel: last.capturedAtLabel,
16673
- status: { kind: "expired" }
16684
+ status: { kind: "expired" },
16685
+ // ENG-6044: advertise the renamed command in the expired header.
16686
+ commandName: agentSlashCommand("/investigate")
16674
16687
  })
16675
16688
  );
16676
16689
  }
@@ -16682,9 +16695,10 @@ async function handleDebugSlashCommand(payload, responseUrl) {
16682
16695
  userId: payload.user_id,
16683
16696
  allowedUsers: ALLOWED_USERS
16684
16697
  });
16698
+ const investigateCmd = agentSlashCommand("/investigate");
16685
16699
  if (!verdict.ok) {
16686
16700
  debugAuditLog(`denied reason=${verdict.reason} user=${payload.user_id ?? "unknown"}`);
16687
- const denialText = verdict.reason === "not-dm" ? `:warning: \`/debug\` only works in a direct message with \`${codeName}\` \u2014 it shows the agent's raw terminal, so it stays 1:1. Open a DM with the bot and run \`/debug\` there.` : verdict.reason === "allowlist-empty" ? `\u{1F6AB} \`/debug\` is disabled for \`${codeName}\` \u2014 no diagnostic allowlist is configured. Because it exposes the agent's raw terminal, \`/debug\` requires a non-empty \`SLACK_ALLOWED_USERS\` on the host (unlike \`/restart\`, it does not open up when the allowlist is unset).` : `\u{1F6AB} \`/debug\` denied \u2014 your Slack user isn't on the diagnostic allowlist for \`${codeName}\`. Ask whoever operates this host to add you to \`SLACK_ALLOWED_USERS\`.`;
16701
+ const denialText = verdict.reason === "not-dm" ? `:warning: \`${investigateCmd}\` only works in a direct message with \`${codeName}\` \u2014 it shows the agent's raw terminal, so it stays 1:1. Open a DM with the bot and run \`${investigateCmd}\` there.` : verdict.reason === "allowlist-empty" ? `\u{1F6AB} \`${investigateCmd}\` is disabled for \`${codeName}\` \u2014 no diagnostic allowlist is configured. Because it exposes the agent's raw terminal, \`${investigateCmd}\` requires a non-empty \`SLACK_ALLOWED_USERS\` on the host (unlike the restart command, it does not open up when the allowlist is unset).` : `\u{1F6AB} \`${investigateCmd}\` denied \u2014 your Slack user isn't on the diagnostic allowlist for \`${codeName}\`. Ask whoever operates this host to add you to \`SLACK_ALLOWED_USERS\`.`;
16688
16702
  await postEphemeralViaResponseUrl(responseUrl, denialText, codeName);
16689
16703
  return;
16690
16704
  }
@@ -16695,7 +16709,7 @@ async function handleDebugSlashCommand(payload, responseUrl) {
16695
16709
  );
16696
16710
  await postEphemeralViaResponseUrl(
16697
16711
  responseUrl,
16698
- `:warning: \`/debug\` can't run \u2014 this channel process has no bot token wired.`,
16712
+ `:warning: \`${investigateCmd}\` can't run \u2014 this channel process has no bot token wired.`,
16699
16713
  codeName
16700
16714
  );
16701
16715
  return;
@@ -16707,7 +16721,7 @@ async function handleDebugSlashCommand(payload, responseUrl) {
16707
16721
  );
16708
16722
  await postEphemeralViaResponseUrl(
16709
16723
  responseUrl,
16710
- `:hourglass: A \`/debug\` tail is already running for \`${codeName}\` (one at a time) \u2014 it expires in ${remaining}.`,
16724
+ `:hourglass: A \`${investigateCmd}\` tail is already running for \`${codeName}\` (one at a time) \u2014 it expires in ${remaining}.`,
16711
16725
  codeName
16712
16726
  );
16713
16727
  return;
@@ -16720,7 +16734,7 @@ async function handleDebugSlashCommand(payload, responseUrl) {
16720
16734
  debugAuditLog(`not-started reason=no-pane-output user=${payload.user_id ?? "unknown"}`);
16721
16735
  await postEphemeralViaResponseUrl(
16722
16736
  responseUrl,
16723
- `:warning: No pane output available for \`${codeName}\` yet \u2014 the agent session may not have started. (If the whole host is wedged, \`/debug\` can't reach it either \u2014 fall back to the SSM diagnostics runbook.)`,
16737
+ `:warning: No pane output available for \`${codeName}\` yet \u2014 the agent session may not have started. (If the whole host is wedged, \`${investigateCmd}\` can't reach it either \u2014 fall back to the SSM diagnostics runbook.)`,
16724
16738
  codeName
16725
16739
  );
16726
16740
  return;
@@ -16772,7 +16786,7 @@ async function handleSlashCommandEnvelope(payload) {
16772
16786
  const responseUrl = payload.response_url;
16773
16787
  const codeName = AGENT_CODE_NAME ?? "unknown";
16774
16788
  if (!command || !responseUrl) return;
16775
- if (command === "/agent-status") {
16789
+ if (matchesAgentCommand(command, "/agent-status")) {
16776
16790
  await postEphemeralViaResponseUrl(responseUrl, buildAgentStatusReply(codeName), codeName);
16777
16791
  return;
16778
16792
  }
@@ -16780,7 +16794,7 @@ async function handleSlashCommandEnvelope(payload) {
16780
16794
  await postEphemeralViaResponseUrl(responseUrl, buildSlackHelpMessage(codeName), codeName);
16781
16795
  return;
16782
16796
  }
16783
- if (command === "/restart") {
16797
+ if (matchesAgentCommand(command, "/restart")) {
16784
16798
  if (ALLOWED_USERS.size > 0 && (!payload.user_id || !ALLOWED_USERS.has(payload.user_id))) {
16785
16799
  process.stderr.write(
16786
16800
  `slack-channel(${codeName}): /restart slash-command denied \u2014 user not in SLACK_ALLOWED_USERS
@@ -16840,7 +16854,7 @@ async function handleSlashCommandEnvelope(payload) {
16840
16854
  }
16841
16855
  return;
16842
16856
  }
16843
- if (command === "/debug") {
16857
+ if (command === "/debug" || matchesAgentCommand(command, "/investigate")) {
16844
16858
  await handleDebugSlashCommand(payload, responseUrl);
16845
16859
  return;
16846
16860
  }
@@ -18521,7 +18535,8 @@ async function connectSocketMode() {
18521
18535
  const threadKey = buildThreadKey(evt.channel, trackTs);
18522
18536
  const rawText = evt.text ?? "";
18523
18537
  const strippedText = rawText.replace(/^\s*<@[^>]+>\s*/, "").trim();
18524
- const isRestartCommand = strippedText === "/restart" || strippedText.startsWith("/restart ");
18538
+ const restartSuffixed = agentSlashCommand("/restart");
18539
+ const isRestartCommand = strippedText === "/restart" || strippedText.startsWith("/restart ") || strippedText === restartSuffixed || strippedText.startsWith(`${restartSuffixed} `);
18525
18540
  const isHelpCommand = strippedText === "/help" || strippedText.startsWith("/help ");
18526
18541
  if (isHelpCommand) {
18527
18542
  await handleHelpCommand({
@@ -22,8 +22,8 @@ import {
22
22
  stopPersistentSession,
23
23
  takeZombieDetection,
24
24
  writePersistentClaudeWrapper
25
- } from "./chunk-SI2WVUAR.js";
26
- import "./chunk-54TIJVLZ.js";
25
+ } from "./chunk-4MZWINDQ.js";
26
+ import "./chunk-T2UTQH6W.js";
27
27
  import "./chunk-XWVM4KPK.js";
28
28
  export {
29
29
  SEND_KEYS_ENTER_DELAY_MS,
@@ -50,4 +50,4 @@ export {
50
50
  takeZombieDetection,
51
51
  writePersistentClaudeWrapper
52
52
  };
53
- //# sourceMappingURL=persistent-session-5LZH3KKT.js.map
53
+ //# sourceMappingURL=persistent-session-BMP74QGP.js.map
@@ -1,7 +1,7 @@
1
1
  import {
2
2
  paneLogPath
3
- } from "./chunk-SI2WVUAR.js";
4
- import "./chunk-54TIJVLZ.js";
3
+ } from "./chunk-4MZWINDQ.js";
4
+ import "./chunk-T2UTQH6W.js";
5
5
  import "./chunk-XWVM4KPK.js";
6
6
 
7
7
  // src/lib/responsiveness-probe.ts
@@ -70,4 +70,4 @@ export {
70
70
  collectResponsivenessProbes,
71
71
  getResponsivenessIntervalMs
72
72
  };
73
- //# sourceMappingURL=responsiveness-probe-DG5VINBC.js.map
73
+ //# sourceMappingURL=responsiveness-probe-AFOPQEFX.js.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.27.88",
3
+ "version": "0.27.90",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {