#!/usr/bin/env bash
# ============================================================================
#  ACCORDO - Installer  ·  by KomputerMechanic
#  The curl one-liner target. Verifies your membership key, then runs the real
#  installer in a temporary folder that is wiped afterwards. The installer is
#  never stored on your machine.
#
#     curl -fsSL https://accordo-free-misty-valley.komputermechanic.com | bash
#     (no --update: Accordo free is installed once, as it is. Updates are Accordo Pro's.)
# ============================================================================
set -euo pipefail
WORKER_URL="https://accordo-free-misty-valley.komputermechanic.com"
TUTORIAL_SLUG="accordo-free"
ACC_UPDATE="${ACC_UPDATE:-}"
for _arg in "$@"; do case "$_arg" in --update) ACC_UPDATE=1 ;; esac; done
if [ -n "$ACC_UPDATE" ]; then
  printf '\n  Accordo free does not get updates: it is installed once, as it is.\n  Updates are part of Accordo Pro.\n\n'
  exit 1
fi

if [ -t 1 ]; then B=$'\e[1m'; DIM=$'\e[2m'; G=$'\e[38;5;71m'; R=$'\e[38;5;167m'; ACC=$'\e[38;5;214m'; Z=$'\e[0m'
else B=; DIM=; G=; R=; ACC=; Z=; fi

printf '\n  %s%sKomputerMechanic  ~  ACCORDO%s\n' "$B" "$ACC" "$Z"
printf '  %sYour AI team in one dashboard · installer%s\n\n' "$DIM" "$Z"

command -v curl >/dev/null || { printf '  %scurl is required.%s\n' "$R" "$Z"; exit 1; }

TMP="$(mktemp -d)"; trap 'rm -rf "$TMP"' EXIT

# ---- Intel Macs: not supported, said BEFORE the key is asked for ---------------------------
# A deliberate scope decision (2026-08-14): the test fleet is Apple Silicon + Linux, and a
# commercial product does not sell onto silicon it has never run on. Said here, before the
# licence prompt, so nobody types a key for a machine we will not support. ACC_INTEL_OK=1
# proceeds anyway for tinkerers - unsupported, clearly labelled.
if [ "$(uname -s 2>/dev/null)" = "Darwin" ] && [ "$(uname -m 2>/dev/null)" = "x86_64" ] && [ -z "${ACC_INTEL_OK:-}" ]; then
  printf '\n  %s%sThis is an Intel-based Mac.%s\n\n' "$R" "$B" "$Z"
  printf '  Accordo supports %sApple Silicon Macs (M1 or newer) and Linux%s.\n' "$B" "$Z"
  printf '  Intel Macs are not supported - not because it cannot work, but because we\n'
  printf '  do not test on them, and we only sell what we test.\n\n'
  printf '  %sNo key was asked for and nothing was changed on this machine.%s\n' "$DIM" "$Z"
  printf '  Determined to try anyway, unsupported? Re-run with ACC_INTEL_OK=1\n'
  printf '  Questions or refunds: %sinfo@komputermechanic.com%s\n\n' "$DIM" "$Z"
  exit 1
fi

# TESTS ONLY: ACC_LOCAL_TARBALL=<file> uses a package already on this machine instead of the worker. It
# skips only the DOWNLOAD: the installer's own licence gate still runs (ACC_LICENSE_REQUIRED decides), and
# no activation is recorded.
if [ -n "${ACC_LOCAL_TARBALL:-}" ]; then
  cp "$ACC_LOCAL_TARBALL" "$TMP/body" || { printf '  %sNo package at %s%s\n' "$R" "$ACC_LOCAL_TARBALL" "$Z"; exit 1; }
  : > "$TMP/head"; KEY="local-test"
  printf '  %sTest run: using the local package %s%s\n' "$DIM" "$ACC_LOCAL_TARBALL" "$Z"
