集成新的Beaver后端服务到应用实例中,替换原有的nanobot实现。 主要变更包括: - 在Dockerfile和环境配置中添加Beaver相关路径和配置变量 - 更新工作目录结构从.nanobot到.beaver - 实现Beaver引擎加载器,支持配置文件加载和工具组装 - 添加内置工具如ListDirectoryTool、ReadFileTool、SearchFilesTool - 更新消息处理流程,支持通道适配器和网关模式 - 重构技能系统,支持显式工具提示和嵌入式检索 - 改进错误处理和生命周期管理 此变更使应用实例能够使用统一的Beaver后端进行AI代理运行时管理。
85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
"""Beaver 内置 skill_view tool。
|
||
|
||
这个工具对应 Hermes 风格的显式 skill loading path:
|
||
1. skill 正文默认不会长期塞进 system prompt
|
||
2. 模型若想查看某个 skill 的完整正文或支持文件,必须显式调用 `skill_view`
|
||
|
||
这样 skill 的按需展开路径会保持显式,而不是依赖 prompt 里长期堆目录信息。
|
||
"""
|
||
|
||
from __future__ import annotations
|
||
|
||
import json
|
||
from dataclasses import dataclass, field
|
||
from typing import Any
|
||
|
||
from beaver.skills.catalog.loader import SkillsLoader
|
||
|
||
SKILL_VIEW_TOOL_DESCRIPTION = (
|
||
"Load the full content of a skill or one of its supporting files. "
|
||
"Use this when you want to inspect a skill in detail."
|
||
)
|
||
|
||
SKILL_VIEW_TOOL_PARAMETERS: dict[str, Any] = {
|
||
"type": "object",
|
||
"properties": {
|
||
"name": {
|
||
"type": "string",
|
||
"description": "The skill name to inspect.",
|
||
},
|
||
"file_path": {
|
||
"type": "string",
|
||
"description": (
|
||
"Optional relative path to a supporting file inside the skill directory, "
|
||
"for example 'references/usage.md'. Omit to load SKILL.md itself."
|
||
),
|
||
},
|
||
},
|
||
"required": ["name"],
|
||
}
|
||
|
||
|
||
def skill_view(*, name: str, file_path: str | None = None, loader: SkillsLoader | None = None) -> str:
|
||
"""读取 skill 正文或支持文件,并返回结构化 JSON。"""
|
||
|
||
if loader is None:
|
||
return json.dumps({"success": False, "error": "Skills loader is not available."}, ensure_ascii=False)
|
||
|
||
try:
|
||
viewed = loader.view_skill(name, file_path=file_path)
|
||
except FileNotFoundError as exc:
|
||
return json.dumps({"success": False, "error": str(exc)}, ensure_ascii=False)
|
||
except ValueError as exc:
|
||
return json.dumps({"success": False, "error": str(exc)}, ensure_ascii=False)
|
||
|
||
if viewed is None:
|
||
return json.dumps({"success": False, "error": f"Unknown skill '{name}'."}, ensure_ascii=False)
|
||
|
||
display_name, content = viewed
|
||
support_files = loader.list_skill_supporting_files(name)
|
||
return json.dumps(
|
||
{
|
||
"success": True,
|
||
"name": name,
|
||
"file": display_name,
|
||
"content": content,
|
||
"supporting_files": support_files,
|
||
},
|
||
ensure_ascii=False,
|
||
)
|
||
|
||
|
||
@dataclass(slots=True)
|
||
class SkillViewTool:
|
||
"""面向 runtime 的 skill_view 工具封装。"""
|
||
|
||
loader: SkillsLoader
|
||
name: str = "skill_view"
|
||
description: str = SKILL_VIEW_TOOL_DESCRIPTION
|
||
toolset: str = "skills"
|
||
always_available: bool = True
|
||
parameters: dict[str, Any] = field(default_factory=lambda: dict(SKILL_VIEW_TOOL_PARAMETERS))
|
||
|
||
async def execute(self, **kwargs: Any) -> str:
|
||
return skill_view(loader=self.loader, **kwargs)
|