#!/usr/bin/env sh
# VCN #41 Bare Metal - wire a coding agent to a local open-weights model.
# Doctor first, then wire. Idempotent and safe: it never deletes anything and
# never installs the Ollama server for you (it tells you the one line to run).
#
# Run:   curl -fsSL https://vcn-41-bare-metal.vercel.app/wire.sh | sh
# Options (append after -s --):   curl -fsSL https://vcn-41-bare-metal.vercel.app/wire.sh | sh -s -- --check
#   --check         doctor only, change nothing
#   --model <tag>   coder model: 0.5b 1.5b 3b 7b 14b 32b (default 7b = qwen2.5-coder:7b)
#   --nebius        wire the Nebius Token Factory fallback instead of localhost
#   -y              assume yes, no prompts
#
# There are NO Wi-Fi credentials in this file. ASCII only.

set -u

MODEL="qwen2.5-coder:7b"
OLLAMA_HOST="http://127.0.0.1:11434"
NEBIUS_URL="https://api.tokenfactory.nebius.com/v1/"
CHECK=0; NEBIUS=0; YES=0

while [ $# -gt 0 ]; do
  case "$1" in
    --check) CHECK=1 ;;
    --nebius) NEBIUS=1 ;;
    --model) shift; [ $# -gt 0 ] && MODEL="$1" ;;
    -y|--yes) YES=1 ;;
    -h|--help) CHECK=1 ;;
    *) : ;;
  esac
  shift
done
case "$MODEL" in
  0.5b|1.5b|3b|7b|14b|32b) MODEL="qwen2.5-coder:$MODEL" ;;
esac

say() { printf "%s\n" "$*"; }
hr()  { say "------------------------------------------------------------"; }

# Read a prompt from the controlling terminal even when stdin is the curl pipe.
# No terminal available: return empty (print-only mode), never hang.
ask() {
  if [ "$YES" = "1" ]; then say "y"; return 0; fi
  if [ -r /dev/tty ]; then
    printf "%s " "$1" > /dev/tty
    a=""; read a < /dev/tty 2>/dev/null || a=""
    say "$a"
  else
    say ""
  fi
}
have_tty() { [ -r /dev/tty ] || [ "$YES" = "1" ]; }

OS="$(uname -s 2>/dev/null || echo unknown)"
ARCH="$(uname -m 2>/dev/null || echo unknown)"
IS_MAC=0; IS_CROS=0
[ "$OS" = "Darwin" ] && IS_MAC=1
if [ -d /opt/google/cros-containers ] || grep -qi 'penguin\|crostini' /proc/version 2>/dev/null; then IS_CROS=1; fi

hr
say "VCN #41 Bare Metal - wiring a coding agent to an open-weights model"
MODE="local"; [ "$NEBIUS" = "1" ] && MODE="nebius fallback"
NOTE=""; [ "$CHECK" = "1" ] && NOTE="  [--check: doctor only]"
say "plan: OS $OS ($ARCH) . model $MODEL . mode $MODE$NOTE"
hr

# ---- Nebius fallback path (no local server needed) ----
if [ "$NEBIUS" = "1" ]; then
  say "Nebius Token Factory is OpenAI-compatible. Only the base URL and key change."
  say "No key yet? Sign up at https://dev.nebius.com/builders for \$50 free Token Factory credit (about 5 min)."
  KEY=""
  if [ "$CHECK" = "0" ]; then KEY="$(ask 'paste your Token Factory API key (or press Enter to leave a placeholder):')"; fi
  [ -z "$KEY" ] && KEY="<your-token-factory-key>"
  say ""
  say "copy-paste to wire it (bash/zsh):"
  say "  export OPENAI_API_BASE=$NEBIUS_URL"
  say "  export OPENAI_API_KEY=$KEY"
  say "  aider --model openai/<nebius-coder-model-id>   # browse the catalog at studio.nebius.com"
  say ""
  say "Cline: the LAB 2 screen, swap Base URL to $NEBIUS_URL"
  if [ "$CHECK" = "0" ] && [ "$KEY" != "<your-token-factory-key>" ] && command -v aider >/dev/null 2>&1 && have_tty; then
    ans="$(ask 'launch aider against Nebius now? [y/N]')"
    case "$ans" in y|Y|yes) export OPENAI_API_BASE="$NEBIUS_URL"; export OPENAI_API_KEY="$KEY"; say "launching aider..."; exec aider --model "openai/Qwen/Qwen2.5-Coder-32B-Instruct" < /dev/tty ;; esac
  fi
  hr
  say "trust gate: nothing is local on this path. It runs on Nebius credits, still open-weights."
  exit 0
fi

