Files
beaver_project/app-instance/backend/beaver/tools/builtins/skill_view.py
steven_li 5ba5c7e4c1 feat(app-instance): 集成Beaver后端并更新配置管理
集成新的Beaver后端服务到应用实例中,替换原有的nanobot实现。

主要变更包括:
- 在Dockerfile和环境配置中添加Beaver相关路径和配置变量
- 更新工作目录结构从.nanobot到.beaver
- 实现Beaver引擎加载器,支持配置文件加载和工具组装
- 添加内置工具如ListDirectoryTool、ReadFileTool、SearchFilesTool
- 更新消息处理流程,支持通道适配器和网关模式
- 重构技能系统,支持显式工具提示和嵌入式检索
- 改进错误处理和生命周期管理

此变更使应用实例能够使用统一的Beaver后端进行AI代理运行时管理。
2026-04-27 17:37:40 +08:00

85 lines
2.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""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)