OpenHands icon indicating copy to clipboard operation
OpenHands copied to clipboard

Rename Conversation to ServerConversation and AppConfig to OpenHandsConfig

Open rbren opened this issue 6 months ago • 6 comments

This PR renames the Conversation class in the server directory to ServerConversation and the AppConfig class to OpenHandsConfig throughout the codebase. It also renames the file app_config.py to openhands_config.py and updates all import statements and references accordingly.

Changes include:

  • Renamed Conversation to ServerConversation in server, evaluation, and tests directories
  • Renamed AppConfig to OpenHandsConfig throughout the codebase
  • Renamed app_config.py to openhands_config.py
  • Updated all import statements and references
  • Updated function name load_app_config to load_openhands_config
  • Fixed formatting issues with pre-commit hooks

To run this PR locally, use the following command:

docker run -it --rm   -p 3000:3000   -v /var/run/docker.sock:/var/run/docker.sock   --add-host host.docker.internal:host-gateway   -e SANDBOX_RUNTIME_CONTAINER_IMAGE=docker.all-hands.dev/all-hands-ai/runtime:32c19bd-nikolaik   --name openhands-app-32c19bd   docker.all-hands.dev/all-hands-ai/openhands:32c19bd

rbren avatar May 28 '25 13:05 rbren

@openhands update tehse tests

test_event_stream = EventStream(sid='test', file_store=<openhands.storage.memory.InMemoryFileStore object at 0x7f050b38bce0>, user_id=None, cur_id=6, cache_size=25)

    @pytest.mark.asyncio
    async def test_run_controller_with_context_window_exceeded_without_truncation(
        mock_agent, mock_runtime, mock_memory, test_event_stream
    ):
        """Tests that the controller would quit upon context window exceeded errors without enable_history_truncation ON."""
    
        class StepState:
            def __init__(self):
                self.has_errored = False
    
            def step(self, state: State):
                # If the state has more than one message and we haven't errored yet,
                # throw the context window exceeded error
                if len(state.history) > 3 and not self.has_errored:
                    error = ContextWindowExceededError(
                        message='prompt is too long: 233885 tokens > 200000 maximum',
                        model='',
                        llm_provider='',
                    )
                    self.has_errored = True
                    raise error
    
                return MessageAction(content=f'STEP {len(state.history)}')
    
        step_state = StepState()
        mock_agent.step = step_state.step
        mock_agent.config = AgentConfig()
        mock_agent.config.enable_history_truncation = False
    
        def on_event_memory(event: Event):
            if isinstance(event, RecallAction):
                microagent_obs = RecallObservation(
                    content='Test microagent content',
                    recall_type=RecallType.KNOWLEDGE,
                )
                microagent_obs._cause = event.id
                test_event_stream.add_event(microagent_obs, EventSource.ENVIRONMENT)
    
        test_event_stream.subscribe(
            EventStreamSubscriber.MEMORY, on_event_memory, str(uuid4())
        )
        mock_runtime.event_stream = test_event_stream
        try:
            state = await asyncio.wait_for(
                run_controller(
                    config=OpenHandsConfig(max_iterations=3),
                    initial_user_action=MessageAction(content='INITIAL'),
                    runtime=mock_runtime,
                    sid='test',
                    agent=mock_agent,
                    fake_user_response_fn=lambda _: 'repeat',
                    memory=mock_memory,
                ),
                timeout=10,
            )
    
        # A timeout error indicates the run_controller entrypoint is not making
        # progress
        except asyncio.TimeoutError as e:
            raise AssertionError(
                'The run_controller function did not complete in time.'
            ) from e
    
        # Hitting the iteration limit indicates the controller is failing for the
        # expected reason
        # With the refactored system message handling, the iteration count is different
        assert state.iteration == 1
        assert state.agent_state == AgentState.ERROR
>       assert (
            state.last_error
            == 'LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error'
        )
E       AssertionError: assert 'LLMContextWindowExceedError: Conversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error' == 'LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error'
E         
E         - LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error
E         ?                              ------
E         + LLMContextWindowExceedError: Conversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error

