| from fastapi import APIRouter, Depends, HTTPException, Request, BackgroundTasks |
| from fastapi.encoders import jsonable_encoder |
| from sqlalchemy.orm import Session |
| from app.models.infrastructure_intents import InfrastructureIntentRequest |
| from app.services.intent_adapter import to_oss_intent |
| from app.services.risk_service import evaluate_intent, evaluate_healing_decision |
| from app.services.intent_store import save_evaluated_intent |
| from app.services.outcome_service import record_outcome |
| from app.api.deps import get_db |
| from pydantic import BaseModel |
| import uuid |
| import logging |
| import time |
|
|
| from agentic_reliability_framework.core.models.event import ReliabilityEvent |
|
|
| |
| from app.core.usage_tracker import enforce_quota, UsageRecord, tracker |
|
|
| logger = logging.getLogger(__name__) |
| router = APIRouter() |
|
|
|
|
| class OutcomeRequest(BaseModel): |
| deterministic_id: str |
| success: bool |
| recorded_by: str |
| notes: str = "" |
|
|
|
|
| class HealingDecisionRequest(BaseModel): |
| event: ReliabilityEvent |
|
|
|
|
| @router.post("/intents/evaluate") |
| async def evaluate_intent_endpoint( |
| request: Request, |
| intent_req: InfrastructureIntentRequest, |
| background_tasks: BackgroundTasks, |
| db: Session = Depends(get_db), |
| quota: dict = Depends(enforce_quota) |
| ): |
| start_time = time.time() |
| api_key = quota["api_key"] |
| tier = quota["tier"] |
| response_data = None |
| error_msg = None |
|
|
| try: |
| oss_intent = to_oss_intent(intent_req) |
| risk_engine = request.app.state.risk_engine |
| result = evaluate_intent( |
| engine=risk_engine, |
| intent=oss_intent, |
| cost_estimate=intent_req.estimated_cost, |
| policy_violations=intent_req.policy_violations |
| ) |
|
|
| deterministic_id = str(uuid.uuid4()) |
| api_payload = jsonable_encoder(intent_req.model_dump()) |
| oss_payload = jsonable_encoder(oss_intent.model_dump()) |
|
|
| save_evaluated_intent( |
| db=db, |
| deterministic_id=deterministic_id, |
| intent_type=intent_req.intent_type, |
| api_payload=api_payload, |
| oss_payload=oss_payload, |
| environment=str(intent_req.environment), |
| risk_score=result["risk_score"] |
| ) |
|
|
| result["intent_id"] = deterministic_id |
| response_data = result |
|
|
| if tracker: |
| record = UsageRecord( |
| api_key=api_key, |
| tier=tier, |
| timestamp=time.time(), |
| endpoint="/api/v1/intents/evaluate", |
| request_body=intent_req.model_dump(), |
| response=response_data, |
| processing_ms=(time.time() - start_time) * 1000, |
| ) |
| await tracker.increment_usage_async(record, background_tasks) |
|
|
| return response_data |
|
|
| except HTTPException: |
| raise |
| except Exception as e: |
| error_msg = str(e) |
| logger.exception("Error in evaluate_intent_endpoint") |
| if tracker: |
| record = UsageRecord( |
| api_key=api_key, |
| tier=tier, |
| timestamp=time.time(), |
| endpoint="/api/v1/intents/evaluate", |
| request_body=intent_req.model_dump(), |
| error=error_msg, |
| processing_ms=(time.time() - start_time) * 1000, |
| ) |
| await tracker.increment_usage_async(record, background_tasks) |
| raise HTTPException(status_code=500, detail=error_msg) |
|
|
|
|
| @router.post("/intents/outcome") |
| async def record_outcome_endpoint( |
| request: Request, |
| outcome: OutcomeRequest, |
| db: Session = Depends(get_db) |
| ): |
| |
| try: |
| risk_engine = request.app.state.risk_engine |
| outcome_record = record_outcome( |
| db=db, |
| deterministic_id=outcome.deterministic_id, |
| success=outcome.success, |
| recorded_by=outcome.recorded_by, |
| notes=outcome.notes, |
| risk_engine=risk_engine |
| ) |
| return {"message": "Outcome recorded", "outcome_id": outcome_record.id} |
| except Exception as e: |
| raise HTTPException(status_code=500, detail=str(e)) |
|
|
|
|
| @router.post("/healing/evaluate") |
| async def evaluate_healing_decision_endpoint( |
| request: Request, |
| decision_req: HealingDecisionRequest, |
| background_tasks: BackgroundTasks, |
| quota: dict = Depends(enforce_quota) |
| ): |
| start_time = time.time() |
| api_key = quota["api_key"] |
| tier = quota["tier"] |
| response_data = None |
| error_msg = None |
|
|
| try: |
| policy_engine = request.app.state.policy_engine |
| rag_graph = getattr(request.app.state, "rag_graph", None) |
| model = getattr(request.app.state, "epistemic_model", None) |
| tokenizer = getattr(request.app.state, "epistemic_tokenizer", None) |
|
|
| response_data = evaluate_healing_decision( |
| event=decision_req.event, |
| policy_engine=policy_engine, |
| decision_engine=None, |
| rag_graph=rag_graph, |
| model=model, |
| tokenizer=tokenizer, |
| ) |
|
|
| if tracker: |
| record = UsageRecord( |
| api_key=api_key, |
| tier=tier, |
| timestamp=time.time(), |
| endpoint="/api/v1/healing/evaluate", |
| request_body=decision_req.model_dump(), |
| response=response_data, |
| processing_ms=(time.time() - start_time) * 1000, |
| ) |
| await tracker.increment_usage_async(record, background_tasks) |
|
|
| return response_data |
|
|
| except HTTPException: |
| raise |
| except Exception as e: |
| error_msg = str(e) |
| logger.exception("Error in evaluate_healing_decision_endpoint") |
| if tracker: |
| record = UsageRecord( |
| api_key=api_key, |
| tier=tier, |
| timestamp=time.time(), |
| endpoint="/api/v1/healing/evaluate", |
| request_body=decision_req.model_dump(), |
| error=error_msg, |
| processing_ms=(time.time() - start_time) * 1000, |
| ) |
| await tracker.increment_usage_async(record, background_tasks) |
| raise HTTPException(status_code=500, detail=error_msg) |
|
|