else
# the "error" from the worker's JSON answer, read properly (a message with a quote in it defeated grep)
_server_reason() {
  python3 -c 'import json, sys
try:
    print((json.load(open(sys.argv[1])).get("error") or "").strip())
except Exception:
    pass' "$1" 2>/dev/null && return 0
  { grep -o '"error":"[^"]*"' "$1" 2>/dev/null || true; } | head -1 | cut -d'"' -f4
}
# membership key — verify, with one extra try in case of a typo
LAST_ERR=""
ATTEMPTS=2; [ -n "${ACC_LICENSE:-}" ] && ATTEMPTS=1
VERIFIED=0
for try in $(seq 1 "$ATTEMPTS"); do
  KEY="${ACC_LICENSE:-}"
  if [ -z "$KEY" ]; then
    [ "$try" -gt 1 ] && printf "  %sLet's try that once more.%s\n" "$DIM" "$Z"
    [ "$try" = 1 ] && printf '  %sNo key yet? Request your free Accordo key at https://komputermechanic.com/accordo%s\n' "$DIM" "$Z"
    read -r -p "  Enter your Accordo key: " KEY </dev/tty || true
  fi
  KEY="$(printf '%s' "$KEY" | tr -d '[:space:]')"
  if [ -z "$KEY" ]; then printf '  %sNo key entered.%s\n' "$R" "$Z"; continue; fi
  printf '  %sChecking your key...%s\n' "$DIM" "$Z"
  # --retry alone does not cover a dropped connection; --retry-all-errors does. Validation is
  # read-only server-side, so retrying it never costs an activation.
  CODE="$(curl -sS --retry 3 --retry-delay 2 --retry-all-errors -X POST "$WORKER_URL" \
          -H 'Content-Type: application/json' \
          -d "{\"license_key\":\"$KEY\",\"tutorial_slug\":\"$TUTORIAL_SLUG\"}" \
          -D "$TMP/head" -o "$TMP/body" -w '%{http_code}' 2>/dev/null || true)"
  CODE="${CODE:0:3}"; [ -n "$CODE" ] || CODE=000      # curl prints 000 itself when nothing answered
  if [ "$CODE" = "200" ]; then VERIFIED=1; break; fi
  # The server says WHY (install limit, renewal date, payment, wrong installer...): show its words as they
  # are. A buyer who hit his install limit was told "check your key and your connection" twelve times
  # (2026-10-12) because the reason was not read. Only a reply that never came is a connection problem.
  ERR="$(_server_reason "$TMP/body")"
  LAST_CODE="$CODE"; LAST_ERR="$ERR"
  if [ -z "$ERR" ]; then
    case "$CODE" in
      000|5??) ERR="Could not reach the key server. Check this machine's internet connection and try again." ;;
      *)       ERR="The key server refused this key (HTTP $CODE) without saying why. Contact info@komputermechanic.com" ;;
    esac
  fi
  printf '  %s✗  %s%s\n' "$R" "$ERR" "$Z"
  # a typo is worth a second try; an install limit, a payment or an expired key is not
  case "$CODE:$LAST_ERR" in 403:*[Ii]nvalid*|403:) : ;; 403:*) break ;; esac
done
if [ "$VERIFIED" != "1" ]; then
  # Don't contradict the server. When it told us WHY (e.g. the install limit is reached),
  # repeating "check your key" sends a customer whose key is perfectly valid down the
  # wrong path. Echo guidance that matches the actual reason.
  if [ -n "$LAST_ERR" ]; then
    # the server's own words were printed above, as they are; just close the run
    printf '\n  %sNothing was installed. Questions: info@komputermechanic.com%s\n\n' "$DIM" "$Z"
  else
    case "${LAST_CODE:-000}" in
      000|5??) printf '\n  %s%sCould not reach the key server.%s Check this machine'"'"'s internet connection and try again.\n\n' "$R" "$B" "$Z" ;;
      *)       printf '\n  %s%sYour key was not accepted.%s Contact info@komputermechanic.com\n\n' "$R" "$B" "$Z" ;;
    esac
  fi
  exit 1
fi
printf '  %s✓ Key verified.%s\n' "$G" "$Z"
fi

# unpack into the temp folder, stamp the key, run, then wipe
tar -xzf "$TMP/body" -C "$TMP" 2>/dev/null || { printf '  %sInstaller package was invalid.%s\n' "$R" "$Z"; exit 1; }
DIR="$TMP/accordo-installer"
[ -f "$DIR/install.sh" ] || { printf '  %sInstaller not found in package.%s\n' "$R" "$Z"; exit 1; }
CUSTOMER="$( { grep -i '^x-km-customer:' "$TMP/head" || true; } | tr -d '\r' | awk '{print $2}')"
printf 'membership_key=%s\ncustomer=%s\ninstalled=%s\n' \
  "$KEY" "$CUSTOMER" "$(date -u +%FT%TZ 2>/dev/null || echo now)" > "$DIR/.license" 2>/dev/null || true

# ---- the terms: accepted BEFORE anything on this machine is touched -----------------------------------
# Right after the membership key and before Docker, Hermes or anything else goes in: the old order showed
# them only once Hermes was already installed (owner, 2026-10-12: "it makes no sense to touch the
# person's machine if they haven't accepted the terms"). The text is payload/TERMS.txt, the same file the
# installer shows when it is run on its own; once accepted here it does not ask again. No Y: nothing
# installed, no install used.
if [ -f "$DIR/payload/TERMS.txt" ]; then
  _tw=70; _te=""; _ti=0; while [ "$_ti" -lt $((_tw + 2)) ]; do _te="${_te}╌"; _ti=$((_ti + 1)); done
  printf '\n  %s┌%s┐%s\n' "$ACC" "$_te" "$Z"
  printf '  %s┊%s %sPLEASE READ  -  LICENSE, DISCLAIMER & TERMS%s\n  %s┊%s\n' "$ACC" "$Z" "$B" "$Z" "$ACC" "$Z"
  awk -v RS= '{gsub(/\n/," "); print; print ""}' "$DIR/payload/TERMS.txt" | fold -s -w "$_tw" | sed "s/^/  ${ACC}┊${Z} /"
  printf '  %s└%s┘%s\n' "$ACC" "$_te" "$Z"
  if [ -n "${ACC_YES:-}" ]; then
    printf '  %s(ACC_YES set: the terms are accepted for this unattended run)%s\n' "$DIM" "$Z"
  elif { : </dev/tty; } 2>/dev/null; then
    _acc=""; read -r -p "  Type Y to accept and continue, anything else to stop: " _acc </dev/tty || _acc=""
    case "$_acc" in [Yy]|[Yy][Ee][Ss]) printf '  %s✓ Terms accepted.%s\n\n' "$G" "$Z" ;;
      *) printf '\n  %sThe terms were not accepted. Nothing was installed and no install was used.%s\n\n' "$R" "$Z"; exit 1 ;; esac
  else
    printf '\n  %sThere is no terminal here to accept the terms.%s Run the installer in a terminal.\n\n' "$R" "$Z"; exit 1
  fi
  export ACC_TERMS_ACCEPTED=1
