feat(cli): add agent state validation to /resume command (#10066)

This commit is contained in:
aeft
2025-08-04 12:14:21 -07:00
committed by GitHub
parent d233e89873
commit a36d1673fa
5 changed files with 64 additions and 6 deletions

View File

@@ -1,6 +1,7 @@
from unittest.mock import MagicMock, patch
import pytest
from prompt_toolkit.formatted_text import HTML
from openhands.cli.commands import (
display_mcp_servers,
@@ -32,6 +33,7 @@ class TestHandleCommands:
config = MagicMock(spec=OpenHandsConfig)
current_dir = '/test/dir'
settings_store = MagicMock(spec=FileSettingsStore)
agent_state = AgentState.RUNNING
return {
'event_stream': event_stream,
@@ -40,6 +42,7 @@ class TestHandleCommands:
'config': config,
'current_dir': current_dir,
'settings_store': settings_store,
'agent_state': agent_state,
}
@pytest.mark.asyncio
@@ -562,13 +565,16 @@ class TestHandleSettingsCommand:
class TestHandleResumeCommand:
@pytest.mark.asyncio
async def test_handle_resume_command(self):
"""Test that handle_resume_command adds the 'continue' message to the event stream."""
@patch('openhands.cli.commands.print_formatted_text')
async def test_handle_resume_command_paused_state(self, mock_print):
"""Test that handle_resume_command works when agent is in PAUSED state."""
# Create a mock event stream
event_stream = MagicMock(spec=EventStream)
# Call the function
close_repl, new_session_requested = await handle_resume_command(event_stream)
# Call the function with PAUSED state
close_repl, new_session_requested = await handle_resume_command(
event_stream, AgentState.PAUSED
)
# Check that the event stream add_event was called with the correct message action
event_stream.add_event.assert_called_once()
@@ -583,6 +589,40 @@ class TestHandleResumeCommand:
assert close_repl is True
assert new_session_requested is False
# Verify no error message was printed
mock_print.assert_not_called()
@pytest.mark.asyncio
@pytest.mark.parametrize(
'invalid_state', [AgentState.RUNNING, AgentState.FINISHED, AgentState.ERROR]
)
@patch('openhands.cli.commands.print_formatted_text')
async def test_handle_resume_command_invalid_states(
self, mock_print, invalid_state
):
"""Test that handle_resume_command shows error for all non-PAUSED states."""
event_stream = MagicMock(spec=EventStream)
close_repl, new_session_requested = await handle_resume_command(
event_stream, invalid_state
)
# Check that no event was added to the stream
event_stream.add_event.assert_not_called()
# Verify print was called with the error message
assert mock_print.call_count == 1
error_call = mock_print.call_args_list[0][0][0]
assert isinstance(error_call, HTML)
assert 'Error: Agent is not paused' in str(error_call)
assert '/resume command is only available when agent is paused' in str(
error_call
)
# Check the return values
assert close_repl is False
assert new_session_requested is False
class TestMCPErrorHandling:
"""Test MCP error handling in commands."""

View File

@@ -248,6 +248,7 @@ class TestCliCommandsPauseResume:
config = MagicMock()
current_dir = '/test/dir'
settings_store = MagicMock()
agent_state = AgentState.PAUSED
# Mock return value
mock_handle_resume.return_value = (False, False)
@@ -266,10 +267,11 @@ class TestCliCommandsPauseResume:
config,
current_dir,
settings_store,
agent_state,
)
# Check that handle_resume_command was called with correct args
mock_handle_resume.assert_called_once_with(event_stream)
mock_handle_resume.assert_called_once_with(event_stream, agent_state)
# Check the return values
assert close_repl is False

View File

@@ -4,6 +4,7 @@ from unittest.mock import MagicMock
import pytest
from openhands.cli.commands import handle_commands
from openhands.core.schema import AgentState
from openhands.core.schema.exit_reason import ExitReason
@@ -51,6 +52,7 @@ async def test_handle_exit_command_returns_intentional(monkeypatch):
MagicMock(),
'/tmp/test',
MagicMock(),
AgentState.RUNNING,
)
assert exit_reason == ExitReason.INTENTIONAL