#!/bin/bash # stop-auto-resume.sh から切り離して起動される。自分の pane に /clear と再開の指示を herdr で送る。 # 使い方: auto-resume-worker.sh <引き継ぎメモのパス> # # /clear が効いたかは、元の場所からメモがなくなったかで判定する(handoff-inject.sh が used/ へ移す)。 # 自動再開を見送ったときは AUTO_RESUME_NOTIFY_CMD を「メッセージ 1 つを引数に取るコマンド」として呼ぶ。 # 未設定ならログ(~/.claude/handoff/auto-resume.log)に残すだけ。 # 前提: herdr、jq、perl。 pane="$1" handoff="$2" POLL_SEC=${AUTO_RESUME_POLL_SEC:-2} INPUT_WAIT_SEC=${AUTO_RESUME_INPUT_WAIT_SEC:-600} CLEAR_WAIT_SEC=${AUTO_RESUME_CLEAR_WAIT_SEC:-30} RESUME_PROMPT="引き継ぎメモから再開して、メモの「次の一手」から続けて" LOG="$HOME/.claude/handoff/auto-resume.log" log() { printf '%s %s %s\n' "$(date '+%F %T')" "$pane" "$1" >>"$LOG" } send() { log "send: $1" herdr agent prompt "$pane" "$1" >/dev/null 2>&1 || log "send failed: $1" } notify() { [ -n "${AUTO_RESUME_NOTIFY_CMD:-}" ] && "$AUTO_RESUME_NOTIFY_CMD" "$1" } give_up() { log "give up: $1" notify "自動再開を見送った: $1。手動で /clear と打てば再開する" exit 0 } # 入力欄(罫線 2 本に挟まれた行)が「❯」だけなら空とみなす。入力欄が見えない時も空ではない扱い # 空の入力欄には薄字(SGR 2)の例文が出るので、ANSI で読んで薄字の部分を消してから判定する input_is_empty() { herdr agent read "$pane" --source visible --lines 40 --format ansi 2>/dev/null \ | perl -pe 's/\e\[2m.*?(?:\e\[(?:0|22)?m|$)//g; s/\e\[[0-9;?]*[A-Za-z]//g; s/\r//g' \ | awk ' /^─/ { prev = last; last = NR; box = body; body = ""; next } { body = body $0 "\n" } END { if (prev == 0) exit 1 gsub(/[ \t\n]/, "", box) exit (box == "❯" || box == ">") ? 0 : 1 }' } agent_status() { herdr agent get "$pane" 2>/dev/null | jq -r '.result.agent.agent_status // empty' } # 送ってよい状態か。承認・質問の画面(blocked)なら諦める ready_to_send() { case "$(agent_status)" in idle|done) input_is_empty ;; blocked) give_up "承認・質問の画面で止まっている" ;; *) return 1 ;; esac } # ターンが終わって待機状態になるまで待つ(Stop hook の時点ではまだ working) herdr agent wait "$pane" --timeout 600000 >/dev/null 2>&1 start=$SECONDS until ready_to_send; do [ $((SECONDS - start)) -ge "$INPUT_WAIT_SEC" ] && give_up "入力欄が $((INPUT_WAIT_SEC / 60)) 分空かなかった" sleep "$POLL_SEC" done # 待っている間にユーザーが手動で /clear した、またはモデルが止める印を置いた [ -f "$handoff" ] || { log "skip: メモが既に無い(手動 /clear 済み)"; exit 0; } [ -f "${handoff%.md}.noauto" ] && { log "skip: .noauto の印がある"; exit 0; } send "/clear" start=$SECONDS while [ -f "$handoff" ]; do [ $((SECONDS - start)) -ge "$CLEAR_WAIT_SEC" ] && give_up "/clear を送ったが引き継ぎメモが読み込まれなかった" sleep "$POLL_SEC" done herdr agent wait "$pane" --timeout 60000 >/dev/null 2>&1 sleep "$POLL_SEC" send "$RESUME_PROMPT" # /clear 直後は新しい文脈の準備中で Enter が取りこぼされ、文字が入力欄に残ることがある(実測) for _ in 1 2 3 4 5; do sleep "$POLL_SEC" if input_is_empty; then log "resumed" exit 0 fi log "resend: enter" herdr agent send-keys "$pane" enter >/dev/null 2>&1 done input_is_empty && { log "resumed"; exit 0; } give_up "再開の指示が入力欄に残ったまま送信されなかった"