fi

printf '  %sStarting the installer...%s\n' "$DIM" "$Z"
cd "$DIR"
# The real installer runs its own licence step; it already verified here, so skip the double-check.
[ -n "${ACC_LOCAL_TARBALL:-}" ] || export ACC_SKIP_LICENSE=1   # a local test package keeps the installer's own gate
set +e

# ---- Hermes in a Docker container on this VPS (Hostinger's image and the like) ---------------
# On such a box there is no `hermes` on the host at all: it lives inside a container, with its
# data at /opt/data, running as its own user. The installer used to die here at "hermes CLI not
# found". Now: if there is no hermes on the host and a running container looks like Hermes, offer
# to install INTO it - the package is copied in and run as the container's Hermes user, and the
# activation is recorded from the result exactly as for a host install.
#
# WHICH container: the first version only looked at containers whose NAME or IMAGE contained
# "hermes", then quietly took the first of them. A buyer with two Hermes containers - one he
# wanted to keep and a new one for Accordo - got the old one every time, because the new one
# was named after his project, not after Hermes (feedback, 2026-09-10). Now every running
# container is PROBED for Hermes (a hermes binary, HERMES_HOME, or a Hermes config in a home
# dir), the ones that already carry an Accordo install are flagged, and with more than one the
# BUYER picks from a numbered list - no default, the installer never chooses a container for
# him (it is his setup). Headless with more than one: stop and ask for ACC_CONTAINER_NAME=<name>.
#
# HOST **AND** CONTAINER: a buyer running Mission Control on the host as root spun up a fresh
# Hermes container to try Accordo beside it, and the script never even looked - the whole Docker
# path was gated on there being NO Hermes on the host, so the host install won by default and
# his container was invisible (feedback, 2026-09-11). Having both is a normal thing to want:
# the old crew keeps working while the new one is tried next to it. So containers are now
# looked for ALWAYS, and when both exist the buyer is asked which one. Unattended runs keep
# the host, exactly as before, and say which containers they saw.
_hermes_on_host() { command -v hermes >/dev/null 2>&1 || [ -x "$HOME/.local/bin/hermes" ] || [ -x /usr/local/bin/hermes ]; }
# does this running container hold a Hermes? asks the container itself, never its name
_ctr_is_hermes() {
  timeout 10 docker exec "$1" sh -c 'command -v hermes >/dev/null 2>&1 || [ -n "${HERMES_HOME:-}" ] \
    || ls /opt/data/config.yaml /home/*/.hermes/config.yaml /root/.hermes/config.yaml >/dev/null 2>&1' >/dev/null 2>&1
}
# the Hermes user's home in this container (where an Accordo install lands), empty if unknown
_ctr_accordo_installed() {
  local hh u home
  hh="$(timeout 10 docker exec "$1" sh -c 'printf %s "${HERMES_HOME:-/opt/data}"' 2>/dev/null || true)"
  u="$(timeout 10 docker exec "$1" sh -c "stat -c %U '${hh:-/opt/data}'" 2>/dev/null || true)"
  home="$(timeout 10 docker exec "$1" sh -c "getent passwd '${u:-hermes}' | cut -d: -f6" 2>/dev/null || true)"
  [ -n "$home" ] && timeout 10 docker exec "$1" sh -c "[ -f '$home/accordo/server/server.py' ]" >/dev/null 2>&1
}
CTR=""
_HOST_HERMES=""; _hermes_on_host && _HOST_HERMES=1
if [ "$(uname -s 2>/dev/null)" = "Linux" ] && command -v docker >/dev/null 2>&1; then
  _NAMES=(); _IMAGES=(); _FLAGS=()
  while IFS=$'\t' read -r _n _img; do
    [ -n "$_n" ] || continue
    if _ctr_is_hermes "$_n" || printf '%s %s' "$_n" "$_img" | grep -qi hermes; then
      _NAMES+=("$_n"); _IMAGES+=("$_img")
      if _ctr_accordo_installed "$_n"; then _FLAGS+=("Accordo already installed")
      else _FLAGS+=(""); fi
    fi
  done < <(docker ps --format '{{.Names}}\t{{.Image}}' 2>/dev/null || true)
  # Hermes containers that exist but are NOT running are named too, so "the script does not
  # see my new container" has an answer on screen: start it, then re-run.
  _STOPPED="$(docker ps -a --filter status=exited --filter status=created --format '{{.Names}} {{.Image}}' 2>/dev/null | grep -i hermes || true)"
  if [ -n "${ACC_CONTAINER_NAME:-}" ]; then
    if docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$ACC_CONTAINER_NAME"; then
      CTR="$ACC_CONTAINER_NAME"; ACC_CONTAINER_OK=1
      printf '\n  %sHermes is running in a Docker container; ACC_CONTAINER_NAME picked %s%s\n' "$B" "$CTR" "$Z"
    elif docker ps -a --format '{{.Names}}' 2>/dev/null | grep -qx "$ACC_CONTAINER_NAME"; then
      printf '\n  %sContainer %s exists but is not running.%s Start it, then re-run:\n     docker start %s\n\n' "$R" "$ACC_CONTAINER_NAME" "$Z" "$ACC_CONTAINER_NAME"; exit 1
    else
      printf '\n  %sNo container called %s on this machine%s (ACC_CONTAINER_NAME). Running containers:\n' "$R" "$ACC_CONTAINER_NAME" "$Z"
      docker ps --format '     {{.Names}}  {{.Image}}' 2>/dev/null; echo; exit 1
    fi
  elif [ "${#_NAMES[@]}" -gt 0 ] && [ -n "$_HOST_HERMES" ]; then
    # Both. Neither is the obvious answer, so neither is assumed.
    printf '\n  %sHermes is installed on this machine AND running in Docker.%s Where should Accordo go?\n' "$B" "$Z"
    printf '     %s0)%s this machine %s(the Hermes already installed here)%s\n' "$B" "$Z" "$DIM" "$Z"
    _i=0; while [ "$_i" -lt "${#_NAMES[@]}" ]; do
      printf '     %s%d)%s %-28s %s%s%s\n' "$B" $((_i+1)) "$Z" "${_NAMES[$_i]}" "$DIM" "${_IMAGES[$_i]}" "$Z"
      [ -n "${_FLAGS[$_i]}" ] && printf '        %s%s%s\n' "$ACC" "${_FLAGS[$_i]}" "$Z"
      _i=$((_i+1))
    done
    [ -n "$_STOPPED" ] && { printf '     %snot running (docker start <name> first):%s\n' "$DIM" "$Z"; printf '%s\n' "$_STOPPED" | sed "s/^/        /"; }
    printf '     %sInstalling into a container leaves whatever is on this machine untouched.%s\n' "$DIM" "$Z"
    if ! { : </dev/tty; } 2>/dev/null; then
      # Unattended keeps the old behaviour to the letter: the host. Changing the
      # default here would silently move somebody else's scripted install.
      printf '\n  %sNo terminal to ask, so Accordo goes on this machine%s (as it always has).\n' "$ACC" "$Z"
      printf '  To install into a container instead, re-run with:  ACC_CONTAINER_NAME=<name>\n\n'
    else
      _try=0; _done=""
      while [ -z "$_done" ] && [ "$_try" -lt 3 ]; do
        read -r -p "  Which one? [0-${#_NAMES[@]}]: " _pick </dev/tty || _pick=""
        if [ "$_pick" = "0" ]; then _done=1; CTR=""          # this machine
        elif printf '%s' "$_pick" | grep -qE '^[0-9]+$' && [ "$_pick" -ge 1 ] && [ "$_pick" -le "${#_NAMES[@]}" ]; then
          CTR="${_NAMES[$((_pick-1))]}"; _done=1
        elif docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$_pick"; then
          CTR="$_pick"; _done=1
        else
          [ -n "$_pick" ] && printf '  %s"%s" is not one of the choices.%s\n' "$R" "$_pick" "$Z"
          _try=$((_try+1))
        fi
      done
      [ -z "$_done" ] && { printf '\n  Nothing installed: no target chosen. Re-run and pick one.\n\n'; exit 1; }
    fi
  elif [ "${#_NAMES[@]}" -gt 0 ]; then
    printf '\n  %sNo Hermes on this machine itself, but Hermes is running in a Docker container:%s\n' "$B" "$Z"
    _i=0; while [ "$_i" -lt "${#_NAMES[@]}" ]; do
      printf '     %s%d)%s %-28s %s%s%s\n' "$B" $((_i+1)) "$Z" "${_NAMES[$_i]}" "$DIM" "${_IMAGES[$_i]}" "$Z"
      [ -n "${_FLAGS[$_i]}" ] && printf '        %s%s%s\n' "$ACC" "${_FLAGS[$_i]}" "$Z"
      _i=$((_i+1))
    done
    [ -n "$_STOPPED" ] && { printf '     %snot running (docker start <name> first):%s\n' "$DIM" "$Z"; printf '%s\n' "$_STOPPED" | sed "s/^/        /"; }
    printf '     %sNot the one you want? Start the Hermes container you mean, or set ACC_CONTAINER_NAME=<name>.%s\n' "$DIM" "$Z"
    if [ "${#_NAMES[@]}" -eq 1 ]; then
      CTR="${_NAMES[0]}"     # the only one: confirmed below, never assumed
    elif ! { : </dev/tty; } 2>/dev/null; then
      printf '\n  %sMore than one Hermes container and no terminal to ask you.%s Name the one you mean and re-run:\n     ACC_CONTAINER_NAME=<name> curl ... | bash\n\n' "$R" "$Z"; exit 1
    else
      _try=0
      while [ -z "$CTR" ] && [ "$_try" -lt 3 ]; do
        read -r -p "  Which container? [1-${#_NAMES[@]}]: " _pick </dev/tty || _pick=""
        if printf '%s' "$_pick" | grep -qE '^[0-9]+$' && [ "$_pick" -ge 1 ] && [ "$_pick" -le "${#_NAMES[@]}" ]; then
          CTR="${_NAMES[$((_pick-1))]}"; break
        elif docker ps --format '{{.Names}}' 2>/dev/null | grep -qx "$_pick"; then
          CTR="$_pick"; break     # any RUNNING container by name, even one the probe did not flag
        fi
        [ -n "$_pick" ] && printf '  %sNo running container "%s" - a number from the list or an exact name.%s\n' "$R" "$_pick" "$Z"
        _try=$((_try+1))
      done
      [ -z "$CTR" ] && { printf '\n  Nothing installed: no container chosen. Re-run and pick one, or set ACC_CONTAINER_NAME=<name>.\n\n'; exit 1; }
    fi
    if [ -z "${ACC_CONTAINER_OK:-}" ] && { : </dev/tty; } 2>/dev/null; then
      read -r -p "  Install Accordo into container '$CTR'? [Y/n]: " _ok </dev/tty || _ok=""
      case "$_ok" in [Nn]*)
        printf '\n  Nothing installed. Start or name the container you want (ACC_CONTAINER_NAME=<name>) and re-run.\n\n'; exit 0 ;;
      esac
    fi
  elif [ -n "$_STOPPED" ] && [ -n "$_HOST_HERMES" ]; then
    # There is a perfectly good Hermes here; a stopped container is worth naming, not fatal.
    printf '\n  %sHermes container(s) here are not running, so Accordo goes on this machine:%s\n' "$DIM" "$Z"
    printf '%s\n' "$_STOPPED" | sed 's/^/     /'
    printf '     %sWanted one of those instead? docker start <name>, then re-run.%s\n' "$DIM" "$Z"
  elif [ -n "$_STOPPED" ]; then
    printf '\n  %sNo Hermes on this machine, and the Hermes container(s) here are not running:%s\n' "$R" "$Z"
    printf '%s\n' "$_STOPPED" | sed 's/^/     /'
    printf '  Start the one you want (docker start <name>), then re-run.\n\n'; exit 1
  fi
