Skip to content

Conversation

@stefandevo
Copy link
Collaborator

@stefandevo stefandevo commented Jan 21, 2026

Summary

  • Add Gemini CLI as a new AI provider alongside Claude, Cursor, Codex, and OpenCode
  • Full integration with settings UI for model selection and authentication status
  • Support for Gemini 2.5 and 3.0 series models

Changes

Provider Implementation

  • New GeminiProvider class extending CliProvider with:
    • JSONL streaming output parsing (--output-format stream-json)
    • Event normalization for init, message, tool_use, tool_result, result events
    • Authentication detection (OAuth, API key, Vertex AI)
    • Model prefix handling (gemini- prefix for CLI invocation)

UI Integration

  • Gemini section in settings sidebar with CLI status and model configuration
  • Gemini models in all phase model dropdowns (Architect, Coder, Reviewer, Finalizer)
  • Authentication status display with error messages
  • Model badges showing thinking capability

Models Supported

  • Gemini 3 Pro Preview / Flash Preview
  • Gemini 2.5 Pro / Flash / Flash Lite

Test plan

  • Verify Gemini CLI detection works when installed
  • Verify authentication status displays correctly (OAuth, API key)
  • Test model selection in feature card dropdowns
  • Test agent execution with Gemini models
  • Verify tool calls display correctly (list_directory, read_file, etc.)

Summary by CodeRabbit

  • New Features

    • Gemini added as a first-class AI provider with streaming CLI integration, model catalog (Gemini 2.5 & 3.x), auth detection, install/login guidance, and model management.
  • UI

    • Settings & setup: Gemini provider tab, CLI status panel, auth/install flows, model configuration and selection UIs, and provider icon.
  • Tests

    • Provider registry tests updated to include Gemini.
  • Chores

    • Types, hooks, queries, store fields, and API endpoints added to support Gemini models and CLI status.

✏️ Tip: You can customize this high-level summary in your review settings.

claude and others added 9 commits January 21, 2026 00:53
- Add GeminiProvider class extending CliProvider for Gemini CLI integration
- Add Gemini models (Gemini 3 Pro/Flash Preview, 2.5 Pro/Flash/Flash-Lite)
- Add gemini-models.ts with model definitions and types
- Update ModelProvider type to include 'gemini'
- Add isGeminiModel() to provider-utils.ts for model detection
- Register Gemini provider in provider-factory with priority 4
- Add Gemini setup detection routes (status, auth, deauth)
- Add GeminiCliStatus to setup store for UI state management
- Add Gemini to PROVIDER_ICON_COMPONENTS for UI icon display
- Add GEMINI_MODELS to model-display for dropdown population
- Support thinking levels: off, low, medium, high

Based on https://github.com/google-gemini/gemini-cli
- Add GeminiCliStatus component for CLI detection display
- Add GeminiSettingsTab component for global settings
- Update provider-tabs.tsx to include Gemini as 5th tab
- Update providers-setup-step.tsx with Gemini provider detection
- Add useGeminiCliStatus hook for querying CLI status
- Add getGeminiStatus, authGemini, deauthGemini to HTTP API client
- Add gemini query key for React Query
- Fix GeminiModelId type to not double-prefix model IDs
- Add 'gemini-provider' to SettingsViewId type
- Add GeminiIcon and gemini-provider to navigation config
- Add gemini-provider to NAV_ID_TO_PROVIDER mapping
- Add gemini-provider case in settings-view switch
- Export GeminiSettingsTab from providers index

This fixes the missing Gemini entry in the AI Providers sidebar menu.
- Create GeminiModelConfiguration component for model selection
- Add enabledGeminiModels and geminiDefaultModel state to app-store
- Add setEnabledGeminiModels, setGeminiDefaultModel, toggleGeminiModel actions
- Update GeminiSettingsTab to show model configuration when CLI is installed
- Import GeminiModelId and getAllGeminiModelIds from types

This adds the ability to configure which Gemini models are available
in the feature modal, similar to other providers like Codex and OpenCode.
- Add GEMINI_MODELS to model-constants.ts for UI dropdowns
- Add Gemini to ALL_MODELS array used throughout the app
- Add GeminiIcon to PROFILE_ICONS mapping
- Fix GEMINI_MODELS in model-display.ts to use correct model IDs
- Update getModelDisplayName to handle Gemini models correctly

Gemini models now appear in all model selection dropdowns including
Model Defaults, Feature Defaults, and feature card settings.
- Fix model ID prefix handling: strip gemini- prefix in agent-service,
  add it back in buildCliArgs for CLI invocation
