hive-forge: single command with subverbs instead of per-verb scripts

This commit is contained in:
damocles 2026-05-20 21:43:26 +02:00 committed by Mara
parent 0a4cde88b0
commit a95ca22b49
2 changed files with 165 additions and 185 deletions

View file

@ -248,7 +248,10 @@
# `nix flake` constantly (devshells, ad-hoc evals, fetching their
# own MCP-server flakes); without this they hit the "experimental
# feature not enabled" wall on the first try.
nix.settings.experimental-features = [ "nix-command" "flakes" ];
nix.settings.experimental-features = [
"nix-command"
"flakes"
];
# `claude-code` is unfree. Each per-agent container's nixosConfiguration
# evaluates its own `nixpkgs` instance, so the operator's host-level
@ -273,9 +276,8 @@
jq
# curl: HTTP client for forge REST API and other web requests.
curl
# hive-forge-*: shell wrappers around the Forgejo REST API
# (hive-forge-view, hive-forge-pr, hive-forge-comment, etc.)
# that replace ad-hoc curl pipelines in agent turns.
# hive-forge <verb>: CLI wrapping common Forgejo REST API operations
# (view, pr, issue, comment, assign, close, labels, branches, etc.)
(pkgs.callPackage ../packages/hive-forge-tools.nix { })
];
@ -298,57 +300,57 @@
pkgs.coreutils
];
script = ''
# No `set -e`: any subshell failure must not propagate.
# A failed unit aborts `nixos-container update` which blocks rebuilds.
FORGE_URL=${lib.escapeShellArg config.hyperhive.forge.url}
# Manager bind-mounts state at /state; sub-agents at
# /agents/<name>/state. Glob both — each container only sees
# its own mount, so there is exactly one hit (or zero when
# the forge hasn't been seeded yet).
TOKEN_FILE=""
for f in /state/forge-token /agents/*/state/forge-token; do
if [ -f "$f" ]; then
TOKEN_FILE="$f"
break
fi
done
if [ -z "$TOKEN_FILE" ]; then
echo "tea-login: no forge-token found; skipping"
exit 0
fi
TOKEN=$(cat "$TOKEN_FILE")
# Resolve the agent username from the forge API.
USER=$(curl -sf --max-time 5 \
-H "Authorization: token $TOKEN" \
"$FORGE_URL/api/v1/user" \
| python3 -c 'import sys,json; print(json.load(sys.stdin).get("login",""))' \
2>/dev/null || true)
if [ -z "$USER" ]; then
echo "tea-login: could not resolve username from forge API; skipping"
exit 0
fi
# tea reads config from $HOME/.config/tea/config.yml.
# Write it directly so we control default:true and always
# refresh a rotated token — no 'tea login add' interactive dance.
CONFIG="$HOME/.config/tea/config.yml"
mkdir -p "$(dirname "$CONFIG")" || true
cat > "$CONFIG" << EOF
logins:
- name: forge
url: $FORGE_URL
token: $TOKEN
default: true
ssh_host: ""
ssh_key: ""
insecure: false
ssh_agent: false
user: $USER
preferences:
editor: false
flag_defaults:
remote: ""
EOF
echo "tea-login: configured for $FORGE_URL as $USER"
# No `set -e`: any subshell failure must not propagate.
# A failed unit aborts `nixos-container update` which blocks rebuilds.
FORGE_URL=${lib.escapeShellArg config.hyperhive.forge.url}
# Manager bind-mounts state at /state; sub-agents at
# /agents/<name>/state. Glob both — each container only sees
# its own mount, so there is exactly one hit (or zero when
# the forge hasn't been seeded yet).
TOKEN_FILE=""
for f in /state/forge-token /agents/*/state/forge-token; do
if [ -f "$f" ]; then
TOKEN_FILE="$f"
break
fi
done
if [ -z "$TOKEN_FILE" ]; then
echo "tea-login: no forge-token found; skipping"
exit 0
fi
TOKEN=$(cat "$TOKEN_FILE")
# Resolve the agent username from the forge API.
USER=$(curl -sf --max-time 5 \
-H "Authorization: token $TOKEN" \
"$FORGE_URL/api/v1/user" \
| python3 -c 'import sys,json; print(json.load(sys.stdin).get("login",""))' \
2>/dev/null || true)
if [ -z "$USER" ]; then
echo "tea-login: could not resolve username from forge API; skipping"
exit 0
fi
# tea reads config from $HOME/.config/tea/config.yml.
# Write it directly so we control default:true and always
# refresh a rotated token — no 'tea login add' interactive dance.
CONFIG="$HOME/.config/tea/config.yml"
mkdir -p "$(dirname "$CONFIG")" || true
cat > "$CONFIG" << EOF
logins:
- name: forge
url: $FORGE_URL
token: $TOKEN
default: true
ssh_host: ""
ssh_key: ""
insecure: false
ssh_agent: false
user: $USER
preferences:
editor: false
flag_defaults:
remote: ""
EOF
echo "tea-login: configured for $FORGE_URL as $USER"
'';
};