From c3a90d2a0769795b7dd8b5d6194fd7e7994ee900 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Sat, 4 Apr 2026 21:17:54 +0200 Subject: [PATCH] Fix reactivation of the same project restarting language servers Reactivation should do nothing at all. Fixes #1280 --- CHANGELOG.md | 7 ++++++- src/serena/agent.py | 21 +++++++++++++++------ src/serena/tools/config_tools.py | 4 +++- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 701cfce7..8d92b384 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,12 @@ -# Latest +# Unreleased (main) Status of the `main` branch. Changes prior to the next official version change will appear here. +* Fixes: + - Fix reactivation of the same project restarting language servers #1280 + +# 1.0.0 + * Memories: * Add `ignored_memory_patterns` configuration option (regex-based) to completely exclude matching memories from listing, reading, and writing. Configurable at both global diff --git a/src/serena/agent.py b/src/serena/agent.py index f036e908..7b1369e4 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -783,10 +783,17 @@ class SerenaAgent: """ return self._language_backend == LanguageBackend.LSP - def _activate_project(self, project: Project, update_active_modes: bool = True, update_active_tools: bool = True) -> None: + def _activate_project(self, project: Project, update_active_modes: bool = True, update_active_tools: bool = True) -> bool: + """ + :return: True if the project was newly activated, False if it was already active + """ + # check if the project is already active + if self._active_project is not None and self._active_project.project_root == project.project_root: + return False + log.info(f"Activating {project.project_name} at {project.project_root}") - # Check if the project requires a different language backend than the one initialized at startup + # check if the project requires a different language backend than the one initialized at startup project_backend = project.project_config.language_backend if project_backend is not None and project_backend != self._language_backend: raise ValueError( @@ -822,14 +829,18 @@ class SerenaAgent: if self._project_activation_callback is not None: self._project_activation_callback() + return True + def activate_project_from_path_or_name( self, project_root_or_name: str, update_active_modes: bool = True, update_active_tools: bool = True - ) -> Project: + ) -> bool: """ Activate a project from a path or a name. If the project was already registered, it will just be activated. If the argument is a path at which no Serena project previously existed, the project will be created beforehand. Raises ProjectNotFoundError if the project could neither be found nor created. + + :return: True if the project was newly activated, False if it was already active """ project_instance: Project | None = self.serena_config.get_project(project_root_or_name) if project_instance is not None: @@ -844,9 +855,7 @@ class SerenaAgent: f"Existing project names: {self.serena_config.project_names}" ) - self._activate_project(project_instance, update_active_modes=update_active_modes, update_active_tools=update_active_tools) - - return project_instance + return self._activate_project(project_instance, update_active_modes=update_active_modes, update_active_tools=update_active_tools) def get_active_tool_names(self) -> list[str]: """ diff --git a/src/serena/tools/config_tools.py b/src/serena/tools/config_tools.py index bdab4706..0e92924a 100644 --- a/src/serena/tools/config_tools.py +++ b/src/serena/tools/config_tools.py @@ -28,7 +28,9 @@ class ActivateProjectTool(Tool, ToolMarkerDoesNotRequireActiveProject): :param project: the name of a registered project to activate or a path to a project directory """ - self.agent.activate_project_from_path_or_name(project) + is_new_activation = self.agent.activate_project_from_path_or_name(project) + if not is_new_activation: + return "Project was already active." result = self.agent.get_project_activation_message() result += "\nIMPORTANT: If you have not yet read the 'Serena Instructions Manual', do it now before continuing!" return result