Luxx/luxx/routes/agent.py

309 lines
8.8 KiB
Python

"""Agent routes module"""
from typing import List, Optional
from fastapi import APIRouter
from pydantic import BaseModel
from luxx.agent.agent import agent_service, task_service
from luxx.agent.task import TaskStatus, StepStatus
from luxx.utils.helpers import success_response, error_response
router = APIRouter(prefix="/agent", tags=["Agent"])
# ==================== Request Models ====================
class CreateAgentRequest(BaseModel):
"""Create agent request"""
name: str
description: str = ""
instructions: str = ""
tools: List[str] = []
class UpdateAgentRequest(BaseModel):
"""Update agent request"""
name: Optional[str] = None
description: Optional[str] = None
instructions: Optional[str] = None
tools: Optional[List[str]] = None
class TaskStep(BaseModel):
"""Task step"""
name: str
description: str = ""
class CreateTaskRequest(BaseModel):
"""Create task request"""
name: str
goal: str
description: str = ""
steps: List[TaskStep] = []
class CreateSubtaskRequest(BaseModel):
"""Create subtask request"""
name: str
goal: str
description: str = ""
class UpdateTaskStatusRequest(BaseModel):
"""Update task status request"""
status: str
# ==================== Agent Endpoints ====================
@router.post("/agents", response_model=dict)
def create_agent(request: CreateAgentRequest):
"""Create a new agent instance"""
agent = agent_service.create_agent(
name=request.name,
description=request.description,
instructions=request.instructions,
tools=request.tools
)
return success_response(
data=agent.to_dict(),
message="Agent created successfully"
)
@router.get("/agents", response_model=dict)
def list_agents():
"""List all agents"""
agents = agent_service.list_agents()
return success_response(
data={
"agents": [a.to_dict() for a in agents],
"total": len(agents)
}
)
@router.get("/agents/{agent_id}", response_model=dict)
def get_agent(agent_id: str):
"""Get agent details"""
agent = agent_service.get_agent(agent_id)
if not agent:
return error_response("Agent not found", 404)
return success_response(data=agent.to_dict())
@router.put("/agents/{agent_id}", response_model=dict)
def update_agent(agent_id: str, request: UpdateAgentRequest):
"""Update agent configuration"""
agent = agent_service.update_agent(
agent_id=agent_id,
name=request.name,
description=request.description,
instructions=request.instructions,
tools=request.tools
)
if not agent:
return error_response("Agent not found", 404)
return success_response(
data=agent.to_dict(),
message="Agent updated successfully"
)
@router.delete("/agents/{agent_id}", response_model=dict)
def delete_agent(agent_id: str):
"""Delete agent instance"""
if agent_service.delete_agent(agent_id):
return success_response(message="Agent deleted successfully")
return error_response("Agent not found", 404)
# ==================== Task Endpoints ====================
@router.post("/tasks", response_model=dict)
def create_task(request: CreateTaskRequest):
"""Create a new task"""
task = task_service.create_task(
name=request.name,
goal=request.goal,
description=request.description,
steps=[s.dict() for s in request.steps] if request.steps else None
)
return success_response(
data=task.to_dict(),
message="Task created successfully"
)
@router.get("/agents/{agent_id}/tasks", response_model=dict)
def get_current_task(agent_id: str):
"""Get agent's current task"""
tasks = task_service.list_tasks(agent_id=agent_id)
if not tasks:
return success_response(
data={"task": None},
message="No task found"
)
return success_response(data={"task": tasks[0].to_dict()})
@router.get("/tasks", response_model=dict)
def list_tasks(agent_id: str = None):
"""List all tasks, optionally filtered by agent"""
tasks = task_service.list_tasks(agent_id=agent_id)
return success_response(
data={
"tasks": [t.to_dict() for t in tasks],
"total": len(tasks)
}
)
@router.get("/tasks/{task_id}", response_model=dict)
def get_task(task_id: str):
"""Get task details"""
task = task_service.get_task(task_id)
if not task:
return error_response("Task not found", 404)
return success_response(data=task.to_dict())
@router.put("/tasks/{task_id}/status", response_model=dict)
def update_task_status(task_id: str, request: UpdateTaskStatusRequest):
"""Update task status"""
try:
task_status = TaskStatus(request.status)
except ValueError:
valid_statuses = [s.value for s in TaskStatus]
return error_response(f"Invalid status: {request.status}. Valid: {valid_statuses}", 400)
task = task_service.update_task_status(task_id, task_status)
if not task:
return error_response("Task not found", 404)
return success_response(
data=task.to_dict(),
message="Task status updated"
)
@router.delete("/tasks/{task_id}", response_model=dict)
def delete_task(task_id: str):
"""Delete task"""
if task_service.delete_task(task_id):
return success_response(message="Task deleted successfully")
return error_response("Task not found", 404)
# ==================== Step Endpoints ====================
@router.post("/tasks/{task_id}/steps", response_model=dict)
def add_step(task_id: str, name: str, description: str = ""):
"""Add step to task"""
step = task_service.add_step(task_id, name, description)
if not step:
return error_response("Task not found", 404)
return success_response(
data=step.to_dict(),
message="Step added successfully"
)
@router.put("/tasks/{task_id}/steps/{step_id}/status", response_model=dict)
def update_step_status(task_id: str, step_id: str, status: str):
"""Update step status"""
try:
step_status = StepStatus(status)
except ValueError:
valid_statuses = [s.value for s in StepStatus]
return error_response(f"Invalid status: {status}. Valid: {valid_statuses}", 400)
task = task_service.get_task(task_id)
if not task:
return error_response("Task not found", 404)
for step in task.steps:
if step.id == step_id:
step.status = step_status
step.updated_at = __import__("datetime").datetime.now()
return success_response(
data=step.to_dict(),
message="Step status updated"
)
return error_response("Step not found", 404)
# ==================== Subtask Endpoints ====================
@router.post("/tasks/{task_id}/subtasks", response_model=dict)
def create_subtask(task_id: str, request: CreateSubtaskRequest):
"""Add subtask to parent task"""
subtask = task_service.add_subtask(
parent_task_id=task_id,
name=request.name,
goal=request.goal,
description=request.description
)
if not subtask:
return error_response("Parent task not found", 404)
return success_response(
data=subtask.to_dict(),
message="Subtask created successfully"
)
@router.get("/tasks/{task_id}/subtasks", response_model=dict)
def list_subtasks(task_id: str):
"""List subtasks of a task"""
task = task_service.get_task(task_id)
if not task:
return error_response("Task not found", 404)
return success_response(
data={
"subtasks": [t.to_dict() for t in task.subtasks],
"total": len(task.subtasks)
}
)
# ==================== Execution Endpoints ====================
@router.post("/agents/{agent_id}/execute", response_model=dict)
def execute_agent(agent_id: str, goal: str):
"""Trigger agent to execute a goal"""
agent = agent_service.get_agent(agent_id)
if not agent:
return error_response("Agent not found", 404)
if agent.status == "executing":
return error_response("Agent is already executing", 400)
# Update agent status
agent.status = "executing"
agent.updated_at = __import__("datetime").datetime.now()
# Create task
task = task_service.create_task(
agent_id=agent_id,
name=f"Task: {goal[:50]}...",
goal=goal,
description=f"Auto-generated task for goal: {goal}"
)
if not task:
return error_response("Failed to create task", 500)
return success_response(
data={
"agent_id": agent_id,
"task_id": task.id,
"status": "executing",
"message": "Agent execution started"
},
message="Execution started"
)