Source code for ralph.agents.execution_state.generic_execution_strategy
"""Generic execution strategy for agents."""
from __future__ import annotations
from typing import TYPE_CHECKING
from ._helpers import _non_blank_output_signal
from .agent_execution_state import AgentExecutionState
if TYPE_CHECKING:
from ralph.agents.activity import AgentActivitySignal
from ralph.agents.completion_signals import CompletionSignals
from ralph.process.liveness import LivenessProbe
from ._live_descendant_handle import _LiveDescendantHandle
[docs]
class GenericExecutionStrategy:
"""Default strategy: single-process lifetime, exit 0 is terminal success.
Replicates the behaviour that existed before the session-aware model was
introduced so that Claude/Codex paths are unaffected.
"""
[docs]
def observe_line(self, line: str) -> None:
"""Observe a raw provider line for optional strategy-specific state updates."""
del line
[docs]
def classify_activity_line(self, line: str) -> AgentActivitySignal | None:
"""Classify a raw output line for idle-watchdog activity.
Generic transports treat any non-blank line as activity while rejecting
whitespace-only heartbeats so a process cannot evade the idle deadline
without emitting meaningful provider output.
"""
return _non_blank_output_signal(line)
def classify_quiet(
self,
handle: _LiveDescendantHandle,
liveness_probe: LivenessProbe,
) -> AgentExecutionState:
del liveness_probe
if hasattr(handle, "has_live_descendants"):
try:
if bool(handle.has_live_descendants()):
return AgentExecutionState.WAITING_ON_CHILD
except Exception:
pass
return AgentExecutionState.ACTIVE
def classify_exit(
self,
handle: _LiveDescendantHandle,
completion_signals: CompletionSignals,
liveness_probe: LivenessProbe | None = None,
) -> AgentExecutionState:
del handle, completion_signals, liveness_probe
return AgentExecutionState.TERMINAL_COMPLETE
def supports_session_continuation(self) -> bool:
return False
def supports_completion_enforcement(self) -> bool:
return False