# CoderFlow Base Image
# Minimal image with Node.js, Python, and Git for AI agent execution

FROM node:24-slim

# Set timezone to Eastern Time to match idev
ENV TZ=America/New_York

# Build arguments for user UID/GID (auto-detected from host, defaults to 1000)
ARG USER_UID=1000
ARG USER_GID=1000

# Install essential tools for development and troubleshooting
# Includes Playwright/Chromium dependencies for browser automation
RUN apt-get update && \
    apt-get install -y \
        expect \
        tmux \
        ncurses-term \
        tzdata \
        git \
        jq \
        procps \
        curl \
        ca-certificates \
        wget \
        netcat-openbsd \
        dnsutils \
        iputils-ping \
        telnet \
        vim \
        nano \
        openssh-client \
        make \
        sshpass \
        uuid-runtime \
        lsof \
        python3 \
        python3-pip \
        python3-venv \
        ripgrep \
        rsync \
        # Document handling tools
        unzip \
        poppler-utils \
        # Playwright/Chromium dependencies (prebaked to avoid needing sudo at runtime)
        libasound2 \
        libatk-bridge2.0-0 \
        libatk1.0-0 \
        libatspi2.0-0 \
        libcairo2 \
        libcups2 \
        libdbus-1-3 \
        libdrm2 \
        libgbm1 \
        libglib2.0-0 \
        libnspr4 \
        libnss3 \
        libpango-1.0-0 \
        libx11-6 \
        libxcb1 \
        libxcomposite1 \
        libxdamage1 \
        libxext6 \
        libxfixes3 \
        libxkbcommon0 \
        libxrandr2 \
        xvfb && \
    ln -sf /usr/share/zoneinfo/America/New_York /etc/localtime && \
    echo "America/New_York" > /etc/timezone && \
    apt-get clean && \
    rm -rf /var/lib/apt/lists/* && \
    ln -s /usr/bin/python3 /usr/bin/python

# Install Python libraries for document handling (docx, pdf)
RUN pip install --break-system-packages python-docx pypdf pdfplumber

# Remove the default 'node' user that comes with node:24-slim (typically UID 1000)
# This prevents conflicts when we create our own user with specified UID
RUN userdel -r node 2>/dev/null || true

# Create 'coder' user and group with UID/GID from build args
# This matches the host user's UID/GID, eliminating permission issues
RUN groupadd -g ${USER_GID} coder && \
    useradd -m -u ${USER_UID} -g ${USER_GID} -s /bin/bash coder && \
    mkdir -p /home/coder/.ssh /home/coder/.claude /home/coder/.codex \
             /home/coder/.config/google-generative-ai /home/coder/.gemini \
             /home/coder/.bob /home/coder/.grok && \
    chown -R coder:coder /home/coder

# Configure git for root user (used during docker builds with BuildKit secrets)
# useHttpPath ensures per-repo credential matching when repos need different tokens
RUN git config --global credential.helper store && \
    git config --global credential.useHttpPath true && \
    git config --global --add safe.directory '*' && \
    git config --global core.autocrlf false

# Configure git for coder user (used at runtime in containers)
# Credential helper chain: our custom helper first, then store as fallback
# Our helper only responds for managed repos (in CODER_MANAGED_REPOS); others fall through to store
# useHttpPath ensures Git sends the full repo path to credential helpers (needed for per-repo matching)
RUN su - coder -c "git config --global credential.helper '/usr/local/bin/coder-git-credential-helper' && \
    git config --global --add credential.helper store && \
    git config --global credential.useHttpPath true && \
    git config --global --add safe.directory '*' && \
    git config --global core.autocrlf false"

# Pre-populate SSH known_hosts with GitHub host keys at build time
# This eliminates the need for ssh-keyscan at runtime, preventing connection storms
# when multiple containers start simultaneously
RUN mkdir -p /etc/ssh && \
    ssh-keyscan github.com >> /etc/ssh/ssh_known_hosts 2>/dev/null && \
    chmod 644 /etc/ssh/ssh_known_hosts

# Configure SSH connection multiplexing for GitHub
# This enables connection reuse across multiple git operations, reducing overhead
COPY ssh_config_template /etc/ssh/ssh_config.d/10-github-multiplexing.conf
RUN chmod 644 /etc/ssh/ssh_config.d/10-github-multiplexing.conf

# Configure shell to source ~/.bash_env for environment variables
# This allows setup.sh to write env vars that persist in all shells (login and non-login)
RUN sed -i '/^# If not running interactively/i # Source environment variables from setup.sh\nif [ -f ~/.bash_env ]; then\n    . ~/.bash_env\nfi\n' /home/coder/.bashrc && \
    printf '\n# Source environment variables from setup.sh\nif [ -f ~/.bash_env ]; then\n    . ~/.bash_env\nfi\n' >> /home/coder/.profile

# Install Claude Code, Codex, Gemini CLI, Bob Shell, and Grok Build CLI globally
# Bob Shell: install via the official installer script (supports --pm flag for non-interactive)
# Grok: official xAI installer drops a binary in ~/.grok/bin/grok and symlinks it from PATH.
#       Run as coder so the binary lands under the coder user's home dir.
RUN npm install -g @openai/codex @google/gemini-cli && \
    bash -c 'curl -fsSL https://bob.ibm.com/download/bobshell.sh | bash -s -- --pm npm' && \
    su - coder -c "curl -fsSL https://claude.ai/install.sh | bash" && \
    su - coder -c "curl -fsSL https://x.ai/cli/install.sh | bash" && \
    ln -sf /home/coder/.grok/bin/grok /usr/local/bin/grok

# Pre-install Playwright browser binaries (not the skill itself)
# This caches ~165MB of Chromium so skills that need browser automation don't have to download at runtime
# System dependencies are already installed above (libasound2, libatk*, etc.)
RUN su - coder -c "npx playwright install chromium"

# Pre-install aitool and codermake globally and install licenses for coder user and root.
RUN npm install -g @profoundlogic/aitool @profoundlogic/codermake && \
    aitool --license-set PLX-7KM2D-QN8FX-W5HRP-BJ3TY-2026A && \
    codermake --license-set PLX-4R8N5-KXJM3-DV7WT-YC2HP-2026A && \
    su - coder -c "aitool --license-set PLX-7KM2D-QN8FX-W5HRP-BJ3TY-2026A" && \
    su - coder -c "codermake --license-set PLX-4R8N5-KXJM3-DV7WT-YC2HP-2026A"

# Install code-server for web-based VS Code
RUN curl -fsSL https://code-server.dev/install.sh | sh && \
    mkdir -p /home/coder/.local/share/code-server && \
    mkdir -p /home/coder/.config/code-server && \
    chown -R coder:coder /home/coder/.local /home/coder/.config

# Pre-install VS Code extensions from configurable list
COPY vscode-extensions.txt /tmp/vscode-extensions.txt
RUN while IFS= read -r extension || [ -n "$extension" ]; do \
      # Skip comments and empty lines
      case "$extension" in \
        \#*|'') continue ;; \
      esac; \
      echo "Installing extension: $extension"; \
      su - coder -c "code-server --install-extension $extension" || echo "Failed to install $extension"; \
    done < /tmp/vscode-extensions.txt && \
    rm /tmp/vscode-extensions.txt

# Pre-install VS Code extensions from pinned VSIX URLs for cases where
# gallery installs are unreliable but direct VSIX installs work.
COPY vscode-extension-vsix-urls.txt /tmp/vscode-extension-vsix-urls.txt
RUN while IFS= read -r extension_url || [ -n "$extension_url" ]; do \
      case "$extension_url" in \
        \#*|'') continue ;; \
      esac; \
      echo "Installing extension from VSIX URL: $extension_url"; \
      tmp_vsix="$(mktemp /tmp/vscode-extension.XXXXXX.vsix)"; \
      if curl -fsSL "$extension_url" -o "$tmp_vsix"; then \
        chmod 644 "$tmp_vsix"; \
        su - coder -c "code-server --install-extension $tmp_vsix" || echo "Failed to install VSIX from $extension_url"; \
      else \
        echo "Failed to download VSIX from $extension_url"; \
      fi; \
      rm -f "$tmp_vsix"; \
    done < /tmp/vscode-extension-vsix-urls.txt && \
    rm /tmp/vscode-extension-vsix-urls.txt

# Configure default VS Code settings for minimal layout
COPY vscode-settings.json /tmp/vscode-settings.json
RUN mkdir -p /home/coder/.local/share/code-server/User && \
    cp /tmp/vscode-settings.json /home/coder/.local/share/code-server/User/settings.json && \
    rm /tmp/vscode-settings.json && \
    chown -R coder:coder /home/coder/.local

# Disable built-in chat/AI extensions that may show unwanted panels
RUN if [ -d "/usr/lib/code-server/lib/vscode/extensions/mermaid-chat-features" ]; then \
      mv /usr/lib/code-server/lib/vscode/extensions/mermaid-chat-features \
         /usr/lib/code-server/lib/vscode/extensions/mermaid-chat-features.disabled || true; \
    fi

# Create workspace directory for repositories
RUN mkdir -p /workspace && \
    chown coder:coder /workspace

# Create task-output directory for results
RUN mkdir -p /task-output && \
    chown coder:coder /task-output

# Set working directory
WORKDIR /workspace

# Copy entrypoint script and AI agent wrapper
COPY entrypoint.sh /usr/local/bin/entrypoint.sh
COPY sync-repos.sh /usr/local/bin/sync-repos.sh
COPY rewind-files.sh /usr/local/bin/rewind-files.sh
COPY agent-wrapper.sh /usr/local/bin/agent-wrapper.sh
COPY tmux.conf /etc/tmux.conf
COPY stamp-debug-stream.js /usr/local/bin/stamp-debug-stream.js
COPY acp-client.js /usr/local/bin/acp-client.js
COPY start-code-server.sh /usr/local/bin/start-code-server.sh
COPY apply-local-state.sh /usr/local/bin/apply-local-state.sh
COPY coder-git-credential-helper /usr/local/bin/coder-git-credential-helper
RUN chmod +x /usr/local/bin/entrypoint.sh /usr/local/bin/sync-repos.sh /usr/local/bin/rewind-files.sh /usr/local/bin/agent-wrapper.sh /usr/local/bin/stamp-debug-stream.js /usr/local/bin/acp-client.js /usr/local/bin/start-code-server.sh /usr/local/bin/apply-local-state.sh /usr/local/bin/coder-git-credential-helper

# Standard instruction templates
COPY standard-instructions/ /usr/local/share/standard-instructions/

# Expose code-server port
EXPOSE 8080

# Set entrypoint
ENTRYPOINT ["/usr/local/bin/entrypoint.sh"]

# Default command: none (entrypoint will run default task)
CMD []
