feat(antigravity): add Antigravity CLI OAuth provider - #29385
Conversation
## Summary Adds `antigravity-cli` as a first-class OAuth-backed inference provider. Hermes reads the local Antigravity CLI token store, refreshes access tokens with OAuth client credentials discovered from the installed `agy` binary or explicit environment overrides, and sends chat completions through the Code Assist daily agent backend using the same OpenAI-compatible facade as `google-gemini-cli`. This keeps the existing `gemini` API-key provider and `google-gemini-cli` OAuth provider separate. Users opt in by selecting `antigravity-cli` from `hermes model` or by setting `HERMES_INFERENCE_PROVIDER=antigravity-cli`. ## Architecture - `agent/antigravity_oauth.py`: Antigravity token-file loading, refresh, cross-process locking, atomic writes, credential clearing, and OAuth client credential discovery from `agy`. - `agent/gemini_cloudcode_adapter.py`: Adds a `credential_source` switch so the existing Cloud Code adapter can use Antigravity OAuth tokens and the daily agent request envelope without changing Gemini CLI behavior. - `agent/google_code_assist.py`: Allows the shared project-context discovery helpers to target the Antigravity daily Code Assist endpoint. - `hermes_cli/auth.py`, `runtime_provider.py`, `providers.py`, `models.py`, `config.py`, `main.py`, and `auth_commands.py`: Provider registration, aliases, optional environment variables, runtime credential resolution, `hermes auth` integration, and the interactive model flow. - `agent/transports/chat_completions.py` and `agent/agent_runtime_helpers.py`: Route `antigravity-cli` through `GeminiCloudCodeClient` with `credential_source="antigravity-cli"`. ## Provider behavior - Antigravity token source is isolated from the Gemini CLI OAuth store: `~/.gemini/antigravity-cli/antigravity-oauth-token`. - Hermes does not start its own Antigravity browser login. If the token file is missing, the model flow tells users to run `agy` and complete Antigravity login. - Hermes does not write discovered project IDs back into the Antigravity token file. Project context is resolved per client and cached in memory. - Model choices follow the same curated-provider pattern as `google-gemini-cli`; the picker does not dump raw backend model keys. - The model flow shows an upfront warning and requires explicit `y` confirmation before reading or refreshing local Antigravity OAuth credentials. - Refresh tries all discovered OAuth client credential candidates before treating `invalid_grant` as authoritative and clearing the token file. ## Public contribution hygiene - No real OAuth client secrets, refresh tokens, API keys, local paths, or private configuration are checked in. - Test credentials are explicit placeholders. - Public commit metadata uses the GitHub noreply identity. ## Tests Focused regression coverage includes: - Antigravity OAuth token load/save/refresh, invalid-grant clearing, multi-candidate client fallback, malformed expiry handling, metadata preservation, concurrent refresh dedupe, and runtime credential shape. - Provider registration, aliases, optional env vars, auth command wiring, runtime provider dispatch, and model/config persistence. - Interactive model flow success, missing-token no-op, and warning cancellation. - Cloud Code adapter routing with Antigravity credential source, daily backend agent envelope, project-context isolation, model ID pass-through, thinking config preservation, streaming SSE, non-streaming SSE aggregation, and non-streaming SSE tool-call aggregation. - Chat completions transport and run-agent client construction. - Opt-in live smoke test for Antigravity recommended Gemini models. Test commands run: - `scripts/run_tests.sh tests/hermes_cli/test_model_provider_persistence.py tests/agent/test_antigravity_oauth.py tests/agent/test_gemini_cloudcode.py tests/agent/transports/test_chat_completions.py tests/run_agent/test_antigravity_cloudcode_client.py` -> 196 passed in the public extraction workspace. - Same focused suite in the private development workspace -> 190 passed. - `HERMES_LIVE_TESTS=1 scripts/run_tests.sh tests/agent/test_antigravity_cloudcode_live.py` -> 1 passed. - `git diff --check upstream/main...HEAD` -> clean. - `python -m py_compile` on changed runtime and test modules -> clean.
3a873fd to
1defe12
Compare
|
Thanks for putting this together. I wanted to flag that there is now an alternate implementation in #29474, with a different auth/model-discovery tradeoff rather than a disagreement with the overall Antigravity-provider direction. The main differences are:
Your approach has clear merits, especially keeping initial login owned by the official CLI and avoiding shelling out to |
|
For maintainers comparing the two Antigravity approaches: I've posted a neutral side-by-side of where #29385 and this PR's alternate (#29474) diverge — credential source, login ownership, model discovery, adapter shape — at #29474 (comment) . It's framed as tradeoffs rather than a recommendation, to make the auth-boundary choice explicit. |
Documentation: Antigravity (Windows) Integration in HermesThis document records the necessary modifications to make the 1. The Problem with the Original Pull RequestsHermes relied on two major PRs that introduced the PR 29474: Browser-Based OAuth ApproachThis PR implemented a native adapter inside Hermes with an OAuth flow identical to the Google Gemini CLI (opening the browser, exchanging codes for tokens, and writing to a
PR 29385: Binary Reading Approach (Linux/macOS)This PR suggested not rebuilding the OAuth flow from scratch, but rather reading the token that the
2. The Implemented Hybrid SolutionWe took the excellent architecture and adapters from PR 29474 and implemented the credential interception logic from PR 29385, but completely rewritten specifically for Windows cryptography and credential vault APIs. Change 1:
|
|
Superseded by #50454 (merged) — #50454 We landed the native |
Summary
Adds
antigravity-clias an OAuth-backed inference provider for Hermes.The implementation keeps Antigravity separate from both the regular
geminiAPI-key provider and the existinggoogle-gemini-cliOAuth provider. Users opt in by selectingantigravity-clifromhermes modelor by settingHERMES_INFERENCE_PROVIDER=antigravity-cli.Why
Google has announced that Antigravity CLI is the consumer migration path for Gemini CLI. The official Google Developers Blog post, "An important update: Transitioning Gemini CLI to Antigravity CLI", says Antigravity CLI is available now and gives a June 18, 2026 transition date for consumer Gemini CLI / Gemini Code Assist request serving.
Hermes already supports Gemini CLI OAuth as a provider. Adding an isolated
antigravity-cliprovider keeps that subscription-backed workflow available as Google moves consumer usage toward Antigravity CLI, while avoiding changes to the existing Gemini CLI and API-key Gemini providers.Implementation
~/.gemini/antigravity-cli/antigravity-oauth-token.agybinary or explicit environment overrides.GeminiCloudCodeClientpath with acredential_sourceswitch for Antigravity-specific auth and the daily Code Assist agent endpoint.hermes modelandhermes authsupport, provider aliases, config/env wiring, docs, and focused regression coverage.agyfirst.Design Notes and Alternatives Considered
google-gemini-cli: Antigravity uses a separate CLI token store, daily Code Assist endpoint, user-agent/request-type envelope, and request ID shape. Keeping it behindantigravity-cliavoids changing Gemini CLI behavior and makes the new path easy to remove or adjust if Antigravity changes.agy --print:agy --printis an agent CLI, not a stable transport API. It can perform workspace/config inspection and its native auth behavior may depend on OS-level login state. Hermes needs a deterministic provider adapter, so this follows the existing Gemini CLI provider pattern and calls the Code Assist backend directly.agyfirst.streamGenerateContent?alt=sseCode Assist path. For OpenAI-compatiblestream=Falsecalls, Hermes still sends the Antigravity request through that SSE endpoint and aggregates the events back into a normal non-streaming completion. Forstream=True, Hermes exposes OpenAI-shaped delta chunks. This avoids inventing an unverified non-streaming Antigravity endpoint while preserving the OpenAI-compatible interface.HERMES_LIVE_TESTS=1.Compatibility and Risk Controls
geminiandgoogle-gemini-clibehavior is unchanged.invalid_grantas final and clearing local credentials.HERMES_LIVE_TESTS=1.Known Limitations
antigravity-cliso it can be adjusted without changing existing Gemini providers.agyfirst so the official CLI owns browser login and token-file creation.agy --print; that path is intentionally avoided because it is an agent CLI, not a deterministic provider transport.GeminiCloudCodeClientbehavior; this PR focuses on provider support, request/response translation, tool calls, reasoning text, and streaming/non-streaming completion behavior.Reviewer Notes
Antigravity CLI is new, so this intentionally mirrors the existing Gemini CLI provider shape where possible while isolating Antigravity-specific token storage and request-envelope behavior behind the new provider.
The model flow includes an explicit warning before reusing local CLI OAuth credentials. Refresh tries all discovered OAuth client credential candidates before treating
invalid_grantas final and clearing the local token file.Verification
scripts/run_tests.sh tests/hermes_cli/test_model_provider_persistence.py tests/agent/test_antigravity_oauth.py tests/agent/test_gemini_cloudcode.py tests/agent/transports/test_chat_completions.py tests/run_agent/test_antigravity_cloudcode_client.pyHERMES_LIVE_TESTS=1 scripts/run_tests.sh tests/agent/test_antigravity_cloudcode_live.pygit diff --check upstream/main...HEADpython -m py_compileon changed runtime and test modules