# ── DeepSeek Harness — 运行时拉取最新版镜像 ──────────────────────────────────
# 镜像只装运行时工具链（Node/Python/gcc/pnpm/Rust 引导），不把 dsh 钉死在
# 构建层。容器每次启动由 docker/entrypoint.sh 从 npm 安装
# @deepseek-ai/dsh@latest（可用 DSH_DIST_TAG / DSH_NPM_REGISTRY 覆盖），
# 安装失败直接退出，不回退到镜像内置版本。
# 构建不再需要本地 dist/ pack 产物。
#
# npm registry / apt 源可通过 --build-arg 覆盖；默认走国内镜像
# （本机/国内构建环境通常无法直连官方源）。
ARG NPM_REGISTRY=https://registry.npmmirror.com
# Debian 软件源可通过 --build-arg APT_MIRROR=... 覆盖；默认走清华镜像
# （deb.debian.org 在国内网络极慢）。
ARG APT_MIRROR=mirrors.tuna.tsinghua.edu.cn
# 基础镜像：默认 ACR 上的 node（由 docker.io/library/node:24.19.0-bookworm-slim 同步）
ARG BASE_IMAGE=registry.cn-hangzhou.aliyuncs.com/skymirror/node:24.19.0-bookworm-slim

FROM ${BASE_IMAGE}
ARG NPM_REGISTRY
ARG APT_MIRROR
ARG TARGETARCH

ENV NPM_CONFIG_REGISTRY=${NPM_REGISTRY} \
    COREPACK_NPM_REGISTRY=${NPM_REGISTRY} \
    NODEJS_ORG_MIRROR=https://npmmirror.com/mirrors/node \
    npm_config_userconfig=/home/dsh/.dsh/.npmrc

# 切换到国内 Debian 镜像（bookworm 的 deb822 源），否则 apt 下载极慢
RUN sed -i "s|deb.debian.org|${APT_MIRROR}|g" /etc/apt/sources.list.d/debian.sources

