From b7abbece0f39e5b1d2c4596dcc98e067df1ae435 Mon Sep 17 00:00:00 2001 From: wutongyuonce <147830929+wutongyuonce@users.noreply.github.com> Date: Sun, 31 May 2026 14:33:07 +0800 Subject: [PATCH] refactor(skill/tools): delegate list_wiki_dir and read_wiki_file_for_skill to canonical agent tools --- openkb/skill/tools.py | 36 ++++++++++++++++-------------------- 1 file changed, 16 insertions(+), 20 deletions(-) diff --git a/openkb/skill/tools.py b/openkb/skill/tools.py index 1c2082a9..5ce45bc5 100644 --- a/openkb/skill/tools.py +++ b/openkb/skill/tools.py @@ -1,17 +1,20 @@ """Path-scoped IO tools for the skill-create agent. The skill-create agent runs with these capabilities: - * READ wiki structure — ``list_wiki_dir`` - * READ wiki markdown — ``read_wiki_file_for_skill`` + * READ wiki structure — ``list_wiki_dir`` (delegates to + ``openkb.agent.tools.list_wiki_files``) + * READ wiki markdown — ``read_wiki_file_for_skill`` (delegates to + ``openkb.agent.tools.read_wiki_file``) * READ PageIndex source pages — ``get_skill_page_content`` (delegates to ``openkb.agent.tools.get_wiki_page_content``) * READ wiki images — ``read_skill_image`` (delegates to ``openkb.agent.tools.read_wiki_image``) * WRITE under skill root — ``write_skill_file`` -The first four wrap the canonical wiki tools in ``openkb/agent/tools.py`` -so the skill agent traverses the wiki the same way the query agent does — -no separate retrieval semantics, no second implementation to drift. +The first four are thin wrappers around the canonical wiki tools in +``openkb/agent/tools.py`` so the skill agent traverses the wiki the same +way the query agent does — no separate retrieval semantics, no second +implementation to drift. These helpers enforce write boundaries at the Python level — every write resolves its target path, then verifies it stays inside the skill root. @@ -23,6 +26,8 @@ from openkb.agent.tools import ( get_wiki_page_content as _get_wiki_page_content, + list_wiki_files as _list_wiki_files, + read_wiki_file as _read_wiki_file, read_wiki_image as _read_wiki_image, ) @@ -30,34 +35,25 @@ def list_wiki_dir(directory: str, wiki_root: str) -> str: """List ``.md`` files in a wiki subdirectory. + Thin wrapper around :func:`openkb.agent.tools.list_wiki_files`. + Args: directory: Path relative to *wiki_root* (e.g. ``"concepts"``). wiki_root: Absolute path to ``/wiki``. """ - root = Path(wiki_root).resolve() - target = (root / directory).resolve() - if not target.is_relative_to(root): - return "Access denied: path escapes wiki root." - if not target.exists() or not target.is_dir(): - return "No files found." - names = sorted(p.name for p in target.iterdir() if p.suffix == ".md") - return "\n".join(names) if names else "No files found." + return _list_wiki_files(directory, wiki_root) def read_wiki_file_for_skill(path: str, wiki_root: str) -> str: """Read a Markdown file from the wiki. + Thin wrapper around :func:`openkb.agent.tools.read_wiki_file`. + Args: path: File path relative to *wiki_root* (e.g. ``"concepts/attention.md"``). wiki_root: Absolute path to ``/wiki``. """ - root = Path(wiki_root).resolve() - full = (root / path).resolve() - if not full.is_relative_to(root): - return "Access denied: path escapes wiki root." - if not full.exists(): - return f"File not found: {path}" - return full.read_text(encoding="utf-8") + return _read_wiki_file(path, wiki_root) def get_skill_page_content(doc_name: str, pages: str, wiki_root: str) -> str: