refactor: replace 'convo' naming with 'conversation' (#10473)

Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
Rohit Malhotra 2025-08-18 15:10:32 -04:00 committed by GitHub
parent baf2cc5c7e
commit 3660933d59
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
21 changed files with 109 additions and 99 deletions

View File

@ -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

View File

@ -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()

View File

@ -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(

View File

@ -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
)

View File

@ -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), (

View File

@ -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(),

View File

@ -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,

View File

@ -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,
)

View File

@ -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

View File

@ -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:

View File

@ -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,

View File

@ -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,
)

View File

@ -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

View File

@ -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

View File

@ -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,
)

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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',

View File

@ -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

View File

@ -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..',
)