Skip to content

Add Antigravity (agy) provider via an ACP compatibility bridge#4497

Open
agentool wants to merge 1 commit into
pingdotgg:mainfrom
agentool:antigravity-provider
Open

Add Antigravity (agy) provider via an ACP compatibility bridge#4497
agentool wants to merge 1 commit into
pingdotgg:mainfrom
agentool:antigravity-provider

Conversation

@agentool

@agentool agentool commented Jul 25, 2026

Copy link
Copy Markdown

Adds antigravity as a provider driver alongside Codex, Claude, Cursor, Grok and OpenCode.

Up front, re: CONTRIBUTING: this is large (+3442) and unsolicited, and I did not open an issue first. Opening it anyway as a working reference rather than a request for your time — if the answer is no, close it and it costs you nothing. Notes on scope and on splitting it are at the bottom.

Why this needs a bridge rather than another ACP driver

Antigravity ships no native agent protocol. Verified against agy 1.1.7:

  • agy agent stdiounexpected arguments: [stdio] (Grok's entrypoint is grok agent stdio)
  • no --acp flag; the binary carries jsonrpc2 and MCP, but no ACP methods
  • Antigravity.app/Contents/Resources/bin/language_server speaks Codeium gRPC (exa.language_server_pb), not ACP

So provider/acp/antigravity/agyBridge.ts presents the ACP surface AcpSessionRuntime already expects, and runs each turn through the documented non-interactive agy --print. It ships as hidden subcommands of the server binary (t3 agy-acp, t3 agy-hook) so it versions with the server and adds no build artifact.

How the event stream is reconstructed

Two documented Antigravity sources correlate on step index — a hook's stepIdx is the transcript record's step_index:

Signal Source
Tool start, name, args, human title (toolSummary) PreToolUse hook
Tool output (real stdout / file contents) transcript record with matching step_index
Tool completed/failed PostToolUse hook
Assistant text, streamed during the turn PLANNER_RESPONSE records as they land
conversationId for resume present on every hook

Neither source alone is sufficient: hooks never carry tool output, the transcript never carries tool arguments.

Three things that cost real debugging time

--add-dir replaces the workspace, it does not extend cwd. Hooks are registered via a throwaway --add-dir workspace so nothing is written into the user's repo — but passing only that dir makes the project invisible to the agent. Both the session cwd and the hook workspace are passed.

Edit diffs must be captured inside the hook process. Both hooks for a fast edit land within one 50ms poll, so reading the file while draining hook output makes "before" read back as "after". The hook brackets the tool call and is the only place that sees true pre-edit state.

Probes must set stdin: "ignore". agy starts a language server and emits nothing while stdin stays open; ChildProcess defaults stdin to "pipe", which hangs it. Presented as installed: true, models: 0 while agy models worked by hand.

Known constraints

All inherent to print mode, documented in AGENTS.md:

  • tools auto-approve (--dangerously-skip-permissions); no approval flow is possible
  • no image attachments, no session modes
  • model binds at spawn, so sessionModelSwitch is "unsupported"
  • assistant text streams per planner step, not per token

The trajectory JSONL format is undocumented. Every parse path degrades to emitting nothing rather than failing a turn, so an agy release that changes it costs observability, not correctness.

UI surface

No new components. The provider renders through the existing rows: PROVIDER_OPTIONS, PROVIDER_ICON_BY_PROVIDER, and PROVIDER_CLIENT_DEFINITIONS, reusing the AntigravityIcon already in Icons.tsx for the editor integration, with an Experimental badge in the same slot Cursor and Grok use for Early Access. CONTRIBUTING asks for before/after images on UI changes — I don't have a clean way to attach them here; the visible delta is one additional provider row.

Verification

  • 1076 tests pass (6 skipped), including 39 new across agyEvents, agyTranscript, AntigravityAcpSupport
  • 0 type errors, 0 lint errors, format clean
  • pnpm build clean; bridge bundles into dist/bin.mjs and all three entrypoints work off the built binary
  • live probe: status: ready | version: 1.1.7 | models: 11
  • a full turn driven through the built binary against real agy: tool calls, real tool output, a file edit with diff, stopReason: end_turn, file on disk actually changed

Three ProviderRegistry fixtures assert an exact provider list or that only the subject provider probes, so they gain the new driver.

On size

Most of the diff is AntigravityAdapter.ts (~690 lines), which follows the existing convention of one standalone adapter per provider (Cursor 1.2k, Grok 1.5k, Claude 3.9k) over the shared ACP helpers. I deliberately did not refactor a shared adapter core out of GrokAdapter, since that would mean touching a working provider to land a new one.

Happy to split this into (1) contracts + bridge + tests and (2) driver + UI wiring, or to drop the text-generation backend, if either would make it reviewable. Equally happy for you to take the bridge approach and reimplement it your way — the --add-dir, hook-timing and stdin findings above are the parts that were expensive to discover.


Note

High Risk
Large new agent execution path that auto-approves tools via --dangerously-skip-permissions and shells out to agy; transcript parsing is best-effort so behavior can drift with CLI changes.

Overview
Adds an experimental antigravity provider for the Antigravity CLI (agy), which has no native agent protocol. Sessions talk to a bundled ACP compatibility bridge (t3 agy-acp / t3 agy-hook) that runs each turn with agy --print and maps hook events plus transcript.jsonl (correlated by step index) into the same runtime events other ACP drivers use.

Server: new driver, adapter, health/model discovery (agy models / --version with stdin: "ignore"), spawn wiring via AntigravityAcpSupport, optional git/text-generation through the bridge, and hidden CLI subcommands registered on the t3 binary. Contracts & web: AntigravitySettings, defaults/aliases, settings form, picker row, and icon. Docs/tests: AGENTS.md bridge constraints; unit tests for hooks/transcript parsing; registry tests disable or expect the new built-in instance.

Reviewed by Cursor Bugbot for commit df9a3f1. Bugbot is set up for automated code reviews on this repo. Configure here.

Note

Add Antigravity (agy) provider via an ACP compatibility bridge

  • Introduces a new antigravity provider driver that wraps the agy CLI tool using a stdio JSON-RPC bridge (t3 agy-acp) rather than native ACP, since Antigravity lacks a built-in ACP server.
  • The bridge spawns agy in print mode and reconstructs session events (tool calls, assistant text, file diffs) by polling hooks (t3 agy-hook) and tailing JSONL transcript files.
  • Adds full TextGeneration support (commit messages, PR content, branch names, thread titles) with a 180-second timeout and structured JSON decoding.
  • Adds settings schema, model slug aliases, health-check probing via agy --version and agy models, and an 'Experimental' badge in the provider picker UI.
  • Risk: print mode auto-approves all tools, does not forward images, and binds the model at session spawn — mid-session model switching is unsupported.

Macroscope summarized df9a3f1.

Antigravity ships no native agent protocol: `agy agent stdio` is not a
thing, and the bundled `language_server` speaks Codeium gRPC rather than
ACP. So this adds a bridge that presents the ACP surface
`AcpSessionRuntime` needs and runs each turn through the documented
non-interactive `agy --print`.

The bridge ships as hidden subcommands of the server binary (`t3 agy-acp`,
`t3 agy-hook`) so it always versions with the server and needs no separate
artifact.

A live event stream is reconstructed from two documented Antigravity
sources that correlate on step index (a hook's `stepIdx` is the transcript
record's `step_index`):

  - Hooks (PreToolUse/PostToolUse/Stop) supply tool name, arguments and
    completion status. They are registered through a throwaway `--add-dir`
    workspace, so nothing is written into the user's repository. Both the
    session cwd and that hook workspace are passed, because `--add-dir`
    replaces the workspace rather than extending cwd -- passing only the
    hook dir hides the project from the agent.
  - The trajectory transcript supplies assistant text and real tool output
    as the turn runs. Its format is undocumented, so every parse path
    degrades to emitting nothing rather than failing a turn.

File contents for an edit diff are captured inside the hook process. The
bridge cannot read them when it drains hook output: both hooks for a fast
edit land within a single poll interval, by which point "before" would
read back as "after".

Any `agy` subcommand spawned for a probe sets `stdin: "ignore"`. `agy`
starts a language server and emits nothing while stdin stays open, so the
default "pipe" hangs it and model discovery returns empty.

Known constraints, all inherent to print mode and documented in AGENTS.md:
tools auto-approve (`--dangerously-skip-permissions`) so no approval flow
is possible; no image attachments; no session modes; the model binds at
spawn, so `sessionModelSwitch` is "unsupported".

The three ProviderRegistry fixtures assert an exact provider list or that
only the subject provider probes, so they gain the new driver.
@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 91285988-23fc-40f4-9ae9-bf4be1db7242

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@github-actions github-actions Bot added vouch:unvouched PR author is not yet trusted in the VOUCHED list. size:XXL 1,000+ changed lines (additions + deletions). labels Jul 25, 2026

@cursor cursor Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using high effort and found 5 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.

Want fixes drafted automatically? Bugbot Autofix can create code changes for findings. A team admin can enable Autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit df9a3f1. Configure here.

return /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i.test(sessionId)
? sessionId
: undefined;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tool output dropped by drain order

Medium Severity

When the session map is missing or unreadable, lookupConversationId (lines 94-102) treats any UUID-formatted sessionId as an Antigravity conversation ID. This can cause session/load to incorrectly attempt resuming a conversation with the bridge's internal session ID instead of starting fresh.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit df9a3f1. Configure here.

}
const condensed = reported.replace(/transcript_full\.jsonl$/, "transcript.jsonl");
return NodeFS.existsSync(condensed) ? condensed : reported;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Transcript path switch reuses offset

Medium Severity

resolveTranscriptPath can switch from transcript_full.jsonl to transcript.jsonl mid-turn while transcriptOffset keeps the prior file's byte position. Reads then skip or misalign early condensed records, dropping assistant text and tool output for that turn.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit df9a3f1. Configure here.

input.assistantText.emitted = true;
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tool output lost after post hook

High Severity

Each drain processes hooks before the transcript, and postToolUseUpdate removes the step from activeToolCalls. Transcript tool output only attaches while that step is still active, so when PostToolUse and the matching transcript record arrive in the same poll—common for fast tools—command and search output is dropped permanently. Post hooks never carry tool bodies, so there is no fallback.

Additional Locations (2)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit df9a3f1. Configure here.

cancelledSessions.add(sessionId);
}
activeChild?.kill("SIGTERM");
return;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale cancel poisons next turn

High Severity

session/cancel always adds the session to cancelledSessions, but that flag is only consumed at the end of runTurn. A cancel that arrives after a turn already finished—or while no child is running—stays set and makes the next successful prompt report stopReason: "cancelled".

Additional Locations (1)
Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit df9a3f1. Configure here.

issue:
"Turn requires non-empty text. Antigravity print mode does not accept attachments.",
});
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Turn starts before empty prompt check

Medium Severity

turn.started is emitted before the adapter rejects attachment-only or whitespace-only prompts. Those requests then fail validation with no matching turn.completed, so the turn can remain in progress in the UI even though Antigravity never accepted the prompt.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit df9a3f1. Configure here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:XXL 1,000+ changed lines (additions + deletions). vouch:unvouched PR author is not yet trusted in the VOUCHED list.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant