| """
|
| API 代理服务 - 调用 Google Antigravity API
|
| """
|
| import httpx
|
| import json
|
| import uuid
|
| from typing import AsyncGenerator
|
| from models import OpenAIChatRequest, Account
|
| from protocol_converter import convert_openai_to_gemini, map_model_name, convert_gemini_to_openai_chunk
|
| from load_balancer import load_balancer
|
|
|
|
|
| GEMINI_API_URL = "https://daily-cloudcode-pa.sandbox.googleapis.com/v1internal:streamGenerateContent"
|
|
|
|
|
| async def stream_chat_completion(
|
| request: OpenAIChatRequest,
|
| account: Account
|
| ) -> AsyncGenerator[str, None]:
|
| """
|
| 流式 Chat Completion
|
|
|
| 1. 将 OpenAI 请求转换为 Gemini 格式
|
| 2. 调用 Google Antigravity API
|
| 3. 将 Gemini 响应转换回 OpenAI 格式
|
| """
|
|
|
| gemini_request = convert_openai_to_gemini(request)
|
|
|
|
|
| upstream_model = map_model_name(request.model)
|
|
|
|
|
| request_body = {
|
| "project": account.token.project_id or "default-project",
|
| "requestId": str(uuid.uuid4()),
|
| "model": upstream_model,
|
| "userAgent": "antigravity-hf",
|
| "request": {
|
| "contents": gemini_request["contents"],
|
| "systemInstruction": gemini_request["systemInstruction"],
|
| "generationConfig": gemini_request["generationConfig"],
|
| "sessionId": account.token.session_id
|
| }
|
| }
|
|
|
|
|
| url = f"{GEMINI_API_URL}?alt=sse"
|
|
|
| async with httpx.AsyncClient(timeout=120.0) as client:
|
| async with client.stream(
|
| "POST",
|
| url,
|
| json=request_body,
|
| headers={
|
| "Authorization": f"Bearer {account.token.access_token}",
|
| "Host": "daily-cloudcode-pa.sandbox.googleapis.com",
|
| "User-Agent": "antigravity-hf/1.0",
|
| "Content-Type": "application/json"
|
| }
|
| ) as response:
|
| if response.status_code != 200:
|
| error_text = await response.aread()
|
| error_msg = f"上游服务错误 ({response.status_code}): {error_text.decode()}"
|
|
|
|
|
| load_balancer.mark_account_error(
|
| account.id,
|
| response.status_code,
|
| error_msg
|
| )
|
|
|
|
|
| yield f"data: {json.dumps({'error': error_msg})}\n\n"
|
| return
|
|
|
|
|
| buffer = ""
|
| async for chunk in response.aiter_text():
|
| buffer += chunk
|
|
|
|
|
| while "\n" in buffer:
|
| line, buffer = buffer.split("\n", 1)
|
| line = line.strip()
|
|
|
| if not line:
|
| continue
|
|
|
| if line.startswith("data: "):
|
| data = line[6:]
|
|
|
| if data == "[DONE]":
|
| yield "data: [DONE]\n\n"
|
| break
|
|
|
| try:
|
| gemini_data = json.loads(data)
|
| openai_chunk = convert_gemini_to_openai_chunk(
|
| gemini_data,
|
| request.model
|
| )
|
| yield f"data: {json.dumps(openai_chunk)}\n\n"
|
| except json.JSONDecodeError:
|
| continue
|
|
|
|
|
| load_balancer.mark_account_success(account.id)
|
|
|
|
|
| async def chat_completion(
|
| request: OpenAIChatRequest,
|
| account: Account
|
| ) -> dict:
|
| """
|
| 非流式 Chat Completion
|
| """
|
| from protocol_converter import convert_gemini_to_openai_response
|
|
|
|
|
| gemini_request = convert_openai_to_gemini(request)
|
| upstream_model = map_model_name(request.model)
|
|
|
| request_body = {
|
| "project": account.token.project_id or "default-project",
|
| "requestId": str(uuid.uuid4()),
|
| "model": upstream_model,
|
| "userAgent": "antigravity-hf",
|
| "request": {
|
| "contents": gemini_request["contents"],
|
| "systemInstruction": gemini_request["systemInstruction"],
|
| "generationConfig": gemini_request["generationConfig"],
|
| "sessionId": account.token.session_id
|
| }
|
| }
|
|
|
|
|
| url = "https://daily-cloudcode-pa.sandbox.googleapis.com/v1internal:generateContent"
|
|
|
| async with httpx.AsyncClient(timeout=120.0) as client:
|
| response = await client.post(
|
| url,
|
| json=request_body,
|
| headers={
|
| "Authorization": f"Bearer {account.token.access_token}",
|
| "Host": "daily-cloudcode-pa.sandbox.googleapis.com",
|
| "User-Agent": "antigravity-hf/1.0",
|
| "Content-Type": "application/json"
|
| }
|
| )
|
|
|
| if response.status_code != 200:
|
| error_msg = f"上游服务错误 ({response.status_code}): {response.text}"
|
| load_balancer.mark_account_error(account.id, response.status_code, error_msg)
|
| return {"error": error_msg}
|
|
|
| load_balancer.mark_account_success(account.id)
|
| gemini_data = response.json()
|
| return convert_gemini_to_openai_response(gemini_data, request.model)
|
|
|