Source code for ralph.agents.builtin_spec
"""Single declarative source for the 7 built-in agent declarations.
The :class:`BuiltinAgentSpec` dataclass mirrors the kwargs accepted by
:func:`ralph.agents.registration.register_agent_support` and the legacy
:class:`AgentSupport.from_registration_kwargs` so the 7 built-in entries
in :mod:`ralph.agents.builtin` can be expressed as a single declarative
row per agent, instead of repeating the kwargs across seven function calls.
Use :meth:`BuiltinAgentSpec.to_support` to materialize the dataclass into
an :class:`AgentSupport` instance. The resulting ``is_builtin`` flag is
always ``True`` so the catalog can treat these entries as reserved.
"""
from __future__ import annotations
import dataclasses
from dataclasses import dataclass
from typing import TYPE_CHECKING, cast
from ralph.agents.support import AgentSupport
from ralph.config.enums import AgentTransport, JsonParserType
if TYPE_CHECKING:
from collections.abc import Callable
from ralph.agents._contracts import StrategyFactory
from ralph.agents.parsers.base import AgentParser
# Fields that are NOT forwarded to ``AgentSupport.from_registration_kwargs``
# via **kwargs because they are passed as positional / named arguments by
# :meth:`BuiltinAgentSpec.to_support`. Kept as a frozenset so the surface
# is explicit and future built-in agent additions do not silently break
# the 7-entry frozen contract pinned by
# ``test_agents/test_builtin_spec_consolidation.py``.
_BUILTIN_SPEC_POSITIONAL_FIELDS: frozenset[str] = frozenset(
{"transport", "parser_factory", "strategy_factory"}
)
[docs]
@dataclass(frozen=True, slots=True)
class BuiltinAgentSpec:
"""Declarative description of one built-in agent.
Attributes:
transport: Transport enum value.
parser_factory: Callable returning a parser instance.
strategy_factory: Callable returning an execution strategy instance.
json_parser: Parser type token.
cmd: Executable command; defaults to ``name`` on materialization.
output_flag: Optional output format flag.
yolo_flag: Optional autonomous flag string.
verbose_flag: Optional verbose flag string.
can_commit: Whether the agent can run git commit.
model_flag: Optional model/provider flag.
print_flag: Optional print flag.
streaming_flag: Optional streaming flag.
session_flag: Optional session continuation flag template.
display_name: Human-readable display name.
interactive: Whether the agent is interactive (PTY).
subagent_capability: Whether the agent exposes usable sub-agent tooling.
no_default_session_flag: When True, suppress the default
``--resume {}`` session template that would otherwise be set
by :meth:`AgentSupport.from_registration_kwargs` for
interactive agents. Used for agy.
"""
transport: AgentTransport
parser_factory: Callable[[], AgentParser]
strategy_factory: StrategyFactory
json_parser: JsonParserType = JsonParserType.GENERIC
cmd: str | None = None
output_flag: str | None = None
yolo_flag: str | None = None
verbose_flag: str | None = None
can_commit: bool = False
model_flag: str | None = None
print_flag: str | None = None
streaming_flag: str | None = None
session_flag: str | None = None
display_name: str | None = None
interactive: bool = False
subagent_capability: bool | None = None
no_default_session_flag: bool = False
[docs]
def to_support(self, name: str) -> AgentSupport:
"""Materialize the dataclass into an :class:`AgentSupport`.
Forwards every dataclass field as a keyword argument to
:meth:`AgentSupport.from_registration_kwargs` so future
BuiltinAgentSpec additions do not require updating two parallel
kwarg lists. ``is_builtin=True`` is always set.
Args:
name: Agent name to assign to the resulting support.
Returns:
The materialized :class:`AgentSupport` with ``is_builtin=True``.
"""
asdict_result: dict[str, object] = cast(
"dict[str, object]",
dataclasses.asdict(self),
)
kwargs: dict[str, object] = {
field: value
for field, value in asdict_result.items()
if field not in _BUILTIN_SPEC_POSITIONAL_FIELDS
}
return AgentSupport.from_registration_kwargs(
name,
transport=self.transport,
parser_factory=self.parser_factory,
strategy_factory=self.strategy_factory,
is_builtin=True,
**kwargs, # type: ignore[arg-type] # reason: autogenerated code has no type support, see docs/agents/type-ignore-policy.md#autogenerated-code
)