# Timmy self-hosted vision worker (issue #15).
#
# Reproducible by construction: the llama.cpp revision and both model hashes are pinned here and in
# deploy/worker/receipts.json, and tests/worker-container.test.js fails if either drifts from
# scripts/bootstrap_selfhost_smolvlm.sh on the host.
#
# The weights are deliberately NOT baked into the image. They are mounted read-only at /models and
# hash-verified against the pinned receipts by the entrypoint before the server starts.

ARG LLAMA_CPP_COMMIT=6d05498314db1b57f81c271080018aa2d0b89be9
ARG MODEL_SHA256=0cf76814555b8665149075b74ab6b5c1d428ea1d3d01c1918c12012e8d7c9f58
ARG MMPROJ_SHA256=ae07ea1facd07dd3230c4483b63e8cda96c6944ad2481f33d531f79e892dd024

# Digest-pinned bases, recorded in deploy/worker/receipts.json. A tag alone can be repointed, so
# the digest is what makes this build reproducible.
FROM nvidia/cuda:12.4.1-devel-ubuntu22.04@sha256:da6791294b0b04d7e65d87b7451d6f2390b4d36225ab0701ee7dfec5769829f5 AS build

ARG LLAMA_CPP_COMMIT
RUN apt-get update \
 && apt-get install --yes --no-install-recommends git ca-certificates cmake build-essential \
 && rm -rf /var/lib/apt/lists/*

WORKDIR /src
RUN git init llama.cpp \
 && cd llama.cpp \
 && git remote add origin https://github.com/ggml-org/llama.cpp \
 && git fetch --depth 1 origin "${LLAMA_CPP_COMMIT}" \
 && git checkout --detach FETCH_HEAD
RUN cmake -S llama.cpp -B llama.cpp/build -DCMAKE_BUILD_TYPE=Release -DLLAMA_CURL=OFF -DGGML_CUDA=ON \
 && cmake --build llama.cpp/build --parallel "$(nproc)" --target llama-server

FROM nvidia/cuda:12.4.1-runtime-ubuntu22.04@sha256:517da2300c184c9999ec203c2665244bdebd3578d12fcc7065e83667932643d9 AS runtime

ARG MODEL_SHA256
ARG MMPROJ_SHA256

RUN apt-get update \
 && apt-get install --yes --no-install-recommends curl ca-certificates \
 && rm -rf /var/lib/apt/lists/* \
 && mkdir -p /models

COPY --from=build /src/llama.cpp/build/bin/ /usr/local/bin/
COPY deploy/worker/entrypoint.sh /usr/local/bin/timmy-worker-entrypoint
COPY scripts/worker_ready.sh /usr/local/bin/timmy-worker-ready
RUN chmod 0755 /usr/local/bin/timmy-worker-entrypoint /usr/local/bin/timmy-worker-ready && ldconfig

# No credential is configured: the worker is a private service the app reaches over host loopback.
# 0.0.0.0 here is the address inside this container's own network namespace; the run recipe decides
# exposure and publishes on 127.0.0.1 only.
ENV TIMMY_MODEL_DIR=/models \
    TIMMY_MODEL_FILE=/models/SmolVLM2-2.2B-Instruct-Q4_K_M.gguf \
    TIMMY_MMPROJ_FILE=/models/mmproj-SmolVLM2-2.2B-Instruct-Q8_0.gguf \
    TIMMY_MODEL_SHA256=${MODEL_SHA256} \
    TIMMY_MMPROJ_SHA256=${MMPROJ_SHA256} \
    TIMMY_MODEL_ALIAS=SmolVLM2-2.2B-Instruct \
    TIMMY_MODEL_HOST=0.0.0.0 \
    TIMMY_MODEL_PORT=8080

USER 10001:10001
EXPOSE 8080

# Health is the post-load gate: the worker is not healthy until the pinned model is being served,
# so an orchestrator cannot route to a worker that cannot answer. start-period covers a cold load.
HEALTHCHECK --interval=30s --timeout=5s --start-period=600s --retries=3 \
  CMD ["/usr/local/bin/timmy-worker-ready", "--host", "127.0.0.1", "--port", "8080", "--alias", "SmolVLM2-2.2B-Instruct"]

ENTRYPOINT ["/usr/local/bin/timmy-worker-entrypoint"]
