@integrity-labs/agt-cli 0.28.330 → 0.28.332
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 +3 -3
- package/dist/{chunk-CDRVXSQ3.js → chunk-YNHMQ4CW.js} +200 -41
- package/dist/chunk-YNHMQ4CW.js.map +1 -0
- package/dist/lib/manager-worker.js +4 -4
- package/dist/mcp/direct-chat-channel.js +92 -51
- package/dist/mcp/slack-channel.js +212 -146
- package/dist/mcp/teams-channel.js +133 -63
- package/dist/mcp/telegram-channel.js +187 -110
- package/dist/{responsiveness-probe-OJJESVVX.js → responsiveness-probe-46XFHCPY.js} +12 -2
- package/dist/responsiveness-probe-46XFHCPY.js.map +1 -0
- package/package.json +1 -1
- package/dist/chunk-CDRVXSQ3.js.map +0 -1
- package/dist/responsiveness-probe-OJJESVVX.js.map +0 -1
package/dist/bin/agt.js
CHANGED
|
@@ -38,7 +38,7 @@ import {
|
|
|
38
38
|
success,
|
|
39
39
|
table,
|
|
40
40
|
warn
|
|
41
|
-
} from "../chunk-
|
|
41
|
+
} from "../chunk-YNHMQ4CW.js";
|
|
42
42
|
import {
|
|
43
43
|
AnchorSessionClient,
|
|
44
44
|
CHANNEL_REGISTRY,
|
|
@@ -4827,7 +4827,7 @@ import { execFileSync, execSync } from "child_process";
|
|
|
4827
4827
|
import { existsSync as existsSync10, realpathSync as realpathSync2 } from "fs";
|
|
4828
4828
|
import chalk18 from "chalk";
|
|
4829
4829
|
import ora16 from "ora";
|
|
4830
|
-
var cliVersion = true ? "0.28.
|
|
4830
|
+
var cliVersion = true ? "0.28.332" : "dev";
|
|
4831
4831
|
async function fetchLatestVersion() {
|
|
4832
4832
|
const host2 = getHost();
|
|
4833
4833
|
if (!host2) return null;
|
|
@@ -5931,7 +5931,7 @@ function handleError(err) {
|
|
|
5931
5931
|
}
|
|
5932
5932
|
|
|
5933
5933
|
// src/bin/agt.ts
|
|
5934
|
-
var cliVersion2 = true ? "0.28.
|
|
5934
|
+
var cliVersion2 = true ? "0.28.332" : "dev";
|
|
5935
5935
|
var program = new Command();
|
|
5936
5936
|
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");
|
|
5937
5937
|
program.hook("preAction", async (thisCommand, actionCommand) => {
|
|
@@ -2712,9 +2712,13 @@ function provisionStopHook(codeName) {
|
|
|
2712
2712
|
"# observed mid-write.",
|
|
2713
2713
|
"atomic_write_payload() {",
|
|
2714
2714
|
' local out_dir="$1" final="$2" jq_expr="$3"; shift 3',
|
|
2715
|
-
' mkdir -p "$out_dir"',
|
|
2715
|
+
' if ! mkdir -p "$out_dir" 2>/dev/null; then return 1; fi',
|
|
2716
2716
|
' local tmp="$out_dir/.${final##*/}.tmp"',
|
|
2717
|
-
|
|
2717
|
+
" # ENG-7805 (CodeRabbit): fail (non-zero) on a jq/write fault instead of",
|
|
2718
|
+
" # mv-ing a half-written tmp - the script has no set -e, so an unguarded jq",
|
|
2719
|
+
" # error would otherwise ship an empty payload AND let callers believe the",
|
|
2720
|
+
" # write succeeded (leaving a recovery-ledger entry orphaned until GC).",
|
|
2721
|
+
' if ! jq -n "$jq_expr" "$@" > "$tmp" 2>/dev/null; then rm -f "$tmp" 2>/dev/null || true; return 1; fi',
|
|
2718
2722
|
' chmod 600 "$tmp" 2>/dev/null || true',
|
|
2719
2723
|
' mv -f "$tmp" "$out_dir/$final"',
|
|
2720
2724
|
"}",
|
|
@@ -2768,19 +2772,47 @@ function provisionStopHook(codeName) {
|
|
|
2768
2772
|
" # it moved on and TEXT is not a reliably-correlated ghost of THIS inbound \u2014",
|
|
2769
2773
|
" # recovering it would post mis-correlated text. Stay silent: a silent gap the",
|
|
2770
2774
|
" # operator re-pings beats wrong content that poisons trust.",
|
|
2771
|
-
"
|
|
2772
|
-
|
|
2773
|
-
'
|
|
2775
|
+
" # ENG-7806 (fm1): delivery-ledger read replaces the transcript scan (conv_key",
|
|
2776
|
+
" # = chat_id, Telegram's conversation grain). no_ledger falls back to the scan.",
|
|
2777
|
+
' local _tg_m="${TG_MARKER_DIR}/$(safe_id "$chat_id")__$(safe_id "$msg_id").json" _tg_iid="" _tg_recv=""',
|
|
2778
|
+
` if [ -f "$_tg_m" ]; then _tg_iid=$(jq -r '.inbound_id // ""' "$_tg_m" 2>/dev/null || echo ""); _tg_recv=$(jq -r '.received_at // ""' "$_tg_m" 2>/dev/null || echo ""); fi`,
|
|
2779
|
+
' case "$(delivery_ledger_verdict "$_tg_iid" "$chat_id" "$_tg_recv")" in',
|
|
2780
|
+
' self) log_ghost "telegram skip=already_delivered chat=$(safe_id "$chat_id")"; return ;;',
|
|
2781
|
+
' moved_on) log_ghost "telegram skip=moved_on_after_tag_ledger chat=$(safe_id "$chat_id")"; return ;;',
|
|
2782
|
+
" no_ledger)",
|
|
2783
|
+
" local replied_other",
|
|
2784
|
+
` replied_other=$(jq -s --arg cid "$chat_id" 'def ctext: (.message.content // .content // []) | if type=="string" then . elif type=="array" then (map(select(type=="object" and .type=="text")|.text)|join(" ")) else "" end; . as $all | ([ range(0; ($all|length)) | select((($all[.]|ctext)|test("<channel ")) and (($all[.]|(.type // .role // "")) != "assistant")) ] | last) as $idx | [ $all[(($idx // -1)+1):][] | select((.type // .role)=="assistant") | (.message.content // .content // []) | (if type=="array" then . else [] end) | .[] | select((.type=="tool_use") and ((.name|tostring)|test("telegram[._](reply|send_message)$")) and (((.input.chat_id // "")|tostring) as $c | ($c != $cid and $c != ""))) ] | length' "$RECENT_FILE" 2>/dev/null || true)`,
|
|
2785
|
+
' if [ "${replied_other:-0}" -gt 0 ] 2>/dev/null; then return; fi',
|
|
2786
|
+
" ;;",
|
|
2787
|
+
" esac",
|
|
2774
2788
|
" local marker_name",
|
|
2775
2789
|
' marker_name="$(safe_id "$chat_id")__$(safe_id "$msg_id").json"',
|
|
2776
2790
|
' local marker_path="${TG_MARKER_DIR}/${marker_name}"',
|
|
2777
2791
|
' if [ ! -f "$marker_path" ]; then log_ghost "telegram skip=no_pending_marker chat=$(safe_id "$chat_id")"; return; fi',
|
|
2792
|
+
" # ENG-7805 (fm2): confirm-before-clear. Cap re-fire with a per-marker ledger and",
|
|
2793
|
+
" # LEAVE the marker for the consumer to clear on confirmed send. Ledger-first",
|
|
2794
|
+
" # fail-safe (same as recover_directchat_for / block-turn-end): if the ledger",
|
|
2795
|
+
" # write fails, log a skip and write no payload rather than re-fire every Stop.",
|
|
2796
|
+
' if ! mkdir -p "$TG_RECOVERY_LEDGER_DIR" 2>/dev/null; then log_ghost "telegram skip=recovery_ledger_unwritable chat=$(safe_id "$chat_id")"; return; fi',
|
|
2797
|
+
" # ENG-7805 (CodeRabbit): atomic acquire - noclobber create fails if the entry",
|
|
2798
|
+
" # already exists (recovery in flight) OR the write faults; the follow-up [ -f ]",
|
|
2799
|
+
' # disambiguates. Closes the "[ -f ] then : >" TOCTOU where two concurrent Stops',
|
|
2800
|
+
" # both observe no entry and both enqueue a duplicate payload.",
|
|
2801
|
+
' if ! ( set -o noclobber; : > "${TG_RECOVERY_LEDGER_DIR}/${marker_name}" ) 2>/dev/null; then',
|
|
2802
|
+
' if [ -f "${TG_RECOVERY_LEDGER_DIR}/${marker_name}" ]; then log_ghost "telegram skip=recovery_in_flight chat=$(safe_id "$chat_id")"; else log_ghost "telegram skip=recovery_ledger_unwritable chat=$(safe_id "$chat_id")"; fi',
|
|
2803
|
+
" return",
|
|
2804
|
+
" fi",
|
|
2778
2805
|
" local TS",
|
|
2779
2806
|
" TS=$(date -u +%Y%m%dT%H%M%S%N)",
|
|
2780
|
-
' atomic_write_payload "${AGENT_DIR}/telegram-recovery-outbox" "${TS}.json" \\',
|
|
2781
|
-
` '{chat_id:$c, message_id:$m, text:$t, source:"ghost-reply-recovery"}' \\`,
|
|
2782
|
-
' --arg c "$chat_id" --arg m "$msg_id" --arg t "$TEXT"',
|
|
2783
|
-
|
|
2807
|
+
' if ! atomic_write_payload "${AGENT_DIR}/telegram-recovery-outbox" "${TS}.json" \\',
|
|
2808
|
+
` '{chat_id:$c, message_id:$m, text:$t, marker_name:$mn, source:"ghost-reply-recovery"}' \\`,
|
|
2809
|
+
' --arg c "$chat_id" --arg m "$msg_id" --arg t "$TEXT" --arg mn "$marker_name"; then',
|
|
2810
|
+
" # ENG-7805 (CodeRabbit): the write faulted after the ledger was acquired -",
|
|
2811
|
+
" # drop the ledger entry so replay + the next Stop are not suppressed until GC.",
|
|
2812
|
+
' rm -f "${TG_RECOVERY_LEDGER_DIR}/${marker_name}" 2>/dev/null || true',
|
|
2813
|
+
' log_ghost "telegram skip=recovery_payload_write_failed chat=$(safe_id "$chat_id")"',
|
|
2814
|
+
" return",
|
|
2815
|
+
" fi",
|
|
2784
2816
|
' log_ghost "telegram RECOVERED chat=$(safe_id "$chat_id") msg=$(safe_id "$msg_id") text_len=${#TEXT}"',
|
|
2785
2817
|
"}",
|
|
2786
2818
|
"recover_slack_for() {",
|
|
@@ -2805,19 +2837,33 @@ function provisionStopHook(codeName) {
|
|
|
2805
2837
|
" # kickoff's, not the DM's). Replies BEFORE this inbound no longer suppress,",
|
|
2806
2838
|
" # so answering an older thread then this one recovers correctly. Silence on",
|
|
2807
2839
|
" # a genuine move-on still beats posting mis-correlated text.",
|
|
2808
|
-
"
|
|
2809
|
-
|
|
2810
|
-
'
|
|
2811
|
-
" #
|
|
2812
|
-
" #
|
|
2813
|
-
" #
|
|
2840
|
+
" # ENG-7806 (fm1): read the inbound-delivery ledger instead of scraping the",
|
|
2841
|
+
" # transcript. Find the target marker for its inbound_id + received_at, then ask",
|
|
2842
|
+
' # the ledger "already delivered / moved on to another conversation?" - a',
|
|
2843
|
+
" # byte-exact record, not coordinate/recency inference. no_ledger (a pre-C",
|
|
2844
|
+
" # session with no ledger data) falls back to the old transcript scan below.",
|
|
2845
|
+
" # CodeRabbit: select the SAME marker recovery will process (oldest for this",
|
|
2846
|
+
" # channel+thread) ONCE, so the self-check reads the exact inbound being recovered,",
|
|
2847
|
+
" # never a sibling message in a busy thread. Reused by the CS-1444 guard + recovery below.",
|
|
2814
2848
|
' local prefix="$(safe_id "$channel")__$(safe_id "$thread_ts")__"',
|
|
2815
2849
|
' local marker_path=""',
|
|
2816
2850
|
" shopt -s nullglob",
|
|
2817
|
-
' for f in "$SL_MARKER_DIR"/${prefix}*.json; do',
|
|
2818
|
-
' if [ -z "$marker_path" ]; then marker_path="$f"; fi',
|
|
2819
|
-
" done",
|
|
2851
|
+
' for f in "$SL_MARKER_DIR"/${prefix}*.json; do if [ -z "$marker_path" ]; then marker_path="$f"; fi; done',
|
|
2820
2852
|
' if [ -z "$marker_path" ]; then log_ghost "slack skip=no_pending_marker channel=$(safe_id "$channel") thread=$(safe_id "$thread_ts")"; return; fi',
|
|
2853
|
+
' local _sl_iid="" _sl_recv=""',
|
|
2854
|
+
` _sl_iid=$(jq -r '.inbound_id // ""' "$marker_path" 2>/dev/null || echo ""); _sl_recv=$(jq -r '.received_at // ""' "$marker_path" 2>/dev/null || echo "")`,
|
|
2855
|
+
' case "$(delivery_ledger_verdict "$_sl_iid" "$thread_ts" "$_sl_recv")" in',
|
|
2856
|
+
' self) log_ghost "slack skip=already_delivered thread=$(safe_id "$thread_ts")"; return ;;',
|
|
2857
|
+
' moved_on) log_ghost "slack skip=moved_on_after_tag_ledger thread=$(safe_id "$thread_ts")"; return ;;',
|
|
2858
|
+
" no_ledger)",
|
|
2859
|
+
" local replied_other",
|
|
2860
|
+
` replied_other=$(jq -s --arg th "$thread_ts" 'def ctext: (.message.content // .content // []) | if type=="string" then . elif type=="array" then (map(select(type=="object" and .type=="text")|.text)|join(" ")) else "" end; . as $all | ([ range(0; ($all|length)) | select((($all[.]|ctext)|test("<channel ")) and (($all[.]|(.type // .role // "")) != "assistant")) ] | last) as $idx | [ $all[(($idx // -1)+1):][] | select((.type // .role)=="assistant") | (.message.content // .content // []) | (if type=="array" then . else [] end) | .[] | select((.type=="tool_use") and ((.name|tostring)|test("slack[._]reply$")) and (((.input.thread_ts // .input.message_ts // "")) as $t | ($t != $th and $t != ""))) ] | length' "$RECENT_FILE" 2>/dev/null || true)`,
|
|
2861
|
+
' if [ "${replied_other:-0}" -gt 0 ] 2>/dev/null; then log_ghost "slack skip=moved_on_after_tag thread=$(safe_id "$thread_ts")"; return; fi',
|
|
2862
|
+
" ;;",
|
|
2863
|
+
" esac",
|
|
2864
|
+
" # marker_path (the oldest for this channel+thread, closest to firing the timeout)",
|
|
2865
|
+
" # was selected above and reused here - one selection shared by the ledger read,",
|
|
2866
|
+
" # the CS-1444 guard, and recovery.",
|
|
2821
2867
|
" # CS-1444: precedence guard against cross-thread mis-delivery. The last",
|
|
2822
2868
|
" # <channel> tag can point at a DISCRETIONARY (auto-followed, un-mentioned)",
|
|
2823
2869
|
" # inbound the agent never owed a reply to (ENG-6319). If the trailing text",
|
|
@@ -2861,13 +2907,29 @@ function provisionStopHook(codeName) {
|
|
|
2861
2907
|
" return",
|
|
2862
2908
|
" fi",
|
|
2863
2909
|
" fi",
|
|
2910
|
+
' local marker_name; marker_name="$(basename "$marker_path")"',
|
|
2911
|
+
" # ENG-7805 (fm2): confirm-before-clear. Cap re-fire with a per-marker ledger and",
|
|
2912
|
+
" # LEAVE the marker for the consumer to clear on confirmed send (ledger-first fail-safe).",
|
|
2913
|
+
' if ! mkdir -p "$SL_RECOVERY_LEDGER_DIR" 2>/dev/null; then log_ghost "slack skip=recovery_ledger_unwritable channel=$(safe_id "$channel") thread=$(safe_id "$thread_ts")"; return; fi',
|
|
2914
|
+
" # ENG-7805 (CodeRabbit): atomic acquire - noclobber create fails if the entry",
|
|
2915
|
+
" # already exists (recovery in flight) OR the write faults; the follow-up [ -f ]",
|
|
2916
|
+
' # disambiguates. Closes the "[ -f ] then : >" TOCTOU between concurrent Stops.',
|
|
2917
|
+
' if ! ( set -o noclobber; : > "${SL_RECOVERY_LEDGER_DIR}/${marker_name}" ) 2>/dev/null; then',
|
|
2918
|
+
' if [ -f "${SL_RECOVERY_LEDGER_DIR}/${marker_name}" ]; then log_ghost "slack skip=recovery_in_flight channel=$(safe_id "$channel") thread=$(safe_id "$thread_ts")"; else log_ghost "slack skip=recovery_ledger_unwritable channel=$(safe_id "$channel") thread=$(safe_id "$thread_ts")"; fi',
|
|
2919
|
+
" return",
|
|
2920
|
+
" fi",
|
|
2864
2921
|
" local TS",
|
|
2865
2922
|
" TS=$(date -u +%Y%m%dT%H%M%S%N)",
|
|
2866
|
-
' atomic_write_payload "${AGENT_DIR}/slack-recovery-outbox" "${TS}.json" \\',
|
|
2867
|
-
` '{channel:$c, thread_ts:$th, text:$t, source:"ghost-reply-recovery"}' \\`,
|
|
2868
|
-
' --arg c "$channel" --arg th "$thread_ts" --arg t "$TEXT"',
|
|
2869
|
-
|
|
2870
|
-
|
|
2923
|
+
' if ! atomic_write_payload "${AGENT_DIR}/slack-recovery-outbox" "${TS}.json" \\',
|
|
2924
|
+
` '{channel:$c, thread_ts:$th, text:$t, marker_name:$mn, source:"ghost-reply-recovery"}' \\`,
|
|
2925
|
+
' --arg c "$channel" --arg th "$thread_ts" --arg t "$TEXT" --arg mn "$marker_name"; then',
|
|
2926
|
+
" # ENG-7805 (CodeRabbit): write faulted after the ledger was acquired - drop",
|
|
2927
|
+
" # the ledger entry so replay + the next Stop are not suppressed until GC.",
|
|
2928
|
+
' rm -f "${SL_RECOVERY_LEDGER_DIR}/${marker_name}" 2>/dev/null || true',
|
|
2929
|
+
' log_ghost "slack skip=recovery_payload_write_failed channel=$(safe_id "$channel") thread=$(safe_id "$thread_ts")"',
|
|
2930
|
+
" return",
|
|
2931
|
+
" fi",
|
|
2932
|
+
' log_ghost "slack RECOVERED channel=$(safe_id "$channel") thread=$(safe_id "$thread_ts") marker=${marker_name} text_len=${#TEXT}"',
|
|
2871
2933
|
"}",
|
|
2872
2934
|
"recover_teams_for() {",
|
|
2873
2935
|
' local conversation_id="$1" reply_to_id="$2" service_url="$3"',
|
|
@@ -2881,29 +2943,53 @@ function provisionStopHook(codeName) {
|
|
|
2881
2943
|
" # teams.replied to a DIFFERENT conversation_id AFTER this inbound tag, TEXT is",
|
|
2882
2944
|
" # not a reliably-correlated ghost of THIS inbound \u2014 stay silent rather than post",
|
|
2883
2945
|
" # mis-correlated text (silence the operator re-pings beats wrong content).",
|
|
2884
|
-
"
|
|
2885
|
-
|
|
2886
|
-
|
|
2887
|
-
" #
|
|
2888
|
-
" #
|
|
2889
|
-
" #
|
|
2890
|
-
" # reply_to_id from the channel tag (which IS the original",
|
|
2891
|
-
" # activity_id the agent saw). Try a prefix match against the",
|
|
2892
|
-
" # marker dir.",
|
|
2946
|
+
" # ENG-7806 (fm1): delivery-ledger read replaces the transcript scan (conv_key",
|
|
2947
|
+
" # = conversation_id). no_ledger falls back to the scan. The teams marker file",
|
|
2948
|
+
" # is hex(conversation_id)[..64]--... so locate it the same way to read its id.",
|
|
2949
|
+
" # CodeRabbit: select the SAME marker recovery will process ONCE (hex(conversation_id)",
|
|
2950
|
+
" # prefix; the activity_id is not available here), so the self-check reads the exact",
|
|
2951
|
+
" # inbound being recovered. Reused by the recovery block below.",
|
|
2893
2952
|
" local hex_conv",
|
|
2894
2953
|
' hex_conv=$(printf %s "$conversation_id" | od -An -tx1 | tr -d " \\n" | cut -c1-64)',
|
|
2895
2954
|
' local marker_path=""',
|
|
2896
2955
|
" shopt -s nullglob",
|
|
2897
|
-
' for f in "$MS_MARKER_DIR"/${hex_conv}*.json; do',
|
|
2898
|
-
' if [ -z "$marker_path" ]; then marker_path="$f"; fi',
|
|
2899
|
-
" done",
|
|
2956
|
+
' for f in "$MS_MARKER_DIR"/${hex_conv}*.json; do if [ -z "$marker_path" ]; then marker_path="$f"; fi; done',
|
|
2900
2957
|
' if [ -z "$marker_path" ]; then log_ghost "teams skip=no_pending_marker conv=$(safe_id "$conversation_id")"; return; fi',
|
|
2958
|
+
' local _ms_iid="" _ms_recv=""',
|
|
2959
|
+
` _ms_iid=$(jq -r '.inbound_id // ""' "$marker_path" 2>/dev/null || echo ""); _ms_recv=$(jq -r '.received_at // ""' "$marker_path" 2>/dev/null || echo "")`,
|
|
2960
|
+
' case "$(delivery_ledger_verdict "$_ms_iid" "$conversation_id" "$_ms_recv")" in',
|
|
2961
|
+
' self) log_ghost "teams skip=already_delivered conv=$(safe_id "$conversation_id")"; return ;;',
|
|
2962
|
+
' moved_on) log_ghost "teams skip=moved_on_after_tag_ledger conv=$(safe_id "$conversation_id")"; return ;;',
|
|
2963
|
+
" no_ledger)",
|
|
2964
|
+
" local replied_other",
|
|
2965
|
+
` replied_other=$(jq -s --arg cid "$conversation_id" 'def ctext: (.message.content // .content // []) | if type=="string" then . elif type=="array" then (map(select(type=="object" and .type=="text")|.text)|join(" ")) else "" end; . as $all | ([ range(0; ($all|length)) | select((($all[.]|ctext)|test("<channel ")) and (($all[.]|(.type // .role // "")) != "assistant")) ] | last) as $idx | [ $all[(($idx // -1)+1):][] | select((.type // .role)=="assistant") | (.message.content // .content // []) | (if type=="array" then . else [] end) | .[] | select((.type=="tool_use") and ((.name|tostring)|test("teams[._]reply$")) and (((.input.conversation_id // "")) as $c | ($c != $cid and $c != ""))) ] | length' "$RECENT_FILE" 2>/dev/null || true)`,
|
|
2966
|
+
' if [ "${replied_other:-0}" -gt 0 ] 2>/dev/null; then return; fi',
|
|
2967
|
+
" ;;",
|
|
2968
|
+
" esac",
|
|
2969
|
+
" # marker_path (hex(conversation_id) prefix match, the marker the agent saw whose",
|
|
2970
|
+
" # activity_id we lack) was selected above and is reused here.",
|
|
2971
|
+
' local marker_name; marker_name="$(basename "$marker_path")"',
|
|
2972
|
+
" # ENG-7805 (fm2): confirm-before-clear. Cap re-fire with a per-marker ledger and",
|
|
2973
|
+
" # LEAVE the marker for the consumer to clear on confirmed send (ledger-first fail-safe).",
|
|
2974
|
+
' if ! mkdir -p "$MS_RECOVERY_LEDGER_DIR" 2>/dev/null; then log_ghost "teams skip=recovery_ledger_unwritable conv=$(safe_id "$conversation_id")"; return; fi',
|
|
2975
|
+
" # ENG-7805 (CodeRabbit): atomic acquire - noclobber create fails if the entry",
|
|
2976
|
+
" # already exists (recovery in flight) OR the write faults; the follow-up [ -f ]",
|
|
2977
|
+
' # disambiguates. Closes the "[ -f ] then : >" TOCTOU between concurrent Stops.',
|
|
2978
|
+
' if ! ( set -o noclobber; : > "${MS_RECOVERY_LEDGER_DIR}/${marker_name}" ) 2>/dev/null; then',
|
|
2979
|
+
' if [ -f "${MS_RECOVERY_LEDGER_DIR}/${marker_name}" ]; then log_ghost "teams skip=recovery_in_flight conv=$(safe_id "$conversation_id")"; else log_ghost "teams skip=recovery_ledger_unwritable conv=$(safe_id "$conversation_id")"; fi',
|
|
2980
|
+
" return",
|
|
2981
|
+
" fi",
|
|
2901
2982
|
" local TS",
|
|
2902
2983
|
" TS=$(date -u +%Y%m%dT%H%M%S%N)",
|
|
2903
|
-
' atomic_write_payload "${AGENT_DIR}/msteams-recovery-outbox" "${TS}.json" \\',
|
|
2904
|
-
` '{conversation_id:$c, reply_to_id:$r, service_url:$s, text:$t, source:"ghost-reply-recovery"}' \\`,
|
|
2905
|
-
' --arg c "$conversation_id" --arg r "$reply_to_id" --arg s "$service_url" --arg t "$TEXT"',
|
|
2906
|
-
|
|
2984
|
+
' if ! atomic_write_payload "${AGENT_DIR}/msteams-recovery-outbox" "${TS}.json" \\',
|
|
2985
|
+
` '{conversation_id:$c, reply_to_id:$r, service_url:$s, text:$t, marker_name:$mn, source:"ghost-reply-recovery"}' \\`,
|
|
2986
|
+
' --arg c "$conversation_id" --arg r "$reply_to_id" --arg s "$service_url" --arg t "$TEXT" --arg mn "$marker_name"; then',
|
|
2987
|
+
" # ENG-7805 (CodeRabbit): write faulted after the ledger was acquired - drop",
|
|
2988
|
+
" # the ledger entry so replay + the next Stop are not suppressed until GC.",
|
|
2989
|
+
' rm -f "${MS_RECOVERY_LEDGER_DIR}/${marker_name}" 2>/dev/null || true',
|
|
2990
|
+
' log_ghost "teams skip=recovery_payload_write_failed conv=$(safe_id "$conversation_id")"',
|
|
2991
|
+
" return",
|
|
2992
|
+
" fi",
|
|
2907
2993
|
' log_ghost "teams RECOVERED conv=$(safe_id "$conversation_id") text_len=${#TEXT}"',
|
|
2908
2994
|
"}",
|
|
2909
2995
|
"# ENG-7814 (ENG-6722 slice E): always-on direct-chat recovery. Re-send the last",
|
|
@@ -2981,6 +3067,79 @@ function provisionStopHook(codeName) {
|
|
|
2981
3067
|
"# entries here as a backstop, same as the block ledger.",
|
|
2982
3068
|
'DC_RECOVERY_LEDGER_DIR="${AGENT_DIR}/.agt-direct-chat-recovery-ledger"',
|
|
2983
3069
|
'if [ -d "$DC_RECOVERY_LEDGER_DIR" ]; then find "$DC_RECOVERY_LEDGER_DIR" -type f -mtime +1 -delete 2>/dev/null || true; fi',
|
|
3070
|
+
"# ENG-7805 (ENG-6722 slice B): per-marker recovery ledgers for slack/telegram/teams.",
|
|
3071
|
+
"# recover_*_for now LEAVES the pending marker in place (confirm-before-clear, fm2)",
|
|
3072
|
+
"# and writes a ledger entry here to cap ONE in-flight recovery per inbound; the",
|
|
3073
|
+
"# channel MCP consumer clears the marker on confirmed send and removes the ledger",
|
|
3074
|
+
"# entry when the recovery resolves (delivered / suppressed / poisoned = re-arm).",
|
|
3075
|
+
"# GC stale entries (>1 day) as a backstop, same as the block + direct-chat ledgers.",
|
|
3076
|
+
'SL_RECOVERY_LEDGER_DIR="${AGENT_DIR}/.agt-slack-recovery-ledger"',
|
|
3077
|
+
'TG_RECOVERY_LEDGER_DIR="${AGENT_DIR}/.agt-telegram-recovery-ledger"',
|
|
3078
|
+
'MS_RECOVERY_LEDGER_DIR="${AGENT_DIR}/.agt-msteams-recovery-ledger"',
|
|
3079
|
+
'for _rl in "$SL_RECOVERY_LEDGER_DIR" "$TG_RECOVERY_LEDGER_DIR" "$MS_RECOVERY_LEDGER_DIR"; do',
|
|
3080
|
+
' if [ -d "$_rl" ]; then find "$_rl" -type f -mtime +1 -delete 2>/dev/null || true; fi',
|
|
3081
|
+
"done",
|
|
3082
|
+
"# ENG-7806 (ENG-6722 slice C): the inbound-delivery ledger - a durable, POSITIVE",
|
|
3083
|
+
'# record ("inbound X was confirmed-delivered at time T") the channel MCPs write on',
|
|
3084
|
+
"# each confirmed reply, keyed by inbound_id. The recover_*_for path reads it instead",
|
|
3085
|
+
"# of scraping the transcript for the replied_other/moved-on decision (fm1). Disjoint",
|
|
3086
|
+
"# from the recovery-ledgers above (those are marker-filename-keyed, negative/in-flight).",
|
|
3087
|
+
"# GC at 1 day like the others (a delivery record only needs to outlive the pending",
|
|
3088
|
+
"# marker + a restart within the recovery window; the MCP never needs it after the",
|
|
3089
|
+
"# marker is gone).",
|
|
3090
|
+
'DELIVERY_LEDGER_DIR="${AGENT_DIR}/.agt-inbound-delivery-ledger"',
|
|
3091
|
+
'if [ -d "$DELIVERY_LEDGER_DIR" ]; then find "$DELIVERY_LEDGER_DIR" -type f -mtime +1 -delete 2>/dev/null || true; fi',
|
|
3092
|
+
"# ENG-7806 telemetry: count each ledger verdict into a counter file the manager",
|
|
3093
|
+
"# already reads+resets (the *-reply-binding-classifications.json suffix), so it",
|
|
3094
|
+
"# reaches CloudWatch as Classification dims with no new pipeline. Best-effort +",
|
|
3095
|
+
"# fully silent (no stdout) - delivery_ledger_verdict runs in $(...), so a stray",
|
|
3096
|
+
"# byte would corrupt the captured verdict.",
|
|
3097
|
+
'LEDGER_METRIC_FILE="${AGENT_DIR}/ghost-ledger-reply-binding-classifications.json"',
|
|
3098
|
+
"bump_ledger_metric() {",
|
|
3099
|
+
' local key="$1" tmp="${LEDGER_METRIC_FILE}.$$.tmp"',
|
|
3100
|
+
' if [ -f "$LEDGER_METRIC_FILE" ]; then',
|
|
3101
|
+
` jq --arg k "$key" '.[$k] = ((.[$k] // 0) + 1)' "$LEDGER_METRIC_FILE" > "$tmp" 2>/dev/null && mv -f "$tmp" "$LEDGER_METRIC_FILE" 2>/dev/null || rm -f "$tmp" 2>/dev/null || true`,
|
|
3102
|
+
" else",
|
|
3103
|
+
` jq -n --arg k "$key" '{($k): 1}' > "$tmp" 2>/dev/null && mv -f "$tmp" "$LEDGER_METRIC_FILE" 2>/dev/null || rm -f "$tmp" 2>/dev/null || true`,
|
|
3104
|
+
" fi",
|
|
3105
|
+
"}",
|
|
3106
|
+
"# Deterministic replacement for the recover_*_for replied_other transcript scan.",
|
|
3107
|
+
"# Echoes exactly one verdict for (inbound_id, conv_key, received_at):",
|
|
3108
|
+
"# self - a delivery record for THIS inbound_id exists (already answered)",
|
|
3109
|
+
"# moved_on - a record for a DIFFERENT conv_key was delivered AFTER this inbound",
|
|
3110
|
+
"# arrived (the agent answered elsewhere; trailing text is ambiguous)",
|
|
3111
|
+
"# clear - the ledger has data but neither of the above (safe to recover)",
|
|
3112
|
+
"# no_ledger - the ledger is empty/absent (pre-C session) -> caller falls back to",
|
|
3113
|
+
"# the transcript scan, so the rollout is safe.",
|
|
3114
|
+
"# ISO-8601 Z timestamps sort lexicographically == chronologically, so a string",
|
|
3115
|
+
"# compare is a correct time compare here (all delivered_at/received_at are UTC Z).",
|
|
3116
|
+
"delivery_ledger_verdict() {",
|
|
3117
|
+
' local iid="$1" convk="$2" recv="$3"',
|
|
3118
|
+
' if [ ! -d "$DELIVERY_LEDGER_DIR" ]; then bump_ledger_metric delivery_ledger_fallback; echo "no_ledger"; return; fi',
|
|
3119
|
+
" shopt -s nullglob",
|
|
3120
|
+
' local _dl_files=("$DELIVERY_LEDGER_DIR"/*.json)',
|
|
3121
|
+
' if [ "${#_dl_files[@]}" = "0" ]; then bump_ledger_metric delivery_ledger_fallback; echo "no_ledger"; return; fi',
|
|
3122
|
+
" # Self-check first (needs only inbound_id): a delivery record for THIS inbound_id",
|
|
3123
|
+
" # means it was already answered, so suppress even if the marker somehow lacks a",
|
|
3124
|
+
" # received_at.",
|
|
3125
|
+
' if [ -n "$iid" ] && [ -f "${DELIVERY_LEDGER_DIR}/$(safe_id "$iid").json" ]; then bump_ledger_metric delivery_ledger_self; echo "self"; return; fi',
|
|
3126
|
+
" # ENG-7806 (CodeRabbit): after the self-check, without THIS marker's own inbound_id",
|
|
3127
|
+
" # AND received_at we cannot make a trustworthy moved-on decision for it (a pre-C",
|
|
3128
|
+
" # marker that predates the ledger, or a torn read). Fall back to the transcript",
|
|
3129
|
+
" # scan rather than defaulting to clear - otherwise, once ANY ledger file exists, an",
|
|
3130
|
+
" # id-less marker would bypass the rollout fallback and recover text the old scan",
|
|
3131
|
+
" # would suppress.",
|
|
3132
|
+
' if [ -z "$iid" ] || [ -z "$recv" ]; then bump_ledger_metric delivery_ledger_fallback; echo "no_ledger"; return; fi',
|
|
3133
|
+
" local _dl_f _dl_ck _dl_da",
|
|
3134
|
+
' for _dl_f in "${_dl_files[@]}"; do',
|
|
3135
|
+
` _dl_ck=$(jq -r '.conv_key // ""' "$_dl_f" 2>/dev/null || echo "")`,
|
|
3136
|
+
` _dl_da=$(jq -r '.delivered_at // ""' "$_dl_f" 2>/dev/null || echo "")`,
|
|
3137
|
+
' if [ -n "$_dl_ck" ] && [ "$_dl_ck" != "$convk" ] && [ -n "$_dl_da" ] && [ -n "$recv" ] && [[ "$_dl_da" > "$recv" ]]; then',
|
|
3138
|
+
' bump_ledger_metric delivery_ledger_moved_on; echo "moved_on"; return',
|
|
3139
|
+
" fi",
|
|
3140
|
+
" done",
|
|
3141
|
+
' bump_ledger_metric delivery_ledger_clear; echo "clear"',
|
|
3142
|
+
"}",
|
|
2984
3143
|
"# Returns 0 (after printing the block JSON to stdout) when it blocked; 1 otherwise.",
|
|
2985
3144
|
'# $1 = "yes"/"no" \u2014 did the agent reply to THIS conversation in the final turn?',
|
|
2986
3145
|
"# (ENG-6727: per-conversation, computed by the caller via replied_this_conv_*)",
|
|
@@ -6797,7 +6956,7 @@ function requireHost() {
|
|
|
6797
6956
|
}
|
|
6798
6957
|
|
|
6799
6958
|
// src/lib/api-client.ts
|
|
6800
|
-
var agtCliVersion = true ? "0.28.
|
|
6959
|
+
var agtCliVersion = true ? "0.28.332" : "dev";
|
|
6801
6960
|
var lastConfigHash = null;
|
|
6802
6961
|
function setConfigHash(hash) {
|
|
6803
6962
|
lastConfigHash = hash && hash.length > 0 ? hash : null;
|
|
@@ -9194,4 +9353,4 @@ export {
|
|
|
9194
9353
|
managerInstallSystemUnitCommand,
|
|
9195
9354
|
managerUninstallSystemUnitCommand
|
|
9196
9355
|
};
|
|
9197
|
-
//# sourceMappingURL=chunk-
|
|
9356
|
+
//# sourceMappingURL=chunk-YNHMQ4CW.js.map
|