Skip to content

feat: add the Gemini agent driver (@agentry/gemini) - #4

Merged
dortort merged 5 commits into
mainfrom
feat/gemini-driver
Aug 8, 2026
Merged

feat: add the Gemini agent driver (@agentry/gemini)#4
dortort merged 5 commits into
mainfrom
feat/gemini-driver

Conversation

@dortort

@dortort dortort commented Aug 8, 2026

Copy link
Copy Markdown
Owner

Summary

Adds @agentry/gemini, a driver that drives the Gemini CLI headlessly via gemini -p --output-format stream-json and normalizes its native stream into the shared Agentry AgentEvent model — the same contract @agentry/claude implements. Wires it into the CLI so agentry test/record can target Gemini with use: { agent: 'gemini' }.

Delivers part of the Phase 5 "cross-agent adapters" roadmap item (spike-gated).

How it works

The event schema was captured live from gemini-cli 0.54.4 (the Phase 0.12 feasibility spike) and cross-checked against the CLI's bundled StreamJsonFormatter. parseGeminiEvents is a pure whole-stream mapper:

Native (--output-format stream-json) AgentEvent
init run.start
message{role,content,delta?} message
tool_use{tool_name,tool_id,parameters} tool_use
tool_result{tool_id,status,output} tool_result
error{severity,message} error
result{status,stats} usage + run.end

Key detail: Gemini streams assistant text as multiple {role:"assistant", delta:true} chunks. The parser coalesces consecutive assistant deltas into a single message (so turns/lastMessage stay correct) — this is why it's whole-stream rather than per-event. Usage and run.end come from the terminal result event. Spawns with stdin ignored.

Capabilities

{ structuredStream: true, llmInterception: 'none',
  mcpTransports: ['stdio','http','sse'], toolPermissionControl: true, nativeBudgetControl: false }

Known limitations (MVP)

  • buildArgs passes --skip-trust — gemini 0.5x refuses untrusted workspaces in headless mode.
  • LLM interception via base-URL is unproven, so declared 'none' and not wired to Agentry's proxy. Transcript record/replay works; wire cassettes do not apply.
  • disallowedTools/mcpConfig/maxBudgetUSD/appendSystemPrompt have no direct headless equivalent and are ignored.

Testing

  • pnpm typecheck clean; new-package tests green (parser incl. delta coalescing + buildArgs); full suite 92 tests, 0 failures, no regressions.
  • Parser fixtures are the live-captured gemini-cli 0.54.4 stream.
  • agentry doctor probes the gemini CLI and prints the driver's capabilities.

Merge notes

  • Branched off main. Additively touches three files the sibling Codex/Antigravity PRs also touch — the selectDriver switch in packages/cli/src/commands/run.ts, doctor.ts, and the tsconfig.json/vitest.config.ts aliases. Whichever PR merges later needs a trivial union-merge.
  • No changeset included: the changesets system is being introduced separately on chore/release-workflow. When that lands, add @agentry/gemini to the fixed-version group and a changeset entry.
  • Heads-up (environment, not this PR): upgrading the local Gemini CLI to 0.54.x drops support for the free "Code Assist for individuals" OAuth tier (IneligibleTierError); an API key (GEMINI_API_KEY) works. Relevant for anyone running live/record mode.

🤖 Generated with Claude Code

@dortort dortort self-assigned this Aug 8, 2026
dortort and others added 5 commits August 8, 2026 16:57
…e workspace

New workspace package mirroring @agentry/claude; adds the tsconfig path, vitest alias, and CLI dependency so the driver resolves across typecheck, tests, and the CLI.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… Agentry event model

parseGeminiEvents is a pure whole-stream mapper: init, message, tool_use, tool_result, error, result. Gemini streams assistant text as delta chunks, so consecutive assistant deltas are coalesced into a single message (one turn); usage and run.end come from the terminal result event. Schema captured live from gemini-cli 0.54.4.

Constraint: Assistant text arrives as streaming deltas and must be coalesced, else turns/lastMessage inflate
Rejected: Declare base-URL LLM interception | unproven for Gemini, so capabilities report 'none' and the proxy is not wired\nConfidence: high\nScope-risk: narrow\nDirective: buildArgs must pass --skip-trust; gemini 0.5x refuses untrusted workspaces headlessly\nNot-tested: mcpConfig / appendSystemPrompt passthrough (ignored in MVP)\nCo-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Fixtures are the live-captured gemini-cli 0.54.4 stream; asserts delta coalescing (one assistant message), tool calls, usage, and run.end.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
selectDriver(config.use.agent) routes 'gemini' to GeminiDriver and defaults to Claude; doctor probes the gemini CLI and prints its capabilities.

Constraint: Parallel driver branches each extend this switch; kept minimal for clean union merges
Confidence: high
Scope-risk: narrow
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@dortort
dortort force-pushed the feat/gemini-driver branch from a649ccc to e1cc893 Compare August 8, 2026 21:01
@dortort
dortort merged commit 78fddb6 into main Aug 8, 2026
1 check passed
@dortort
dortort deleted the feat/gemini-driver branch August 8, 2026 21:01
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant