270 lines
11 KiB
Python
270 lines
11 KiB
Python
from __future__ import annotations
|
|
|
|
from fastapi import Depends, HTTPException, Query
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
|
|
|
from ...core.response import ApiResponse, success_response
|
|
from ...dependencies.permissions import require_manager_user
|
|
from ...dependencies.tenant import get_tenant_id
|
|
from ...models import User
|
|
from ...schemas.mounted_ai_runtime import (
|
|
MountedAICutoverStatusPayload,
|
|
MountedAIEvalSuiteDetailPayload,
|
|
MountedAIEvalSuiteListPayload,
|
|
MountedAIHardCaseListPayload,
|
|
MountedAIReplayRunPayload,
|
|
MountedAIReplayRunRequest,
|
|
MountedAIRunDetailPayload,
|
|
MountedAIRunListPayload,
|
|
MountedAISourceActivationListPayload,
|
|
MountedAISourceActivationUpsertPayload,
|
|
MountedAISourceActivationUpsertRequest,
|
|
MountedAISourceListPayload,
|
|
MountedAIToolPolicyListPayload,
|
|
MountedAIToolPolicyUpsertPayload,
|
|
MountedAIToolPolicyUpsertRequest,
|
|
MountedAITrainingOpsPayload,
|
|
MountedAITopicListPayload,
|
|
)
|
|
from ...services.mounted_ai_runtime_service import MountedAIRuntimeService
|
|
from .shared import *
|
|
|
|
|
|
@router.get("/mounted-ai/sources", response_model=ApiResponse[MountedAISourceListPayload])
|
|
async def list_mounted_ai_sources(
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_sources(tenant_id=effective_tenant_id)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/source-activations", response_model=ApiResponse[MountedAISourceActivationListPayload])
|
|
async def list_mounted_ai_source_activations(
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_source_activations(tenant_id=effective_tenant_id)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/tool-policies", response_model=ApiResponse[MountedAIToolPolicyListPayload])
|
|
async def list_mounted_ai_tool_policies(
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_tool_policies(tenant_id=effective_tenant_id)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/topics", response_model=ApiResponse[MountedAITopicListPayload])
|
|
async def list_mounted_ai_topics(
|
|
mode: str | None = Query(default=None),
|
|
limit: int = Query(default=20, ge=1, le=100),
|
|
offset: int = Query(default=0, ge=0),
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_topics(
|
|
tenant_id=effective_tenant_id,
|
|
limit=limit,
|
|
offset=offset,
|
|
mode=mode,
|
|
)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/runs", response_model=ApiResponse[MountedAIRunListPayload])
|
|
async def list_mounted_ai_runs(
|
|
status: str | None = Query(default=None),
|
|
limit: int = Query(default=20, ge=1, le=100),
|
|
offset: int = Query(default=0, ge=0),
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_runs(
|
|
tenant_id=effective_tenant_id,
|
|
limit=limit,
|
|
offset=offset,
|
|
status=status,
|
|
)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/runs/{run_id}", response_model=ApiResponse[MountedAIRunDetailPayload])
|
|
async def get_mounted_ai_run_detail(
|
|
run_id: int,
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
try:
|
|
data = await MountedAIRuntimeService(db).get_run_detail(
|
|
tenant_id=effective_tenant_id,
|
|
run_id=run_id,
|
|
)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/cutover-status", response_model=ApiResponse[MountedAICutoverStatusPayload])
|
|
async def get_mounted_ai_cutover_status(
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).get_cutover_status(tenant_id=effective_tenant_id)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/eval-suites", response_model=ApiResponse[MountedAIEvalSuiteListPayload])
|
|
async def list_mounted_ai_eval_suites(
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_eval_suites(tenant_id=effective_tenant_id)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/eval-suites/{dataset_id}", response_model=ApiResponse[MountedAIEvalSuiteDetailPayload])
|
|
async def get_mounted_ai_eval_suite_detail(
|
|
dataset_id: int,
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
try:
|
|
data = await MountedAIRuntimeService(db).get_eval_suite_detail(
|
|
tenant_id=effective_tenant_id,
|
|
dataset_id=dataset_id,
|
|
)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/training-ops", response_model=ApiResponse[MountedAITrainingOpsPayload])
|
|
async def get_mounted_ai_training_ops(
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_training_ops(tenant_id=effective_tenant_id)
|
|
return success_response(data)
|
|
|
|
|
|
@router.get("/mounted-ai/hard-cases", response_model=ApiResponse[MountedAIHardCaseListPayload])
|
|
async def list_mounted_ai_hard_cases(
|
|
limit: int = Query(default=20, ge=1, le=100),
|
|
offset: int = Query(default=0, ge=0),
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
data = await MountedAIRuntimeService(db).list_hard_cases(
|
|
tenant_id=effective_tenant_id,
|
|
limit=limit,
|
|
offset=offset,
|
|
)
|
|
return success_response(data)
|
|
|
|
|
|
@router.post("/mounted-ai/admin/source-activation", response_model=ApiResponse[MountedAISourceActivationUpsertPayload])
|
|
async def upsert_mounted_ai_source_activation(
|
|
payload: MountedAISourceActivationUpsertRequest,
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
try:
|
|
data = await MountedAIRuntimeService(db).upsert_source_activation(
|
|
tenant_id=effective_tenant_id,
|
|
source_system=payload.source_system,
|
|
scope_type=payload.scope_type,
|
|
scope_ref=payload.scope_ref,
|
|
status=payload.status,
|
|
cutover_mode=payload.cutover_mode,
|
|
auto_reply_enabled=payload.auto_reply_enabled,
|
|
notes=payload.notes,
|
|
metadata_json=payload.metadata_json,
|
|
)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
return success_response(data)
|
|
|
|
|
|
@router.post("/mounted-ai/admin/tool-policy", response_model=ApiResponse[MountedAIToolPolicyUpsertPayload])
|
|
async def upsert_mounted_ai_tool_policy(
|
|
payload: MountedAIToolPolicyUpsertRequest,
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
try:
|
|
data = await MountedAIRuntimeService(db).upsert_tool_policy(
|
|
tenant_id=effective_tenant_id,
|
|
tool_name=payload.tool_name,
|
|
risk_level=payload.risk_level,
|
|
confirm_required=payload.confirm_required,
|
|
auto_execute_allowed=payload.auto_execute_allowed,
|
|
is_active=payload.is_active,
|
|
source_scope=payload.source_scope,
|
|
tenant_scope=payload.tenant_scope,
|
|
policy_metadata=payload.policy_metadata,
|
|
notes=payload.notes,
|
|
)
|
|
except ValueError as exc:
|
|
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
|
return success_response(data)
|
|
|
|
|
|
@router.post("/mounted-ai/admin/replay-run", response_model=ApiResponse[MountedAIReplayRunPayload])
|
|
async def replay_mounted_ai_run(
|
|
payload: MountedAIReplayRunRequest,
|
|
current_user: User = Depends(require_manager_user),
|
|
db: AsyncSession = Depends(get_db),
|
|
tenant_id: int = Depends(get_tenant_id),
|
|
):
|
|
effective_tenant_id = int(getattr(current_user, "tenant_id", tenant_id) or tenant_id)
|
|
try:
|
|
data = await MountedAIRuntimeService(db).replay_run(
|
|
tenant_id=effective_tenant_id,
|
|
actor_id=int(getattr(current_user, "id", 0) or 0),
|
|
run_id=payload.run_id,
|
|
asset_type=payload.asset_type,
|
|
bucket_key=payload.bucket_key,
|
|
question_text=payload.question_text,
|
|
answer_text=payload.answer_text,
|
|
corrected_answer=payload.corrected_answer,
|
|
notes=payload.notes,
|
|
persist_quality_asset=payload.persist_quality_asset,
|
|
overall_score=payload.overall_score,
|
|
rule_score=payload.rule_score,
|
|
llm_score=payload.llm_score,
|
|
findings=payload.findings,
|
|
)
|
|
except ValueError as exc:
|
|
message = str(exc)
|
|
raise HTTPException(status_code=404 if "not found" in message else 400, detail=message) from exc
|
|
return success_response(data)
|