mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-07-08 13:12:08 +00:00
fix(skills): widen call-time skills-dir resolution to skill_manager_tool
Same bug class as skills_tool: module-level SKILLS_DIR pinned at import under the launch HERMES_HOME makes skill_manage() write/edit against the wrong profile in long-lived multi-profile runtimes. Apply the same _skills_dir() call-time resolution (honoring explicit test patches of SKILLS_DIR) to _containing_skills_root, _resolve_skill_dir, _find_skill_in_other_profiles, and create-result path reporting. Refs #40677
This commit is contained in:
parent
4a99571d54
commit
c6a3d412d4
1 changed files with 23 additions and 6 deletions
|
|
@ -150,6 +150,22 @@ import yaml
|
|||
# All skills live in ~/.hermes/skills/ (single source of truth)
|
||||
HERMES_HOME = get_hermes_home()
|
||||
SKILLS_DIR = HERMES_HOME / "skills"
|
||||
_SKILLS_DIR_AT_IMPORT = SKILLS_DIR
|
||||
|
||||
|
||||
def _skills_dir() -> Path:
|
||||
"""Return the active profile's skills directory at call time.
|
||||
|
||||
Long-lived multi-profile runtimes (Dashboard/TUI/Desktop backend, cron,
|
||||
kanban workers) import this module once under the launch HERMES_HOME and
|
||||
later bind a different profile per session (#40677). Honor an explicitly
|
||||
patched module-level ``SKILLS_DIR`` (tests), otherwise resolve from the
|
||||
live profile-scoped HERMES_HOME on every call.
|
||||
"""
|
||||
configured = Path(SKILLS_DIR)
|
||||
if configured != _SKILLS_DIR_AT_IMPORT:
|
||||
return configured
|
||||
return get_hermes_home() / "skills"
|
||||
|
||||
MAX_NAME_LENGTH = 64
|
||||
MAX_DESCRIPTION_LENGTH = 1024
|
||||
|
|
@ -174,7 +190,7 @@ def _containing_skills_root(skill_path: Path) -> Path:
|
|||
return root
|
||||
except (ValueError, OSError):
|
||||
continue
|
||||
return SKILLS_DIR
|
||||
return _skills_dir()
|
||||
|
||||
|
||||
def _is_path_redirect(path: Path) -> bool:
|
||||
|
|
@ -562,8 +578,8 @@ def _validate_content_size(content: str, label: str = "SKILL.md") -> Optional[st
|
|||
def _resolve_skill_dir(name: str, category: str = None) -> Path:
|
||||
"""Build the directory path for a new skill, optionally under a category."""
|
||||
if category:
|
||||
return SKILLS_DIR / category / name
|
||||
return SKILLS_DIR / name
|
||||
return _skills_dir() / category / name
|
||||
return _skills_dir() / name
|
||||
|
||||
|
||||
def _find_skill(name: str) -> Optional[Dict[str, Any]]:
|
||||
|
|
@ -608,8 +624,9 @@ def _find_skill_in_other_profiles(name: str) -> List[Tuple[str, Path]]:
|
|||
return matches
|
||||
|
||||
# Collect (profile_name, skills_dir) for every profile EXCEPT the
|
||||
# one whose SKILLS_DIR we already searched in _find_skill().
|
||||
active_dir = SKILLS_DIR.resolve() if SKILLS_DIR.exists() else SKILLS_DIR
|
||||
# one whose skills dir we already searched in _find_skill().
|
||||
_active = _skills_dir()
|
||||
active_dir = _active.resolve() if _active.exists() else _active
|
||||
candidates: List[Tuple[str, Path]] = []
|
||||
|
||||
# Default profile (~/.hermes/skills) — only consider when active is non-default.
|
||||
|
|
@ -828,7 +845,7 @@ def _create_skill(name: str, content: str, category: str = None) -> Dict[str, An
|
|||
result = {
|
||||
"success": True,
|
||||
"message": f"Skill '{name}' created.",
|
||||
"path": str(skill_dir.relative_to(SKILLS_DIR)),
|
||||
"path": str(skill_dir.relative_to(_skills_dir())),
|
||||
"skill_md": str(skill_md),
|
||||
"_change": {"description": _desc},
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue