# The image `gmlx launch --container` builds for a client that sets neither
# image: nor build:. Each client installs in a stage named after it, and
# the CLIENT build argument picks the stage that the last stage starts
# from, so a build runs only the stages of that one client. EXTRA_PACKAGES
# carries the launch config's packages: list. gmlx tags the result
# gmlx.invalid/launch-<client>:<hash> and :base. The hash covers the lines
# outside the client stages and that client's own stage, so moving one
# client's pin rebuilds only that client. A custom agent with runtime:
# python builds the runtime-python stage the same way, which adds uv to the
# python stage, and uv installs the agent's dependencies at run time.
# Elia and Open WebUI need a Python older than the one Debian ships, so
# their stages start from python-3.12, which makes /opt/venv again with the
# Python 3.12 that the uv of runtime-python downloads. uv checks that
# download against the sha256 in its own release, so the uv pin also fixes
# that Python, and a new uv pin, not a Debian update, brings its security
# fixes.
#
# The layers go from the most shared to the least: the common packages are
# one layer for every client, the Python clients share one more, and a
# packages: change rebuilds only the last layer, never the client install.
#
# The base image is pinned by digest, each client by the VERSION at the top
# of its stage, and each release download by that version and its sha256,
# so a build installs the versions gmlx names. The npm and pip dependencies
# of a client resolve at build time. The Debian packages are not pinned:
# they come from the Debian release that the base image digest fixes, at
# their current security updates. The common stage also upgrades the
# packages of the base image, so a build without its cache, such as
# --rebuild, brings their security updates too. To move a pin, change the
# version and its sha256 together: the digest of a GitHub release asset is
# on its release page.
ARG CLIENT=common
ARG PIP_VERSION=26.2.1

FROM docker.io/library/node:24-trixie-slim@sha256:8ec5d7557396cfe32d21c3f9c13072355ceab22b584578ca4bb28af31120cffe AS common
RUN set -eux; \
    apt-get update; \
    apt-get upgrade -y; \
    apt-get install -y --no-install-recommends \
        git ripgrep ca-certificates curl openssh-client less procps bzip2; \
    rm -rf /var/lib/apt/lists/*

FROM common AS python
ARG PIP_VERSION
RUN set -eux; \
    apt-get update; \
    apt-get install -y --no-install-recommends python3 python3-venv; \
    rm -rf /var/lib/apt/lists/*; \
    python3 -m venv /opt/venv; \
    /opt/venv/bin/pip install --no-cache-dir pip==$PIP_VERSION

FROM python AS runtime-python
ARG VERSION=0.12.22
RUN set -eux; \
    curl -fsSL -o /tmp/uv.tar.gz \
        "https://github.com/astral-sh/uv/releases/download/$VERSION/uv-aarch64-unknown-linux-gnu.tar.gz"; \
    echo "6f66a14e8239871fb477f9746c941fedfa77e8fe28a8bc7c07e1dc7f53a66712  /tmp/uv.tar.gz" \
        | sha256sum -c -; \
    tar -xzf /tmp/uv.tar.gz -C /usr/local/bin --strip-components=1 --no-same-owner \
        uv-aarch64-unknown-linux-gnu/uv uv-aarch64-unknown-linux-gnu/uvx; \
    rm /tmp/uv.tar.gz

FROM common AS opencode
ARG VERSION=1.18.32
RUN npm install -g opencode-ai@$VERSION && npm cache clean --force

FROM common AS claude-code
ARG VERSION=2.1.283
RUN npm install -g @anthropic-ai/claude-code@$VERSION && npm cache clean --force

FROM common AS pi
ARG VERSION=1.0.1
RUN npm install -g @earendil-works/pi-coding-agent@$VERSION && npm cache clean --force

FROM common AS dsh
ARG VERSION=0.2.0-rc.2
RUN npm install -g @deepseek-ai/dsh@$VERSION && npm cache clean --force

FROM common AS omp
ARG VERSION=18.4.0
RUN set -eux; \
    curl -fsSL -o /usr/local/bin/omp \
        "https://github.com/can1357/oh-my-pi/releases/download/v$VERSION/omp-linux-arm64"; \
    echo "8ade0ab092b569c73a3be3ce7c5f74f8107d4528b85fd9767ed68dc029b062e1  /usr/local/bin/omp" \
        | sha256sum -c -; \
    chmod 755 /usr/local/bin/omp

FROM common AS goose
ARG VERSION=1.52.0
RUN set -eux; \
    curl -fsSL -o /tmp/goose.tar.bz2 \
        "https://github.com/aaif-goose/goose/releases/download/v$VERSION/goose-aarch64-unknown-linux-musl.tar.bz2"; \
    echo "ff8f21ac5740c4bf45905dd310b331037f0fe8bdf148c468945ba3ac14b6089a  /tmp/goose.tar.bz2" \
        | sha256sum -c -; \
    tar -xjf /tmp/goose.tar.bz2 -C /usr/local/bin ./goose; \
    rm /tmp/goose.tar.bz2

FROM common AS aichat
ARG VERSION=0.30.0
RUN set -eux; \
    curl -fsSL -o /tmp/aichat.tar.gz \
        "https://github.com/sigoden/aichat/releases/download/v$VERSION/aichat-v$VERSION-aarch64-unknown-linux-musl.tar.gz"; \
    echo "eb1cd0948569404c5d9d01c10b32b902e11f8231073315456454dec246bdf26e  /tmp/aichat.tar.gz" \
        | sha256sum -c -; \
    tar -xzf /tmp/aichat.tar.gz -C /usr/local/bin aichat; \
    rm /tmp/aichat.tar.gz

FROM python AS hermes
ARG VERSION=0.19.0
RUN /opt/venv/bin/pip install --no-cache-dir "hermes-agent[mcp]==$VERSION"

FROM runtime-python AS python-3.12
ARG PIP_VERSION
RUN set -eux; \
    export UV_NO_CACHE=1 UV_PYTHON_INSTALL_DIR=/opt/python; \
    uv venv --clear --python 3.12 /opt/venv; \
    uv pip install --python /opt/venv/bin/python pip==$PIP_VERSION

FROM python-3.12 AS elia
ARG VERSION=1.10.0
RUN /opt/venv/bin/pip install --no-cache-dir elia-chat==$VERSION

FROM python-3.12 AS open-webui
ARG VERSION=0.11.4
RUN set -eux; \
    /opt/venv/bin/pip install --no-cache-dir torch==2.14.0 \
        --index-url https://download.pytorch.org/whl/cpu; \
    /opt/venv/bin/pip install --no-cache-dir open-webui==$VERSION

FROM ${CLIENT}
ENV PATH=/opt/venv/bin:$PATH
ARG EXTRA_PACKAGES=""
RUN set -eux; \
    if [ -n "$EXTRA_PACKAGES" ]; then \
        apt-get update; \
        apt-get install -y --no-install-recommends $EXTRA_PACKAGES; \
        rm -rf /var/lib/apt/lists/*; \
    fi
