mirror of
https://github.com/pewdiepie-archdaemon/odysseus.git
synced 2026-10-31 02:02:22 +01:00
Merge pull request #6888 from redpersongpt/codex/skill-version-preservation
fix(skills): preserve version strings across markdown saves
This commit is contained in:
@@ -84,10 +84,14 @@ _FM_KEY_RE = re.compile(r"^([a-z_][a-z0-9_]*):\s*(.*)$", re.IGNORECASE)
|
||||
_FM_BLOCK_LIST_RE = re.compile(r"^\s*-\s*(.*)$")
|
||||
|
||||
|
||||
def _parse_scalar(raw: str) -> Any:
|
||||
def _parse_scalar(raw: str, *, string_only: bool = False) -> Any:
|
||||
raw = raw.strip()
|
||||
if raw == "":
|
||||
return ""
|
||||
# String fields keep their spelling; quoted values still use the decoder
|
||||
# below so existing escapes round-trip as before.
|
||||
if string_only and not (raw[0] == raw[-1] and raw[0] in ("'", '"')):
|
||||
return raw
|
||||
if raw.startswith("[") and raw.endswith("]"):
|
||||
inner = raw[1:-1].strip()
|
||||
if not inner:
|
||||
@@ -171,7 +175,7 @@ def parse_frontmatter(text: str) -> tuple[Dict[str, Any], str]:
|
||||
pending_key = key
|
||||
fm[key] = []
|
||||
else:
|
||||
fm[key] = _parse_scalar(val)
|
||||
fm[key] = _parse_scalar(val, string_only=(key == "version"))
|
||||
pending_key = None
|
||||
continue
|
||||
m2 = _FM_BLOCK_LIST_RE.match(line)
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
"""Issue #2131: editing a skill must not reinterpret its version as a number."""
|
||||
|
||||
import pytest
|
||||
|
||||
from services.memory.skill_format import Skill, parse_frontmatter
|
||||
from services.memory.skills import SkillsManager
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"raw, expected",
|
||||
[
|
||||
("1.10", "1.10"),
|
||||
("2.20", "2.20"),
|
||||
("01", "01"),
|
||||
("0", "0"),
|
||||
("1.0.0", "1.0.0"),
|
||||
("true", "true"),
|
||||
("null", "null"),
|
||||
('"1.10"', "1.10"),
|
||||
("'2.20'", "2.20"),
|
||||
('"release\\u002d01"', "release-01"),
|
||||
],
|
||||
)
|
||||
def test_version_survives_repeated_markdown_saves(raw, expected):
|
||||
markdown = f"---\nname: demo\nversion: {raw}\nconfidence: 0.80\n---\n"
|
||||
for _ in range(3):
|
||||
skill = Skill.from_markdown(markdown)
|
||||
assert skill.version == expected
|
||||
assert skill.confidence == 0.8
|
||||
markdown = skill.to_markdown()
|
||||
|
||||
|
||||
def test_version_preservation_keeps_other_frontmatter_types():
|
||||
fm, _ = parse_frontmatter(
|
||||
"---\nversion: 1.10\nconfidence: 0.80\nuses: 3\n"
|
||||
"enabled: true\ntags: [one, two]\n---\n"
|
||||
)
|
||||
assert fm == {
|
||||
"version": "1.10", "confidence": 0.8, "uses": 3,
|
||||
"enabled": True, "tags": ["one", "two"],
|
||||
}
|
||||
|
||||
|
||||
@pytest.mark.parametrize("version_line", ["", "version:\n", 'version: ""\n'])
|
||||
def test_missing_or_empty_version_retains_default(version_line):
|
||||
skill = Skill.from_markdown(f"---\nname: demo\n{version_line}---\n")
|
||||
assert skill.version == "1.0.0"
|
||||
|
||||
|
||||
def test_version_survives_unrelated_edits_on_disk(tmp_path):
|
||||
manager = SkillsManager(str(tmp_path))
|
||||
manager.add_skill(name="demo", version="1.10", owner="alice")
|
||||
for i in range(3):
|
||||
assert manager.update_skill("demo", {"description": f"Edit {i}"}, owner="alice")
|
||||
stored = manager.load(owner="alice")
|
||||
assert stored[0]["version"] == "1.10"
|
||||
assert stored[0]["description"] == f"Edit {i}"
|
||||
markdown = next((tmp_path / "skills").rglob("SKILL.md")).read_text(encoding="utf-8")
|
||||
assert "version: 1.10\n" in markdown
|
||||
Reference in New Issue
Block a user