from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from typing import List, Optional import uuid from datetime import datetime from ..db import get_db from ..models import Assistant, Workflow from ..schemas import ( AssistantCreate, AssistantUpdate, AssistantOut, WorkflowCreate, WorkflowUpdate, WorkflowOut ) router = APIRouter() def assistant_to_dict(assistant: Assistant) -> dict: return { "id": assistant.id, "name": assistant.name, "callCount": assistant.call_count, "opener": assistant.opener or "", "prompt": assistant.prompt or "", "knowledgeBaseId": assistant.knowledge_base_id, "language": assistant.language, "voice": assistant.voice, "speed": assistant.speed, "hotwords": assistant.hotwords or [], "tools": assistant.tools or [], "interruptionSensitivity": assistant.interruption_sensitivity, "configMode": assistant.config_mode, "apiUrl": assistant.api_url, "apiKey": assistant.api_key, "llmModelId": assistant.llm_model_id, "asrModelId": assistant.asr_model_id, "embeddingModelId": assistant.embedding_model_id, "rerankModelId": assistant.rerank_model_id, "created_at": assistant.created_at, "updated_at": assistant.updated_at, } def _apply_assistant_update(assistant: Assistant, update_data: dict) -> None: field_map = { "knowledgeBaseId": "knowledge_base_id", "interruptionSensitivity": "interruption_sensitivity", "configMode": "config_mode", "apiUrl": "api_url", "apiKey": "api_key", "llmModelId": "llm_model_id", "asrModelId": "asr_model_id", "embeddingModelId": "embedding_model_id", "rerankModelId": "rerank_model_id", } for field, value in update_data.items(): setattr(assistant, field_map.get(field, field), value) # ============ Assistants ============ @router.get("/assistants") def list_assistants( page: int = 1, limit: int = 50, db: Session = Depends(get_db) ): """获取助手列表""" query = db.query(Assistant) total = query.count() assistants = query.order_by(Assistant.created_at.desc()) \ .offset((page-1)*limit).limit(limit).all() return { "total": total, "page": page, "limit": limit, "list": [assistant_to_dict(a) for a in assistants] } @router.get("/assistants/{id}", response_model=AssistantOut) def get_assistant(id: str, db: Session = Depends(get_db)): """获取单个助手详情""" assistant = db.query(Assistant).filter(Assistant.id == id).first() if not assistant: raise HTTPException(status_code=404, detail="Assistant not found") return assistant_to_dict(assistant) @router.post("/assistants", response_model=AssistantOut) def create_assistant(data: AssistantCreate, db: Session = Depends(get_db)): """创建新助手""" assistant = Assistant( id=str(uuid.uuid4())[:8], user_id=1, # 默认用户,后续添加认证 name=data.name, opener=data.opener, prompt=data.prompt, knowledge_base_id=data.knowledgeBaseId, language=data.language, voice=data.voice, speed=data.speed, hotwords=data.hotwords, tools=data.tools, interruption_sensitivity=data.interruptionSensitivity, config_mode=data.configMode, api_url=data.apiUrl, api_key=data.apiKey, llm_model_id=data.llmModelId, asr_model_id=data.asrModelId, embedding_model_id=data.embeddingModelId, rerank_model_id=data.rerankModelId, ) db.add(assistant) db.commit() db.refresh(assistant) return assistant_to_dict(assistant) @router.put("/assistants/{id}") def update_assistant(id: str, data: AssistantUpdate, db: Session = Depends(get_db)): """更新助手""" assistant = db.query(Assistant).filter(Assistant.id == id).first() if not assistant: raise HTTPException(status_code=404, detail="Assistant not found") update_data = data.model_dump(exclude_unset=True) _apply_assistant_update(assistant, update_data) assistant.updated_at = datetime.utcnow() db.commit() db.refresh(assistant) return assistant_to_dict(assistant) @router.delete("/assistants/{id}") def delete_assistant(id: str, db: Session = Depends(get_db)): """删除助手""" assistant = db.query(Assistant).filter(Assistant.id == id).first() if not assistant: raise HTTPException(status_code=404, detail="Assistant not found") db.delete(assistant) db.commit() return {"message": "Deleted successfully"} # ============ Workflows ============ @router.get("/workflows", response_model=List[WorkflowOut]) def list_workflows( page: int = 1, limit: int = 50, db: Session = Depends(get_db) ): """获取工作流列表""" query = db.query(Workflow) total = query.count() workflows = query.order_by(Workflow.created_at.desc()) \ .offset((page-1)*limit).limit(limit).all() return {"total": total, "page": page, "limit": limit, "list": workflows} @router.post("/workflows", response_model=WorkflowOut) def create_workflow(data: WorkflowCreate, db: Session = Depends(get_db)): """创建工作流""" workflow = Workflow( id=str(uuid.uuid4())[:8], user_id=1, name=data.name, node_count=data.nodeCount, created_at=data.createdAt or datetime.utcnow().isoformat(), updated_at=data.updatedAt or "", global_prompt=data.globalPrompt, nodes=data.nodes, edges=data.edges, ) db.add(workflow) db.commit() db.refresh(workflow) return workflow @router.get("/workflows/{id}", response_model=WorkflowOut) def get_workflow(id: str, db: Session = Depends(get_db)): """获取单个工作流""" workflow = db.query(Workflow).filter(Workflow.id == id).first() if not workflow: raise HTTPException(status_code=404, detail="Workflow not found") return workflow @router.put("/workflows/{id}", response_model=WorkflowOut) def update_workflow(id: str, data: WorkflowUpdate, db: Session = Depends(get_db)): """更新工作流""" workflow = db.query(Workflow).filter(Workflow.id == id).first() if not workflow: raise HTTPException(status_code=404, detail="Workflow not found") update_data = data.model_dump(exclude_unset=True) for field, value in update_data.items(): setattr(workflow, field, value) workflow.updated_at = datetime.utcnow().isoformat() db.commit() db.refresh(workflow) return workflow @router.delete("/workflows/{id}") def delete_workflow(id: str, db: Session = Depends(get_db)): """删除工作流""" workflow = db.query(Workflow).filter(Workflow.id == id).first() if not workflow: raise HTTPException(status_code=404, detail="Workflow not found") db.delete(workflow) db.commit() return {"message": "Deleted successfully"}