fix tea-login: write config.yml directly, always refresh token

This commit is contained in:
damocles 2026-05-20 20:51:02 +02:00
parent d8e64742f4
commit 3c6c257506

View file

@ -275,11 +275,11 @@
curl curl
]; ];
# One-shot: configure tea with the agent's forge token if # One-shot: write tea's config.yml from the seeded forge token so
# hive-c0re seeded one and tea hasn't been configured yet. # the agent can use `tea` without interactive prompts. Runs on
# Runs before the harness service so the first turn can already # every boot so a rotated token (hive-c0re remints on each agent
# `tea repos create`. *Always* exits 0 — never fail a NixOS # rebuild) is always reflected. *Always* exits 0 — never fail a
# switch-to-configuration over a missing/temperamental forge. # NixOS switch-to-configuration over a missing/temperamental forge.
systemd.services.tea-login = { systemd.services.tea-login = {
description = "configure tea CLI from hive-forge token (best-effort)"; description = "configure tea CLI from hive-forge token (best-effort)";
wantedBy = [ "multi-user.target" ]; wantedBy = [ "multi-user.target" ];
@ -289,18 +289,18 @@
RemainAfterExit = true; RemainAfterExit = true;
}; };
path = [ path = [
pkgs.tea pkgs.curl
pkgs.python3
pkgs.coreutils pkgs.coreutils
]; ];
script = '' script = ''
# No `set -e`: any subshell failure here (tea exit, mkdir, # No `set -e`: any subshell failure must not propagate.
# missing forge) must not propagate. A failed unit aborts # A failed unit aborts `nixos-container update` which blocks rebuilds.
# `nixos-container update`, which would block every rebuild. FORGE_URL=${lib.escapeShellArg config.hyperhive.forge.url}
CONFIG=/root/.config/tea/config.yml
# Manager bind-mounts state at /state; sub-agents at # Manager bind-mounts state at /state; sub-agents at
# /agents/<name>/state. Glob both — each container only sees # /agents/<name>/state. Glob both — each container only sees
# its own mount, so there's exactly one hit either way (or # its own mount, so there is exactly one hit (or zero when
# zero, when the forge hasn't been seeded yet). # the forge hasn't been seeded yet).
TOKEN_FILE="" TOKEN_FILE=""
for f in /state/forge-token /agents/*/state/forge-token; do for f in /state/forge-token /agents/*/state/forge-token; do
if [ -f "$f" ]; then if [ -f "$f" ]; then
@ -309,22 +309,42 @@
fi fi
done done
if [ -z "$TOKEN_FILE" ]; then if [ -z "$TOKEN_FILE" ]; then
echo "tea-login: no forge-token (hive-forge not seeded); skipping" echo "tea-login: no forge-token found; skipping"
exit 0 exit 0
fi fi
if [ -f "$CONFIG" ]; then TOKEN=$(cat "$TOKEN_FILE")
echo "tea-login: $CONFIG already present; skipping" # 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 exit 0
fi 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 mkdir -p "$(dirname "$CONFIG")" || true
if ! tea login add \ cat > "$CONFIG" << EOF
--name forge \ logins:
--url ${lib.escapeShellArg config.hyperhive.forge.url} \ - name: forge
--token "$(cat "$TOKEN_FILE")"; then url: $FORGE_URL
echo "tea-login: tea login add failed; continuing without tea" token: $TOKEN
exit 0 default: true
fi ssh_host: ""
echo "tea-login: configured for ${config.hyperhive.forge.url} from $TOKEN_FILE" 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"
''; '';
}; };