fi

# ---- Hermes this installer set up last time, whose model or Telegram step did not finish ---------------
# The marker in Hermes' data says so. Without this, a re-run found Hermes, skipped straight to the dashboard and
# installed it on a model that never answered. Now the setup continues at the model, in that same container.
_MADE_HERMES=""
if [ -n "$CTR" ] && docker exec "$CTR" sh -c 'test -f "${HERMES_HOME:-/opt/data}/.accordo-hermes-setup"' >/dev/null 2>&1; then
  printf '\n  %sHermes is in container %s, but its setup did not finish last time.%s Continuing with your AI model.\n' "$B" "$CTR" "$Z"
  _HD_OUT="$(ACC_HD_RESUME="$CTR" bash "$DIR/payload/hermes-docker.sh")" || { printf '\n  %sHermes could not be set up (see above). Nothing of Accordo was installed and no install was used.%s\n\n' "$R" "$Z"; exit 1; }
  _p="$(printf '%s\n' "$_HD_OUT" | sed -n 's/^PORT=//p' | tail -1)"; [ -n "$_p" ] && ACC_PORT="$_p"
  export ACC_PORT ACC_PUBLISHED=1 ACC_HERMES_MADE=1
  ACC_CONTAINER_OK=1; _MADE_HERMES=1
