@integrity-labs/agt-cli 0.27.18 → 0.27.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.
package/dist/bin/agt.js CHANGED
@@ -27,7 +27,7 @@ import {
27
27
  success,
28
28
  table,
29
29
  warn
30
- } from "../chunk-CDMAMIVX.js";
30
+ } from "../chunk-42X4APXP.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.18" : "dev";
4646
+ var cliVersion = true ? "0.27.20" : "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.18" : "dev";
5178
+ var cliVersion2 = true ? "0.27.20" : "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) => {
@@ -6910,4 +6910,4 @@ export {
6910
6910
  managerInstallSystemUnitCommand,
6911
6911
  managerUninstallSystemUnitCommand
6912
6912
  };
6913
- //# sourceMappingURL=chunk-CDMAMIVX.js.map
6913
+ //# sourceMappingURL=chunk-42X4APXP.js.map
@@ -15,7 +15,7 @@ import {
15
15
  provisionOrientHook,
16
16
  provisionStopHook,
17
17
  requireHost
18
- } from "../chunk-CDMAMIVX.js";
18
+ } from "../chunk-42X4APXP.js";
19
19
  import {
20
20
  getProjectDir as getProjectDir2,
21
21
  getReadyTasks,
@@ -3166,7 +3166,7 @@ var cachedFrameworkVersion = null;
3166
3166
  var lastVersionCheckAt = 0;
3167
3167
  var VERSION_CHECK_INTERVAL_MS = 5 * 60 * 1e3;
3168
3168
  var lastResponsivenessProbeAt = 0;
3169
- var agtCliVersion = true ? "0.27.18" : "dev";
3169
+ var agtCliVersion = true ? "0.27.20" : "dev";
3170
3170
  function resolveBrewPath(execFileSync4) {
3171
3171
  try {
3172
3172
  const out = execFileSync4("which", ["brew"], { timeout: 5e3 }).toString().trim();
package/dist/mcp/index.js CHANGED
@@ -21771,7 +21771,12 @@ server.tool(
21771
21771
  "schedule_update",
21772
21772
  // Lead with user phrasings the agent should match against, then explain
21773
21773
  // the two modes. Order matters for tool selection.
21774
- 'Update an existing scheduled task. USE THIS TOOL when the user says: "change the schedule for X", "run the daily report at 10am instead of 9am", "pause the standup schedule", "move the weekly digest to Mondays", "make this report more concise", "add a section about X to the daily summary", "tell the Y schedule to also cover Z", "post these to the Customer Success channel from now on". Two modes: (1) DIRECT FIELD UPDATES \u2014 set cron_expression/interval/timezone/delivery_channel/delivery_to/enabled/name/prompt to change those values directly. (2) LLM DESCRIPTION REWRITE \u2014 pass description_feedback to have the platform rewrite the task prompt based on natural-language feedback (e.g. "make this more concise" or "add a section about the team backlog"). Default for LLM rewrites is preview-then-apply: call once to get the proposed rewrite, show the diff to the user, call again with auto_apply=true on confirmation. Direct field updates apply immediately. The two modes are mutually exclusive \u2014 one request is EITHER a field update OR a description rewrite.\n\nIMPORTANT \u2014 `delivery_to` requires a Slack channel ID (e.g. `C0123ABC456`), NOT a human channel name. If the user references a channel by its name ("the Customer Success channel"), call `mcp__slack__slack.list_channels` first with `query: "customer success"` to get the matching `id`, then pass that id as `delivery_to` here. Do not guess channel ids.',
21774
+ // CR PR #1601: field names + delivery_to shape brought into line with the
21775
+ // actual zod schema below. The prior copy referenced `cron_expression` /
21776
+ // `interval` (which the schema doesn't accept) and described
21777
+ // `delivery_to` as a raw channel ID (it's a structured DeliveryTargetSchema
21778
+ // object). Agents reading the old wording were producing invalid calls.
21779
+ 'Update an existing scheduled task. USE THIS TOOL when the user says: "change the schedule for X", "run the daily report at 10am instead of 9am", "pause the standup schedule", "move the weekly digest to Mondays", "make this report more concise", "add a section about X to the daily summary", "tell the Y schedule to also cover Z", "post these to the Customer Success channel from now on". Two modes: (1) DIRECT FIELD UPDATES \u2014 set schedule_expr/schedule_every/schedule_at/timezone/delivery_channel/delivery_to/enabled/name/prompt to change those values directly (pair the expression field with the matching schedule_kind: cron/every/at). (2) LLM DESCRIPTION REWRITE \u2014 pass description_feedback to have the platform rewrite the task prompt based on natural-language feedback (e.g. "make this more concise" or "add a section about the team backlog"). Default for LLM rewrites is preview-then-apply: call once to get the proposed rewrite, show the diff to the user, call again with auto_apply=true on confirmation. Direct field updates apply immediately. The two modes are mutually exclusive \u2014 one request is EITHER a field update OR a description rewrite.\n\nIMPORTANT \u2014 `delivery_to` is a structured target object, not a human channel name. If the user references a Slack channel by name ("the Customer Success channel"), call `mcp__slack__slack.list_channels` first with `query: "customer success"` to get the matching `id`, then pass `delivery_to: { kind: "channel", provider: "slack", channel_id: "<id>" }`. Do not guess channel ids.',
21775
21780
  {
21776
21781
  task_id: external_exports.string().describe("The task ID to update (from schedule_list)"),
21777
21782
  // Direct-field mode
@@ -22279,32 +22284,46 @@ async function forwardToolCall(toolName, args) {
22279
22284
  FORWARD_TOOL_CALL_TIMEOUT_MS
22280
22285
  );
22281
22286
  }
22287
+ var LOCAL_TOOL_NAMES = /* @__PURE__ */ new Set([
22288
+ "kanban_list",
22289
+ "kanban_add",
22290
+ "kanban_move",
22291
+ "kanban_update",
22292
+ "kanban_progress",
22293
+ "kanban_done",
22294
+ "status_standup",
22295
+ "status_update",
22296
+ "drift_report",
22297
+ "token_refresh",
22298
+ "acpx_prompt",
22299
+ "acpx_exec",
22300
+ "acpx_spawn",
22301
+ "acpx_cancel",
22302
+ "acpx_status",
22303
+ "acpx_close",
22304
+ "schedule_list",
22305
+ "schedule_create",
22306
+ "schedule_delete",
22307
+ "schedule_update",
22308
+ "knowledge_list",
22309
+ "knowledge_add",
22310
+ "knowledge_update",
22311
+ "knowledge_delete",
22312
+ "plugin_list",
22313
+ "plugin_improve",
22314
+ "dashboards_list",
22315
+ "dashboards_show",
22316
+ "dashboards_upsert",
22317
+ "dashboards_request_refresh",
22318
+ "dashboards_pending_refreshes",
22319
+ "dashboards_persist_widget",
22320
+ "projects_list",
22321
+ "projects_get",
22322
+ "projects_get_source_chunk"
22323
+ ]);
22282
22324
  async function registerForwardedApiTools() {
22283
22325
  const apiTools = await discoverApiTools();
22284
- const localToolNames = /* @__PURE__ */ new Set([
22285
- "kanban_list",
22286
- "kanban_add",
22287
- "kanban_move",
22288
- "kanban_update",
22289
- "kanban_progress",
22290
- "kanban_done",
22291
- "status_standup",
22292
- "status_update",
22293
- "drift_report",
22294
- "token_refresh",
22295
- "acpx_prompt",
22296
- "acpx_exec",
22297
- "acpx_spawn",
22298
- "acpx_cancel",
22299
- "knowledge_list",
22300
- "knowledge_search",
22301
- "knowledge_read",
22302
- "knowledge_add",
22303
- "knowledge_update",
22304
- "knowledge_delete",
22305
- "plugin_list",
22306
- "plugin_improve"
22307
- ]);
22326
+ const localToolNames = LOCAL_TOOL_NAMES;
22308
22327
  let registered = 0;
22309
22328
  let skipped = 0;
22310
22329
  for (const tool of apiTools) {
@@ -14265,6 +14265,9 @@ function decideAckReaction(i) {
14265
14265
  }
14266
14266
  return "ack";
14267
14267
  }
14268
+ function decideRecoveryHeal(i) {
14269
+ return i.wasUndeliverable && i.hasTarget ? "heal" : "none";
14270
+ }
14268
14271
  function oldestPendingMarkerAgeMs(dir, now = Date.now()) {
14269
14272
  if (!dir) return null;
14270
14273
  let names;
@@ -15589,14 +15592,16 @@ function slackPendingInboundPath(channel, threadTs, messageTs) {
15589
15592
  if (!SLACK_PENDING_INBOUND_DIR) return null;
15590
15593
  return join4(SLACK_PENDING_INBOUND_DIR, safeSlackMarkerName(channel, threadTs, messageTs));
15591
15594
  }
15592
- function writeSlackPendingInboundMarker(channel, threadTs, messageTs) {
15595
+ function writeSlackPendingInboundMarker(channel, threadTs, messageTs, undeliverable = false) {
15593
15596
  const path = slackPendingInboundPath(channel, threadTs, messageTs);
15594
15597
  if (!path || !SLACK_PENDING_INBOUND_DIR) return;
15595
15598
  const marker = {
15596
15599
  channel,
15597
15600
  thread_ts: threadTs,
15598
15601
  message_ts: messageTs,
15599
- received_at: (/* @__PURE__ */ new Date()).toISOString()
15602
+ received_at: (/* @__PURE__ */ new Date()).toISOString(),
15603
+ // Only persist the flag when set — keeps healthy-path markers byte-identical.
15604
+ ...undeliverable ? { undeliverable: true } : {}
15600
15605
  };
15601
15606
  try {
15602
15607
  mkdirSync3(SLACK_PENDING_INBOUND_DIR, { recursive: true, mode: 448 });
@@ -15608,6 +15613,43 @@ function writeSlackPendingInboundMarker(channel, threadTs, messageTs) {
15608
15613
  );
15609
15614
  }
15610
15615
  }
15616
+ function healSlackUndeliverable(channel, messageTs) {
15617
+ if (!BOT_TOKEN || !channel || !messageTs) return;
15618
+ const headers = {
15619
+ "Content-Type": "application/json",
15620
+ Authorization: `Bearer ${BOT_TOKEN}`
15621
+ };
15622
+ fetch("https://slack.com/api/reactions.remove", {
15623
+ method: "POST",
15624
+ headers,
15625
+ body: JSON.stringify({ channel, timestamp: messageTs, name: "x" })
15626
+ }).catch(() => {
15627
+ }).finally(() => {
15628
+ fetch("https://slack.com/api/reactions.add", {
15629
+ method: "POST",
15630
+ headers,
15631
+ body: JSON.stringify({ channel, timestamp: messageTs, name: "eyes" })
15632
+ }).catch(() => {
15633
+ });
15634
+ });
15635
+ }
15636
+ function clearSlackMarkerFileWithHeal(fullPath) {
15637
+ let marker = null;
15638
+ try {
15639
+ marker = JSON.parse(readFileSync4(fullPath, "utf-8"));
15640
+ } catch {
15641
+ }
15642
+ if (marker && decideRecoveryHeal({
15643
+ wasUndeliverable: marker.undeliverable === true,
15644
+ hasTarget: Boolean(marker.channel && marker.message_ts)
15645
+ }) === "heal") {
15646
+ healSlackUndeliverable(marker.channel, marker.message_ts);
15647
+ }
15648
+ try {
15649
+ if (existsSync2(fullPath)) unlinkSync2(fullPath);
15650
+ } catch {
15651
+ }
15652
+ }
15611
15653
  function clearAllSlackPendingMarkersForThread(channel, threadTs) {
15612
15654
  if (!SLACK_PENDING_INBOUND_DIR) return;
15613
15655
  const safeChan = channel.replace(/[^A-Za-z0-9_-]/g, "_");
@@ -15616,10 +15658,7 @@ function clearAllSlackPendingMarkersForThread(channel, threadTs) {
15616
15658
  try {
15617
15659
  for (const f of readdirSync2(SLACK_PENDING_INBOUND_DIR)) {
15618
15660
  if (!f.startsWith(prefix) || !f.endsWith(".json")) continue;
15619
- try {
15620
- unlinkSync2(join4(SLACK_PENDING_INBOUND_DIR, f));
15621
- } catch {
15622
- }
15661
+ clearSlackMarkerFileWithHeal(join4(SLACK_PENDING_INBOUND_DIR, f));
15623
15662
  }
15624
15663
  } catch {
15625
15664
  }
@@ -15800,8 +15839,8 @@ function startSlackRecoveryOutboxWatcher() {
15800
15839
  }
15801
15840
  startSlackRecoveryOutboxWatcher();
15802
15841
  var STALE_MARKER_MS = 24 * 60 * 60 * 1e3;
15803
- function trackPendingMessage(channel, threadTs, messageTs) {
15804
- writeSlackPendingInboundMarker(channel, threadTs, messageTs);
15842
+ function trackPendingMessage(channel, threadTs, messageTs, undeliverable = false) {
15843
+ writeSlackPendingInboundMarker(channel, threadTs, messageTs, undeliverable);
15805
15844
  }
15806
15845
  function sweepSlackStaleMarkersOnBoot() {
15807
15846
  if (!SLACK_PENDING_INBOUND_DIR) return;
@@ -15888,10 +15927,7 @@ function noteThreadActivityByMessageTs(channel, messageTs) {
15888
15927
  for (const filename of filenames) {
15889
15928
  if (!filename.startsWith(channelPrefix)) continue;
15890
15929
  if (!filename.endsWith(messageSuffix)) continue;
15891
- try {
15892
- unlinkSync2(join4(SLACK_PENDING_INBOUND_DIR, filename));
15893
- } catch {
15894
- }
15930
+ clearSlackMarkerFileWithHeal(join4(SLACK_PENDING_INBOUND_DIR, filename));
15895
15931
  }
15896
15932
  }
15897
15933
  var RESTART_FLAGS_DIR = join4(homedir2(), ".augmented", "restart-flags");
@@ -17888,7 +17924,7 @@ async function connectSocketMode() {
17888
17924
  });
17889
17925
  }
17890
17926
  if (channel && ts && shouldEngage) {
17891
- trackPendingMessage(channel, threadTs, ts);
17927
+ trackPendingMessage(channel, threadTs, ts, ackDecision === "undeliverable");
17892
17928
  }
17893
17929
  const userName = await resolveUserName(user);
17894
17930
  const fileMeta = await buildInboundFileMeta(evt.files, AGENT_CODE_NAME, channel);
@@ -15517,6 +15517,9 @@ function decideAckReaction(i) {
15517
15517
  }
15518
15518
  return "ack";
15519
15519
  }
15520
+ function decideRecoveryHeal(i) {
15521
+ return i.wasUndeliverable && i.hasTarget ? "heal" : "none";
15522
+ }
15520
15523
  function oldestPendingMarkerAgeMs(dir, now = Date.now()) {
15521
15524
  if (!dir) return null;
15522
15525
  let names;
@@ -15805,6 +15808,40 @@ async function notifyUndeliverable(chatId, messageId) {
15805
15808
  function __resetUndeliverableNoticeThrottle() {
15806
15809
  lastUndeliverableNoticeAt.clear();
15807
15810
  }
15811
+ var lastBackOnlineNoticeAt = /* @__PURE__ */ new Map();
15812
+ function notifyBackOnline(chatId) {
15813
+ const key2 = String(chatId);
15814
+ const now = Date.now();
15815
+ const last = lastBackOnlineNoticeAt.get(key2);
15816
+ if (last != null && now - last < UNDELIVERABLE_NOTICE_THROTTLE_MS) return;
15817
+ lastBackOnlineNoticeAt.set(key2, now);
15818
+ void (async () => {
15819
+ try {
15820
+ const resp = await telegramApiCall(
15821
+ "sendMessage",
15822
+ {
15823
+ chat_id: chatId,
15824
+ text: "\u2705 Back online \u2014 catching up on what I missed."
15825
+ },
15826
+ 1e4
15827
+ );
15828
+ if (!resp.ok) {
15829
+ process.stderr.write(
15830
+ `telegram-channel(${AGENT_CODE_NAME}): back-online notice failed (chat=${redactId(chatId)}): ${resp.description ?? "unknown"}
15831
+ `
15832
+ );
15833
+ }
15834
+ } catch (err) {
15835
+ process.stderr.write(
15836
+ `telegram-channel(${AGENT_CODE_NAME}): back-online notice error: ${err.message}
15837
+ `
15838
+ );
15839
+ }
15840
+ })();
15841
+ }
15842
+ function __resetBackOnlineNoticeThrottle() {
15843
+ lastBackOnlineNoticeAt.clear();
15844
+ }
15808
15845
  var RESTART_FLAGS_DIR = join4(homedir2(), ".augmented", "restart-flags");
15809
15846
  function buildTelegramHelpMessage(codeName) {
15810
15847
  return [
@@ -15972,14 +16009,16 @@ function pendingInboundPath(chatId, messageId) {
15972
16009
  if (!PENDING_INBOUND_DIR) return null;
15973
16010
  return join4(PENDING_INBOUND_DIR, safeMarkerName(chatId, messageId));
15974
16011
  }
15975
- function writePendingInboundMarker(chatId, messageId, chatType) {
16012
+ function writePendingInboundMarker(chatId, messageId, chatType, undeliverable = false) {
15976
16013
  const path = pendingInboundPath(chatId, messageId);
15977
16014
  if (!path || !PENDING_INBOUND_DIR) return;
15978
16015
  const marker = {
15979
16016
  chat_id: chatId,
15980
16017
  message_id: messageId,
15981
16018
  chat_type: chatType,
15982
- received_at: (/* @__PURE__ */ new Date()).toISOString()
16019
+ received_at: (/* @__PURE__ */ new Date()).toISOString(),
16020
+ // Only persist the flag when set — keeps healthy-path markers byte-identical.
16021
+ ...undeliverable ? { undeliverable: true } : {}
15983
16022
  };
15984
16023
  try {
15985
16024
  mkdirSync3(PENDING_INBOUND_DIR, { recursive: true, mode: 448 });
@@ -15991,14 +16030,28 @@ function writePendingInboundMarker(chatId, messageId, chatType) {
15991
16030
  );
15992
16031
  }
15993
16032
  }
15994
- function clearPendingInboundMarker(chatId, messageId) {
15995
- const path = pendingInboundPath(chatId, messageId);
15996
- if (!path) return;
16033
+ function clearTelegramMarkerFileWithHeal(fullPath) {
16034
+ let marker = null;
15997
16035
  try {
15998
- if (existsSync2(path)) unlinkSync3(path);
16036
+ marker = JSON.parse(readFileSync3(fullPath, "utf-8"));
16037
+ } catch {
16038
+ }
16039
+ if (marker && decideRecoveryHeal({
16040
+ wasUndeliverable: marker.undeliverable === true,
16041
+ hasTarget: Boolean(marker.chat_id)
16042
+ }) === "heal") {
16043
+ notifyBackOnline(marker.chat_id);
16044
+ }
16045
+ try {
16046
+ if (existsSync2(fullPath)) unlinkSync3(fullPath);
15999
16047
  } catch {
16000
16048
  }
16001
16049
  }
16050
+ function clearPendingInboundMarker(chatId, messageId) {
16051
+ const path = pendingInboundPath(chatId, messageId);
16052
+ if (!path) return;
16053
+ clearTelegramMarkerFileWithHeal(path);
16054
+ }
16002
16055
  var MAX_RECOVERY_ATTEMPTS = 3;
16003
16056
  function nextRetryName(filename) {
16004
16057
  const match = filename.match(/^(.*?)(?:\.retry-(\d+))?\.json$/);
@@ -16166,8 +16219,8 @@ function startRecoveryOutboxWatcher() {
16166
16219
  }
16167
16220
  startRecoveryOutboxWatcher();
16168
16221
  var STALE_MARKER_MS = 24 * 60 * 60 * 1e3;
16169
- function trackPendingMessage(chatId, messageId, chatType) {
16170
- writePendingInboundMarker(chatId, messageId, chatType);
16222
+ function trackPendingMessage(chatId, messageId, chatType, undeliverable = false) {
16223
+ writePendingInboundMarker(chatId, messageId, chatType, undeliverable);
16171
16224
  }
16172
16225
  function sweepTelegramStaleMarkersOnBoot() {
16173
16226
  if (!PENDING_INBOUND_DIR) return;
@@ -16246,10 +16299,7 @@ function clearPendingMessage(chatId, messageId) {
16246
16299
  for (const filename of filenames) {
16247
16300
  if (!filename.startsWith(prefix)) continue;
16248
16301
  if (!filename.endsWith(".json")) continue;
16249
- try {
16250
- unlinkSync3(join4(PENDING_INBOUND_DIR, filename));
16251
- } catch {
16252
- }
16302
+ clearTelegramMarkerFileWithHeal(join4(PENDING_INBOUND_DIR, filename));
16253
16303
  }
16254
16304
  }
16255
16305
  function noteThreadActivity(chatId, messageId) {
@@ -17104,7 +17154,7 @@ async function pollLoop() {
17104
17154
  } else if (ackDecision === "undeliverable") {
17105
17155
  void notifyUndeliverable(chatId, messageId);
17106
17156
  }
17107
- trackPendingMessage(chatId, messageId, msg.chat.type);
17157
+ trackPendingMessage(chatId, messageId, msg.chat.type, ackDecision === "undeliverable");
17108
17158
  const fileMeta = [];
17109
17159
  for (const attachment of classifiedAttachments) {
17110
17160
  if (attachment.kind === "image") {
@@ -17231,5 +17281,6 @@ pollLoop().catch((err) => {
17231
17281
  process.exit(1);
17232
17282
  });
17233
17283
  export {
17284
+ __resetBackOnlineNoticeThrottle,
17234
17285
  __resetUndeliverableNoticeThrottle
17235
17286
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@integrity-labs/agt-cli",
3
- "version": "0.27.18",
3
+ "version": "0.27.20",
4
4
  "description": "Augmented Team CLI — agent provisioning and management",
5
5
  "type": "module",
6
6
  "engines": {