Files
cleveragents-core/benchmarks/skill_resolution_bench.py
Jeff 20321f21ee
CI / lint (push) Waiting to run
CI / typecheck (push) Waiting to run
CI / security (push) Waiting to run
CI / quality (push) Waiting to run
CI / unit_tests (push) Waiting to run
CI / integration_tests (push) Waiting to run
CI / coverage (push) Blocked by required conditions
CI / build (push) Waiting to run
CI / docker (push) Blocked by required conditions
feat(skill): add skill domain model and resolver
2026-02-14 03:54:14 +00:00

178 lines
5.4 KiB
Python

"""ASV benchmarks for Skill domain model and resolution.
Measures the performance of:
- Skill model construction (Pydantic validation)
- Skill.as_cli_dict() serialization
- Skill.from_config() factory
- SkillResolver.resolve_tools() flattening
- SkillResolver.compute_capability_summary() aggregation
"""
from __future__ import annotations
import sys
from pathlib import Path
try:
from cleveragents.domain.models.core.skill import (
Skill,
SkillAgentSource,
SkillInclude,
SkillInlineTool,
SkillMcpSource,
SkillResolver,
)
from cleveragents.domain.models.core.tool import (
ToolCapability,
ToolSource,
)
except ModuleNotFoundError:
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
from cleveragents.domain.models.core.skill import (
Skill,
SkillAgentSource,
SkillInclude,
SkillInlineTool,
SkillMcpSource,
SkillResolver,
)
from cleveragents.domain.models.core.tool import (
ToolCapability,
ToolSource,
)
def _make_skill() -> Skill:
"""Create a fully-populated Skill for benchmarking."""
return Skill(
name="bench/full-skill",
description="Benchmark skill",
tool_refs=["bench/tool-a", "bench/tool-b", "bench/tool-c"],
includes=[SkillInclude(name="bench/base-skill")],
anonymous_tools=[
SkillInlineTool(
description="Inline bench tool",
source=ToolSource.CUSTOM,
code="return True",
capability=ToolCapability(writes=True, side_effects=["fs"]),
),
],
mcp_servers=[
SkillMcpSource(
server="npx @mcp/bench-server",
tools=["read", "write"],
env={"KEY": "val"},
),
],
agent_skills=[SkillAgentSource(path="./skills/bench")],
overrides={"bench/tool-a": {"timeout": 600}},
)
def _make_registry() -> dict[str, Skill]:
"""Create a skill registry for resolution benchmarks."""
base = Skill(
name="bench/base-skill",
description="Base skill",
tool_refs=["bench/base-tool-1", "bench/base-tool-2"],
)
return {"bench/base-skill": base}
class SkillConstructionSuite:
"""Benchmark Skill model construction (Pydantic validation)."""
def time_skill_construction(self) -> None:
"""Benchmark creating a fully-populated Skill object."""
_make_skill()
def time_skill_minimal_construction(self) -> None:
"""Benchmark creating a minimal Skill object."""
Skill(
name="bench/minimal",
description="Minimal skill",
)
def time_inline_tool_construction(self) -> None:
"""Benchmark SkillInlineTool construction."""
SkillInlineTool(
description="Bench inline",
source=ToolSource.CUSTOM,
code="return True",
)
def time_mcp_source_construction(self) -> None:
"""Benchmark SkillMcpSource construction."""
SkillMcpSource(
server="npx @mcp/bench",
tools=["read", "write"],
)
class SkillSerializationSuite:
"""Benchmark Skill serialization methods."""
def setup(self) -> None:
"""Create objects for serialization benchmarks."""
self.skill = _make_skill()
def time_skill_as_cli_dict(self) -> None:
"""Benchmark Skill.as_cli_dict() ordered dict generation."""
self.skill.as_cli_dict()
def time_skill_model_dump(self) -> None:
"""Benchmark Pydantic model_dump() serialization."""
self.skill.model_dump()
def time_skill_model_dump_json(self) -> None:
"""Benchmark Pydantic model_dump_json() JSON serialization."""
self.skill.model_dump_json()
class SkillFromConfigSuite:
"""Benchmark Skill.from_config() factory."""
def setup(self) -> None:
"""Prepare config dict for benchmarks."""
self.config = {
"name": "bench/from-config",
"description": "Config benchmark",
"tools": ["bench/tool-a", "bench/tool-b"],
"includes": [{"name": "bench/base-skill"}],
"anonymous_tools": [
{
"description": "Inline",
"source": "custom",
"code": "return True",
},
],
"mcp_servers": [
{"server": "npx @mcp/bench", "tools": ["read"]},
],
"agent_skills": [{"path": "./skills/bench"}],
}
def time_skill_from_config(self) -> None:
"""Benchmark Skill.from_config()."""
Skill.from_config(self.config)
class SkillResolutionSuite:
"""Benchmark SkillResolver.resolve_tools()."""
def setup(self) -> None:
"""Create skill and registry for benchmarks."""
self.skill = _make_skill()
self.registry = _make_registry()
self.registry[self.skill.name] = self.skill
self.resolver = SkillResolver()
def time_resolve_tools(self) -> None:
"""Benchmark resolve_tools() with one include level."""
self.resolver.resolve_tools(self.skill, self.registry)
def time_compute_capability_summary(self) -> None:
"""Benchmark compute_capability_summary()."""
resolved = self.resolver.resolve_tools(self.skill, self.registry)
self.resolver.compute_capability_summary(self.skill, resolved)