✨ feature: add Google Antigravity agents and models to the dashboard - #5410
Conversation
Signed-off-by: Douglas Baggett <doug.baggett@gmail.com>
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
|
Quality verification (live hive host): fetched Filed by quality agent (hold-gated mode).🐝 Hive Agent: — hive: agent=quality backend=copilot model=claude-fable-5 |
Summary
backend: agy, installs Google's Antigravity CLI in themain image, and launches it with the model/effort pairing the CLI requires.
The dashboard did not expose that support:
agywas absent from every agentmethod dropdown, so an operator could select it only by editing configuration
outside the UI.
model picker has an explicit per-CLI catalog, but an unregistered CLI falls
through to
COPILOT_CLI_MODELS. Adding only anagymethod option wouldtherefore advertise Copilot models that Antigravity does not support.
gives it its own account-aware model inventory. The server runs the vendor's
agy modelscommand against the same.geministate the agents use; the UIreceives the live IDs through
/api/config/backendsand keeps an 11-modelstatic floor for first paint and failed/offline discovery.
catalog endpoint. The existing agy launcher, contributor path, authentication
flow, billing classification, and fixed
--effort lowlaunch invariant areunchanged.
Observable failure
The backend is valid everywhere below the dashboard:
config.CLIBackendscontainsagy, so config validation accepts it;config/backends.confmaps it to theagybinary;agent.backendLaunchCmdsupplies--dangerously-skip-permissionsand, when amodel is set,
--model <id> --effort low;But
static/index.html's independently maintainedKNOWN_BACKENDSdid notcontain
agy. Every agent-card and detail-panel method selector renders fromthat array, so the supported backend was impossible to choose on the dashboard.
Nor was adding one string sufficient. Before this change,
modelsForBackend('agy')reached the generic unknown-backend branch:That would put Claude/GPT models in Antigravity's dropdown based on GitHub
Copilot's catalog rather than on what
agy --modelaccepts.Root cause
The authoritative Go/shell backend registries and the dashboard picker are
deliberately separate.
backend_picker_parity_test.goguarded the dangerousdirection — every UI option must be launchable — but explicitly allowed the
reverse direction, where a launchable backend is omitted from the UI. That is
reasonable for contributor-only or otherwise constrained CLIs, but it meant the
existing agy support could not make the dashboard fail a test by drifting behind
it.
The model layer repeated the same shape.
queryCLIModelsandcliStaticFallbackhad backend-specific cases for Copilot, Claude, Gemini,Goose, Codex, and bob, while the frontend had its own
CLI_BACKENDSandCLI_FALLBACK_MODELSmaps. agy existed in none of those four places. Theunknown-backend Copilot fallback then hid the omission by returning a non-empty,
but wrong, dropdown.
Change
Dashboard method and first-paint catalog
src/pkg/dashboard/static/index.htmlnow:agyinKNOWN_BACKENDS, so both agent method selectors offer it;agyas the stored backend ID;agyin the client-sideCLI_BACKENDSdiscovery allowlist;AGY_CLI_MODELSfallback rather than Copilot's list.The fallback is the exact 11-ID order returned by the locally installed
Antigravity CLI 1.1.18 on 2026-08-31:
These are preserved verbatim. In particular, the
-high/-medium/-lowsuffixes are part of Antigravity's model IDs; this PR does not reinterpret them
as Hive's separate reasoning-effort setting.
Account-aware server discovery
New
src/pkg/dashboard/cli_models_agy.goadds agy to the existing CLI modelpipeline:
agy modelsis bounded by a five-second timeout and parsed as the CLI'sobserved tab-delimited
<id>\t<display name>output;/data/homeexists, the subprocess runs with that HOME and workingdirectory. Per-UID interactive homes already bridge
.geminiback there, sothe probe sees the same signed-in account as the agents without guessing one
agent's home or reading OAuth files itself;
and never copied into Hive logs;
or an empty list returns
fallback=trueand the static floor. A format changeis never treated as an authoritative empty catalog, which could otherwise
auto-heal agents away from working models;
retention machinery, so one transient omission does not churn agent models.
handleBackendsnow returns an agy entry with its models and fallback flag, andthe frontend consumes it through the same
/api/config/backendspath as theother CLIs.
Regression coverage and operator record
cli_models_agy_test.gocovers the output parser, live and failed probes, themissing-binary path, UI visibility, exact frontend/Go fallback parity, and the
actual
/api/config/backendswire response. The generic picker-parity comment isupdated to point backend-specific visibility promises at explicit tests, while
retaining its original picker-must-be-dispatchable invariant.
CHANGELOG.mdrecords the user-visible method and model selection support underUnreleased → Added.
Design decisions and boundaries
Use
agy models, not the Gemini API. Antigravity's observed catalog is not aGemini-only list: it includes Claude and GPT-OSS IDs and is scoped to the Google
account signed into the CLI. Reusing
discoverGeminiModelswould query adifferent product/auth mechanism and return models that are not proof of agy
support.
Live list plus static floor, not either one alone. A hardcoded-only list
would become stale as Google changes the service. A live-only list would leave a
blank dropdown on first paint, on developer builds without the binary, and on a
hive whose operator has not signed in yet. The existing
fallbackcontractmakes that distinction visible and prevents fallback data from driving
auto-heal.
No OAuth handling in Hive. The probe delegates credential resolution to the
vendor CLI and does not parse, refresh, log, or transport
.geminicontents.This preserves the existing ownership boundary and avoids rotating state out
from under a running agent.
No authentication claim. This does not solve fresh headless Kubernetes
authentication. agy still has interactive Google OAuth and no API-key mode; an
operator must seed a usable session. #5406 remains open for verifying that path.
No launcher or effort change. Selecting a model still reaches the existing
launch command as
--model <id> --effort low. agy requires an effort flagwhenever a model is supplied; per-agent effort selection is a separate feature
and is not introduced here.
Testing
cd src && env GOCACHE="$PWD/.test-cache/go" GOTMPDIR="$PWD/.test-cache/tmp" CCACHE_DIR="$PWD/.test-cache/ccache" go build ./...— passed.
cd src && env GOCACHE="$PWD/.test-cache/go" GOTMPDIR="$PWD/.test-cache/tmp" CCACHE_DIR="$PWD/.test-cache/ccache" go test ./pkg/dashboard -count=1— passed,
55.490s.cd src && env GOCACHE="$PWD/.test-cache/go" GOTMPDIR="$PWD/.test-cache/tmp" CCACHE_DIR="$PWD/.test-cache/ccache" go test ./pkg/dashboard -run '^(TestParseAgyModelsOutput|TestParseAgyModelsOutputRejectsChangedFormat|TestQueryCLIModelsAgyLiveInventory|TestQueryCLIModelsAgyFailureUsesStaticFallback|TestExecAgyModelsProbeBinaryMissing|TestDashboardOffersAgyWithDedicatedModels|TestHandleBackendsServesAgyInventory|TestBackendPickerOffersOnlyDispatchableBackends|TestBackendPickerInferenceListMatchesGo)$' -count=1— passed (
0.038s): parser success/changed-format refusal,live/fallback/missing-binary discovery, picker visibility and dispatchability,
exact JS/Go fallback parity, and backend API response.
cd src && env GOCACHE="$PWD/.test-cache/go" GOTMPDIR="$PWD/.test-cache/tmp" CCACHE_DIR="$PWD/.test-cache/ccache" go test ./pkg/config -run '^(TestValidateBackend_AcceptsAllSupported|TestShellAndGoCLIBackendListsAgree|TestBackendBinaryAndPermFlagCoverKnownBackends)$' -count=1— passed (
0.071s).cd src && env GOCACHE="$PWD/.test-cache/go" GOTMPDIR="$PWD/.test-cache/tmp" CCACHE_DIR="$PWD/.test-cache/ccache" go test ./pkg/agent -run '^(TestStart_AgyLaunchCommandLine|TestAgyLaunchCommandLine_NoModel|TestInvocationMetadata|TestBackendBinaryName_AgyLaunchesAntigravityCLI|TestAcceptedBackendsAreLaunchableByConstruction)$' -count=1— passed (
0.005s).agy --version/agy modelsagainst the existing signed-in local CLI —version
1.1.18, 11 records matching the checked-in fallback order.cd src && env GOCACHE="$PWD/.test-cache/go" GOTMPDIR="$PWD/.test-cache/tmp" CCACHE_DIR="$PWD/.test-cache/ccache" go test ./pkg/config ./pkg/agent -count=1— the broad runreached unrelated environment-sensitive failures.
pkg/config'sTestGateFailsClosedWithoutIP6Tablessaw the host's real unprivilegedip6tables(Permission denied) instead of its intended missing-binarycondition, and three
TestEntrypointHardensRuntimeConfigItRecreatescasescould not
chownwithout root/CAP_CHOWN, leaving test files 0644 instead of0600.
pkg/agenthad one timing failure,TestSendKick_RestartsCrashedCLIThenDelivers; rerunning that exact test inisolation passed in
9.415s. None touches dashboard/model discovery code.The default Go and ccache locations are read-only in this workspace, so the
commands above redirect only build caches into a temporary, removed directory;
the tested source and command semantics are otherwise unchanged.
Related issues
Related: #5406 tracks the still-unverified agy headless Kubernetes authentication
path; this PR deliberately does not close it.
Contributor checklist
v4(the repository's default branch).git commit -s).user-visible change is recorded in
CHANGELOG.md; the existing backend setupguide already documents agy's install, auth, model, effort, and confinement
contract.
CHANGELOG.mdhas an entry under Unreleased → Added.account data are committed.