feat(cli): add agy (Antigravity CLI) as an agent backend#1430
Open
charliezong18 wants to merge 3 commits into
Open
feat(cli): add agy (Antigravity CLI) as an agent backend#1430charliezong18 wants to merge 3 commits into
charliezong18 wants to merge 3 commits into
Conversation
Add agy — Google's Antigravity CLI — as a first-class agent backend so it can be used inside Happy as a fallback when Claude Code hits usage limits. agy has no ACP/JSON streaming mode; its only non-interactive surface is `agy --print`, which streams plain text and persists a per-cwd conversation for resume. It therefore follows the bespoke (non-ACP) openclaw pattern rather than the gemini ACP integration: - src/agy/: constants, types, cliArgs (buildAgyArgs), conversationStore, AgyBackend (spawns `agy --print` per turn, streams stdout -> AgentMessage), runAgy (orchestrator mirroring runOpenClaw), plus ui/ink/AgyDisplay.tsx. - AgyBackend spawns with stdio ['ignore','pipe','pipe']: agy --print blocks until stdin hits EOF, so an open stdin pipe hangs the turn forever. - Permission mapping: yolo/safe-yolo/bypassPermissions/acceptEdits -> --dangerously-skip-permissions; otherwise --sandbox. - Registered 'agy' everywhere 'openclaw' appears: detectCLI, index.ts subcommand + help, daemon/run.ts dispatch, AgentId, BackendFlavor, controlServer z.enum, registerCommonHandlers; happy-agent SupportedAgent + SUPPORTED_AGENTS; happy-app picker (agentDefaults, persistence, new-session picker + icon, settings labels, storageTypes cliAvailability, ops spawn unions, AgentInput). - Tests: agy/cliArgs.test.ts + agy/AgyBackend.test.ts (10 tests). Additive: the existing gemini integration is unchanged. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
The standalone gemini CLI is EOL and agy (Antigravity CLI) is its successor, so steer users toward `happy agy`. Gemini stays fully functional — this only adds deprecation signals: - index.ts: console.warn on `happy gemini` startup pointing to agy; mark the help line "[deprecated — use agy]". - happy-cli/README.md: mark `happy gemini` deprecated and document `happy agy` in the agents list, commands table, and requirements. - happy-app new-session picker: label gemini "gemini (deprecated)". Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
Multi-model review (Gemini via agy + DeepSeek) of the agy backend surfaced three issues, now fixed in AgyBackend.sendPrompt: - Guard against duplicate terminal handling: Node fires both 'error' and 'close' on spawn failure, which previously emitted two status:'error' messages and rejected twice. A `settled` flag now processes only the first. - Avoid the this.child overwrite race: only null `this.child` when it still points at this child (cleanup() guard), so a late close from a cancelled turn can't orphan a newer turn's process. - Add a Node-side watchdog: `agy --print` is bounded by --print-timeout, but if it hangs the turn would never settle; kill the child after the parsed timeout + 30s buffer. Tests: add no-double-emit (error→close) and cancel()-kills-child cases. Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude <noreply@anthropic.com> Co-Authored-By: Happy <yesreply@happy.engineering>
9b91d5e to
5ed0750
Compare
Author
|
hey @bra1nDump — thanks again for the quick turnaround on #1440! 🙏 whenever you've got bandwidth, #1430 (agy / Antigravity CLI backend) is also ready for a look. it's bigger (~1.2k lines) but fully additive — the gemini provider is untouched, it just registers i wrote up the design rationale in #1429 (tl;dr: agy has no ACP/JSON mode, so it follows the bespoke |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What & why
Adds agy — Google's Antigravity CLI — as a first-class agent backend, so it can be driven from Happy (terminal + phone/web app) as a fallback when Claude Code hits its usage limit.
Additive: the existing Gemini integration is untouched.
Design
agy has no ACP / JSON streaming mode (unlike Gemini = ACP, Codex = app-server JSON-RPC). Its only stable non-interactive surface is
agy --print "<prompt>", which streams plain text and persists a per-cwd conversation for resume. So it can't reuseAcpBackend— it follows the bespoke (non-ACP)openclawpattern instead: a backend that translates its own output into Happy'sAgentMessagestream and rides the same session pipeline, app-selectable without the ACP /MessageAdapter/agentRegistrymachinery.New
packages/happy-cli/src/agy/:constants,types,cliArgs(buildAgyArgs),conversationStoreAgyBackend— spawnsagy --printper turn, streams stdout →AgentMessagerunAgy— orchestrator mirroringrunOpenClawui/ink/AgyDisplay.tsx— terminal status viewKey details:
agy --printblocks until stdin reaches EOF, soAgyBackendspawns withstdio: ['ignore', 'pipe', 'pipe']. An open stdin pipe hangs the turn forever (caught during testing).yolo/safe-yolo/bypassPermissions/acceptEdits→--dangerously-skip-permissions; otherwise--sandbox. (Print mode is one-shot and can't surface an interactive approval prompt, so non-skip modes defer to agy's ownsettings.json.)--conversation.--model "<display name>"; defaults to a Gemini model (the fallback exists because Claude is rate-limited).Registration
'agy'added everywhere'openclaw'already appears:detectCLI,index.tssubcommand + help,daemon/run.tsdispatch,AgentId,BackendFlavor,controlServerzod enum,registerCommonHandlers.SupportedAgent,SUPPORTED_AGENTS.agentDefaults,persistence, picker + icon, settings labels,storageTypescliAvailability,opsspawn unions,AgentInput).Tests
agy/cliArgs.test.ts+agy/AgyBackend.test.ts(10 tests, incl. the stdin-EOF guard). Full happy-cli unit suite passes (691/691); happy-cli, happy-agent, and happy-app all typecheck.Notes / follow-ups (not done here)
agentapiHTTP server (structured tool / permission events) is possible later, but it needs an undocumented running language-server — out of scope.Visual proof
agy driven end-to-end from the Happy app, not just unit tests: a Happy session running the
agybackend — online, answering a prompt and correctly identifying itself as Antigravity (Gemini 3.1 Pro). This shows the backend spawns, streams its output back into Happy'sAgentMessagepipeline, and is usable from the app/browser.Closes #1429
Refs #1313