diff --git a/src/nano/prompt.py b/src/nano/prompt.py index b3dbb961c..46a148d4b 100644 --- a/src/nano/prompt.py +++ b/src/nano/prompt.py @@ -25,6 +25,8 @@ from __future__ import annotations +import os + from pathlib import Path from typing import Any @@ -126,13 +128,15 @@ def _skills_section(cwd: str) -> str: # advertised but unusable (and would only bloat the prompt). Drop them. entries: list[tuple[str, str, str]] = [] for skill in skills: - paths = getattr(skill, "paths", None) or [] - if not paths: + # ``paths`` is the conditional-activation glob list, not a file + # location; the loadable file is ``/SKILL.md``. + root = getattr(skill, "skill_root", None) + if not root: continue entries.append(( _xml_escape(str(getattr(skill, "name", ""))), _xml_escape(str(getattr(skill, "description", "") or "")), - _xml_escape(str(paths[0])), + _xml_escape(os.path.join(str(root), "SKILL.md")), )) if not entries: return "" diff --git a/tests/nano/test_nano_prompt.py b/tests/nano/test_nano_prompt.py index 6180f7d34..963241234 100644 --- a/tests/nano/test_nano_prompt.py +++ b/tests/nano/test_nano_prompt.py @@ -120,3 +120,17 @@ def test_default_path_unchanged_when_nano_off(no_skills, tmp_path): # The maximal prompt keeps its signature sections. assert "# Doing tasks" in joined assert "nano mode" not in joined + + +def test_skills_section_lists_skill_by_root_not_paths(monkeypatch): + """A skill is located at /SKILL.md; ``paths`` is only the + conditional-activation glob list and is usually empty.""" + import src.command_system as cs + from src.nano.prompt import _skills_section + + skill = SimpleNamespace( + name="demo", description="d", paths=[], skill_root="/x/skills/demo" + ) + monkeypatch.setattr(cs, "get_skill_tool_commands", lambda cwd: (skill,)) + out = _skills_section("/tmp") + assert "/x/skills/demo/SKILL.md" in out