mirror of
https://github.com/OpenHands/OpenHands.git
synced 2025-12-26 05:48:36 +08:00
feat(CLI): Enhance --file option to prompt agent to read and understand file first (#9398)
Co-authored-by: openhands <openhands@all-hands.dev>
This commit is contained in:
parent
70ad469fb2
commit
b74da7d4c3
@ -77,7 +77,6 @@ async def cleanup_session(
|
||||
controller: AgentController,
|
||||
) -> None:
|
||||
"""Clean up all resources from the current session."""
|
||||
|
||||
event_stream = runtime.event_stream
|
||||
end_state = controller.get_state()
|
||||
end_state.save_to_session(
|
||||
@ -434,7 +433,23 @@ async def main_with_loop(loop: asyncio.AbstractEventLoop) -> None:
|
||||
return
|
||||
|
||||
# Read task from file, CLI args, or stdin
|
||||
task_str = read_task(args, config.cli_multiline_input)
|
||||
if args.file:
|
||||
# For CLI usage, we want to enhance the file content with a prompt
|
||||
# that instructs the agent to read and understand the file first
|
||||
with open(args.file, 'r', encoding='utf-8') as file:
|
||||
file_content = file.read()
|
||||
|
||||
# Create a prompt that instructs the agent to read and understand the file first
|
||||
task_str = f"""The user has tagged a file '{args.file}'.
|
||||
Please read and understand the following file content first:
|
||||
|
||||
```
|
||||
{file_content}
|
||||
```
|
||||
|
||||
After reviewing the file, please ask the user what they would like to do with it."""
|
||||
else:
|
||||
task_str = read_task(args, config.cli_multiline_input)
|
||||
|
||||
# Run the first session
|
||||
new_session_requested = await run_session(
|
||||
|
||||
@ -345,6 +345,7 @@ async def test_main_without_task(
|
||||
mock_args.agent_cls = None
|
||||
mock_args.llm_config = None
|
||||
mock_args.name = None
|
||||
mock_args.file = None
|
||||
mock_parse_args.return_value = mock_args
|
||||
|
||||
# Mock config
|
||||
@ -427,6 +428,7 @@ async def test_main_with_task(
|
||||
mock_args = MagicMock()
|
||||
mock_args.agent_cls = 'custom-agent'
|
||||
mock_args.llm_config = 'custom-config'
|
||||
mock_args.file = None
|
||||
mock_parse_args.return_value = mock_args
|
||||
|
||||
# Mock config
|
||||
@ -523,6 +525,7 @@ async def test_main_with_session_name_passes_name_to_run_session(
|
||||
mock_args.agent_cls = None
|
||||
mock_args.llm_config = None
|
||||
mock_args.name = test_session_name # Set the session name
|
||||
mock_args.file = None
|
||||
mock_parse_args.return_value = mock_args
|
||||
|
||||
# Mock config
|
||||
@ -831,3 +834,93 @@ async def test_config_loading_order(
|
||||
|
||||
# Verify that run_session was called with the correct arguments
|
||||
mock_run_session.assert_called_once()
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@patch('openhands.cli.main.parse_arguments')
|
||||
@patch('openhands.cli.main.setup_config_from_args')
|
||||
@patch('openhands.cli.main.FileSettingsStore.get_instance')
|
||||
@patch('openhands.cli.main.check_folder_security_agreement')
|
||||
@patch('openhands.cli.main.run_session')
|
||||
@patch('openhands.cli.main.LLMSummarizingCondenserConfig')
|
||||
@patch('openhands.cli.main.NoOpCondenserConfig')
|
||||
@patch('builtins.open', new_callable=MagicMock)
|
||||
async def test_main_with_file_option(
|
||||
mock_open,
|
||||
mock_noop_condenser,
|
||||
mock_llm_condenser,
|
||||
mock_run_session,
|
||||
mock_check_security,
|
||||
mock_get_settings_store,
|
||||
mock_setup_config,
|
||||
mock_parse_args,
|
||||
):
|
||||
"""Test main function with a file option."""
|
||||
loop = asyncio.get_running_loop()
|
||||
|
||||
# Mock arguments
|
||||
mock_args = MagicMock()
|
||||
mock_args.agent_cls = None
|
||||
mock_args.llm_config = None
|
||||
mock_args.name = None
|
||||
mock_args.file = '/path/to/test/file.txt'
|
||||
mock_args.task = None
|
||||
mock_parse_args.return_value = mock_args
|
||||
|
||||
# Mock config
|
||||
mock_config = MagicMock()
|
||||
mock_config.workspace_base = '/test/dir'
|
||||
mock_config.cli_multiline_input = False
|
||||
mock_setup_config.return_value = mock_config
|
||||
|
||||
# Mock settings store
|
||||
mock_settings_store = AsyncMock()
|
||||
mock_settings = MagicMock()
|
||||
mock_settings.agent = 'test-agent'
|
||||
mock_settings.llm_model = 'test-model'
|
||||
mock_settings.llm_api_key = 'test-api-key'
|
||||
mock_settings.llm_base_url = 'test-base-url'
|
||||
mock_settings.confirmation_mode = True
|
||||
mock_settings.enable_default_condenser = True
|
||||
mock_settings_store.load.return_value = mock_settings
|
||||
mock_get_settings_store.return_value = mock_settings_store
|
||||
|
||||
# Mock condenser config to return a mock instead of validating
|
||||
mock_llm_condenser_instance = MagicMock()
|
||||
mock_llm_condenser.return_value = mock_llm_condenser_instance
|
||||
|
||||
# Mock security check
|
||||
mock_check_security.return_value = True
|
||||
|
||||
# Mock file open
|
||||
mock_file = MagicMock()
|
||||
mock_file.__enter__.return_value.read.return_value = 'This is a test file content.'
|
||||
mock_open.return_value = mock_file
|
||||
|
||||
# Mock run_session to return False (no new session requested)
|
||||
mock_run_session.return_value = False
|
||||
|
||||
# Run the function
|
||||
await cli.main_with_loop(loop)
|
||||
|
||||
# Assertions
|
||||
mock_parse_args.assert_called_once()
|
||||
mock_setup_config.assert_called_once_with(mock_args)
|
||||
mock_get_settings_store.assert_called_once()
|
||||
mock_settings_store.load.assert_called_once()
|
||||
mock_check_security.assert_called_once_with(mock_config, '/test/dir')
|
||||
|
||||
# Verify file was opened
|
||||
mock_open.assert_called_once_with('/path/to/test/file.txt', 'r', encoding='utf-8')
|
||||
|
||||
# Check that run_session was called with expected arguments
|
||||
mock_run_session.assert_called_once()
|
||||
# Extract the task_str from the call
|
||||
task_str = mock_run_session.call_args[0][4]
|
||||
assert "The user has tagged a file '/path/to/test/file.txt'" in task_str
|
||||
assert 'Please read and understand the following file content first:' in task_str
|
||||
assert 'This is a test file content.' in task_str
|
||||
assert (
|
||||
'After reviewing the file, please ask the user what they would like to do with it.'
|
||||
in task_str
|
||||
)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user