from uuid import UUID from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.auth.dependencies import get_current_active_user from app.db import get_db_session from app.models.project import Project from app.models.tool_instance import ToolInstance from app.models.user import User from app.schemas.tool_instance import ToolInstanceCreate, ToolInstanceRead, ToolInstanceUpdate router = APIRouter(tags=["tool-instances"]) async def _get_project_for_user( project_id: UUID, user: User, session: AsyncSession ) -> Project: project = await session.get(Project, project_id) if not project or project.owner_id != user.id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Project not found") return project @router.post("/projects/{project_id}/tool-instances", response_model=ToolInstanceRead, status_code=status.HTTP_201_CREATED) # noqa: E501 async def create_tool_instance( project_id: UUID, ti_in: ToolInstanceCreate, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> ToolInstance: await _get_project_for_user(project_id, current_user, session) ti = ToolInstance(**ti_in.model_dump(), project_id=project_id) session.add(ti) await session.commit() await session.refresh(ti) return ti @router.get("/projects/{project_id}/tool-instances", response_model=list[ToolInstanceRead]) async def list_tool_instances( project_id: UUID, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> list[ToolInstance]: await _get_project_for_user(project_id, current_user, session) result = await session.execute( select(ToolInstance).where(ToolInstance.project_id == project_id) ) return list(result.scalars().all()) @router.get("/projects/{project_id}/tool-instances/{instance_id}", response_model=ToolInstanceRead) async def get_tool_instance( project_id: UUID, instance_id: UUID, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> ToolInstance: await _get_project_for_user(project_id, current_user, session) ti = await session.get(ToolInstance, instance_id) if not ti or ti.project_id != project_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tool instance not found") return ti @router.put("/projects/{project_id}/tool-instances/{instance_id}", response_model=ToolInstanceRead) async def update_tool_instance( project_id: UUID, instance_id: UUID, ti_in: ToolInstanceUpdate, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> ToolInstance: await _get_project_for_user(project_id, current_user, session) ti = await session.get(ToolInstance, instance_id) if not ti or ti.project_id != project_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tool instance not found") update_data = ti_in.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(ti, field, value) await session.commit() await session.refresh(ti) return ti @router.delete("/projects/{project_id}/tool-instances/{instance_id}", status_code=status.HTTP_204_NO_CONTENT) # noqa: E501 async def delete_tool_instance( project_id: UUID, instance_id: UUID, current_user: User = Depends(get_current_active_user), session: AsyncSession = Depends(get_db_session), ) -> None: await _get_project_for_user(project_id, current_user, session) ti = await session.get(ToolInstance, instance_id) if not ti or ti.project_id != project_id: raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail="Tool instance not found") await session.delete(ti) await session.commit()