feat: 将项目从nano重命名为beaver并更新相关配置

- 将所有环境变量前缀从NANO_改为BEAVER_
- 更新README.md文档内容,包括项目介绍、组件说明和快速开始指南
- 修改.gitignore文件,添加auth-portal运行时路径排除规则
- 更新app-instance镜像标签从nano/app-instance改为beaver/app-instance
- 增强技能安全检查器,支持工具前缀白名单功能
- 添加技能草稿重新检查安全性API端点
- 扩展证据选择器,收集工具调用名称用于技能学习
- 改进技能合成器,基于实际调用的工具生成工具提示
- 优化路由超时处理机制,增加重试逻辑
- 更新后端架构文档,添加可视化入口和基础概念说明
- 实现在WebSocket消息中传递工具迭代次数信息
This commit is contained in:
2026-05-20 18:01:06 +08:00
parent 3b0af173cc
commit 9d6cde2d23
63 changed files with 4894 additions and 1596 deletions

View File

@ -15,7 +15,12 @@ from beaver.skills.reviews import ReviewService
from beaver.skills.specs import SkillSpecStore
def _pipeline(tmp_path: Path, *, allowed_tools: set[str] | None = None) -> SkillLearningPipelineService:
def _pipeline(
tmp_path: Path,
*,
allowed_tools: set[str] | None = None,
allowed_prefixes: set[str] | None = None,
) -> SkillLearningPipelineService:
spec_store = SkillSpecStore(tmp_path)
run_store = RunMemoryStore(tmp_path / "memory" / "runs")
learning_store = SkillLearningStore(tmp_path / "memory" / "skills")
@ -32,7 +37,10 @@ def _pipeline(tmp_path: Path, *, allowed_tools: set[str] | None = None) -> Skill
draft_service=drafts,
review_service=ReviewService(spec_store),
publisher=SkillPublisher(spec_store),
safety_checker=SkillDraftSafetyChecker(allowed_tool_names=allowed_tools),
safety_checker=SkillDraftSafetyChecker(
allowed_tool_names=allowed_tools,
allowed_tool_prefixes=allowed_prefixes,
),
)
@ -106,3 +114,53 @@ def test_safety_blocks_unknown_tool_hint(tmp_path: Path) -> None:
assert report.passed is False
assert "unknown tool hints" in report.blocked_reasons[0]
def test_safety_allows_configured_mcp_tool_prefix(tmp_path: Path) -> None:
pipeline = _pipeline(
tmp_path,
allowed_tools={"echo"},
allowed_prefixes={"mcp_officebench_"},
)
draft = pipeline.draft_service.create_new_skill_draft(
skill_name="officebench-excel",
proposed_content="# OfficeBench Excel\n\nUse the configured OfficeBench MCP tools.",
proposed_frontmatter={
"description": "officebench",
"tools": [
"mcp_officebench_shell_list_directory",
"mcp_officebench_excel_read_file",
"mcp_officebench_excel_set_cell",
],
},
created_by="test",
reason="test",
)
report = pipeline.check_safety(draft.skill_name, draft.draft_id)
assert report.passed is True
assert report.blocked_reasons == []
def test_safety_blocks_unconfigured_mcp_tool_prefix(tmp_path: Path) -> None:
pipeline = _pipeline(
tmp_path,
allowed_tools={"echo"},
allowed_prefixes={"mcp_outlook_mcp_"},
)
draft = pipeline.draft_service.create_new_skill_draft(
skill_name="wrong-mcp",
proposed_content="# Wrong MCP\n\nUse an unconfigured MCP namespace.",
proposed_frontmatter={
"description": "wrong mcp",
"tools": ["mcp_officebench_excel_set_cell"],
},
created_by="test",
reason="test",
)
report = pipeline.check_safety(draft.skill_name, draft.draft_id)
assert report.passed is False
assert "mcp_officebench_excel_set_cell" in report.blocked_reasons[0]