Files
notescraft/scripts/pi-wave.sh
T
Marcos Paulo bf4f55aed1 scripts: codex runner (AGENT_CLI=codex)
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-14 00:14:49 -03:00

60 lines
2.9 KiB
Bash
Executable File

#!/usr/bin/env bash
# Run one pi agent per task file in a wave directory, each in its own git worktree.
# usage: scripts/pi-wave.sh scripts/waves/wave1 [parallel=4]
set -euo pipefail
root=$(git rev-parse --show-toplevel)
dir=$(cd "$1" && pwd)
par=${2:-4}
mkdir -p "$root/.worktrees"
run() {
task=$(basename "$1" .md)
wt="$root/.worktrees/$task"
[ -d "$wt" ] || git -C "$root" worktree add -q "$wt" -b "feat/$task"
if [ "${AGENT_CLI:-pi}" = codex ]; then
# Codex CLI: model and effort from CODEX_MODEL / CODEX_EFFORT (defaults: gpt-6.1-sol, high).
# The sandbox may write the worktree, this task's target dir and the cargo/rustup homes.
mkdir -p "$root/target/agent-$task"
(
cd "$wt"
PATH="$HOME/.cargo/bin:$PATH" CARGO_NET_GIT_FETCH_WITH_CLI=true CARGO_TARGET_DIR="$root/target/agent-$task" \
timeout 3000 codex exec --skip-git-repo-check --ignore-user-config --ignore-rules --ephemeral --json \
-m "${CODEX_MODEL:-gpt-6.1-sol}" -c "model_reasoning_effort=\"${CODEX_EFFORT:-high}\"" \
--sandbox workspace-write -c sandbox_workspace_write.network_access=true \
--add-dir "$root/target/agent-$task" --add-dir "$HOME/.cargo" --add-dir "$HOME/.rustup" \
-o "$root/.worktrees/$task.log" -C "$wt" "$(cat "$root/scripts/waves/_common.md" "$1")" >"$root/.worktrees/$task.jsonl" 2>&1
)
rc=$?
else
(
cd "$wt"
# message_update events repeat the whole partial message (quadratic log size): drop them
PATH="$HOME/.cargo/bin:$PATH" CARGO_NET_GIT_FETCH_WITH_CLI=true CARGO_TARGET_DIR="${PI_SHARED_TARGET:-$root/target/agent-$task}" \
timeout 3000 pi -p --mode json --no-session --no-extensions --no-skills --no-themes -np --thinking low ${PI_EXTRA:-} \
"$(cat "$root/scripts/waves/_common.md" "$1")" 2>&1 | grep --line-buffered -v '"type":"message_update"' >"$root/.worktrees/$task.jsonl"
)
rc=$?
# final assistant text -> <task>.log
python3 - "$root/.worktrees/$task.jsonl" >"$root/.worktrees/$task.log" <<'PY'
import json,sys
last=""
for l in open(sys.argv[1],errors="replace"):
try: e=json.loads(l)
except ValueError: continue
if e.get("type")=="message_end" and e["message"].get("role")=="assistant":
t="".join(c.get("text","") for c in e["message"]["content"] if c.get("type")=="text")
if t.strip(): last=t
print(last)
PY
fi
# an empty final message means the agent never answered
[ -s "$root/.worktrees/$task.log" ] && [ "$(wc -c <"$root/.worktrees/$task.log")" -gt 2 ] || rc="$rc-EMPTY-LOG"
echo "$task exit $rc" >>"$root/.worktrees/summary.log"
}
export -f run
export root
export AGENT_CLI CODEX_MODEL CODEX_EFFORT PI_EXTRA PI_SHARED_TARGET
# an optional order.txt (one task file name per line) sets the queue order; else alphabetical
if [ -f "$dir/order.txt" ]; then sed "s|^|$dir/|" "$dir/order.txt"; else ls "$dir"/*.md; fi | xargs -P "$par" -I{} bash -c 'run {}'