letsbe-orchestrator/app/routes/files.py

95 lines
2.6 KiB
Python
Raw Normal View History

"""File management endpoints for creating FILE_INSPECT tasks."""
import uuid
from fastapi import APIRouter, HTTPException, status
from sqlalchemy import select
from app.db import AsyncSessionDep
from app.models.agent import Agent
from app.models.task import Task, TaskStatus
from app.models.tenant import Tenant
from app.schemas.file import FileInspectRequest
from app.schemas.task import TaskResponse
router = APIRouter(prefix="/agents/{agent_id}/files", tags=["File Management"])
# --- Helper functions ---
async def get_tenant_by_id(db: AsyncSessionDep, tenant_id: uuid.UUID) -> Tenant | None:
"""Retrieve a tenant by ID."""
result = await db.execute(select(Tenant).where(Tenant.id == tenant_id))
return result.scalar_one_or_none()
async def get_agent_by_id(db: AsyncSessionDep, agent_id: uuid.UUID) -> Agent | None:
"""Retrieve an agent by ID."""
result = await db.execute(select(Agent).where(Agent.id == agent_id))
return result.scalar_one_or_none()
# --- Route handlers ---
@router.post(
"/inspect",
response_model=TaskResponse,
status_code=status.HTTP_201_CREATED,
)
async def inspect_file(
agent_id: uuid.UUID,
request: FileInspectRequest,
db: AsyncSessionDep,
) -> Task:
"""
Create a FILE_INSPECT task to read file contents.
The SysAdmin Agent will execute this task and return the file
contents (up to max_bytes) in the task result.
## Request Body
- **tenant_id**: UUID of the tenant
- **path**: Absolute path to the file to inspect
- **max_bytes**: Optional max bytes to read (default 4096, max 1MB)
## Response
Returns the created Task with type="FILE_INSPECT" and status="pending".
"""
# Validate tenant exists
tenant = await get_tenant_by_id(db, request.tenant_id)
if tenant is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Tenant {request.tenant_id} not found",
)
# Validate agent exists
agent = await get_agent_by_id(db, agent_id)
if agent is None:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Agent {agent_id} not found",
)
# Build payload
payload: dict = {"path": request.path}
if request.max_bytes is not None:
payload["max_bytes"] = request.max_bytes
# Create the task
task = Task(
tenant_id=request.tenant_id,
agent_id=agent_id,
type="FILE_INSPECT",
payload=payload,
status=TaskStatus.PENDING.value,
)
db.add(task)
await db.commit()
await db.refresh(task)
return task