f8f7c1cbfa
Remove the --format/-f flag from the CLI `agents session export` command
to align with spec §1986, which defines the command as JSON-only:
agents session export [(--output|-o) <FILE>] <SESSION_ID>
The --format md (Markdown) option is only specified for the TUI slash
command /session:export --format md, not for the CLI command.
Changes:
- src/cleveragents/cli/commands/session.py: Remove fmt parameter and
Markdown export branch from export_session(); remove unused SessionMessage
import; update docstring to reference spec §1986
- benchmarks/session_model_bench.py: Remove two broken @click.option
decorators that were incorrectly inserted between method definitions
(click not imported, decorators applied to wrong functions, breaks ASV)
- features/tui_session_export_import.feature: Update CLI export scenarios
to reflect JSON-only behavior; add @tdd_issue and @tdd_issue_1451 tags
- features/steps/tui_thought_block_steps.py: Restore original step names
(thought block rendered text should contain) to fix AmbiguousStep conflict
with tui_first_run_steps.py
- features/tui_thought_block.feature: Update step references to match
restored step names
ISSUES CLOSED: #1451
156 lines
4.9 KiB
Python
156 lines
4.9 KiB
Python
"""ASV benchmarks for Session domain model validation and serialization.
|
|
|
|
Measures the performance of:
|
|
- Session model construction (Pydantic validation)
|
|
- SessionMessage construction
|
|
- Session.append_message() auto-sequencing
|
|
- Session.as_cli_dict() serialization
|
|
- Session.as_export_dict() serialization with checksum
|
|
- SessionTokenUsage construction
|
|
- Session.get_messages() with pagination
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import sys
|
|
from pathlib import Path
|
|
|
|
try:
|
|
from cleveragents.domain.models.core.session import (
|
|
MessageRole,
|
|
Session,
|
|
SessionMessage,
|
|
SessionTokenUsage,
|
|
)
|
|
except ModuleNotFoundError:
|
|
sys.path.insert(0, str(Path(__file__).resolve().parents[1] / "src"))
|
|
from cleveragents.domain.models.core.session import (
|
|
MessageRole,
|
|
Session,
|
|
SessionMessage,
|
|
SessionTokenUsage,
|
|
)
|
|
|
|
from ulid import ULID
|
|
|
|
|
|
def _make_session(message_count: int = 0) -> Session:
|
|
"""Create a Session with optional messages for benchmarking."""
|
|
session = Session(session_id=str(ULID()))
|
|
for i in range(message_count):
|
|
session.append_message(MessageRole.USER, f"Benchmark message {i}")
|
|
return session
|
|
|
|
|
|
def _make_message() -> SessionMessage:
|
|
"""Create a fully-populated SessionMessage for benchmarking."""
|
|
return SessionMessage(
|
|
message_id=str(ULID()),
|
|
role=MessageRole.USER,
|
|
content="Benchmark message content",
|
|
sequence=0,
|
|
metadata={"key": "value"},
|
|
)
|
|
|
|
|
|
class SessionValidationSuite:
|
|
"""Benchmark Session model construction (Pydantic validation)."""
|
|
|
|
def time_session_construction(self) -> None:
|
|
"""Benchmark creating a minimal Session object."""
|
|
Session(session_id=str(ULID()))
|
|
|
|
def time_session_with_actor(self) -> None:
|
|
"""Benchmark creating a Session with actor_name."""
|
|
Session(session_id=str(ULID()), actor_name="local/orchestrator")
|
|
|
|
def time_message_construction(self) -> None:
|
|
"""Benchmark creating a SessionMessage."""
|
|
_make_message()
|
|
|
|
def time_tool_message_construction(self) -> None:
|
|
"""Benchmark creating a tool SessionMessage with tool_call_id."""
|
|
SessionMessage(
|
|
message_id=str(ULID()),
|
|
role=MessageRole.TOOL,
|
|
content="Tool result",
|
|
sequence=0,
|
|
tool_call_id="call_123",
|
|
)
|
|
|
|
def time_token_usage_construction(self) -> None:
|
|
"""Benchmark SessionTokenUsage construction."""
|
|
SessionTokenUsage(
|
|
input_tokens=1000,
|
|
output_tokens=500,
|
|
estimated_cost=0.05,
|
|
)
|
|
|
|
|
|
class SessionAppendSuite:
|
|
"""Benchmark Session.append_message() auto-sequencing."""
|
|
|
|
def setup(self) -> None:
|
|
"""Create a session for append benchmarks."""
|
|
self.session = _make_session()
|
|
|
|
def time_append_single_message(self) -> None:
|
|
"""Benchmark appending a single message."""
|
|
self.session.append_message(MessageRole.USER, "Benchmark message")
|
|
|
|
def time_append_10_messages(self) -> None:
|
|
"""Benchmark appending 10 messages sequentially."""
|
|
session = _make_session()
|
|
for i in range(10):
|
|
session.append_message(MessageRole.USER, f"Message {i}")
|
|
|
|
|
|
class SessionSerializationSuite:
|
|
"""Benchmark Session serialization methods."""
|
|
|
|
def setup(self) -> None:
|
|
"""Create a session with messages for serialization benchmarks."""
|
|
self.session = _make_session(message_count=10)
|
|
self.session.link_plan(str(ULID()))
|
|
self.large_session = _make_session(message_count=100)
|
|
|
|
def time_as_cli_dict(self) -> None:
|
|
"""Benchmark Session.as_cli_dict() ordered dict generation."""
|
|
self.session.as_cli_dict()
|
|
|
|
def time_as_export_dict(self) -> None:
|
|
"""Benchmark Session.as_export_dict() with checksum generation."""
|
|
self.session.as_export_dict()
|
|
|
|
def time_as_export_dict_large(self) -> None:
|
|
"""Benchmark export dict for a large session (100 messages)."""
|
|
self.large_session.as_export_dict()
|
|
|
|
def time_model_dump(self) -> None:
|
|
"""Benchmark Pydantic model_dump() serialization."""
|
|
self.session.model_dump()
|
|
|
|
def time_model_dump_json(self) -> None:
|
|
"""Benchmark Pydantic model_dump_json() JSON serialization."""
|
|
self.session.model_dump_json()
|
|
|
|
|
|
class SessionPaginationSuite:
|
|
"""Benchmark Session.get_messages() with pagination."""
|
|
|
|
def setup(self) -> None:
|
|
"""Create a session with many messages for pagination benchmarks."""
|
|
self.session = _make_session(message_count=100)
|
|
|
|
def time_get_all_messages(self) -> None:
|
|
"""Benchmark getting all messages (no limit)."""
|
|
self.session.get_messages()
|
|
|
|
def time_get_first_10(self) -> None:
|
|
"""Benchmark getting first 10 messages."""
|
|
self.session.get_messages(limit=10)
|
|
|
|
def time_get_with_offset(self) -> None:
|
|
"""Benchmark getting messages with offset."""
|
|
self.session.get_messages(limit=10, offset=50)
|