f48eb5a05f
CI / benchmark-publish (pull_request) Has been skipped
CI / lint (pull_request) Successful in 15s
CI / quality (pull_request) Successful in 19s
CI / build (pull_request) Successful in 24s
CI / security (pull_request) Successful in 34s
CI / typecheck (pull_request) Successful in 43s
CI / integration_tests (pull_request) Successful in 2m37s
CI / unit_tests (pull_request) Successful in 6m12s
CI / docker (pull_request) Successful in 1m1s
CI / benchmark-regression (pull_request) Successful in 15m33s
CI / coverage (pull_request) Successful in 21m54s
Implement `agents repl` command providing an interactive read-eval-print loop that dispatches to existing CLI commands without the `agents` prefix. Features: - Command dispatch via existing Typer app - readline history with --no-history opt-out (default: ~/.cleveragents/history) - Tab-completion for all CLI commands and built-in commands - !! last-command repetition - Prompt context from CLEVERAGENTS_PROJECT / CLEVERAGENTS_PLAN env vars - Ctrl+C (continue) and Ctrl+D (exit) signal handling - Multi-line input with \ continuation - :help and :exit/:quit built-in commands Test coverage: - 15 Behave scenarios (features/repl.feature) - 10 Robot Framework smoke tests (robot/repl_smoke.robot) - ASV benchmark suite (benchmarks/repl_bench.py) - All nox sessions pass: lint, typecheck, unit_tests, integration_tests - Coverage: 97.2% (threshold: 97%)
105 lines
3.2 KiB
Python
105 lines
3.2 KiB
Python
"""Benchmarks for CleverAgents REPL startup and helpers."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
from io import StringIO
|
|
from pathlib import Path
|
|
from unittest.mock import patch
|
|
|
|
try:
|
|
from cleveragents.cli.commands.repl import (
|
|
_get_prompt_context,
|
|
_setup_completer,
|
|
dispatch_command,
|
|
run_repl,
|
|
)
|
|
except ModuleNotFoundError:
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
from cleveragents.cli.commands.repl import (
|
|
_get_prompt_context,
|
|
_setup_completer,
|
|
dispatch_command,
|
|
run_repl,
|
|
)
|
|
|
|
|
|
class _FakeInput:
|
|
"""Feed predetermined lines then raise ``EOFError``."""
|
|
|
|
def __init__(self, lines: list[str]) -> None:
|
|
self._lines = list(lines)
|
|
self._idx = 0
|
|
|
|
def __call__(self, prompt: str = "") -> str:
|
|
if self._idx >= len(self._lines):
|
|
raise EOFError
|
|
line = self._lines[self._idx]
|
|
self._idx += 1
|
|
return line
|
|
|
|
|
|
def _run_repl_silent(lines: list[str]) -> int:
|
|
"""Run REPL with mocked console and input; return exit code."""
|
|
from rich.console import Console
|
|
|
|
buf = StringIO()
|
|
console = Console(file=buf, no_color=True, width=200)
|
|
fake = _FakeInput(lines)
|
|
with (
|
|
patch("cleveragents.cli.commands.repl._console", console),
|
|
patch("builtins.input", fake),
|
|
):
|
|
return run_repl(no_history=True)
|
|
|
|
|
|
class TimeSuite:
|
|
"""Measure REPL startup and helper latency."""
|
|
|
|
def time_prompt_context_default(self) -> None:
|
|
"""Benchmark ``_get_prompt_context`` with no env vars."""
|
|
old_proj = os.environ.pop("CLEVERAGENTS_PROJECT", None)
|
|
old_plan = os.environ.pop("CLEVERAGENTS_PLAN", None)
|
|
try:
|
|
_get_prompt_context()
|
|
finally:
|
|
if old_proj is not None:
|
|
os.environ["CLEVERAGENTS_PROJECT"] = old_proj
|
|
if old_plan is not None:
|
|
os.environ["CLEVERAGENTS_PLAN"] = old_plan
|
|
|
|
def time_prompt_context_with_vars(self) -> None:
|
|
"""Benchmark ``_get_prompt_context`` with project and plan set."""
|
|
old_proj = os.environ.get("CLEVERAGENTS_PROJECT")
|
|
old_plan = os.environ.get("CLEVERAGENTS_PLAN")
|
|
os.environ["CLEVERAGENTS_PROJECT"] = "bench-proj"
|
|
os.environ["CLEVERAGENTS_PLAN"] = "bench-plan"
|
|
try:
|
|
_get_prompt_context()
|
|
finally:
|
|
if old_proj is None:
|
|
os.environ.pop("CLEVERAGENTS_PROJECT", None)
|
|
else:
|
|
os.environ["CLEVERAGENTS_PROJECT"] = old_proj
|
|
if old_plan is None:
|
|
os.environ.pop("CLEVERAGENTS_PLAN", None)
|
|
else:
|
|
os.environ["CLEVERAGENTS_PLAN"] = old_plan
|
|
|
|
def time_setup_completer(self) -> None:
|
|
"""Benchmark installing the readline completer."""
|
|
_setup_completer()
|
|
|
|
def time_repl_immediate_eof(self) -> None:
|
|
"""Benchmark REPL startup → immediate EOF exit."""
|
|
_run_repl_silent([])
|
|
|
|
def time_repl_help_then_exit(self) -> None:
|
|
"""Benchmark REPL: ``:help`` then exit."""
|
|
_run_repl_silent([":help"])
|
|
|
|
def time_dispatch_version(self) -> None:
|
|
"""Benchmark ``dispatch_command(["--version"])``."""
|
|
dispatch_command(["--version"])
|