"""人格 API。""" from fastapi import APIRouter, Depends, Query, status from app.api.v1.deps import get_current_user from app.schemas.auth import CurrentUser from app.schemas.common import Page from app.schemas.personality import ( PersonalityProposalResponse, PersonalityResponse, ProposePersonalityUpdateRequest, ) from app.services.personality import ( approve_personality_proposal, get_current_personality, list_personality_proposals, list_personality_versions, propose_personality_update, reject_personality_proposal, rollback_personality, ) router = APIRouter(prefix="/personality", tags=["personality"]) @router.get("/current", response_model=PersonalityResponse) async def current_personality( current_user: CurrentUser = Depends(get_current_user), ) -> PersonalityResponse: return await get_current_personality(owner_scope=current_user.owner_scope) @router.get("/versions", response_model=Page[PersonalityResponse]) async def personality_versions( character_id: str | None = Query(default=None, description="人物 ID,省略取当前激活人物。"), page: int = Query(default=1, ge=1), page_size: int = Query(default=20, ge=1, le=100), current_user: CurrentUser = Depends(get_current_user), ) -> Page[PersonalityResponse]: return await list_personality_versions( character_id=character_id, page=page, page_size=page_size, owner_scope=current_user.owner_scope, ) @router.get("/proposals", response_model=Page[PersonalityProposalResponse]) async def personality_proposals( character_id: str | None = Query(default=None, description="人物 ID,省略取当前激活人物。"), status: str | None = Query( default=None, description="按状态过滤:pending / approved / rejected / applied" ), page: int = Query(default=1, ge=1), page_size: int = Query(default=20, ge=1, le=100), current_user: CurrentUser = Depends(get_current_user), ) -> Page[PersonalityProposalResponse]: """人格修改建议列表(待审审批墙数据源)。""" return await list_personality_proposals( character_id=character_id, status=status, page=page, page_size=page_size, owner_scope=current_user.owner_scope, ) # —— 人格修改建议与版本回滚(api-spec §11) —— @router.post( "/propose-update", response_model=PersonalityProposalResponse, status_code=status.HTTP_201_CREATED, ) async def propose_personality_update_endpoint( payload: ProposePersonalityUpdateRequest, current_user: CurrentUser = Depends(get_current_user), ) -> PersonalityProposalResponse: """提交人格修改建议;进入 pending 待审核,不直接写入人格版本。""" return await propose_personality_update( character_id=payload.character_id, fields=payload.fields, reason=payload.reason, owner_scope=current_user.owner_scope, ) @router.post( "/proposals/{proposal_id}/approve", response_model=PersonalityProposalResponse, ) async def approve_proposal( proposal_id: str, current_user: CurrentUser = Depends(get_current_user), ) -> PersonalityProposalResponse: """审核通过人格建议:派生新人格版本并切换人物当前指针。""" return await approve_personality_proposal(proposal_id, owner_scope=current_user.owner_scope) @router.post( "/proposals/{proposal_id}/reject", response_model=PersonalityProposalResponse, ) async def reject_proposal( proposal_id: str, current_user: CurrentUser = Depends(get_current_user), ) -> PersonalityProposalResponse: """驳回人格建议:标记 rejected,不生成新版本。""" return await reject_personality_proposal(proposal_id, owner_scope=current_user.owner_scope) @router.post("/versions/{version_id}/rollback", response_model=PersonalityResponse) async def rollback_personality_version( version_id: str, character_id: str | None = Query(default=None, description="人物 ID,省略取当前激活人物。"), current_user: CurrentUser = Depends(get_current_user), ) -> PersonalityResponse: """回滚到指定人格版本;被取代的旧版本标记 rolled_back_at。""" return await rollback_personality( character_id=character_id, version_id=version_id, owner_scope=current_user.owner_scope )