@@ -27,7 +27,7 @@ import { autoSyncState } from "./state-repo.js"
2727// INVARIANT: Credentials are stored in isolated account directory
2828// COMPLEXITY: O(1) for API key, O(user_interaction) for OAuth
2929
30- type GeminiRuntime = FileSystem . FileSystem | Path . Path | CommandExecutor . CommandExecutor
30+ export type GeminiRuntime = FileSystem . FileSystem | Path . Path | CommandExecutor . CommandExecutor
3131type GeminiAuthMethod = "none" | "api-key" | "oauth"
3232
3333const geminiImageName = "docker-git-auth-gemini:latest"
@@ -47,9 +47,9 @@ export const geminiAuthRoot = ".docker-git/.orch/auth/gemini"
4747const geminiApiKeyFileName = ".api-key"
4848const geminiEnvFileName = ".env"
4949
50- const geminiApiKeyPath = ( accountPath : string ) : string => `${ accountPath } /${ geminiApiKeyFileName } `
51- const geminiEnvFilePath = ( accountPath : string ) : string => `${ accountPath } /${ geminiEnvFileName } `
52- const geminiCredentialsPath = ( accountPath : string ) : string => `${ accountPath } /${ geminiCredentialsDir } `
50+ export const geminiApiKeyPath = ( accountPath : string ) : string => `${ accountPath } /${ geminiApiKeyFileName } `
51+ export const geminiEnvFilePath = ( accountPath : string ) : string => `${ accountPath } /${ geminiEnvFileName } `
52+ export const geminiCredentialsPath = ( accountPath : string ) : string => `${ accountPath } /${ geminiCredentialsDir } `
5353
5454// CHANGE: render Dockerfile for Gemini CLI authentication image
5555// WHY: Gemini CLI OAuth requires running in Docker for headless environments
@@ -96,7 +96,7 @@ const resolveGeminiAccountPath = (path: Path.Path, rootPath: string, label: stri
9696 return { accountLabel, accountPath }
9797}
9898
99- const withGeminiAuth = < A , E > (
99+ export const withGeminiAuth = < A , E > (
100100 command : AuthGeminiLoginCommand | AuthGeminiLogoutCommand | AuthGeminiStatusCommand ,
101101 run : (
102102 context : GeminiAccountContext
@@ -200,7 +200,7 @@ const hasOauthCredentials = (
200200// PURITY: SHELL
201201// INVARIANT: API key takes precedence over OAuth credentials
202202// COMPLEXITY: O(1)
203- const resolveGeminiAuthMethod = (
203+ export const resolveGeminiAuthMethod = (
204204 fs : FileSystem . FileSystem ,
205205 accountPath : string
206206) : Effect . Effect < GeminiAuthMethod , PlatformError > =>
@@ -234,6 +234,24 @@ export const authGeminiLogin = (
234234 const apiKeyFilePath = geminiApiKeyPath ( accountPath )
235235 yield * _ ( fs . writeFileString ( apiKeyFilePath , `${ apiKey . trim ( ) } \n` ) )
236236 yield * _ ( fs . chmod ( apiKeyFilePath , 0o600 ) , Effect . orElseSucceed ( ( ) => void 0 ) )
237+
238+ const credentialsDir = geminiCredentialsPath ( accountPath )
239+ yield * _ ( fs . makeDirectory ( credentialsDir , { recursive : true } ) )
240+ const settingsPath = `${ credentialsDir } /settings.json`
241+ yield * _ (
242+ fs . writeFileString (
243+ settingsPath ,
244+ JSON . stringify (
245+ {
246+ model : "gemini-3.1-pro-preview" ,
247+ web_search : true ,
248+ security : { folderTrust : { enabled : false } , approvalPolicy : "never" }
249+ } ,
250+ null ,
251+ 2
252+ ) + "\n"
253+ )
254+ )
237255 } ) ) . pipe (
238256 Effect . zipRight ( autoSyncState ( `chore(state): auth gemini ${ accountLabel } ` ) )
239257 )
@@ -253,16 +271,11 @@ export const authGeminiLoginCli = (
253271 _command : AuthGeminiLoginCommand
254272) : Effect . Effect < void , PlatformError | CommandFailedError , GeminiRuntime > =>
255273 Effect . gen ( function * ( _ ) {
256- yield * _ ( Effect . log ( "Gemini CLI supports two authentication methods:" ) )
257- yield * _ ( Effect . log ( "" ) )
258- yield * _ ( Effect . log ( "1. API Key (recommended for simplicity):" ) )
259- yield * _ ( Effect . log ( " - Go to https://ai.google.dev/aistudio" ) )
260- yield * _ ( Effect . log ( " - Create or retrieve your API key" ) )
261- yield * _ ( Effect . log ( " - Use: docker-git menu -> Auth profiles -> Gemini CLI: set API key" ) )
262- yield * _ ( Effect . log ( "" ) )
263- yield * _ ( Effect . log ( "2. OAuth (Sign in with Google):" ) )
264- yield * _ ( Effect . log ( " - Use: docker-git menu -> Auth profiles -> Gemini CLI: login via OAuth" ) )
265- yield * _ ( Effect . log ( " - Follow the prompts to authenticate with your Google account" ) )
274+ yield * _ (
275+ Effect . log (
276+ "Gemini CLI supports two authentication methods:\n\n1. API Key (recommended for simplicity):\n - Go to https://ai.google.dev/aistudio\n - Create or retrieve your API key\n - Use: docker-git menu -> Auth profiles -> Gemini CLI: set API key\n\n2. OAuth (Sign in with Google):\n - Use: docker-git menu -> Auth profiles -> Gemini CLI: login via OAuth\n - Follow the prompts to authenticate with your Google account"
277+ )
278+ )
266279 } )
267280
268281// CHANGE: login to Gemini CLI via OAuth in Docker container
@@ -299,7 +312,16 @@ const prepareGeminiCredentialsDir = (
299312const writeInitialSettings = ( credentialsDir : string , fs : FileSystem . FileSystem ) =>
300313 Effect . gen ( function * ( _ ) {
301314 const settingsPath = `${ credentialsDir } /settings.json`
302- yield * _ ( fs . writeFileString ( settingsPath , JSON . stringify ( { security : { folderTrust : { enabled : false } } } ) ) )
315+ yield * _ (
316+ fs . writeFileString (
317+ settingsPath ,
318+ JSON . stringify ( {
319+ model : "gemini-3.1-pro-preview" ,
320+ web_search : true ,
321+ security : { folderTrust : { enabled : false } }
322+ } )
323+ )
324+ )
303325
304326 const trustedFoldersPath = `${ credentialsDir } /trustedFolders.json`
305327 yield * _ (
@@ -340,6 +362,8 @@ export const authGeminiLoginOauth = (
340362 settingsPath ,
341363 JSON . stringify (
342364 {
365+ model : "gemini-3.1-pro-preview" ,
366+ web_search : true ,
343367 security : {
344368 folderTrust : { enabled : false } ,
345369 auth : { selectedType : "oauth-personal" } ,
@@ -358,53 +382,5 @@ export const authGeminiLoginOauth = (
358382 )
359383}
360384
361- // CHANGE: show Gemini CLI auth status for a given label
362- // WHY: allow verifying API key/OAuth presence without exposing credentials
363- // QUOTE(ТЗ): "Добавь поддержку gemini CLI"
364- // REF: issue-146
365- // SOURCE: https://geminicli.com/docs/get-started/authentication/
366- // FORMAT THEOREM: forall cmd: authGeminiStatus(cmd) -> connected(cmd, method) | disconnected(cmd)
367- // PURITY: SHELL
368- // EFFECT: Effect<void, PlatformError | CommandFailedError, GeminiRuntime>
369- // INVARIANT: never logs API keys or OAuth tokens
370- // COMPLEXITY: O(1)
371- export const authGeminiStatus = (
372- command : AuthGeminiStatusCommand
373- ) : Effect . Effect < void , PlatformError | CommandFailedError , GeminiRuntime > =>
374- withGeminiAuth ( command , ( { accountLabel, accountPath, fs } ) =>
375- Effect . gen ( function * ( _ ) {
376- const authMethod = yield * _ ( resolveGeminiAuthMethod ( fs , accountPath ) )
377- if ( authMethod === "none" ) {
378- yield * _ ( Effect . log ( `Gemini not connected (${ accountLabel } ).` ) )
379- return
380- }
381- yield * _ ( Effect . log ( `Gemini connected (${ accountLabel } , ${ authMethod } ).` ) )
382- } ) )
383-
384- // CHANGE: logout Gemini CLI by clearing API key and OAuth credentials for a label
385- // WHY: allow revoking Gemini CLI access deterministically
386- // QUOTE(ТЗ): "Добавь поддержку gemini CLI"
387- // REF: issue-146
388- // SOURCE: https://geminicli.com/docs/get-started/authentication/
389- // FORMAT THEOREM: forall cmd: authGeminiLogout(cmd) -> credentials_cleared(cmd)
390- // PURITY: SHELL
391- // EFFECT: Effect<void, PlatformError | CommandFailedError, GeminiRuntime>
392- // INVARIANT: all credential files (API key and OAuth) are removed from account directory
393- // COMPLEXITY: O(1)
394- export const authGeminiLogout = (
395- command : AuthGeminiLogoutCommand
396- ) : Effect . Effect < void , PlatformError | CommandFailedError , GeminiRuntime > =>
397- Effect . gen ( function * ( _ ) {
398- const accountLabel = normalizeAccountLabel ( command . label , "default" )
399- yield * _ (
400- withGeminiAuth ( command , ( { accountPath, fs } ) =>
401- Effect . gen ( function * ( _ ) {
402- // Clear API key
403- yield * _ ( fs . remove ( geminiApiKeyPath ( accountPath ) , { force : true } ) )
404- yield * _ ( fs . remove ( geminiEnvFilePath ( accountPath ) , { force : true } ) )
405- // Clear OAuth credentials (entire .gemini directory)
406- yield * _ ( fs . remove ( geminiCredentialsPath ( accountPath ) , { recursive : true , force : true } ) )
407- } ) )
408- )
409- yield * _ ( autoSyncState ( `chore(state): auth gemini logout ${ accountLabel } ` ) )
410- } ) . pipe ( Effect . asVoid )
385+ export { authGeminiLogout } from "./auth-gemini-logout.js"
386+ export { authGeminiStatus } from "./auth-gemini-status.js"
0 commit comments