Update tool panel

This commit is contained in:
Xin Wang
2026-02-09 00:14:11 +08:00
parent 0fc56e2685
commit 77b186dceb
7 changed files with 537 additions and 120 deletions

View File

@@ -1,12 +1,14 @@
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.orm import Session
from typing import Optional, Dict, Any
from typing import Optional, Dict, Any, List
import time
import uuid
import httpx
from datetime import datetime
from ..db import get_db
from ..models import LLMModel, ASRModel
from ..models import LLMModel, ASRModel, ToolResource
from ..schemas import ToolResourceCreate, ToolResourceOut, ToolResourceUpdate
router = APIRouter(prefix="/tools", tags=["Tools & Autotest"])
@@ -83,6 +85,36 @@ TOOL_REGISTRY = {
},
}
TOOL_CATEGORY_MAP = {
"search": "query",
"weather": "query",
"translate": "query",
"knowledge": "query",
"calculator": "system",
"code_interpreter": "system",
}
TOOL_ICON_MAP = {
"search": "Globe",
"weather": "CloudSun",
"translate": "Globe",
"knowledge": "Box",
"calculator": "Terminal",
"code_interpreter": "Terminal",
}
def _builtin_tool_to_resource(tool_id: str, payload: Dict[str, Any]) -> Dict[str, Any]:
return {
"id": tool_id,
"name": payload.get("name", tool_id),
"description": payload.get("description", ""),
"category": TOOL_CATEGORY_MAP.get(tool_id, "system"),
"icon": TOOL_ICON_MAP.get(tool_id, "Wrench"),
"enabled": True,
"is_system": True,
}
@router.get("/list")
def list_available_tools():
@@ -98,6 +130,122 @@ def get_tool_detail(tool_id: str):
return TOOL_REGISTRY[tool_id]
# ============ Tool Resource CRUD ============
@router.get("/resources")
def list_tool_resources(
category: Optional[str] = None,
enabled: Optional[bool] = None,
include_system: bool = True,
page: int = 1,
limit: int = 100,
db: Session = Depends(get_db),
):
"""获取工具资源列表(内置工具 + 自定义工具)。"""
merged: List[Dict[str, Any]] = []
if include_system:
for tool_id, payload in TOOL_REGISTRY.items():
merged.append(_builtin_tool_to_resource(tool_id, payload))
query = db.query(ToolResource)
if category:
query = query.filter(ToolResource.category == category)
if enabled is not None:
query = query.filter(ToolResource.enabled == enabled)
custom_tools = query.order_by(ToolResource.created_at.desc()).all()
for item in custom_tools:
merged.append({
"id": item.id,
"name": item.name,
"description": item.description,
"category": item.category,
"icon": item.icon,
"enabled": item.enabled,
"is_system": item.is_system,
})
if category:
merged = [item for item in merged if item.get("category") == category]
if enabled is not None:
merged = [item for item in merged if item.get("enabled") == enabled]
total = len(merged)
start = max(page - 1, 0) * limit
end = start + limit
return {"total": total, "page": page, "limit": limit, "list": merged[start:end]}
@router.get("/resources/{id}", response_model=ToolResourceOut)
def get_tool_resource(id: str, db: Session = Depends(get_db)):
"""获取单个工具资源详情。"""
if id in TOOL_REGISTRY:
tool = _builtin_tool_to_resource(id, TOOL_REGISTRY[id])
return ToolResourceOut(**tool)
item = db.query(ToolResource).filter(ToolResource.id == id).first()
if not item:
raise HTTPException(status_code=404, detail="Tool resource not found")
return item
@router.post("/resources", response_model=ToolResourceOut)
def create_tool_resource(data: ToolResourceCreate, db: Session = Depends(get_db)):
"""创建自定义工具资源。"""
candidate_id = (data.id or "").strip()
if candidate_id and candidate_id in TOOL_REGISTRY:
raise HTTPException(status_code=400, detail="Tool ID conflicts with system tool")
item = ToolResource(
id=candidate_id or f"tool_{str(uuid.uuid4())[:8]}",
user_id=1,
name=data.name,
description=data.description,
category=data.category,
icon=data.icon,
enabled=data.enabled,
is_system=False,
)
db.add(item)
db.commit()
db.refresh(item)
return item
@router.put("/resources/{id}", response_model=ToolResourceOut)
def update_tool_resource(id: str, data: ToolResourceUpdate, db: Session = Depends(get_db)):
"""更新自定义工具资源。"""
if id in TOOL_REGISTRY:
raise HTTPException(status_code=400, detail="System tools are read-only")
item = db.query(ToolResource).filter(ToolResource.id == id).first()
if not item:
raise HTTPException(status_code=404, detail="Tool resource not found")
update_data = data.model_dump(exclude_unset=True)
for field, value in update_data.items():
setattr(item, field, value)
item.updated_at = datetime.utcnow()
db.commit()
db.refresh(item)
return item
@router.delete("/resources/{id}")
def delete_tool_resource(id: str, db: Session = Depends(get_db)):
"""删除自定义工具资源。"""
if id in TOOL_REGISTRY:
raise HTTPException(status_code=400, detail="System tools cannot be deleted")
item = db.query(ToolResource).filter(ToolResource.id == id).first()
if not item:
raise HTTPException(status_code=404, detail="Tool resource not found")
db.delete(item)
db.commit()
return {"message": "Deleted successfully"}
# ============ Autotest ============
class AutotestResult:
"""自动测试结果"""