AgentGraph / utils /environment.py
wu981526092's picture
Fix OAuth according to HF official documentation
b9161fb
"""
Environment Detection Utilities
This module provides utilities to detect the deployment environment
and configure authentication accordingly.
"""
import os
from typing import Dict, Any, Optional
def is_huggingface_space() -> bool:
"""
Detect if the application is running in Hugging Face Spaces.
Returns:
bool: True if running in HF Spaces, False otherwise
"""
# HF Spaces sets specific environment variables
hf_indicators = [
"SPACE_ID", # HF Space identifier
"SPACE_AUTHOR_NAME", # Space author
"SPACE_REPO_NAME", # Space repository name
"OAUTH_CLIENT_ID", # OAuth client ID (when oauth enabled)
]
return any(os.getenv(indicator) for indicator in hf_indicators)
def is_local_development() -> bool:
"""
Detect if the application is running in local development mode.
Returns:
bool: True if running locally, False otherwise
"""
return not is_huggingface_space()
def get_environment_info() -> Dict[str, Any]:
"""
Get comprehensive environment information.
Returns:
Dict containing environment details
"""
env_info = {
"is_hf_space": is_huggingface_space(),
"is_local_dev": is_local_development(),
"space_id": os.getenv("SPACE_ID"),
"space_author": os.getenv("SPACE_AUTHOR_NAME"),
"space_repo": os.getenv("SPACE_REPO_NAME"),
"oauth_enabled": bool(os.getenv("OAUTH_CLIENT_ID")),
"host": os.getenv("HOST", "localhost"),
"port": os.getenv("PORT", "7860"),
}
return env_info
def should_enable_auth() -> bool:
"""
Determine if authentication should be enabled based on environment.
Returns:
bool: True if auth should be enabled, False otherwise
"""
return is_huggingface_space()
def get_oauth_config() -> Optional[Dict[str, str]]:
"""
Get OAuth configuration if available.
Returns:
Dict with OAuth config or None if not available
"""
if not should_enable_auth():
return None
# Force HF-compatible scope for HF Spaces, ignore environment variable
if is_huggingface_space():
# HF automatically includes 'openid profile', we specify additional scopes
scopes = "openid profile read-repos"
else:
scopes = os.getenv("OAUTH_SCOPES", "read-repos")
# Warn about unsupported scopes for HF Spaces
if is_huggingface_space():
unsupported_scopes = []
for scope in scopes.split():
if scope not in ["email", "read-repos", "write-repos", "manage-repos",
"read-mcp", "write-discussions", "read-billing",
"inference-api", "jobs", "webhooks"]:
unsupported_scopes.append(scope)
if unsupported_scopes:
print(f"⚠️ Warning: Unsupported OAuth scopes detected: {unsupported_scopes}")
print("πŸ“ Supported HF scopes: email, read-repos, write-repos, manage-repos, read-mcp, write-discussions, read-billing, inference-api, jobs, webhooks")
oauth_config = {
"client_id": os.getenv("OAUTH_CLIENT_ID"),
"client_secret": os.getenv("OAUTH_CLIENT_SECRET"),
"scopes": scopes,
"provider_url": os.getenv("OPENID_PROVIDER_URL", "https://huggingface.co"),
}
# Only return config if client_id is available
if oauth_config["client_id"]:
return oauth_config
return None
def debug_environment() -> None:
"""
Print debug information about the current environment.
"""
env_info = get_environment_info()
oauth_config = get_oauth_config()
print("🌍 Environment Debug Information:")
print("=" * 50)
print(f"πŸ—οΈ Environment Type: {'HF Spaces' if env_info['is_hf_space'] else 'Local Development'}")
print(f"πŸ” Authentication: {'Enabled' if should_enable_auth() else 'Disabled'}")
if env_info['is_hf_space']:
print(f"πŸ†” Space ID: {env_info['space_id']}")
print(f"πŸ‘€ Author: {env_info['space_author']}")
print(f"πŸ“¦ Repo: {env_info['space_repo']}")
if oauth_config:
print(f"πŸ”‘ OAuth Client ID: {oauth_config['client_id'][:8]}..." if oauth_config['client_id'] else "Not set")
print(f"πŸ”’ OAuth Scopes: {oauth_config['scopes']}")
else:
print("❌ OAuth not configured")
else:
print("🏠 Running in local development mode")
print("πŸ’‘ Authentication will be automatically enabled when deployed to HF Spaces")
print("=" * 50)