Files
JARVIS/backend/app/agents/tools/base.py

162 lines
4.5 KiB
Python
Raw Normal View History

"""工具基类 - 工具系统重构 Phase 6.1"""
from abc import ABC, abstractmethod
from typing import Any, Generic, TypeVar
from app.agents.tools.manifest import (
PermissionClass,
SideEffectScope,
ToolCategory,
ToolManifest,
)
T = TypeVar("T")
class BaseTool(ABC, Generic[T]):
"""工具基类
提供工具的标准接口和默认实现
所有自定义工具应继承此类
"""
def __init__(
self,
name: str,
description: str,
category: ToolCategory,
permission_class: PermissionClass,
side_effect_scope: SideEffectScope = SideEffectScope.NONE,
requires_confirmation: bool = False,
is_streaming: bool = False,
tags: list[str] | None = None,
):
self.name = name
self.description = description
self.category = category
self.permission_class = permission_class
self.side_effect_scope = side_effect_scope
self.requires_confirmation = requires_confirmation
self.is_streaming = is_streaming
self.tags = tags or []
def get_manifest(self) -> ToolManifest:
"""获取工具元数据
Returns:
工具元数据
"""
return ToolManifest(
name=self.name,
description=self.description,
category=self.category,
parameters=self.get_parameters(),
return_schema=self.get_return_schema(),
permission_class=self.permission_class,
side_effect_scope=self.side_effect_scope,
requires_confirmation=self.requires_confirmation,
is_streaming=self.is_streaming,
tags=self.tags,
)
@abstractmethod
def get_parameters(self) -> dict[str, Any]:
"""获取参数 SchemaJSON Schema 格式)
Returns:
参数 schema
"""
pass
@abstractmethod
def get_return_schema(self) -> dict[str, Any]:
"""获取返回值 Schema
Returns:
返回值 schema
"""
pass
@abstractmethod
async def execute(self, **kwargs) -> T:
"""执行工具
Args:
**kwargs: 工具参数
Returns:
执行结果
"""
pass
async def execute_safe(self, **kwargs) -> dict[str, Any]:
"""安全执行工具,捕获异常
Args:
**kwargs: 工具参数
Returns:
包含 success result/error 的字典
"""
try:
result = await self.execute(**kwargs)
return {"success": True, "result": result}
except Exception as e:
return {"success": False, "error": str(e)}
def __repr__(self) -> str:
return f"<{self.__class__.__name__}(name={self.name!r})>"
class ReadTool(BaseTool):
"""只读工具基类"""
def __init__(self, **kwargs):
kwargs.setdefault("category", ToolCategory.READ)
kwargs.setdefault("permission_class", PermissionClass.READ)
kwargs.setdefault("side_effect_scope", SideEffectScope.NONE)
super().__init__(**kwargs)
class WriteTool(BaseTool):
"""写入工具基类"""
def __init__(self, **kwargs):
kwargs.setdefault("category", ToolCategory.WRITE)
kwargs.setdefault("permission_class", PermissionClass.WRITE)
kwargs.setdefault("side_effect_scope", SideEffectScope.LOCAL_STATE)
super().__init__(**kwargs)
class DBWriteTool(BaseTool):
"""数据库写入工具基类"""
def __init__(self, **kwargs):
kwargs.setdefault("category", ToolCategory.DB_WRITE)
kwargs.setdefault("permission_class", PermissionClass.WRITE)
kwargs.setdefault("side_effect_scope", SideEffectScope.DB_WRITE)
kwargs.setdefault("requires_confirmation", True)
super().__init__(**kwargs)
class ExternalTool(BaseTool):
"""外部工具基类(执行外部命令等)"""
def __init__(self, **kwargs):
kwargs.setdefault("category", ToolCategory.EXTERNAL)
kwargs.setdefault("permission_class", PermissionClass.EXTERNAL)
kwargs.setdefault("side_effect_scope", SideEffectScope.NETWORK)
kwargs.setdefault("requires_confirmation", True)
super().__init__(**kwargs)
class NetworkTool(BaseTool):
"""网络工具基类"""
def __init__(self, **kwargs):
kwargs.setdefault("category", ToolCategory.NETWORK)
kwargs.setdefault("permission_class", PermissionClass.EXTERNAL)
kwargs.setdefault("side_effect_scope", SideEffectScope.NETWORK)
super().__init__(**kwargs)