# syntax=docker/dockerfile:1
FROM node:24-bookworm-slim

RUN --mount=type=cache,target=/var/cache/apt,sharing=locked \
    --mount=type=cache,target=/var/lib/apt/lists,sharing=locked \
  apt-get update \
  && apt-get install -y --no-install-recommends git openssh-client ca-certificates curl gnupg \
  && mkdir -p /etc/apt/keyrings \
  && curl -fsSL https://cli.github.com/packages/githubcli-archive-keyring.gpg \
    | gpg --dearmor -o /etc/apt/keyrings/githubcli-archive-keyring.gpg \
  && chmod go+r /etc/apt/keyrings/githubcli-archive-keyring.gpg \
  && echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/githubcli-archive-keyring.gpg] https://cli.github.com/packages stable main" \
    > /etc/apt/sources.list.d/github-cli.list \
  && curl -fsSL https://ngrok-agent.s3.amazonaws.com/ngrok.asc \
    | gpg --dearmor -o /etc/apt/keyrings/ngrok-archive-keyring.gpg \
  && chmod go+r /etc/apt/keyrings/ngrok-archive-keyring.gpg \
  && echo "deb [signed-by=/etc/apt/keyrings/ngrok-archive-keyring.gpg] https://ngrok-agent.s3.amazonaws.com buster main" \
    > /etc/apt/sources.list.d/ngrok.list \
  && apt-get update \
  && apt-get install -y --no-install-recommends gh ngrok

ARG WAKE_VERSION
RUN test -n "$WAKE_VERSION" || (echo "WAKE_VERSION build arg is required" && exit 1)

RUN --mount=type=cache,target=/root/.npm \
  npm install -g @anthropic-ai/claude-code @openai/codex "@atolis-hq/wake@${WAKE_VERSION}"

RUN mkdir -p /etc/codex /usr/local/lib/wake \
  && cp /usr/local/lib/node_modules/@atolis-hq/wake/dist/src/execution/infrastructure/codex-stop-hook.js /usr/local/lib/wake/codex-stop-hook.js \
  && printf '%s\n' \
    '[features]' \
    'hooks = true' \
    '' \
    '[hooks]' \
    'managed_dir = "/usr/local/lib/wake"' \
    '' \
    '[[hooks.Stop]]' \
    '[[hooks.Stop.hooks]]' \
    'type = "command"' \
    'command = "node /usr/local/lib/wake/codex-stop-hook.js"' \
    'timeout = 10' \
    > /etc/codex/requirements.toml

RUN useradd --create-home --shell /bin/bash wake \
  && mkdir -p /home/wake/.codex-runtime \
  && mkdir -p /home/wake/.cursor \
  && chown -R wake:wake /home/wake/.codex-runtime \
  && chown -R wake:wake /home/wake/.cursor

ENV CODEX_HOME=/home/wake/.codex-runtime
ENV PATH=/home/wake/.local/bin:$PATH

RUN curl https://cursor.com/install -fsS | HOME=/home/wake bash \
  && printf '#!/bin/bash\n[ "$1" = "agent" ] && shift\nexec ~/.local/bin/agent "$@"\n' \
     > /home/wake/.local/bin/cursor \
  && chmod +x /home/wake/.local/bin/cursor \
  && chown -R wake:wake /home/wake/.local

USER root
WORKDIR /home/wake

EXPOSE 4317

# No WAKE_MAIN_JS here: there is no /app in a packaged-mode image, and its
# absence is the signal (see resolveWakeInvocation in
# sandbox-entrypoint-command.ts) that the CLI should be invoked via the bare
# `wake` binary that `npm install -g` puts on PATH, rather than a hardcoded
# npm global lib path that varies by npm/OS setup.
#
# /wake/.wake is bind-mounted from the host and self-update actively creates
# and deletes its own lock files there while this container is starting, so
# a recursive chown can race a file disappearing mid-walk. That single ENOENT
# must not be fatal under set -eu — it would otherwise crash the container
# before wake start ever runs.
ENTRYPOINT ["sh", "-c", "set -eu; mkdir -p /wake/.wake; chown -R wake:wake /wake/.wake || true; exec su wake -s /bin/sh -c 'exec wake sandbox-entrypoint'"]
