Files
roboco/docker/scripts/usage-report-hook.sh
Renn F 1b992df3ad fix(hooks): repair 3 production hooks broken by a heredoc/stdin bug
`<pipe JSON> | python3 - <<'PY'` makes both `python3 -` and the heredoc claim
stdin; the heredoc wins, so the piped JSON is silently discarded — each hook
read empty input and never triggered. Fixed to `python3 -c "$(cat <<'PY')"`
(cat consumes the heredoc, python3's stdin stays free for the pipe), matching
the already-correct fable-stop-gate-hook.sh.

Impact, all verified before/after:
- user-prompt-hook.sh: the prompt-injection guard ALLOWED injection strings
  (exit 0); now correctly DENIES (exit 2). Security hole closed.
- post-tool-budget-hook.sh: every tool call hashed to {tool:unknown} — loop
  detection was blind; now hashes the real tool + args.
- usage-report-hook.sh: transcript path resolved empty so its curl sync never
  fired; now fires correctly.

2-line change per file; no logic/threshold/message/contract change. bash-guard
78/78 + fable-hooks 15/15 green; repo-wide grep confirms no remaining instances.
2026-07-04 06:51:18 +02:00

36 lines
1.1 KiB
Bash
Executable File

#!/usr/bin/env bash
# PostToolUse + Stop: sync token usage from the Claude Code transcript.
#
# Claude Code does not pass token counts to hooks, but it does pass the
# path to the session transcript (.jsonl), which records per-message
# `usage`. We hand that path to the SDK server, which parses the transcript
# and SETS the cumulative totals (absolute, idempotent — safe to call after
# every tool and again at Stop). The orchestrator later reads these via
# /usage/status to finalize the spawn-session row and the usage dashboard.
#
# Fire-and-forget — never block Claude on this. Always exit 0.
set -u
SDK_URL="${ROBOCO_SDK_URL:-http://localhost:9000}"
input=$(cat 2>/dev/null || true)
[[ -z "$input" ]] && exit 0
TRANSCRIPT=$(printf '%s' "$input" | python3 -c "$(cat <<'PY'
import json, sys
try:
d = json.loads(sys.stdin.read())
print(d.get("transcript_path", ""))
except Exception:
print("")
PY
)")
[[ -z "$TRANSCRIPT" ]] && exit 0
curl -sf -m 3 -X POST "$SDK_URL/usage/sync" \
-H "Content-Type: application/json" \
-d "{\"transcript_path\":\"$TRANSCRIPT\"}" >/dev/null 2>&1 || true
exit 0