gemini

package
v0.2.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Feb 11, 2026 License: MIT Imports: 18 Imported by: 0

Documentation

Overview

Package gemini provides Google Gemini CLI integration for Moat.

This package handles:

  • Credential injection through proxy configuration
  • Configuration file generation for Gemini CLI
  • Session management for Gemini runs
  • Background OAuth token refresh

Authentication

Gemini supports two authentication methods:

  1. API Key - Standard API access via x-goog-api-key header
  2. OAuth - Google OAuth2 access with automatic token refresh

Credentials are handled via proxy injection, never exposed to containers:

  • Container receives placeholder credentials in ~/.gemini/
  • The Moat proxy intercepts requests and adds real Authorization headers

Important: OAuth vs API Key Use Different API Backends

Gemini CLI routes to different API backends depending on authentication:

  • API key mode: generativelanguage.googleapis.com (Google AI SDK)
  • OAuth mode: cloudcode-pa.googleapis.com (Cloud Code Private API)

The proxy must inject credentials for the correct host based on auth type.

For OAuth, the proxy also performs token substitution on oauth2.googleapis.com — replacing placeholder tokens in the container's oauth_creds.json with real tokens before requests are forwarded to Google.

Index

Constants

View Source
const (
	// GeminiInitMountPath is where the staging directory is mounted in containers.
	GeminiInitMountPath = "/moat/gemini-init"

	// GeminiAPIHost is the API endpoint used by Gemini CLI in OAuth mode.
	// OAuth mode uses the Cloud Code Private API, NOT generativelanguage.googleapis.com.
	GeminiAPIHost = "cloudcode-pa.googleapis.com"

	// GeminiAPIKeyHost is the API endpoint used in API key mode.
	GeminiAPIKeyHost = "generativelanguage.googleapis.com"

	// GeminiOAuthHost is Google's OAuth2 endpoint.
	GeminiOAuthHost = "oauth2.googleapis.com"

	// ProxyInjectedPlaceholder is the placeholder for proxy-injected credentials.
	ProxyInjectedPlaceholder = credential.ProxyInjectedPlaceholder

	// OAuthClientID is the public OAuth client ID used by Gemini CLI.
	//
	// Source: @google/gemini-cli-core npm package, code_assist/oauth2.ts
	//   npm pack @google/gemini-cli-core && tar xzf *.tgz
	//   grep "OAUTH_CLIENT_ID" package/dist/src/code_assist/oauth2.js
	//
	// This is an installed/desktop OAuth application. Per Google's OAuth2 docs:
	// https://developers.google.com/identity/protocols/oauth2#installed
	// "The process results in a client ID and, in some cases, a client secret,
	// which you embed in the source code of your application."
	OAuthClientID = "681255809395-oo8ft2oprdrnp9e3aqf6av3hmdib135j.apps.googleusercontent.com"

	// OAuthClientSecret is the public OAuth client secret used by Gemini CLI.
	//
	// Source: same file as OAuthClientID above (code_assist/oauth2.ts).
	// The Gemini CLI source includes this comment:
	//   "It's ok to save this in git because this is an installed application [...]
	//    In this context, the client secret is obviously not treated as a secret."
	//
	// See: https://developers.google.com/identity/protocols/oauth2#installed
	OAuthClientSecret = "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"

	// OAuthTokenURL is Google's OAuth2 token endpoint.
	OAuthTokenURL = "https://oauth2.googleapis.com/token"

	// ModelsURL is the Gemini API models endpoint for key validation.
	ModelsURL = "https://generativelanguage.googleapis.com/v1beta/models"

	// CredentialsFile is the path to Gemini CLI's OAuth credentials relative to home.
	CredentialsFile = ".gemini/oauth_creds.json"
)

Variables

This section is empty.

Functions

func DefaultDependencies

func DefaultDependencies() []string

DefaultDependencies returns the default dependencies for running Gemini CLI.

func GenerateMCPConfig

func GenerateMCPConfig(cfg *config.Config, grants []string) ([]byte, error)

GenerateMCPConfig generates MCP server configuration for Gemini. Returns nil if no MCP servers are configured.