fi

# ---- no Hermes anywhere: install it in Docker first (Linux servers) ---------------------------------
# Not on this machine and not in any container: Hermes Agent (Nous Research, MIT) is set up in Docker by
# payload/hermes-docker.sh, which asks the buyer for their AI model (Hermes' own wizard), their Telegram
# bot token and their Telegram user ID. Accordo then installs into that container like any other.
if [ -z "$CTR" ] && [ -z "$_HOST_HERMES" ] && [ "$(uname -s 2>/dev/null)" = "Linux" ]; then
  printf '\n  %sThere is no Hermes on this server yet.%s Accordo runs on Hermes Agent (free, open source,\n' "$B" "$Z"
  printf '  by Nous Research). The installer can set it up for you in Docker first.\n'
  _go="y"
  if [ -z "${ACC_YES:-}" ] && { : </dev/tty; } 2>/dev/null; then
    read -r -p "  Install Hermes Agent in Docker now? [Y/n]: " _go </dev/tty || _go=""
  fi
  case "${_go:-y}" in [Nn]*) printf '\n  Nothing installed. Install Hermes yourself, then run this installer again.\n\n'; exit 0 ;; esac
  _HD_OUT="$(bash "$DIR/payload/hermes-docker.sh")" || { printf '\n  %sHermes could not be set up (see above). Nothing of Accordo was installed and no install was used.%s\n\n' "$R" "$Z"; exit 1; }
  CTR="$(printf '%s\n' "$_HD_OUT" | sed -n 's/^CONTAINER=//p' | tail -1)"
  ACC_PORT="$(printf '%s\n' "$_HD_OUT" | sed -n 's/^PORT=//p' | tail -1)"
  [ -n "$CTR" ] && [ -n "$ACC_PORT" ] || { printf '  %sHermes was set up but did not report its container.%s\n' "$R" "$Z"; exit 1; }
  export ACC_PORT ACC_PUBLISHED=1 ACC_HERMES_MADE=1
  ACC_CONTAINER_OK=1; _MADE_HERMES=1
  # a fresh Docker may still need sudo for this account
  docker ps >/dev/null 2>&1 || docker() { sudo docker "$@"; }
