diff --git a/openhands/cli/main.py b/openhands/cli/main.py index 0c7cf49621..bf9975b52b 100644 --- a/openhands/cli/main.py +++ b/openhands/cli/main.py @@ -83,7 +83,7 @@ from openhands.microagent.microagent import BaseMicroagent from openhands.runtime import get_runtime_cls from openhands.runtime.base import Runtime from openhands.storage.settings.file_settings_store import FileSettingsStore -from openhands.utils.utils import create_registry_and_convo_stats +from openhands.utils.utils import create_registry_and_conversation_stats async def cleanup_session( @@ -148,7 +148,7 @@ async def run_session( None, display_initialization_animation, 'Initializing...', is_loaded ) - llm_registry, convo_stats, config = create_registry_and_convo_stats( + llm_registry, conversation_stats, config = create_registry_and_conversation_stats( config, sid, None, @@ -169,7 +169,9 @@ async def run_session( runtime.subscribe_to_shell_stream(stream_to_console) - controller, initial_state = create_controller(agent, runtime, config, convo_stats) + controller, initial_state = create_controller( + agent, runtime, config, conversation_stats + ) event_stream = runtime.event_stream diff --git a/openhands/controller/agent_controller.py b/openhands/controller/agent_controller.py index b6c52708c9..cc77a4e456 100644 --- a/openhands/controller/agent_controller.py +++ b/openhands/controller/agent_controller.py @@ -109,7 +109,7 @@ class AgentController: self, agent: Agent, event_stream: EventStream, - convo_stats: ConversationStats, + conversation_stats: ConversationStats, iteration_delta: int, budget_per_task_delta: float | None = None, agent_to_llm_config: dict[str, LLMConfig] | None = None, @@ -149,7 +149,7 @@ class AgentController: self.agent = agent self.headless_mode = headless_mode self.is_delegate = is_delegate - self.convo_stats = convo_stats + self.conversation_stats = conversation_stats # the event stream must be set before maybe subscribing to it self.event_stream = event_stream @@ -165,7 +165,7 @@ class AgentController: # state from the previous session, state from a parent agent, or a fresh state self.set_initial_state( state=initial_state, - convo_stats=convo_stats, + conversation_stats=conversation_stats, max_iterations=iteration_delta, max_budget_per_task=budget_per_task_delta, confirmation_mode=confirmation_mode, @@ -687,7 +687,7 @@ class AgentController: user_id=self.user_id, agent=delegate_agent, event_stream=self.event_stream, - convo_stats=self.convo_stats, + conversation_stats=self.conversation_stats, iteration_delta=self._initial_max_iterations, budget_per_task_delta=self._initial_max_budget_per_task, agent_to_llm_config=self.agent_to_llm_config, @@ -951,7 +951,7 @@ class AgentController: def set_initial_state( self, state: State | None, - convo_stats: ConversationStats, + conversation_stats: ConversationStats, max_iterations: int, max_budget_per_task: float | None, confirmation_mode: bool = False, @@ -959,7 +959,7 @@ class AgentController: self.state_tracker.set_initial_state( self.id, state, - convo_stats, + conversation_stats, max_iterations, max_budget_per_task, confirmation_mode, @@ -1000,7 +1000,7 @@ class AgentController: action: The action to attach metrics to """ # Get metrics from agent LLM - metrics = self.convo_stats.get_combined_metrics() + metrics = self.conversation_stats.get_combined_metrics() # Create a clean copy with only the fields we want to keep clean_metrics = Metrics() diff --git a/openhands/controller/state/state.py b/openhands/controller/state/state.py index 4f9ca24a1f..e3690a2e53 100644 --- a/openhands/controller/state/state.py +++ b/openhands/controller/state/state.py @@ -85,7 +85,7 @@ class State: limit_increase_amount=100, current_value=0, max_value=100 ) ) - convo_stats: ConversationStats | None = None + conversation_stats: ConversationStats | None = None budget_flag: BudgetControlFlag | None = None confirmation_mode: bool = False history: list[Event] = field(default_factory=list) @@ -122,8 +122,8 @@ class State: def save_to_session( self, sid: str, file_store: FileStore, user_id: str | None ) -> None: - convo_stats = self.convo_stats - self.convo_stats = None # Don't save convo stats, handles itself + conversation_stats = self.conversation_stats + self.conversation_stats = None # Don't save conversation stats, handles itself pickled = pickle.dumps(self) logger.debug(f'Saving state to session {sid}:{self.agent_state}') @@ -144,7 +144,7 @@ class State: logger.error(f'Failed to save state to session: {e}') raise e - self.convo_stats = convo_stats # restore reference + self.conversation_stats = conversation_stats # restore reference @staticmethod def restore_from_session( diff --git a/openhands/controller/state/state_tracker.py b/openhands/controller/state/state_tracker.py index c3aad9effc..4813ec798e 100644 --- a/openhands/controller/state/state_tracker.py +++ b/openhands/controller/state/state_tracker.py @@ -51,7 +51,7 @@ class StateTracker: self, id: str, state: State | None, - convo_stats: ConversationStats, + conversation_stats: ConversationStats, max_iterations: int, max_budget_per_task: float | None, confirmation_mode: bool = False, @@ -74,7 +74,7 @@ class StateTracker: session_id=id.removesuffix('-delegate'), user_id=self.user_id, inputs={}, - convo_stats=convo_stats, + conversation_stats=conversation_stats, iteration_flag=IterationControlFlag( limit_increase_amount=max_iterations, current_value=0, @@ -99,7 +99,7 @@ class StateTracker: if self.state.start_id <= -1: self.state.start_id = 0 - state.convo_stats = convo_stats + state.conversation_stats = conversation_stats def _init_history(self, event_stream: EventStream) -> None: """Initializes the agent's history from the event stream. @@ -248,8 +248,8 @@ class StateTracker: if self.sid and self.file_store: self.state.save_to_session(self.sid, self.file_store, self.user_id) - if self.state.convo_stats: - self.state.convo_stats.save_metrics() + if self.state.conversation_stats: + self.state.conversation_stats.save_metrics() def run_control_flags(self): """Performs one step of the control flags""" @@ -262,7 +262,7 @@ class StateTracker: Budget flag will monitor for when budget is exceeded """ # Sync cost across all llm services from llm registry - if self.state.budget_flag and self.state.convo_stats: + if self.state.budget_flag and self.state.conversation_stats: self.state.budget_flag.current_value = ( - self.state.convo_stats.get_combined_metrics().accumulated_cost + self.state.conversation_stats.get_combined_metrics().accumulated_cost ) diff --git a/openhands/core/main.py b/openhands/core/main.py index ff944a31ea..f2555766f8 100644 --- a/openhands/core/main.py +++ b/openhands/core/main.py @@ -36,7 +36,7 @@ from openhands.mcp import add_mcp_tools_to_agent from openhands.memory.memory import Memory from openhands.runtime.base import Runtime from openhands.utils.async_utils import call_async_from_sync -from openhands.utils.utils import create_registry_and_convo_stats +from openhands.utils.utils import create_registry_and_conversation_stats class FakeUserResponseFunc(Protocol): @@ -96,7 +96,7 @@ async def run_controller( """ sid = sid or generate_sid(config) - llm_registry, convo_stats, config = create_registry_and_convo_stats( + llm_registry, conversation_stats, config = create_registry_and_conversation_stats( config, sid, None, @@ -163,7 +163,7 @@ async def run_controller( ) controller, initial_state = create_controller( - agent, runtime, config, convo_stats, replay_events=replay_events + agent, runtime, config, conversation_stats, replay_events=replay_events ) assert isinstance(initial_user_action, Action), ( diff --git a/openhands/core/setup.py b/openhands/core/setup.py index 26917648fa..6835bca4f4 100644 --- a/openhands/core/setup.py +++ b/openhands/core/setup.py @@ -218,7 +218,7 @@ def create_controller( agent: Agent, runtime: Runtime, config: OpenHandsConfig, - convo_stats: ConversationStats, + conversation_stats: ConversationStats, headless_mode: bool = True, replay_events: list[Event] | None = None, ) -> tuple[AgentController, State | None]: @@ -236,7 +236,7 @@ def create_controller( controller = AgentController( agent=agent, - convo_stats=convo_stats, + conversation_stats=conversation_stats, iteration_delta=config.max_iterations, budget_per_task_delta=config.max_budget_per_task, agent_to_llm_config=config.get_agent_to_llm_config_map(), diff --git a/openhands/server/conversation_manager/docker_nested_conversation_manager.py b/openhands/server/conversation_manager/docker_nested_conversation_manager.py index 107fd11253..e53953f7dd 100644 --- a/openhands/server/conversation_manager/docker_nested_conversation_manager.py +++ b/openhands/server/conversation_manager/docker_nested_conversation_manager.py @@ -42,7 +42,7 @@ from openhands.storage.files import FileStore from openhands.storage.locations import get_conversation_dir from openhands.utils.async_utils import call_sync_from_async from openhands.utils.import_utils import get_impl -from openhands.utils.utils import create_registry_and_convo_stats +from openhands.utils.utils import create_registry_and_conversation_stats @dataclass @@ -486,14 +486,14 @@ class DockerNestedConversationManager(ConversationManager): user_id, sid, self.config ) - llm_registry, convo_stats, config = create_registry_and_convo_stats( - config, sid, user_id, settings + llm_registry, conversation_stats, config = ( + create_registry_and_conversation_stats(config, sid, user_id, settings) ) session = Session( sid=sid, llm_registry=llm_registry, - convo_stats=convo_stats, + conversation_stats=conversation_stats, file_store=self.file_store, config=config, sio=self.sio, diff --git a/openhands/server/conversation_manager/standalone_conversation_manager.py b/openhands/server/conversation_manager/standalone_conversation_manager.py index 2e07b187ee..12823ed46e 100644 --- a/openhands/server/conversation_manager/standalone_conversation_manager.py +++ b/openhands/server/conversation_manager/standalone_conversation_manager.py @@ -39,7 +39,7 @@ from openhands.utils.conversation_summary import ( ) from openhands.utils.import_utils import get_impl from openhands.utils.shutdown_listener import should_continue -from openhands.utils.utils import create_registry_and_convo_stats +from openhands.utils.utils import create_registry_and_conversation_stats from .conversation_manager import ConversationManager @@ -335,15 +335,15 @@ class StandaloneConversationManager(ConversationManager): ) await self.close_session(oldest_conversation_id) - llm_registry, convo_stats, config = create_registry_and_convo_stats( - self.config, sid, user_id, settings + llm_registry, conversation_stats, config = ( + create_registry_and_conversation_stats(self.config, sid, user_id, settings) ) session = Session( sid=sid, file_store=self.file_store, config=config, llm_registry=llm_registry, - convo_stats=convo_stats, + conversation_stats=conversation_stats, sio=self.sio, user_id=user_id, ) diff --git a/openhands/server/services/conversation_service.py b/openhands/server/services/conversation_service.py index 1ade6fad76..2f6d35f82f 100644 --- a/openhands/server/services/conversation_service.py +++ b/openhands/server/services/conversation_service.py @@ -53,7 +53,7 @@ async def initialize_conversation( conversation_title = get_default_conversation_title(conversation_id) logger.info(f'Saving metadata for conversation {conversation_id}') - convo_metadata = ConversationMetadata( + conversation_metadata = ConversationMetadata( trigger=conversation_trigger, conversation_id=conversation_id, title=conversation_title, @@ -63,12 +63,12 @@ async def initialize_conversation( git_provider=git_provider, ) - await conversation_store.save_metadata(convo_metadata) - return convo_metadata + await conversation_store.save_metadata(conversation_metadata) + return conversation_metadata try: - convo_metadata = await conversation_store.get_metadata(conversation_id) - return convo_metadata + conversation_metadata = await conversation_store.get_metadata(conversation_id) + return conversation_metadata except Exception: pass @@ -83,7 +83,7 @@ async def start_conversation( image_urls: list[str] | None, replay_json: str | None, conversation_id: str, - convo_metadata: ConversationMetadata, + conversation_metadata: ConversationMetadata, conversation_instructions: str | None, mcp_config: MCPConfig | None = None, ) -> AgentLoopInfo: @@ -92,7 +92,7 @@ async def start_conversation( extra={ 'signal': 'create_conversation', 'user_id': user_id, - 'trigger': convo_metadata.trigger, + 'trigger': conversation_metadata.trigger, }, ) logger.info('Loading settings') @@ -119,10 +119,10 @@ async def start_conversation( raise MissingSettingsError('Settings not found') session_init_args['git_provider_tokens'] = git_provider_tokens - session_init_args['selected_repository'] = convo_metadata.selected_repository + session_init_args['selected_repository'] = conversation_metadata.selected_repository session_init_args['custom_secrets'] = custom_secrets - session_init_args['selected_branch'] = convo_metadata.selected_branch - session_init_args['git_provider'] = convo_metadata.git_provider + session_init_args['selected_branch'] = conversation_metadata.selected_branch + session_init_args['git_provider'] = conversation_metadata.git_provider session_init_args['conversation_instructions'] = conversation_instructions if mcp_config: session_init_args['mcp_config'] = mcp_config diff --git a/openhands/server/services/conversation_stats.py b/openhands/server/services/conversation_stats.py index 0f0354e65e..65522fdf30 100644 --- a/openhands/server/services/conversation_stats.py +++ b/openhands/server/services/conversation_stats.py @@ -6,7 +6,9 @@ from openhands.core.logger import openhands_logger as logger from openhands.llm.llm_registry import RegistryEvent from openhands.llm.metrics import Metrics from openhands.storage.files import FileStore -from openhands.storage.locations import get_conversation_stats_filename +from openhands.storage.locations import ( + get_conversation_stats_filename, +) class ConversationStats: diff --git a/openhands/server/session/agent_session.py b/openhands/server/session/agent_session.py index 0a9acf6033..ec441f6f03 100644 --- a/openhands/server/session/agent_session.py +++ b/openhands/server/session/agent_session.py @@ -67,7 +67,7 @@ class AgentSession: sid: str, file_store: FileStore, llm_registry: LLMRegistry, - convo_stats: ConversationStats, + conversation_stats: ConversationStats, status_callback: Callable | None = None, user_id: str | None = None, ) -> None: @@ -86,7 +86,7 @@ class AgentSession: extra={'session_id': sid, 'user_id': user_id} ) self.llm_registry = llm_registry - self.convo_stats = convo_stats + self.conversation_stats = conversation_stats async def start( self, @@ -450,7 +450,7 @@ class AgentSession: user_id=self.user_id, file_store=self.file_store, event_stream=self.event_stream, - convo_stats=self.convo_stats, + conversation_stats=self.conversation_stats, agent=agent, iteration_delta=int(max_iterations), budget_per_task_delta=max_budget_per_task, diff --git a/openhands/server/session/session.py b/openhands/server/session/session.py index fe20df3558..0137e010ed 100644 --- a/openhands/server/session/session.py +++ b/openhands/server/session/session.py @@ -55,7 +55,7 @@ class Session: sid: str, config: OpenHandsConfig, llm_registry: LLMRegistry, - convo_stats: ConversationStats, + conversation_stats: ConversationStats, file_store: FileStore, sio: socketio.AsyncServer | None, user_id: str | None = None, @@ -66,12 +66,12 @@ class Session: self.file_store = file_store self.logger = OpenHandsLoggerAdapter(extra={'session_id': sid}) self.llm_registry = llm_registry - self.convo_stats = convo_stats + self.conversation_stats = conversation_stats self.agent_session = AgentSession( sid, file_store, llm_registry=self.llm_registry, - convo_stats=convo_stats, + conversation_stats=conversation_stats, status_callback=self.queue_status_message, user_id=user_id, ) diff --git a/openhands/utils/conversation_summary.py b/openhands/utils/conversation_summary.py index b20fdafe66..f281fe1f5f 100644 --- a/openhands/utils/conversation_summary.py +++ b/openhands/utils/conversation_summary.py @@ -51,7 +51,7 @@ async def generate_conversation_title( ] title = llm_registry.request_extraneous_completion( - 'convo_title_creator', llm_config, messages + 'conversation_title_creator', llm_config, messages ) # Ensure the title isn't too long diff --git a/openhands/utils/utils.py b/openhands/utils/utils.py index 7abd386f31..db24201bb0 100644 --- a/openhands/utils/utils.py +++ b/openhands/utils/utils.py @@ -19,7 +19,7 @@ def setup_llm_config(config: OpenHandsConfig, settings: Settings) -> OpenHandsCo return config -def create_registry_and_convo_stats( +def create_registry_and_conversation_stats( config: OpenHandsConfig, sid: str, user_id: str | None, @@ -32,6 +32,6 @@ def create_registry_and_convo_stats( agent_cls = user_settings.agent if user_settings else None llm_registry = LLMRegistry(user_config, agent_cls) file_store = get_file_store(user_config.file_store, user_config.file_store_path) - convo_stats = ConversationStats(file_store, sid, user_id) - llm_registry.subscribe(convo_stats.register_llm) - return llm_registry, convo_stats, user_config + conversation_stats = ConversationStats(file_store, sid, user_id) + llm_registry.subscribe(conversation_stats.register_llm) + return llm_registry, conversation_stats, user_config diff --git a/tests/unit/test_agent_controller.py b/tests/unit/test_agent_controller.py index 1777f4959b..99c945cacb 100644 --- a/tests/unit/test_agent_controller.py +++ b/tests/unit/test_agent_controller.py @@ -171,7 +171,7 @@ async def test_set_agent_state(mock_agent_with_stats, mock_event_stream): controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -192,7 +192,7 @@ async def test_on_event_message_action(mock_agent_with_stats, mock_event_stream) controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -214,7 +214,7 @@ async def test_on_event_change_agent_state_action( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -238,7 +238,7 @@ async def test_react_to_exception( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, status_callback=mock_status_callback, iteration_delta=10, sid='test', @@ -263,7 +263,7 @@ async def test_react_to_content_policy_violation( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, status_callback=mock_status_callback, iteration_delta=10, sid='test', @@ -450,7 +450,7 @@ async def test_max_iterations_extension(mock_agent_with_stats, mock_event_stream controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -481,7 +481,7 @@ async def test_max_iterations_extension(mock_agent_with_stats, mock_event_stream controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -522,7 +522,7 @@ async def test_step_max_budget(mock_agent_with_stats, mock_event_stream): controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, budget_per_task_delta=10, sid='test', @@ -553,7 +553,7 @@ async def test_step_max_budget_headless(mock_agent_with_stats, mock_event_stream controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, budget_per_task_delta=10, sid='test', @@ -598,7 +598,7 @@ async def test_budget_reset_on_continue(mock_agent_with_stats, mock_event_stream controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, budget_per_task_delta=initial_budget, sid='test', @@ -654,7 +654,7 @@ async def test_reset_with_pending_action_no_observation( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -707,7 +707,7 @@ async def test_reset_with_pending_action_stopped_state( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -760,7 +760,7 @@ async def test_reset_with_pending_action_existing_observation( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -806,7 +806,7 @@ async def test_reset_without_pending_action(mock_agent_with_stats, mock_event_st controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -840,7 +840,7 @@ async def test_reset_with_pending_action_no_metadata( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -972,7 +972,7 @@ async def test_notify_on_llm_retry( controller = AgentController( agent=mock_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, status_callback=mock_status_callback, iteration_delta=10, sid='test', @@ -1484,7 +1484,7 @@ async def test_action_metrics_copy(mock_agent_with_stats): controller = AgentController( agent=mock_agent, event_stream=event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -1599,7 +1599,7 @@ async def test_condenser_metrics_included(mock_agent_with_stats, test_event_stre controller = AgentController( agent=mock_agent, event_stream=test_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -1658,7 +1658,7 @@ async def test_first_user_message_with_identical_content( controller = AgentController( agent=mock_agent, event_stream=test_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test', confirmation_mode=False, @@ -1726,7 +1726,7 @@ async def test_agent_controller_processes_null_observation_with_cause( controller = AgentController( agent=mock_agent, event_stream=event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test-session', ) @@ -1802,7 +1802,7 @@ def test_agent_controller_should_step_with_null_observation_cause_zero( controller = AgentController( agent=mock_agent, event_stream=event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, sid='test-session', ) @@ -1828,7 +1828,7 @@ def test_system_message_in_event_stream(mock_agent_with_stats, test_event_stream _ = AgentController( agent=mock_agent, event_stream=test_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=10, ) diff --git a/tests/unit/test_agent_delegation.py b/tests/unit/test_agent_delegation.py index fdb9c9d4d8..469bb13748 100644 --- a/tests/unit/test_agent_delegation.py +++ b/tests/unit/test_agent_delegation.py @@ -175,7 +175,7 @@ async def test_delegation_flow( parent_controller = AgentController( agent=mock_parent_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=1, # Add the required iteration_delta parameter sid='parent', confirmation_mode=False, @@ -250,7 +250,9 @@ async def test_delegation_flow( ) # verify local metrics are accessible via snapshot # Check that the conversation stats has the combined metrics (parent + delegate) - combined_metrics = delegate_controller.state.convo_stats.get_combined_metrics() + combined_metrics = ( + delegate_controller.state.conversation_stats.get_combined_metrics() + ) assert ( combined_metrics.accumulated_cost == 6 # Make sure delegate tracks global cost (2 from parent + 4 from delegate) @@ -303,7 +305,7 @@ async def test_delegate_step_different_states( controller = AgentController( agent=mock_parent_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=1, # Add the required iteration_delta parameter sid='test', confirmation_mode=False, @@ -394,7 +396,7 @@ async def test_delegate_hits_global_limits( parent_controller = AgentController( agent=mock_parent_agent, event_stream=mock_event_stream, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, iteration_delta=1, # Add the required iteration_delta parameter sid='parent', confirmation_mode=False, diff --git a/tests/unit/test_agent_session.py b/tests/unit/test_agent_session.py index e05e69815c..5dc67b1d88 100644 --- a/tests/unit/test_agent_session.py +++ b/tests/unit/test_agent_session.py @@ -86,7 +86,7 @@ async def test_agent_session_start_with_no_state( sid='test-session', file_store=file_store, llm_registry=mock_llm_registry, - convo_stats=mock_conversation_stats, + conversation_stats=mock_conversation_stats, ) # Create a mock runtime and set it up @@ -178,7 +178,7 @@ async def test_agent_session_start_with_restored_state( sid='test-session', file_store=file_store, llm_registry=mock_llm_registry, - convo_stats=mock_conversation_stats, + conversation_stats=mock_conversation_stats, ) # Create a mock runtime and set it up @@ -276,7 +276,7 @@ async def test_metrics_centralization_via_conversation_stats( sid='test-session', file_store=file_store, llm_registry=mock_llm_registry, - convo_stats=mock_conversation_stats, + conversation_stats=mock_conversation_stats, ) # Create a mock runtime and set it up @@ -324,14 +324,16 @@ async def test_metrics_centralization_via_conversation_stats( ) # Verify that the ConversationStats is properly set up - assert session.controller.state.convo_stats is mock_conversation_stats + assert session.controller.state.conversation_stats is mock_conversation_stats # Add some metrics to the agent's LLM (simulating LLM usage) test_cost = 0.05 session.controller.agent.llm.metrics.add_cost(test_cost) # Verify that the cost is reflected in the combined metrics from the conversation stats - combined_metrics = session.controller.state.convo_stats.get_combined_metrics() + combined_metrics = ( + session.controller.state.conversation_stats.get_combined_metrics() + ) assert combined_metrics.accumulated_cost == test_cost # Add more cost to simulate additional LLM usage @@ -339,7 +341,9 @@ async def test_metrics_centralization_via_conversation_stats( session.controller.agent.llm.metrics.add_cost(additional_cost) # Verify the combined metrics reflect the total cost - combined_metrics = session.controller.state.convo_stats.get_combined_metrics() + combined_metrics = ( + session.controller.state.conversation_stats.get_combined_metrics() + ) assert combined_metrics.accumulated_cost == test_cost + additional_cost # Reset the agent and verify that combined metrics are preserved @@ -347,7 +351,7 @@ async def test_metrics_centralization_via_conversation_stats( # Combined metrics should still be preserved after agent reset assert ( - session.controller.state.convo_stats.get_combined_metrics().accumulated_cost + session.controller.state.conversation_stats.get_combined_metrics().accumulated_cost == test_cost + additional_cost ) @@ -366,7 +370,7 @@ async def test_budget_control_flag_syncs_with_metrics( sid='test-session', file_store=file_store, llm_registry=mock_llm_registry, - convo_stats=mock_conversation_stats, + conversation_stats=mock_conversation_stats, ) # Create a mock runtime and set it up @@ -466,7 +470,7 @@ def test_override_provider_tokens_with_custom_secret( sid='test-session', file_store=file_store, llm_registry=mock_llm_registry, - convo_stats=mock_conversation_stats, + conversation_stats=mock_conversation_stats, ) # Create test data diff --git a/tests/unit/test_mcp_config.py b/tests/unit/test_mcp_config.py index e1455bc4ea..8ac78e1a7c 100644 --- a/tests/unit/test_mcp_config.py +++ b/tests/unit/test_mcp_config.py @@ -431,7 +431,7 @@ async def test_session_preserves_env_mcp_config(monkeypatch): config=config, sio=AsyncMock(), llm_registry=LLMRegistry(config=OpenHandsConfig()), - convo_stats=ConversationStats(None, 'test-sid', None), + conversation_stats=ConversationStats(None, 'test-sid', None), ) # Create empty settings diff --git a/tests/unit/test_mcp_tool_timeout_stall.py b/tests/unit/test_mcp_tool_timeout_stall.py index e5ce5a72e0..209cf4fa46 100644 --- a/tests/unit/test_mcp_tool_timeout_stall.py +++ b/tests/unit/test_mcp_tool_timeout_stall.py @@ -38,7 +38,7 @@ class MockLLM: @pytest.fixture -def convo_stats(): +def conversation_stats(): return ConversationStats(None, 'convo-id', None) @@ -61,7 +61,7 @@ class MockAgent(Agent): @pytest.mark.asyncio -async def test_mcp_tool_timeout_error_handling(convo_stats): +async def test_mcp_tool_timeout_error_handling(conversation_stats): """Test that verifies MCP tool timeout errors are properly handled and returned as observations.""" # Create a mock MCPClient mock_client = mock.MagicMock(spec=MCPClient) @@ -100,7 +100,7 @@ async def test_mcp_tool_timeout_error_handling(convo_stats): controller = AgentController( agent=agent, event_stream=event_stream, - convo_stats=convo_stats, + conversation_stats=conversation_stats, iteration_delta=10, budget_per_task_delta=None, sid='test-session', @@ -150,7 +150,7 @@ async def test_mcp_tool_timeout_error_handling(convo_stats): @pytest.mark.asyncio -async def test_mcp_tool_timeout_agent_continuation(convo_stats): +async def test_mcp_tool_timeout_agent_continuation(conversation_stats): """Test that verifies the agent can continue processing after an MCP tool timeout.""" # Create a mock MCPClient mock_client = mock.MagicMock(spec=MCPClient) @@ -189,7 +189,7 @@ async def test_mcp_tool_timeout_agent_continuation(convo_stats): controller = AgentController( agent=agent, event_stream=event_stream, - convo_stats=convo_stats, + conversation_stats=conversation_stats, iteration_delta=10, budget_per_task_delta=None, sid='test-session', diff --git a/tests/unit/test_memory.py b/tests/unit/test_memory.py index 539e91d880..37b055bc47 100644 --- a/tests/unit/test_memory.py +++ b/tests/unit/test_memory.py @@ -612,7 +612,7 @@ async def test_conversation_instructions_plumbed_to_memory( sid='test-session', file_store=file_store, llm_registry=mock_llm_registry, - convo_stats=ConversationStats(file_store, 'test-session', None), + conversation_stats=ConversationStats(file_store, 'test-session', None), ) # Create a mock runtime and set it up diff --git a/tests/unit/test_session.py b/tests/unit/test_session.py index e9211b6a4f..d31a7cf678 100644 --- a/tests/unit/test_session.py +++ b/tests/unit/test_session.py @@ -65,7 +65,7 @@ async def test_notify_on_llm_retry( file_store=InMemoryFileStore({}), config=config, llm_registry=llm_registry, - convo_stats=conversation_stats, + conversation_stats=conversation_stats, sio=mock_sio, user_id='..uid..', )