mirror of
https://github.com/NCBM/plyngent.git
synced 2026-11-07 15:37:55 +08:00
tools/skills: list, read, and search skills
skill_list shows what was discovered (name, source root, directory, description) together with the copies a name collision shadowed and the notes from repaired frontmatter, so a third-party skill never disappears quietly. skill_read addresses a skill by name and defaults to its SKILL.md, reusing read_file for ranges, line numbers, and the continuation token; a bundled file is resolved inside the skill directory only, symlinks included. skill_search greps every visible skill (or one) and rebases each hit on its skill, which makes a match attributable without absolute paths. Reads need no grant: the host registers the roots as static read-only roots on the workspace policy, so read_file/grep_files see skill directories too while write access stays denied — skill writes will go through their own confirm. Grep used to drop every file outside the primary workspace root, which also hid hits under a granted directory; those now come back as absolute paths.
This commit is contained in:
@@ -821,6 +821,53 @@ def test_every_builtin_tool_has_a_pretty_line() -> None:
|
||||
assert missing == []
|
||||
|
||||
|
||||
async def test_pretty_skill_tools(capsys: pytest.CaptureFixture[str]) -> None:
|
||||
await render_events(
|
||||
_aiter(
|
||||
[_pretty_call("skill_list", "{}"), _result("skills: 3\npdf-processing [plyngent-user] /x — Extract PDFs")]
|
||||
)
|
||||
)
|
||||
out = capsys.readouterr().out
|
||||
assert "* Skills (3 skills)" in out
|
||||
|
||||
await render_events(
|
||||
_aiter(
|
||||
[
|
||||
_pretty_call("skill_read", '{"name": "pdf-processing"}'),
|
||||
_result("L1-40\n# PDF processing\n"),
|
||||
]
|
||||
)
|
||||
)
|
||||
out = capsys.readouterr().out
|
||||
assert "* Skill 'pdf-processing' L1-40 (done)" in out
|
||||
|
||||
await render_events(
|
||||
_aiter(
|
||||
[
|
||||
_pretty_call("skill_read", '{"name": "pdf-processing", "file": "scripts/run.sh"}'),
|
||||
_result("L1-3\n#!/bin/sh\n"),
|
||||
]
|
||||
)
|
||||
)
|
||||
out = capsys.readouterr().out
|
||||
assert "* Skill 'pdf-processing' scripts/run.sh L1-3 (done)" in out
|
||||
|
||||
await render_events(
|
||||
_aiter(
|
||||
[
|
||||
_pretty_call("skill_search", '{"pattern": "pdftotext"}'),
|
||||
_result("alpha/SKILL.md:3: Use pdftotext.\nbeta/notes.md:1: pdftotext again"),
|
||||
]
|
||||
)
|
||||
)
|
||||
out = capsys.readouterr().out
|
||||
assert "* Skill Search 'pdftotext' (2 matches in 2 skills)" in out
|
||||
|
||||
await render_events(_aiter([_pretty_call("skill_search", '{"pattern": "nope"}'), _result("(no matches)")]))
|
||||
out = capsys.readouterr().out
|
||||
assert "* Skill Search 'nope' (no matches)" in out
|
||||
|
||||
|
||||
async def test_pretty_prefix_shown_while_call_runs(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
capsys: pytest.CaptureFixture[str],
|
||||
|
||||
Reference in New Issue
Block a user