all repos — dot @ master

Shell, editor and terminal configuration, and the tools that go with them

skills/pi-subagent/status.sh (view raw)

 1
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
#!/bin/bash
# Report on the subagents of one workdir: what is still running, and the
# cost table of everything that finished, failed attempts included.
#
#   status.sh <workdir>                 report once
#   status.sh --wait [secs] <workdir>   report every <secs> (default 60) until
#                                       nothing is running, then the table
#
# Exit status: 0 when nothing is running, 3 while something still is.
#
# "Running" means <workdir>/out/<name>.running exists and its PID is alive. A
# marker whose process is gone (run-agent.sh was killed) is reported as stale
# and removed.

set -u

wait=""; interval=60
if [[ "${1:-}" == "--wait" ]]
then
  wait=y; shift
  if [[ "${1:-}" =~ ^[0-9]+$ ]]; then interval="$1"; shift; fi
fi
P="${1:?workdir}"
out="$P/out"

running() {
  local marker pid alive=()
  for marker in "$out"/*.running
  do
    [[ -e "$marker" ]] || continue
    pid="$(cat "$marker" 2>/dev/null)"
    if [[ -n "$pid" ]] && kill -0 "$pid" 2>/dev/null
    then
      alive+=("$(basename "$marker" .running)")
    else
      echo "stale: $(basename "$marker" .running) (process gone)" >&2
      rm -f "$marker"
    fi
  done
  echo "${alive[*]:-}"
}

free_gb() {
  df -k "$P" | awk 'NR==2 {printf "%.1f", $4/1048576}'
}

if [[ -n "$wait" ]]
then
  while :
  do
    names="$(running)"
    [[ -z "$names" ]] && break
    echo "$(date +%H:%M:%S) running=$(wc -w <<< "$names" | tr -d ' ') freeGB=$(free_gb): $names"
    sleep "$interval"
  done
fi

names="$(running)"
if [[ -n "$names" ]]
then
  echo "running: $names"
fi

shopt -s nullglob
costs=("$out"/*.cost.json)
if [[ ${#costs[@]} -gt 0 ]]
then
  {
    echo -e "name\tprovider\tmodel\texit\tstop\tsecs\tturns\tin\tout\tanswer_bytes\tcost"
    for f in "${costs[@]}"
    do
      n="$(basename "$f" .cost.json)"
      bytes=0
      [[ -e "$out/$n.md" ]] && bytes="$(wc -c < "$out/$n.md" | tr -d '[:space:]')"
      jq -r --arg b "$bytes" '[.name,.provider,.model,(.exit|tostring),(.stopReason // "-"),(.seconds|tostring),
             (.turns|tostring),(.input|tostring),(.output|tostring),$b,
             (.cost*10000|round/10000|tostring)] | @tsv' "$f" 2>/dev/null \
        || echo -e "$n\t?\t?\t?\t?\t?\t?\t?\t?\t$bytes\t(unreadable cost file)"
    done | sort -t$'\t' -k11 -rn
  } | column -t -s$'\t'
  jq -s -r '"runs: \(length)  failed: \(map(select(.exit != 0)) | length)  total cost: $\(map(.cost) | add | .*10000 | round/10000)"' \
    "${costs[@]}" 2>/dev/null
fi

[[ -z "$names" ]] || exit 3