# 基础工具 + node-gyp/插件编译链（build-essential + python3）+ Python 3.11（apt 预编译，glibc 一致）。
# python3-dev 提供 Python.h，供 agent 编译带 C 扩展的 Python 包。
# 工具链保留（npm 路径镜像）：koffi 优先用包内预编译平台二进制，landlock 等无预编译的
# 原生件在安装期按 arch 编译。JDK/Go 不再内置（旧全量镜像的能力，npm 路径按需安装）。
RUN apt-get update && apt-get install -y --no-install-recommends \
        curl ca-certificates git xz-utils \
        build-essential \
        python3 python3-dev python3-pip python3-venv \
    && rm -rf /var/lib/apt/lists/*

# npm 精确版本 + pnpm（`dsh plugin add` 内部走 pnpm，allowBuilds 预置在安装期生效）
RUN npm install -g npm@11.17.0 \
    && corepack enable \
    && corepack prepare pnpm@11.7.0 --activate

# Rust 按需安装：只内置 rustup-init 引导程序（几 MB），首次调用 cargo/rustc/rustup 时
# 由 /usr/local/bin/ensure-rust 把最小 stable toolchain 装进 dsh-data 持久卷，镜像省下 ~1GB。
RUN case "$TARGETARCH" in \
      amd64) RUSTUP_TRIPLE=x86_64-unknown-linux-gnu ;; \
      arm64) RUSTUP_TRIPLE=aarch64-unknown-linux-gnu ;; \
      *) echo "unsupported arch: $TARGETARCH" >&2; exit 1 ;; \
    esac \
    && (curl -fsSL "https://mirrors.ustc.edu.cn/rust-static/rustup/dist/${RUSTUP_TRIPLE}/rustup-init" -o /usr/local/bin/rustup-init \
        || curl -fsSL "https://rsproxy.cn/rustup/dist/${RUSTUP_TRIPLE}/rustup-init" -o /usr/local/bin/rustup-init) \
    && chmod +x /usr/local/bin/rustup-init

# Rust toolchain 下载走 USTC 镜像（清华 rustup 镜像已下线该路径）；toolchain 与 cargo 家目录落在 dsh-data 卷内（重启后保留）
ENV RUSTUP_HOME=/home/dsh/.dsh/rustup \
    CARGO_HOME=/home/dsh/.dsh/cargo \
    RUSTUP_DIST_SERVER=https://mirrors.ustc.edu.cn/rust-static \
    RUSTUP_UPDATE_ROOT=https://mirrors.ustc.edu.cn/rust-static/rustup

# cargo 默认走清华 crates 稀疏索引（写入持久卷，首次挂载空卷时随镜像复制进去）
RUN mkdir -p /home/dsh/.dsh/cargo \
    && printf '%s\n' \
      '[source.crates-io]' \
      'replace-with = "tuna"' \
      '[source.tuna]' \
      'registry = "sparse+https://mirrors.tuna.tsinghua.edu.cn/crates.io-index/"' \
      > /home/dsh/.dsh/cargo/config.toml

# Rust 包装器 + python 软链接（python/pip 与 python3/pip3 同名可互换）
COPY docker/ensure-rust.sh /usr/local/bin/ensure-rust
RUN chmod +x /usr/local/bin/ensure-rust \
    && ln -sf /usr/local/bin/ensure-rust /usr/local/bin/cargo \
    && ln -sf /usr/local/bin/ensure-rust /usr/local/bin/rustc \
    && ln -sf /usr/local/bin/ensure-rust /usr/local/bin/rustup \
    && ln -sf /usr/bin/python3 /usr/local/bin/python \
    && ln -sf /usr/bin/pip3 /usr/local/bin/pip

# DSH 数据目录（会话/设置/配置/插件）与 agent 工作目录
# 写一份 npmrc 让运行时 npm / `dsh plugin add`（内部走 pnpm）默认用同一镜像；
# 放在 dsh-data 卷内，首次挂载空卷时 Docker 会复制进去，之后仍可被用户覆盖。
# 运行时 ENV 的 npm_config_userconfig 指向这里（HOME=/workspace 使 /root/.npmrc 不生效）。
RUN mkdir -p /home/dsh/.dsh /workspace \
    && printf "registry=%s\n" "${NPM_REGISTRY}" > /home/dsh/.dsh/.npmrc \
    && printf "registry=%s\n" "${NPM_REGISTRY}" > /root/.npmrc

# GOROOT/GOPATH/JAVA_HOME 已随 JDK/Go 移除；PATH 恢复标准顺序（含 /usr/local/bin 供 dsh 等软链）
ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin

# pip 默认走清华镜像（供 agent 在 venv 里 pip install）
ENV PIP_INDEX_URL=https://pypi.tuna.tsinghua.edu.cn/simple

ENV DSH_HOME=/home/dsh/.dsh
ENV NODE_ENV=production
# 让目录选择器默认起始目录为 /workspace（os.homedir() 读 HOME）
ENV HOME=/workspace
# pnpm 全局目录放进 dsh-data 卷，避免 HOME=/workspace 未挂载时全局包/状态丢失
ENV PNPM_HOME=/home/dsh/.dsh/pnpm

# 3081 = dsh 内部 127.0.0.1；3080 = entrypoint 的 0.0.0.0 转发（Docker -p 映射 3080）
EXPOSE 3080

# 启动时安装最新版 dsh，起 3080→127.0.0.1:3081 转发后 exec web；失败则非零退出
# （见 docker/entrypoint.sh）
COPY docker/entrypoint.sh /usr/local/bin/dsh-entrypoint
RUN chmod +x /usr/local/bin/dsh-entrypoint
ENTRYPOINT ["/usr/local/bin/dsh-entrypoint"]
# 额外参数追加给 dsh web；--no-open 与端口由 entrypoint 固定（内部 3081 / 转发 3080）
CMD []
