diff --git a/cmd/ax/Dockerfile b/cmd/ax/Dockerfile index 78a8c8e9..16a1b901 100644 --- a/cmd/ax/Dockerfile +++ b/cmd/ax/Dockerfile @@ -12,14 +12,19 @@ # See the License for the specific language governing permissions and # limitations under the License. -# Comprehensive AX image: the Go `ax` binary plus the Antigravity Python sidecar -# (SDK, localharness, agent), on a Debian-based image with shell tooling for -# skills/code execution. Used by both the ax-server (`ax serve`) and the harness -# actor (`ax harness`, which forks the Python sidecar). +# Multi-target AX image build: +# --target antigravity : python:3.13-slim + the Antigravity Python sidecar +# (SDK, localharness, agent). Used by the antigravity +# harness actor (`ax harness antigravity`). +# --target ax : debian:stable-slim + the Go `ax` binary. Used by +# the ax-server (`ax serve`) and the Go interactions +# harness actor (`ax harness antigravity-interactions`). # -# Build context: repository root. The image targets the cluster's linux/amd64 -# nodes, so it is built with `--platform linux/amd64`. For a standalone build: -# docker build --platform linux/amd64 -f cmd/ax/Dockerfile -t . && docker push +# Build context: repository root. Images target the cluster's linux/amd64 nodes, +# so build with `--platform linux/amd64`. +# For a standalone build: +# docker build --platform linux/amd64 --target antigravity -f cmd/ax/Dockerfile -t . && docker push +# docker build --platform linux/amd64 --target ax -f cmd/ax/Dockerfile -t . && docker push # --- Stage 1: build the ax Go binary (with the harness build tag) ------------- FROM --platform=$BUILDPLATFORM golang:1.26 AS build @@ -32,7 +37,8 @@ COPY . . RUN CGO_ENABLED=0 GOOS=${TARGETOS} GOARCH=${TARGETARCH} \ go build -o /out/ax ./cmd/ax -FROM python:3.13-slim +# --- antigravity image ------- +FROM python:3.13-slim AS antigravity WORKDIR /workspace RUN apt-get update \ @@ -73,3 +79,23 @@ EXPOSE 80 # which serves the HarnessService on :80. CMD ["/ax-app/ax", "harness", \ "--host", "0.0.0.0", "--port", "80"] + +# --- ax image (Go-only) for the interactions harness and ax-server ----------- +FROM debian:stable-slim AS ax +WORKDIR /workspace + +RUN apt-get update \ + && apt-get install -y --no-install-recommends \ + ca-certificates \ + curl \ + less \ + procps \ + wget \ + && rm -rf /var/lib/apt/lists/* + +COPY --from=build /out/ax /ax-app/ax + +EXPOSE 80 + +CMD ["/ax-app/ax", "harness", "antigravity-interactions", \ + "--host", "0.0.0.0", "--port", "80"] diff --git a/hack/install-ax.sh b/hack/install-ax.sh index 249f30e2..78f2b630 100755 --- a/hack/install-ax.sh +++ b/hack/install-ax.sh @@ -105,10 +105,13 @@ detect_container_engine() { fi } -# build_ax_image builds and pushes the comprehensive ax image (the Go ax binary -# plus the Antigravity Python sidecar) and echoes its digest-pinned reference on -# stdout. Requires AX_IMAGE_REPO and a container engine. -build_ax_image() { +# _build_and_push_ax builds one target of cmd/ax/Dockerfile into ${repo}:, +# pushes it, and echoes the digest-pinned reference on stdout. Args: +# $1 repo - fully-qualified image repo (e.g. gcr.io/proj/ax) +# $2 target - Dockerfile target stage (ax | antigravity) +# Requires AX_IMAGE_REPO and a container engine. +_build_and_push_ax() { + local repo="$1" target="$2" if [[ -z "${AX_IMAGE_REPO:-}" ]]; then echo "Error: AX_IMAGE_REPO environment variable must be set" >&2 exit 1 @@ -120,14 +123,14 @@ build_ax_image() { exit 1 fi - local repo tag image digest - repo="${AX_IMAGE_REPO}/ax" + local tag image digest tag="$(git rev-parse --short HEAD)" image="${repo}:${tag}" - log_step "build_ax_image -> ${image}" >&2 + log_step "build ${target} -> ${image}" >&2 "${CONTAINER_ENGINE}" build \ --platform linux/amd64 \ + --target "${target}" \ -f cmd/ax/Dockerfile \ -t "${image}" \ . 2>&1 \ @@ -156,6 +159,18 @@ build_ax_image() { echo "${repo}@${digest}" } +# build_ax_image builds and pushes the Go-only ax image used by the ax-server and the +# Go interactions harness. +build_ax_image() { + _build_and_push_ax "${AX_IMAGE_REPO}/ax" ax +} + +# build_ax_antigravity_image builds and pushes the antigravity image used by the +# antigravity harness. +build_ax_antigravity_image() { + _build_and_push_ax "${AX_IMAGE_REPO}/ax-antigravity" antigravity +} + build_ateom_image() { if [[ -n "${ATEOM_IMAGE:-}" ]]; then echo "${ATEOM_IMAGE}" @@ -206,8 +221,9 @@ deploy_ax_server() { echo "Using GCS Bucket: ${AX_SNAPSHOTS_BUCKET}" # Build and push the images, capturing their digest-pinned references. - local ax_image ateom_image + local ax_image ax_antigravity_image ateom_image ax_image=$(build_ax_image) + ax_antigravity_image=$(build_ax_antigravity_image) ateom_image=$(build_ateom_image) # Resolve the event-log Postgres DSN. By default ax-server connects to an @@ -241,6 +257,7 @@ deploy_ax_server() { -e "s|\${GEMINI_API_KEY}|${GEMINI_API_KEY}|g" -e "s|\${AX_SNAPSHOTS_BUCKET}|${AX_SNAPSHOTS_BUCKET}|g" -e "s|\${AX_IMAGE}|${ax_image}|g" + -e "s|\${AX_ANTIGRAVITY_IMAGE}|${ax_antigravity_image}|g" -e "s|\${ATEOM_IMAGE}|${ateom_image}|g" -e "s|\${GOOGLE_CLOUD_PROJECT}|${GOOGLE_CLOUD_PROJECT:-}|g" -e "s|\${AX_CONFIG_CONTENT}|${ax_config_content}|g" diff --git a/manifests/README.md b/manifests/README.md index 6e68e670..fe3678de 100644 --- a/manifests/README.md +++ b/manifests/README.md @@ -18,22 +18,27 @@ The target Kubernetes cluster is assumed to have ### 1. Build and Deploy > [!NOTE] -> Do not manually edit `manifests/ax-deployment.yaml`. The installation script automatically injects your `${GEMINI_API_KEY}`, `${AX_SNAPSHOTS_BUCKET}`, and the built `${AX_IMAGE}` and `${ATEOM_IMAGE}` references during deployment. +> Do not manually edit `manifests/ax-deployment.yaml`. The installation script automatically injects your `${GEMINI_API_KEY}`, `${AX_SNAPSHOTS_BUCKET}`, and the built `${AX_IMAGE}`, `${AX_ANTIGRAVITY_IMAGE}`, and `${ATEOM_IMAGE}` references during deployment. The installation script builds the required images and applies the resolved manifests to your cluster: -- the comprehensive **ax** image, built from `cmd/ax/Dockerfile`, +- the **ax** image (the Go `ax` binary only), built from the `ax` + target of `cmd/ax/Dockerfile`; used by the ax-server and the Go interactions + harness, +- the **ax-antigravity** image (the Antigravity Python + sidecar: SDK, localharness, agent), built from the `antigravity` target of + `cmd/ax/Dockerfile`; used by the antigravity harness actor, - the **ateom-gvisor** worker image, built with `ko` from the `go.mod` pinned substrate module. #### Build prerequisites -The ax image bundles the antigravity SDK, installed from PyPI at build time. -The image targets the cluster's **linux/amd64** -nodes and is built with `--platform linux/amd64`. +The ax-antigravity image bundles the antigravity SDK, installed from PyPI at +build time. Both images target the cluster's **linux/amd64** +nodes and are built with `--platform linux/amd64`. -You also need a container engine to build and push the ax image. The script +You also need a container engine to build and push the ax images. The script auto-detects one (preferring a **running** docker, then podman); force a choice with `CONTAINER_ENGINE=docker` or `CONTAINER_ENGINE=podman`: @@ -45,9 +50,10 @@ with `CONTAINER_ENGINE=docker` or `CONTAINER_ENGINE=podman`: #### Registry authentication -`GOOGLE_CLOUD_PROJECT` sets `AX_IMAGE_REPO=gcr.io/$GOOGLE_CLOUD_PROJECT`. The deploy pushes two -images — the **ax** image (via your container engine) and the **ateom** image -(via `ko`) — and both authenticate through the gcloud credential helper: +`GOOGLE_CLOUD_PROJECT` sets `AX_IMAGE_REPO=gcr.io/$GOOGLE_CLOUD_PROJECT`. The deploy pushes three +images — the **ax** and **ax-antigravity** images (via your container engine) and +the **ateom** image (via `ko`) — and all authenticate through the gcloud +credential helper: ```bash gcloud auth login # authenticate gcloud diff --git a/manifests/ax-deployment.yaml b/manifests/ax-deployment.yaml index 1c45dace..fda42868 100644 --- a/manifests/ax-deployment.yaml +++ b/manifests/ax-deployment.yaml @@ -50,7 +50,7 @@ spec: pauseImage: "gcr.io/gke-release/pause@sha256:bcbd57ba5653580ec647b16d8163cdd1112df3609129b01f912a8032e48265da" containers: - name: "axantigravity" - image: ${AX_IMAGE} + image: ${AX_ANTIGRAVITY_IMAGE} # Substrate ignores the image CMD/ENV/WORKDIR, so the harness command and # environment are specified here. `ax harness antigravity` forks the # Antigravity Python sidecar, which serves on port 80 because substrate