@rulemetric/hooks 0.5.0 → 0.5.2
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/package.json +1 -1
- package/scripts/_post.sh +62 -0
- package/scripts/session-end.sh +18 -12
package/package.json
CHANGED
package/scripts/_post.sh
CHANGED
|
@@ -73,3 +73,65 @@ _rulemetric_post_event() {
|
|
|
73
73
|
[ -n "$hdr_file" ] && rm -f "$hdr_file"
|
|
74
74
|
return 1
|
|
75
75
|
}
|
|
76
|
+
|
|
77
|
+
# _rulemetric_send <method> <url> <auth_header> <payload> <log_tag> [max_time_s]
|
|
78
|
+
# Method-aware sibling of _rulemetric_post_event for the session-END writes that
|
|
79
|
+
# previously used a bare `curl -sf` and SILENTLY DROPPED on any failure — enrich
|
|
80
|
+
# (PATCH), reimport (POST), derive-enrichment (POST). When the API fast-503s under
|
|
81
|
+
# transient DB-pool load, those calls dropped, leaving sessions un-enriched / empty
|
|
82
|
+
# (the "insights stuck at 06/30" cause). Same bounded 503/429/network retry +
|
|
83
|
+
# capped Retry-After as _rulemetric_post_event; 4xx permanent; logs final failure.
|
|
84
|
+
# Returns 0 on 2xx. `max_time_s` defaults to 4 (reimport passes 8 for large bodies).
|
|
85
|
+
# `max_attempts` defaults to $_RM_POST_MAX_ATTEMPTS; the FOREGROUND reimport passes
|
|
86
|
+
# 2 to cap its worst-case session-end tail-latency (it blocks the hook — see below).
|
|
87
|
+
_rulemetric_send() {
|
|
88
|
+
local method="$1" url="$2" auth="$3" payload="$4" tag="$5" max_time="${6:-4}" max_attempts="${7:-$_RM_POST_MAX_ATTEMPTS}"
|
|
89
|
+
local attempt=1 http_code="000" body="" hdr_file retry_after sleep_s
|
|
90
|
+
|
|
91
|
+
hdr_file=$(mktemp "${TMPDIR:-/tmp}/rm-send.XXXXXX" 2>/dev/null || true)
|
|
92
|
+
|
|
93
|
+
while [ "$attempt" -le "$max_attempts" ]; do
|
|
94
|
+
if [ -n "$hdr_file" ]; then
|
|
95
|
+
body=$(curl -s --noproxy '*' --max-time "$max_time" -D "$hdr_file" -w '\n%{http_code}' \
|
|
96
|
+
-X "$method" "$url" -H "$auth" -H "Content-Type: application/json" \
|
|
97
|
+
-d "$payload" 2>&1) || true
|
|
98
|
+
else
|
|
99
|
+
body=$(curl -s --noproxy '*' --max-time "$max_time" -w '\n%{http_code}' \
|
|
100
|
+
-X "$method" "$url" -H "$auth" -H "Content-Type: application/json" \
|
|
101
|
+
-d "$payload" 2>&1) || true
|
|
102
|
+
fi
|
|
103
|
+
http_code=$(printf '%s' "$body" | tail -1)
|
|
104
|
+
body=$(printf '%s' "$body" | sed '$d')
|
|
105
|
+
|
|
106
|
+
if [ "$http_code" = "200" ] || [ "$http_code" = "201" ]; then
|
|
107
|
+
[ -n "$hdr_file" ] && rm -f "$hdr_file"
|
|
108
|
+
return 0
|
|
109
|
+
fi
|
|
110
|
+
|
|
111
|
+
if [ "$http_code" = "503" ] || [ "$http_code" = "429" ] || [ "$http_code" = "000" ]; then
|
|
112
|
+
if [ "$attempt" -lt "$max_attempts" ]; then
|
|
113
|
+
retry_after=""
|
|
114
|
+
if [ -n "$hdr_file" ]; then
|
|
115
|
+
retry_after=$(grep -i '^Retry-After:' "$hdr_file" 2>/dev/null | tail -1 | tr -dc '0-9' || true)
|
|
116
|
+
fi
|
|
117
|
+
if [ -n "$retry_after" ] && [ "$retry_after" -gt 0 ] 2>/dev/null; then
|
|
118
|
+
sleep_s="$retry_after"
|
|
119
|
+
else
|
|
120
|
+
sleep_s="$attempt"
|
|
121
|
+
fi
|
|
122
|
+
if [ "$sleep_s" -gt "$_RM_POST_RETRY_CAP_S" ] 2>/dev/null; then
|
|
123
|
+
sleep_s="$_RM_POST_RETRY_CAP_S"
|
|
124
|
+
fi
|
|
125
|
+
sleep "$sleep_s" 2>/dev/null || true
|
|
126
|
+
attempt=$((attempt + 1))
|
|
127
|
+
continue
|
|
128
|
+
fi
|
|
129
|
+
fi
|
|
130
|
+
|
|
131
|
+
break
|
|
132
|
+
done
|
|
133
|
+
|
|
134
|
+
_rulemetric_log "$tag" "error" "http_${http_code}_attempt_${attempt}: ${body}"
|
|
135
|
+
[ -n "$hdr_file" ] && rm -f "$hdr_file"
|
|
136
|
+
return 1
|
|
137
|
+
}
|
package/scripts/session-end.sh
CHANGED
|
@@ -2,6 +2,11 @@
|
|
|
2
2
|
# RuleMetric: Finalize session with full transcript import
|
|
3
3
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
4
4
|
source "$SCRIPT_DIR/_log.sh" 2>/dev/null || _rulemetric_log() { :; }
|
|
5
|
+
# Bounded retry-on-503 for the session-end writes (reimport/enrich/derive) so a
|
|
6
|
+
# transient DB-pool wedge doesn't SILENTLY drop them (the "insights stuck" cause).
|
|
7
|
+
# Log if the helper can't load (packaging regression) — otherwise the writes below
|
|
8
|
+
# would hit `command not found` and degrade silently (backgrounded ones with NO log).
|
|
9
|
+
source "$SCRIPT_DIR/_post.sh" 2>/dev/null || _rulemetric_log "session-end" "warn" "post_helper_unavailable"
|
|
5
10
|
|
|
6
11
|
set -euo pipefail
|
|
7
12
|
trap 'echo "rulemetric session-end failed at line $LINENO: $BASH_COMMAND" >&2; _rulemetric_log "session-end" "error" "line $LINENO: $BASH_COMMAND"; exit 1' ERR
|
|
@@ -41,10 +46,13 @@ fi
|
|
|
41
46
|
# Try to reimport with full transcript, fall back to close
|
|
42
47
|
if [ -n "$HOOK_TRANSCRIPT_PATH" ] && [ -f "$HOOK_TRANSCRIPT_PATH" ]; then
|
|
43
48
|
CONTENT=$(cat "$HOOK_TRANSCRIPT_PATH")
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
49
|
+
REIMPORT_PAYLOAD="{\"content\":$(echo "$CONTENT" | jq -Rs .),\"tool\":\"$HOOK_TOOL\"}"
|
|
50
|
+
# Retry-on-503 (max-time 8 for the large transcript body); this is FOREGROUND and
|
|
51
|
+
# blocks the hook, so cap at 2 attempts (worst-case tail ~18s on a hard API hang,
|
|
52
|
+
# vs ~32s at 3) — the common fast-503 wedge still recovers in <1s. Fall back to
|
|
53
|
+
# close if it still fails after retries — a dropped reimport leaves the session EMPTY.
|
|
54
|
+
_rulemetric_send POST "${RULEMETRIC_API_URL}/api/sessions/${RW_SESSION_ID}/reimport" \
|
|
55
|
+
"$AUTH_HEADER" "$REIMPORT_PAYLOAD" "session-end-reimport" 8 2 \
|
|
48
56
|
> /dev/null 2>&1 || {
|
|
49
57
|
_rulemetric_log "session-end" "fallback" "reimport_failed"
|
|
50
58
|
curl -sf --noproxy '*' --max-time 4 -X POST "${RULEMETRIC_API_URL}/api/sessions/${RW_SESSION_ID}/close" \
|
|
@@ -127,18 +135,16 @@ except:
|
|
|
127
135
|
" 2>/dev/null)
|
|
128
136
|
|
|
129
137
|
if [ -n "$ENRICH_PAYLOAD" ]; then
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
138
|
+
# Backgrounded retry-on-503 so a transient wedge doesn't drop enrichment
|
|
139
|
+
# (leaving insights stuck at the last-enriched session).
|
|
140
|
+
(_rulemetric_send PATCH "${RULEMETRIC_API_URL}/api/sessions/${RW_SESSION_ID}/enrich" \
|
|
141
|
+
"$AUTH_HEADER" "$ENRICH_PAYLOAD" "session-end-enrich" > /dev/null 2>&1) &
|
|
134
142
|
fi
|
|
135
143
|
fi
|
|
136
144
|
else
|
|
137
145
|
# Non-Claude tools: derive enrichment from stored session events
|
|
138
|
-
(
|
|
139
|
-
|
|
140
|
-
-H "Content-Type: application/json" \
|
|
141
|
-
-d '{}' > /dev/null 2>&1) &
|
|
146
|
+
(_rulemetric_send POST "${RULEMETRIC_API_URL}/api/sessions/${RW_SESSION_ID}/derive-enrichment" \
|
|
147
|
+
"$AUTH_HEADER" '{}' "session-end-derive" 8 > /dev/null 2>&1) &
|
|
142
148
|
fi
|
|
143
149
|
|
|
144
150
|
# ── Tail transcript for 429 rate-limit events ──
|