@@ -115,29 +115,47 @@ export const GeminiCLIOAuthPlugin = async (
115115 authorize : async ( ) => {
116116 console . log ( "\n=== Google Gemini OAuth Setup ===" ) ;
117117
118+ // Detect headless/SSH environment
119+ const isHeadless = ! ! (
120+ process . env . SSH_CONNECTION ||
121+ process . env . SSH_CLIENT ||
122+ process . env . SSH_TTY ||
123+ process . env . OPENCODE_HEADLESS
124+ ) ;
125+
118126 let listener : OAuthListener | null = null ;
119- try {
120- listener = await startOAuthListener ( ) ;
121- const { host } = new URL ( GEMINI_REDIRECT_URI ) ;
122- console . log ( "1. You'll be asked to sign in to your Google account and grant permission." ) ;
123- console . log (
124- `2. We'll automatically capture the browser redirect on http://${ host } . No need to paste anything back here.` ,
125- ) ;
126- console . log ( "3. Once you see the 'Authentication complete' page in your browser, return to this terminal." ) ;
127- } catch ( error ) {
127+ if ( ! isHeadless ) {
128+ try {
129+ listener = await startOAuthListener ( ) ;
130+ const { host } = new URL ( GEMINI_REDIRECT_URI ) ;
131+ console . log ( "1. You'll be asked to sign in to your Google account and grant permission." ) ;
132+ console . log (
133+ `2. We'll automatically capture the browser redirect on http://${ host } . No need to paste anything back here.` ,
134+ ) ;
135+ console . log ( "3. Once you see the 'Authentication complete' page in your browser, return to this terminal." ) ;
136+ } catch ( error ) {
137+ console . log ( "1. You'll be asked to sign in to your Google account and grant permission." ) ;
138+ console . log ( "2. After you approve, the browser will try to redirect to a 'localhost' page." ) ;
139+ console . log (
140+ "3. This page will show an error like 'This site can't be reached'. This is perfectly normal and means it worked!" ,
141+ ) ;
142+ console . log (
143+ "4. Once you see that error, copy the entire URL from the address bar, paste it back here, and press Enter." ,
144+ ) ;
145+ if ( error instanceof Error ) {
146+ console . log ( `\nWarning: Couldn't start the local callback listener (${ error . message } ). Falling back to manual copy/paste.` ) ;
147+ } else {
148+ console . log ( "\nWarning: Couldn't start the local callback listener. Falling back to manual copy/paste." ) ;
149+ }
150+ }
151+ } else {
152+ console . log ( "Headless environment detected. Using manual OAuth flow." ) ;
128153 console . log ( "1. You'll be asked to sign in to your Google account and grant permission." ) ;
129- console . log ( "2. After you approve, the browser will try to redirect to a 'localhost' page ." ) ;
154+ console . log ( "2. After you approve, the browser will redirect to a 'localhost' URL ." ) ;
130155 console . log (
131- "3. This page will show an error like 'This site can’t be reached'. This is perfectly normal and means it worked! " ,
156+ "3. Copy the ENTIRE URL from your browser's address bar (it will look like: http://localhost:8085/oauth2callback?code=...&state=...) " ,
132157 ) ;
133- console . log (
134- "4. Once you see that error, copy the entire URL from the address bar, paste it back here, and press Enter." ,
135- ) ;
136- if ( error instanceof Error ) {
137- console . log ( `\nWarning: Couldn't start the local callback listener (${ error . message } ). Falling back to manual copy/paste.` ) ;
138- } else {
139- console . log ( "\nWarning: Couldn't start the local callback listener. Falling back to manual copy/paste." ) ;
140- }
158+ console . log ( "4. Paste the URL back here and press Enter." ) ;
141159 }
142160 console . log ( "\n" ) ;
143161
0 commit comments