peijun1's picture
Deploy AI Studio Proxy API to Hugging Face Spaces
a5784e9
Raw
History Blame Contribute Delete
9.57 kB
import argparse
import os
import re
import sys
from typing import Dict, Optional
from launcher.utils import get_proxy_from_gsettings
# --- Configuration Constants ---
PYTHON_EXECUTABLE = sys.executable
ENDPOINT_CAPTURE_TIMEOUT = int(os.environ.get("ENDPOINT_CAPTURE_TIMEOUT", "45"))
DEFAULT_SERVER_PORT = int(os.environ.get("DEFAULT_FASTAPI_PORT", "2048"))
DEFAULT_CAMOUFOX_PORT = int(os.environ.get("DEFAULT_CAMOUFOX_PORT", "9222"))
DEFAULT_STREAM_PORT = int(os.environ.get("STREAM_PORT", "3120"))
DEFAULT_HELPER_ENDPOINT = os.environ.get("GUI_DEFAULT_HELPER_ENDPOINT", "")
DEFAULT_AUTH_SAVE_TIMEOUT = int(os.environ.get("AUTH_SAVE_TIMEOUT", "30"))
DEFAULT_SERVER_LOG_LEVEL = os.environ.get("SERVER_LOG_LEVEL", "INFO")
AUTH_PROFILES_DIR = os.path.join(
os.path.dirname(os.path.dirname(__file__)), "auth_profiles"
)
ACTIVE_AUTH_DIR = os.path.join(AUTH_PROFILES_DIR, "active")
SAVED_AUTH_DIR = os.path.join(AUTH_PROFILES_DIR, "saved")
LOG_DIR = os.path.join(os.path.dirname(os.path.dirname(__file__)), "logs")
LAUNCHER_LOG_FILE_PATH = os.path.join(LOG_DIR, "launch_app.log")
DIRECT_LAUNCH = os.environ.get("DIRECT_LAUNCH", "").lower() in ("true", "1", "yes")
ws_regex = re.compile(r"(ws://\S+)")
def determine_proxy_configuration(
internal_camoufox_proxy_arg: Optional[str] = None,
) -> Dict[str, Optional[str]]:
"""
Unified proxy configuration determination function.
Priority: Command-line arguments > Environment variables > System settings.
"""
result = {"camoufox_proxy": None, "stream_proxy": None, "source": "No Proxy"}
if internal_camoufox_proxy_arg is not None:
if internal_camoufox_proxy_arg.strip():
result["camoufox_proxy"] = internal_camoufox_proxy_arg.strip()
result["stream_proxy"] = internal_camoufox_proxy_arg.strip()
result["source"] = (
f"CLI argument --internal-camoufox-proxy: {internal_camoufox_proxy_arg.strip()}"
)
else:
result["source"] = (
"CLI argument --internal-camoufox-proxy='' (Explicitly disabled)"
)
return result
unified_proxy = os.environ.get("UNIFIED_PROXY_CONFIG")
if unified_proxy:
result["camoufox_proxy"] = unified_proxy
result["stream_proxy"] = unified_proxy
result["source"] = f"Environment variable UNIFIED_PROXY_CONFIG: {unified_proxy}"
return result
http_proxy = os.environ.get("HTTP_PROXY")
if http_proxy:
result["camoufox_proxy"] = http_proxy
result["stream_proxy"] = http_proxy
result["source"] = f"Environment variable HTTP_PROXY: {http_proxy}"
return result
https_proxy = os.environ.get("HTTPS_PROXY")
if https_proxy:
result["camoufox_proxy"] = https_proxy
result["stream_proxy"] = https_proxy
result["source"] = f"Environment variable HTTPS_PROXY: {https_proxy}"
return result
if sys.platform.startswith("linux"):
gsettings_proxy = get_proxy_from_gsettings()
if gsettings_proxy:
result["camoufox_proxy"] = gsettings_proxy
result["stream_proxy"] = gsettings_proxy
result["source"] = f"gsettings System Proxy: {gsettings_proxy}"
return result
return result
def parse_args() -> argparse.Namespace:
# Resolve defaults at call time to avoid module-import-time env pinning
# (e.g., test sessions that override STREAM_PORT globally).
runtime_default_server_port = int(
os.environ.get("DEFAULT_FASTAPI_PORT", str(DEFAULT_SERVER_PORT))
)
runtime_default_stream_port = int(
os.environ.get("STREAM_PORT", str(DEFAULT_STREAM_PORT))
)
runtime_default_camoufox_port = int(
os.environ.get("DEFAULT_CAMOUFOX_PORT", str(DEFAULT_CAMOUFOX_PORT))
)
runtime_default_helper_endpoint = os.environ.get(
"GUI_DEFAULT_HELPER_ENDPOINT", DEFAULT_HELPER_ENDPOINT
)
runtime_default_auth_save_timeout = int(
os.environ.get("AUTH_SAVE_TIMEOUT", str(DEFAULT_AUTH_SAVE_TIMEOUT))
)
runtime_default_server_log_level = os.environ.get(
"SERVER_LOG_LEVEL", DEFAULT_SERVER_LOG_LEVEL
)
parser = argparse.ArgumentParser(
description="Launcher for Camoufox browser simulation and FastAPI proxy server.",
formatter_class=argparse.ArgumentDefaultsHelpFormatter,
)
# Internal parameters
parser.add_argument(
"--internal-launch-mode",
type=str,
choices=["debug", "headless", "virtual_headless"],
help=argparse.SUPPRESS,
)
parser.add_argument(
"--internal-auth-file", type=str, default=None, help=argparse.SUPPRESS
)
parser.add_argument(
"--internal-camoufox-port",
type=int,
default=runtime_default_camoufox_port,
help=argparse.SUPPRESS,
)
parser.add_argument(
"--internal-camoufox-proxy", type=str, default=None, help=argparse.SUPPRESS
)
parser.add_argument(
"--internal-camoufox-os", type=str, default="random", help=argparse.SUPPRESS
)
# User-visible parameters
parser.add_argument(
"--server-port",
type=int,
default=runtime_default_server_port,
help=f"FastAPI server listening port (Default: {runtime_default_server_port})",
)
parser.add_argument(
"--stream-port",
type=int,
default=runtime_default_stream_port,
help=f"Streaming proxy server port. Provide 0 to disable. Default: {runtime_default_stream_port}",
)
parser.add_argument(
"--helper",
type=str,
default=runtime_default_helper_endpoint,
help=f"Helper server getStreamResponse endpoint. Provide empty string to disable. Default: {runtime_default_helper_endpoint}",
)
parser.add_argument(
"--camoufox-debug-port",
type=int,
default=runtime_default_camoufox_port,
help=f"Internal Camoufox instance debugging port (Default: {runtime_default_camoufox_port})",
)
mode_selection_group = parser.add_mutually_exclusive_group()
mode_selection_group.add_argument(
"--debug",
action="store_true",
help="Start in debug mode (browser visible, interactive auth allowed)",
)
mode_selection_group.add_argument(
"--headless",
action="store_true",
help="Start in headless mode (no browser UI, requires pre-saved auth)",
)
mode_selection_group.add_argument(
"--virtual-display",
action="store_true",
help="Start in headless mode with virtual display (Xvfb, Linux only)",
)
parser.add_argument(
"--active-auth-json",
type=str,
default=None,
help="[Optional] Path to active authentication JSON file.",
)
debug_logs_default = os.environ.get("DEBUG_LOGS_ENABLED", "false").lower() == "true"
trace_logs_default = os.environ.get("TRACE_LOGS_ENABLED", "false").lower() == "true"
auto_save_auth_default = os.environ.get("AUTO_SAVE_AUTH", "false").lower() == "true"
parser.add_argument(
"--auto-save-auth",
action="store_true",
help="[Debug Mode] Automatically prompt and save new auth state after successful login.",
)
parser.add_argument(
"--save-auth-as",
type=str,
default=None,
help="[Debug Mode] Filename for the new auth file (without .json extension).",
)
parser.add_argument(
"--auth-save-timeout",
type=int,
default=runtime_default_auth_save_timeout,
help=f"[Debug Mode] Timeout in seconds to wait for auth save. Default: {runtime_default_auth_save_timeout}",
)
parser.add_argument(
"--exit-on-auth-save",
action="store_true",
help="[Debug Mode] Automatically close the launcher and processes after saving new auth file.",
)
parser.add_argument(
"--server-log-level",
type=str,
default=runtime_default_server_log_level,
choices=["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"],
help=f"Log level for server.py. Default: {runtime_default_server_log_level}",
)
parser.add_argument(
"--server-redirect-print",
action="store_true",
help="Redirect server.py print output to its logging system.",
)
parser.add_argument(
"--debug-logs",
action="store_true",
default=debug_logs_default,
help="Enable internal DEBUG logs for server.py (DEBUG_LOGS_ENABLED env).",
)
parser.add_argument(
"--trace-logs",
action="store_true",
default=trace_logs_default,
help="Enable internal TRACE logs for server.py (TRACE_LOGS_ENABLED env).",
)
parser.add_argument(
"--skip-frontend-build",
action="store_true",
help="Skip frontend build check (for environments without Node.js/npm).",
)
args = parser.parse_args()
# Mark which arguments were explicitly set via CLI
args.debug_logs_from_cli = "--debug-logs" in sys.argv
args.trace_logs_from_cli = "--trace-logs" in sys.argv
args.auto_save_auth_from_cli = "--auto-save-auth" in sys.argv
args.server_redirect_print_from_cli = "--server-redirect-print" in sys.argv
# Use environment variables if not set via CLI
if not args.debug_logs_from_cli:
args.debug_logs = debug_logs_default
if not args.trace_logs_from_cli:
args.trace_logs = trace_logs_default
if not args.auto_save_auth_from_cli:
args.auto_save_auth = auto_save_auth_default
return args