Spaces:
Running
Running
File size: 5,967 Bytes
c3b0824 c86a50e 9963145 d12a6b6 9963145 c86a50e c3b0824 9963145 d12a6b6 c3b0824 4fe6125 d12a6b6 4fe6125 d12a6b6 4fe6125 d12a6b6 4fe6125 d12a6b6 c3b0824 9963145 1ee60d9 cb01b8b 9963145 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 |
import logging
import os
from fastapi import FastAPI, Request, Response
from fastapi.middleware.cors import CORSMiddleware
from .gemini_routes import router as gemini_router
from .openai_routes import router as openai_router
from .auth import get_credentials, get_user_project_id, onboard_user
# Load environment variables from .env file
try:
from dotenv import load_dotenv
load_dotenv()
logging.info("Environment variables loaded from .env file")
except ImportError:
logging.warning("python-dotenv not installed, .env file will not be loaded automatically")
except Exception as e:
logging.warning(f"Could not load .env file: {e}")
# Configure logging
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
app = FastAPI()
# Add CORS middleware for preflight requests
app.add_middleware(
CORSMiddleware,
allow_origins=["*"], # Allow all origins
allow_credentials=True,
allow_methods=["*"], # Allow all methods
allow_headers=["*"], # Allow all headers
)
@app.on_event("startup")
async def startup_event():
try:
logging.info("Starting Gemini proxy server...")
# Check if credentials exist
import os
from .config import CREDENTIAL_FILE
env_creds_json = os.getenv("GEMINI_CREDENTIALS")
creds_file_exists = os.path.exists(CREDENTIAL_FILE)
if env_creds_json or creds_file_exists:
try:
# Try to load existing credentials without OAuth flow first
creds = get_credentials(allow_oauth_flow=False)
if creds:
try:
proj_id = get_user_project_id(creds)
if proj_id:
onboard_user(creds, proj_id)
logging.info(f"Successfully onboarded with project ID: {proj_id}")
logging.info("Gemini proxy server started successfully")
logging.info("Authentication required - Password: see .env file")
except Exception as e:
logging.error(f"Setup failed: {str(e)}")
logging.warning("Server started but may not function properly until setup issues are resolved.")
else:
logging.warning("Credentials file exists but could not be loaded. Server started - authentication will be required on first request.")
except Exception as e:
logging.error(f"Credential loading error: {str(e)}")
logging.warning("Server started but credentials need to be set up.")
else:
# No credentials found - prompt user to authenticate
logging.info("No credentials found. Starting OAuth authentication flow...")
try:
creds = get_credentials(allow_oauth_flow=True)
if creds:
try:
proj_id = get_user_project_id(creds)
if proj_id:
onboard_user(creds, proj_id)
logging.info(f"Successfully onboarded with project ID: {proj_id}")
logging.info("Gemini proxy server started successfully")
except Exception as e:
logging.error(f"Setup failed: {str(e)}")
logging.warning("Server started but may not function properly until setup issues are resolved.")
else:
logging.error("Authentication failed. Server started but will not function until credentials are provided.")
except Exception as e:
logging.error(f"Authentication error: {str(e)}")
logging.warning("Server started but authentication failed.")
logging.info("Authentication required - Password: see .env file")
except Exception as e:
logging.error(f"Startup error: {str(e)}")
logging.warning("Server may not function properly.")
@app.options("/{full_path:path}")
async def handle_preflight(request: Request, full_path: str):
"""Handle CORS preflight requests without authentication."""
return Response(
status_code=200,
headers={
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, PUT, DELETE, PATCH, OPTIONS",
"Access-Control-Allow-Headers": "*",
"Access-Control-Allow-Credentials": "true",
}
)
# Root endpoint - no authentication required
@app.get("/")
async def root():
"""
Root endpoint providing project information.
No authentication required.
"""
return {
"name": "geminicli2api",
"description": "OpenAI-compatible API proxy for Google's Gemini models via gemini-cli",
"purpose": "Provides both OpenAI-compatible endpoints (/v1/chat/completions) and native Gemini API endpoints for accessing Google's Gemini models",
"version": "1.0.0",
"endpoints": {
"openai_compatible": {
"chat_completions": "/v1/chat/completions",
"models": "/v1/models"
},
"native_gemini": {
"models": "/v1beta/models",
"generate": "/v1beta/models/{model}/generateContent",
"stream": "/v1beta/models/{model}/streamGenerateContent"
},
"health": "/health"
},
"authentication": "Required for all endpoints except root and health",
"repository": "https://github.com/user/geminicli2api"
}
# Health check endpoint for Docker/Hugging Face
@app.get("/health")
async def health_check():
"""Health check endpoint for container orchestration."""
return {"status": "healthy", "service": "geminicli2api"}
app.include_router(openai_router)
app.include_router(gemini_router) |