mirror of
https://github.com/fawney19/Aether.git
synced 2026-09-02 17:30:23 +08:00
refactor: 移除 Python 后端源码,全面迁移至 Rust gateway 架构
- 删除全部 Python 源码 (src/) 及 Alembic 迁移脚本,归档至 _deprecated_py_src/ - 重构 Rust gateway ai_pipeline: 拆分 planner/finalize 模块,新增 contracts/adaptation 层 - 重组 handlers 模块为 admin/public/proxy/internal/shared 子模块结构 - 新增 executor 模块,引入 Rust 原生数据库迁移 (aether-data/migrations) - 简化 CI/Docker 构建流程,移除 base image 二级构建,统一为单一 app image - 移除 Python 相关基础设施文件 (entrypoint.sh, gunicorn_conf.py, Dockerfile.base)
This commit is contained in:
386
_deprecated_py_src/api/internal/gateway_routes.py
Normal file
386
_deprecated_py_src/api/internal/gateway_routes.py
Normal file
@@ -0,0 +1,386 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request
|
||||
from fastapi.responses import JSONResponse, Response
|
||||
from sqlalchemy.orm import Session
|
||||
|
||||
from src.database import get_db
|
||||
|
||||
from . import gateway as gateway_impl
|
||||
from .gateway_contract import (
|
||||
CONTROL_EXECUTED_HEADER,
|
||||
GatewayAuthContextRequest,
|
||||
GatewayExecuteRequest,
|
||||
GatewayResolveRequest,
|
||||
GatewayStreamReportRequest,
|
||||
GatewaySyncReportRequest,
|
||||
classify_gateway_route,
|
||||
)
|
||||
|
||||
router = APIRouter(
|
||||
prefix="/api/internal/gateway",
|
||||
tags=["Internal - Gateway"],
|
||||
include_in_schema=False,
|
||||
)
|
||||
|
||||
|
||||
def _ensure_legacy_internal_gateway_request(request: Request) -> Response | None:
|
||||
if gateway_impl._request_allows_legacy_chat_cli_internal_gateway(request):
|
||||
return None
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
|
||||
|
||||
@router.post("/resolve")
|
||||
async def resolve_gateway_route(
|
||||
request: Request, payload: GatewayResolveRequest
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
decision = classify_gateway_route(payload.method, payload.path, payload.headers)
|
||||
decision.auth_context = await gateway_impl._resolve_auth_context(payload, decision)
|
||||
return JSONResponse(status_code=200, content=decision.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.post("/auth-context")
|
||||
async def resolve_gateway_auth_context(
|
||||
request: Request,
|
||||
payload: GatewayAuthContextRequest,
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
auth_context = await gateway_impl._resolve_auth_context_signature(
|
||||
headers=payload.headers,
|
||||
query_string=payload.query_string,
|
||||
auth_endpoint_signature=payload.auth_endpoint_signature,
|
||||
)
|
||||
return JSONResponse(status_code=200, content={"auth_context": auth_context})
|
||||
|
||||
|
||||
@router.post("/decision-sync")
|
||||
async def decide_gateway_sync(
|
||||
request: Request,
|
||||
payload: GatewayExecuteRequest,
|
||||
db: Session = Depends(get_db),
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
decision = classify_gateway_route(payload.method, payload.path, payload.headers)
|
||||
if not gateway_impl._allows_legacy_chat_cli_internal_route(request, decision):
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
auth_context = await gateway_impl._resolve_gateway_execute_auth_context(
|
||||
payload=payload,
|
||||
decision=decision,
|
||||
)
|
||||
|
||||
if auth_context is None or not auth_context.access_allowed:
|
||||
return JSONResponse(status_code=200, content={"action": "fallback_plan"})
|
||||
|
||||
try:
|
||||
resolved = await gateway_impl._build_gateway_sync_decision_response(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
auth_context=auth_context,
|
||||
decision=decision,
|
||||
)
|
||||
except HTTPException as exc:
|
||||
headers = dict(exc.headers or {})
|
||||
headers[CONTROL_EXECUTED_HEADER] = "true"
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={"detail": exc.detail},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
if resolved is None:
|
||||
body: dict[str, object] = {"action": "fallback_plan"}
|
||||
if payload.auth_context is None:
|
||||
body["auth_context"] = auth_context.model_dump(exclude_none=True)
|
||||
return JSONResponse(status_code=200, content=body)
|
||||
|
||||
if payload.auth_context is not None:
|
||||
resolved.auth_context = None
|
||||
|
||||
return JSONResponse(status_code=200, content=resolved.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.post("/decision-stream")
|
||||
async def decide_gateway_stream(
|
||||
request: Request,
|
||||
payload: GatewayExecuteRequest,
|
||||
db: Session = Depends(get_db),
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
decision = classify_gateway_route(payload.method, payload.path, payload.headers)
|
||||
if not gateway_impl._allows_legacy_chat_cli_internal_route(request, decision):
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
auth_context = await gateway_impl._resolve_gateway_execute_auth_context(
|
||||
payload=payload,
|
||||
decision=decision,
|
||||
)
|
||||
|
||||
if auth_context is None or not auth_context.access_allowed:
|
||||
return JSONResponse(status_code=200, content={"action": "fallback_plan"})
|
||||
|
||||
try:
|
||||
resolved = await gateway_impl._build_gateway_stream_decision_response(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
auth_context=auth_context,
|
||||
decision=decision,
|
||||
)
|
||||
except HTTPException as exc:
|
||||
headers = dict(exc.headers or {})
|
||||
headers[CONTROL_EXECUTED_HEADER] = "true"
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={"detail": exc.detail},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
if resolved is None:
|
||||
body: dict[str, object] = {"action": "fallback_plan"}
|
||||
if payload.auth_context is None:
|
||||
body["auth_context"] = auth_context.model_dump(exclude_none=True)
|
||||
return JSONResponse(status_code=200, content=body)
|
||||
|
||||
if payload.auth_context is not None:
|
||||
resolved.auth_context = None
|
||||
|
||||
return JSONResponse(status_code=200, content=resolved.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.post("/execute-sync")
|
||||
async def execute_gateway_sync(
|
||||
request: Request,
|
||||
payload: GatewayExecuteRequest,
|
||||
db: Session = Depends(get_db),
|
||||
) -> Response:
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
return await gateway_impl._execute_gateway_control_request(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
require_stream=False,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/execute-stream")
|
||||
async def execute_gateway_stream(
|
||||
request: Request,
|
||||
payload: GatewayExecuteRequest,
|
||||
db: Session = Depends(get_db),
|
||||
) -> Response:
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
return await gateway_impl._execute_gateway_control_request(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
require_stream=True,
|
||||
)
|
||||
|
||||
|
||||
@router.post("/plan-stream")
|
||||
async def plan_gateway_stream(
|
||||
request: Request,
|
||||
payload: GatewayExecuteRequest,
|
||||
db: Session = Depends(get_db),
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
decision = classify_gateway_route(payload.method, payload.path, payload.headers)
|
||||
if not gateway_impl._allows_legacy_chat_cli_internal_route(request, decision):
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
try:
|
||||
planned = await gateway_impl._build_gateway_stream_plan_response(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
)
|
||||
except HTTPException as exc:
|
||||
headers = dict(exc.headers or {})
|
||||
headers[CONTROL_EXECUTED_HEADER] = "true"
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={"detail": exc.detail},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
if planned is None:
|
||||
response = await gateway_impl._execute_gateway_control_request(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
require_stream=True,
|
||||
)
|
||||
if gateway_impl._is_gateway_control_executed_response(response):
|
||||
return response
|
||||
return gateway_impl._build_proxy_public_fallback_response()
|
||||
|
||||
if payload.auth_context is not None:
|
||||
planned.auth_context = None
|
||||
|
||||
return JSONResponse(status_code=200, content=planned.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.post("/plan-sync")
|
||||
async def plan_gateway_sync(
|
||||
request: Request,
|
||||
payload: GatewayExecuteRequest,
|
||||
db: Session = Depends(get_db),
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
decision = classify_gateway_route(payload.method, payload.path, payload.headers)
|
||||
if not gateway_impl._allows_legacy_chat_cli_internal_route(request, decision):
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
try:
|
||||
planned = await gateway_impl._build_gateway_sync_plan_response(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
)
|
||||
except HTTPException as exc:
|
||||
headers = dict(exc.headers or {})
|
||||
headers[CONTROL_EXECUTED_HEADER] = "true"
|
||||
return JSONResponse(
|
||||
status_code=exc.status_code,
|
||||
content={"detail": exc.detail},
|
||||
headers=headers,
|
||||
)
|
||||
|
||||
if planned is None:
|
||||
response = await gateway_impl._execute_gateway_control_request(
|
||||
request=request,
|
||||
payload=payload,
|
||||
db=db,
|
||||
require_stream=False,
|
||||
)
|
||||
if gateway_impl._is_gateway_control_executed_response(response):
|
||||
return response
|
||||
return gateway_impl._build_proxy_public_fallback_response()
|
||||
|
||||
if payload.auth_context is not None:
|
||||
planned.auth_context = None
|
||||
|
||||
return JSONResponse(status_code=200, content=planned.model_dump(exclude_none=True))
|
||||
|
||||
|
||||
@router.post("/report-sync")
|
||||
async def report_gateway_sync(
|
||||
request: Request,
|
||||
payload: GatewaySyncReportRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
if not gateway_impl._allows_legacy_chat_cli_report_route(request, payload.report_kind):
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
payload_copy = payload.model_copy(deep=True)
|
||||
if gateway_impl._gateway_sync_report_requires_inline(payload_copy):
|
||||
db, cleanup = gateway_impl._resolve_gateway_background_db(getattr(request, "app", None))
|
||||
try:
|
||||
await gateway_impl._run_gateway_sync_report_background(payload_copy, db)
|
||||
finally:
|
||||
if cleanup is not None:
|
||||
cleanup()
|
||||
return JSONResponse(status_code=200, content={"ok": True})
|
||||
background_tasks.add_task(
|
||||
gateway_impl._run_gateway_sync_report_background_with_session,
|
||||
payload_copy,
|
||||
getattr(request, "app", None),
|
||||
)
|
||||
return JSONResponse(status_code=200, content={"ok": True})
|
||||
|
||||
|
||||
@router.post("/finalize-sync")
|
||||
async def finalize_gateway_sync(
|
||||
request: Request,
|
||||
payload: GatewaySyncReportRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
if not gateway_impl._allows_legacy_chat_cli_report_route(request, payload.report_kind):
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
fast_response = await gateway_impl._maybe_build_gateway_core_sync_fast_success_response(payload)
|
||||
if fast_response is not None:
|
||||
if payload.report_kind in {
|
||||
"openai_chat_sync_finalize",
|
||||
"claude_chat_sync_finalize",
|
||||
"gemini_chat_sync_finalize",
|
||||
}:
|
||||
background_tasks.add_task(
|
||||
gateway_impl._run_gateway_chat_sync_finalize_background_with_session,
|
||||
payload.model_copy(deep=True),
|
||||
)
|
||||
elif payload.report_kind in {
|
||||
"openai_cli_sync_finalize",
|
||||
"openai_compact_sync_finalize",
|
||||
"claude_cli_sync_finalize",
|
||||
"gemini_cli_sync_finalize",
|
||||
}:
|
||||
background_tasks.add_task(
|
||||
gateway_impl._run_gateway_cli_sync_finalize_background_with_session,
|
||||
payload.model_copy(deep=True),
|
||||
)
|
||||
fast_response.headers[CONTROL_EXECUTED_HEADER] = "true"
|
||||
return fast_response
|
||||
|
||||
db, cleanup = gateway_impl._resolve_gateway_finalize_db(request)
|
||||
try:
|
||||
response = await gateway_impl._finalize_gateway_sync_response(
|
||||
payload,
|
||||
db=db,
|
||||
background_tasks=background_tasks,
|
||||
)
|
||||
except Exception:
|
||||
if cleanup is not None:
|
||||
cleanup()
|
||||
raise
|
||||
if cleanup is not None:
|
||||
background_tasks.add_task(cleanup)
|
||||
response.headers[CONTROL_EXECUTED_HEADER] = "true"
|
||||
return response
|
||||
|
||||
|
||||
@router.post("/report-stream")
|
||||
async def report_gateway_stream(
|
||||
request: Request,
|
||||
payload: GatewayStreamReportRequest,
|
||||
background_tasks: BackgroundTasks,
|
||||
) -> Response:
|
||||
gateway_impl.ensure_loopback(request)
|
||||
retired = _ensure_legacy_internal_gateway_request(request)
|
||||
if retired is not None:
|
||||
return retired
|
||||
if not gateway_impl._allows_legacy_chat_cli_report_route(request, payload.report_kind):
|
||||
return gateway_impl._build_retired_internal_gateway_response()
|
||||
background_tasks.add_task(
|
||||
gateway_impl._run_gateway_stream_report_background_with_session,
|
||||
payload.model_copy(deep=True),
|
||||
getattr(request, "app", None),
|
||||
)
|
||||
return JSONResponse(status_code=200, content={"ok": True})
|
||||
Reference in New Issue
Block a user