diff --git a/go.mod b/go.mod index 960ea24..97c64ea 100644 --- a/go.mod +++ b/go.mod @@ -6,7 +6,7 @@ require ( charm.land/huh/v2 v2.0.3 charm.land/lipgloss/v2 v2.0.3 github.com/a2aproject/a2a-go/v2 v2.2.0 - github.com/agent-substrate/substrate v0.0.0-20260612160914-27aa4eec85f2 + github.com/agent-substrate/substrate v0.0.0-20260616211440-0ec9b650a0ab github.com/envoyproxy/go-control-plane/envoy v1.37.0 github.com/google/uuid v1.6.0 github.com/spf13/cobra v1.10.2 diff --git a/go.sum b/go.sum index 071664b..dc3da9e 100644 --- a/go.sum +++ b/go.sum @@ -16,8 +16,8 @@ github.com/MakeNowJust/heredoc v1.0.0 h1:cXCdzVdstXyiTqTvfqk9SDHpKNjxuom+DOlyEeQ github.com/MakeNowJust/heredoc v1.0.0/go.mod h1:mG5amYoWBHf8vpLOuehzbGGw0EHxpZZ6lCpQ4fNJ8LE= github.com/a2aproject/a2a-go/v2 v2.2.0 h1:eayiNXYpyTOLVhhQrGmIHlcy8GnOdnwaNdYQPvS84Ik= github.com/a2aproject/a2a-go/v2 v2.2.0/go.mod h1:htTxMwicNXXXEwwfjuB/Pd1g7UHDrswhSievncmTVcE= -github.com/agent-substrate/substrate v0.0.0-20260612160914-27aa4eec85f2 h1:SlFLoJ3EPWrgR3bBlwCUmpJY6rqrAmvkwb1a9++WOBw= -github.com/agent-substrate/substrate v0.0.0-20260612160914-27aa4eec85f2/go.mod h1:TgdtEUV6iaflJTwmS8ONiGsyyJD+5okPZj2H6mM8WlA= +github.com/agent-substrate/substrate v0.0.0-20260616211440-0ec9b650a0ab h1:ESQ0AWzhw3GROJ5ZIT6tzqHg92mIEqdp/esSmK3s6zQ= +github.com/agent-substrate/substrate v0.0.0-20260616211440-0ec9b650a0ab/go.mod h1:TgdtEUV6iaflJTwmS8ONiGsyyJD+5okPZj2H6mM8WlA= github.com/atotto/clipboard v0.1.4 h1:EH0zSVneZPSuFR11BlR9YppQTVDbh5+16AmcJi4g1z4= github.com/atotto/clipboard v0.1.4/go.mod h1:ZY9tmq7sm5xIbd9bOK4onWV4S6X0u6GY7Vn0Yu86PYI= github.com/aymanbagabas/go-udiff v0.4.1 h1:OEIrQ8maEeDBXQDoGCbbTTXYJMYRCRO1fnodZ12Gv5o= diff --git a/internal/hack/install-ax.sh b/internal/hack/install-ax.sh index d0a54a7..2ee316e 100755 --- a/internal/hack/install-ax.sh +++ b/internal/hack/install-ax.sh @@ -41,6 +41,37 @@ function log_step() { echo -e "${COLOR_CYAN}[step]: ${step_name}${COLOR_RESET}" } +# wait_with_spinner runs a blocking command while showing a simple spinner on an +# interactive terminal, then reports "done"/"failed" and returns the command's +# exit status. +wait_with_spinner() { + local msg="$1"; shift + if [[ ! -t 2 ]]; then + "$@" + return $? + fi + + local out; out="$(mktemp)" + "$@" >"${out}" 2>&1 & + local pid=$! frames='|/-\' i=0 + while kill -0 "${pid}" 2>/dev/null; do + i=$(( (i + 1) % ${#frames} )) + printf '\r%s %s' "${frames:${i}:1}" "${msg}" >&2 + sleep 0.1 + done + + local status=0 + wait "${pid}" || status=$? + if [[ "${status}" -eq 0 ]]; then + printf '\r\033[K%s... done\n' "${msg}" >&2 + else + printf '\r\033[K%s... failed\n' "${msg}" >&2 + cat "${out}" >&2 + fi + rm -f "${out}" + return "${status}" +} + function usage() { echo "Usage: $0 [options]" echo "" @@ -171,6 +202,35 @@ build_antigravity_image() { echo "${repo}@${digest}" } +build_ateom_image() { + if [[ -n "${ATEOM_IMAGE:-}" ]]; then + echo "${ATEOM_IMAGE}" + return + fi + if [[ -z "${KO_DOCKER_REPO:-}" ]]; then + echo "Error: KO_DOCKER_REPO environment variable must be set" >&2 + exit 1 + fi + + # Resolve the substrate source for the version AX is pinned to in go.mod. + go mod download github.com/agent-substrate/substrate + local sub_dir ateom_ref + sub_dir="$(go list -m -f '{{.Dir}}' github.com/agent-substrate/substrate)" + if [[ -z "${sub_dir}" ]]; then + echo "Error: could not locate the substrate module (go list -m)." >&2 + exit 1 + fi + + log_step "build_ateom_image (from ${sub_dir})" >&2 + ateom_ref="$(cd "${sub_dir}" && KO_DOCKER_REPO="${KO_DOCKER_REPO}" GOFLAGS="" ko build --platform=linux/amd64 -B ./cmd/ateom-gvisor)" + + if [[ "${ateom_ref}" != *@sha256:* ]]; then + echo "Error: ko did not return a digest-pinned ateom image (got '${ateom_ref}')." >&2 + exit 1 + fi + echo "${ateom_ref}" +} + deploy_ax_server() { log_step "deploy_ax_server" @@ -187,15 +247,23 @@ deploy_ax_server() { echo "Using GCS Bucket: ${BUCKET_NAME}" # Build and push the antigravity harness image, capturing its reference. - local antigravity_image + local antigravity_image ateom_image antigravity_image=$(build_antigravity_image) + ateom_image=$(build_ateom_image) # Render template and apply with ko sed -e "s|\${GEMINI_API_KEY}|${GEMINI_API_KEY}|g" \ -e "s|\${BUCKET_NAME}|${BUCKET_NAME}|g" \ -e "s|\${ANTIGRAVITY_IMAGE}|${antigravity_image}|g" \ + -e "s|\${ATEOM_IMAGE}|${ateom_image}|g" \ internal/manifests/ax-deployment2.yaml \ | run_ko -f - + + # Wait for the antigravity ActorTemplate's golden snapshot to be ready. + log_step "wait for actortemplate/ax-harness-template to be Ready" + wait_with_spinner "waiting for golden snapshot (timeout ${AX_WAIT_TIMEOUT:-5m})" \ + run_kubectl wait --for=condition=Ready actortemplate/ax-harness-template \ + -n ax --timeout="${AX_WAIT_TIMEOUT:-5m}" } delete_ax_server() { @@ -205,6 +273,7 @@ delete_ax_server() { sed -e "s|\${GEMINI_API_KEY}|dummy-key|g" \ -e "s|\${BUCKET_NAME}|dummy-bucket|g" \ -e "s|\${ANTIGRAVITY_IMAGE}|dummy-image|g" \ + -e "s|\${ATEOM_IMAGE}|dummy-image|g" \ internal/manifests/ax-deployment2.yaml \ | run_kubectl delete --ignore-not-found -f - } diff --git a/internal/manifests/README.md b/internal/manifests/README.md index 23805b0..f4d8cf1 100644 --- a/internal/manifests/README.md +++ b/internal/manifests/README.md @@ -27,12 +27,16 @@ and container image are provided by AX. ### 1. Build and Deploy > [!NOTE] -> Do not manually edit `internal/manifests/ax-deployment2.yaml`. The installation script automatically injects your `${GEMINI_API_KEY}`, `${BUCKET_NAME}`, and the built `${ANTIGRAVITY_IMAGE}` reference during deployment. +> Do not manually edit `internal/manifests/ax-deployment2.yaml`. The installation script automatically injects your `${GEMINI_API_KEY}`, `${BUCKET_NAME}`, and the built `${ANTIGRAVITY_IMAGE}` and `${ATEOM_IMAGE}` references during deployment. -The installation script builds two images and applies the resolved manifests to -your cluster: the AX control-plane (Go) image, built with `ko` using the -`harness` build tag, and the built-in **antigravity harness** image, built from -`python/antigravity/Dockerfile` with Docker or Podman. +The installation script builds the required images and applies the resolved +manifests to your cluster: + +- the AX control-plane (Go) image, built with `ko` using the `harness` build tag; +- the built-in **antigravity harness** image, built from + `python/antigravity/Dockerfile` with Docker or Podman; +- the **ateom-gvisor** worker image, built with `ko` from the `go.mod` pinned + substrate module. #### Build prerequisites @@ -80,11 +84,6 @@ export KO_DEFAULTPLATFORMS="linux/amd64" ./internal/hack/install-ax.sh --deploy-ax-server ``` -Wait until the templates are ready: -```bash -kubectl wait --for=condition=Ready actortemplate/ax-harness-template -n ax --timeout=5m -``` - ### 2. Port-Forward Services The `harness` path has no Envoy router or `Service`; connect directly to the `ax-server` `ReplicaSet`: diff --git a/internal/manifests/ax-deployment2.yaml b/internal/manifests/ax-deployment2.yaml index 5d12159..d33dd06 100644 --- a/internal/manifests/ax-deployment2.yaml +++ b/internal/manifests/ax-deployment2.yaml @@ -34,7 +34,7 @@ metadata: namespace: ax spec: replicas: 5 - ateomImage: ko://github.com/agent-substrate/substrate/cmd/ateom-gvisor + ateomImage: ${ATEOM_IMAGE} --- apiVersion: ate.dev/v1alpha1 kind: ActorTemplate