mirror of
https://github.com/NousResearch/hermes-agent.git
synced 2026-05-01 01:51:44 +00:00
fix(agent): log defensive parse failures in skill_utils
- Add logger.debug with exc_info on YAML/frontmatter and config read paths that previously swallowed exceptions (parse_frontmatter, external dirs, discover_all_skill_config_vars, resolve_skill_config_values). - Align get_disabled_skill_names error logging with exc_info for parity. - Add tests/agent/test_skill_utils.py regression coverage. Made-with: Cursor
This commit is contained in:
parent
37913d9109
commit
4d5408fd16
2 changed files with 136 additions and 6 deletions
103
tests/agent/test_skill_utils.py
Normal file
103
tests/agent/test_skill_utils.py
Normal file
|
|
@ -0,0 +1,103 @@
|
|||
"""Regression tests for agent.skill_utils logging on defensive parse paths."""
|
||||
|
||||
import logging
|
||||
import os
|
||||
from unittest.mock import patch
|
||||
|
||||
|
||||
class TestParseFrontmatter:
|
||||
def test_malformed_yaml_falls_back_to_line_parser(self):
|
||||
from agent.skill_utils import parse_frontmatter
|
||||
|
||||
content = (
|
||||
"---\n"
|
||||
"name: broken-skill\n"
|
||||
"bad: [ this bracket never closes\n"
|
||||
"---\n\n"
|
||||
"# Body\n"
|
||||
)
|
||||
fm, body = parse_frontmatter(content)
|
||||
assert "name" in fm
|
||||
assert fm["name"] == "broken-skill"
|
||||
assert "# Body" in body
|
||||
|
||||
def test_malformed_yaml_emits_debug_log(self, caplog):
|
||||
import agent.skill_utils as su
|
||||
|
||||
caplog.set_level(logging.DEBUG, logger=su.__name__)
|
||||
content = (
|
||||
"---\n"
|
||||
"x: [\n"
|
||||
"---\n\n"
|
||||
"ok\n"
|
||||
)
|
||||
su.parse_frontmatter(content)
|
||||
assert any(
|
||||
"frontmatter YAML parse failed" in r.message for r in caplog.records
|
||||
)
|
||||
|
||||
|
||||
class TestGetExternalSkillsDirsLogging:
|
||||
def test_yaml_failure_logs_and_returns_empty(self, tmp_path, caplog):
|
||||
home = tmp_path / ".hermes"
|
||||
home.mkdir()
|
||||
(home / "skills").mkdir()
|
||||
(home / "config.yaml").write_text("skills:\n external_dirs: []\n")
|
||||
|
||||
import agent.skill_utils as su
|
||||
|
||||
caplog.set_level(logging.DEBUG, logger=su.__name__)
|
||||
with patch.dict(os.environ, {"HERMES_HOME": str(home)}):
|
||||
with patch.object(su, "yaml_load", side_effect=ValueError("forced")):
|
||||
result = su.get_external_skills_dirs()
|
||||
assert result == []
|
||||
assert any(
|
||||
"external skills dirs" in r.message for r in caplog.records
|
||||
)
|
||||
|
||||
|
||||
class TestDiscoverAllSkillConfigVarsLogging:
|
||||
def test_unreadable_skill_file_skipped_with_log(self, tmp_path, caplog):
|
||||
home = tmp_path / ".hermes"
|
||||
home.mkdir()
|
||||
(home / "skills").mkdir()
|
||||
(home / "config.yaml").write_text("skills:\n external_dirs: []\n")
|
||||
skill_dir = home / "skills" / "bad-read"
|
||||
skill_dir.mkdir()
|
||||
bad = skill_dir / "SKILL.md"
|
||||
bad.write_bytes(b"\xff\xfe not utf-8")
|
||||
|
||||
import agent.skill_utils as su
|
||||
|
||||
caplog.set_level(logging.DEBUG, logger=su.__name__)
|
||||
with patch.dict(os.environ, {"HERMES_HOME": str(home)}):
|
||||
out = su.discover_all_skill_config_vars()
|
||||
assert out == []
|
||||
assert any("Skipping skill file" in r.message for r in caplog.records)
|
||||
|
||||
|
||||
class TestResolveSkillConfigValuesLogging:
|
||||
def test_yaml_failure_logs(self, tmp_path, caplog):
|
||||
home = tmp_path / ".hermes"
|
||||
home.mkdir()
|
||||
(home / "skills").mkdir()
|
||||
(home / "config.yaml").write_text("skills: {}\n")
|
||||
|
||||
import agent.skill_utils as su
|
||||
|
||||
caplog.set_level(logging.DEBUG, logger=su.__name__)
|
||||
vars_ = [
|
||||
{
|
||||
"key": "k",
|
||||
"description": "d",
|
||||
"default": "defval",
|
||||
"prompt": "p",
|
||||
}
|
||||
]
|
||||
with patch.dict(os.environ, {"HERMES_HOME": str(home)}):
|
||||
with patch.object(su, "yaml_load", side_effect=RuntimeError("bad yaml")):
|
||||
resolved = su.resolve_skill_config_values(vars_)
|
||||
assert resolved["k"] == "defval"
|
||||
assert any(
|
||||
"skill config var resolution" in r.message for r in caplog.records
|
||||
)
|
||||
Loading…
Add table
Add a link
Reference in a new issue