feat(platform): close AI expense value loop

Add tenant-safe value, telemetry, connector, commercial, and production-readiness foundations.
This commit is contained in:
caoxiaozhu
2026-07-17 14:14:08 +08:00
parent 242d68c36f
commit 787bc3a481
507 changed files with 82072 additions and 6344 deletions

View File

@@ -5,13 +5,15 @@ from typing import Annotated
from fastapi import APIRouter, Depends, HTTPException, Query, status
from sqlalchemy.orm import Session
from app.api.deps import get_current_user, get_db
from app.api.deps import CurrentUserContext, get_current_user, get_db
from app.schemas.agent_run import AgentRunRead, AgentRunStatsRead
from app.schemas.common import ErrorResponse
from app.services.agent_run_access_policy import AgentRunAccessPolicy
from app.services.agent_runs import AgentRunService
router = APIRouter(prefix="/agent-runs", dependencies=[Depends(get_current_user)])
DbSession = Annotated[Session, Depends(get_db)]
CurrentUser = Annotated[CurrentUserContext, Depends(get_current_user)]
@router.get(
@@ -22,6 +24,7 @@ DbSession = Annotated[Session, Depends(get_db)]
)
def list_agent_runs(
db: DbSession,
current_user: CurrentUser,
agent: Annotated[
str | None,
Query(description="Agent 名称筛选。"),
@@ -39,9 +42,17 @@ def list_agent_runs(
Query(ge=1, le=100, description="返回记录上限。"),
] = 20,
) -> list[AgentRunRead]:
return AgentRunService(db).list_runs(
agent=agent, status=status_value, source=source, limit=limit
tenant_id = AgentRunAccessPolicy.require_current_tenant_id(current_user)
scope_clause = AgentRunAccessPolicy.build_query_scope(current_user)
runs = AgentRunService(db).list_runs_for_tenant(
tenant_id=tenant_id,
agent=agent,
status=status_value,
source=source,
limit=limit,
scope_clause=scope_clause,
)
return AgentRunAccessPolicy.filter_list_items(runs, current_user, db)
@router.get(
@@ -52,6 +63,7 @@ def list_agent_runs(
)
def summarize_agent_runs(
db: DbSession,
current_user: CurrentUser,
agent: Annotated[
str | None,
Query(description="Agent 名称筛选。"),
@@ -69,11 +81,15 @@ def summarize_agent_runs(
Query(ge=1, le=500, description="统计最近记录数。"),
] = 200,
) -> AgentRunStatsRead:
return AgentRunService(db).summarize_runs(
tenant_id = AgentRunAccessPolicy.require_current_tenant_id(current_user)
scope_clause = AgentRunAccessPolicy.build_query_scope(current_user)
return AgentRunService(db).summarize_runs_for_tenant(
tenant_id=tenant_id,
agent=agent,
status=status_value,
source=source,
limit=limit,
scope_clause=scope_clause,
)
@@ -89,8 +105,17 @@ def summarize_agent_runs(
}
},
)
def get_agent_run(run_id: str, db: DbSession) -> AgentRunRead:
run = AgentRunService(db).get_run(run_id)
def get_agent_run(
run_id: str,
db: DbSession,
current_user: CurrentUser,
) -> AgentRunRead:
tenant_id = AgentRunAccessPolicy.require_current_tenant_id(current_user)
run = AgentRunService(db).get_run_for_tenant(
run_id,
tenant_id=tenant_id,
)
if run is None:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Run not found")
AgentRunAccessPolicy.require_detail_read(run, current_user)
return run