Initial commit: AI Video Assistant fullstack platform.
Add pipecat-based backend with WebRTC/WS voice routes, Next.js frontend, and Docker Compose orchestration. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
87
backend/routes/assistants.py
Normal file
87
backend/routes/assistants.py
Normal file
@@ -0,0 +1,87 @@
|
||||
"""助手 CRUD。前端「助手列表 / 创建 / 编辑」对接这里。
|
||||
|
||||
助手配置不含 key,所以无需打码。
|
||||
"""
|
||||
|
||||
import uuid
|
||||
|
||||
from db.models import Assistant
|
||||
from db.session import get_session
|
||||
from fastapi import APIRouter, Depends, HTTPException
|
||||
from schemas import AssistantOut, AssistantUpsert
|
||||
from sqlalchemy import select
|
||||
from sqlalchemy.ext.asyncio import AsyncSession
|
||||
|
||||
router = APIRouter(prefix="/api/assistants", tags=["assistants"])
|
||||
|
||||
|
||||
def _to_out(a: Assistant) -> AssistantOut:
|
||||
return AssistantOut(
|
||||
id=a.id,
|
||||
name=a.name,
|
||||
greeting=a.greeting,
|
||||
prompt=a.prompt,
|
||||
runtime_mode=a.runtime_mode, # type: ignore[arg-type]
|
||||
model=a.model,
|
||||
asr=a.asr,
|
||||
voice=a.voice,
|
||||
enable_interrupt=a.enable_interrupt,
|
||||
updated_at=a.updated_at.isoformat() if a.updated_at else None,
|
||||
)
|
||||
|
||||
|
||||
@router.get("", response_model=list[AssistantOut])
|
||||
async def list_assistants(session: AsyncSession = Depends(get_session)):
|
||||
rows = (
|
||||
await session.execute(select(Assistant).order_by(Assistant.updated_at.desc()))
|
||||
).scalars().all()
|
||||
return [_to_out(a) for a in rows]
|
||||
|
||||
|
||||
@router.post("", response_model=AssistantOut)
|
||||
async def create_assistant(
|
||||
body: AssistantUpsert, session: AsyncSession = Depends(get_session)
|
||||
):
|
||||
a = Assistant(id=f"asst_{uuid.uuid4().hex[:12]}", **body.model_dump())
|
||||
session.add(a)
|
||||
await session.commit()
|
||||
await session.refresh(a)
|
||||
return _to_out(a)
|
||||
|
||||
|
||||
@router.get("/{assistant_id}", response_model=AssistantOut)
|
||||
async def get_assistant(
|
||||
assistant_id: str, session: AsyncSession = Depends(get_session)
|
||||
):
|
||||
a = await session.get(Assistant, assistant_id)
|
||||
if not a:
|
||||
raise HTTPException(404, "助手不存在")
|
||||
return _to_out(a)
|
||||
|
||||
|
||||
@router.put("/{assistant_id}", response_model=AssistantOut)
|
||||
async def update_assistant(
|
||||
assistant_id: str,
|
||||
body: AssistantUpsert,
|
||||
session: AsyncSession = Depends(get_session),
|
||||
):
|
||||
a = await session.get(Assistant, assistant_id)
|
||||
if not a:
|
||||
raise HTTPException(404, "助手不存在")
|
||||
for k, v in body.model_dump().items():
|
||||
setattr(a, k, v)
|
||||
await session.commit()
|
||||
await session.refresh(a)
|
||||
return _to_out(a)
|
||||
|
||||
|
||||
@router.delete("/{assistant_id}")
|
||||
async def delete_assistant(
|
||||
assistant_id: str, session: AsyncSession = Depends(get_session)
|
||||
):
|
||||
a = await session.get(Assistant, assistant_id)
|
||||
if not a:
|
||||
raise HTTPException(404, "助手不存在")
|
||||
await session.delete(a)
|
||||
await session.commit()
|
||||
return {"ok": True}
|
||||
Reference in New Issue
Block a user