func HasCredential

func HasCredential() bool

HasCredential returns true if a Gemini credential exists in the store.

func IsOAuthCredential

func IsOAuthCredential(cred *provider.Credential) bool

IsOAuthCredential returns true if the credential is a Gemini OAuth credential.

func NetworkHosts

func NetworkHosts() []string

NetworkHosts returns the list of hosts that Gemini needs network access to. These should be added to the network allow list for containers running Gemini.

func WriteMCPConfig

func WriteMCPConfig(workspaceDir string, mcpJSON []byte) error

WriteMCPConfig writes the MCP configuration to the workspace.

Types

type Auth

type Auth struct {
	HTTPClient *http.Client
	APIURL     string
}

Auth handles Gemini API key authentication.

func (*Auth) CreateAPIKeyCredential

func (a *Auth) CreateAPIKeyCredential(apiKey string) *provider.Credential

CreateAPIKeyCredential creates a provider.Credential from a validated API key.

func (*Auth) CreateOAuthCredential

func (a *Auth) CreateOAuthCredential(accessToken, refreshToken string, expiresAt time.Time) *provider.Credential

CreateOAuthCredential creates a provider.Credential from OAuth tokens. The access token is stored in Token, the refresh token in Metadata.

func (*Auth) PromptForAPIKey

func (a *Auth) PromptForAPIKey() (string, error)

PromptForAPIKey prompts the user to enter their Gemini API key.

func (*Auth) ValidateKey

func (a *Auth) ValidateKey(ctx context.Context, apiKey string) error

ValidateKey validates a Gemini API key by listing models.

type AuthSettings

type AuthSettings struct {
	SelectedType string `json:"selectedType"` // "oauth-personal", "gemini-api-key"
}

AuthSettings holds authentication configuration.

type CLICredentials

type CLICredentials struct {
	HomeDir string // Override for testing; empty uses os.UserHomeDir
}

CLICredentials handles extraction of Gemini CLI OAuth credentials.

func (*CLICredentials) CreateMoatCredential

func (c *CLICredentials) CreateMoatCredential(token *CLIOAuthToken) *provider.Credential

CreateMoatCredential creates a provider.Credential from Gemini CLI OAuth token.

func (*CLICredentials) GetCredentials

func (c *CLICredentials) GetCredentials() (*CLIOAuthToken, error)

GetCredentials reads OAuth credentials from ~/.gemini/oauth_creds.json.

func (*CLICredentials) HasCredentials

func (c *CLICredentials) HasCredentials() bool

HasCredentials returns true if Gemini CLI credentials are available.

type CLIOAuthToken

type CLIOAuthToken struct {
	AccessToken  string `json:"access_token"`
	RefreshToken string `json:"refresh_token"`
	Scope        string `json:"scope"`
	TokenType    string `json:"token_type"`
	ExpiryDate   int64  `json:"expiry_date"` // Unix timestamp in milliseconds
}

CLIOAuthToken represents the OAuth credentials stored by Gemini CLI in ~/.gemini/oauth_creds.json.

func (*CLIOAuthToken) ExpiresAtTime

func (t *CLIOAuthToken) ExpiresAtTime() time.Time

ExpiresAtTime returns the expiration time.

func (*CLIOAuthToken) IsExpired

func (t *CLIOAuthToken) IsExpired() bool

IsExpired returns true if the access token has expired.

type MCPConfig

type MCPConfig struct {
	MCPServers map[string]MCPServer `json:"mcpServers"`
}

MCPConfig represents the MCP configuration structure for Gemini.

type MCPServer

type MCPServer struct {
	Command string            `json:"command"`
	Args    []string          `json:"args,omitempty"`
	Env     map[string]string `json:"env,omitempty"`
	Cwd     string            `json:"cwd,omitempty"`
}

MCPServer represents a single MCP server configuration.

type OAuthCreds

type OAuthCreds struct {
	AccessToken  string `json:"access_token"`
	Scope        string `json:"scope"`
	TokenType    string `json:"token_type"`
	IDToken      string `json:"id_token,omitempty"`
	ExpiryDate   int64  `json:"expiry_date"`
	RefreshToken string `json:"refresh_token"`
}

