# syntax=docker/dockerfile:1.7
# Nemotron-3.5-Bolt-74B-A9B-24GB serving image (1x DGX Spark).
#
# The model card's Quick Start pins the STOCK vLLM nightly at commit
# 77154ca6116ae34cbfe314beef1016bde9b63989 (2026-10-14) — the first build
# that registers LiLiCorrDraftModel (the DFlash LiLiCorr speculator) and the
# ultra_v3 reasoning parser. eugr/spark-vllm-b12x is a DIFFERENT vLLM fork
# (commit 8244d1c44) that does NOT carry those, so it cannot serve Bolt with
# the card's flags. This wrapper reproduces the card exactly: the card's
# nightly base + `pip install b12x` + `vllm download-kernels`, baked once so
# every serve is reproducible and needs no runtime pip/network.
#
# Pinned by arm64 digest (nightly tags expire); see versions.env.

ARG BASE_IMAGE
FROM ${BASE_IMAGE}

ARG B12X_VERSION

# The card's runtime setup, baked: b12x wheel + pre-downloaded vLLM kernels.
# B12X_CACHE_DIR keeps the JIT-compiled native + autotuned kernels per node
# (the recipe bind-mounts a host dir there, like the other JIT caches).
ENV B12X_CACHE_DIR=/root/.cache/b12x

# The card's ultra_v3 reasoning-parser plugin (shipped in the model repo).
# Baked so the serve needs no network; referenced by absolute path from the
# recipe (--reasoning-parser-plugin /opt/ultra_v3_reasoning_parser.py).
RUN set -eux; \
    curl -fsSL -o /opt/ultra_v3_reasoning_parser.py \
      "https://huggingface.co/nvidia/NVIDIA-Nemotron-3.5-Bolt-74B-A9B-24GB/resolve/main/ultra_v3_reasoning_parser.py"; \
    test -s /opt/ultra_v3_reasoning_parser.py

RUN set -eux; \
    pip install --no-cache-dir "b12x==${B12X_VERSION}"; \
    python3 -c "import b12x; print('b12x import OK')"; \
    vllm download-kernels || echo "vllm download-kernels: nothing to fetch / already present"
# NOTE: we do NOT pre-build the b12x native here. It links -lcuda (the CUDA
# *driver* lib), which the nvidia container runtime only mounts at RUNTIME
# (--gpus all) — it is absent in the build image, so a build-time `load()`
# fails with `ld: cannot find -lcuda`. b12x JIT-builds the native on the first
# serve instead (libcuda present then); B12X_CACHE_DIR persists it per node.
