diff --git a/src/serena/agent.py b/src/serena/agent.py index b8f56661..06062321 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -17,7 +17,7 @@ from sensai.util.logging import LogTime from interprompt.jinja_template import JinjaTemplate from serena import serena_version from serena.analytics import RegisteredTokenCountEstimator, ToolUsageStats -from serena.config.context_mode import RegisteredContext, SerenaAgentContext, SerenaAgentMode +from serena.config.context_mode import SerenaAgentContext, SerenaAgentMode from serena.config.serena_config import SerenaConfig, ToolInclusionDefinition, ToolSet from serena.dashboard import SerenaDashboardAPI from serena.ls_manager import LanguageServerManager @@ -141,8 +141,8 @@ class SerenaAgent: # determine the base toolset defining the set of exposed tools (which e.g. the MCP shall see), # limited by the Serena config, the context (which is fixed for the session) and JetBrains mode tool_inclusion_definitions: list[ToolInclusionDefinition] = [self.serena_config, self._context] - if self._context.name == RegisteredContext.IDE_ASSISTANT.value: - tool_inclusion_definitions.extend(self._ide_assistant_context_tool_inclusion_definitions(project)) + if self._context.single_project: + tool_inclusion_definitions.extend(self._single_project_context_tool_inclusion_definitions(project)) if self.serena_config.jetbrains: tool_inclusion_definitions.append(SerenaAgentMode.from_name_internal("jetbrains")) @@ -240,7 +240,7 @@ 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 _ide_assistant_context_tool_inclusion_definitions(self, project_root_or_name: str | None) -> list[ToolInclusionDefinition]: + def _single_project_context_tool_inclusion_definitions(self, project_root_or_name: str | None) -> list[ToolInclusionDefinition]: """ In the IDE assistant 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 @@ -258,6 +258,9 @@ class SerenaAgent: # 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()] diff --git a/src/serena/config/context_mode.py b/src/serena/config/context_mode.py index ed2eb11c..7a6fc6e9 100644 --- a/src/serena/config/context_mode.py +++ b/src/serena/config/context_mode.py @@ -125,14 +125,29 @@ class SerenaAgentContext(ToolInclusionDefinition, ToStringMixin): """ name: str + """the name of the context""" + prompt: str """ a Jinja2 template for the generation of the system prompt. It is formatted by the agent (see SerenaAgent._format_prompt()). """ + description: str = "" + tool_description_overrides: dict[str, str] = field(default_factory=dict) - """Maps tool names to custom descriptions, default descriptions are extracted from the tool docstrings.""" + """ + maps tool names to custom descriptions, default descriptions are extracted from the tool docstrings. + """ + + single_project: bool = False + """ + whether to assume that Serena shall only work on a single project in this context (provided that a project is given + when Serena is started). + If set to true and a project is provided at startup, the set of tools is limited to those required by the project's + concrete configuration, and other tools are excluded completely, allowing the set of tools to be minimal. + The `activate_project` tool will, therefore, be disabled in this case, as project switching is not allowed. + """ def _tostring_includes(self) -> list[str]: return ["name"] diff --git a/src/serena/resources/config/contexts/context.template.yml b/src/serena/resources/config/contexts/context.template.yml index c01a1177..f9873413 100644 --- a/src/serena/resources/config/contexts/context.template.yml +++ b/src/serena/resources/config/contexts/context.template.yml @@ -8,4 +8,11 @@ included_optional_tools: [] # mapping of tool names to an override of their descriptions (the default description is the docstring of the Tool's apply method). # Sometimes, tool descriptions are too long (e.g., for ChatGPT), or users may want to override them for another reason. -tool_description_overrides: {} \ No newline at end of file +tool_description_overrides: {} + +# whether to assume that Serena shall only work on a single project in this context (provided that a project is given +# when Serena is started). +# If set to true and a project is provided at startup, the set of tools is limited to those required by the project's +# concrete configuration, and other tools are excluded completely, allowing the set of tools to be minimal. +# The `activate_project` tool will, therefore, be disabled in this case, as project switching is not allowed. +single_project: false \ No newline at end of file diff --git a/src/serena/resources/config/contexts/ide-assistant.yml b/src/serena/resources/config/contexts/ide-assistant.yml index e9332c3e..78b865b5 100644 --- a/src/serena/resources/config/contexts/ide-assistant.yml +++ b/src/serena/resources/config/contexts/ide-assistant.yml @@ -25,3 +25,10 @@ excluded_tools: tool_description_overrides: {} +# whether to assume that Serena shall only work on a single project in this context (provided that a project is given +# when Serena is started). +# If set to true and a project is provided at startup, the set of tools is limited to those required by the project's +# concrete configuration, and other tools are excluded completely, allowing the set of tools to be minimal. +# Tools explicitly disabled by the project will not be available at all. +# The `activate_project` tool is always disabled in this case, as project switching cannot be allowed. +single_project: true