from fastapi import APIRouter, Depends, HTTPException from sqlalchemy import select from sqlalchemy.ext.asyncio import AsyncSession from app.models.database import get_session from app.models.orm import Character from app.models.schemas import ( CharacterResponse, CharacterCreate, CharacterStatus, CharacterSpeakRequest, SoulUpdateRequest, CharacterGenerateRequest, ) from app.services.character_generator import character_generator from app.services.hermes_client import hermes_client from app.services.soul_generator import soul_generator router = APIRouter() @router.get("", response_model=list[CharacterResponse]) async def list_characters(session: AsyncSession = Depends(get_session)): result = await session.execute(select(Character)) return list(result.scalars().all()) @router.get("/{character_id}", response_model=CharacterResponse) async def get_character(character_id: str, session: AsyncSession = Depends(get_session)): result = await session.execute(select(Character).where(Character.id == character_id)) character = result.scalars().first() if not character: raise HTTPException(status_code=404, detail="Character not found") return character @router.put("/{character_id}/soul") async def update_character_soul( character_id: str, req: SoulUpdateRequest, session: AsyncSession = Depends(get_session), ): result = await session.execute(select(Character).where(Character.id == character_id)) character = result.scalars().first() if not character: raise HTTPException(status_code=404, detail="Character not found") previous = character.hermes_profile character.soul_md = req.soul_md character.knowledge_base = req.knowledge_base await hermes_client.create_profile(previous, req.soul_md) await session.commit() await session.refresh(character) return {"ok": True, "character_id": character_id} @router.post("/{character_id}/speak") async def character_speak( character_id: str, req: CharacterSpeakRequest, session: AsyncSession = Depends(get_session), ): result = await session.execute(select(Character).where(Character.id == character_id)) character = result.scalars().first() if not character: raise HTTPException(status_code=404, detail="Character not found") prompt = req.prompt or "根据当前剧本进度自然发言" response = await hermes_client.chat(character.hermes_profile, prompt) return { "character_id": character_id, "character_name": character.name, "response": response, } @router.post("/{character_id}/profile") async def create_character_profile( character_id: str, session: AsyncSession = Depends(get_session), ): result = await session.execute(select(Character).where(Character.id == character_id)) character = result.scalars().first() if not character: raise HTTPException(status_code=404, detail="Character not found") success = await character_generator.create_profile(character) await session.commit() return {"ok": success, "character_id": character_id} @router.post("/generate", response_model=list[CharacterResponse]) async def generate_characters( req: CharacterGenerateRequest, session: AsyncSession = Depends(get_session), ): result = await session.execute(select(Character).where(Character.script_id == req.script_id)) existing = list(result.scalars().all()) for char in existing: await session.delete(char) await session.commit() character_data = [{"name": name} for name in req.character_names] characters = await character_generator.generate_characters( session, req.script_id, character_data ) return characters @router.post("/{character_id}/status") async def update_character_status( character_id: str, status: CharacterStatus, session: AsyncSession = Depends(get_session), ): result = await session.execute(select(Character).where(Character.id == character_id)) character = result.scalars().first() if not character: raise HTTPException(status_code=404, detail="Character not found") character.status = status await session.commit() await session.refresh(character) return {"ok": True, "status": character.status.value} @router.delete("/{character_id}") async def delete_character(character_id: str, session: AsyncSession = Depends(get_session)): result = await session.execute(select(Character).where(Character.id == character_id)) character = result.scalars().first() if not character: raise HTTPException(status_code=404, detail="Character not found") await character_generator.delete_profile(character) await session.delete(character) await session.commit() return {"ok": True}