Parcourir la source

Fix logger import (#985)

* fix logger import
* fix mypy version
* make mypy happy (#994)

---------

Co-authored-by: Engel Nyst <enyst@users.noreply.github.com>
Robert Brennan il y a 1 an
Parent
commit
9846e24299

+ 1 - 2
.github/workflows/lint.yml

@@ -35,9 +35,8 @@ jobs:
       - name: Create mypy cache directory
         run: mkdir -p .mypy_cache
       - name: Install dependencies
-        run: pip install ruff mypy types-PyYAML types-toml
+        run: pip install ruff mypy==1.9.0 types-PyYAML types-toml
       - name: Run mypy
         run: python -m mypy --install-types --non-interactive --config-file dev_config/python/mypy.ini opendevin/ agenthub/
       - name: Run ruff
         run: ruff check --config dev_config/python/ruff.toml opendevin/ agenthub/
-      

+ 1 - 1
opendevin/controller/agent_controller.py

@@ -17,7 +17,7 @@ from opendevin.action import (
 )
 from opendevin.observation import Observation, AgentErrorObservation, NullObservation
 from opendevin import config
-from opendevin.logging import opendevin_logger as logger
+from opendevin.logger import opendevin_logger as logger
 
 from .command_manager import CommandManager
 

+ 3 - 2
opendevin/llm/llm.py

@@ -3,7 +3,7 @@ from litellm import completion as litellm_completion
 from functools import partial
 
 from opendevin import config
-from opendevin.logging import llm_prompt_logger, llm_response_logger
+from opendevin.logger import llm_prompt_logger, llm_response_logger
 
 DEFAULT_API_KEY = config.get('LLM_API_KEY')
 DEFAULT_BASE_URL = config.get('LLM_BASE_URL')
@@ -24,7 +24,8 @@ class LLM:
         self.api_key = api_key if api_key else DEFAULT_API_KEY
         self.base_url = base_url if base_url else DEFAULT_BASE_URL
 
-        self._completion = partial(litellm_completion, model=self.model_name, api_key=self.api_key, base_url=self.base_url)
+        self._completion = partial(
+            litellm_completion, model=self.model_name, api_key=self.api_key, base_url=self.base_url)
 
         completion_unwrapped = self._completion
 

+ 3 - 2
opendevin/logging.py → opendevin/logger.py

@@ -63,7 +63,7 @@ def log_uncaught_exceptions(ex_cls, ex, tb):
 
 sys.excepthook = log_uncaught_exceptions
 
-opendevin_logger = logging.getLogger("opendevin")
+opendevin_logger = logging.getLogger('opendevin')
 opendevin_logger.setLevel(logging.INFO)
 opendevin_logger.addHandler(get_console_handler())
 opendevin_logger.addHandler(get_file_handler())
@@ -78,6 +78,8 @@ logging.getLogger('LiteLLM Router').disabled = True
 logging.getLogger('LiteLLM Proxy').disabled = True
 
 # LLM prompt and response logging
+
+
 class LlmFileHandler(logging.FileHandler):
 
     def __init__(self, filename, mode='a', encoding=None, delay=False):
@@ -114,7 +116,6 @@ class LlmFileHandler(logging.FileHandler):
         self.message_counter += 1
 
 
-
 def get_llm_prompt_file_handler():
     """
     Returns a file handler for LLM prompt logging.

+ 10 - 8
opendevin/plan.py

@@ -1,20 +1,22 @@
 from typing import List
-from opendevin.logging import opendevin_logger as logger
+from opendevin.logger import opendevin_logger as logger
 
 OPEN_STATE = 'open'
 COMPLETED_STATE = 'completed'
 ABANDONED_STATE = 'abandoned'
 IN_PROGRESS_STATE = 'in_progress'
 VERIFIED_STATE = 'verified'
-STATES = [OPEN_STATE, COMPLETED_STATE, ABANDONED_STATE, IN_PROGRESS_STATE, VERIFIED_STATE]
+STATES = [OPEN_STATE, COMPLETED_STATE,
+          ABANDONED_STATE, IN_PROGRESS_STATE, VERIFIED_STATE]
+
 
 class Task:
     id: str
     goal: str
-    parent: "Task | None"
-    subtasks: List["Task"]
+    parent: 'Task | None'
+    subtasks: List['Task']
 
-    def __init__(self, parent: "Task | None", goal: str, state: str=OPEN_STATE, subtasks: List = []):
+    def __init__(self, parent: 'Task | None', goal: str, state: str = OPEN_STATE, subtasks: List = []):
         """Initializes a new instance of the Task class.
 
         Args:
@@ -41,7 +43,7 @@ class Task:
 
         self.state = OPEN_STATE
 
-    def to_string(self, indent=""):
+    def to_string(self, indent=''):
         """Returns a string representation of the task and its subtasks.
 
         Args:
@@ -99,7 +101,7 @@ class Task:
             if self.parent is not None:
                 self.parent.set_state(state)
 
-    def get_current_task(self) -> "Task | None":
+    def get_current_task(self) -> 'Task | None':
         """Retrieves the current task in progress.
 
         Returns:
@@ -112,6 +114,7 @@ class Task:
             return self
         return None
 
+
 class Plan:
     """Represents a plan consisting of tasks.
 
@@ -194,4 +197,3 @@ class Plan:
             The current task in progress, or None if no task is in progress.
         """
         return self.task.get_current_task()
-

+ 7 - 2
opendevin/sandbox/sandbox.py

@@ -12,7 +12,7 @@ from typing import Dict, List, Tuple, Union
 import docker
 
 from opendevin import config
-from opendevin.logging import opendevin_logger as logger
+from opendevin.logger import opendevin_logger as logger
 from opendevin.controller.command_executor import CommandExecutor
 
 InputType = namedtuple('InputType', ['content'])
@@ -208,7 +208,12 @@ class DockerInteractive(CommandExecutor):
         else:
             username = 'root'
         logger.info(
-            f"Connecting to {username}@{hostname} via ssh. If you encounter any issues, you can try `ssh -v -p 2222 {username}@{hostname}` with the password '{self._ssh_password}' and report the issue on GitHub."
+            f"Connecting to {username}@{hostname} via ssh."
+        )
+        logger.info(
+            # FIXME: mypy and autopep8 fight each other on this line
+            # autopep8: off
+            f"If you encounter any issues, you can try `ssh -v -p 2222 {username}@{hostname}` with the password '{self._ssh_password}' and report the issue on GitHub."
         )
         self.ssh.login(hostname, username, self._ssh_password, port=2222)
 

+ 1 - 1
opendevin/server/agent/manager.py

@@ -10,7 +10,7 @@ from opendevin.action import (
 from opendevin.agent import Agent
 from opendevin.controller import AgentController
 from opendevin.llm.llm import LLM
-from opendevin.logging import opendevin_logger as logger
+from opendevin.logger import opendevin_logger as logger
 from opendevin.observation import NullObservation, Observation, UserMessageObservation
 from opendevin.schema import ActionType, ConfigType
 from opendevin.server.session import session_manager

+ 9 - 9
opendevin/server/auth/auth.py

@@ -1,22 +1,22 @@
 import os
 import jwt
 from typing import Dict
-from opendevin.logging import opendevin_logger as logger
+from opendevin.logger import opendevin_logger as logger
 
-JWT_SECRET = os.getenv("JWT_SECRET", "5ecRe7")
+JWT_SECRET = os.getenv('JWT_SECRET', '5ecRe7')
 
 
 def get_sid_from_token(token: str) -> str:
     """Gets the session id from a JWT token."""
     try:
-        payload = jwt.decode(token, JWT_SECRET, algorithms=["HS256"])
+        payload = jwt.decode(token, JWT_SECRET, algorithms=['HS256'])
         if payload is None:
-            logger.error("Invalid token")
-            return ""
-        return payload["sid"]
+            logger.error('Invalid token')
+            return ''
+        return payload['sid']
     except Exception as e:
-        logger.exception("Error decoding token: %s", e)
-        return ""
+        logger.exception('Error decoding token: %s', e)
+        return ''
 
 
 def sign_token(payload: Dict[str, object]) -> str:
@@ -25,4 +25,4 @@ def sign_token(payload: Dict[str, object]) -> str:
     #     "sid": sid,
     #     # "exp": datetime.now(timezone.utc) + timedelta(minutes=15),
     # }
-    return jwt.encode(payload, JWT_SECRET, algorithm="HS256")
+    return jwt.encode(payload, JWT_SECRET, algorithm='HS256')

+ 12 - 11
opendevin/server/session/msg_stack.py

@@ -6,11 +6,11 @@ import uuid
 from typing import Dict, List
 
 from opendevin.schema.action import ActionType
-from opendevin.logging import opendevin_logger as logger
+from opendevin.logger import opendevin_logger as logger
 
 
-CACHE_DIR = os.getenv("CACHE_DIR", "cache")
-MSG_CACHE_FILE = os.path.join(CACHE_DIR, "messages.json")
+CACHE_DIR = os.getenv('CACHE_DIR', 'cache')
+MSG_CACHE_FILE = os.path.join(CACHE_DIR, 'messages.json')
 
 
 class Message:
@@ -23,12 +23,12 @@ class Message:
         self.payload = payload
 
     def to_dict(self):
-        return {"id": self.id, "role": self.role, "payload": self.payload}
+        return {'id': self.id, 'role': self.role, 'payload': self.payload}
 
     @classmethod
     def from_dict(cls, data: Dict):
-        m = cls(data["role"], data["payload"])
-        m.id = data["id"]
+        m = cls(data['role'], data['payload'])
+        m.id = data['id']
         return m
 
 
@@ -45,7 +45,7 @@ class MessageStack:
         self._save_messages()
 
     def handle_signal(self, signum, _):
-        logger.info("Received signal %s, exiting...", signum)
+        logger.info('Received signal %s, exiting...', signum)
         self.close()
         exit(0)
 
@@ -70,7 +70,7 @@ class MessageStack:
         cnt = 0
         for msg in self._messages[sid]:
             # Ignore assistant init message for now.
-            if "action" in msg.payload and msg.payload["action"] == ActionType.INIT:
+            if 'action' in msg.payload and msg.payload['action'] == ActionType.INIT:
                 continue
             cnt += 1
         return cnt
@@ -81,16 +81,17 @@ class MessageStack:
         data = {}
         for sid, msgs in self._messages.items():
             data[sid] = [msg.to_dict() for msg in msgs]
-        with open(MSG_CACHE_FILE, "w+") as file:
+        with open(MSG_CACHE_FILE, 'w+') as file:
             json.dump(data, file)
 
     def _load_messages(self):
         try:
             # TODO: delete useless messages
-            with open(MSG_CACHE_FILE, "r") as file:
+            with open(MSG_CACHE_FILE, 'r') as file:
                 data = json.load(file)
                 for sid, msgs in data.items():
-                    self._messages[sid] = [Message.from_dict(msg) for msg in msgs]
+                    self._messages[sid] = [
+                        Message.from_dict(msg) for msg in msgs]
         except FileNotFoundError:
             pass
         except json.decoder.JSONDecodeError:

+ 11 - 11
opendevin/server/session/session.py

@@ -3,7 +3,7 @@ from typing import Dict, Callable
 from fastapi import WebSocket, WebSocketDisconnect
 from .msg_stack import message_stack
 
-from opendevin.logging import opendevin_logger as logger
+from opendevin.logger import opendevin_logger as logger
 
 DEL_DELT_SEC = 60 * 60 * 5
 
@@ -27,20 +27,20 @@ class Session:
                 try:
                     data = await self.websocket.receive_json()
                 except ValueError:
-                    await self.send_error("Invalid JSON")
+                    await self.send_error('Invalid JSON')
                     continue
 
-                message_stack.add_message(self.sid, "user", data)
-                action = data.get("action", None)
+                message_stack.add_message(self.sid, 'user', data)
+                action = data.get('action', None)
                 await dispatch(action, data)
         except WebSocketDisconnect:
             self.is_alive = False
-            logger.info("WebSocket disconnected, sid: %s", self.sid)
+            logger.info('WebSocket disconnected, sid: %s', self.sid)
         except RuntimeError as e:
             # WebSocket is not connected
-            if "WebSocket is not connected" in str(e):
+            if 'WebSocket is not connected' in str(e):
                 self.is_alive = False
-            logger.exception("Error in loop_recv: %s", e)
+            logger.exception('Error in loop_recv: %s', e)
 
     async def send(self, data: Dict[str, object]) -> bool:
         try:
@@ -55,11 +55,11 @@ class Session:
 
     async def send_error(self, message: str) -> bool:
         """Sends an error message to the client."""
-        return await self.send({"error": True, "message": message})
+        return await self.send({'error': True, 'message': message})
 
     async def send_message(self, message: str) -> bool:
         """Sends a message to the client."""
-        return await self.send({"message": message})
+        return await self.send({'message': message})
 
     def update_connection(self, ws: WebSocket):
         self.websocket = ws
@@ -67,8 +67,8 @@ class Session:
         self.last_active_ts = int(time.time())
 
     def load_from_data(self, data: Dict) -> bool:
-        self.last_active_ts = data.get("last_active_ts", 0)
+        self.last_active_ts = data.get('last_active_ts', 0)
         if self.last_active_ts < int(time.time()) - DEL_DELT_SEC:
             return False
-        self.is_alive = data.get("is_alive", False)
+        self.is_alive = data.get('is_alive', False)
         return True