diff --git a/mateclaw-server/src/main/java/vip/mate/agent/binding/service/AgentBindingService.java b/mateclaw-server/src/main/java/vip/mate/agent/binding/service/AgentBindingService.java index de01e15b..35a66135 100644 --- a/mateclaw-server/src/main/java/vip/mate/agent/binding/service/AgentBindingService.java +++ b/mateclaw-server/src/main/java/vip/mate/agent/binding/service/AgentBindingService.java @@ -486,7 +486,36 @@ public class AgentBindingService { "extract_document_text", "extract_pdf_text", "extract_docx_text", - "readMateClawDoc" + "readMateClawDoc", + // Wiki knowledge-base tools. These are agent-wide capabilities + // tied to whichever knowledge base is attached to the agent, and + // are never declared inside any skill manifest. Like the document + // and media generators above, the skill-binding allowlist would + // otherwise strip every wiki_* tool from any agent that has a + // skill bound — so the agent could no longer read or write its + // own knowledge base ("save this result into the knowledge base" + // failed with a not-found / no-permission style error). Each tool + // degrades with a clear "no knowledge base" message when the + // agent has none attached, so advertising them unconditionally + // is safe. + "wiki_read_page", + "wiki_list_pages", + "wiki_search_pages", + "wiki_semantic_search", + "wiki_trace_source", + "wiki_create_page", + "wiki_compile_page", + "wiki_read_many", + "wiki_archive_page", + "wiki_unarchive_page", + "wiki_delete_page", + "wiki_related_pages", + "wiki_explain_relation", + "wiki_enrich_page", + "wiki_list_transformations", + "wiki_apply_transformation", + "wiki_apply_transformation_to_page", + "wiki_aggregate_transformation" ); private ResolvedSkill findResolvedSkillById(Long skillId) { diff --git a/mateclaw-server/src/test/java/vip/mate/agent/binding/AgentBindingServiceTest.java b/mateclaw-server/src/test/java/vip/mate/agent/binding/AgentBindingServiceTest.java index 2bb5499d..70d8f7ad 100644 --- a/mateclaw-server/src/test/java/vip/mate/agent/binding/AgentBindingServiceTest.java +++ b/mateclaw-server/src/test/java/vip/mate/agent/binding/AgentBindingServiceTest.java @@ -357,6 +357,27 @@ class AgentBindingServiceTest { + "否则 AgentToolSet.withAllowedToolsOnly 会变成空集禁掉所有工具"); } + @Test + @DisplayName("Issue #143: 绑定任意工具后,wiki 知识库工具仍留在 effective allowlist(可读写知识库)") + void wikiToolsSurviveSkillBindingAllowlist() { + // Reproduce issue #143: once an agent has any binding, the effective + // allowlist turns on. Wiki tools live on the WikiTool bean and are + // never declared by a skill manifest, so before the fix they were + // filtered out — the agent could chat but lost its KB read/write + // tools and reported "no permission" when asked to save a result. + seedBuiltinTool("builtin_probe"); + bindingService.setToolBindings(agentId, List.of("builtin_probe")); + + Set effective = bindingService.getEffectiveToolNames(agentId); + assertNotNull(effective, "binding 非空时应返回 allowlist(非 null)"); + assertTrue(effective.contains("wiki_create_page"), + "wiki_create_page 必须留在 allowlist —— 否则 AI 无法把结果写入知识库(issue #143)。" + + "实际 allowlist: " + effective); + assertTrue(effective.contains("wiki_read_page"), + "wiki_read_page 必须留在 allowlist —— 否则 agent 无法读取自己的知识库。" + + "实际 allowlist: " + effective); + } + @Test @DisplayName("unbindTool 后 DB 里真的没行(物理 delete,不是软删留 deleted=1)") void unbindPhysicallyRemovesRow() {