OAuthCreds represents the ~/.gemini/oauth_creds.json file structure.

type OAuthError

type OAuthError struct {
	Code        string // OAuth error code: "invalid_grant", "invalid_request", etc.
	Description string // Human-readable description from Google
}

OAuthError represents an OAuth error from Google's token endpoint. Use errors.As to check for this type and IsRevoked() to detect token revocation.

func (*OAuthError) Error

func (e *OAuthError) Error() string

func (*OAuthError) IsRevoked

func (e *OAuthError) IsRevoked() bool

IsRevoked returns true if the error indicates the refresh token was revoked.

type Provider

type Provider struct{}

Provider implements provider.CredentialProvider and provider.AgentProvider for Google Gemini CLI credentials.

func (*Provider) CanRefresh

func (p *Provider) CanRefresh(cred *provider.Credential) bool

CanRefresh reports whether this credential can be refreshed. OAuth tokens can be refreshed; API keys cannot.

func (*Provider) Cleanup

func (p *Provider) Cleanup(cleanupPath string)

Cleanup cleans up Gemini resources.

func (*Provider) ConfigureProxy

func (p *Provider) ConfigureProxy(proxy provider.ProxyConfigurer, cred *provider.Credential)

ConfigureProxy sets up proxy headers for Gemini API.

func (*Provider) ContainerEnv

func (p *Provider) ContainerEnv(cred *provider.Credential) []string

ContainerEnv returns environment variables for Gemini.

func (*Provider) ContainerMounts

func (p *Provider) ContainerMounts(cred *provider.Credential, containerHome string) ([]provider.MountConfig, string, error)

ContainerMounts returns mounts needed for Gemini. This method returns empty because Gemini setup uses the staging directory approach instead of direct mounts.

func (*Provider) Grant

func (p *Provider) Grant(ctx context.Context) (*provider.Credential, error)

Grant acquires Gemini credentials interactively or from environment.

func (*Provider) ImpliedDependencies

func (p *Provider) ImpliedDependencies() []string

ImpliedDependencies returns dependencies implied by the Gemini provider.

func (*Provider) Name

func (p *Provider) Name() string

Name returns the provider identifier.

func (*Provider) PrepareContainer

func (p *Provider) PrepareContainer(ctx context.Context, opts provider.PrepareOpts) (*provider.ContainerConfig, error)

PrepareContainer sets up staging directories and config files for Gemini CLI. It creates a staging directory with settings.json and optionally oauth_creds.json that will be copied to ~/.gemini at container startup by moat-init.

func (*Provider) Refresh

Refresh re-acquires a fresh token and updates the proxy.

func (*Provider) RefreshInterval

func (p *Provider) RefreshInterval() time.Duration

RefreshInterval returns how often to attempt refresh. Google OAuth tokens expire after 1 hour; refresh 15 minutes before.

func (*Provider) RegisterCLI

func (p *Provider) RegisterCLI(root *cobra.Command)

RegisterCLI registers Gemini-related CLI commands. This adds the `moat gemini` command group with subcommands.

type RefreshResult

type RefreshResult struct {
	AccessToken string
	ExpiresAt   time.Time
}

RefreshResult holds the result of a token refresh.

type SecuritySettings

type SecuritySettings struct {
	Auth AuthSettings `json:"auth"`
}

SecuritySettings holds security-related settings.

type Settings

type Settings struct {
	Security SecuritySettings `json:"security"`
}

Settings represents Gemini CLI settings.json structure.

type TokenRefresher

type TokenRefresher struct {
	TokenURL   string       // Override for testing; empty uses OAuthTokenURL
	HTTPClient *http.Client // Override for testing
}

TokenRefresher refreshes Google OAuth2 access tokens using a refresh token.

func (*TokenRefresher) Refresh

func (r *TokenRefresher) Refresh(ctx context.Context, refreshToken string) (*RefreshResult, error)

Refresh exchanges a refresh token for a new access token.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL