feat: add built-in Antigravity CLI (agy) agent plugin - #405
Conversation
Google's standalone gemini-cli is ineligible for individual OAuth; agy is the working path to Gemini/Claude/GPT-OSS. Register as a proper built-in (relative imports) to avoid OTUI env-var double-registration from external ralph-tui package imports. Co-authored-by: Cursor <cursoragent@cursor.com>
|
@djbclark is attempting to deploy a commit to the plgeek Team on Vercel. A member of the Team first needs to authorize it. |
📝 WalkthroughWalkthroughAdds a complete Antigravity ( ChangesAntigravity agent
Estimated code review effort: 4 (Complex) | ~45 minutes Sequence Diagram(s)sequenceDiagram
participant AntigravityAgentPlugin
participant agy CLI
participant JSONL parser
participant Execution callbacks
AntigravityAgentPlugin->>agy CLI: Send arguments and prompt through stdin
agy CLI-->>AntigravityAgentPlugin: Stream JSONL output
AntigravityAgentPlugin->>JSONL parser: Parse complete lines
JSONL parser-->>Execution callbacks: Emit text, tool, and error events
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches 💡 1🛠️ Fix failing CI checks 💡
Warning There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure. 🔧 ESLint
ESLint install failed. For unrecoverable errors, disable the tool in CodeRabbit configuration. 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. Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🧹 Nitpick comments (6)
src/plugins/agents/builtin/antigravity.test.ts (2)
160-168: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueCall the protected members directly; the
unknowncasts are unnecessary.
TestableAntigravityPluginextendsAntigravityAgentPlugin, so it can access theprotectedbuildArgsandgetStdinInputmembers without a cast. Removing the casts keeps the tests type-checked against the real signatures.♻️ Proposed refactor
class TestableAntigravityPlugin extends AntigravityAgentPlugin { testBuildArgs(prompt: string): string[] { - return (this as unknown as { buildArgs: (p: string) => string[] }).buildArgs(prompt); + return this.buildArgs(prompt); } testGetStdinInput(prompt: string): string | undefined { - return (this as unknown as { getStdinInput: (p: string) => string | undefined }).getStdinInput(prompt); + return this.getStdinInput(prompt); } }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/agents/builtin/antigravity.test.ts` around lines 160 - 168, Update TestableAntigravityPlugin.testBuildArgs and testGetStdinInput to call the inherited protected buildArgs and getStdinInput members directly, removing the unknown casts and duplicate method type annotations while preserving their existing return behavior.
373-405: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winAdd coverage for the chunked stdout buffering in
execute.The tests cover the parser but not the buffering in
antigravity.tsLines 349-433. That code holds a partial JSONL line acrossonStdoutchunks and flushes it inonEnd. It is the most defect-prone logic in this PR. Add a test that feeds one JSON object split across two chunks and asserts that exactly one text event reachesonStdout.Do you want me to generate this test?
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/agents/builtin/antigravity.test.ts` around lines 373 - 405, Add a test covering execute’s stdout buffering in antigravity.ts: feed one JSONL object split across two onStdout chunks, then trigger onEnd and assert exactly one text event is delivered to onStdout. Keep the existing parser tests unchanged and verify the reconstructed event content.src/plugins/agents/builtin/antigravity.ts (4)
447-457: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueSimplify
validateModel; all three branches returnnull.The checks at Line 448 and Lines 453-455 are dead code. The
model === undefinedcomparison is also unreachable because the parameter type isstring. Keep the explanatory comment and returnnulldirectly.♻️ Proposed refactor
override validateModel(model: string): string | null { - if (model === '' || model === undefined) { - return null; - } // Accept any non-empty model string — `agy models` list drifts over time. // Known IDs are offered in setup; custom/newer IDs should still work. - if (model.trim().length === 0) { - return null; - } + void model; return null; }🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/agents/builtin/antigravity.ts` around lines 447 - 457, In Antigravity’s validateModel method, remove the redundant empty/undefined and whitespace checks, preserve the explanatory comment about accepting any non-empty or custom model string, and return null directly.
349-433: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winExtract the shared JSONL emit logic from
flushBufferand theonStdoutwrapper.Lines 354-377 and Lines 398-426 implement the same two steps: forward raw JSON objects to
onJsonlMessage, then parse the text into display events and forward them toonStdoutSegmentsandonStdout. The buffering logic is correct, so this is a maintainability change only. A single helper keeps the two paths from drifting.♻️ Proposed refactor
+ const emitJsonlMessages = (lines: string[]) => { + if (!options?.onJsonlMessage) return; + for (const line of lines) { + const trimmed = line.trim(); + if (!trimmed.startsWith('{')) continue; + try { + options.onJsonlMessage(JSON.parse(trimmed)); + } catch { + // Not valid JSON, skip + } + } + }; + + const emitDisplayEvents = (text: string) => { + const events = parseAntigravityOutputToEvents(text); + if (events.length === 0) return; + if (options?.onStdoutSegments) { + const segments = processAgentEventsToSegments(events); + if (segments.length > 0) options.onStdoutSegments(segments); + } + if (options?.onStdout) { + const formatted = processAgentEvents(events); + if (formatted.length > 0) options.onStdout(formatted); + } + }; + const flushBuffer = () => { if (!jsonlBuffer) return; const trimmed = jsonlBuffer.trim(); + jsonlBuffer = ''; if (!trimmed) return; - ... + emitJsonlMessages([trimmed]); + emitDisplayEvents(trimmed); };Then call
emitJsonlMessages(lines)andemitDisplayEvents(completeData)inside theonStdoutwrapper.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/agents/builtin/antigravity.ts` around lines 349 - 433, Extract the duplicated JSONL forwarding and display-event forwarding from flushBuffer and the parsedOptions.onStdout wrapper into shared local helpers, such as emitJsonlMessages and emitDisplayEvents. Replace both inline implementations with calls to those helpers, while preserving the existing buffering behavior and callback ordering.
224-262: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueDeclare
timerbeforesafeResolveto remove the temporal-dead-zone dependency.
safeResolvereadstimerat Line 227, buttimeris declared at Line 259. The current code is safe because every call site runs asynchronously. A future synchronous call would throw aReferenceError. Declare the handle first withlet timer: ReturnType<typeof setTimeout> | undefined;and assign it later.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/agents/builtin/antigravity.ts` around lines 224 - 262, Declare the timer handle before the safeResolve callback in the version-check flow, using an optional ReturnType<typeof setTimeout> variable, then assign it when creating the timeout. Update safeResolve to safely clear the possibly undefined timer while preserving the existing settlement behavior.
71-94: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low valueExtract
tool_infoonce to remove the duplicated type guard.The same
tool_infoobject check runs twice, at Lines 75-79 and Lines 82-86. A single narrowed local makes the branch easier to read. Behavior stays the same.♻️ Proposed refactor
} else if (stepType === 'tool') { if (state === 'ACTIVE') { - const toolName = - (typeof step.tool_name === 'string' && step.tool_name) || - (step.tool_info != null && - typeof step.tool_info === 'object' && - !Array.isArray(step.tool_info) && - typeof (step.tool_info as Record<string, unknown>).name === 'string' - ? ((step.tool_info as Record<string, unknown>).name as string) - : 'unknown'); - let toolInput: Record<string, unknown> | undefined; - if ( - step.tool_info != null && - typeof step.tool_info === 'object' && - !Array.isArray(step.tool_info) - ) { - const info = step.tool_info as Record<string, unknown>; - if (info.parameters != null && typeof info.parameters === 'object' && !Array.isArray(info.parameters)) { - toolInput = info.parameters as Record<string, unknown>; - } else { - toolInput = info; - } - } + const info = + step.tool_info != null && + typeof step.tool_info === 'object' && + !Array.isArray(step.tool_info) + ? (step.tool_info as Record<string, unknown>) + : undefined; + const toolName = + (typeof step.tool_name === 'string' && step.tool_name) || + (typeof info?.name === 'string' ? info.name : 'unknown'); + let toolInput: Record<string, unknown> | undefined; + if (info) { + toolInput = + info.parameters != null && + typeof info.parameters === 'object' && + !Array.isArray(info.parameters) + ? (info.parameters as Record<string, unknown>) + : info; + } events.push({ type: 'tool_use', name: toolName, input: toolInput });🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@src/plugins/agents/builtin/antigravity.ts` around lines 71 - 94, Refactor the ACTIVE tool handling in the step-processing branch to narrow and store step.tool_info once in a local variable, then reuse that narrowed object for both toolName extraction and toolInput construction. Remove the duplicated object/array type guards while preserving the existing fallback names and parameter-selection behavior.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@website/content/docs/plugins/agents/antigravity.mdx`:
- Line 122: Update website/content/docs/plugins/agents/antigravity.mdx at lines
122-122 and 138-138: remove the claim that --print requires a prompt argument,
and replace the prohibition with the actual Ralph TUI plugin behavior, including
its specific reason for omitting --print if intentional.
- Line 23: Update the authentication guidance at
website/content/docs/plugins/agents/antigravity.mdx lines 23-23 to instruct
users to run agy interactively and complete browser-based Google Sign-In,
removing the oauth_creds.json requirement. Update the troubleshooting step at
website/content/docs/plugins/agents/antigravity.mdx lines 154-154 to remove
credential-directory checks; retain ~/.gemini references only for plugin
configuration or skill paths.
---
Nitpick comments:
In `@src/plugins/agents/builtin/antigravity.test.ts`:
- Around line 160-168: Update TestableAntigravityPlugin.testBuildArgs and
testGetStdinInput to call the inherited protected buildArgs and getStdinInput
members directly, removing the unknown casts and duplicate method type
annotations while preserving their existing return behavior.
- Around line 373-405: Add a test covering execute’s stdout buffering in
antigravity.ts: feed one JSONL object split across two onStdout chunks, then
trigger onEnd and assert exactly one text event is delivered to onStdout. Keep
the existing parser tests unchanged and verify the reconstructed event content.
In `@src/plugins/agents/builtin/antigravity.ts`:
- Around line 447-457: In Antigravity’s validateModel method, remove the
redundant empty/undefined and whitespace checks, preserve the explanatory
comment about accepting any non-empty or custom model string, and return null
directly.
- Around line 349-433: Extract the duplicated JSONL forwarding and display-event
forwarding from flushBuffer and the parsedOptions.onStdout wrapper into shared
local helpers, such as emitJsonlMessages and emitDisplayEvents. Replace both
inline implementations with calls to those helpers, while preserving the
existing buffering behavior and callback ordering.
- Around line 224-262: Declare the timer handle before the safeResolve callback
in the version-check flow, using an optional ReturnType<typeof setTimeout>
variable, then assign it when creating the timeout. Update safeResolve to safely
clear the possibly undefined timer while preserving the existing settlement
behavior.
- Around line 71-94: Refactor the ACTIVE tool handling in the step-processing
branch to narrow and store step.tool_info once in a local variable, then reuse
that narrowed object for both toolName extraction and toolInput construction.
Remove the duplicated object/array type guards while preserving the existing
fallback names and parameter-selection behavior.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository UI
Review profile: CHILL
Plan: Pro Plus
Run ID: 0cdba8c8-9081-4e62-94c5-9d7a0e052c95
📒 Files selected for processing (6)
src/plugins/agents/builtin/antigravity.test.tssrc/plugins/agents/builtin/antigravity.tssrc/plugins/agents/builtin/index.tssrc/setup/skill-installer.tswebsite/content/docs/plugins/agents/antigravity.mdxwebsite/lib/navigation.ts
| agy models | ||
| ``` | ||
|
|
||
| Authenticate with your Google account so credentials exist under `~/.gemini` (for example `oauth_creds.json`). |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Correct the authentication guidance.
agy uses the operating-system keyring and falls back to browser-based Google Sign-In. It does not require an oauth_creds.json file under ~/.gemini. Tell users to run agy interactively and complete sign-in. Keep ~/.gemini references only for plugin configuration or skill paths. (antigravity.google)
website/content/docs/plugins/agents/antigravity.mdx#L23-L23: replace the credential-file requirement.website/content/docs/plugins/agents/antigravity.mdx#L154-L154: replace the credential-directory troubleshooting step.
📍 Affects 1 file
website/content/docs/plugins/agents/antigravity.mdx#L23-L23(this comment)website/content/docs/plugins/agents/antigravity.mdx#L154-L154
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/content/docs/plugins/agents/antigravity.mdx` at line 23, Update the
authentication guidance at website/content/docs/plugins/agents/antigravity.mdx
lines 23-23 to instruct users to run agy interactively and complete
browser-based Google Sign-In, removing the oauth_creds.json requirement. Update
the troubleshooting step at website/content/docs/plugins/agents/antigravity.mdx
lines 154-154 to remove credential-directory checks; retain ~/.gemini references
only for plugin configuration or skill paths.
| When Ralph TUI executes a task with Antigravity: | ||
|
|
||
| 1. **Build command**: `agy --output-format stream-json [--dangerously-skip-permissions] [--model …]` | ||
| 2. **Pass prompt via stdin**: Avoids shell escaping; `--print` is omitted because that flag requires a prompt argument |
There was a problem hiding this comment.
🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win
Remove the stale --print rationale.
Current AGY releases support headless --print / -p runs and explicitly handle authentication when stdin contains a piped prompt. Do not state that these flags cannot be used with stdin because they require a prompt argument. If Ralph TUI intentionally omits the flag, document the plugin-specific reason instead. (antigravity.google)
website/content/docs/plugins/agents/antigravity.mdx#L122-L122: remove the claim that--printrequires a prompt argument.website/content/docs/plugins/agents/antigravity.mdx#L138-L138: replace the prohibition with the actual plugin behavior.
📍 Affects 1 file
website/content/docs/plugins/agents/antigravity.mdx#L122-L122(this comment)website/content/docs/plugins/agents/antigravity.mdx#L138-L138
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@website/content/docs/plugins/agents/antigravity.mdx` at line 122, Update
website/content/docs/plugins/agents/antigravity.mdx at lines 122-122 and
138-138: remove the claim that --print requires a prompt argument, and replace
the prohibition with the actual Ralph TUI plugin behavior, including its
specific reason for omitting --print if intentional.
Summary
Adds a built-in agent plugin for Google's Antigravity CLI (
agy) — the multi-model (Gemini/Claude/GPT-OSS) CLI under a Google AI Pro subscription.Not a fix to the existing
geminiplugin — that one wraps Google's separate standalonegemini-cli, which as of 2026-08-02 returnsIneligibleTierErrorfor individual-account OAuth ("migrate to the Antigravity suite of products"). Antigravity is the actual working path to these models now.src/plugins/agents/builtin/antigravity.ts— modeled onpi.ts/gemini.ts, stdin prompt input,--output-format stream-jsonevent parsing,--dangerously-skip-permissionsbuiltin/index.ts,AGENT_ID_MAPinsetup/skill-installer.tswebsite/content/docs/plugins/agents/antigravity.mdx) + nav entryBuilt as a proper built-in (relative imports within the package) rather than an external user plugin — an earlier attempt at the latter hit a real bug where importing the published
ralph-tuipackage from outside triggers a duplicate@opentui/coreenvironment-variable registration crash.Test plan
bun run typecheck— cleanbun run build— cleanbun test src/plugins/agents/builtin/antigravity.test.ts— 44 passbun run dist/cli.js doctor --agent antigravity— HEALTHY (real preflight round-trip, not mocked)Summary by CodeRabbit
New Features
agy) CLI agent.Documentation
Tests