fi

# ---- no Hermes on a Mac: install it natively first ------------------------------------------------
# A Mac has no Docker, so Hermes goes in the way its own docs install it (payload/hermes-native.sh asks
# the same three things: AI model, Telegram bot token, Telegram user ID). Accordo then installs on
# this Mac like on any Mac that already had Hermes.
# a Mac where this installer put Hermes in last time but the model or Telegram step did not finish: continue there
_HN_RESUME=""
[ -z "$CTR" ] && [ -n "$_HOST_HERMES" ] && [ "$(uname -s 2>/dev/null)" = "Darwin" ] \
  && [ -f "${HERMES_HOME:-$HOME/.hermes}/.accordo-hermes-setup" ] && _HN_RESUME=1
if [ -z "$CTR" ] && { [ -z "$_HOST_HERMES" ] || [ -n "$_HN_RESUME" ]; } && [ "$(uname -s 2>/dev/null)" = "Darwin" ]; then
  if [ -n "$_HN_RESUME" ]; then
    printf '\n  %sHermes is on this Mac, but its setup did not finish last time.%s Continuing with your AI model.\n' "$B" "$Z"
  else
    printf '\n  %sThere is no Hermes on this Mac yet.%s Accordo runs on Hermes Agent (free, open source,\n' "$B" "$Z"
    printf '  by Nous Research). The installer can set it up for you first.\n'
    _go="y"
    if [ -z "${ACC_YES:-}" ] && { : </dev/tty; } 2>/dev/null; then
      read -r -p "  Install Hermes Agent now? [Y/n]: " _go </dev/tty || _go=""
    fi
    case "${_go:-y}" in [Nn]*) printf '\n  Nothing installed. Install Hermes yourself, then run this installer again.\n\n'; exit 0 ;; esac
  fi
  _HN_OUT="$(ACC_HN_RESUME="$_HN_RESUME" bash "$DIR/payload/hermes-native.sh")" || { printf '\n  %sHermes could not be set up (see above). Nothing of Accordo was installed and no install was used.%s\n\n' "$R" "$Z"; exit 1; }
  _HN_BIN="$(printf '%s\n' "$_HN_OUT" | sed -n 's/^HERMES=//p' | tail -1)"
  [ -n "$_HN_BIN" ] || { printf '  %sHermes was set up but did not report where it is.%s\n' "$R" "$Z"; exit 1; }
  export PATH="$(dirname "$_HN_BIN"):$PATH" ACC_HERMES_MADE=1
  _HOST_HERMES=1; _MADE_HERMES=1
fi

# a container that publishes the dashboard port on this server's 127.0.0.1 (one this installer made, on a
# re-run): the tunnel and the tailnet go through that port, not the container's own address
if [ -n "$CTR" ] && [ -z "${ACC_PUBLISHED:-}" ]; then
  _pub="$(docker port "$CTR" 2>/dev/null | grep -oE '127\.0\.0\.1:[0-9]+' | head -1 | cut -d: -f2)"
  [ -n "$_pub" ] && { ACC_PORT="${ACC_PORT:-$_pub}"; export ACC_PORT ACC_PUBLISHED=1; }
fi

