SysOps: deploy-all — 2026-06-09 10:41 UTC
This commit is contained in:
@@ -7,7 +7,7 @@ from fastapi import APIRouter, HTTPException
|
||||
from pydantic import BaseModel, Field
|
||||
|
||||
from app.db import fetch_all
|
||||
from app.services import agent_souls
|
||||
from app.services import agent_approvals, agent_souls
|
||||
|
||||
router = APIRouter(prefix="/api/agents", tags=["agents-api"])
|
||||
|
||||
@@ -20,6 +20,21 @@ class SoulUpdate(BaseModel):
|
||||
is_active: Optional[bool] = None
|
||||
|
||||
|
||||
class ActionRequestBody(BaseModel):
|
||||
agent_key: str
|
||||
title: str = Field(..., min_length=1, max_length=255)
|
||||
action_type: str = "query"
|
||||
query_payload: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
class RejectBody(BaseModel):
|
||||
reason: str = ""
|
||||
|
||||
|
||||
class ExecuteBody(BaseModel):
|
||||
result: dict[str, Any] = Field(default_factory=dict)
|
||||
|
||||
|
||||
@router.get("/souls")
|
||||
def api_list_souls() -> dict[str, Any]:
|
||||
return {"items": agent_souls.list_souls(), "count": len(agent_souls.list_souls())}
|
||||
@@ -33,6 +48,15 @@ def api_get_soul(agent_key: str) -> dict[str, Any]:
|
||||
return {"soul": soul}
|
||||
|
||||
|
||||
@router.get("/souls/{agent_key}/events")
|
||||
def api_list_agent_events(agent_key: str, limit: int = 50) -> dict[str, Any]:
|
||||
soul = agent_souls.get_soul(agent_key)
|
||||
if not soul:
|
||||
raise HTTPException(404, "Agent not found")
|
||||
items = agent_souls.list_agent_events(agent_key, limit=min(limit, 100))
|
||||
return {"agent_key": agent_key.lower(), "items": items, "count": len(items)}
|
||||
|
||||
|
||||
@router.put("/souls/{agent_key}")
|
||||
def api_update_soul(agent_key: str, body: SoulUpdate) -> dict[str, Any]:
|
||||
try:
|
||||
@@ -92,4 +116,111 @@ def api_agents_mesh() -> dict[str, Any]:
|
||||
"""
|
||||
)
|
||||
edges = [{"source": str(r["source_key"]), "target": "herman", "weight": int(r["weight"])} for r in edge_rows]
|
||||
return {"nodes": nodes, "edges": edges}
|
||||
return {"nodes": nodes, "edges": edges, "executives": [{"id": "ceo", "label": "CEO", "role": "Aissa"}, {"id": "cto", "label": "CTO", "role": "Platform"}]}
|
||||
|
||||
|
||||
@router.get("/approvals")
|
||||
def api_list_approvals(status: Optional[str] = None, limit: int = 50) -> dict[str, Any]:
|
||||
try:
|
||||
items = agent_approvals.list_requests(status=status, limit=limit)
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
return {"items": items, "count": len(items)}
|
||||
|
||||
|
||||
@router.post("/requests")
|
||||
def api_create_action_request(body: ActionRequestBody) -> dict[str, Any]:
|
||||
try:
|
||||
req = agent_approvals.create_request(
|
||||
body.agent_key,
|
||||
body.title,
|
||||
action_type=body.action_type,
|
||||
query_payload=body.query_payload,
|
||||
)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=400, detail=str(exc)) from exc
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
return {"ok": True, "request": req, "message": "Wacht op goedkeuring voordat query uitgevoerd mag worden"}
|
||||
|
||||
|
||||
@router.post("/approvals/{request_id}/approve")
|
||||
def api_approve_request(request_id: int) -> dict[str, Any]:
|
||||
import os
|
||||
|
||||
import httpx
|
||||
|
||||
try:
|
||||
req = agent_approvals.approve_request(request_id, approved_by="ceo")
|
||||
action = req.get("action_type") or ""
|
||||
auto_result = None
|
||||
|
||||
if action in ("config_backup", "maintenance_scan"):
|
||||
tools_url = os.getenv("TOOLS_API_URL", "http://tools-api:8700").rstrip("/")
|
||||
path = "/ops/backup/run" if action == "config_backup" else "/ops/maintenance/scan"
|
||||
payload = {"approval_request_id": request_id} if action == "config_backup" else None
|
||||
with httpx.Client(timeout=180.0) as client:
|
||||
resp = client.post(f"{tools_url}{path}", json=payload or {})
|
||||
try:
|
||||
auto_result = resp.json()
|
||||
except Exception:
|
||||
auto_result = {"ok": False, "detail": resp.text}
|
||||
req = agent_approvals.mark_executed(request_id, auto_result or {})
|
||||
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
return {"ok": True, "request": req, "executed": auto_result is not None, "result": auto_result}
|
||||
|
||||
|
||||
@router.post("/approvals/{request_id}/reject")
|
||||
def api_reject_request(request_id: int, body: RejectBody) -> dict[str, Any]:
|
||||
try:
|
||||
req = agent_approvals.reject_request(request_id, reason=body.reason)
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
return {"ok": True, "request": req}
|
||||
|
||||
|
||||
@router.post("/approvals/{request_id}/execute")
|
||||
def api_execute_approved_request(request_id: int, body: ExecuteBody) -> dict[str, Any]:
|
||||
import os
|
||||
|
||||
import httpx
|
||||
|
||||
try:
|
||||
req = agent_approvals.require_approved(request_id)
|
||||
result_payload = body.result or {}
|
||||
action = req.get("action_type") or ""
|
||||
|
||||
if action == "config_backup":
|
||||
tools_url = os.getenv("TOOLS_API_URL", "http://tools-api:8700").rstrip("/")
|
||||
with httpx.Client(timeout=180.0) as client:
|
||||
resp = client.post(
|
||||
f"{tools_url}/ops/backup/run",
|
||||
json={"approval_request_id": request_id},
|
||||
)
|
||||
try:
|
||||
result_payload = resp.json()
|
||||
except Exception:
|
||||
result_payload = {"ok": False, "detail": resp.text}
|
||||
if resp.status_code >= 400:
|
||||
raise HTTPException(status_code=502, detail=result_payload.get("detail") or resp.text)
|
||||
|
||||
elif action == "maintenance_scan":
|
||||
tools_url = os.getenv("TOOLS_API_URL", "http://tools-api:8700").rstrip("/")
|
||||
with httpx.Client(timeout=120.0) as client:
|
||||
resp = client.post(f"{tools_url}/ops/maintenance/scan")
|
||||
result_payload = resp.json() if resp.status_code < 400 else {"ok": False, "detail": resp.text}
|
||||
|
||||
req = agent_approvals.mark_executed(request_id, result_payload)
|
||||
except HTTPException:
|
||||
raise
|
||||
except PermissionError as exc:
|
||||
raise HTTPException(status_code=403, detail=str(exc)) from exc
|
||||
except ValueError as exc:
|
||||
raise HTTPException(status_code=404, detail=str(exc)) from exc
|
||||
except Exception as exc:
|
||||
raise HTTPException(status_code=500, detail=str(exc)) from exc
|
||||
return {"ok": True, "request": req}
|
||||
|
||||
Reference in New Issue
Block a user