core: Registry, Skills, Router, Executor, Verifier, Runner mit Tests
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,78 @@
|
||||
from knaster.registry import AdapterSpec, Registry
|
||||
from knaster.skills import compact_body, parse_skill
|
||||
|
||||
|
||||
def test_slot_effective_context_prefers_calibration(registry):
|
||||
slot = registry.slot("tier1-general")
|
||||
assert slot.effective_context == 2000
|
||||
registry.set_calibrated_context("tier1-general", 1500)
|
||||
assert registry.slot("tier1-general").effective_context == 1500
|
||||
|
||||
|
||||
def test_effective_context_never_exceeds_max(registry):
|
||||
registry.set_calibrated_context("tier1-general", 999999)
|
||||
assert registry.slot("tier1-general").effective_context == 8192
|
||||
|
||||
|
||||
def test_status_and_strong_slot(registry):
|
||||
registry.set_status("tier1-general", "degraded", reason="test", set_by="healer")
|
||||
slot = registry.slot("tier1-general")
|
||||
assert not slot.available and slot.set_by == "healer"
|
||||
assert registry.strong_slot().name == "tier0-strong"
|
||||
|
||||
|
||||
def test_unknown_fallback_rejected(store):
|
||||
import pytest
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
Registry.from_dict({"slots": {"a": {"tier": 1, "litellm_model": "a", "base_model": "b",
|
||||
"max_context": 10, "fallbacks": ["x"]}}}, store)
|
||||
|
||||
|
||||
def test_adapter_overlay_and_active(registry):
|
||||
assert registry.active_adapter("base-14b", "rechnungen").name == "rechnungen-v1"
|
||||
registry.set_adapter(AdapterSpec(name="rechnungen-v2", base_model="base-14b", cluster="rechnungen",
|
||||
version=2, status="active"))
|
||||
assert registry.active_adapter("base-14b", "rechnungen").name == "rechnungen-v2"
|
||||
registry.set_adapter(AdapterSpec(name="rechnungen-v2", base_model="base-14b", cluster="rechnungen",
|
||||
version=2, status="retired"))
|
||||
assert registry.active_adapter("base-14b", "rechnungen").name == "rechnungen-v1"
|
||||
assert registry.active_adapter("other-base", "rechnungen") is None
|
||||
|
||||
|
||||
def test_base_model_override_and_export(registry):
|
||||
registry.set_base_model("tier1-general", "new-base")
|
||||
assert registry.slot("tier1-general").base_model == "new-base"
|
||||
exported = registry.export()
|
||||
assert exported["slots"]["tier1-general"]["base_model"] == "new-base"
|
||||
|
||||
|
||||
def test_parse_skill_and_compact(library):
|
||||
skill = library.get("rechnung-extrahieren")
|
||||
assert skill.cluster == "rechnungen"
|
||||
assert skill.meta.output.format == "json"
|
||||
assert "Beispiele" in skill.prompt("full")
|
||||
assert "Beispiele" not in skill.prompt("compact")
|
||||
assert "Lies Nummer" in skill.prompt("compact")
|
||||
|
||||
|
||||
def test_compact_body_keeps_following_sections():
|
||||
body = "# T\nA\n## Beispiele\nx\ny\n## Regeln\nR\n"
|
||||
assert compact_body(body) == "# T\nA\n## Regeln\nR"
|
||||
|
||||
|
||||
def test_parse_skill_requires_fields():
|
||||
import pytest
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
parse_skill("---\nname: x\n---\nbody")
|
||||
with pytest.raises(ValueError):
|
||||
parse_skill("kein frontmatter")
|
||||
|
||||
|
||||
def test_routable_and_state_overlay(library):
|
||||
names = {s.name for s in library.routable()}
|
||||
assert "entwurf" not in names and "vertrag-pruefen" in names
|
||||
library.set_state("rechnung-extrahieren", status="demoted", reason="drift")
|
||||
assert library.get("rechnung-extrahieren").meta.status == "demoted"
|
||||
assert library.get("rechnung-extrahieren").meta.stage == 1
|
||||
Reference in New Issue
Block a user