Author SHA1 Message Date
rootandClaude Sonnet 5.5 21ddd48548 fix: 提示詞不再使用 /mattpocock-skills:implement
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:59:21 +08:00
rootandClaude Sonnet 5.5 8c0213bc7f feat: agent 預設模型改為 claude-sonnet-5-5
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 13:51:32 +08:00
rootandClaude Sonnet 5.5 a31687a50f chore: bump plugin manifests to 0.0.7
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 01:37:33 +00:00
rootandClaude Sonnet 5.5 2ac96deb4b fix: git 走 HTTPS 時改用 tea 預設 login 的 token 認證
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 01:37:33 +00:00
rootandClaude Sonnet 5.5 066f9f959f fix: tea 遇到 TLS 憑證錯誤時自動重試,避免輪詢腳本中斷
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-08 01:37:33 +00:00
8 changed files with 58 additions and 8 deletions
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "herdr-issue", "name": "herdr-issue",
"version": "0.0.6", "version": "0.0.7",
"description": "透過 Herdr 讓 Claude agent 逐一實作 Gitea 議題(每個議題一個 worktree 與 tab)。", "description": "透過 Herdr 讓 Claude agent 逐一實作 Gitea 議題(每個議題一個 worktree 與 tab)。",
"skills": "./skills", "skills": "./skills",
"author": { "author": {
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "herdr-issue", "name": "herdr-issue",
"version": "0.0.6", "version": "0.0.7",
"description": "透過 Herdr 讓 Claude agent 逐一實作 Gitea 議題(每個議題一個 worktree 與 tab)。", "description": "透過 Herdr 讓 Claude agent 逐一實作 Gitea 議題(每個議題一個 worktree 與 tab)。",
"skills": "./skills" "skills": "./skills"
} }
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "herdr-issue", "name": "herdr-issue",
"version": "0.0.6", "version": "0.0.7",
"description": "透過 Herdr 讓 Claude agent 逐一實作 Gitea 議題(每個議題一個 worktree 與 tab)。", "description": "透過 Herdr 讓 Claude agent 逐一實作 Gitea 議題(每個議題一個 worktree 與 tab)。",
"skills": "./skills/" "skills": "./skills/"
} }
+4 -2
View File
@@ -9,7 +9,7 @@ description: "Run Gitea issues through Herdr: one Claude agent per issue in its
## 使用者身分 ## 使用者身分
Gitea 一律以 tea 的預設 login(`tea login list` 中 default 為 true 的那個)操作:`lib.sh` 會取出它並讓所有 tea 呼叫加上 `--login`,避免在 clone 裡 tea 依 remote URL 挑到別的帳號。`start.sh` 也會把該使用者的名稱與 email 設成 worktree 的 git commit 身分。要換人先 `tea login default <name>`,或設 `HERDR_ISSUE_LOGIN`。 Gitea 一律以 tea 的預設 login(`tea login list` 中 default 為 true 的那個)操作:`lib.sh` 會取出它並讓所有 tea 呼叫加上 `--login`,避免在 clone 裡 tea 依 remote URL 挑到別的帳號。`start.sh` 也會把該使用者的名稱與 email 設成 worktree 的 git commit 身分。git 走 HTTPS 的帳密由 `scripts/git-credential.sh`(git credential helper)提供,用同一個 login 的 token:腳本內的 git 自動套用,`start.sh` 也會把它寫進 clone 的本地設定(只對該 Gitea 主機),所以 agent 在 worktree 裡 push/fetch 不會再出現 `could not read Username`。要換人先 `tea login default <name>`,或設 `HERDR_ISSUE_LOGIN`。
## 語言規則 ## 語言規則
@@ -59,4 +59,6 @@ Gitea 一律以 tea 的預設 login(`tea login list` 中 default 為 true 的
| `tick.sh` | 子 agent | 勾議題內文第 k 個核取方塊 | | `tick.sh` | 子 agent | 勾議題內文第 k 個核取方塊 |
| `pr-wait.sh` | 子 agent(背景) | 等 PR 衝突、關閉或合併 | | `pr-wait.sh` | 子 agent(背景) | 等 PR 衝突、關閉或合併 |
環境變數:`HERDR_ISSUE_INTERVAL`(pr-wait 輪詢秒數,預設 300)、`HERDR_ISSUE_WATCH_INTERVAL`(watch-issue 輪詢秒數,預設 5)、`HERDR_ISSUE_BLOCKED_AFTER`(blocked 多久才通知,預設 60 秒)、`HERDR_ISSUE_MODEL`(預設 `claude-opus-5-5`)。 TLS/憑證錯誤:`lib.sh` 的 tea 包裝會自動重試(預設 5 次、間隔 3 秒),輪詢中的 `watch-issue.sh`、`pr-wait.sh` 因此不會被一次性的連線問題打斷;不會關閉憑證驗證。若憑證長期有問題,請修正伺服器或系統 CA,而不是略過驗證。
環境變數:`HERDR_ISSUE_TLS_RETRIES`(TLS 重試次數,預設 5)、`HERDR_ISSUE_INTERVAL`(pr-wait 輪詢秒數,預設 300)、`HERDR_ISSUE_WATCH_INTERVAL`(watch-issue 輪詢秒數,預設 5)、`HERDR_ISSUE_BLOCKED_AFTER`(blocked 多久才通知,預設 60 秒)、`HERDR_ISSUE_MODEL`(預設 `claude-sonnet-5-5`)。
+24
View File
@@ -0,0 +1,24 @@
#!/usr/bin/env bash
# git credential helper:用 tea 預設 login 的帳號與 token 回應 HTTPS 認證,避免 git 要互動輸入帳密
# ("could not read Username ... No such device or address")。只處理 get,且只回應該 login 的主機。
[ "${1:-}" = get ] || exit 0
exec python3 -c '
import os, sys
req = dict(l.split("=", 1) for l in sys.stdin.read().splitlines() if "=" in l)
cfg = os.path.join(os.environ.get("XDG_CONFIG_HOME") or os.path.expanduser("~/.config"), "tea", "config.yml")
logins, cur = [], None
for line in open(cfg):
s = line.strip()
if s.startswith("- name:"):
cur = {"name": s.split(":", 1)[1].strip()}; logins.append(cur)
elif cur is not None and ":" in s:
k, v = s.split(":", 1)
if k in ("url", "token", "user", "default"): cur[k] = v.strip().strip("\"\x27")
want = os.environ.get("HERDR_ISSUE_LOGIN")
pick = next((l for l in logins if l["name"] == want), None) if want else None
pick = pick or next((l for l in logins if l.get("default") == "true"), None)
if not pick or not pick.get("token"): sys.exit(0)
host = pick["url"].split("://", 1)[-1].rstrip("/")
if req.get("host") != host: sys.exit(0)
print("username=" + pick["user"]); print("password=" + pick["token"])
'
+21 -2
View File
@@ -6,7 +6,7 @@ LABEL="in-progress"
LABEL_COLOR="0e8a16" LABEL_COLOR="0e8a16"
LABEL_DESC="Herdr 的 agent 正在實作" LABEL_DESC="Herdr 的 agent 正在實作"
INTERVAL="${HERDR_ISSUE_INTERVAL:-300}" INTERVAL="${HERDR_ISSUE_INTERVAL:-300}"
MODEL="${HERDR_ISSUE_MODEL:-claude-opus-5-5}" MODEL="${HERDR_ISSUE_MODEL:-claude-sonnet-5-5}"
SCRIPTS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" SCRIPTS="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
die() { echo "herdr-issue: $*" >&2; exit 1; } die() { echo "herdr-issue: $*" >&2; exit 1; }
@@ -19,7 +19,26 @@ print(next((l['name'] for l in json.load(sys.stdin) if str(l.get('default')).low
fi fi
[ -n "$HERDR_ISSUE_LOGIN" ] || { echo "herdr-issue: tea 沒有預設 login,請先 tea login default <name>" >&2; exit 1; } [ -n "$HERDR_ISSUE_LOGIN" ] || { echo "herdr-issue: tea 沒有預設 login,請先 tea login default <name>" >&2; exit 1; }
export HERDR_ISSUE_LOGIN export HERDR_ISSUE_LOGIN
tea() { command tea "$1" --login "$HERDR_ISSUE_LOGIN" "${@:2}"; }
# git 走 HTTPS 時沒有帳密又不能互動輸入會失敗,所以腳本內的 git 一律用 tea 預設 login 的 token(git-credential.sh)。
export GIT_TERMINAL_PROMPT=0
git() { command git -c credential.helper= -c "credential.helper=$SCRIPTS/git-credential.sh" "$@"; }
# TLS/憑證錯誤多半是暫時的(連線被重置、代理、時鐘),遇到就重試幾次,不要讓輪詢中的腳本因此中斷;
# 其他錯誤原樣回傳。不關閉憑證驗證。重試次數 HERDR_ISSUE_TLS_RETRIES(預設 5),間隔 3 秒。
tea() {
local out err rc=0 try max="${HERDR_ISSUE_TLS_RETRIES:-5}" ef; ef="$(mktemp)"
for ((try = 1; try <= max; try++)); do
out="$(command tea "$1" --login "$HERDR_ISSUE_LOGIN" "${@:2}" 2>"$ef")" && rc=0 || rc=$?
err="$(cat "$ef")"
if ! grep -qiE 'tls|x509|certificate|handshake' <<<"$out$err"; then break; fi
echo "herdr-issue: tea 遇到 TLS/憑證錯誤(第 $try/$max 次),3 秒後重試" >&2
rc=${rc/#0/1}; sleep 3
done
rm -f "$ef"
[ -z "$err" ] || printf '%s\n' "$err" >&2
printf '%s\n' "$out"
return "$rc"
}
# 從 stdin 讀 JSON,執行 python 片段,d 是解析後的物件。 # 從 stdin 讀 JSON,執行 python 片段,d 是解析後的物件。
jq_py() { python3 -c "import sys,json jq_py() { python3 -c "import sys,json
+1 -1
View File
@@ -1,4 +1,4 @@
/mattpocock-skills:implement {LINK} 請實作這個 Gitea 議題:{LINK}(先用 tea issues 讀完整內文與留言,依 Acceptance criteria 逐項完成)。
你在分支 issue-{N} 的 worktree 裡,從 origin/main 建立,請在這裡實作,不要另外建 worktree。 你在分支 issue-{N} 的 worktree 裡,從 origin/main 建立,請在這裡實作,不要另外建 worktree。
{RESUME} {RESUME}
+5
View File
@@ -60,6 +60,11 @@ fi
GIT_USER="$(command tea login list --output json | jq_py "print(next((l['user'] for l in d if l['name']=='$HERDR_ISSUE_LOGIN'),''))")" GIT_USER="$(command tea login list --output json | jq_py "print(next((l['user'] for l in d if l['name']=='$HERDR_ISSUE_LOGIN'),''))")"
GIT_EMAIL="$(tea api "/user" | jq_py 'print(d.get("email") or "")' 2>/dev/null || true)" GIT_EMAIL="$(tea api "/user" | jq_py 'print(d.get("email") or "")' 2>/dev/null || true)"
git -C "$CLONE" config extensions.worktreeConfig true git -C "$CLONE" config extensions.worktreeConfig true
# agent 在 worktree 裡自己跑的 git(push、fetch)也要有帳密:把 helper 設到 clone 的本地設定(worktree 共用),只對這個主機生效
GIT_HOST_URL="$(command tea login list --output json | jq_py "print(next((l['url'] for l in d if l['name']=='$HERDR_ISSUE_LOGIN'),''))")"
if [ -n "$GIT_HOST_URL" ]; then
git -C "$CLONE" config --local --replace-all "credential.$GIT_HOST_URL.helper" "$SCRIPTS/git-credential.sh"
fi
git -C "$WT" config --worktree user.name "$GIT_USER" git -C "$WT" config --worktree user.name "$GIT_USER"
[ -z "$GIT_EMAIL" ] || git -C "$WT" config --worktree user.email "$GIT_EMAIL" [ -z "$GIT_EMAIL" ] || git -C "$WT" config --worktree user.email "$GIT_EMAIL"