知你客服

This commit is contained in:
rjb
2026-03-06 22:31:41 +08:00
parent 171a6edf94
commit 9d3198f6bc
31 changed files with 6579 additions and 80 deletions

View File

@@ -53,7 +53,7 @@ class AgentResponse(BaseModel):
workflow_config: Dict[str, Any]
version: int
status: str
user_id: str
user_id: Optional[str] # 允许为None
created_at: datetime
updated_at: datetime
@@ -116,7 +116,23 @@ async def get_agents(
# 排序和分页
agents = query.order_by(Agent.created_at.desc()).offset(skip).limit(limit).all()
return agents
# 转换为响应格式,确保user_id和日期时间字段正确处理
result = []
for agent in agents:
result.append({
"id": agent.id,
"name": agent.name,
"description": agent.description,
"workflow_config": agent.workflow_config,
"version": agent.version,
"status": agent.status,
"user_id": agent.user_id if agent.user_id else None,
"created_at": agent.created_at if agent.created_at else datetime.now(),
"updated_at": agent.updated_at if agent.updated_at else datetime.now()
})
return result
@router.post("", response_model=AgentResponse, status_code=status.HTTP_201_CREATED)

View File

@@ -4,7 +4,8 @@
from fastapi import APIRouter, Depends, HTTPException, status
from fastapi.security import OAuth2PasswordBearer, OAuth2PasswordRequestForm
from sqlalchemy.orm import Session
from pydantic import BaseModel, EmailStr
from pydantic import BaseModel, field_validator
import re
import logging
from app.core.database import get_db
from app.core.security import verify_password, get_password_hash, create_access_token
@@ -31,9 +32,16 @@ oauth2_scheme = OAuth2PasswordBearer(tokenUrl="/api/v1/auth/login")
class UserCreate(BaseModel):
"""用户创建模型"""
username: str
email: EmailStr
email: str
password: str
@field_validator("email")
@classmethod
def email_format(cls, v: str) -> str:
if not v or not re.match(r"^[^@]+@[^@]+\.[^@]+$", v):
raise ValueError("邮箱格式无效")
return v.lower()
class UserResponse(BaseModel):
"""用户响应模型"""

View File

@@ -63,7 +63,26 @@ async def list_tools(
)
tools = query.order_by(Tool.use_count.desc(), Tool.created_at.desc()).all()
return tools
# 转换为响应格式,确保日期时间字段转换为字符串
result = []
for tool in tools:
result.append({
"id": tool.id,
"name": tool.name,
"description": tool.description,
"category": tool.category,
"function_schema": tool.function_schema,
"implementation_type": tool.implementation_type,
"implementation_config": tool.implementation_config,
"is_public": tool.is_public,
"use_count": tool.use_count,
"user_id": tool.user_id,
"created_at": tool.created_at.isoformat() if tool.created_at else "",
"updated_at": tool.updated_at.isoformat() if tool.updated_at else ""
})
return result
@router.get("/builtin")
@@ -82,7 +101,22 @@ async def get_tool(
tool = db.query(Tool).filter(Tool.id == tool_id).first()
if not tool:
raise HTTPException(status_code=404, detail="工具不存在")
return tool
# 转换为响应格式,确保日期时间字段转换为字符串
return {
"id": tool.id,
"name": tool.name,
"description": tool.description,
"category": tool.category,
"function_schema": tool.function_schema,
"implementation_type": tool.implementation_type,
"implementation_config": tool.implementation_config,
"is_public": tool.is_public,
"use_count": tool.use_count,
"user_id": tool.user_id,
"created_at": tool.created_at.isoformat() if tool.created_at else "",
"updated_at": tool.updated_at.isoformat() if tool.updated_at else ""
}
@router.post("", response_model=ToolResponse, status_code=201)
@@ -112,7 +146,21 @@ async def create_tool(
db.commit()
db.refresh(tool)
return tool
# 转换为响应格式,确保日期时间字段转换为字符串
return {
"id": tool.id,
"name": tool.name,
"description": tool.description,
"category": tool.category,
"function_schema": tool.function_schema,
"implementation_type": tool.implementation_type,
"implementation_config": tool.implementation_config,
"is_public": tool.is_public,
"use_count": tool.use_count,
"user_id": tool.user_id,
"created_at": tool.created_at.isoformat() if tool.created_at else "",
"updated_at": tool.updated_at.isoformat() if tool.updated_at else ""
}
@router.put("/{tool_id}", response_model=ToolResponse)
@@ -148,7 +196,21 @@ async def update_tool(
db.commit()
db.refresh(tool)
return tool
# 转换为响应格式,确保日期时间字段转换为字符串
return {
"id": tool.id,
"name": tool.name,
"description": tool.description,
"category": tool.category,
"function_schema": tool.function_schema,
"implementation_type": tool.implementation_type,
"implementation_config": tool.implementation_config,
"is_public": tool.is_public,
"use_count": tool.use_count,
"user_id": tool.user_id,
"created_at": tool.created_at.isoformat() if tool.created_at else "",
"updated_at": tool.updated_at.isoformat() if tool.updated_at else ""
}
@router.delete("/{tool_id}", status_code=200)

View File

@@ -22,6 +22,22 @@ logger = logging.getLogger(__name__)
router = APIRouter(prefix="/api/v1/workflows", tags=["workflows"])
def _workflow_to_response(workflow: Workflow) -> dict:
"""将Workflow对象转换为响应格式"""
return {
"id": workflow.id,
"name": workflow.name,
"description": workflow.description,
"nodes": workflow.nodes,
"edges": workflow.edges,
"version": workflow.version,
"status": workflow.status,
"user_id": workflow.user_id if workflow.user_id else None,
"created_at": workflow.created_at if workflow.created_at else datetime.now(),
"updated_at": workflow.updated_at if workflow.updated_at else datetime.now()
}
class WorkflowCreate(BaseModel):
"""工作流创建模型"""
name: str
@@ -48,7 +64,7 @@ class WorkflowResponse(BaseModel):
edges: List[Dict[str, Any]]
version: int
status: str
user_id: str
user_id: Optional[str] # 允许为None
created_at: datetime
updated_at: datetime
@@ -117,7 +133,7 @@ async def create_workflow_from_template(
db.add(workflow)
db.commit()
db.refresh(workflow)
return workflow
return _workflow_to_response(workflow)
@router.get("", response_model=List[WorkflowResponse])
@@ -187,7 +203,9 @@ async def get_workflows(
query = query.order_by(order_by.desc())
workflows = query.offset(skip).limit(limit).all()
return workflows
# 转换为响应格式,确保user_id和日期时间字段正确处理
return [_workflow_to_response(w) for w in workflows]
@router.post("", response_model=WorkflowResponse, status_code=status.HTTP_201_CREATED)
@@ -216,7 +234,7 @@ async def create_workflow(
db.add(workflow)
db.commit()
db.refresh(workflow)
return workflow
return _workflow_to_response(workflow)
@router.get("/{workflow_id}", response_model=WorkflowResponse)
@@ -235,7 +253,7 @@ async def get_workflow(
if not check_workflow_permission(db, current_user, workflow, "read"):
raise HTTPException(status_code=403, detail="无权访问此工作流")
return workflow
return _workflow_to_response(workflow)
@router.put("/{workflow_id}", response_model=WorkflowResponse)
@@ -299,7 +317,7 @@ async def update_workflow(
workflow.version += 1
db.commit()
db.refresh(workflow)
return workflow
return _workflow_to_response(workflow)
@router.delete("/{workflow_id}", status_code=status.HTTP_204_NO_CONTENT)
@@ -395,7 +413,7 @@ async def import_workflow(
db.add(workflow)
db.commit()
db.refresh(workflow)
return workflow
return _workflow_to_response(workflow)
@router.post("/{workflow_id}/execute")
@@ -631,4 +649,4 @@ async def rollback_workflow_version(
logger.info(f"工作流 {workflow_id} 已回滚到版本 {version}")
return workflow
return _workflow_to_response(workflow)