gcli2api / config.py
lightspeed's picture
Upload 3 files
a8c0fef verified
"""
Configuration constants for the Geminicli2api proxy server.
Centralizes all configuration to avoid duplication across modules.
"""
import os
from typing import Any, Optional
# Client Configuration
# 需要自动封禁的错误码 (默认值,可通过环境变量或配置覆盖)
AUTO_BAN_ERROR_CODES = [401, 403]
# Default Safety Settings for Google API
DEFAULT_SAFETY_SETTINGS = [
{"category": "HARM_CATEGORY_HARASSMENT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_HATE_SPEECH", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_SEXUALLY_EXPLICIT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_DANGEROUS_CONTENT", "threshold": "BLOCK_NONE"},
{"category": "HARM_CATEGORY_CIVIC_INTEGRITY", "threshold": "BLOCK_NONE"}
]
# Helper function to get base model name from any variant
def get_base_model_name(model_name):
"""Convert variant model name to base model name."""
# Remove all possible suffixes in order
suffixes = ["-maxthinking", "-nothinking", "-search"]
for suffix in suffixes:
if model_name.endswith(suffix):
return model_name[:-len(suffix)]
return model_name
# Helper function to check if model uses search grounding
def is_search_model(model_name):
"""Check if model name indicates search grounding should be enabled."""
return "-search" in model_name
# Helper function to check if model uses no thinking
def is_nothinking_model(model_name):
"""Check if model name indicates thinking should be disabled."""
return "-nothinking" in model_name
# Helper function to check if model uses max thinking
def is_maxthinking_model(model_name):
"""Check if model name indicates maximum thinking budget should be used."""
return "-maxthinking" in model_name
# Helper function to get thinking budget for a model
def get_thinking_budget(model_name):
"""Get the appropriate thinking budget for a model based on its name and variant."""
if is_nothinking_model(model_name):
return 128 # Limited thinking for pro
elif is_maxthinking_model(model_name):
return 32768
else:
# Default thinking budget for regular models
return -1 # Default for all models
# Helper function to check if thinking should be included in output
def should_include_thoughts(model_name):
"""Check if thoughts should be included in the response."""
if is_nothinking_model(model_name):
# For nothinking mode, still include thoughts if it's a pro model
base_model = get_base_model_name(model_name)
return "gemini-2.5-pro" in base_model
else:
# For all other modes, include thoughts
return True
# Dynamic Configuration System - Optimized for memory efficiency
async def get_config_value(key: str, default: Any = None, env_var: Optional[str] = None) -> Any:
"""Get configuration value with priority: ENV > Storage > default."""
# Priority 1: Environment variable
if env_var and os.getenv(env_var):
return os.getenv(env_var)
# Priority 2: Storage system
try:
from src.storage_adapter import get_storage_adapter
storage_adapter = await get_storage_adapter()
value = await storage_adapter.get_config(key)
# 检查值是否存在(不是None),允许空字符串、0、False等有效值
if value is not None:
return value
except Exception as e:
# Debug: print import/storage errors
# print(f"Config storage error for key {key}: {e}")
pass
return default
# Configuration getters - all async
async def get_proxy_config():
"""Get proxy configuration."""
proxy_url = await get_config_value("proxy", env_var="PROXY")
return proxy_url if proxy_url else None
async def get_calls_per_rotation() -> int:
"""Get calls per rotation setting."""
env_value = os.getenv("CALLS_PER_ROTATION")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("calls_per_rotation", 100))
async def get_auto_ban_enabled() -> bool:
"""Get auto ban enabled setting."""
env_value = os.getenv("AUTO_BAN")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("auto_ban_enabled", False))
async def get_auto_ban_error_codes() -> list:
"""
Get auto ban error codes.
Environment variable: AUTO_BAN_ERROR_CODES (comma-separated, e.g., "400,403")
TOML config key: auto_ban_error_codes
Default: [400, 403]
"""
env_value = os.getenv("AUTO_BAN_ERROR_CODES")
if env_value:
try:
return [int(code.strip()) for code in env_value.split(",") if code.strip()]
except ValueError:
pass
codes = await get_config_value("auto_ban_error_codes")
if codes and isinstance(codes, list):
return codes
return AUTO_BAN_ERROR_CODES
async def get_retry_429_max_retries() -> int:
"""Get max retries for 429 errors."""
env_value = os.getenv("RETRY_429_MAX_RETRIES")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("retry_429_max_retries", 5))
async def get_retry_429_enabled() -> bool:
"""Get 429 retry enabled setting."""
env_value = os.getenv("RETRY_429_ENABLED")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("retry_429_enabled", True))
async def get_retry_429_interval() -> float:
"""Get 429 retry interval in seconds."""
env_value = os.getenv("RETRY_429_INTERVAL")
if env_value:
try:
return float(env_value)
except ValueError:
pass
return float(await get_config_value("retry_429_interval", 1))
# Model name lists for different features
BASE_MODELS = [
"gemini-2.5-pro-preview-06-05",
"gemini-2.5-pro",
"gemini-2.5-pro-preview-05-06",
"gemini-2.5-flash",
]
def get_available_models(router_type="openai"):
"""
Get available models with feature prefixes.
Args:
router_type: "openai" or "gemini"
Returns:
List of model names with feature prefixes
"""
models = []
for base_model in BASE_MODELS:
# 基础模型
models.append(base_model)
# 假流式模型 (前缀格式)
models.append(f"假流式/{base_model}")
# 流式抗截断模型 (仅在流式传输时有效,前缀格式)
models.append(f"流式抗截断/{base_model}")
# 支持thinking模式后缀与功能前缀组合
for thinking_suffix in ["-maxthinking", "-nothinking", "-search"]:
# 基础模型 + thinking后缀
models.append(f"{base_model}{thinking_suffix}")
# 假流式 + thinking后缀
models.append(f"假流式/{base_model}{thinking_suffix}")
# 流式抗截断 + thinking后缀
models.append(f"流式抗截断/{base_model}{thinking_suffix}")
return models
def is_fake_streaming_model(model_name: str) -> bool:
"""Check if model name indicates fake streaming should be used."""
return model_name.startswith("假流式/")
def is_anti_truncation_model(model_name: str) -> bool:
"""Check if model name indicates anti-truncation should be used."""
return model_name.startswith("流式抗截断/")
def get_base_model_from_feature_model(model_name: str) -> str:
"""Get base model name from feature model name."""
# Remove feature prefixes
for prefix in ["假流式/", "流式抗截断/"]:
if model_name.startswith(prefix):
return model_name[len(prefix):]
return model_name
async def get_anti_truncation_max_attempts() -> int:
"""
Get maximum attempts for anti-truncation continuation.
Environment variable: ANTI_TRUNCATION_MAX_ATTEMPTS
TOML config key: anti_truncation_max_attempts
Default: 3
"""
env_value = os.getenv("ANTI_TRUNCATION_MAX_ATTEMPTS")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("anti_truncation_max_attempts", 3))
# Server Configuration
async def get_server_host() -> str:
"""
Get server host setting.
Environment variable: HOST
TOML config key: host
Default: 0.0.0.0
"""
return str(await get_config_value("host", "0.0.0.0", "HOST"))
async def get_server_port() -> int:
"""
Get server port setting.
Environment variable: PORT
TOML config key: port
Default: 7861
"""
env_value = os.getenv("PORT")
if env_value:
try:
return int(env_value)
except ValueError:
pass
return int(await get_config_value("port", 7861))
async def get_api_password() -> str:
"""
Get API password setting for chat endpoints.
Environment variable: API_PASSWORD
TOML config key: api_password
Default: Uses PASSWORD env var for compatibility, otherwise 'pwd'
"""
# 优先使用 API_PASSWORD,如果没有则使用通用 PASSWORD 保证兼容性
api_password = await get_config_value("api_password", None, "API_PASSWORD")
if api_password is not None:
return str(api_password)
# 兼容性:使用通用密码
return str(await get_config_value("password", "pwd", "PASSWORD"))
async def get_panel_password() -> str:
"""
Get panel password setting for web interface.
Environment variable: PANEL_PASSWORD
TOML config key: panel_password
Default: Uses PASSWORD env var for compatibility, otherwise 'pwd'
"""
# 优先使用 PANEL_PASSWORD,如果没有则使用通用 PASSWORD 保证兼容性
panel_password = await get_config_value("panel_password", None, "PANEL_PASSWORD")
if panel_password is not None:
return str(panel_password)
# 兼容性:使用通用密码
return str(await get_config_value("password", "pwd", "PASSWORD"))
async def get_server_password() -> str:
"""
Get server password setting (deprecated, use get_api_password or get_panel_password).
Environment variable: PASSWORD
TOML config key: password
Default: pwd
"""
return str(await get_config_value("password", "pwd", "PASSWORD"))
async def get_credentials_dir() -> str:
"""
Get credentials directory setting.
Environment variable: CREDENTIALS_DIR
TOML config key: credentials_dir
Default: ./creds
"""
return str(await get_config_value("credentials_dir", "./creds", "CREDENTIALS_DIR"))
async def get_code_assist_endpoint() -> str:
"""
Get Code Assist endpoint setting.
Environment variable: CODE_ASSIST_ENDPOINT
TOML config key: code_assist_endpoint
Default: https://cloudcode-pa.googleapis.com
"""
return str(await get_config_value("code_assist_endpoint", "https://cloudcode-pa.googleapis.com", "CODE_ASSIST_ENDPOINT"))
async def get_auto_load_env_creds() -> bool:
"""
Get auto load environment credentials setting.
Environment variable: AUTO_LOAD_ENV_CREDS
TOML config key: auto_load_env_creds
Default: False
"""
env_value = os.getenv("AUTO_LOAD_ENV_CREDS")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("auto_load_env_creds", False))
async def get_compatibility_mode_enabled() -> bool:
"""
Get compatibility mode setting.
兼容性模式:启用后所有system消息全部转换成user,停用system_instructions。
该选项可能会降低模型理解能力,但是能避免流式空回的情况。
Environment variable: COMPATIBILITY_MODE
TOML config key: compatibility_mode_enabled
Default: True
"""
env_value = os.getenv("COMPATIBILITY_MODE")
if env_value:
return env_value.lower() in ("true", "1", "yes", "on")
return bool(await get_config_value("compatibility_mode_enabled", True))
async def get_oauth_proxy_url() -> str:
"""
Get OAuth proxy URL setting.
用于Google OAuth2认证的代理URL。
Environment variable: OAUTH_PROXY_URL
TOML config key: oauth_proxy_url
Default: https://oauth2.googleapis.com
"""
return str(await get_config_value("oauth_proxy_url", "https://oauth2.googleapis.com", "OAUTH_PROXY_URL"))
async def get_googleapis_proxy_url() -> str:
"""
Get Google APIs proxy URL setting.
用于Google APIs调用的代理URL。
Environment variable: GOOGLEAPIS_PROXY_URL
TOML config key: googleapis_proxy_url
Default: https://www.googleapis.com
"""
return str(await get_config_value("googleapis_proxy_url", "https://www.googleapis.com", "GOOGLEAPIS_PROXY_URL"))
async def get_resource_manager_api_url() -> str:
"""
Get Google Cloud Resource Manager API URL setting.
用于Google Cloud Resource Manager API的URL。
Environment variable: RESOURCE_MANAGER_API_URL
TOML config key: resource_manager_api_url
Default: https://cloudresourcemanager.googleapis.com
"""
return str(await get_config_value("resource_manager_api_url", "https://cloudresourcemanager.googleapis.com", "RESOURCE_MANAGER_API_URL"))
async def get_service_usage_api_url() -> str:
"""
Get Google Cloud Service Usage API URL setting.
用于Google Cloud Service Usage API的URL。
Environment variable: SERVICE_USAGE_API_URL
TOML config key: service_usage_api_url
Default: https://serviceusage.googleapis.com
"""
return str(await get_config_value("service_usage_api_url", "https://serviceusage.googleapis.com", "SERVICE_USAGE_API_URL"))
# MongoDB Configuration
async def get_mongodb_uri() -> str:
"""
Get MongoDB connection URI setting.
MongoDB连接URI,用于分布式部署时的数据存储。
设置此项后将不再使用本地/creds和TOML文件。
Environment variable: MONGODB_URI
TOML config key: mongodb_uri
Default: None (使用本地文件存储)
示例格式:
- mongodb://username:password@localhost:27017/database
- mongodb+srv://username:password@cluster.mongodb.net/database
"""
return str(await get_config_value("mongodb_uri", "", "MONGODB_URI"))
async def get_mongodb_database() -> str:
"""
Get MongoDB database name setting.
MongoDB数据库名称。
Environment variable: MONGODB_DATABASE
TOML config key: mongodb_database
Default: gcli2api
"""
return str(await get_config_value("mongodb_database", "gcli2api", "MONGODB_DATABASE"))
async def is_mongodb_mode() -> bool:
"""
Check if MongoDB mode is enabled.
检查是否启用了MongoDB模式。
如果配置了MongoDB URI,则启用MongoDB模式,不再使用本地文件。
Returns:
bool: True if MongoDB mode is enabled, False otherwise
"""
mongodb_uri = await get_mongodb_uri()
return bool(mongodb_uri and mongodb_uri.strip())