#!/usr/bin/env bash # Serve the router stack. Used by launchd (and fine to run manually). # Assumes ./.venv is already set up by start.sh. No pip here (works offline at boot). set -uo pipefail cd "$(dirname "$0")" export PATH="/opt/homebrew/bin:/usr/bin:/bin:/usr/sbin:/sbin:${PATH:-}" # clear any stale instances via recorded PIDs (never pattern-match — that can # match unrelated processes, including a shell that merely mentions "router.py") for pf in .litellm.pid .router.pid; do [ -f "$pf" ] && kill "$(cat "$pf" 2>/dev/null)" 2>/dev/null || true done sleep 1 export OLLAMA_KEEP_ALIVE="${OLLAMA_KEEP_ALIVE:-30m}" curl -s http://127.0.0.1:11434/api/generate \ -d '{"model":"qwen3:8b","prompt":"ok","stream":false,"keep_alive":-1}' >/dev/null 2>&1 || true # optional auth: create a file .apikey with a token to require Bearer auth [ -f .apikey ] && export ROUTER_API_KEY="$(cat .apikey)" # dedicated famapp key: any request with this Bearer token is forced onto uncensored models [ -f .uncensored_key ] && export ROUTER_UNCENSORED_KEY="$(cat .uncensored_key)" # LiteLLM backend (internal only) .venv/bin/litellm --config litellm.config.yaml --host 127.0.0.1 --port 4000 > litellm.log 2>&1 & LITELLM_PID=$!; echo "$LITELLM_PID" > .litellm.pid trap 'kill $LITELLM_PID 2>/dev/null || true; rm -f .router.pid' EXIT INT TERM for i in $(seq 1 60); do curl -sf http://127.0.0.1:4000/health/liveliness >/dev/null 2>&1 && break; sleep 2 done # Router (network-facing). Backgrounded with recorded PID, then waited on so launchd # tracks run.sh and the trap tears down LiteLLM when the router exits. export ROUTER_UPSTREAM="http://127.0.0.1:4000/v1" export ROUTER_HOST="0.0.0.0" .venv/bin/python router.py & ROUTER_PID=$!; echo "$ROUTER_PID" > .router.pid wait $ROUTER_PID