fix: #33 内置多模态工具现在在工具市场 /api/v1/tools 中可见

list_tools 端点合并内置工具(image_ocr/image_vision/speech_to_text/text_to_speech 等),
按 scope=public/all 时自动包含,无需额外种子到 DB。

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
renjianbo
2026-05-06 22:13:41 +08:00
parent 9054f42cda
commit 5b5eb84dfb
9 changed files with 1095 additions and 7 deletions

View File

@@ -96,6 +96,44 @@ def _tool_to_dict(tool: Tool) -> dict:
# ─── 工具市场浏览 ──────────────────────────────────────────────
def _builtin_schema_to_tool_dict(schema: dict) -> dict:
"""将 tool_registry 中的 schema 转为与 DB Tool 一致的字典格式。"""
func = schema.get("function", schema)
name = func.get("name", "")
desc = func.get("description", "")
params = func.get("parameters", {})
# 根据工具名自动归类
cat = "系统工具"
if name in ("image_ocr", "image_vision"):
cat = "多模态"
elif name in ("speech_to_text", "text_to_speech"):
cat = "多模态"
elif name.startswith("file_"):
cat = "文件操作"
elif name.startswith("http") or name.startswith("url"):
cat = "网络请求"
elif name.startswith("database") or name.startswith("sql"):
cat = "数据库"
elif name.startswith("agent_"):
cat = "AI Agent"
elif name in ("web_search", "send_email", "browser_use"):
cat = "网络请求"
return {
"id": f"builtin_{name}",
"name": name,
"description": desc,
"category": cat,
"function_schema": schema,
"implementation_type": "builtin",
"implementation_config": None,
"is_public": True,
"use_count": 0,
"user_id": None,
"created_at": "",
"updated_at": "",
}
@router.get("", response_model=List[ToolResponse])
async def list_tools(
category: Optional[str] = Query(None, description="按分类筛选"),
@@ -104,7 +142,7 @@ async def list_tools(
db: Session = Depends(get_db),
current_user: Optional[User] = Depends(get_current_user),
):
"""浏览工具市场。"""
"""浏览工具市场(含内置工具 + 数据库工具)"""
query = db.query(Tool)
if scope == "public":
@@ -122,7 +160,23 @@ async def list_tools(
)
tools = query.order_by(Tool.use_count.desc(), Tool.created_at.desc()).all()
return [_tool_to_dict(t) for t in tools]
result = [_tool_to_dict(t) for t in tools]
db_names = {t["name"] for t in result}
# 合并内置工具(未在 DB 中覆盖的)
if scope != "mine":
for schema in tool_registry.get_all_tool_schemas():
entry = _builtin_schema_to_tool_dict(schema)
if entry["name"] not in db_names:
if category and entry["category"] != category:
continue
if search:
kw = search.lower()
if kw not in entry["name"].lower() and kw not in entry["description"].lower():
continue
result.append(entry)
return result
@router.get("/categories", response_model=List[str])
@@ -131,7 +185,7 @@ async def list_categories(db: Session = Depends(get_db)):
rows = db.query(Tool.category).filter(Tool.category.isnot(None)).distinct().all()
cats = sorted(set(r[0] for r in rows if r[0]))
# 加上常用分类
defaults = ["数据处理", "网络请求", "文件操作", "AI服务", "数据库", "通知", "自定义"]
defaults = ["数据处理", "网络请求", "文件操作", "AI服务", "数据库", "通知", "自定义", "多模态", "系统工具"]
for d in defaults:
if d not in cats:
cats.append(d)