- Fix event normalization to match actual Gemini CLI output format:
  - type: 'init' (not 'system')
  - type: 'message' with role (not 'assistant')
  - tool_name/tool_id/parameters/output field names
- Add --sandbox false and --approval-mode yolo for faster execution
- Remove thinking level selector from UI (Gemini CLI doesn't support it)
- Update auth status to show errors properly
@coderabbitai
Copy link

coderabbitai bot commented Jan 21, 2026

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

📝 Walkthrough

Walkthrough

Adds first-class Gemini CLI support across server, types, and UI: a new GeminiProvider with CLI streaming, setup routes for status/auth, Gemini model types and registration, UI settings/setup components and hooks, store/state changes, and tests updated to include Gemini.

Changes

Cohort / File(s) Summary
Server: Gemini provider
apps/server/src/providers/gemini-provider.ts
New GeminiProvider: CLI spawn/streaming, event typings/normalization, error mapping, auth detection, model listing, install/version detection, and async streaming executeQuery.
Server: setup routes
apps/server/src/routes/setup/index.ts, apps/server/src/routes/setup/routes/gemini-status.ts, apps/server/src/routes/setup/routes/auth-gemini.ts, apps/server/src/routes/setup/routes/deauth-gemini.ts
New endpoints: GET /api/setup/gemini-status, POST /api/setup/auth-gemini, POST /api/setup/deauth-gemini for detection, auth, and disconnect marker handling.
Server: provider wiring & tests
apps/server/src/providers/provider-factory.ts, apps/server/tests/unit/providers/provider-factory.test.ts
Register Gemini provider (alias google), update model normalization to include gemini prefixes/suffixes, add .gemini-disconnected marker handling; tests updated to include Gemini.
Types: Gemini models & utils
libs/types/src/gemini-models.ts, libs/types/src/provider-utils.ts, libs/types/src/model-display.ts, libs/types/src/model.ts, libs/types/src/index.ts, libs/types/src/settings.ts
New GEMINI_MODEL_MAP, GeminiModelId, GeminiAuthStatus, GeminiThinkingLevel; isGeminiModel helper; exports and ModelId/ModelProvider unions extended.
UI: Settings & model config
apps/ui/src/components/views/settings-view/providers/gemini-settings-tab.tsx, apps/ui/src/components/views/settings-view/providers/gemini-model-configuration.tsx, apps/ui/src/components/views/settings-view/cli-status/gemini-cli-status.tsx, apps/ui/src/components/views/settings-view/...
New Gemini settings tab, model configuration UI, CLI status component, navigation entries, model selector support, and wiring to app store actions/state.
UI: Setup flow
apps/ui/src/components/views/setup-view/steps/providers-setup-step.tsx
Adds Gemini tab/content to provider setup with CLI install/auth flows (polling, clipboard helpers) and store wiring for CLI status.
UI: Queries, API client, store
apps/ui/src/hooks/queries/use-cli-status.ts, apps/ui/src/hooks/queries/index.ts, apps/ui/src/lib/http-api-client.ts, apps/ui/src/lib/query-keys.ts, apps/ui/src/store/app-store.ts, apps/ui/src/store/setup-store.ts
New useGeminiCliStatus hook, query key ['cli','gemini'], HTTP endpoints getGeminiStatus, authGemini, deauthGemini; app store fields/actions for enabledGeminiModels, geminiDefaultModel, and geminiCliStatus.
UI: Icons & small updates
apps/ui/src/components/ui/provider-icon.tsx, apps/ui/src/components/views/board-view/shared/model-constants.ts, various settings/navigation files
Expose GeminiIcon, include Gemini in model lists, profile icons, navigation and small UI adjustments.

Sequence Diagram(s)

sequenceDiagram
    participant UI as User / UI
    participant API as Server API
    participant CLI as Gemini CLI (local)
    participant FS as File System

    UI->>API: GET /api/setup/gemini-status
    API->>FS: stat .automaker/.gemini-disconnected
    alt marker present
        FS-->>API: marker found
        API-->>UI: installed: true?, auth: none
    else
        API->>CLI: detect installation & version (spawn/check path)
        CLI-->>API: version/path or not installed
        API->>CLI: check auth (env/API key/credentials file)
        CLI-->>API: auth status
        API-->>UI: installed/version/path/auth info
    end

    UI->>API: POST /api/setup/auth-gemini
    API->>FS: unlink .gemini-disconnected (if exists)
    FS-->>API: removed
    API-->>UI: { success: true }

    UI->>API: POST /api/setup/deauth-gemini
    API->>FS: write .gemini-disconnected marker
    FS-->>API: written
    API-->>UI: { success: true }
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~75 minutes

Possibly related PRs

Suggested labels

type: feature

Suggested reviewers

  • Shironex

Poem

🐇
I hopped in code with nimble feet,
Brought Gemini streams — so fast and neat,
Models lined up, prompts in tune,
CLI lights gleam beneath the moon,
Hooray — the rabbit dances, sweet!

🚥 Pre-merge checks | ✅ 2 | ❌ 1
❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 65.52% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: add Gemini CLI provider integration' clearly and concisely describes the main change: adding Gemini as a new AI provider with CLI integration.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing touches
  • 📝 Generate docstrings

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 and usage tips.

@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @stefandevo, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request introduces a significant new feature by integrating Google's Gemini CLI as a first-class AI provider. It enables users to leverage Gemini's advanced models directly within the application, offering a seamless experience for model selection, authentication, and execution. The changes span both the backend, with a new provider implementation, and the frontend, with extensive UI updates to ensure full configurability and status visibility for Gemini.

Highlights

  • Gemini CLI Provider Integration: Introduced a new GeminiProvider class that extends CliProvider to enable interaction with the Gemini CLI. This includes handling JSONL streaming output, normalizing events (init, message, tool_use, tool_result, result), and detecting various authentication methods (OAuth, API key, Vertex AI).
  • Comprehensive UI Integration: The user interface has been updated to fully support Gemini. This includes a dedicated Gemini section in the settings sidebar, allowing users to view CLI status and configure models. Gemini models are now available in all phase model dropdowns (Architect, Coder, Reviewer, Finalizer), complete with authentication status displays and model badges indicating thinking capabilities.
  • Model Support: The integration supports a range of Gemini models, including the latest Gemini 3 Pro Preview and Flash Preview, as well as Gemini 2.5 Pro, Flash, and Flash Lite. Model selection and configuration are managed through the new UI components.
  • Error Handling and Installation Status: Custom error mapping has been implemented for Gemini-specific error codes (e.g., not installed, not authenticated, rate limited, model unavailable, network error, process crashed). The system can also detect the installation status of the Gemini CLI and provide relevant installation and login instructions.

🧠 New Feature in Public Preview: You can now enable Memory to help Gemini Code Assist learn from your team's feedback. This makes future code reviews more consistent and personalized to your project's style. Click here to enable Memory in your admin console.

Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@stefandevo stefandevo added Enhancement Improvements to existing functionality or UI. Testers-Requested Request for others to test an enhancement or bug fix/etc. Do Not Merge Use this label if something should not be merged. labels Jan 21, 2026
Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces a comprehensive integration for the Gemini CLI provider, covering backend logic, API routes, and UI components. The implementation is thorough, but there are a few critical issues to address. The npm package name for the Gemini CLI is incorrect in several places, which will prevent users from installing it correctly. There are also several instances of synchronous file system operations within asynchronous functions, which should be converted to asynchronous calls to avoid blocking the event loop. Finally, some TypeScript interfaces for Gemini stream events are inconsistent with the documented data format, which could lead to confusion and maintenance issues.

- Add GeminiProvider import and spy mock
- Update expected provider count from 4 to 5
- Add test for GeminiProvider inclusion
- Add gemini key to checkAllProviders test
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 11

🤖 Fix all issues with AI agents
In `@apps/server/src/providers/gemini-provider.ts`:
- Around line 431-436: The user-facing install string in
getInstallInstructions() is wrong — replace the placeholder package name
`@anthropic-ai/gemini-cli` with the correct Gemini CLI package (or change the
message to clearly indicate it's pending/placeholder), e.g., update the return
value of protected getInstallInstructions() to either the accurate package name
for Gemini CLI or a “TBD/see docs” phrasing so the instruction is not
misleading.
- Around line 150-154: The npxPackage value in getSpawnConfig() is using the
wrong npm namespace; update the npxPackage field in the getSpawnConfig() method
of the Gemini provider to use the official package name "@google/gemini-cli"
instead of "@anthropic-ai/gemmini-cli" (locate the npxPackage property in
getSpawnConfig() and replace the string with "@google/gemini-cli").

In `@apps/server/src/providers/provider-factory.ts`:
- Around line 307-313: Tests expecting 4 providers must be updated to account
for the new Gemini registration: find assertions and helpers that check provider
counts (e.g., calls to getAllProviders() and checkAllProviders(), any
EXPECTED_PROVIDER_COUNT or similar constants) and change expected values from 4
to 5 (or update snapshots that assert provider list length), and add/adjust any
assertions that validate provider identities to include 'gemini' (or its alias
'google') so the tests reflect the new provider registration in
factory.registerProvider('gemini', ...).

In `@apps/ui/src/components/views/board-view/shared/model-constants.ts`:
- Around line 131-140: GEMINI_MODELS constructs ModelOption entries using
GEMINI_MODEL_MAP but sets badge to undefined for non-thinking models, causing
inconsistency with the fallback 'Speed' used elsewhere; update the badge logic
in GEMINI_MODELS (and related fields if present) to use 'Speed' as the fallback
(e.g., set badge to config.supportsThinking ? 'Thinking' : 'Speed') so that
badge, hasThinking, id, label and description remain consistent with the display
expectations.

In
`@apps/ui/src/components/views/settings-view/providers/gemini-settings-tab.tsx`:
- Around line 30-41: The mapping in the useMemo for cliStatus ignores the
server's installCommand and loginCommand fields and returns installCommands
(plural) only; update the transform in the cliStatus useMemo to read
cliStatusData.installCommand and cliStatusData.loginCommand and forward them on
the returned object (or normalize names to match SharedCliStatus), and if
SharedCliStatus lacks a loginCommand field, extend SharedCliStatus to include
loginCommand so the UI receives both install and login hints from the API.

In `@apps/ui/src/components/views/settings-view/providers/provider-tabs.tsx`:
- Line 3: The import line for provider icons (AnthropicIcon, CursorIcon,
OpenAIIcon, GeminiIcon, OpenCodeIcon) is not Prettier-formatted; run the
project's Prettier config (or your editor formatter) on
apps/ui/src/components/views/settings-view/providers/provider-tabs.tsx and
reformat the import statement so it conforms to the project's style (line
breaks/spacing as configured) and clears the pipeline formatting warning.

In `@apps/ui/src/components/views/setup-view/steps/providers-setup-step.tsx`:
- Line 34: The import statement pulling AnthropicIcon, CursorIcon, OpenAIIcon,
OpenCodeIcon, and GeminiIcon from '@/components/ui/provider-icon' is triggering
Prettier formatting errors; reformat the import (or run the project's Prettier)
so it conforms to the project's line-length rules—e.g., split the long import
across multiple lines or let Prettier rewrite it—ensuring the module name
provider-icon and the named exports AnthropicIcon, CursorIcon, OpenAIIcon,
OpenCodeIcon, and GeminiIcon remain unchanged.
- Around line 1391-1397: The fallback install command currently uses the wrong
package name; update both usages of the literal fallback string that reference
geminiCliStatus?.installCommand (the displayed command and the value passed into
copyCommand) to use 'npm install -g `@google/gemini-cli`' instead of
'@anthropic/gemini-cli' so that the UI and the copy action show/install the
official Gemini CLI package.

In `@apps/ui/src/store/app-store.ts`:
- Around line 2752-2761: Add the Gemini settings to the settings sync list by
including the keys for enabledGeminiModels and geminiDefaultModel in the
SETTINGS_FIELDS_TO_SYNC array in use-settings-sync.ts so those values set by
setEnabledGeminiModels, setGeminiDefaultModel and toggleGeminiModel persist
across sessions; also add the analogous Codex keys (e.g., enabledCodexModels and
codexDefaultModel) to the same SETTINGS_FIELDS_TO_SYNC array so Codex settings
persist alongside the existing Cursor and OpenCode provider settings.

In `@apps/ui/src/store/setup-store.ts`:
- Around line 66-79: The GeminiCliStatus interface is missing the hasEnvApiKey
field in its auth object; update the GeminiCliStatus definition so the auth
property includes hasEnvApiKey?: boolean (optional) alongside authenticated,
method, and hasApiKey to match server responses and preserve API parity for
environment-key auth state.

In `@libs/types/src/gemini-models.ts`:
- Around line 83-88: The comment for the GeminiThinkingLevel type incorrectly
states it maps to a CLI flag; update the JSDoc for GeminiThinkingLevel to
clarify that these values represent the Gemini API's thinking control
(thinkingLevel/thinkingBudget) rather than a currently supported CLI flag, or
remove the CLI flag reference entirely so the comment accurately describes
API-level usage; locate the export type GeminiThinkingLevel and edit its
preceding comment accordingly.
🧹 Nitpick comments (2)
apps/server/src/routes/setup/routes/auth-gemini.ts (1)

17-39: Consider using async fs operations for consistency.

The handler is declared async but uses synchronous fs.existsSync and fs.unlinkSync. While this works fine for quick file operations, using fs.promises would be more consistent with the async handler pattern and avoid blocking the event loop:

♻️ Optional refactor using async fs
 import type { Request, Response } from 'express';
 import { getErrorMessage, logError } from '../common.js';
-import * as fs from 'fs';
+import * as fs from 'fs/promises';
 import * as path from 'path';

 const DISCONNECTED_MARKER_FILE = '.gemini-disconnected';

 export function createAuthGeminiHandler() {
   return async (_req: Request, res: Response): Promise<void> => {
     try {
       const projectRoot = process.cwd();
       const automakerDir = path.join(projectRoot, '.automaker');
       const markerPath = path.join(automakerDir, DISCONNECTED_MARKER_FILE);

       // Remove the disconnection marker if it exists
-      if (fs.existsSync(markerPath)) {
-        fs.unlinkSync(markerPath);
-      }
+      try {
+        await fs.unlink(markerPath);
+      } catch {
+        // File doesn't exist, nothing to remove
+      }

       res.json({
         success: true,
         message: 'Gemini CLI connected to app',
       });
     } catch (error) {
       logError(error, 'Auth Gemini failed');
       res.status(500).json({
         success: false,
         error: getErrorMessage(error),
       });
     }
   };
 }
apps/ui/src/components/views/settings-view/cli-status/gemini-cli-status.tsx (1)

9-22: Reuse shared Gemini auth types to avoid drift.
These types are already defined in @automaker/types. Prefer importing the shared type and deriving the method union locally. As per coding guidelines, ...

♻️ Suggested refactor
-import type { CliStatus } from '../shared/types';
+import type { CliStatus } from '../shared/types';
+import type { GeminiAuthStatus } from '@automaker/types';
 import { GeminiIcon } from '@/components/ui/provider-icon';
 
-export type GeminiAuthMethod =
-  | 'api_key'
-  | 'google_login'
-  | 'vertex_ai'
-  | 'none';
-
-export interface GeminiAuthStatus {
-  authenticated: boolean;
-  method: GeminiAuthMethod;
-  hasApiKey?: boolean;
-  hasEnvApiKey?: boolean;
-  hasCredentialsFile?: boolean;
-  error?: string;
-}
+type GeminiAuthMethod = GeminiAuthStatus['method'];

Comment on lines +307 to +313
// Register Gemini provider
registerProvider('gemini', {
factory: () => new GeminiProvider(),
aliases: ['google'],
canHandleModel: (model: string) => isGeminiModel(model),
priority: 4, // Between opencode (3) and codex (5)
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Update provider-count tests for the new Gemini registration.
CI reports failures because provider counts now return 5 instead of 4. Please update the test expectations for getAllProviders() and checkAllProviders() to account for Gemini.

🤖 Prompt for AI Agents
In `@apps/server/src/providers/provider-factory.ts` around lines 307 - 313, Tests
expecting 4 providers must be updated to account for the new Gemini
registration: find assertions and helpers that check provider counts (e.g.,
calls to getAllProviders() and checkAllProviders(), any EXPECTED_PROVIDER_COUNT
or similar constants) and change expected values from 4 to 5 (or update
snapshots that assert provider list length), and add/adjust any assertions that
validate provider identities to include 'gemini' (or its alias 'google') so the
tests reflect the new provider registration in
factory.registerProvider('gemini', ...).

Comment on lines 30 to 41
// Transform CLI status to the expected format
const cliStatus = useMemo((): SharedCliStatus | null => {
if (!cliStatusData) return null;
return {
success: cliStatusData.success ?? false,
status: cliStatusData.installed ? 'installed' : 'not_installed',
method: cliStatusData.auth?.method,
version: cliStatusData.version,
path: cliStatusData.path,
recommendation: cliStatusData.recommendation,
installCommands: cliStatusData.installCommands,
};
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Map install/login commands from the API payload.

The server responds with installCommand and loginCommand, but the mapping reads installCommands and never forwards loginCommand, so install/login hints can disappear in the UI. Consider normalizing here (and extending SharedCliStatus if needed).

🛠️ Suggested update
     return {
       success: cliStatusData.success ?? false,
       status: cliStatusData.installed ? 'installed' : 'not_installed',
       method: cliStatusData.auth?.method,
       version: cliStatusData.version,
       path: cliStatusData.path,
-      recommendation: cliStatusData.recommendation,
-      installCommands: cliStatusData.installCommands,
+      recommendation: cliStatusData.recommendation,
+      installCommands: cliStatusData.installCommand
+        ? [cliStatusData.installCommand]
+        : cliStatusData.installCommands,
+      loginCommand: cliStatusData.loginCommand,
     };
🤖 Prompt for AI Agents
In `@apps/ui/src/components/views/settings-view/providers/gemini-settings-tab.tsx`
around lines 30 - 41, The mapping in the useMemo for cliStatus ignores the
server's installCommand and loginCommand fields and returns installCommands
(plural) only; update the transform in the cliStatus useMemo to read
cliStatusData.installCommand and cliStatusData.loginCommand and forward them on
the returned object (or normalize names to match SharedCliStatus), and if
SharedCliStatus lacks a loginCommand field, extend SharedCliStatus to include
loginCommand so the UI receives both install and login hints from the API.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/server/src/providers/provider-factory.ts`:
- Around line 313-319: The test comment references the wrong line numbers for
the assertion about gemini-3-pro routing; update the test's assertion comment to
point to lines 160-163 (not 156-159) and/or adjust any inline note near the
assertion that mentions line numbers so it correctly documents that
getProviderForModelName() chooses Cursor over Gemini due to Cursor's higher
priority; check related symbols LEGACY_CURSOR_MODEL_MAP, isCursorModel,
getProviderForModelName, and the provider registration for 'gemini'
(registerProvider('gemini', ... priority: 4)) to ensure the comment accurately
reflects the current provider priority and legacy model mapping behavior.
♻️ Duplicate comments (2)
apps/ui/src/components/views/setup-view/steps/providers-setup-step.tsx (2)

34-40: LGTM on the import addition.

The GeminiIcon import follows the project's path alias conventions. The formatting issue was already flagged in a previous review.


1393-1410: Wrong package name in fallback install command.

The fallback uses @anthropic/gemini-cli but the official package is @google/gemini-cli. This affects both the displayed command (line 1397) and the copied command (line 1404).

🐛 Proposed fix
               <code className="flex-1 bg-muted px-3 py-2 rounded text-sm font-mono text-foreground overflow-x-auto">
-                  {geminiCliStatus?.installCommand || 'npm install -g `@anthropic/gemini-cli`'}
+                  {geminiCliStatus?.installCommand || 'npm install -g `@google/gemini-cli`'}
               </code>
               <Button
                 variant="ghost"
                 size="icon"
                 onClick={() =>
                   copyCommand(
-                      geminiCliStatus?.installCommand || 'npm install -g `@anthropic/gemini-cli`'
+                      geminiCliStatus?.installCommand || 'npm install -g `@google/gemini-cli`'
                   )
                 }
               >
🧹 Nitpick comments (2)
apps/ui/src/components/views/setup-view/steps/providers-setup-step.tsx (1)

1750-1756: Consider using a distinct color for Gemini.

Gemini uses 'text-blue-500' which is the same as Cursor. For visual differentiation, consider using a Gemini-associated color (e.g., 'text-purple-500' or 'text-indigo-500' to align with Google's Gemini branding).

♻️ Suggested change
     {
       id: 'gemini' as const,
       label: 'Gemini',
       icon: GeminiIcon,
       status: getProviderStatus(isGeminiInstalled, isGeminiAuthenticated),
-      color: 'text-blue-500',
+      color: 'text-purple-500',
     },
apps/server/tests/unit/providers/provider-factory.test.ts (1)

221-222: Consider adding tests for Gemini-specific provider lookups.

The current coverage verifies Gemini is present in the provider list, but there are no tests for:

  • getProviderByName('gemini') returning GeminiProvider
  • getProviderByName('google') returning GeminiProvider (alias support)
  • Gemini model routing via getProviderForModel('gemini-2.5-flash')

These would ensure the registration and alias configuration work correctly.

Comment on lines +313 to +319
// Register Gemini provider
registerProvider('gemini', {
factory: () => new GeminiProvider(),
aliases: ['google'],
canHandleModel: (model: string) => isGeminiModel(model),
priority: 4, // Between opencode (3) and codex (5)
});
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
echo "=== Checking provider-factory.ts for Gemini and other provider priorities ==="
rg -n "priority:" --type ts apps/server/src/providers/provider-factory.ts

echo ""
echo "=== Looking for test file with gemini-3-pro routing test ==="
fd -e test.ts -e spec.ts | xargs grep -l "gemini-3-pro" 2>/dev/null | head -5

Repository: AutoMaker-Org/automaker

Length of output: 559


🏁 Script executed:

#!/bin/bash
echo "=== Checking isGeminiModel and isCursorModel implementation ==="
rg -n "isGeminiModel|isCursorModel" --type ts -A 10 libs/types/src/provider-utils.ts

echo ""
echo "=== Looking for Cursor model map definitions ==="
rg -n "CursorModel|cursorModels" --type ts libs/ -A 5 | head -50

Repository: AutoMaker-Org/automaker

Length of output: 4737


🏁 Script executed:

#!/bin/bash
echo "=== Checking if Cursor provider includes gemini models ==="
rg -n "gemini" --type ts libs/ apps/ | grep -i "cursor\|model" | head -20

Repository: AutoMaker-Org/automaker

Length of output: 1697


🏁 Script executed:

#!/bin/bash
echo "=== Checking test file lines 156-159 ==="
sed -n '150,165p' apps/server/tests/unit/providers/provider-factory.test.ts

echo ""
echo "=== Checking if gemini-3-pro is in GEMINI_MODEL_MAP ==="
rg -n "gemini-3-pro|gemini-3-flash" --type ts libs/types/src/gemini-models.ts -B 2 -A 2

echo ""
echo "=== Checking LEGACY_CURSOR_MODEL_MAP for gemini models ==="
rg -n "LEGACY_CURSOR_MODEL_MAP|gemini-3" --type ts libs/types/src/cursor-models.ts | head -20

Repository: AutoMaker-Org/automaker

Length of output: 1758


🏁 Script executed:

#!/bin/bash
echo "=== Check full GEMINI_MODEL_MAP structure ==="
cat libs/types/src/gemini-models.ts | head -50

Repository: AutoMaker-Org/automaker

Length of output: 1483


🏁 Script executed:

#!/bin/bash
echo "=== Verify the actual check order and model routing logic ==="
sed -n '160,195p' libs/types/src/provider-utils.ts

Repository: AutoMaker-Org/automaker

Length of output: 1163


🏁 Script executed:

#!/bin/bash
echo "=== Check ProviderFactory.getProviderForModel implementation ==="
rg -n "getProviderForModel" --type ts apps/server/src/providers/provider-factory.ts -A 20

Repository: AutoMaker-Org/automaker

Length of output: 2817


🏁 Script executed:

#!/bin/bash
echo "=== Check if there's special handling that overrides getModelProvider ==="
rg -n "gemini-3-pro|LEGACY_CURSOR_MODEL_MAP" --type ts apps/server/src/providers/ -B 3 -A 3

Repository: AutoMaker-Org/automaker

Length of output: 140


🏁 Script executed:

#!/bin/bash
echo "=== Check Cursor provider's canHandleModel implementation ==="
rg -n "canHandleModel" --type ts apps/server/src/providers/provider-factory.ts -B 5 -A 5 | grep -A 5 -B 5 "cursor"

Repository: AutoMaker-Org/automaker

Length of output: 440


🏁 Script executed:

#!/bin/bash
echo "=== Get full provider registrations with canHandleModel details ==="
sed -n '280,330p' apps/server/src/providers/provider-factory.ts

Repository: AutoMaker-Org/automaker

Length of output: 1357


Correct the line number reference for the test assertion.

The test at lines 160-163 (not 156-159) confirms that gemini-3-pro routes to CursorProvider. This is the correct behavior given the provider registration logic: getProviderForModelName() iterates through providers sorted by priority (descending), checking each canHandleModel function. Since Cursor has priority 10 and Gemini has priority 4, Cursor's canHandleModel is evaluated first. Both return true for gemini-3-pro (it's a legacy Cursor model in LEGACY_CURSOR_MODEL_MAP and starts with the gemini- prefix), but Cursor wins due to its higher priority.

The architectural concern remains valid: gemini-3-pro and gemini-3-flash are legacy Cursor model aliases, so they intentionally route to Cursor. If the Gemini CLI should handle its native models preferentially in the future, consider removing these models from LEGACY_CURSOR_MODEL_MAP or adjusting the logic in isCursorModel.

🤖 Prompt for AI Agents
In `@apps/server/src/providers/provider-factory.ts` around lines 313 - 319, The
test comment references the wrong line numbers for the assertion about
gemini-3-pro routing; update the test's assertion comment to point to lines
160-163 (not 156-159) and/or adjust any inline note near the assertion that
mentions line numbers so it correctly documents that getProviderForModelName()
chooses Cursor over Gemini due to Cursor's higher priority; check related
symbols LEGACY_CURSOR_MODEL_MAP, isCursorModel, getProviderForModelName, and the
provider registration for 'gemini' (registerProvider('gemini', ... priority: 4))
to ensure the comment accurately reflects the current provider priority and
legacy model mapping behavior.

- Fix npm package name from @anthropic-ai/gemini-cli to @google/gemini-cli
- Fix comments in gemini-provider.ts to match actual CLI output format
- Convert sync fs operations to async using fs/promises
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/server/src/routes/setup/routes/deauth-gemini.ts`:
- Around line 16-42: Update the import that currently pulls getErrorMessage and
logError from a relative module to use the shared package namespace: replace the
relative import with import { getErrorMessage, logError } from
'@automaker/common' so the handler (createDeauthGeminiHandler) uses the shared
package; also apply the same change to the corresponding imports in
auth-gemini.ts and gemini-status.ts to keep consistency for getErrorMessage and
logError.
🧹 Nitpick comments (3)
apps/server/src/providers/gemini-provider.ts (3)

228-230: Consider adding runtime validation for incoming events.

The type assertion event as GeminiStreamEvent on line 229 bypasses runtime type checking. If the CLI sends malformed JSON or an unexpected structure, this could lead to subtle bugs. Consider adding a validation check for the type property before processing.

♻️ Suggested validation
   normalizeEvent(event: unknown): ProviderMessage | null {
-    const geminiEvent = event as GeminiStreamEvent;
+    if (!event || typeof event !== 'object' || !('type' in event)) {
+      logger.debug('Received invalid event structure');
+      return null;
+    }
+    const geminiEvent = event as GeminiStreamEvent;

536-550: Consider using async exec for version check.

execSync on line 541 blocks the event loop. While the 5-second timeout limits exposure and this is called infrequently, consider using the async exec from child_process/promises for consistency with the async method signature.

♻️ Suggested async version
+import { exec } from 'child_process/promises';
+
   async getVersion(): Promise<string | null> {
     this.ensureCliDetected();
     if (!this.cliPath) return null;
 
     try {
-      const result = execSync(`"${this.cliPath}" --version`, {
-        encoding: 'utf8',
+      const { stdout } = await exec(`"${this.cliPath}" --version`, {
         timeout: 5000,
-        stdio: 'pipe',
-      }).trim();
-      return result;
+      });
+      return stdout.trim();
     } catch {
       return null;
     }
   }

571-572: Redundant variable assignment.

hasEnvApiKey is assigned the same value as hasApiKey on line 572. If they're meant to track different things (e.g., env var vs settings file), the logic needs adjustment. Otherwise, consider removing the redundant variable.

♻️ Suggested simplification
     // Determine the likely auth method based on environment
     const hasApiKey = !!process.env.GEMINI_API_KEY;
-    const hasEnvApiKey = hasApiKey;
     const hasVertexAi = !!(
       process.env.GOOGLE_APPLICATION_CREDENTIALS || process.env.GOOGLE_CLOUD_PROJECT
     );
 
-    logger.debug(`checkAuth: hasApiKey=${hasApiKey}, hasVertexAi=${hasVertexAi}`);
+    logger.debug(`checkAuth: hasApiKey=${hasApiKey}, hasVertexAi=${hasVertexAi}`);

Then update return statements to use hasApiKey for both hasApiKey and hasEnvApiKey fields, or clarify the distinction if they should differ.

Add enabledGeminiModels, geminiDefaultModel, enabledCodexModels, and
codexDefaultModel to SETTINGS_FIELDS_TO_SYNC for persistence across sessions.
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Fix all issues with AI agents
In `@apps/ui/src/hooks/use-settings-sync.ts`:
- Around line 69-72: The SETTINGS_FIELDS_TO_SYNC list now includes
enabledCodexModels, codexDefaultModel, enabledGeminiModels, and
geminiDefaultModel but refreshSettingsFromServer() never restores them; update
the useAppStore.setState(...) call inside refreshSettingsFromServer to set
enabledCodexModels and codexDefaultModel and enabledGeminiModels and
geminiDefaultModel from the sanitized values you derive (analogous to
enabledCursorModels/cursorDefaultModel and
enabledOpencodeModels/opencodeDefaultModel), ensuring the fields names match
SETTINGS_FIELDS_TO_SYNC and are assigned the corresponding
sanitizedCodex*/sanitizedGemini* variables used earlier in that function.

- Use 'Speed' badge for non-thinking Gemini models (consistency)
- Fix installCommand mapping in gemini-settings-tab.tsx
- Add hasEnvApiKey to GeminiCliStatus interface for API parity
- Clarify GeminiThinkingLevel comment (CLI doesn't support --thinking-level)
Add sanitization and restoration logic for enabledCodexModels,
codexDefaultModel, enabledGeminiModels, and geminiDefaultModel
in refreshSettingsFromServer() to match the fields in SETTINGS_FIELDS_TO_SYNC.
- Add tool name mapping to normalize Gemini CLI tool names to standard
  names (e.g., write_todos -> TodoWrite, read_file -> Read)
- Add normalizeGeminiToolInput to convert write_todos format to TodoWrite
  format (description -> content, handle cancelled status)
- Pass --include-directories with cwd to fix workspace restriction errors
  when Gemini CLI has a different cached workspace from previous sessions
@stefandevo stefandevo removed the Do Not Merge Use this label if something should not be merged. label Jan 22, 2026
@stefandevo stefandevo merged commit f480386 into AutoMaker-Org:v0.14.0rc Jan 23, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Enhancement Improvements to existing functionality or UI. Testers-Requested Request for others to test an enhancement or bug fix/etc.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants