129 lines
4.5 KiB
Bash
Executable File
129 lines
4.5 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Dispatch to a standard live Herdr agent, with conservative failover.
|
|
set -euo pipefail
|
|
|
|
usage() {
|
|
cat <<'EOF'
|
|
用法:
|
|
scripts/herdr-agent-dispatch.sh --explain <lane>
|
|
scripts/herdr-agent-dispatch.sh [--timeout-ms N] <lane> <prompt>
|
|
|
|
lane: governance | critical-review | implementation | ui | test | fast-check | long-context
|
|
EOF
|
|
}
|
|
|
|
route_for() {
|
|
case "$1" in
|
|
governance) printf '%s\n' orchestrator_codex context_kimi implementer_cursor reserve_claude ;;
|
|
critical-review) printf '%s\n' orchestrator_codex reserve_claude context_kimi ;;
|
|
implementation) printf '%s\n' implementer_cursor implementer_cline verifier_antigravity orchestrator_codex ;;
|
|
ui) printf '%s\n' implementer_cursor verifier_antigravity implementer_cline ;;
|
|
test) printf '%s\n' implementer_cursor implementer_cline verifier_antigravity ;;
|
|
fast-check) printf '%s\n' verifier_antigravity implementer_cline implementer_cursor ;;
|
|
long-context) printf '%s\n' context_pi context_kimi orchestrator_codex ;;
|
|
*) return 1 ;;
|
|
esac
|
|
}
|
|
|
|
if [[ "${1:-}" == "--explain" ]]; then
|
|
[[ $# -eq 2 ]] || { usage >&2; exit 2; }
|
|
if ! route_for "$2"; then
|
|
printf '[错误] 未知 lane: %s\n' "$2" >&2
|
|
exit 2
|
|
fi
|
|
exit 0
|
|
fi
|
|
|
|
timeout_ms=120000
|
|
if [[ "${1:-}" == "--timeout-ms" ]]; then
|
|
[[ $# -ge 4 ]] || { usage >&2; exit 2; }
|
|
timeout_ms="$2"
|
|
shift 2
|
|
fi
|
|
|
|
if [[ $# -ne 2 ]]; then
|
|
usage >&2
|
|
exit 2
|
|
fi
|
|
|
|
lane="$1"
|
|
prompt="$2"
|
|
if ! routes="$(route_for "${lane}")"; then
|
|
printf '[错误] 未知 lane: %s\n' "${lane}" >&2
|
|
exit 2
|
|
fi
|
|
|
|
if [[ ! "${timeout_ms}" =~ ^[1-9][0-9]*$ ]]; then
|
|
printf '[错误] timeout 必须是正整数毫秒。\n' >&2
|
|
exit 2
|
|
fi
|
|
if [[ "${HERDR_ENV:-}" != "1" ]]; then
|
|
printf '[错误] 当前进程不在 Herdr 管理的 pane 中。\n' >&2
|
|
exit 1
|
|
fi
|
|
command -v jq >/dev/null 2>&1 || { printf '[错误] 缺少 jq。\n' >&2; exit 1; }
|
|
|
|
repo_root="$(git rev-parse --show-toplevel 2>/dev/null || true)"
|
|
if [[ -z "${repo_root}" || ! -f "${repo_root}/AGENTS.md" || ! -f "${repo_root}/PROJECT.md" ]]; then
|
|
printf '[错误] 必须从 Agent-System 任务 worktree 派发。\n' >&2
|
|
exit 1
|
|
fi
|
|
branch="$(git branch --show-current)"
|
|
if [[ "${branch}" != feature/* && "${branch}" != fix/* ]]; then
|
|
printf '[错误] 只允许从 feature/* 或 fix/* 分支派发,当前为 %s。\n' "${branch}" >&2
|
|
exit 1
|
|
fi
|
|
current_cwd="$(realpath -m "${repo_root}")"
|
|
agent_json="$(herdr agent list)"
|
|
dispatch_id="${BASHPID:-$$}-${SECONDS}"
|
|
retry_prefix="HERDR_RETRY:${dispatch_id}"
|
|
protocol="$(printf '\n\n[Herdr failover protocol]\n只有在尚未写文件、未运行有副作用命令,且仅因额度、认证或客户端故障无法开始时,回复独占一行 %s:quota、%s:auth 或 %s:client。已经开始工作时不得返回该标记;请写 handoff 并说明当前状态。' "${retry_prefix}" "${retry_prefix}" "${retry_prefix}")"
|
|
|
|
while IFS= read -r target; do
|
|
row="$(jq -c --arg name "${target}" '.result.agents[] | select(.name == $name)' <<<"${agent_json}" | head -n 1)"
|
|
if [[ -z "${row}" ]]; then
|
|
printf '[跳过] %s 未在线。\n' "${target}" >&2
|
|
continue
|
|
fi
|
|
|
|
status="$(jq -r '.agent_status' <<<"${row}")"
|
|
agent_cwd="$(jq -r '.cwd' <<<"${row}")"
|
|
if [[ "${agent_cwd}" != "${current_cwd}" ]]; then
|
|
printf '[跳过] %s cwd=%s,不是当前任务 worktree。\n' "${target}" "${agent_cwd}" >&2
|
|
continue
|
|
fi
|
|
if [[ "${status}" != "idle" && "${status}" != "done" ]]; then
|
|
printf '[跳过] %s 状态为 %s。\n' "${target}" "${status}" >&2
|
|
continue
|
|
fi
|
|
|
|
printf '[派发] lane=%s target=%s\n' "${lane}" "${target}" >&2
|
|
set +e
|
|
result="$(herdr agent prompt "${target}" "${prompt}${protocol}" --wait --timeout "${timeout_ms}" 2>&1)"
|
|
rc=$?
|
|
set -e
|
|
|
|
if [[ ${rc} -ne 0 ]]; then
|
|
if rg -q 'agent_blocked|agent_not_found|agent_not_ready' <<<"${result}"; then
|
|
printf '[降级] %s 在投递前不可用。\n' "${target}" >&2
|
|
continue
|
|
fi
|
|
printf '%s\n' "${result}" >&2
|
|
printf '[停止] 结果可能已投递;为避免重复执行,不自动切换备援。\n' >&2
|
|
exit 75
|
|
fi
|
|
|
|
transcript="$(herdr agent read "${target}" --source recent-unwrapped --lines 120 2>/dev/null || true)"
|
|
if rg -q "^${retry_prefix}:(quota|auth|client)$" <<<"${transcript}"; then
|
|
printf '[降级] %s 明确报告写入前失败。\n' "${target}" >&2
|
|
agent_json="$(herdr agent list)"
|
|
continue
|
|
fi
|
|
|
|
printf '%s\n' "${result}"
|
|
exit 0
|
|
done <<<"${routes}"
|
|
|
|
printf '[错误] lane=%s 无可用实例;请用 herdr-agent-start.sh 启动标准实例。\n' "${lane}" >&2
|
|
exit 69
|