fix(skills): enforce allowed-tools metadata (#2626)

* fix(skills): parse allowed-tools frontmatter

* fix(skills): validate allowed-tools metadata

* fix(skills): add shared allowed-tools policy

* fix(subagents): enforce skill allowed-tools

* fix(agent): enforce skill allowed-tools

* refactor(skills): dedupe TypeVar and reuse cached enabled skills

- Drop redundant module-level TypeVar in tool_policy; rely on PEP 695 syntax.
- Expose get_cached_enabled_skills() and have the lead agent reuse it
  instead of synchronously rescanning skills on every request.

* fix(agent): expose config-scoped skill cache

* fix(subagents): pass filtered tools explicitly

* fix(skills): clean allowed-tools policy feedback
This commit is contained in:
AochenShen99
2026-05-07 08:34:43 +08:00
committed by GitHub
parent 2b0e62f679
commit cef4224381
12 changed files with 553 additions and 55 deletions
+27
View File
@@ -86,6 +86,33 @@ def test_parse_license_field(tmp_path):
assert skill.license == "MIT"
def test_parse_missing_allowed_tools_returns_none(tmp_path):
skill_file = _write_skill(tmp_path, "name: my-skill\ndescription: Test")
skill = parse_skill_file(skill_file, category="custom")
assert skill is not None
assert skill.allowed_tools is None
def test_parse_allowed_tools_list(tmp_path):
skill_file = _write_skill(tmp_path, 'name: my-skill\ndescription: Test\nallowed-tools: ["bash", "read_file"]')
skill = parse_skill_file(skill_file, category="custom")
assert skill is not None
assert skill.allowed_tools == ["bash", "read_file"]
def test_parse_empty_allowed_tools_list(tmp_path):
skill_file = _write_skill(tmp_path, "name: my-skill\ndescription: Test\nallowed-tools: []")
skill = parse_skill_file(skill_file, category="custom")
assert skill is not None
assert skill.allowed_tools == []
def test_parse_invalid_allowed_tools_returns_none(tmp_path):
skill_file = _write_skill(tmp_path, "name: my-skill\ndescription: Test\nallowed-tools: bash")
skill = parse_skill_file(skill_file, category="custom")
assert skill is None
def test_parse_missing_name_returns_none(tmp_path):
"""Skills missing a name field are rejected."""
skill_file = _write_skill(tmp_path, "description: A test skill")