@integrity-labs/agt-cli 0.28.398 → 0.28.400

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
@@ -40,7 +40,7 @@ import {
40
40
  success,
41
41
  table,
42
42
  warn
43
- } from "../chunk-QQ4ZC5K3.js";
43
+ } from "../chunk-MZ7EU4V7.js";
44
44
  import {
45
45
  AnchorSessionClient,
46
46
  CHANNEL_REGISTRY,
@@ -4829,7 +4829,7 @@ import { execFileSync, execSync } from "child_process";
4829
4829
  import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
4830
4830
  import chalk18 from "chalk";
4831
4831
  import ora16 from "ora";
4832
- var cliVersion = true ? "0.28.398" : "dev";
4832
+ var cliVersion = true ? "0.28.400" : "dev";
4833
4833
  async function fetchLatestVersion() {
4834
4834
  const host2 = getHost();
4835
4835
  if (!host2) return null;
@@ -6001,7 +6001,7 @@ function handleError(err) {
6001
6001
  }
6002
6002
 
6003
6003
  // src/bin/agt.ts
6004
- var cliVersion2 = true ? "0.28.398" : "dev";
6004
+ var cliVersion2 = true ? "0.28.400" : "dev";
6005
6005
  var program = new Command();
6006
6006
  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");
6007
6007
  program.hook("preAction", async (thisCommand, actionCommand) => {
@@ -2683,7 +2683,7 @@ function provisionStopHook(codeName) {
2683
2683
  "# classify a miss without guessing. A missing TAG_SOURCE here explains the",
2684
2684
  "# 'marker present but never recovered' mystery (no <channel> tag correlated).",
2685
2685
  "REPLY_IN_LAST=no",
2686
- `if echo "$TOOL_NAMES" | grep -qE '(^|__)(slack|telegram|teams)[._](reply|send_message)$'; then REPLY_IN_LAST=yes; fi`,
2686
+ `if echo "$TOOL_NAMES" | grep -qE '(^|__)(slack|telegram|teams)[._](reply|send_message)$|(^|__)direct_chat[._](reply|consume)$'; then REPLY_IN_LAST=yes; fi`,
2687
2687
  'log_ghost "stop source=${TAG_SOURCE:-none} pending(tg=$TG_PENDING sl=$SL_PENDING ms=$MS_PENDING dc=$DC_PENDING) text_len=${#TEXT} reply_tool_in_final_turn=$REPLY_IN_LAST"',
2688
2688
  'extract_attr() { echo "$1" | grep -oE "$2=\\"[^\\"]+\\"" | head -1 | sed -E "s/$2=\\"(.*)\\"/\\\\1/"; }',
2689
2689
  "# Atomic write helper: jq \u2192 tmp file in same dir, then rename. The",
@@ -2990,18 +2990,30 @@ function provisionStopHook(codeName) {
2990
2990
  " done",
2991
2991
  ' if [ -z "$marker_path" ]; then log_ghost "direct-chat skip=no_pending_marker session=$(safe_id "$session_id")"; return; fi',
2992
2992
  ' local marker_name; marker_name="$(basename "$marker_path")"',
2993
- " # Already recovered once and awaiting delivery confirmation \u21D2 do not re-send.",
2994
- ' if [ -f "${DC_RECOVERY_LEDGER_DIR}/${marker_name}" ]; then log_ghost "direct-chat skip=recovery_in_flight session=$(safe_id "$session_id")"; return; fi',
2995
2993
  " # Persist the per-marker cap BEFORE the side effect (same fail-safe as",
2996
2994
  " # block-turn-end): if the ledger dir/file write fails we could re-recover every",
2997
2995
  " # Stop, so degrade to a logged skip and write no payload.",
2998
2996
  ' if ! mkdir -p "$DC_RECOVERY_LEDGER_DIR" 2>/dev/null; then log_ghost "direct-chat skip=recovery_ledger_unwritable session=$(safe_id "$session_id")"; return; fi',
2999
- ' if ! : > "${DC_RECOVERY_LEDGER_DIR}/${marker_name}" 2>/dev/null; then log_ghost "direct-chat skip=recovery_ledger_unwritable session=$(safe_id "$session_id")"; return; fi',
2997
+ " # ENG-7944 (CodeRabbit): atomic acquire - noclobber create fails if the entry",
2998
+ " # already exists (recovery in flight) OR the write faults; the follow-up [ -f ]",
2999
+ ' # disambiguates. Closes the "[ -f ] then : >" TOCTOU where two concurrent Stops',
3000
+ " # both observe no entry and both enqueue a duplicate payload (matches the",
3001
+ " # telegram/slack recovery paths).",
3002
+ ' if ! ( set -o noclobber; : > "${DC_RECOVERY_LEDGER_DIR}/${marker_name}" ) 2>/dev/null; then',
3003
+ ' if [ -f "${DC_RECOVERY_LEDGER_DIR}/${marker_name}" ]; then log_ghost "direct-chat skip=recovery_in_flight session=$(safe_id "$session_id")"; else log_ghost "direct-chat skip=recovery_ledger_unwritable session=$(safe_id "$session_id")"; fi',
3004
+ " return",
3005
+ " fi",
3000
3006
  " local TS",
3001
3007
  " TS=$(date -u +%Y%m%dT%H%M%S%N)",
3002
- ' atomic_write_payload "$DC_RECOVERY_OUTBOX_DIR" "${TS}.json" \\',
3008
+ ' if ! atomic_write_payload "$DC_RECOVERY_OUTBOX_DIR" "${TS}.json" \\',
3003
3009
  ` '{session_id:$s, text:$t, marker_name:$mn, source:"ghost-reply-recovery"}' \\`,
3004
- ' --arg s "$session_id" --arg t "$TEXT" --arg mn "$marker_name"',
3010
+ ' --arg s "$session_id" --arg t "$TEXT" --arg mn "$marker_name"; then',
3011
+ " # ENG-7944 (CodeRabbit): the write faulted after the ledger was acquired -",
3012
+ " # drop the ledger entry so replay + the next Stop are not suppressed until GC.",
3013
+ ' rm -f "${DC_RECOVERY_LEDGER_DIR}/${marker_name}" 2>/dev/null || true',
3014
+ ' log_ghost "direct-chat skip=recovery_payload_write_failed session=$(safe_id "$session_id")"',
3015
+ " return",
3016
+ " fi",
3005
3017
  ' log_ghost "direct-chat RECOVERED session=$(safe_id "$session_id") text_len=${#TEXT}"',
3006
3018
  "}",
3007
3019
  '# ENG-6467 / ADR-0024 Slice 2.5 \u2014 block-turn-end (the D1 "composed-but-unsent"',
@@ -3034,11 +3046,10 @@ function provisionStopHook(codeName) {
3034
3046
  "# ENG-7814 (ENG-6722 slice E): always-on direct-chat recovery. When ON, an owed",
3035
3047
  "# and unanswered direct-chat inbound that block-turn-end did NOT handle gets its",
3036
3048
  "# last assistant text written to a direct-chat-recovery-outbox that the direct-chat",
3037
- "# MCP re-sends via /host/direct-chat/reply. Registry flag direct-chat-recovery; the",
3038
- "# env var is the operator/host override the bash reads directly. OFF (default) keeps",
3039
- "# today's behavior (direct-chat gets block-turn-end only, no recovery).",
3040
- "DC_RECOVERY_ON=0",
3041
- 'case "${AGT_DIRECT_CHAT_RECOVERY_ENABLED:-}" in true|1|TRUE|True) DC_RECOVERY_ON=1;; esac',
3049
+ "# MCP re-sends via /host/direct-chat/reply. ENG-7944: recovery is now always-on",
3050
+ "# (matching Slack/Telegram/Teams). The kill-switch is the MCP consumer flag",
3051
+ "# (direct-chat-recovery / AGT_DIRECT_CHAT_RECOVERY_ENABLED), which can be set",
3052
+ "# to false to disable delivery without a deploy. DC_RECOVERY_ON removed.",
3042
3053
  'DC_RECOVERY_OUTBOX_DIR="${AGENT_DIR}/direct-chat-recovery-outbox"',
3043
3054
  "# Per-marker recovery ledger: caps ONE in-flight recovery per inbound (so a marker",
3044
3055
  "# left pending for confirm-before-clear is not re-recovered every Stop). The MCP",
@@ -3284,29 +3295,27 @@ function provisionStopHook(codeName) {
3284
3295
  ' DC_REPLIED=no; if replied_this_conv_directchat "$SESSION_ID"; then DC_REPLIED=yes; fi',
3285
3296
  ` if emit_block_if_obligated "$DC_REPLIED" "$DC_CAND" 'direct_chat.reply'; then exit 0; fi`,
3286
3297
  ' if [ "$DC_REPLIED" = "no" ]; then',
3287
- ' if [ "$DC_RECOVERY_ON" = "1" ]; then',
3288
- ' recover_directchat_for "$SESSION_ID" "$HEX_SESSION"',
3289
- " else",
3290
- ' log_ghost "direct-chat skip=no_recovery_path session=$(safe_id "$SESSION_ID") (block-turn-end off/capped; direct-chat-recovery off)"',
3291
- " fi",
3298
+ " # ENG-7944: call unconditionally \u2014 mirrors the always-on Slack/Telegram/Teams",
3299
+ " # recovery paths. The MCP consumer (processDirectChatRecoveryOutboxFile) still",
3300
+ " # gates on the direct-chat-recovery feature flag before delivering, so the hook",
3301
+ " # just writes the outbox payload and lets the consumer decide. DC_RECOVERY_ON",
3302
+ " # is no longer needed here.",
3303
+ ' recover_directchat_for "$SESSION_ID" "$HEX_SESSION"',
3292
3304
  " fi",
3293
3305
  " fi",
3294
3306
  'elif [ -z "$TAG_SOURCE" ]; then',
3295
3307
  " # ENG-6467: TAG_SOURCE=none fallback (AC1). Guarded on an EMPTY source, not",
3296
- " # a catch-all else: a parsed-but-unsupported source (e.g. direct-chat, which",
3297
- " # has its own durable replay) must NOT fall through here, or its trailing",
3298
- " # text could be misdelivered to a pending slack/telegram/teams marker.",
3299
- " # The last <channel> tag could not be parsed (a malformed/partial preamble,",
3300
- " # or any residual extraction miss) yet a reply is owed. When EXACTLY ONE",
3301
- " # channel marker is pending",
3302
- " # agent-wide AND the final turn produced text with NO reply tool call,",
3303
- " # there is a single unambiguous candidate, so recover it. Cross-thread",
3304
- " # mis-correlation (the koda risk) is impossible with one candidate, and the",
3305
- " # recover_*_for recency guard still suppresses if the agent moved on. The",
3306
- " # marker key is read from the marker contents (real channel markers carry",
3307
- " # channel/thread_ts | chat_id/message_id | conversation_id/service_url); a",
3308
- " # contentless {} marker yields empty keys and recover_*_for returns early.",
3309
- " TOTAL_PENDING=$(( TG_PENDING + SL_PENDING + MS_PENDING ))",
3308
+ " # a catch-all else: a parsed-but-unsupported source must NOT fall through here",
3309
+ " # or its trailing text could be misdelivered to a pending marker on the wrong",
3310
+ " # channel. The last <channel> tag could not be parsed (a malformed/partial",
3311
+ " # preamble, or any residual extraction miss) yet a reply is owed. When EXACTLY",
3312
+ " # ONE channel marker is pending agent-wide AND the final turn produced text",
3313
+ " # with NO reply tool call, there is a single unambiguous candidate, so recover",
3314
+ " # it. Cross-thread mis-correlation is impossible with one candidate, and the",
3315
+ " # recover_*_for recency guard still suppresses if the agent moved on.",
3316
+ " # ENG-7944: DC_PENDING is now included so a lone direct-chat pending marker",
3317
+ " # with an unparsed tag can also be recovered via the single-candidate path.",
3318
+ " TOTAL_PENDING=$(( TG_PENDING + SL_PENDING + MS_PENDING + DC_PENDING ))",
3310
3319
  ' if [ "$TOTAL_PENDING" = "1" ] && [ "$REPLY_IN_LAST" = "no" ]; then',
3311
3320
  " shopt -s nullglob",
3312
3321
  ' if [ "$SL_PENDING" = "1" ]; then',
@@ -3331,6 +3340,14 @@ function provisionStopHook(codeName) {
3331
3340
  ' log_ghost "fallback=tag_source_none channel=msteams marker=$(basename "$f")"',
3332
3341
  ' recover_teams_for "$FB_CONV" "$FB_RID" "$FB_SVC"',
3333
3342
  " done",
3343
+ ' elif [ "$DC_PENDING" = "1" ]; then',
3344
+ " # ENG-7944: single-candidate direct-chat recovery for unparsed TAG_SOURCE.",
3345
+ ' for f in "$DC_MARKER_DIR"/*.json; do',
3346
+ ` FB_SID=$(jq -r '.session_id // empty' "$f" 2>/dev/null || true)`,
3347
+ ' FB_HSID=$(printf %s "$FB_SID" | od -An -tx1 | tr -d " \\n")',
3348
+ ' log_ghost "fallback=tag_source_none channel=direct-chat marker=$(basename "$f")"',
3349
+ ' recover_directchat_for "$FB_SID" "$FB_HSID"',
3350
+ " done",
3334
3351
  " fi",
3335
3352
  " else",
3336
3353
  ' log_ghost "skip=tag_source_none pending_total=$TOTAL_PENDING reply_in_last=$REPLY_IN_LAST"',
@@ -6196,7 +6213,7 @@ function requireHost() {
6196
6213
  }
6197
6214
 
6198
6215
  // src/lib/api-client.ts
6199
- var agtCliVersion = true ? "0.28.398" : "dev";
6216
+ var agtCliVersion = true ? "0.28.400" : "dev";
6200
6217
  var lastConfigHash = null;
6201
6218
  function setConfigHash(hash) {
6202
6219
  lastConfigHash = hash && hash.length > 0 ? hash : null;
@@ -8662,4 +8679,4 @@ export {
8662
8679
  managerInstallSystemUnitCommand,
8663
8680
  managerUninstallSystemUnitCommand
8664
8681
  };
8665
- //# sourceMappingURL=chunk-QQ4ZC5K3.js.map
8682
+ //# sourceMappingURL=chunk-MZ7EU4V7.js.map