Stability: CPU fix with psutil interval and LLM timeouts

This commit is contained in:
Marcos
2026-03-22 14:36:20 -03:00
parent fde085835b
commit 64731a24a5
9 changed files with 2073 additions and 13 deletions

129
main.py
View File

@@ -52,7 +52,7 @@ async def check_login(is_auth: bool = Depends(verify_password)):
async def get_system_status(is_auth: bool = Depends(verify_password)):
"""Retorna o status do sistema (CPU, RAM, Disco) sem travar o loop."""
def get_stats():
cpu_percent = psutil.cpu_percent(interval=0.1)
cpu_percent = psutil.cpu_percent(interval=0.5)
vm = psutil.virtual_memory()
disk = psutil.disk_usage('/')
return {
@@ -190,6 +190,133 @@ async def telegram_webhook(request: Request):
print("Update recebido do Telegram:", update)
return {"ok": True}
# ============================================================
# NOVOS ENDPOINTS - ORQUESTRADOR
# ============================================================
from orchestrator import (
orchestrate, handle_message, get_orchestrator_status,
get_llm_config, set_llm_config, format_confirmation_message,
format_completion_message
)
from llm_providers import get_available_models
from credential_manager import sync_credentials
@app.post("/api/orchestrate")
async def orchestrate_task(task_data: dict, is_auth: bool = Depends(verify_password)):
"""
Executa tarefa orquestrada.
POST /api/orchestrate
{
"task": "faz deploy do app X",
"confirmed": false
}
Response:
{
"status": "needs_confirmation" | "completed",
"plan": {...},
"confirmation_needed_for": [...],
"message": "..." (para display)
}
"""
task = task_data.get("task", "")
confirmed = task_data.get("confirmed", False)
if not task:
return JSONResponse(content={"status": "error", "message": "Task vazia"}, status_code=400)
result = orchestrate(task, user_confirmed=confirmed)
# Formata mensagem para display
if result["status"] == "needs_confirmation":
message = format_confirmation_message(result)
return JSONResponse(content={
"status": "needs_confirmation",
"plan": result["plan"],
"confirmation_needed_for": result["confirmation_needed_for"],
"message": message
})
return JSONResponse(content={
"status": "completed",
"plan": result["plan"],
"results": result.get("results", []),
"message": format_completion_message(result) if 'format_completion_message' in dir() else "Concluído"
})
@app.get("/api/orchestrator-status")
async def get_orch_status(is_auth: bool = Depends(verify_password)):
"""Retorna status do orquestrador."""
return JSONResponse(content=get_orchestrator_status())
@app.get("/api/llm-config")
async def get_llm_configuration(is_auth: bool = Depends(verify_password)):
"""Retorna configuração atual de LLMs."""
return JSONResponse(content=get_llm_config())
@app.post("/api/llm-config")
async def update_llm_configuration(config_data: dict, is_auth: bool = Depends(verify_password)):
"""Atualiza configuração de LLMs."""
planner_provider = config_data.get("planner_provider") or None
planner_model = config_data.get("planner_model") or None
executor_provider = config_data.get("executor_provider") or None
executor_model = config_data.get("executor_model") or None
changes = set_llm_config(
planner_provider=planner_provider,
planner_model=planner_model,
executor_provider=executor_provider,
executor_model=executor_model
)
return JSONResponse(content={"status": "success", "changes": changes})
@app.get("/api/llm-models")
async def list_llm_models(is_auth: bool = Depends(verify_password)):
"""Lista modelos disponíveis para cada provider."""
models = get_available_models()
return JSONResponse(content={"models": models})
@app.post("/api/sync-credentials")
async def sync_creds(is_auth: bool = Depends(verify_password)):
"""Força sincronização de credenciais."""
result = sync_credentials()
return JSONResponse(content=result)
@app.get("/api/tools")
async def list_tools(is_auth: bool = Depends(verify_password)):
"""Lista todas as ferramentas disponíveis."""
from tools_v2 import get_tools_by_danger
return JSONResponse(content={
"tools": {
"safe": get_tools_by_danger("safe"),
"medium": get_tools_by_danger("medium"),
"dangerous": get_tools_by_danger("dangerous")
}
})
@app.post("/api/handle-message")
async def handle_web_message(message: dict, is_auth: bool = Depends(verify_password)):
"""
Manipula mensagem do usuário (alternativa ao chat normal).
Suporta confirmação de ações perigosas.
POST /api/handle-message
{
"text": "faz deploy do app",
"confirmed": false
}
"""
text = message.get("text", "")
confirmed = message.get("confirmed", False)
if not text:
return JSONResponse(content={"reply": "Mensagem vazia"})
reply = await run_in_threadpool(handle_message, text=text, confirmed=confirmed)
return JSONResponse(content={"reply": reply})
if __name__ == "__main__":
import uvicorn
uvicorn.run("main:app", host="0.0.0.0", port=8000, reload=True)