from fastapi import APIRouter, Depends, HTTPException, Query from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.database import get_db from app.models.skill import Skill from app.models.user import User from app.routers.auth import get_current_user from app.schemas.skill import SkillCreate, SkillOut, SkillUpdate from app.services.admin_bootstrap_service import ensure_builtin_skills from app.services.skill_service import SkillService router = APIRouter(prefix="/api/skills", tags=["Skill"]) @router.post("", response_model=SkillOut, status_code=201) async def create_skill( data: SkillCreate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): skill = Skill( name=data.name, description=data.description, instructions=data.instructions, agent_type=data.agent_type, tools=data.tools, required_context=data.required_context, output_format=data.output_format, visibility=data.visibility, team_id=data.team_id, is_active=data.is_active, owner_id=current_user.id, ) db.add(skill) await db.commit() await db.refresh(skill) return skill @router.get("", response_model=list[SkillOut]) async def list_skills( agent_type: str | None = Query(default=None), visibility: str | None = Query(default=None), current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): service = SkillService(db) return await service.list_for_user(current_user.id, agent_type=agent_type, visibility=visibility) @router.post("/bootstrap-builtin", response_model=list[SkillOut]) async def bootstrap_builtin_skills( current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): await ensure_builtin_skills(db, preferred_owner_id=current_user.id) service = SkillService(db) return await service.list_for_user(current_user.id) @router.get("/{skill_id}", response_model=SkillOut) async def get_skill( skill_id: str, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(Skill).where(Skill.id == skill_id)) skill = result.scalar_one_or_none() if not skill: raise HTTPException(status_code=404, detail="Skill not found") return skill @router.put("/{skill_id}", response_model=SkillOut) async def update_skill( skill_id: str, data: SkillUpdate, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(Skill).where(Skill.id == skill_id)) skill = result.scalar_one_or_none() if not skill: raise HTTPException(status_code=404, detail="Skill not found") if data.name is not None: skill.name = data.name if data.description is not None: skill.description = data.description if data.instructions is not None: skill.instructions = data.instructions if data.agent_type is not None: skill.agent_type = data.agent_type if data.tools is not None: skill.tools = data.tools if data.required_context is not None: skill.required_context = data.required_context if data.output_format is not None: skill.output_format = data.output_format if data.visibility is not None: skill.visibility = data.visibility if data.team_id is not None: skill.team_id = data.team_id if data.is_active is not None: skill.is_active = data.is_active await db.commit() await db.refresh(skill) return skill @router.delete("/{skill_id}", status_code=204) async def delete_skill( skill_id: str, current_user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): result = await db.execute(select(Skill).where(Skill.id == skill_id)) skill = result.scalar_one_or_none() if not skill: raise HTTPException(status_code=404, detail="Skill not found") await db.delete(skill) await db.commit()