From 546be7ca8e0806575929e3f03286f5656aff0ba6 Mon Sep 17 00:00:00 2001 From: Christian Balcom Date: Sat, 27 Apr 2024 08:15:16 -0400 Subject: [PATCH] Handle Unicode errors (#1388) * Add errors for non-unicode file data or command return, trim excessively long command returns. * Fix lint issue. * Fix lint issue (try 2). * Realized that prompts were trimmed elsewhere and dropped the new addition. --- opendevin/action/bash.py | 4 ++-- opendevin/action/fileop.py | 4 ++++ opendevin/controller/action_manager.py | 17 ++++++++++------- 3 files changed, 16 insertions(+), 9 deletions(-) diff --git a/opendevin/action/bash.py b/opendevin/action/bash.py index b24d1f96ba..1757c7ea3c 100644 --- a/opendevin/action/bash.py +++ b/opendevin/action/bash.py @@ -6,7 +6,7 @@ from opendevin.schema import ActionType if TYPE_CHECKING: from opendevin.controller import AgentController - from opendevin.observation import CmdOutputObservation + from opendevin.observation import CmdOutputObservation, Observation @dataclass @@ -15,7 +15,7 @@ class CmdRunAction(ExecutableAction): background: bool = False action: str = ActionType.RUN - async def run(self, controller: 'AgentController') -> 'CmdOutputObservation': + async def run(self, controller: 'AgentController') -> 'Observation': return controller.action_manager.run_command(self.command, self.background) @property diff --git a/opendevin/action/fileop.py b/opendevin/action/fileop.py index 610327af25..2395879029 100644 --- a/opendevin/action/fileop.py +++ b/opendevin/action/fileop.py @@ -85,6 +85,8 @@ class FileReadAction(ExecutableAction): code_view = ''.join(read_lines) except FileNotFoundError: return AgentErrorObservation(f'File not found: {self.path}') + except UnicodeDecodeError: + return AgentErrorObservation(f'File could not be decoded as utf-8: {self.path}') except IsADirectoryError: return AgentErrorObservation(f'Path is a directory: {self.path}. You can only read files') except PermissionError: @@ -144,6 +146,8 @@ class FileWriteAction(ExecutableAction): return AgentErrorObservation(f'File not found: {self.path}') except IsADirectoryError: return AgentErrorObservation(f'Path is a directory: {self.path}. You can only write to files') + except UnicodeDecodeError: + return AgentErrorObservation(f'File could not be decoded as utf-8: {self.path}') except PermissionError: return AgentErrorObservation(f'Malformed paths not permitted: {self.path}') return FileWriteObservation(content='', path=self.path) diff --git a/opendevin/controller/action_manager.py b/opendevin/controller/action_manager.py index bc4f6d67de..d9c91a2c76 100644 --- a/opendevin/controller/action_manager.py +++ b/opendevin/controller/action_manager.py @@ -1,7 +1,7 @@ from typing import List from opendevin import config -from opendevin.observation import CmdOutputObservation +from opendevin.observation import CmdOutputObservation, AgentErrorObservation from opendevin.sandbox import DockerExecBox, DockerSSHBox, Sandbox, LocalBox, E2BBox from opendevin.schema import ConfigType from opendevin.action import ( @@ -54,17 +54,20 @@ class ActionManager: observation = await action.run(agent_controller) return observation - def run_command(self, command: str, background=False) -> CmdOutputObservation: + def run_command(self, command: str, background=False) -> Observation: if background: return self._run_background(command) else: return self._run_immediately(command) - def _run_immediately(self, command: str) -> CmdOutputObservation: - exit_code, output = self.sandbox.execute(command) - return CmdOutputObservation( - command_id=-1, content=output, command=command, exit_code=exit_code - ) + def _run_immediately(self, command: str) -> Observation: + try: + exit_code, output = self.sandbox.execute(command) + return CmdOutputObservation( + command_id=-1, content=output, command=command, exit_code=exit_code + ) + except UnicodeDecodeError: + return AgentErrorObservation('Command output could not be decoded as utf-8') def _run_background(self, command: str) -> CmdOutputObservation: bg_cmd = self.sandbox.execute_in_background(command)