From e3eb782be56bb80fa7f000b6e8e97c36ffd0048b Mon Sep 17 00:00:00 2001 From: Levi Neely Date: Sat, 18 Apr 2026 13:52:22 +0200 Subject: [PATCH] =?UTF-8?q?scripts:=20b/job=20parallel=20improvements=20?= =?UTF-8?q?=E2=80=94=20streaming=20results,=20input/output=20headers,=20-f?= =?UTF-8?q?ailfast?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- scripts/b/job | 90 ++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 68 insertions(+), 22 deletions(-) diff --git a/scripts/b/job b/scripts/b/job index b3eb2b8..21d4fde 100755 --- a/scripts/b/job +++ b/scripts/b/job @@ -11,9 +11,10 @@ # -backend backend override # -model model override # -json shorthand for -output json; emit JSONL output -# -parallel run the same prompt N times in parallel (default: 1) -# -keep do not remove job(s) after printing result -# -bg submit job and exit immediately; prints session id(s); implies -keep +# -parallel run the same prompt N times in parallel (default: 1) +# -keep do not remove job(s) after printing result +# -bg submit job and exit immediately; prints session id(s); implies -keep +# -failfast on first failure, cancel remaining running jobs and exit set -euo pipefail @@ -38,26 +39,28 @@ Flags: -parallel N run the same prompt N times in parallel (default: 1) -keep do not remove job(s) after printing result -bg submit and exit immediately; prints job id(s); implies -keep + -failfast on first failure, cancel remaining running jobs and exit -help show this help EOF exit 0 } -name=; cwd=; agent=; backend=; model=; output=; parallel=1; keep=0; bg=0 +name=; cwd=; agent=; backend=; model=; output=; parallel=1; keep=0; bg=0; failfast=0 while [ $# -gt 0 ]; do case $1 in - -name) name=$2; shift ;; - -cwd) cwd=$2; shift ;; - -agent) agent=$2; shift ;; - -backend) backend=$2; shift ;; - -model) model=$2; shift ;; - -json) output=json ;; - -parallel) parallel=$2; shift ;; - -keep) keep=1 ;; - -bg) bg=1; keep=1 ;; - -help) usage ;; - --) shift; break ;; + -name) name=$2; shift ;; + -cwd) cwd=$2; shift ;; + -agent) agent=$2; shift ;; + -backend) backend=$2; shift ;; + -model) model=$2; shift ;; + -json) output=json ;; + -parallel) parallel=$2; shift ;; + -keep) keep=1 ;; + -bg) bg=1; keep=1 ;; + -failfast) failfast=1 ;; + -help) usage ;; + --) shift; break ;; -*) die "unknown flag: $1" ;; *) break ;; esac @@ -99,16 +102,60 @@ if [ "$bg" -eq 1 ]; then fi rc=0 -for i in $(seq 0 $((parallel - 1))); do - id="${name}-${i}" + +if [ "$parallel" -gt 1 ]; then + abort=$(mktemp) + trap 'rm -f "$abort"' EXIT + pids=() + for i in $(seq 0 $((parallel - 1))); do + id="${name}-${i}" + B="$MOUNT/b/$id" + ( + while true; do + [ -s "$abort" ] && exit 1 + status=$(tr -d '[:space:]' < "$B/status" 2>/dev/null) || { sleep 0.05; continue; } + case "$status" in + done*) break ;; + failed*) printf 'subagent %s failed: %s\n' "$id" "$status" >&2 + if [ "$failfast" -eq 1 ]; then + echo 1 > "$abort" + for j in $(seq 0 $((parallel - 1))); do + jid="${name}-${j}" + [ "$jid" != "$id" ] && rm -r "$MOUNT/b/$jid" 2>/dev/null || true + done + fi + [ "$keep" -eq 0 ] && rm -r "$B" 2>/dev/null || true + exit 1 ;; + *) sleep 0.05 ;; + esac + done + if [ -s "$abort" ]; then + [ "$keep" -eq 0 ] && rm -r "$B" 2>/dev/null || true + exit 1 + fi + if [ -n "$output" ]; then + printf '{"session":"%s","result":%s}\n' "$id" \ + "$(cat "$B/result" 2>/dev/null | jq -Rs .)" + else + printf '=== %s ===\nInput: "%s"\nOutput: ' "$id" "$prompt" + cat "$B/result" 2>/dev/null + printf '\n' + fi + [ "$keep" -eq 0 ] && rm -r "$B" 2>/dev/null || true + ) & + pids+=($!) + done + for pid in "${pids[@]}"; do wait "$pid" || rc=1; done +else + id="${name}-0" B="$MOUNT/b/$id" while true; do status=$(tr -d '[:space:]' < "$B/status" 2>/dev/null) || { sleep 0.05; continue; } case "$status" in - done*) break ;; - failed*) rc=1; break ;; - *) sleep 0.05 ;; + done*) break ;; + failed*) rc=1; break ;; + *) sleep 0.05 ;; esac done @@ -116,12 +163,11 @@ for i in $(seq 0 $((parallel - 1))); do printf '{"session":"%s","result":%s}\n' "$id" \ "$(cat "$B/result" 2>/dev/null | jq -Rs .)" else - [ "$parallel" -gt 1 ] && printf '=== %s ===\n' "$id" cat "$B/result" 2>/dev/null printf '\n' fi [ "$keep" -eq 0 ] && rm -r "$B" 2>/dev/null || true -done +fi exit $rc