FROM python:3.13-slim AS base

COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/

# Non-root user created up front and owning /app, so no `chown -R` over the
# venv is needed after each code change (that cost ~2min per rebuild).
RUN addgroup --system app && adduser --system --ingroup app app

WORKDIR /app
RUN mkdir -p /app/packages/agent/logs && chown -R app:app /app
USER app

# The system user has no home dir, so uv's default cache path is unwritable.
ENV UV_CACHE_DIR=/tmp/uv-cache

# Build context is the REPO ROOT, not packages/agent: uv.lock is the workspace
# lockfile and lives there (see root pyproject.toml [tool.uv.workspace]).
# Both members' pyproject.toml are needed for --frozen to validate the lock.
COPY --chown=app:app pyproject.toml uv.lock ./
COPY --chown=app:app packages/agent/pyproject.toml packages/agent/
COPY --chown=app:app packages/grammar-py/pyproject.toml packages/grammar-py/
RUN uv sync --frozen --no-install-project --package udiagent --extra server --extra langfuse --extra duckdb --extra starrocks --extra bedrock

# Copy application code and data
COPY --chown=app:app packages/agent/src/ ./packages/agent/src/
COPY --chown=app:app packages/agent/data/ ./packages/agent/data/
COPY --chown=app:app packages/agent/README.md ./packages/agent/

# Install the project itself
# duckdb/starrocks are needed whenever UDI_QUERY_BACKENDS is set: the connector
# imports in _engine_from_config are lazy, and _load_query_engines swallows the
# resulting ImportError into a warning — so without them a configured backend
# degrades silently to 404s instead of failing at startup. bedrock is needed
# whenever UDI_BEDROCK is set, and is likewise imported eagerly at startup.
RUN uv sync --frozen --package udiagent --extra server --extra langfuse --extra duckdb --extra starrocks --extra bedrock

WORKDIR /app/packages/agent

# 8000, not 80: the process runs as the non-root `app` user, and runtimes that
# keep the kernel default (ports < 1024 privileged — e.g. Fargate, unlike Docker)
# would refuse the bind. Hosts map their own port onto it (`-p 80:8000`).
EXPOSE 8000

# Reported by GET /. Last, so a new commit doesn't invalidate the layers above.
ARG GIT_SHA=""
ENV UDI_GIT_SHA=${GIT_SHA}

CMD ["uv", "run", "--frozen", "--no-sync", "fastapi", "run", "src/udiagent/server/app.py", "--port", "8000", "--host", "0.0.0.0"]