if [ -n "$CTR" ]; then
  # the user Hermes runs as inside the container: whoever owns its data dir (uid 10000 on the
  # official image). Root via a plain docker exec would leave files the gateway cannot read.
  _CHH="$(docker exec "$CTR" sh -c 'printf %s "${HERMES_HOME:-/opt/data}"' 2>/dev/null || echo /opt/data)"
  _CUSER="$(docker exec "$CTR" sh -c "stat -c %U '$_CHH'" 2>/dev/null || echo hermes)"
  printf '  %sCopying the installer into %s (as %s, data at %s)...%s\n' "$DIM" "$CTR" "$_CUSER" "$_CHH" "$Z"
  docker cp "$TMP/body" "$CTR:/tmp/accordo-installer.tar.gz" >/dev/null 2>&1 \
    || { printf '  %sCould not copy the installer into the container.%s\n' "$R" "$Z"; exit 1; }
  docker cp "$DIR/.license" "$CTR:/tmp/accordo-installer.license" >/dev/null 2>&1 || true
  # docker cp keeps OUR uid on the files; in the container's sticky /tmp the Hermes user could
  # then neither move the licence stamp nor remove the package afterwards (found by the lane)
  docker exec "$CTR" chown "$_CUSER" /tmp/accordo-installer.tar.gz /tmp/accordo-installer.license >/dev/null 2>&1 || true
  # The installer's prompts read the terminal, so hand it ours (-it, stdin from /dev/tty).
  # Without a terminal (a fully piped run) stdin is /dev/null and ACC_YES answers: NEVER the
  # bootstrap's own stdin, which is this very script arriving from curl - docker exec -i would
  # swallow the rest of it.
  _CSCRIPT='rm -rf /tmp/accordo-installer && tar -xzf /tmp/accordo-installer.tar.gz -C /tmp \
      && mv -f /tmp/accordo-installer.license /tmp/accordo-installer/.license 2>/dev/null
    cd /tmp/accordo-installer && ACC_CONTAINER=1 bash install.sh; rc=$?
    rm -rf /tmp/accordo-installer /tmp/accordo-installer.tar.gz; exit $rc'
  # `-e /dev/tty` is true on every Linux box, even with no terminal attached (the device file
  # exists); only OPENING it tells the truth.
  # every ACC_* knob set on the VPS shell travels into the container (ACC_VPS_HOST, ACC_PORT,
  # ACC_NO_VOICE, ACC_FORCE_REINSTALL, ACC_TG_LINK...), or a re-run could never be steered
  # the tunnel the buyer is told to open goes through THIS server: name it for them, since from
  # inside the container its address is unknowable (ACC_VPS_HOST set by hand wins)
  [ -n "${ACC_VPS_HOST:-}" ] || ACC_VPS_HOST="$(id -un)@$( { hostname -I 2>/dev/null || true; } | awk '{print $1}')"
  case "$ACC_VPS_HOST" in *@) ACC_VPS_HOST="" ;; *) export ACC_VPS_HOST ;; esac
  _ENVARGS=()
  while IFS= read -r _kv; do _ENVARGS+=(-e "$_kv"); done < <(env | grep -E '^ACC_[A-Z_]+=' | grep -vE '^ACC_(LICENSE|SKIP_LICENSE|CONTAINER|TG_TOKEN|TG_USER|OPENROUTER_KEY|MINIMAX_KEY)=' || true)
  # the bootstrap validated the key above, so the installer inside skips its own check (not for a local test package)
  [ -n "${ACC_LOCAL_TARBALL:-}" ] || _ENVARGS+=(-e "ACC_SKIP_LICENSE=1")
  if { : </dev/tty; } 2>/dev/null; then
    docker exec -it -u "$_CUSER" "${_ENVARGS[@]}" "$CTR" bash -c "$_CSCRIPT" </dev/tty
  else
    docker exec -i -u "$_CUSER" -e ACC_YES=1 "${_ENVARGS[@]}" "$CTR" bash -c "$_CSCRIPT" </dev/null
  fi
  INSTALL_EXIT=$?
  docker exec "$CTR" rm -f /tmp/accordo-installer.tar.gz /tmp/accordo-installer.license >/dev/null 2>&1 || true
else
# ---- pick the installer for this operating system ---------------------------
# macOS ships bash 3.2 (2007, frozen because bash 4 is GPLv3) and lacks GNU tools like
# `timeout` and `grep -P`, and has launchd instead of systemd. It gets its own installer.
# The Linux install.sh is left exactly as tested.
#
# `uname -s` decides — Darwin on every Mac, Linux on every Linux — but we SHOW the answer
# and let the buyer correct it, so a wrong guess can never silently run the wrong one.
OS_NAME="$(uname -s 2>/dev/null || echo unknown)"
if [ "$OS_NAME" = "Darwin" ] && [ -f ./install.sh ]; then
  PICKED="macos"; PICKED_LABEL="macOS"
else
  PICKED="linux"; PICKED_LABEL="Linux"
fi

# Friendly name only — "Darwin" is macOS's internal kernel name and means nothing to a buyer.
printf '\n  %sDetected system:%s %s%s%s\n' "$DIM" "$Z" "$B" "$PICKED_LABEL" "$Z"

