Files
freemo a9465c4865
CI / benchmark-publish (pull_request) Has been skipped
CI / build (pull_request) Successful in 18s
CI / helm (pull_request) Successful in 22s
CI / typecheck (pull_request) Successful in 50s
CI / lint (pull_request) Successful in 3m19s
CI / quality (pull_request) Successful in 3m53s
CI / security (pull_request) Successful in 4m12s
CI / integration_tests (pull_request) Successful in 7m10s
CI / unit_tests (pull_request) Successful in 7m27s
CI / docker (pull_request) Successful in 1m30s
CI / coverage (pull_request) Successful in 11m54s
CI / e2e_tests (pull_request) Successful in 19m37s
CI / status-check (pull_request) Successful in 1s
CI / build (push) Successful in 15s
CI / helm (push) Successful in 23s
CI / security (push) Successful in 57s
CI / lint (push) Successful in 3m18s
CI / quality (push) Successful in 3m39s
CI / typecheck (push) Successful in 3m52s
CI / integration_tests (push) Successful in 8m48s
CI / unit_tests (push) Successful in 9m38s
CI / docker (push) Successful in 1m18s
CI / coverage (push) Successful in 11m48s
CI / e2e_tests (push) Successful in 20m13s
CI / status-check (push) Successful in 1s
CI / benchmark-publish (push) Successful in 28m20s
CI / benchmark-regression (push) Has been skipped
CI / benchmark-regression (pull_request) Successful in 54m52s
fix(cli): derive actor name from config file instead of positional argument
Remove the <NAME> positional argument from `actor add` command. The actor
name is now derived from the `name` field inside the config YAML file, per
the specification: `agents actor add (--config|-c) <FILE> [--update]`.
Updated all BDD and integration tests to pass name via config file.

ISSUES CLOSED: #914
2026-03-30 18:27:59 +00:00

174 lines
5.1 KiB
Python

"""ASV benchmarks for Actor CLI command throughput.
Measures the performance of:
- Actor add (config parse + validate)
- Actor list rendering (rich / json / yaml / plain)
- Actor show rendering (rich / json / yaml / plain)
- Actor remove
"""
from __future__ import annotations
import importlib
import json
import os
import sys
import tempfile
from pathlib import Path
from typing import Any
from unittest.mock import MagicMock, patch
# Ensure the local *source* tree is importable even when ASV has an
# older build of the package installed.
_SRC = str(Path(__file__).resolve().parents[1] / "src")
if _SRC not in sys.path:
sys.path.insert(0, _SRC)
import cleveragents # noqa: E402
importlib.reload(cleveragents)
from typer.testing import CliRunner # noqa: E402
from cleveragents.cli.commands.actor import app as actor_app # noqa: E402
from cleveragents.domain.models.core.actor import Actor # noqa: E402
_VALID_CONFIG = {
"name": "local/bench",
"provider": "openai",
"model": "gpt-4",
"temperature": 0.5,
"max_tokens": 256,
}
_runner = CliRunner()
def _mock_actor(
name: str = "local/bench-actor",
provider: str = "openai",
model: str = "gpt-4",
config: dict[str, Any] | None = None,
) -> Actor:
blob = config or {"provider": provider, "model": model}
return Actor(
id=1,
name=name,
provider=provider,
model=model,
config_blob=blob,
config_hash=Actor.compute_hash(blob),
unsafe=False,
is_built_in=False,
is_default=False,
)
class ActorCLIAddSuite:
"""Benchmark actor add --config throughput."""
def setup(self) -> None:
fd, self._path = tempfile.mkstemp(suffix=".json")
with os.fdopen(fd, "w") as fh:
json.dump(_VALID_CONFIG, fh)
self._mock_registry = MagicMock()
self._mock_registry.upsert_actor.return_value = _mock_actor()
self._patcher = patch(
"cleveragents.cli.commands.actor._get_services",
return_value=(MagicMock(), self._mock_registry),
)
self._patcher.start()
def teardown(self) -> None:
self._patcher.stop()
Path(self._path).unlink(missing_ok=True)
def time_add_from_config(self) -> None:
"""Benchmark add --config end-to-end."""
_runner.invoke(actor_app, ["add", "--config", self._path])
class ActorCLIListSuite:
"""Benchmark actor list throughput."""
def setup(self) -> None:
self._mock_registry = MagicMock()
self._mock_registry.list_actors.return_value = [
_mock_actor(f"local/actor-{i}") for i in range(50)
]
self._patcher = patch(
"cleveragents.cli.commands.actor._get_services",
return_value=(MagicMock(), self._mock_registry),
)
self._patcher.start()
def teardown(self) -> None:
self._patcher.stop()
def time_list_rich(self) -> None:
"""Benchmark listing actors (rich default)."""
_runner.invoke(actor_app, ["list"])
def time_list_json(self) -> None:
"""Benchmark listing actors (json format)."""
_runner.invoke(actor_app, ["list", "--format", "json"])
def time_list_yaml(self) -> None:
"""Benchmark listing actors (yaml format)."""
_runner.invoke(actor_app, ["list", "--format", "yaml"])
def time_list_plain(self) -> None:
"""Benchmark listing actors (plain format)."""
_runner.invoke(actor_app, ["list", "--format", "plain"])
class ActorCLIShowSuite:
"""Benchmark actor show throughput."""
def setup(self) -> None:
self._mock_registry = MagicMock()
self._mock_registry.get_actor.return_value = _mock_actor()
self._patcher = patch(
"cleveragents.cli.commands.actor._get_services",
return_value=(MagicMock(), self._mock_registry),
)
self._patcher.start()
def teardown(self) -> None:
self._patcher.stop()
def time_show_rich(self) -> None:
"""Benchmark showing actor (rich default)."""
_runner.invoke(actor_app, ["show", "local/bench-actor"])
def time_show_json(self) -> None:
"""Benchmark showing actor (json format)."""
_runner.invoke(actor_app, ["show", "local/bench-actor", "--format", "json"])
def time_show_yaml(self) -> None:
"""Benchmark showing actor (yaml format)."""
_runner.invoke(actor_app, ["show", "local/bench-actor", "--format", "yaml"])
def time_show_plain(self) -> None:
"""Benchmark showing actor (plain format)."""
_runner.invoke(actor_app, ["show", "local/bench-actor", "--format", "plain"])
class ActorCLIRemoveSuite:
"""Benchmark actor remove throughput."""
def setup(self) -> None:
self._mock_registry = MagicMock()
self._patcher = patch(
"cleveragents.cli.commands.actor._get_services",
return_value=(MagicMock(), self._mock_registry),
)
self._patcher.start()
def teardown(self) -> None:
self._patcher.stop()
def time_remove(self) -> None:
"""Benchmark removing an actor."""
_runner.invoke(actor_app, ["remove", "local/bench-actor"])