feat(agent): add agent folder management routes and functionality
This commit is contained in:
parent
0e3c331a72
commit
72f666aca1
@ -1,7 +1,7 @@
|
|||||||
from fastapi import APIRouter, Depends, HTTPException, status, Header
|
from fastapi import APIRouter, Depends, HTTPException, status, Header, Query
|
||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from src.config.database import get_db
|
from src.config.database import get_db
|
||||||
from typing import List, Dict, Any
|
from typing import List, Dict, Any, Optional
|
||||||
import uuid
|
import uuid
|
||||||
from src.core.jwt_middleware import (
|
from src.core.jwt_middleware import (
|
||||||
get_jwt_token,
|
get_jwt_token,
|
||||||
@ -10,6 +10,9 @@ from src.core.jwt_middleware import (
|
|||||||
from src.schemas.schemas import (
|
from src.schemas.schemas import (
|
||||||
Agent,
|
Agent,
|
||||||
AgentCreate,
|
AgentCreate,
|
||||||
|
AgentFolder,
|
||||||
|
AgentFolderCreate,
|
||||||
|
AgentFolderUpdate,
|
||||||
)
|
)
|
||||||
from src.services import (
|
from src.services import (
|
||||||
agent_service,
|
agent_service,
|
||||||
@ -65,6 +68,243 @@ router = APIRouter(
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Rotas para pastas de agentes
|
||||||
|
@router.post(
|
||||||
|
"/folders", response_model=AgentFolder, status_code=status.HTTP_201_CREATED
|
||||||
|
)
|
||||||
|
async def create_folder(
|
||||||
|
folder: AgentFolderCreate,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
"""Cria uma nova pasta para organizar agentes"""
|
||||||
|
# Verifica se o usuário tem acesso ao cliente da pasta
|
||||||
|
await verify_user_client(payload, db, folder.client_id)
|
||||||
|
|
||||||
|
return agent_service.create_agent_folder(
|
||||||
|
db, folder.client_id, folder.name, folder.description
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/folders", response_model=List[AgentFolder])
|
||||||
|
async def read_folders(
|
||||||
|
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
"""Lista as pastas de agentes de um cliente"""
|
||||||
|
# Verifica se o usuário tem acesso aos dados deste cliente
|
||||||
|
await verify_user_client(payload, db, x_client_id)
|
||||||
|
|
||||||
|
return agent_service.get_agent_folders_by_client(db, x_client_id, skip, limit)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/folders/{folder_id}", response_model=AgentFolder)
|
||||||
|
async def read_folder(
|
||||||
|
folder_id: uuid.UUID,
|
||||||
|
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
"""Obtém os detalhes de uma pasta específica"""
|
||||||
|
# Verifica se o usuário tem acesso aos dados deste cliente
|
||||||
|
await verify_user_client(payload, db, x_client_id)
|
||||||
|
|
||||||
|
folder = agent_service.get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Pasta não encontrada"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verifica se a pasta pertence ao cliente informado
|
||||||
|
if folder.client_id != x_client_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Pasta não pertence ao cliente informado",
|
||||||
|
)
|
||||||
|
|
||||||
|
return folder
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/folders/{folder_id}", response_model=AgentFolder)
|
||||||
|
async def update_folder(
|
||||||
|
folder_id: uuid.UUID,
|
||||||
|
folder_data: AgentFolderUpdate,
|
||||||
|
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
"""Atualiza uma pasta de agentes"""
|
||||||
|
# Verifica se o usuário tem acesso aos dados deste cliente
|
||||||
|
await verify_user_client(payload, db, x_client_id)
|
||||||
|
|
||||||
|
# Verifica se a pasta existe
|
||||||
|
folder = agent_service.get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Pasta não encontrada"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verifica se a pasta pertence ao cliente informado
|
||||||
|
if folder.client_id != x_client_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Pasta não pertence ao cliente informado",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Atualiza a pasta
|
||||||
|
updated_folder = agent_service.update_agent_folder(
|
||||||
|
db, folder_id, folder_data.name, folder_data.description
|
||||||
|
)
|
||||||
|
return updated_folder
|
||||||
|
|
||||||
|
|
||||||
|
@router.delete("/folders/{folder_id}", status_code=status.HTTP_204_NO_CONTENT)
|
||||||
|
async def delete_folder(
|
||||||
|
folder_id: uuid.UUID,
|
||||||
|
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
"""Remove uma pasta de agentes"""
|
||||||
|
# Verifica se o usuário tem acesso aos dados deste cliente
|
||||||
|
await verify_user_client(payload, db, x_client_id)
|
||||||
|
|
||||||
|
# Verifica se a pasta existe
|
||||||
|
folder = agent_service.get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Pasta não encontrada"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verifica se a pasta pertence ao cliente informado
|
||||||
|
if folder.client_id != x_client_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Pasta não pertence ao cliente informado",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Deleta a pasta
|
||||||
|
if not agent_service.delete_agent_folder(db, folder_id):
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Pasta não encontrada"
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
@router.get("/folders/{folder_id}/agents", response_model=List[Agent])
|
||||||
|
async def read_folder_agents(
|
||||||
|
folder_id: uuid.UUID,
|
||||||
|
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
"""Lista os agentes em uma pasta específica"""
|
||||||
|
# Verifica se o usuário tem acesso aos dados deste cliente
|
||||||
|
await verify_user_client(payload, db, x_client_id)
|
||||||
|
|
||||||
|
# Verifica se a pasta existe
|
||||||
|
folder = agent_service.get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Pasta não encontrada"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verifica se a pasta pertence ao cliente informado
|
||||||
|
if folder.client_id != x_client_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Pasta não pertence ao cliente informado",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Lista os agentes da pasta
|
||||||
|
agents = agent_service.get_agents_by_folder(db, folder_id, skip, limit)
|
||||||
|
|
||||||
|
# Adiciona URL do agent card quando necessário
|
||||||
|
for agent in agents:
|
||||||
|
if not agent.agent_card_url:
|
||||||
|
agent.agent_card_url = agent.agent_card_url_property
|
||||||
|
|
||||||
|
return agents
|
||||||
|
|
||||||
|
|
||||||
|
@router.put("/{agent_id}/folder", response_model=Agent)
|
||||||
|
async def assign_agent_to_folder(
|
||||||
|
agent_id: uuid.UUID,
|
||||||
|
folder_id: Optional[uuid.UUID] = None,
|
||||||
|
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
"""Atribui um agente a uma pasta ou remove da pasta atual (se folder_id=None)"""
|
||||||
|
# Verifica se o usuário tem acesso aos dados deste cliente
|
||||||
|
await verify_user_client(payload, db, x_client_id)
|
||||||
|
|
||||||
|
# Verifica se o agente existe
|
||||||
|
agent = agent_service.get_agent(db, agent_id)
|
||||||
|
if not agent:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Agente não encontrado"
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verifica se o agente pertence ao cliente informado
|
||||||
|
if agent.client_id != x_client_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Agente não pertence ao cliente informado",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Se folder_id for fornecido, verifica se a pasta existe e pertence ao mesmo cliente
|
||||||
|
if folder_id:
|
||||||
|
folder = agent_service.get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND, detail="Pasta não encontrada"
|
||||||
|
)
|
||||||
|
|
||||||
|
if folder.client_id != x_client_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_403_FORBIDDEN,
|
||||||
|
detail="Pasta não pertence ao cliente informado",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Atribui o agente à pasta ou remove da pasta atual
|
||||||
|
updated_agent = agent_service.assign_agent_to_folder(db, agent_id, folder_id)
|
||||||
|
|
||||||
|
if not updated_agent.agent_card_url:
|
||||||
|
updated_agent.agent_card_url = updated_agent.agent_card_url_property
|
||||||
|
|
||||||
|
return updated_agent
|
||||||
|
|
||||||
|
|
||||||
|
# Modificação nas rotas existentes para suportar filtro por pasta
|
||||||
|
@router.get("/", response_model=List[Agent])
|
||||||
|
async def read_agents(
|
||||||
|
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
||||||
|
skip: int = 0,
|
||||||
|
limit: int = 100,
|
||||||
|
folder_id: Optional[uuid.UUID] = Query(None, description="Filtrar por pasta"),
|
||||||
|
db: Session = Depends(get_db),
|
||||||
|
payload: dict = Depends(get_jwt_token),
|
||||||
|
):
|
||||||
|
# Verify if the user has access to this client's data
|
||||||
|
await verify_user_client(payload, db, x_client_id)
|
||||||
|
|
||||||
|
# Get agents with optional folder filter
|
||||||
|
agents = agent_service.get_agents_by_client(
|
||||||
|
db, x_client_id, skip, limit, True, folder_id
|
||||||
|
)
|
||||||
|
|
||||||
|
for agent in agents:
|
||||||
|
if not agent.agent_card_url:
|
||||||
|
agent.agent_card_url = agent.agent_card_url_property
|
||||||
|
|
||||||
|
return agents
|
||||||
|
|
||||||
|
|
||||||
@router.post("/", response_model=Agent, status_code=status.HTTP_201_CREATED)
|
@router.post("/", response_model=Agent, status_code=status.HTTP_201_CREATED)
|
||||||
async def create_agent(
|
async def create_agent(
|
||||||
agent: AgentCreate,
|
agent: AgentCreate,
|
||||||
@ -82,26 +322,6 @@ async def create_agent(
|
|||||||
return db_agent
|
return db_agent
|
||||||
|
|
||||||
|
|
||||||
@router.get("/", response_model=List[Agent])
|
|
||||||
async def read_agents(
|
|
||||||
x_client_id: uuid.UUID = Header(..., alias="x-client-id"),
|
|
||||||
skip: int = 0,
|
|
||||||
limit: int = 100,
|
|
||||||
db: Session = Depends(get_db),
|
|
||||||
payload: dict = Depends(get_jwt_token),
|
|
||||||
):
|
|
||||||
# Verify if the user has access to this client's data
|
|
||||||
await verify_user_client(payload, db, x_client_id)
|
|
||||||
|
|
||||||
agents = agent_service.get_agents_by_client(db, x_client_id, skip, limit)
|
|
||||||
|
|
||||||
for agent in agents:
|
|
||||||
if not agent.agent_card_url:
|
|
||||||
agent.agent_card_url = agent.agent_card_url_property
|
|
||||||
|
|
||||||
return agents
|
|
||||||
|
|
||||||
|
|
||||||
@router.get("/{agent_id}", response_model=Agent)
|
@router.get("/{agent_id}", response_model=Agent)
|
||||||
async def read_agent(
|
async def read_agent(
|
||||||
agent_id: uuid.UUID,
|
agent_id: uuid.UUID,
|
||||||
|
@ -51,6 +51,23 @@ class User(Base):
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class AgentFolder(Base):
|
||||||
|
__tablename__ = "agent_folders"
|
||||||
|
|
||||||
|
id = Column(UUID(as_uuid=True), primary_key=True, default=uuid.uuid4)
|
||||||
|
client_id = Column(UUID(as_uuid=True), ForeignKey("clients.id", ondelete="CASCADE"))
|
||||||
|
name = Column(String, nullable=False)
|
||||||
|
description = Column(Text, nullable=True)
|
||||||
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||||
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||||
|
|
||||||
|
# Relação com o cliente
|
||||||
|
client = relationship("Client", backref="agent_folders")
|
||||||
|
|
||||||
|
# Relação com os agentes
|
||||||
|
agents = relationship("Agent", back_populates="folder")
|
||||||
|
|
||||||
|
|
||||||
class Agent(Base):
|
class Agent(Base):
|
||||||
__tablename__ = "agents"
|
__tablename__ = "agents"
|
||||||
|
|
||||||
@ -63,6 +80,12 @@ class Agent(Base):
|
|||||||
api_key = Column(String, nullable=True, default="")
|
api_key = Column(String, nullable=True, default="")
|
||||||
instruction = Column(Text)
|
instruction = Column(Text)
|
||||||
agent_card_url = Column(String, nullable=True)
|
agent_card_url = Column(String, nullable=True)
|
||||||
|
# Nova coluna para a pasta - opcional (nullable=True)
|
||||||
|
folder_id = Column(
|
||||||
|
UUID(as_uuid=True),
|
||||||
|
ForeignKey("agent_folders.id", ondelete="SET NULL"),
|
||||||
|
nullable=True,
|
||||||
|
)
|
||||||
config = Column(JSON, default={})
|
config = Column(JSON, default={})
|
||||||
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
created_at = Column(DateTime(timezone=True), server_default=func.now())
|
||||||
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
updated_at = Column(DateTime(timezone=True), onupdate=func.now())
|
||||||
@ -74,6 +97,9 @@ class Agent(Base):
|
|||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# Relação com a pasta
|
||||||
|
folder = relationship("AgentFolder", back_populates="agents")
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def agent_card_url_property(self) -> str:
|
def agent_card_url_property(self) -> str:
|
||||||
"""Virtual URL for the agent card"""
|
"""Virtual URL for the agent card"""
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
from pydantic import BaseModel, Field, validator
|
from pydantic import BaseModel, Field, validator, EmailStr, UUID4, ConfigDict
|
||||||
from typing import Optional, Dict, Any, Union, List
|
from typing import Optional, Dict, Any, Union, List
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from uuid import UUID
|
from uuid import UUID
|
||||||
@ -213,3 +213,26 @@ class Tool(ToolBase):
|
|||||||
|
|
||||||
class Config:
|
class Config:
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
||||||
|
|
||||||
|
# Schema para pasta de agentes
|
||||||
|
class AgentFolderBase(BaseModel):
|
||||||
|
name: str
|
||||||
|
description: Optional[str] = None
|
||||||
|
|
||||||
|
|
||||||
|
class AgentFolderCreate(AgentFolderBase):
|
||||||
|
client_id: UUID4
|
||||||
|
|
||||||
|
|
||||||
|
class AgentFolderUpdate(AgentFolderBase):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class AgentFolder(AgentFolderBase):
|
||||||
|
id: UUID4
|
||||||
|
client_id: UUID4
|
||||||
|
created_at: datetime
|
||||||
|
updated_at: Optional[datetime] = None
|
||||||
|
|
||||||
|
model_config = ConfigDict(from_attributes=True)
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
from sqlalchemy.orm import Session
|
from sqlalchemy.orm import Session
|
||||||
from sqlalchemy.exc import SQLAlchemyError
|
from sqlalchemy.exc import SQLAlchemyError
|
||||||
from fastapi import HTTPException, status
|
from fastapi import HTTPException, status
|
||||||
from src.models.models import Agent
|
from src.models.models import Agent, AgentFolder
|
||||||
from src.schemas.schemas import AgentCreate
|
from src.schemas.schemas import AgentCreate
|
||||||
from typing import List, Optional, Dict, Any, Union
|
from typing import List, Optional, Dict, Any, Union
|
||||||
from src.services.mcp_server_service import get_mcp_server
|
from src.services.mcp_server_service import get_mcp_server
|
||||||
@ -89,11 +89,16 @@ def get_agents_by_client(
|
|||||||
skip: int = 0,
|
skip: int = 0,
|
||||||
limit: int = 100,
|
limit: int = 100,
|
||||||
active_only: bool = True,
|
active_only: bool = True,
|
||||||
|
folder_id: Optional[uuid.UUID] = None,
|
||||||
) -> List[Agent]:
|
) -> List[Agent]:
|
||||||
"""Search for agents by client with pagination"""
|
"""Search for agents by client with pagination and optional folder filter"""
|
||||||
try:
|
try:
|
||||||
query = db.query(Agent).filter(Agent.client_id == client_id)
|
query = db.query(Agent).filter(Agent.client_id == client_id)
|
||||||
|
|
||||||
|
# Filtra por pasta se especificado
|
||||||
|
if folder_id is not None:
|
||||||
|
query = query.filter(Agent.folder_id == folder_id)
|
||||||
|
|
||||||
agents = query.offset(skip).limit(limit).all()
|
agents = query.offset(skip).limit(limit).all()
|
||||||
|
|
||||||
return agents
|
return agents
|
||||||
@ -604,3 +609,179 @@ def activate_agent(db: Session, agent_id: uuid.UUID) -> bool:
|
|||||||
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
detail="Error reactivating agent",
|
detail="Error reactivating agent",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
# Funções para pastas de agentes
|
||||||
|
def create_agent_folder(
|
||||||
|
db: Session, client_id: uuid.UUID, name: str, description: Optional[str] = None
|
||||||
|
) -> AgentFolder:
|
||||||
|
"""Cria uma nova pasta para organizar agentes"""
|
||||||
|
try:
|
||||||
|
folder = AgentFolder(client_id=client_id, name=name, description=description)
|
||||||
|
db.add(folder)
|
||||||
|
db.commit()
|
||||||
|
db.refresh(folder)
|
||||||
|
logger.info(f"Pasta de agentes criada com sucesso: {folder.id}")
|
||||||
|
return folder
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
db.rollback()
|
||||||
|
logger.error(f"Erro ao criar pasta de agentes: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail=f"Erro ao criar pasta de agentes: {str(e)}",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_agent_folder(db: Session, folder_id: uuid.UUID) -> Optional[AgentFolder]:
|
||||||
|
"""Busca uma pasta de agentes pelo ID"""
|
||||||
|
try:
|
||||||
|
return db.query(AgentFolder).filter(AgentFolder.id == folder_id).first()
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
logger.error(f"Erro ao buscar pasta de agentes {folder_id}: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Erro ao buscar pasta de agentes",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_agent_folders_by_client(
|
||||||
|
db: Session, client_id: uuid.UUID, skip: int = 0, limit: int = 100
|
||||||
|
) -> List[AgentFolder]:
|
||||||
|
"""Lista as pastas de agentes de um cliente"""
|
||||||
|
try:
|
||||||
|
return (
|
||||||
|
db.query(AgentFolder)
|
||||||
|
.filter(AgentFolder.client_id == client_id)
|
||||||
|
.offset(skip)
|
||||||
|
.limit(limit)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
logger.error(f"Erro ao listar pastas de agentes: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Erro ao listar pastas de agentes",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def update_agent_folder(
|
||||||
|
db: Session,
|
||||||
|
folder_id: uuid.UUID,
|
||||||
|
name: Optional[str] = None,
|
||||||
|
description: Optional[str] = None,
|
||||||
|
) -> Optional[AgentFolder]:
|
||||||
|
"""Atualiza uma pasta de agentes"""
|
||||||
|
try:
|
||||||
|
folder = get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if name is not None:
|
||||||
|
folder.name = name
|
||||||
|
if description is not None:
|
||||||
|
folder.description = description
|
||||||
|
|
||||||
|
db.commit()
|
||||||
|
db.refresh(folder)
|
||||||
|
logger.info(f"Pasta de agentes atualizada: {folder_id}")
|
||||||
|
return folder
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
db.rollback()
|
||||||
|
logger.error(f"Erro ao atualizar pasta de agentes {folder_id}: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Erro ao atualizar pasta de agentes",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def delete_agent_folder(db: Session, folder_id: uuid.UUID) -> bool:
|
||||||
|
"""Remove uma pasta de agentes e desvincula os agentes"""
|
||||||
|
try:
|
||||||
|
folder = get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Desvincula os agentes da pasta (não deleta os agentes)
|
||||||
|
agents = db.query(Agent).filter(Agent.folder_id == folder_id).all()
|
||||||
|
for agent in agents:
|
||||||
|
agent.folder_id = None
|
||||||
|
|
||||||
|
# Deleta a pasta
|
||||||
|
db.delete(folder)
|
||||||
|
db.commit()
|
||||||
|
logger.info(f"Pasta de agentes removida: {folder_id}")
|
||||||
|
return True
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
db.rollback()
|
||||||
|
logger.error(f"Erro ao remover pasta de agentes {folder_id}: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Erro ao remover pasta de agentes",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def assign_agent_to_folder(
|
||||||
|
db: Session, agent_id: uuid.UUID, folder_id: Optional[uuid.UUID]
|
||||||
|
) -> Optional[Agent]:
|
||||||
|
"""Atribui um agente a uma pasta (ou remove da pasta se folder_id for None)"""
|
||||||
|
try:
|
||||||
|
agent = get_agent(db, agent_id)
|
||||||
|
if not agent:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Se folder_id for None, remove o agente da pasta atual
|
||||||
|
if folder_id is None:
|
||||||
|
agent.folder_id = None
|
||||||
|
db.commit()
|
||||||
|
db.refresh(agent)
|
||||||
|
logger.info(f"Agente removido da pasta: {agent_id}")
|
||||||
|
return agent
|
||||||
|
|
||||||
|
# Verifica se a pasta existe
|
||||||
|
folder = get_agent_folder(db, folder_id)
|
||||||
|
if not folder:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_404_NOT_FOUND,
|
||||||
|
detail="Pasta não encontrada",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Verifica se a pasta pertence ao mesmo cliente do agente
|
||||||
|
if folder.client_id != agent.client_id:
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_400_BAD_REQUEST,
|
||||||
|
detail="A pasta deve pertencer ao mesmo cliente do agente",
|
||||||
|
)
|
||||||
|
|
||||||
|
# Atribui o agente à pasta
|
||||||
|
agent.folder_id = folder_id
|
||||||
|
db.commit()
|
||||||
|
db.refresh(agent)
|
||||||
|
logger.info(f"Agente atribuído à pasta {folder_id}: {agent_id}")
|
||||||
|
return agent
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
db.rollback()
|
||||||
|
logger.error(f"Erro ao atribuir agente à pasta: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Erro ao atribuir agente à pasta",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def get_agents_by_folder(
|
||||||
|
db: Session, folder_id: uuid.UUID, skip: int = 0, limit: int = 100
|
||||||
|
) -> List[Agent]:
|
||||||
|
"""Lista os agentes de uma pasta específica"""
|
||||||
|
try:
|
||||||
|
return (
|
||||||
|
db.query(Agent)
|
||||||
|
.filter(Agent.folder_id == folder_id)
|
||||||
|
.offset(skip)
|
||||||
|
.limit(limit)
|
||||||
|
.all()
|
||||||
|
)
|
||||||
|
except SQLAlchemyError as e:
|
||||||
|
logger.error(f"Erro ao listar agentes da pasta {folder_id}: {str(e)}")
|
||||||
|
raise HTTPException(
|
||||||
|
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
|
||||||
|
detail="Erro ao listar agentes da pasta",
|
||||||
|
)
|
||||||
|
Loading…
Reference in New Issue
Block a user