ソースを参照

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.
Christian Balcom 1 年間 前
コミット
546be7ca8e

+ 2 - 2
opendevin/action/bash.py

@@ -6,7 +6,7 @@ from opendevin.schema import ActionType
 
 
 if TYPE_CHECKING:
 if TYPE_CHECKING:
     from opendevin.controller import AgentController
     from opendevin.controller import AgentController
-    from opendevin.observation import CmdOutputObservation
+    from opendevin.observation import CmdOutputObservation, Observation
 
 
 
 
 @dataclass
 @dataclass
@@ -15,7 +15,7 @@ class CmdRunAction(ExecutableAction):
     background: bool = False
     background: bool = False
     action: str = ActionType.RUN
     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)
         return controller.action_manager.run_command(self.command, self.background)
 
 
     @property
     @property

+ 4 - 0
opendevin/action/fileop.py

@@ -85,6 +85,8 @@ class FileReadAction(ExecutableAction):
                         code_view = ''.join(read_lines)
                         code_view = ''.join(read_lines)
                 except FileNotFoundError:
                 except FileNotFoundError:
                     return AgentErrorObservation(f'File not found: {self.path}')
                     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:
                 except IsADirectoryError:
                     return AgentErrorObservation(f'Path is a directory: {self.path}. You can only read files')
                     return AgentErrorObservation(f'Path is a directory: {self.path}. You can only read files')
             except PermissionError:
             except PermissionError:
@@ -144,6 +146,8 @@ class FileWriteAction(ExecutableAction):
                     return AgentErrorObservation(f'File not found: {self.path}')
                     return AgentErrorObservation(f'File not found: {self.path}')
                 except IsADirectoryError:
                 except IsADirectoryError:
                     return AgentErrorObservation(f'Path is a directory: {self.path}. You can only write to files')
                     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:
             except PermissionError:
                 return AgentErrorObservation(f'Malformed paths not permitted: {self.path}')
                 return AgentErrorObservation(f'Malformed paths not permitted: {self.path}')
         return FileWriteObservation(content='', path=self.path)
         return FileWriteObservation(content='', path=self.path)

+ 10 - 7
opendevin/controller/action_manager.py

@@ -1,7 +1,7 @@
 from typing import List
 from typing import List
 
 
 from opendevin import config
 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.sandbox import DockerExecBox, DockerSSHBox, Sandbox, LocalBox, E2BBox
 from opendevin.schema import ConfigType
 from opendevin.schema import ConfigType
 from opendevin.action import (
 from opendevin.action import (
@@ -54,17 +54,20 @@ class ActionManager:
         observation = await action.run(agent_controller)
         observation = await action.run(agent_controller)
         return observation
         return observation
 
 
-    def run_command(self, command: str, background=False) -> CmdOutputObservation:
+    def run_command(self, command: str, background=False) -> Observation:
         if background:
         if background:
             return self._run_background(command)
             return self._run_background(command)
         else:
         else:
             return self._run_immediately(command)
             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:
     def _run_background(self, command: str) -> CmdOutputObservation:
         bg_cmd = self.sandbox.execute_in_background(command)
         bg_cmd = self.sandbox.execute_in_background(command)