tests/unit/test_agent_controller.py:1045: AssertionError
_____________________ test_update_conversation_with_title ______________________
[gw0] linux -- Python 3.12.4 /home/runner/.cache/pypoetry/virtualenvs/openhands-ai-2f2V0C4o-py3.12/bin/python
@pytest.mark.asyncio
    async def test_update_conversation_with_title():
        """Test that _update_conversation_for_event updates the title when needed."""
        # Mock dependencies
        sio = MagicMock()
        sio.emit = AsyncMock()
        file_store = InMemoryFileStore()
        server_config = MagicMock()
    
        # Create test conversation
        conversation_id = 'test-conversation'
        user_id = 'test-user'
    
        # Create test settings
        settings = Settings(
            llm_model='test-model',
            llm_api_key='test-key',
            llm_base_url='test-url',
        )
    
        # Mock the conversation store and metadata
        mock_conversation_store = AsyncMock()
        mock_metadata = MagicMock()
        mock_metadata.title = f'ServerConversation {conversation_id[:5]}'  # Default title
        mock_conversation_store.get_metadata.return_value = mock_metadata
    
        # Create the conversation manager
        manager = StandaloneConversationManager(
            sio=sio,
            config=OpenHandsConfig(),
            file_store=file_store,
            server_config=server_config,
            monitoring_listener=MonitoringListener(),
        )
    
        # Mock the _get_conversation_store method
        manager._get_conversation_store = AsyncMock(return_value=mock_conversation_store)
    
        # Mock the auto_generate_title function
        with patch(
            'openhands.server.conversation_manager.standalone_conversation_manager.auto_generate_title',
            AsyncMock(return_value='Generated Title'),
        ):
            # Call the method
            await manager._update_conversation_for_event(user_id, conversation_id, settings)
    
            # Verify the title was updated
>           assert mock_metadata.title == 'Generated Title'
E           AssertionError: assert 'ServerConversation test-' == 'Generated Title'
E             
E             - Generated Title
E             + ServerConversation test-

tests/unit/test_auto_generate_title.py:228: AssertionError
=========================== short test summary info ============================
FAILED tests/unit/test_agent_controller.py::test_run_controller_with_context_window_exceeded_without_truncation
FAILED tests/unit/test_auto_generate_title.py::test_update_conversation_with_title
============ 2 failed, 1137 passed, 23 skipped in 71.03s (0:01:11) =============

rbren avatar May 28 '25 13:05 rbren

I'm on it! rbren can track my progress at all-hands.dev

openhands-ai[bot] avatar May 28 '25 13:05 openhands-ai[bot]

Work Summary

I successfully addressed the failing tests in the PR #8754 on the rename-conversation-appconfig branch. The PR was renaming AppConfig to OpenHandsConfig throughout the codebase, but there were two failing tests that needed to be fixed:

Changes Made:

  1. Fixed the error message assertion in test_agent_controller.py:

    • Changed the expected error message from 'LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit...' to 'LLMContextWindowExceedError: Conversation history longer than LLM context window limit...'
    • This aligns with the actual error message defined in the LLMContextWindowExceedError class.
  2. Fixed the default title in test_auto_generate_title.py:

    • Changed the mock title from f'ServerConversation {conversation_id[:5]}' to f'Conversation {conversation_id[:5]}'
    • This matches the actual implementation in the get_default_conversation_title function.

Verification:

  • All changes passed the pre-commit hooks, including ruff, mypy, and formatting checks.
  • The changes were successfully committed and pushed to the rename-conversation-appconfig branch.

These changes should fix the failing tests that were mentioned in the PR comment, allowing the PR to pass CI checks.

openhands-ai[bot] avatar May 28 '25 13:05 openhands-ai[bot]

@openhands update this test