# Only ask when there is a terminal AND a choice to make. Piped/unattended runs keep the
# detected answer. ACC_OS=macos|linux overrides without prompting.
if [ -n "${ACC_OS:-}" ]; then
  case "$ACC_OS" in
    macos|Darwin|mac) PICKED="macos"; PICKED_LABEL="macOS" ;;
    linux|Linux)      PICKED="linux"; PICKED_LABEL="Linux" ;;
  esac
  printf '  %sACC_OS set — using %s.%s\n' "$DIM" "$PICKED_LABEL" "$Z"
elif [ -z "${ACC_YES:-}" ] && { : </dev/tty; } 2>/dev/null; then    # a terminal we can really open
  read -r -p "  Is that correct? [Y/n]: " OS_OK </dev/tty || OS_OK=""
  case "$OS_OK" in
    [Nn]*)
      printf '  Which are you on?  %s1%s) Linux   %s2%s) macOS\n' "$B" "$Z" "$B" "$Z"
      read -r -p "  Enter 1 or 2: " OS_PICK </dev/tty || OS_PICK=""
      case "$OS_PICK" in
        2) PICKED="macos"; PICKED_LABEL="macOS" ;;
        *) PICKED="linux"; PICKED_LABEL="Linux" ;;
      esac
      ;;
  esac
fi

if [ "$PICKED" = "macos" ] && [ -f ./install.sh ]; then
  INSTALLER="./install.sh"
else
  [ "$PICKED" = "macos" ] && printf '  %sNo macOS installer in this package — falling back to the standard one.%s\n' "$R" "$Z"
  INSTALLER="./install.sh"
fi
printf '  %sRunning the %s installer...%s\n' "$DIM" "$PICKED_LABEL" "$Z"

bash "$INSTALLER"
INSTALL_EXIT=$?
fi   # (host install)
# the container this installer made publishes the dashboard on this server's 127.0.0.1: put it on the
# owner's tailnet from here (inside the container there is no Tailscale)
if [ -n "${ACC_PUBLISHED:-}" ] && [ -n "${CTR:-}" ] && [ "${INSTALL_EXIT:-1}" = "0" ] && [ "${ACC_TAILNET:-y}" != "0" ] && command -v tailscale >/dev/null 2>&1 && tailscale status >/dev/null 2>&1; then
  _TP="${ACC_TS_PORT:-8453}"
  if tailscale serve --bg --https="$_TP" "http://127.0.0.1:$ACC_PORT" >/dev/null 2>&1 || sudo tailscale serve --bg --https="$_TP" "http://127.0.0.1:$ACC_PORT" >/dev/null 2>&1; then
    _TSN="$(tailscale status --json 2>/dev/null | python3 -c 'import json,sys;print(json.load(sys.stdin)["Self"]["DNSName"].rstrip("."))' 2>/dev/null)"
    _KEY="$(docker exec -u hermes "$CTR" sh -c "sed -n 's/^ACCORDO_TOKEN=//p' /opt/data/accordo/.accordo-secrets" 2>/dev/null)"
    printf '\n  %sOn your tailnet (your devices only), your one-tap link:%s\n  %shttps://%s:%s/?k=%s%s\n' "$B" "$Z" "$G" "$_TSN" "$_TP" "$_KEY" "$Z"
  fi
fi
set -e

if [ -n "${ACC_LOCAL_TARBALL:-}" ]; then
  [ "$INSTALL_EXIT" = "0" ] && printf '\n  %s✓ Installed (test run: no activation recorded).%s\n' "$G" "$Z"; exit "$INSTALL_EXIT"
elif [ "$INSTALL_EXIT" = "0" ]; then
  printf '\n  %sRecording activation...%s\n' "$DIM" "$Z"
  ACT_CODE="$(curl -sS -X POST "$WORKER_URL" \
    -H 'Content-Type: application/json' \
    -d "{\"license_key\":\"$KEY\",\"tutorial_slug\":\"$TUTORIAL_SLUG\",\"action\":\"activate\"}" \
    -o "$TMP/act" -w '%{http_code}' 2>/dev/null || echo 000)"
  if [ "$ACT_CODE" = "200" ]; then
    USED="$(grep -o '"used":[0-9]*' "$TMP/act" 2>/dev/null | cut -d: -f2 || true)"
    LIMIT="$(grep -o '"limit":[0-9]*' "$TMP/act" 2>/dev/null | cut -d: -f2 || true)"
    printf '  %s✓ Activation recorded (%s/%s installs used).%s\n' "$G" "${USED:-?}" "${LIMIT:-?}" "$Z"
  else
    printf '  %s⚠ Could not record activation — the install succeeded, but the count may not have updated.%s\n' "$R" "$Z"
  fi
else
  printf '\n  %s✗ Installation failed — no activation was recorded. Your install count was not affected.%s\n' "$R" "$Z"
  exit "$INSTALL_EXIT"
fi
