Spaces:
Build error
Build error
| from openhands.events.action import ( | |
| Action, | |
| AgentFinishAction, | |
| AgentRejectAction, | |
| BrowseInteractiveAction, | |
| BrowseURLAction, | |
| CmdRunAction, | |
| FileEditAction, | |
| FileReadAction, | |
| FileWriteAction, | |
| MessageAction, | |
| RecallAction, | |
| ) | |
| from openhands.events.action.action import ActionConfirmationStatus | |
| from openhands.events.action.files import FileEditSource, FileReadSource | |
| from openhands.events.serialization import ( | |
| event_from_dict, | |
| event_to_dict, | |
| ) | |
| def serialization_deserialization( | |
| original_action_dict, cls, max_message_chars: int = 10000 | |
| ): | |
| action_instance = event_from_dict(original_action_dict) | |
| assert isinstance(action_instance, Action), ( | |
| 'The action instance should be an instance of Action.' | |
| ) | |
| assert isinstance(action_instance, cls), ( | |
| f'The action instance should be an instance of {cls.__name__}.' | |
| ) | |
| # event_to_dict is the regular serialization of an event | |
| serialized_action_dict = event_to_dict(action_instance) | |
| # it has an extra message property, for the UI | |
| serialized_action_dict.pop('message') | |
| assert serialized_action_dict == original_action_dict, ( | |
| 'The serialized action should match the original action dict.' | |
| ) | |
| def test_event_props_serialization_deserialization(): | |
| original_action_dict = { | |
| 'id': 42, | |
| 'source': 'agent', | |
| 'timestamp': '2021-08-01T12:00:00', | |
| 'action': 'message', | |
| 'args': { | |
| 'content': 'This is a test.', | |
| 'image_urls': None, | |
| 'wait_for_response': False, | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, MessageAction) | |
| def test_message_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'message', | |
| 'args': { | |
| 'content': 'This is a test.', | |
| 'image_urls': None, | |
| 'wait_for_response': False, | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, MessageAction) | |
| def test_agent_finish_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'finish', | |
| 'args': { | |
| 'outputs': {}, | |
| 'thought': '', | |
| 'task_completed': None, | |
| 'final_thought': '', | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, AgentFinishAction) | |
| def test_agent_reject_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'reject', | |
| 'args': {'outputs': {}, 'thought': ''}, | |
| } | |
| serialization_deserialization(original_action_dict, AgentRejectAction) | |
| def test_cmd_run_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'run', | |
| 'args': { | |
| 'blocking': False, | |
| 'command': 'echo "Hello world"', | |
| 'is_input': False, | |
| 'thought': '', | |
| 'hidden': False, | |
| 'confirmation_state': ActionConfirmationStatus.CONFIRMED, | |
| 'is_static': False, | |
| 'cwd': None, | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, CmdRunAction) | |
| def test_browse_url_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'browse', | |
| 'args': {'thought': '', 'url': 'https://www.example.com'}, | |
| } | |
| serialization_deserialization(original_action_dict, BrowseURLAction) | |
| def test_browse_interactive_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'browse_interactive', | |
| 'args': { | |
| 'thought': '', | |
| 'browser_actions': 'goto("https://www.example.com")', | |
| 'browsergym_send_msg_to_user': '', | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, BrowseInteractiveAction) | |
| def test_file_read_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'read', | |
| 'args': { | |
| 'path': '/path/to/file.txt', | |
| 'start': 0, | |
| 'end': -1, | |
| 'thought': 'None', | |
| 'impl_source': 'default', | |
| 'view_range': None, | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, FileReadAction) | |
| def test_file_write_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'write', | |
| 'args': { | |
| 'path': '/path/to/file.txt', | |
| 'content': 'Hello world', | |
| 'start': 0, | |
| 'end': 1, | |
| 'thought': 'None', | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, FileWriteAction) | |
| def test_file_edit_action_aci_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'edit', | |
| 'args': { | |
| 'path': '/path/to/file.txt', | |
| 'command': 'str_replace', | |
| 'file_text': None, | |
| 'old_str': 'old text', | |
| 'new_str': 'new text', | |
| 'insert_line': None, | |
| 'content': '', | |
| 'start': 1, | |
| 'end': -1, | |
| 'thought': 'Replacing text', | |
| 'impl_source': 'oh_aci', | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, FileEditAction) | |
| def test_file_edit_action_llm_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'edit', | |
| 'args': { | |
| 'path': '/path/to/file.txt', | |
| 'command': None, | |
| 'file_text': None, | |
| 'old_str': None, | |
| 'new_str': None, | |
| 'insert_line': None, | |
| 'content': 'Updated content', | |
| 'start': 1, | |
| 'end': 10, | |
| 'thought': 'Updating file content', | |
| 'impl_source': 'llm_based_edit', | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, FileEditAction) | |
| def test_cmd_run_action_legacy_serialization(): | |
| original_action_dict = { | |
| 'action': 'run', | |
| 'args': { | |
| 'blocking': False, | |
| 'command': 'echo "Hello world"', | |
| 'thought': '', | |
| 'hidden': False, | |
| 'confirmation_state': ActionConfirmationStatus.CONFIRMED, | |
| 'keep_prompt': False, # will be treated as no-op | |
| }, | |
| } | |
| event = event_from_dict(original_action_dict) | |
| assert isinstance(event, Action) | |
| assert isinstance(event, CmdRunAction) | |
| assert event.command == 'echo "Hello world"' | |
| assert event.hidden is False | |
| assert not hasattr(event, 'keep_prompt') | |
| event_dict = event_to_dict(event) | |
| assert 'keep_prompt' not in event_dict['args'] | |
| assert ( | |
| event_dict['args']['confirmation_state'] == ActionConfirmationStatus.CONFIRMED | |
| ) | |
| assert event_dict['args']['blocking'] is False | |
| assert event_dict['args']['command'] == 'echo "Hello world"' | |
| assert event_dict['args']['thought'] == '' | |
| assert event_dict['args']['is_input'] is False | |
| def test_file_llm_based_edit_action_legacy_serialization(): | |
| original_action_dict = { | |
| 'action': 'edit', | |
| 'args': { | |
| 'path': '/path/to/file.txt', | |
| 'content': 'dummy content', | |
| 'start': 1, | |
| 'end': -1, | |
| 'thought': 'Replacing text', | |
| 'impl_source': 'oh_aci', | |
| 'translated_ipython_code': None, | |
| }, | |
| } | |
| event = event_from_dict(original_action_dict) | |
| assert isinstance(event, Action) | |
| assert isinstance(event, FileEditAction) | |
| # Common arguments | |
| assert event.path == '/path/to/file.txt' | |
| assert event.thought == 'Replacing text' | |
| assert event.impl_source == FileEditSource.OH_ACI | |
| assert not hasattr(event, 'translated_ipython_code') | |
| # OH_ACI arguments | |
| assert event.command == '' | |
| assert event.file_text is None | |
| assert event.old_str is None | |
| assert event.new_str is None | |
| assert event.insert_line is None | |
| # LLM-based editing arguments | |
| assert event.content == 'dummy content' | |
| assert event.start == 1 | |
| assert event.end == -1 | |
| event_dict = event_to_dict(event) | |
| assert 'translated_ipython_code' not in event_dict['args'] | |
| # Common arguments | |
| assert event_dict['args']['path'] == '/path/to/file.txt' | |
| assert event_dict['args']['impl_source'] == 'oh_aci' | |
| assert event_dict['args']['thought'] == 'Replacing text' | |
| # OH_ACI arguments | |
| assert event_dict['args']['command'] == '' | |
| assert event_dict['args']['file_text'] is None | |
| assert event_dict['args']['old_str'] is None | |
| assert event_dict['args']['new_str'] is None | |
| assert event_dict['args']['insert_line'] is None | |
| # LLM-based editing arguments | |
| assert event_dict['args']['content'] == 'dummy content' | |
| assert event_dict['args']['start'] == 1 | |
| assert event_dict['args']['end'] == -1 | |
| def test_file_ohaci_edit_action_legacy_serialization(): | |
| original_action_dict = { | |
| 'action': 'edit', | |
| 'args': { | |
| 'path': '/workspace/game_2048.py', | |
| 'content': '', | |
| 'start': 1, | |
| 'end': -1, | |
| 'thought': "I'll help you create a simple 2048 game in Python. I'll use the str_replace_editor to create the file.", | |
| 'impl_source': 'oh_aci', | |
| 'translated_ipython_code': "print(file_editor(**{'command': 'create', 'path': '/workspace/game_2048.py', 'file_text': 'New file content'}))", | |
| }, | |
| } | |
| event = event_from_dict(original_action_dict) | |
| assert isinstance(event, Action) | |
| assert isinstance(event, FileEditAction) | |
| # Common arguments | |
| assert event.path == '/workspace/game_2048.py' | |
| assert ( | |
| event.thought | |
| == "I'll help you create a simple 2048 game in Python. I'll use the str_replace_editor to create the file." | |
| ) | |
| assert event.impl_source == FileEditSource.OH_ACI | |
| assert not hasattr(event, 'translated_ipython_code') | |
| # OH_ACI arguments | |
| assert event.command == 'create' | |
| assert event.file_text == 'New file content' | |
| assert event.old_str is None | |
| assert event.new_str is None | |
| assert event.insert_line is None | |
| # LLM-based editing arguments | |
| assert event.content == '' | |
| assert event.start == 1 | |
| assert event.end == -1 | |
| event_dict = event_to_dict(event) | |
| assert 'translated_ipython_code' not in event_dict['args'] | |
| # Common arguments | |
| assert event_dict['args']['path'] == '/workspace/game_2048.py' | |
| assert event_dict['args']['impl_source'] == 'oh_aci' | |
| assert ( | |
| event_dict['args']['thought'] | |
| == "I'll help you create a simple 2048 game in Python. I'll use the str_replace_editor to create the file." | |
| ) | |
| # OH_ACI arguments | |
| assert event_dict['args']['command'] == 'create' | |
| assert event_dict['args']['file_text'] == 'New file content' | |
| assert event_dict['args']['old_str'] is None | |
| assert event_dict['args']['new_str'] is None | |
| assert event_dict['args']['insert_line'] is None | |
| # LLM-based editing arguments | |
| assert event_dict['args']['content'] == '' | |
| assert event_dict['args']['start'] == 1 | |
| assert event_dict['args']['end'] == -1 | |
| def test_agent_microagent_action_serialization_deserialization(): | |
| original_action_dict = { | |
| 'action': 'recall', | |
| 'args': { | |
| 'query': 'What is the capital of France?', | |
| 'thought': 'I need to find information about France', | |
| 'recall_type': 'knowledge', | |
| }, | |
| } | |
| serialization_deserialization(original_action_dict, RecallAction) | |
| def test_file_read_action_legacy_serialization(): | |
| original_action_dict = { | |
| 'action': 'read', | |
| 'args': { | |
| 'path': '/workspace/test.txt', | |
| 'start': 0, | |
| 'end': -1, | |
| 'thought': 'Reading the file contents', | |
| 'impl_source': 'oh_aci', | |
| 'translated_ipython_code': "print(file_editor(**{'command': 'view', 'path': '/workspace/test.txt'}))", | |
| }, | |
| } | |
| event = event_from_dict(original_action_dict) | |
| assert isinstance(event, Action) | |
| assert isinstance(event, FileReadAction) | |
| # Common arguments | |
| assert event.path == '/workspace/test.txt' | |
| assert event.thought == 'Reading the file contents' | |
| assert event.impl_source == FileReadSource.OH_ACI | |
| assert not hasattr(event, 'translated_ipython_code') | |
| assert not hasattr( | |
| event, 'command' | |
| ) # FileReadAction should not have command attribute | |
| # Read-specific arguments | |
| assert event.start == 0 | |
| assert event.end == -1 | |
| event_dict = event_to_dict(event) | |
| assert 'translated_ipython_code' not in event_dict['args'] | |
| assert ( | |
| 'command' not in event_dict['args'] | |
| ) # command should not be in serialized args | |
| # Common arguments in serialized form | |
| assert event_dict['args']['path'] == '/workspace/test.txt' | |
| assert event_dict['args']['impl_source'] == 'oh_aci' | |
| assert event_dict['args']['thought'] == 'Reading the file contents' | |
| # Read-specific arguments in serialized form | |
| assert event_dict['args']['start'] == 0 | |
| assert event_dict['args']['end'] == -1 | |