=================================== FAILURES ===================================
_____ test_run_controller_with_context_window_exceeded_without_truncation ______
[gw3] linux -- Python 3.12.4 /home/runner/.cache/pypoetry/virtualenvs/openhands-ai-2f2V0C4o-py3.12/bin/python
mock_agent = <MagicMock spec='Agent' id='139887724626864'>
mock_runtime = <MagicMock spec='ActionExecutionClient' id='139887722237536'>
mock_memory = <MagicMock spec='Memory' id='139887722241184'>
test_event_stream = EventStream(sid='test', file_store=<openhands.storage.memory.InMemoryFileStore object at 0x7f3a25fe2210>, user_id=None, cur_id=6, cache_size=25)

    @pytest.mark.asyncio
    async def test_run_controller_with_context_window_exceeded_without_truncation(
        mock_agent, mock_runtime, mock_memory, test_event_stream
    ):
        """Tests that the controller would quit upon context window exceeded errors without enable_history_truncation ON."""
    
        class StepState:
            def __init__(self):
                self.has_errored = False
    
            def step(self, state: State):
                # If the state has more than one message and we haven't errored yet,
                # throw the context window exceeded error
                if len(state.history) > 3 and not self.has_errored:
                    error = ContextWindowExceededError(
                        message='prompt is too long: 233885 tokens > 200000 maximum',
                        model='',
                        llm_provider='',
                    )
                    self.has_errored = True
                    raise error
    
                return MessageAction(content=f'STEP {len(state.history)}')
    
        step_state = StepState()
        mock_agent.step = step_state.step
        mock_agent.config = AgentConfig()
        mock_agent.config.enable_history_truncation = False
    
        def on_event_memory(event: Event):
            if isinstance(event, RecallAction):
                microagent_obs = RecallObservation(
                    content='Test microagent content',
                    recall_type=RecallType.KNOWLEDGE,
                )
                microagent_obs._cause = event.id
                test_event_stream.add_event(microagent_obs, EventSource.ENVIRONMENT)
    
        test_event_stream.subscribe(
            EventStreamSubscriber.MEMORY, on_event_memory, str(uuid4())
        )
        mock_runtime.event_stream = test_event_stream
        try:
            state = await asyncio.wait_for(
                run_controller(
                    config=OpenHandsConfig(max_iterations=3),
                    initial_user_action=MessageAction(content='INITIAL'),
                    runtime=mock_runtime,
                    sid='test',
                    agent=mock_agent,
                    fake_user_response_fn=lambda _: 'repeat',
                    memory=mock_memory,
                ),
                timeout=10,
            )
    
        # A timeout error indicates the run_controller entrypoint is not making
        # progress
        except asyncio.TimeoutError as e:
            raise AssertionError(
                'The run_controller function did not complete in time.'
            ) from e
    
        # Hitting the iteration limit indicates the controller is failing for the
        # expected reason
        # With the refactored system message handling, the iteration count is different
        assert state.iteration == 1
        assert state.agent_state == AgentState.ERROR
        assert (
            state.last_error
            == 'LLMContextWindowExceedError: Conversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error'
        )
    
        error_observations = test_event_stream.get_matching_events(
            reverse=True, limit=1, event_types=(AgentStateChangedObservation)
        )
        assert len(error_observations) == 1
        error_observation = error_observations[0]
>       assert (
            error_observation.reason
            == 'LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error'
        )
E       AssertionError: assert 'LLMContextWindowExceedError: Conversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error' == 'LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error'
E         
E         - LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error
E         ?                              ------
E         + LLMContextWindowExceedError: Conversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error

tests/unit/test_agent_controller.py:1055: AssertionError
=========================== short test summary info ============================
FAILED tests/unit/test_agent_controller.py::test_run_controller_with_context_window_exceeded_without_truncation
============ 1 failed, 1138 passed, 23 skipped in 72.41s (0:01:12) =============

make sure it passes

rbren avatar May 28 '25 13:05 rbren

I'm on it! rbren can track my progress at all-hands.dev

openhands-ai[bot] avatar May 28 '25 13:05 openhands-ai[bot]

Work Summary

I successfully fixed the failing test in PR #8754 on the rename-conversation-appconfig branch.

Issue Identified

The test test_run_controller_with_context_window_exceeded_without_truncation was failing because of a mismatch in the expected error message. The test was expecting:

LLMContextWindowExceedError: ServerConversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error

But the actual error message was:

LLMContextWindowExceedError: Conversation history longer than LLM context window limit. Consider turning on enable_history_truncation config to avoid this error

Solution Implemented

I updated the test to match the actual error message by removing "Server" from "ServerConversation" in the expected error message. This aligns with the PR's purpose of renaming AppConfig to OpenHandsConfig and related changes.

Changes Made

  1. Modified the assertion in tests/unit/test_agent_controller.py to match the actual error message
  2. Verified the fix by running the test, which now passes
  3. Committed and pushed the changes to the rename-conversation-appconfig branch

The PR should now pass all tests and be ready for review.

openhands-ai[bot] avatar May 28 '25 13:05 openhands-ai[bot]