From 95e4ca490fa9f8f4f744d5ea6c4798a444777029 Mon Sep 17 00:00:00 2001 From: Leo Date: Thu, 2 May 2024 19:53:57 +0800 Subject: [PATCH] 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 Co-authored-by: Robert Brennan --- Makefile | 10 ++- .../opendevin/controller/agent_controller.md | 20 ++++++ frontend/package.json | 4 +- opendevin/controller/action_manager.py | 18 ++---- opendevin/controller/agent_controller.py | 62 ++++++++++++++----- opendevin/sandbox/plugins/requirement.py | 3 +- 6 files changed, 86 insertions(+), 31 deletions(-) diff --git a/Makefile b/Makefile index e8f174697e..8db71efe2e 100644 --- a/Makefile +++ b/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 diff --git a/docs/modules/python/opendevin/controller/agent_controller.md b/docs/modules/python/opendevin/controller/agent_controller.md index ac772c9cf5..3df4bcd3fc 100644 --- a/docs/modules/python/opendevin/controller/agent_controller.md +++ b/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 diff --git a/frontend/package.json b/frontend/package.json index 56f2d04f15..8f9713ce76 100644 --- a/frontend/package.json +++ b/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" ] diff --git a/opendevin/controller/action_manager.py b/opendevin/controller/action_manager.py index ea5e0404f9..504146935d 100644 --- a/opendevin/controller/action_manager.py +++ b/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}') diff --git a/opendevin/controller/agent_controller.py b/opendevin/controller/agent_controller.py index 6d3d5a4be0..2065c16b1c 100644 --- a/opendevin/controller/agent_controller.py +++ b/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') diff --git a/opendevin/sandbox/plugins/requirement.py b/opendevin/sandbox/plugins/requirement.py index 31731a0853..c4ade58849 100644 --- a/opendevin/sandbox/plugins/requirement.py +++ b/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