Selaa lähdekoodia

Feat: add lint frontend and lint all to Makefile. (#1354)

* Feat: add lint frontend and lint all to Makefile.

* style codes.

* Remove redundant target.

---------

Co-authored-by: Jim Su <jimsu@protonmail.com>
Co-authored-by: Robert Brennan <accounts@rbren.io>
Leo 1 vuosi sitten
vanhempi
sitoutus
95e4ca490f

+ 9 - 1
Makefile

@@ -148,10 +148,18 @@ install-precommit-hooks:
 	@poetry run pre-commit install --config $(PRECOMMIT_CONFIG_PATH)
 	@echo "$(GREEN)Pre-commit hooks installed successfully.$(RESET)"
 
-lint:
+lint-backend:
 	@echo "$(YELLOW)Running linters...$(RESET)"
 	@poetry run pre-commit run --files $$(git diff --name-only $$(git merge-base main $$(git branch --show-current)) $$(git branch --show-current) | tr '\n' ' ') --show-diff-on-failure --config $(PRECOMMIT_CONFIG_PATH)
 
+lint-frontend:
+	@echo "$(YELLOW)Running linters for frontend...$(RESET)"
+	@cd frontend && npm run lint
+
+lint:
+	@$(MAKE) -s lint-frontend
+	@$(MAKE) -s lint-backend
+
 build-frontend:
 	@echo "$(YELLOW)Building frontend...$(RESET)"
 	@cd frontend && npm run build

+ 20 - 0
docs/modules/python/opendevin/controller/agent_controller.md

@@ -9,6 +9,26 @@ title: opendevin.controller.agent_controller
 class AgentController()
 ```
 
+#### \_\_init\_\_
+
+```python
+def __init__(agent: Agent,
+             sid: str = 'default',
+             max_iterations: int = MAX_ITERATIONS,
+             max_chars: int = MAX_CHARS,
+             callbacks: List[Callable] = [])
+```
+
+Initializes a new instance of the AgentController class.
+
+**Arguments**:
+
+- `agent` - The agent instance to control.
+- `sid` - The session ID of the agent.
+- `max_iterations` - The maximum number of iterations the agent can run.
+- `max_chars` - The maximum number of characters the agent can output.
+- `callbacks` - A list of callback functions to run after each action.
+
 #### setup\_task
 
 ```python

+ 2 - 2
frontend/package.json

@@ -43,7 +43,7 @@
     "preview": "vite preview",
     "make-i18n": "node scripts/make-i18n-translations.cjs",
     "prelint": "npm run make-i18n",
-    "lint": "eslint src/**/*.ts* && prettier --check src/**/*.ts*",
+    "lint": "eslint src --ext .ts,.tsx,.js && prettier --check src/**/*.{ts,tsx}",
     "prepare": "cd .. && husky install frontend/.husky"
   },
   "husky": {
@@ -52,7 +52,7 @@
     }
   },
   "lint-staged": {
-    "src/**/*.ts*": [
+    "src/**/*.{ts,tsx,js}": [
       "eslint --fix",
       "prettier --write"
     ]

+ 6 - 12
opendevin/controller/action_manager.py

@@ -20,28 +20,22 @@ class ActionManager:
     sandbox: Sandbox
 
     def __init__(
-            self,
-            sid: str,
+        self,
+        sid: str = 'default',
     ):
         sandbox_type = config.get(ConfigType.SANDBOX_TYPE).lower()
         if sandbox_type == 'exec':
             self.sandbox = DockerExecBox(
-                sid=(sid or 'default'),
-                timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
+                sid=(sid or 'default'), timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
             )
         elif sandbox_type == 'local':
-            self.sandbox = LocalBox(
-                timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
-            )
+            self.sandbox = LocalBox(timeout=config.get(ConfigType.SANDBOX_TIMEOUT))
         elif sandbox_type == 'ssh':
             self.sandbox = DockerSSHBox(
-                sid=(sid or 'default'),
-                timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
+                sid=(sid or 'default'), timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
             )
         elif sandbox_type == 'e2b':
-            self.sandbox = E2BBox(
-                timeout=config.get(ConfigType.SANDBOX_TIMEOUT)
-            )
+            self.sandbox = E2BBox(timeout=config.get(ConfigType.SANDBOX_TIMEOUT))
         else:
             raise ValueError(f'Invalid sandbox type: {sandbox_type}')
 

+ 47 - 15
opendevin/controller/agent_controller.py

@@ -55,12 +55,20 @@ class AgentController:
     def __init__(
         self,
         agent: Agent,
-        inputs: dict = {},
         sid: str = 'default',
         max_iterations: int = MAX_ITERATIONS,
         max_chars: int = MAX_CHARS,
         callbacks: List[Callable] = [],
     ):
+        """Initializes a new instance of the AgentController class.
+
+        Args:
+            agent: The agent instance to control.
+            sid: The session ID of the agent.
+            max_iterations: The maximum number of iterations the agent can run.
+            max_chars: The maximum number of characters the agent can output.
+            callbacks: A list of callback functions to run after each action.
+        """
         self.id = sid
         self.agent = agent
         self.max_iterations = max_iterations
@@ -73,8 +81,12 @@ class AgentController:
         self.browser = BrowserEnv()
 
 
-        if isinstance(agent, CodeActAgent) and not isinstance(self.action_manager.sandbox, DockerSSHBox):
-            logger.warning('CodeActAgent requires DockerSSHBox as sandbox! Using other sandbox that are not stateful (LocalBox, DockerExecBox) will not work properly.')
+        if isinstance(agent, CodeActAgent) and not isinstance(
+            self.action_manager.sandbox, DockerSSHBox
+        ):
+            logger.warning(
+                'CodeActAgent requires DockerSSHBox as sandbox! Using other sandbox that are not stateful (LocalBox, DockerExecBox) will not work properly.'
+            )
 
         self._await_user_message_queue: asyncio.Queue = asyncio.Queue()
 
@@ -119,7 +131,10 @@ class AgentController:
             except Exception:
                 logger.error('Error in loop', exc_info=True)
                 await self._run_callbacks(
-                    AgentErrorObservation('Oops! Something went wrong while completing your task. You can check the logs for more info.'))
+                    AgentErrorObservation(
+                        'Oops! Something went wrong while completing your task. You can check the logs for more info.'
+                    )
+                )
                 await self.set_task_state_to(TaskState.STOPPED)
                 break
 
@@ -139,14 +154,15 @@ class AgentController:
 
             if self._is_stuck():
                 logger.info('Loop detected, stopping task')
-                observation = AgentErrorObservation('I got stuck into a loop, the task has stopped.')
+                observation = AgentErrorObservation(
+                    'I got stuck into a loop, the task has stopped.'
+                )
                 await self._run_callbacks(observation)
                 await self.set_task_state_to(TaskState.STOPPED)
                 break
 
     async def setup_task(self, task: str, inputs: dict = {}):
-        """Sets up the agent controller with a task.
-        """
+        """Sets up the agent controller with a task."""
         self._task_state = TaskState.RUNNING
         await self.notify_task_state_changed()
         self.state = State(Plan(task))
@@ -203,14 +219,19 @@ class AgentController:
             self.add_history(NullAction(), message)
 
         else:
-            raise ValueError(f'Task (state: {self._task_state}) is not in a state to add user message')
+            raise ValueError(
+                f'Task (state: {self._task_state}) is not in a state to add user message'
+            )
 
     async def wait_for_user_input(self) -> UserMessageObservation:
         self._task_state = TaskState.AWAITING_USER_INPUT
         await self.notify_task_state_changed()
         # wait for the next user message
         if len(self.callbacks) == 0:
-            logger.info('Use STDIN to request user message as no callbacks are registered', extra={'msg_type': 'INFO'})
+            logger.info(
+                'Use STDIN to request user message as no callbacks are registered',
+                extra={'msg_type': 'INFO'},
+            )
             message = input('Request user input [type /exit to stop interaction] >> ')
             user_message_observation = UserMessageObservation(message)
         else:
@@ -312,22 +333,33 @@ class AgentController:
         return self.state
 
     def _is_stuck(self):
-        if self.state is None or self.state.history is None or len(self.state.history) < 3:
+        if (
+            self.state is None
+            or self.state.history is None
+            or len(self.state.history) < 3
+        ):
             return False
 
         # if the last three (Action, Observation) tuples are too repetitive
         # the agent got stuck in a loop
         if all(
-            [self.state.history[-i][0] == self.state.history[-3][0] for i in range(1, 3)]
+            [
+                self.state.history[-i][0] == self.state.history[-3][0]
+                for i in range(1, 3)
+            ]
         ):
             # it repeats same action, give it a chance, but not if:
-            if (all
-                    (isinstance(self.state.history[-i][1], NullObservation) for i in range(1, 4))):
+            if all(
+                isinstance(self.state.history[-i][1], NullObservation)
+                for i in range(1, 4)
+            ):
                 # same (Action, NullObservation): like 'think' the same thought over and over
                 logger.debug('Action, NullObservation loop detected')
                 return True
-            elif (all
-                  (isinstance(self.state.history[-i][1], AgentErrorObservation) for i in range(1, 4))):
+            elif all(
+                isinstance(self.state.history[-i][1], AgentErrorObservation)
+                for i in range(1, 4)
+            ):
                 # (NullAction, AgentErrorObservation): errors coming from an exception
                 # (Action, AgentErrorObservation): the same action getting an error, even if not necessarily the same error
                 logger.debug('Action, AgentErrorObservation loop detected')

+ 2 - 1
opendevin/sandbox/plugins/requirement.py

@@ -4,9 +4,10 @@ from dataclasses import dataclass
 @dataclass
 class PluginRequirement:
     """Requirement for a plugin."""
+
     name: str
     # FOLDER/FILES to be copied to the sandbox
     host_src: str
     sandbox_dest: str
-    # NOTE: bash_script_path shoulds be relative to the `sandbox_dest` path
+    # NOTE: bash_script_path should be relative to the `sandbox_dest` path
     bash_script_path: str