rhodawk-ai-devops-engine / entrypoint.sh
Architect8999's picture
feat: integrate camofox-browser anti-detection browser
95b8512 verified
Raw
History Blame Contribute Delete
4.19 kB
#!/usr/bin/env bash
# ─────────────────────────────────────────────────────────────────────
# Rhodawk runtime bootstrap.
#
# 1. Launch the camofox-browser anti-detection browser server on
# 127.0.0.1:9377 (used by the orchestrator via camofox_client.py).
# 2. Launch the OpenClaude headless gRPC daemon for the DigitalOcean
# Inference provider on :50051 (PRIMARY).
# 3. Launch the OpenClaude headless gRPC daemon for OpenRouter on
# :50052 (FALLBACK) β€” only if OPENROUTER_API_KEY is present.
# 4. Wait briefly for everything to bind, then hand control to app.py
# which talks to them over gRPC + HTTP.
# ─────────────────────────────────────────────────────────────────────
set -eo pipefail
OC_DIR=/opt/openclaude
CAMOFOX_DIR=/opt/camofox
LOG_DIR="${LOG_DIR:-/tmp}"
mkdir -p "${LOG_DIR}"
# ─── camofox-browser ─────────────────────────────────────────────────
# Anti-detection Firefox-fork browser server. Lazily downloads the
# Camoufox engine (~300MB) on first launch into the user's home dir,
# so the first start may take a minute. Subsequent starts are fast.
start_camofox() {
local entry="${CAMOFOX_DIR}/node_modules/@askjo/camofox-browser/server.js"
[[ -f "${entry}" ]] || entry="${CAMOFOX_DIR}/node_modules/camofox-browser/server.js"
if [[ ! -f "${entry}" ]]; then
echo "[entrypoint] camofox-browser not installed β€” skipping"
return 0
fi
echo "[entrypoint] starting camofox-browser on ${CAMOFOX_HOST:-127.0.0.1}:${CAMOFOX_PORT:-9377}"
(
cd "${CAMOFOX_DIR}"
PORT="${CAMOFOX_PORT:-9377}" \
HOST="${CAMOFOX_HOST:-127.0.0.1}" \
CAMOFOX_HEADLESS="${CAMOFOX_HEADLESS:-virtual}" \
CAMOFOX_PROFILE_DIR="${CAMOFOX_PROFILE_DIR:-/data/camofox/profiles}" \
CAMOFOX_COOKIES_DIR="${CAMOFOX_COOKIES_DIR:-/data/camofox/cookies}" \
CAMOFOX_API_KEY="${CAMOFOX_API_KEY:-}" \
PROXY_HOST="${PROXY_HOST:-}" \
PROXY_PORT="${PROXY_PORT:-}" \
PROXY_USERNAME="${PROXY_USERNAME:-}" \
PROXY_PASSWORD="${PROXY_PASSWORD:-}" \
node "${entry}" \
> "${LOG_DIR}/camofox.log" 2>&1 &
echo $! > "${LOG_DIR}/camofox.pid"
)
}
start_daemon() {
local label=$1 port=$2 base_url=$3 api_key=$4 model=$5
if [[ -z "${api_key}" ]]; then
echo "[entrypoint] skipping ${label} daemon β€” no API key"
return 0
fi
echo "[entrypoint] starting OpenClaude ${label} daemon on :${port}"
(
cd "${OC_DIR}"
CLAUDE_CODE_USE_OPENAI=1 \
OPENAI_API_KEY="${api_key}" \
OPENAI_BASE_URL="${base_url}" \
OPENAI_MODEL="${model}" \
GRPC_PORT="${port}" \
GRPC_HOST=0.0.0.0 \
OPENCLAUDE_AUTO_APPROVE=1 \
MCP_RUNTIME_CONFIG="${MCP_RUNTIME_CONFIG:-/tmp/mcp_runtime.json}" \
bun run scripts/start-grpc.ts \
> "${LOG_DIR}/openclaude-${label}.log" 2>&1 &
echo $! > "${LOG_DIR}/openclaude-${label}.pid"
)
}
# camofox first β€” slowest to bind because of the lazy engine download.
start_camofox
# DigitalOcean Inference (PRIMARY)
DO_BASE="${DO_INFERENCE_BASE_URL:-https://inference.do-ai.run/v1}"
DO_MODEL="${DO_INFERENCE_MODEL:-llama3.3-70b-instruct}"
start_daemon "do" 50051 "${DO_BASE}" \
"${DO_INFERENCE_API_KEY:-${DIGITALOCEAN_INFERENCE_KEY:-}}" \
"${DO_MODEL}"
# OpenRouter (FALLBACK)
OR_BASE="${OPENROUTER_BASE_URL:-https://openrouter.ai/api/v1}"
OR_MODEL="${OPENROUTER_MODEL:-qwen/qwen-2.5-coder-32b-instruct:free}"
start_daemon "or" 50052 "${OR_BASE}" "${OPENROUTER_API_KEY:-}" "${OR_MODEL}"
# Brief settle window so the first healing call doesn't race the binder.
# The Python client also has wait_ready() so this is just a friendly nudge.
sleep 2
echo "[entrypoint] launching Rhodawk orchestrator…"
exec python -u app.py