From 1af077a2b432f450939f802c7a70f270b71b64cd Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Thu, 5 Jun 2025 16:55:42 +0200 Subject: [PATCH] gui_log_level -> log_level. Also added possibility to set trace_lsp_communication in config and cli [ci skip] --- src/serena/agent.py | 28 +++++++++++-------- src/serena/mcp.py | 27 +++++++++++++----- .../resources/serena_config.template.yml | 8 ++++-- 3 files changed, 43 insertions(+), 20 deletions(-) diff --git a/src/serena/agent.py b/src/serena/agent.py index 296b22d5..cde3bc17 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -222,6 +222,7 @@ class SerenaConfigBase(ABC): projects: list[Project] = field(default_factory=list) gui_log_window_enabled: bool = False log_level: int = logging.INFO + trace_lsp_communication: bool = False web_dashboard: bool = True tool_timeout: float = DEFAULT_TOOL_TIMEOUT @@ -502,7 +503,8 @@ class SerenaAgent: modes: list[SerenaAgentMode] | None = None, enable_web_dashboard: bool | None = None, enable_gui_log_window: bool | None = None, - gui_log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = None, + log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = None, + trace_lsp_communication: bool | None = None, ): """ :param project: the project to load immediately or None to not load any project; may be a path to the project or a name of @@ -524,16 +526,18 @@ class SerenaAgent: self.serena_config.web_dashboard = enable_web_dashboard if enable_gui_log_window is not None: self.serena_config.gui_log_window_enabled = enable_gui_log_window - if gui_log_level is not None: - gui_log_level = cast(Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], gui_log_level.upper()) + if log_level is not None: + log_level = cast(Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"], log_level.upper()) # transform to int - self.serena_config.log_level = logging.getLevelNamesMapping()[gui_log_level] + self.serena_config.log_level = logging.getLevelNamesMapping()[log_level] + if trace_lsp_communication is not None: + self.serena_config.trace_lsp_communication = trace_lsp_communication # adjust log level - log_level = self.serena_config.log_level - if Logger.root.level > log_level: - log.info(f"Changing the root logger level to {log_level}") - Logger.root.setLevel(log_level) + serena_log_level = self.serena_config.log_level + if Logger.root.level > serena_log_level: + log.info(f"Changing the root logger level to {serena_log_level}") + Logger.root.setLevel(serena_log_level) # open GUI log window if enabled self._gui_log_handler: Union["GuiLogViewerHandler", None] = None # noqa @@ -546,7 +550,7 @@ class SerenaAgent: from serena.gui_log_viewer import GuiLogViewer, GuiLogViewerHandler self._gui_log_handler = GuiLogViewerHandler( - GuiLogViewer("dashboard", title="Serena Logs"), level=log_level, format_string=LOG_FORMAT + GuiLogViewer("dashboard", title="Serena Logs"), level=serena_log_level, format_string=LOG_FORMAT ) Logger.root.addHandler(self._gui_log_handler) @@ -560,7 +564,7 @@ class SerenaAgent: # start the dashboard (web frontend), registering its log handler if self.serena_config.web_dashboard: - dashboard_log_handler = MemoryLogHandler(level=log_level) + dashboard_log_handler = MemoryLogHandler(level=serena_log_level) Logger.root.addHandler(dashboard_log_handler) self._dashboard_thread, port = SerenaDashboardAPI(dashboard_log_handler, tool_names).run_in_thread() webbrowser.open(f"http://localhost:{port}/dashboard/index.html") @@ -802,7 +806,9 @@ class SerenaAgent: # instantiate and start the language server assert self._active_project is not None multilspy_config = MultilspyConfig( - code_language=self._active_project.project_config.language, ignored_paths=self._active_project.project_config.ignored_paths + code_language=self._active_project.project_config.language, + ignored_paths=self._active_project.project_config.ignored_paths, + trace_lsp_communication=self.serena_config.trace_lsp_communication, ) ls_logger = MultilspyLogger(log_level=self.serena_config.log_level) log.info(f"Starting language server for {self._active_project.project_root}.") diff --git a/src/serena/mcp.py b/src/serena/mcp.py index a6c471b3..3f9d4efc 100644 --- a/src/serena/mcp.py +++ b/src/serena/mcp.py @@ -104,7 +104,8 @@ def create_mcp_server_and_agent( modes: Sequence[str] = DEFAULT_MODES, enable_web_dashboard: bool | None = None, enable_gui_log_window: bool | None = None, - gui_log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = None, + log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = None, + trace_lsp_communication: bool | None = None, ) -> tuple[FastMCP, SerenaAgent]: """ Create an MCP server. @@ -119,7 +120,9 @@ def create_mcp_server_and_agent( :param enable_web_dashboard: Whether to enable the web dashboard. If not specified, will take the value from the serena configuration. :param enable_gui_log_window: Whether to enable the GUI log window. It currently does not work on macOS, and setting this to True will be ignored then. If not specified, will take the value from the serena configuration. - :param gui_log_level: Log level for the GUI log window. If not specified, will take the value from the serena configuration. + :param log_level: Log level. If not specified, will take the value from the serena configuration. + :param trace_lsp_communication: Whether to trace the communication between Serena and the language servers. + This is useful for debugging language server issues. """ mcp: FastMCP | None = None context_instance = SerenaAgentContext.load(context) @@ -134,7 +137,8 @@ def create_mcp_server_and_agent( modes=modes_instances, enable_web_dashboard=enable_web_dashboard, enable_gui_log_window=enable_gui_log_window, - gui_log_level=gui_log_level, + log_level=log_level, + trace_lsp_communication=trace_lsp_communication, ) except Exception as e: show_fatal_exception_safe(e) @@ -264,10 +268,17 @@ PROJECT_TYPE = ProjectType() "If not specified, will take the value from the serena configuration.", ) @click.option( - "--gui-log-level", + "--log-level", type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]), default=None, - help="Log level for the GUI log window. If not specified, will take the value from the serena configuration.", + help="Log level for GUI, dashboard and other logging. If not specified, will take the value from the serena configuration.", +) +@click.option( + "--trace-lsp-communication", + type=bool, + is_flag=False, + default=None, + help="Whether to trace the communication between Serena and the language servers. This is useful for debugging language server issues.", ) def start_mcp_server( project_file_opt: str | None, @@ -279,7 +290,8 @@ def start_mcp_server( port: int = 8000, enable_web_dashboard: bool | None = None, enable_gui_log_window: bool | None = None, - gui_log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = None, + log_level: Literal["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"] | None = None, + trace_lsp_communication: bool | None = None, ) -> None: """Starts the Serena MCP server. By default, will not activate any project at startup. If you want to start with an already active project, use --project to pass the project name or path. @@ -299,7 +311,8 @@ def start_mcp_server( modes=modes, enable_web_dashboard=enable_web_dashboard, enable_gui_log_window=enable_gui_log_window, - gui_log_level=gui_log_level, + log_level=log_level, + trace_lsp_communication=trace_lsp_communication, ) # log after server creation such that the log appears in the GUI diff --git a/src/serena/resources/serena_config.template.yml b/src/serena/resources/serena_config.template.yml index e78dd18a..e6509877 100644 --- a/src/serena/resources/serena_config.template.yml +++ b/src/serena/resources/serena_config.template.yml @@ -1,5 +1,5 @@ gui_log_window: False -# Whether to open a graphical window with Serena's logs. +# whether to open a graphical window with Serena's logs. # This is mainly supported on Windows and (partly) on Linux; not available on macOS. # If you want to see the logs in a web browser, use the `web_dashboard` option instead. # Limitations: doesn't seem to work with the community version of Claude Desktop for Linux @@ -16,13 +16,17 @@ gui_log_window: False # we have to live with this limitation for now. web_dashboard: True -# Whether to open the Serena web dashboard (which will be accessible through your web browser) that +# whether to open the Serena web dashboard (which will be accessible through your web browser) that # shows Serena's current session logs - as an alternative to the GUI log window which # is supported on all platforms. log_level: 20 # the minimum log level for the GUI log window and the dashboard (10 = debug, 20 = info, 30 = warning, 40 = error) +trace_lsp_communication: False +# whether to trace the communication between Serena and the language servers. +# This is useful for debugging language server issues. + tool_timeout: 240 # timeout, in seconds, after which tool executions are terminated