From 1b8fe642add64ee43fca8730626df0ecaa141603 Mon Sep 17 00:00:00 2001 From: Dominik Jain Date: Tue, 24 Feb 2026 12:45:02 +0100 Subject: [PATCH] Use preloaded RegisteredProject in _single_project_context_tool_inclusion_definitions to avoid loading the full project more than once (only needs ProjectConfig) --- src/serena/agent.py | 39 ++++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 19 deletions(-) diff --git a/src/serena/agent.py b/src/serena/agent.py index 474beec2..5181ce47 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -338,7 +338,7 @@ class SerenaAgent: tool_inclusion_definitions.append(self.serena_config) tool_inclusion_definitions.append(self._context) if self._context.single_project: - tool_inclusion_definitions.extend(self._single_project_context_tool_inclusion_definitions(project)) + tool_inclusion_definitions.extend(self._single_project_context_tool_inclusion_definitions(registered_project_to_activate)) if self._language_backend == LanguageBackend.JETBRAINS: tool_inclusion_definitions.append(SerenaAgentMode.from_name_internal("jetbrains")) self._base_tool_set = ToolSet.default().apply(*tool_inclusion_definitions) @@ -437,7 +437,9 @@ class SerenaAgent: os.environ["COMSPEC"] = "" # force use of default shell log.info("Adjusting COMSPEC environment variable to use the default shell instead of '%s'", comspec) - def _single_project_context_tool_inclusion_definitions(self, project_root_or_name: str | None) -> list[ToolInclusionDefinition]: + def _single_project_context_tool_inclusion_definitions( + self, registered_project: RegisteredProject | None + ) -> list[ToolInclusionDefinition]: """ When in a single-project context, the agent is assumed to work on a single project, and we thus want to apply that project's tool exclusions/inclusions from the get-go, limiting the set @@ -445,25 +447,24 @@ class SerenaAgent: Furthermore, we disable tools that are only relevant for project activation. So if the project exists, we apply all the aforementioned exclusions. - :param project_root_or_name: the project root path or project name - :return: + NOTE: This uses an existing registered project (instead of project auto-generation), + because the result must be returned instantaneously + (project generation could take too much time), so as not to delay MCP server startup + and provide responses to the client immediately. + + :param registered_project: the registered project or None + :return: the list of tool inclusion definitions to apply for a single-project context, based on the given registered project (if any) """ tool_inclusion_definitions = [] - if project_root_or_name is not None: - # Note: Auto-generation is disabled, because the result must be returned instantaneously - # (project generation could take too much time), so as not to delay MCP server startup - # and provide responses to the client immediately. - project = self.load_project_from_path_or_name(project_root_or_name, autogenerate=False) - if project is not None: - log.info( - "Applying tool inclusion/exclusion definitions for single-project context based on project '%s'", project.project_name - ) - tool_inclusion_definitions.append( - ToolInclusionDefinition( - excluded_tools=[ActivateProjectTool.get_name_from_cls(), GetCurrentConfigTool.get_name_from_cls()] - ) - ) - tool_inclusion_definitions.append(project.project_config) + if registered_project is not None: + log.info( + "Applying tool inclusion/exclusion definitions for single-project context based on project '%s'", + registered_project.project_name, + ) + tool_inclusion_definitions.append( + ToolInclusionDefinition(excluded_tools=[ActivateProjectTool.get_name_from_cls(), GetCurrentConfigTool.get_name_from_cls()]) + ) + tool_inclusion_definitions.append(registered_project.project_config) return tool_inclusion_definitions def record_tool_usage(self, input_kwargs: dict, tool_result: str | dict, tool: Tool) -> None: