import ast from openhands.controller.action_parser import ActionParser, ResponseParser from openhands.core.logger import openhands_logger as logger from openhands.events.action import ( Action, BrowseInteractiveAction, ) class BrowsingResponseParser(ResponseParser): def __init__(self): # Need to pay attention to the item order in self.action_parsers super().__init__() self.action_parsers = [BrowsingActionParserMessage()] self.default_parser = BrowsingActionParserBrowseInteractive() def parse(self, response: str) -> Action: action_str = self.parse_response(response) return self.parse_action(action_str) def parse_response(self, response) -> str: action_str = response['choices'][0]['message']['content'] if action_str is None: return '' action_str = action_str.strip() if not action_str.endswith('```'): action_str = action_str + ')```' logger.info(action_str) return action_str def parse_action(self, action_str: str) -> Action: for action_parser in self.action_parsers: if action_parser.check_condition(action_str): return action_parser.parse(action_str) return self.default_parser.parse(action_str) class BrowsingActionParserMessage(ActionParser): """Parser action: - BrowseInteractiveAction(browser_actions) - unexpected response format, message back to user """ def __init__( self, ): pass def check_condition(self, action_str: str) -> bool: return '```' not in action_str def parse(self, action_str: str) -> Action: msg = f'send_msg_to_user("""{action_str}""")' return BrowseInteractiveAction( browser_actions=msg, thought=action_str, browsergym_send_msg_to_user=action_str, ) class BrowsingActionParserBrowseInteractive(ActionParser): """Parser action: - BrowseInteractiveAction(browser_actions) - handle send message to user function call in BrowserGym """ def __init__( self, ): pass def check_condition(self, action_str: str) -> bool: return True def parse(self, action_str: str) -> Action: thought = action_str.split('```')[0].strip() action_str = action_str.split('```')[1].strip() msg_content = '' for sub_action in action_str.split('\n'): if 'send_msg_to_user(' in sub_action: tree = ast.parse(sub_action) args = tree.body[0].value.args # type: ignore msg_content = args[0].value return BrowseInteractiveAction( browser_actions=action_str, thought=thought, browsergym_send_msg_to_user=msg_content, )