# ---- Local path: doctor ----
# 1. ollama installed?
if ! command -v ollama >/dev/null 2>&1; then
  say "x  ollama is not installed."
  if [ "$IS_MAC" = "1" ]; then
    say "   install it, then re-run this:  brew install ollama   (or the app from https://ollama.com)"
  elif [ "$IS_CROS" = "1" ]; then
    say "   Chromebook: enable Linux (Settings > About ChromeOS > Developers), then in Crostini:"
    say "   curl -fsSL https://ollama.com/install.sh | sh"
  else
    say "   install it, then re-run this:  curl -fsSL https://ollama.com/install.sh | sh"
  fi
  exit 1
fi
say "ok  ollama installed"

# 2. server alive?
if ! curl -fsS "$OLLAMA_HOST/v1/models" >/dev/null 2>&1; then
  say "x  the ollama server is not answering at $OLLAMA_HOST"
  say "   start it in another terminal:  ollama serve"
  [ "$IS_MAC" = "1" ] && say "   (macOS: if that says 'address already in use', the app already serves it, you are fine)"
  exit 1
fi
say "ok  server alive at $OLLAMA_HOST/v1"

# 3. coder model present?
if ! ollama list 2>/dev/null | grep -Fq "$MODEL"; then
  say "-  model $MODEL is not pulled yet."
  if [ "$CHECK" = "1" ]; then
    say "   (--check) would run:  ollama pull $MODEL"
  else
    ans="$(ask "pull $MODEL now? it downloads a few GB (7b is ~4.7GB) [y/N]")"
    case "$ans" in
      y|Y|yes) say "   pulling $MODEL ..."; ollama pull "$MODEL" || { say "   pull failed, try a smaller tag: --model 3b"; exit 1; } ;;
      *) say "   skipped. pull it yourself with:  ollama pull $MODEL   (or a smaller one: 0.5b 1.5b 3b)"; ;;
    esac
  fi
else
  say "ok  model $MODEL present"
fi

# 4. smoke test one /v1 call
say "-  smoke test: one /v1/chat/completions call ..."
RESP="$(curl -fsS "$OLLAMA_HOST/v1/chat/completions" -H "Content-Type: application/json" -d "{\"model\":\"$MODEL\",\"messages\":[{\"role\":\"user\",\"content\":\"say hi in one word\"}]}" 2>/dev/null || echo "")"
REPLY="$(printf "%s" "$RESP" | sed -n 's/.*"content":"\([^"]*\)".*/\1/p' | head -1)"
if [ -n "$REPLY" ]; then say "ok  model replied: $REPLY"; else say "-  no reply yet (model may still be loading, or not pulled); the wiring below is still correct"; fi

if [ "$CHECK" = "1" ]; then
  hr
  say "doctor done (--check made no changes). To wire + launch, re-run without --check."
  exit 0
fi

# 5. aider installed?
if ! command -v aider >/dev/null 2>&1; then
  say "-  aider is not installed."
  ans="$(ask 'install aider now with the official installer (curl -LsSf https://aider.chat/install.sh | sh)? [y/N]')"
  case "$ans" in
    y|Y|yes) say "   installing aider ..."; curl -LsSf https://aider.chat/install.sh | sh || say "   installer had trouble; see https://aider.chat/docs/install.html" ;;
    *) say "   skipped. install it later:  curl -LsSf https://aider.chat/install.sh | sh" ;;
  esac
else
  say "ok  aider installed"
fi

# 6. print the exact launch block (exports do NOT survive a piped shell, so copy this)
hr
say "wire + launch (copy-paste; the exports below do not survive this piped script):"
say "  export OLLAMA_API_BASE=$OLLAMA_HOST"
say "  aider --model ollama_chat/$MODEL"
hr
say "Cline (VS Code, cannot be automated): set these four values"
say "  Provider: OpenAI Compatible"
say "  Base URL: $OLLAMA_HOST/v1"
say "  API Key:  local   (any value)"
say "  Model ID: $MODEL"
say "Claude Code (optional; native to Ollama, no proxy - use a FRESH terminal so you"
say "do not clobber a session wired to z.ai or your real Anthropic login):"
say "  ANTHROPIC_AUTH_TOKEN=ollama ANTHROPIC_BASE_URL=$OLLAMA_HOST ANTHROPIC_API_KEY= claude --model $MODEL"
say "  (one-command alt: ollama launch claude --model $MODEL)"
say "  revert to hosted Claude Code: the vars above are one-shot; any new terminal is already reverted"
hr

# 7. offer to launch aider now (exec inherits the env we set here; read from the tty)
if command -v aider >/dev/null 2>&1 && have_tty; then
  ans="$(ask 'launch aider now against your local model? [y/N]')"
  case "$ans" in
    y|Y|yes) export OLLAMA_API_BASE="$OLLAMA_HOST"; say "launching aider... (watch your 'ollama serve' logs, that is your proof it is local)"; exec aider --model "ollama_chat/$MODEL" < /dev/tty ;;
  esac
fi

say "trust gate: watch the 'ollama serve' logs while the agent works. Traffic there = it is local."
