@integrity-labs/agt-cli 0.15.6 → 0.15.8

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/mcp/index.js CHANGED
@@ -21040,6 +21040,12 @@ var AGT_API_KEY = process.env.AGT_API_KEY;
21040
21040
  var AGT_AGENT_ID = process.env.AGT_AGENT_ID;
21041
21041
  var AGT_AGENT_CODE_NAME = process.env.AGT_AGENT_CODE_NAME;
21042
21042
  var AGT_APP_URL = (process.env.AGT_APP_URL ?? "").replace(/\/+$/, "");
21043
+ function readRunId() {
21044
+ const raw = process.env.AGT_RUN_ID ?? "";
21045
+ if (!raw || raw === "${AGT_RUN_ID}") return null;
21046
+ return raw;
21047
+ }
21048
+ var AGT_RUN_ID = readRunId();
21043
21049
  var AGT_TOKEN = process.env.AGT_TOKEN ?? "";
21044
21050
  if (!AGT_HOST || !AGT_AGENT_ID || !AGT_TOKEN && !AGT_API_KEY) {
21045
21051
  console.error(
@@ -21166,6 +21172,7 @@ server.tool(
21166
21172
  async (params) => {
21167
21173
  const data = await apiPost("/host/kanban", {
21168
21174
  agent_id: AGT_AGENT_ID,
21175
+ run_id: AGT_RUN_ID,
21169
21176
  add: [
21170
21177
  {
21171
21178
  title: params.title,
@@ -21791,6 +21798,8 @@ server.tool(
21791
21798
  async (params) => {
21792
21799
  const data = await apiPost("/host/knowledge", {
21793
21800
  agent_id: AGT_AGENT_ID,
21801
+ // ENG-4538 will land a run_id column on team_knowledge; until then
21802
+ // the /host/knowledge endpoint has nowhere to stamp AGT_RUN_ID.
21794
21803
  add: [
21795
21804
  {
21796
21805
  title: params.title,
@@ -14156,17 +14156,21 @@ var ALLOWED_USERS = new Set(
14156
14156
  );
14157
14157
  var THREAD_AUTO_FOLLOW = process.env.SLACK_THREAD_AUTO_FOLLOW ?? "off";
14158
14158
  var CHANNEL_RESPONSE_MODE = parseResponseMode(process.env.SLACK_CHANNEL_RESPONSE_MODE);
14159
- var RESPONSE_TIMEOUT_MS = 12e4;
14159
+ var RESPONSE_TIMEOUT_MS = 3e5;
14160
14160
  var pendingMessages = /* @__PURE__ */ new Map();
14161
14161
  function trackPendingMessage(channel, threadTs, messageTs) {
14162
14162
  const key = `${channel}:${threadTs}:${messageTs}`;
14163
14163
  const timer = setTimeout(async () => {
14164
14164
  pendingMessages.delete(key);
14165
14165
  try {
14166
- await fetch("https://slack.com/api/reactions.add", {
14166
+ await fetch("https://slack.com/api/chat.postMessage", {
14167
14167
  method: "POST",
14168
14168
  headers: { "Content-Type": "application/json", Authorization: `Bearer ${BOT_TOKEN}` },
14169
- body: JSON.stringify({ channel, timestamp: messageTs, name: "x" })
14169
+ body: JSON.stringify({
14170
+ channel,
14171
+ thread_ts: threadTs,
14172
+ text: "Sorry \u2014 I didn't get a response back to you within 5 minutes, so this one fell on the floor. Please re-send if it's still relevant."
14173
+ })
14170
14174
  });
14171
14175
  } catch {
14172
14176
  }
@@ -14271,8 +14275,8 @@ var mcp = new Server(
14271
14275
  "Address users by user_name, never by raw user ID. In multi-participant threads the CURRENT speaker is the one on the latest <channel> tag \u2014 don't conflate with earlier participants.",
14272
14276
  "Mentioned in a channel \u2192 respond in that thread. DM \u2192 respond directly.",
14273
14277
  'auto_followed="true" messages are from threads you previously joined: reply only if you have something useful to add. Skip if the conversation moved on, the message is directed at someone else, or your input would not add value.',
14274
- 'Reaction taxonomy (use slack.react sparingly \u2014 most messages need a reply, not a reaction): \u{1F440} = ack/working on it (already auto-added on inbound, do not duplicate); \u2705 = action completed successfully; \u274C = you TRIED to execute the requested action and it FAILED with an error. Do NOT use \u274C to mean "skipped", "disagree", "n/a", "not addressed to me", or "no response needed".',
14275
- `When a message in a thread is not addressed to you (different @-mention, conversation between others, auto_followed catch-up): SILENTLY SKIP \u2014 no reaction, no reply, do nothing. Adding \u274C in this case is wrong; it gives the user a misleading "execution failed" signal when in fact you correctly identified the message wasn't yours to handle.`,
14278
+ "Reaction taxonomy (use slack.react sparingly \u2014 most messages need a reply, not a reaction): \u{1F440} = ack/working on it (already auto-added on inbound, do not duplicate); \u2705 = action completed successfully. NEVER react to signal failure \u2014 users misread emoji reactions and don't know why something failed. If an action failed, send a slack.reply with one sentence explaining what went wrong (no stack traces, no secrets) so the user understands.",
14279
+ `When a message in a thread is not addressed to you (different @-mention, conversation between others, auto_followed catch-up): SILENTLY SKIP \u2014 no reaction, no reply, do nothing. Do NOT post a "this wasn't for me" message and do NOT add a failure reaction; either is misleading.`,
14276
14280
  "To deliver a file, save it under your project dir and call slack.upload_file with path, channel, thread_ts."
14277
14281
  ].join(" ")
14278
14282
  }
@@ -14300,13 +14304,13 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
14300
14304
  },
14301
14305
  {
14302
14306
  name: "slack.react",
14303
- description: 'Add an emoji reaction to a Slack message. Use sparingly \u2014 prefer a text reply. Reaction taxonomy: \u2705 = action completed successfully; \u274C (`x`) = you TRIED to execute the requested action and it FAILED with an error. Do NOT use \u274C for "skipped", "disagree", "not addressed to me", "n/a", or "noted" \u2014 those need either a text reply or no response at all. \u{1F440} (eyes) is already auto-applied on inbound; do not duplicate.',
14307
+ description: "Add an emoji reaction to a Slack message. Use sparingly \u2014 prefer a text reply. Reaction taxonomy: \u2705 = action completed successfully. NEVER react to signal failure \u2014 users can't tell why it failed from a reaction. On failure, call slack.reply with one sentence explaining what went wrong instead. \u{1F440} (eyes) is already auto-applied on inbound; do not duplicate.",
14304
14308
  inputSchema: {
14305
14309
  type: "object",
14306
14310
  properties: {
14307
14311
  channel: { type: "string", description: "Slack channel ID" },
14308
14312
  timestamp: { type: "string", description: "Message timestamp to react to" },
14309
- emoji: { type: "string", description: 'Emoji name without colons (e.g. "white_check_mark", "x"). Only use "x" when an execution attempt actually failed.' }
14313
+ emoji: { type: "string", description: 'Emoji name without colons (e.g. "white_check_mark"). Do NOT use "x" or any other failure emoji \u2014 send a slack.reply explaining the failure instead.' }
14310
14314
  },
14311
14315
  required: ["channel", "timestamp", "emoji"]
14312
14316
  }
@@ -14150,8 +14150,7 @@ function telegramApiCall(method, body, timeoutMs) {
14150
14150
  });
14151
14151
  }
14152
14152
  var ACK_EMOJI = "\u{1F440}";
14153
- var TIMEOUT_EMOJI = "\u{1F494}";
14154
- var RESPONSE_TIMEOUT_MS = 12e4;
14153
+ var RESPONSE_TIMEOUT_MS = 3e5;
14155
14154
  async function setMessageReaction(chatId, messageId, emoji2) {
14156
14155
  try {
14157
14156
  const resp = await telegramApiCall(
@@ -14183,7 +14182,29 @@ function trackPendingMessage(chatId, messageId, chatType) {
14183
14182
  if (existing) clearTimeout(existing.timer);
14184
14183
  const timer = setTimeout(() => {
14185
14184
  pendingMessages.delete(key);
14186
- void setMessageReaction(chatId, messageId, TIMEOUT_EMOJI);
14185
+ void setMessageReaction(chatId, messageId, null);
14186
+ void telegramApiCall(
14187
+ "sendMessage",
14188
+ {
14189
+ chat_id: chatId,
14190
+ text: "Sorry \u2014 I didn't get a response back to you within 5 minutes, so this one fell on the floor. Please re-send if it's still relevant.",
14191
+ reply_to_message_id: Number(messageId),
14192
+ allow_sending_without_reply: true
14193
+ },
14194
+ 1e4
14195
+ ).then((resp) => {
14196
+ if (!resp.ok) {
14197
+ process.stderr.write(
14198
+ `telegram-channel(${AGENT_CODE_NAME}): timeout sendMessage failed for chat ${redactId(chatId)} message ${redactId(messageId)}: ${resp.description ?? "unknown"}
14199
+ `
14200
+ );
14201
+ }
14202
+ }).catch((err) => {
14203
+ process.stderr.write(
14204
+ `telegram-channel(${AGENT_CODE_NAME}): timeout sendMessage error for chat ${redactId(chatId)} message ${redactId(messageId)}: ${err.message}
14205
+ `
14206
+ );
14207
+ });
14187
14208
  process.stderr.write(
14188
14209
  `telegram-channel(${AGENT_CODE_NAME}): response timeout for message ${redactId(messageId)} in chat ${redactId(chatId)}
14189
14210
  `
@@ -14203,11 +14224,21 @@ function clearPendingMessage(chatId, messageId) {
14203
14224
  return;
14204
14225
  }
14205
14226
  const prefix = `${chatId}:`;
14227
+ let clearedPrivate = false;
14206
14228
  for (const [key, entry] of pendingMessages) {
14207
14229
  if (!key.startsWith(prefix)) continue;
14208
14230
  if (entry.chatType !== "private") continue;
14209
14231
  clearTimeout(entry.timer);
14210
14232
  pendingMessages.delete(key);
14233
+ clearedPrivate = true;
14234
+ }
14235
+ if (clearedPrivate) return;
14236
+ for (const [key, entry] of pendingMessages) {
14237
+ if (!key.startsWith(prefix)) continue;
14238
+ if (entry.chatType === "private") continue;
14239
+ clearTimeout(entry.timer);
14240
+ pendingMessages.delete(key);
14241
+ return;
14211
14242
  }
14212
14243
  }
14213
14244
  var mcp = new Server(
@@ -14227,7 +14258,7 @@ var mcp = new Server(
14227
14258
  'For work >30s follow CLAUDE.md kanban flow: kanban.add, reply with "On it \u2014 tracking here: <kanban URL>", move to in_progress, do the work, reply with the result. Simple lookups skip kanban but still reply.',
14228
14259
  "Address users by user_name; user is the numeric Telegram ID. Reply-to a specific message with reply_to_message_id, otherwise omit.",
14229
14260
  "Resolve ambiguous times against your own Timezone from CLAUDE.md \u2014 do not ask the user.",
14230
- `Reaction taxonomy (use telegram.react sparingly \u2014 prefer a text reply via telegram.reply): \u{1F440} = ack/working on it (already auto-added on inbound, do not duplicate); \u{1F44D} or \u{1F389} = action completed successfully; \u{1F494} = you TRIED to execute the requested action and it FAILED with an error (Telegram's free-tier stand-in for Slack's \u274C; the literal \u274C is not on the bot-allowed emoji list). Do NOT use \u{1F494} for "skipped", "disagree", "n/a", or "no response needed" \u2014 those need either a text reply or no reaction. Free-tier emoji set: \u{1F44D} \u{1F44E} \u2764 \u{1F525} \u{1F389} \u{1F914} \u{1F92F} \u{1F64F} \u{1F44C} \u{1F440} \u{1F4AF} \u270D \u{1FAE1} \u{1F192} \u{1F973} \u{1F494} (premium-only fail silently).`
14261
+ "Reaction taxonomy (use telegram.react sparingly \u2014 prefer a text reply via telegram.reply): \u{1F440} = ack/working on it (already auto-added on inbound, do not duplicate); \u{1F44D} or \u{1F389} = action completed successfully. NEVER react to signal failure \u2014 users misread emoji reactions and don't know why something failed. If an action failed, send a telegram.reply with one sentence explaining what went wrong (no stack traces, no secrets) so the user understands. Free-tier emoji set: \u{1F44D} \u{1F44E} \u2764 \u{1F525} \u{1F389} \u{1F914} \u{1F92F} \u{1F64F} \u{1F44C} \u{1F440} \u{1F4AF} \u270D \u{1FAE1} \u{1F192} \u{1F973} \u{1F494} (premium-only fail silently)."
14231
14262
  ].join(" ")
14232
14263
  }
14233
14264
  );
@@ -14287,7 +14318,7 @@ mcp.setRequestHandler(ListToolsRequestSchema, async () => ({
14287
14318
  },
14288
14319
  {
14289
14320
  name: "telegram.react",
14290
- description: `Add an emoji reaction to a Telegram message. Use sparingly \u2014 prefer a text reply via telegram.reply. Reaction taxonomy: \u{1F44D} or \u{1F389} = action completed successfully; \u{1F494} = you TRIED to execute the requested action and it FAILED with an error (free-tier stand-in for Slack's \u274C). Do NOT use \u{1F494} for "skipped", "disagree", or "noted" \u2014 those need a text reply or no reaction at all. \u{1F440} is already auto-applied on inbound; do not duplicate. Only free-tier emoji reactions are available to bots (Premium-only emoji fail silently). Pass an empty string or omit emoji to clear the bot's reaction on that message.`,
14321
+ description: "Add an emoji reaction to a Telegram message. Use sparingly \u2014 prefer a text reply via telegram.reply. Reaction taxonomy: \u{1F44D} or \u{1F389} = action completed successfully. NEVER react to signal failure \u2014 users can't tell why it failed from a reaction. On failure, call telegram.reply with one sentence explaining what went wrong instead. \u{1F440} is already auto-applied on inbound; do not duplicate. Only free-tier emoji reactions are available to bots (Premium-only emoji fail silently). Pass an empty string or omit emoji to clear the bot's reaction on that message.",
14291
14322
  inputSchema: {
14292
14323
  type: "object",
14293
14324
  properties: {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.15.6",
3
+ "version": "0.15.8",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {