#!/bin/sh
# raxol-code — interactive coding agent TUI (the axol face) from any dir.
#
#   raxol-code
#   raxol-code --continue            # resume the most recent session
#   raxol-code --resume sess-123-4   # resume a specific session
#   raxol-code --sessions            # list saved sessions and exit
#   raxol-code --harness anthropic --model claude-sonnet-5
#   raxol-code --ascii               # ASCII-only face for legacy terminals
#
# mix raxol.code lives in the raxol_agent package. Main raxol does not
# depend on raxol_agent (the dep runs the other way), so `mix raxol.code`
# at the repo root can't find the task. This shim runs it from the package
# while keeping the CALLER's cwd as the agent's working directory (the
# fs/shell tools are scoped to it via RAXOL_CLI_CWD). It execs mix so the
# full-screen UI inherits this shell's controlling terminal -- the driver
# gates on isatty(stdout), which System.cmd-style pipes would fail.
# Requires deps compiled once: (cd packages/raxol_agent && mix deps.get)

set -e

# shellcheck disable=SC1007  # CDPATH= is an intentional env prefix for a safe cd
SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd)
REPO_ROOT=$(dirname -- "$SCRIPT_DIR")
CALLER_CWD=$(pwd)

cd "$REPO_ROOT/packages/raxol_agent"

# Compile quietly first so build chatter doesn't flash before the UI takes
# the alternate screen. MAKEFLAGS=-s silences the termbox2 NIF make check.
#
# `< /dev/null` detaches the compile step from stdin: Mix boots a full VM whose
# `prim_tty` owns fd 0 and reads ahead, so keystrokes typed while this step
# runs are consumed and discarded here instead of reaching the UI (the defect
# fixed in bin/raxol-acp).
MAKEFLAGS=-s mix compile >/dev/null 2>&1 </dev/null || {
  echo "raxol-code: compile failed; run (cd packages/raxol_agent && mix compile) for details" >&2
  exit 70
}

# RAXOL_CLI_CWD scopes the fs/shell tools to where the user invoked this.
# exec hands mix this shell's terminal so isatty(stdout) holds and the TUI
# initializes.
#
# Precompiling is not sufficient on its own: `mix <task>` must load the project
# to find the task module, and that loadpaths pass announces dep work on stdout
# ("==> raxol_terminal", "Compiling N files (.ex)") before the task can install
# a quiet shell -- elixir_make's NIF check reads as stale on every invocation,
# so it is not a first-run-only cost. That flashed before the alternate screen,
# and lands in the middle of the output of the headless paths (--help,
# --sessions, --replay). `mix run` is built into Mix, so it parses before any
# project loadpaths and honours --no-deps-check; the task still runs
# `app.start` itself.
#
# No -noinput here, unlike bin/raxol-acp: this process's stdio IS the terminal
# the UI draws on, and the driver needs fd 0 for keys. Verified interactively
# through a pty -- the TUI initializes and takes the alternate screen under
# `mix run` exactly as it did under `mix raxol.code`.
exec env \
  MAKEFLAGS=-s \
  RAXOL_CLI_CWD="$CALLER_CWD" \
  mix run \
    --no-start \
    --no-compile \
    --no-deps-check \
    --no-archives-check \
    --no-elixir-version-check \
    -e 'Mix.Tasks.Raxol.Code.run(System.argv())' \
    -- "$@"
