Skip to content

Commit f58e685

Browse files
committed
Enhance the logic by adding a better function to detect whether we can open the browser.
1 parent 3f49a50 commit f58e685

File tree

1 file changed

+45
-11
lines changed

1 file changed

+45
-11
lines changed

codeflash/code_utils/oauth_handler.py

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,10 @@
55
import hashlib
66
import http.server
77
import json
8+
import os
89
import secrets
910
import socket
11+
import sys
1012
import threading
1113
import time
1214
import urllib.parse
@@ -646,18 +648,50 @@ def exchange_code_for_token(self, code: str, code_verifier: str, redirect_uri: s
646648
return api_key
647649

648650

649-
def _is_graphical_browser() -> bool:
650-
text_browsers = {"lynx", "links", "w3m", "elinks", "links2"}
651-
651+
def get_browser_name_fallback() -> str | None:
652652
try:
653-
# Get the default browser
654-
browser = webbrowser.get()
655-
browser_name = getattr(browser, "name", "").lower()
656-
657-
# Check if it's a known text browser
658-
return all(text_browser not in browser_name for text_browser in text_browsers)
653+
controller = webbrowser.get()
654+
# controller.name exists for most browser controllers
655+
return getattr(controller, "name", None)
659656
except Exception:
660-
return True
657+
return None
658+
659+
660+
def should_attempt_browser_launch() -> bool:
661+
# A list of browser names that indicate we should not attempt to open a
662+
# web browser for the user.
663+
browser_blocklist = ["www-browser", "lynx", "links", "w3m", "elinks", "links2"]
664+
browser_env = os.environ.get("BROWSER") or get_browser_name_fallback()
665+
if browser_env and browser_env in browser_blocklist:
666+
return False
667+
668+
# Common environment variables used in CI/CD or other non-interactive shells.
669+
if os.environ.get("CI") or os.environ.get("DEBIAN_FRONTEND") == "noninteractive":
670+
return False
671+
672+
# The presence of SSH_CONNECTION indicates a remote session.
673+
# We should not attempt to launch a browser unless a display is explicitly available
674+
# (checked below for Linux).
675+
is_ssh = bool(os.environ.get("SSH_CONNECTION"))
676+
677+
# On Linux, the presence of a display server is a strong indicator of a GUI.
678+
if sys.platform == "linux":
679+
# These are environment variables that can indicate a running compositor on
680+
# Linux.
681+
display_variables = ["DISPLAY", "WAYLAND_DISPLAY", "MIR_SOCKET"]
682+
has_display = any(os.environ.get(v) for v in display_variables)
683+
if not has_display:
684+
return False
685+
686+
# If in an SSH session on a non-Linux OS (e.g., macOS), don't launch browser.
687+
# The Linux case is handled above (it's allowed if DISPLAY is set).
688+
if is_ssh and sys.platform != "linux":
689+
return False
690+
691+
# For non-Linux OSes, we generally assume a GUI is available
692+
# unless other signals (like SSH) suggest otherwise.
693+
# The `open` command's error handling will catch final edge cases.
694+
return True
661695

662696

663697
def _wait_for_manual_code_input(oauth: OAuthHandler) -> None:
@@ -706,7 +740,7 @@ def perform_oauth_signin() -> str | None:
706740
click.echo("❌ Failed to start local server.")
707741
return None
708742

709-
if _is_graphical_browser():
743+
if should_attempt_browser_launch():
710744
# Try to open browser
711745
click.echo("🌐 Opening browser to sign in to CodeFlash…")
712746
with contextlib.suppress(Exception):

0 commit comments

Comments
 (0)