# syntax=docker/dockerfile:1.7
# mimo26-spark-vllm: thin FROM wrapper over the r39 b12x vLLM image that
# (1) teaches vLLM's eagle3 aux-hidden-state hook to resolve the interface
# on the inner language model when the outer model is a multimodal wrapper
# (MiMoV2OmniForCausalLM), and (2) makes the DFlash MXFP8 guards tolerate a
# vLLM build without ModelOptMxFp8LinearMethod (r39 predates that class).
# No kernel changes.
#
# Why (2026-09-28): MiMo-V2.6-Flash-MOPD resolves to the Omni architecture
# because the checkpoint ships visual/audio encoders. For method=dflash the
# GPU model runner flips use_aux_hidden_state_outputs=True and then
# set_eagle3_aux_hidden_state_layers() isinstance-checks SupportsEagle3 on
# the OUTER wrapper — which never implements it — and dies with "Model does
# not support EAGLE3 interface" right after weight loading. Everything that
# actually carries aux state (MiMoV2Model + EagleModelMixin) is one level in,
# and _inner_decoder() already knows how to find it.
#
# The patcher is anchor-based and refuses to run against unexpected sources
# (see patches/eagle3-omni-inner.py), so the build FAILS LOUDLY if the base
# vLLM ever restructures that function instead of silently no-oping.

ARG BASE_IMAGE
FROM ${BASE_IMAGE}

COPY patches/eagle3-omni-inner.py /opt/sm121/patches/eagle3-omni-inner.py
COPY patches/dflash-mxfp8-import-optional.py /opt/sm121/patches/dflash-mxfp8-import-optional.py

RUN set -eux; \
    python3 /opt/sm121/patches/eagle3-omni-inner.py --apply; \
    # Fail the build if the patched module no longer imports or the hook
    # regressed to raising on a wrapper-like model.
    python3 /opt/sm121/patches/eagle3-omni-inner.py --check; \
    python3 -c "import vllm.v1.worker.gpu.spec_decode.eagle.eagle3_utils as m; \
assert 'get_language_model' in open(m.__file__).read(), 'patch vanished'"; \
    # DFlash MXFP8 guards must tolerate a vLLM without ModelOptMxFp8LinearMethod.
    python3 /opt/sm121/patches/dflash-mxfp8-import-optional.py --apply; \
    python3 /opt/sm121/patches/dflash-mxfp8-import-optional.py --check; \
    # vLLM's import-time INFO logs land on stdout — grep the actual path line.
    SRC="$(python3 -c 'import vllm, os; print(vllm.__path__[0])' 2>/dev/null | grep '^/' | tail -1)"; \
    python3 -m py_compile \
      "$SRC/v1/worker/gpu/spec_decode/eagle/eagle3_utils.py" \
      "$SRC/model_executor/models/qwen3_dflash.py"; \
    find /usr/local/lib/python3.12/dist-packages/vllm -name '__pycache__' -type d -prune -exec rm -rf {} + 2>/dev/null || true
