Files
herdr-issue/skills/herdr-issue/scripts/start.sh
T
2026-10-07 17:04:51 +00:00

80 lines
3.7 KiB
Bash
Executable File
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#!/usr/bin/env bash
# 用法:start.sh <owner/repo> <N>
# 在目前 clone 旁建 worktree、開 Herdr tab、啟動 claude、送提示詞並確認 agent 有反應、掛 in-progress 標籤。
# 送出提示詞後 15 秒內沒觀察到 working 或 blocked 就視為失敗並回滾(關 tab、移除 worktree、刪本次新建的分支)。
# 最後一行印出 JSON:{"tab":..,"pane":..,"path":..,"resumed":..,"state":"working"|"blocked"}
source "$(dirname "$0")/lib.sh"
REPO="${1:?}"; N="${2:?用法:start.sh <owner/repo> <N>}"
LINK="https://gitea.jsc.idv.tw/$REPO/issues/$N"
test "${HERDR_ENV:-}" = 1 || die "不在 Herdr 裡(HERDR_ENV≠1)"
CLONE="$(clone_root_for "$REPO")"
BRANCH="issue-$N"
WT="$(worktree_path "$N" "$CLONE")"
if [ "$(agent_status "$N")" != missing ]; then
die "issue-$N 的 agent 還活著(tab $(tab_for_issue "$N")),不重複啟動"
fi
[ "$(issue_state "$REPO" "$N")" = open ] || die "#$N 不是 open"
BLOCKERS="$(open_blockers "$REPO" "$N")" || exit 1
[ -z "$BLOCKERS" ] || die "#$N 被還沒關閉的議題擋住:$(echo "$BLOCKERS" | tr '\n' ' ')(Gitea 依賴設定)。等它們關閉,或到 Gitea 拿掉依賴再啟動"
git -C "$CLONE" fetch --quiet origin
RESUMED=false
if git -C "$CLONE" show-ref --verify --quiet "refs/heads/$BRANCH"; then
RESUMED=true
if ! git -C "$CLONE" worktree list --porcelain | grep -qx "worktree $WT"; then
git -C "$CLONE" worktree add --quiet "$WT" "$BRANCH"
fi
else
git -C "$CLONE" worktree add --quiet -b "$BRANCH" "$WT" origin/main
fi
TAB=""
# 回滾到跟沒跑過一樣:關 tab、移除 worktree;分支只在本次新建時刪除。
rollback() {
[ -n "$TAB" ] && herdr tab close "$TAB" >/dev/null 2>&1 || true
if git -C "$CLONE" worktree list --porcelain | grep -qx "worktree $WT"; then
git -C "$CLONE" worktree remove --force "$WT" >/dev/null 2>&1 || true
fi
$RESUMED || git -C "$CLONE" branch -D "$BRANCH" >/dev/null 2>&1 || true
}
TAB_JSON="$(herdr tab create --workspace "${HERDR_WORKSPACE_ID:?}" --cwd "$WT" --label "#$N" --no-focus)"
TAB="$(jq_py 'print(find(d,"tab")["tab_id"])' <<<"$TAB_JSON")"
PANE="$(jq_py 'print(find(d,"root_pane")["pane_id"])' <<<"$TAB_JSON")"
START_ERR="$(mktemp)"
for _ in 1 2 3 4 5 6; do
if herdr agent start "issue-$N" --kind claude --pane "$PANE" --timeout 90000 -- --model "$MODEL" >/dev/null 2>"$START_ERR"; then
rm -f "$START_ERR"; break
fi
sleep 2
done
if [ -f "$START_ERR" ]; then
cat "$START_ERR" >&2; rm -f "$START_ERR"
rollback
die "agent 啟動失敗,已回滾"
fi
if $RESUMED; then RESUME_LINE="分支已有先前進度,先看 git log 和議題核取方塊再接續。"; else RESUME_LINE=""; fi
PROMPT="$(sed -e "s|{LINK}|$LINK|g" -e "s|{REPO}|$REPO|g" -e "s|{N}|$N|g" -e "s|{S}|$SCRIPTS|g" -e "s|{RESUME}|$RESUME_LINE|" "$SCRIPTS/prompt.txt")"
# 送出後必須觀察到 agent 進入 working 或 blocked;否則 Herdr 回非 0(agent_prompt_stalled、timeout、agent_blocked 等)。
PROMPT_ERR="$(mktemp)"
if PROMPT_OUT="$(herdr agent prompt "issue-$N" "$PROMPT" --wait --until working --until blocked --timeout 15000 2>"$PROMPT_ERR")"; then
rm -f "$PROMPT_ERR"
else
echo "herdr-issue: 送出提示詞後 agent 沒有反應,已回滾" >&2
cat "$PROMPT_ERR" >&2; rm -f "$PROMPT_ERR"
rollback
exit 1
fi
STATE="$(jq_py 'print(find(d,"agent_status") or "")' <<<"$PROMPT_OUT" 2>/dev/null || true)"
case "$STATE" in working|blocked) ;; *) STATE="$(agent_status "$N")" ;; esac
ensure_label "$REPO"
tea issues edit "$N" --repo "$REPO" --remove-labels "$LABEL" >/dev/null 2>&1 || true
tea issues edit "$N" --repo "$REPO" --add-labels "$LABEL" >/dev/null
printf '{"tab":"%s","pane":"%s","path":"%s","resumed":%s,"state":"%s"}\n' "$TAB" "$PANE" "$WT" "$RESUMED" "$STATE"