#!/usr/bin/env bash
# SPDX-License-Identifier: AGPL-3.0-only
# Copyright 2026-present the Unsloth AI Inc. team. All rights reserved.
#
# Install one coding-agent CLI for the Local Agent Guides CI. Isolated as
# failure class (b) "agent package install failed": npm/curl flakiness here
# is the single biggest source of false reds, so installs retry with
# backoff and the only ::error:: this script can emit is class (b). The
# install recipes mirror the install_hint strings in
# unsloth_cli/commands/connect.py at HEAD.
#
# Usage: agent-guides-install.sh <agent>
#   agent in: claude codex hermes openclaw opencode pi
set -uo pipefail

AGENT="${1:?usage: agent-guides-install.sh <agent>}"
mkdir -p logs
LOG="logs/install-${AGENT}.log"

install_fail() {
  echo "::error::[agent install failed] agent=${AGENT}: $* (class (b): the agent CLI did not install; not a server or guide problem)." >&2
  echo "---- tail $LOG ----" >&2
  tail -60 "$LOG" 2>/dev/null || true
  exit 1
}

# npm registry flakiness is common in CI; retry 3x with linear backoff.
npm_retry() {
  local pkg="$1" i
  for i in 1 2 3; do
    if npm install -g "$pkg" >> "$LOG" 2>&1; then
      return 0
    fi
    echo "[install] npm install -g $pkg attempt $i failed; backing off $((i * 10))s" | tee -a "$LOG"
    sleep "$((i * 10))"
  done
  return 1
}

# curl|bash installers, retried at the curl layer. We download to a temp file
# first and only execute on a fully successful fetch, so a truncated download
# (network hiccup mid-stream) can never run a half-written installer.
curl_bash() {
  local url="$1"; shift
  local i tmp
  tmp="$(mktemp)"
  for i in 1 2 3; do
    if curl -fsSL --retry 3 --retry-delay 5 "$url" -o "$tmp" 2>>"$LOG" \
        && bash "$tmp" "$@" >> "$LOG" 2>&1; then
      rm -f "$tmp"
      return 0
    fi
    echo "[install] curl|bash $url attempt $i failed; backing off $((i * 10))s" | tee -a "$LOG"
    sleep "$((i * 10))"
  done
  rm -f "$tmp"
  return 1
}

echo "[install] agent=$AGENT (log=$LOG)"
case "$AGENT" in
  claude)
    # connect.py install_hint: curl -fsSL https://claude.ai/install.sh | bash
    curl_bash "https://claude.ai/install.sh" || install_fail "claude installer failed"
    # The installer drops the binary under ~/.local/bin.
    echo "$HOME/.local/bin" >> "$GITHUB_PATH"
    ;;
  codex)
    # connect.py install_hint: npm install -g @openai/codex
    npm_retry "@openai/codex" || install_fail "npm install -g @openai/codex failed"
    ;;
  opencode)
    # connect.py install_hint: npm install -g opencode-ai
    npm_retry "opencode-ai" || install_fail "npm install -g opencode-ai failed"
    ;;
  openclaw)
    # connect.py install_hint: curl -fsSL https://openclaw.ai/install.sh | bash
    # npm is the more deterministic path in CI and matches the agent's docs;
    # fall back to the connect.py curl installer if the npm tag is missing.
    if ! npm_retry "openclaw@latest"; then
      curl_bash "https://openclaw.ai/install.sh" || install_fail "openclaw install failed (npm + curl)"
      echo "$HOME/.local/bin" >> "$GITHUB_PATH"
    fi
    ;;
  hermes)
    # connect.py install_hint:
    #   curl -fsSL .../NousResearch/hermes-agent/main/scripts/install.sh | bash
    curl_bash "https://raw.githubusercontent.com/NousResearch/hermes-agent/main/scripts/install.sh" \
      --non-interactive --skip-setup --skip-browser --no-skills \
      || install_fail "hermes installer failed"
    echo "$HOME/.local/bin" >> "$GITHUB_PATH"
    ;;
  pi)
    # No connect.py recipe; the agent's documented package name. The CLI moved
    # from the now-deprecated @mariozechner scope to @earendil-works (the old
    # scope is frozen, so installing it would test a stale Pi against the API).
    npm_retry "@earendil-works/pi-coding-agent" \
      || install_fail "npm install -g @earendil-works/pi-coding-agent failed"
    ;;
  *)
    install_fail "unknown agent '$AGENT'"
    ;;
esac

echo "[install] OK for $AGENT"
