fix: address community issues #37 #30 #36

- s03: inject reminder into tool_result instead of mutating history (#37)
- s05: SkillLoader uses rglob("SKILL.md") + frontmatter name priority,
  matching Agent Skills standard (#30, PR #34)
- CI: upgrade actions/checkout and actions/setup-node to v6 (#36)
- docs: update s05 skill directory structure in all 3 languages
This commit is contained in:
CrazyBoyM 2026-02-28 00:09:57 +08:00
parent 4f39ee4512
commit dbffe7c8d0
10 changed files with 75 additions and 61 deletions

View file

@ -7,19 +7,25 @@ Two-layer skill injection that avoids bloating the system prompt:
Layer 1 (cheap): skill names in system prompt (~100 tokens/skill)
Layer 2 (on demand): full skill body in tool_result
skills/
pdf/
SKILL.md <-- frontmatter (name, description) + body
code-review/
SKILL.md
System prompt:
+--------------------------------------+
| You are a coding agent. |
| Skills available: |
| - git: Git workflow helpers | <-- Layer 1: metadata only
| - test: Testing best practices |
| - pdf: Process PDF files... | <-- Layer 1: metadata only
| - code-review: Review code... |
+--------------------------------------+
When model calls load_skill("git"):
When model calls load_skill("pdf"):
+--------------------------------------+
| tool_result: |
| <skill> |
| Full git workflow instructions... | <-- Layer 2: full body
| Full PDF processing instructions | <-- Layer 2: full body
| Step 1: ... |
| Step 2: ... |
| </skill> |
@ -44,10 +50,10 @@ if os.getenv("ANTHROPIC_BASE_URL"):
WORKDIR = Path.cwd()
client = Anthropic(base_url=os.getenv("ANTHROPIC_BASE_URL"))
MODEL = os.environ["MODEL_ID"]
SKILLS_DIR = WORKDIR / ".skills"
SKILLS_DIR = WORKDIR / "skills"
# -- SkillLoader: parse .skills/*.md files with YAML frontmatter --
# -- SkillLoader: scan skills/<name>/SKILL.md with YAML frontmatter --
class SkillLoader:
def __init__(self, skills_dir: Path):
self.skills_dir = skills_dir
@ -57,10 +63,10 @@ class SkillLoader:
def _load_all(self):
if not self.skills_dir.exists():
return
for f in sorted(self.skills_dir.glob("*.md")):
name = f.stem
for f in sorted(self.skills_dir.rglob("SKILL.md")):
text = f.read_text()
meta, body = self._parse_frontmatter(text)
name = meta.get("name", f.parent.name)
self.skills[name] = {"meta": meta, "body": body, "path": str(f)}
def _parse_frontmatter(self, text: str) -> tuple: