diff --git a/src/serena/agent.py b/src/serena/agent.py index d5b69269..953e4241 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -640,12 +640,10 @@ class SerenaAgent: # determine the effective language backend for this session. # If a startup project is provided and has a per-project override, use it; otherwise use the global config. # Since we don't want to change the toolset after startup, the language backend cannot be changed within a running Serena session - self._language_backend = self.serena_config.language_backend - if registered_project_to_activate is not None and registered_project_to_activate.project_config.language_backend is not None: - self._language_backend = registered_project_to_activate.project_config.language_backend - log.info(f"Using language backend as configured in project.yml: {self._language_backend.name}") - else: - log.info(f"Using language backend from global configuration: {self._language_backend.name}") + self._language_backend = self.serena_config.determine_language_backend( + project_config=registered_project_to_activate.project_config if registered_project_to_activate is not None else None, + log_choice=True, + ) # create the tool names mapping for prompts self._prompt_tool_names_mapping = self._create_prompt_tool_names_mapping(self._language_backend) diff --git a/src/serena/config/serena_config.py b/src/serena/config/serena_config.py index 0b8fc673..2b580082 100644 --- a/src/serena/config/serena_config.py +++ b/src/serena/config/serena_config.py @@ -1297,3 +1297,14 @@ class SerenaConfig(SharedConfig, ModeSelectionDefinitionWithBaseModes): if glob_match(pattern, project_root_str): return True return False + + def determine_language_backend(self, project_config: ProjectConfig | None = None, log_choice: bool = False): + language_backend = self.language_backend + if project_config and project_config.language_backend is not None: + language_backend = project_config.language_backend + if log_choice: + log.info(f"Using language backend as configured in project: {language_backend.name}") + else: + if log_choice: + log.info(f"Using language backend from global configuration: {language_backend.name}") + return language_backend diff --git a/src/serena/project.py b/src/serena/project.py index e40c2dab..87d0f969 100644 --- a/src/serena/project.py +++ b/src/serena/project.py @@ -9,6 +9,7 @@ from sensai.util.logging import LogTime from sensai.util.string import TextBuilder, ToStringMixin from serena.config.serena_config import ( + LanguageBackend, ProjectConfig, SerenaConfig, ) @@ -121,6 +122,16 @@ class Project(ToStringMixin): def project_name(self) -> str: return self.project_config.project_name + @property + def language_backend(self) -> LanguageBackend: + # The backend configuration is fundamentally owned by the agent, so it takes + # precedence. (Note: The agent does not necessary honour the project's choice, + # as it may be invalid.) + if self._agent is not None: + return self._agent.get_language_backend() + else: + return self.serena_config.determine_language_backend(self.project_config) + @classmethod def load( cls,