diff --git a/.serena/project.yml b/.serena/project.yml index 0170423a..84b6fcf8 100644 --- a/.serena/project.yml +++ b/.serena/project.yml @@ -48,41 +48,41 @@ read_only: false # Below is the complete list of tools for convenience. # To make sure you have the latest list of tools, and to view their descriptions, # execute `uv run scripts/print_tool_overview.py`. -# -# * `activate_project`: Activates a project by name. +# * `activate_project`: Activates a project based on the project name or path. # * `check_onboarding_performed`: Checks whether project onboarding was already performed. # * `create_text_file`: Creates/overwrites a file in the project directory. -# * `delete_lines`: Deletes a range of lines within a file. -# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. +# * `delete_memory`: Delete a memory file. Should only happen if a user asks for it explicitly, +# for example by saying that the information retrieved from a memory file is no longer correct +# or no longer relevant for the project. +# * `edit_memory`: Replaces content matching a regular expression in a memory. # * `execute_shell_command`: Executes a shell command. -# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. -# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). -# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). +# * `find_file`: Finds files in the given relative paths +# * `find_referencing_symbols`: Finds symbols that reference the given symbol using the language server backend +# * `find_symbol`: Performs a global (or local) search using the language server backend. # * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. # * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. -# * `initial_instructions`: Gets the initial instructions for the current project. -# Should only be used in settings where the system prompt cannot be set, -# e.g. in clients you have no control over, like Claude Desktop. +# * `initial_instructions`: Provides instructions Serena usage (i.e. the 'Serena Instructions Manual') +# for clients that do not read the initial instructions when the MCP server is connected. # * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. -# * `insert_at_line`: Inserts content at a given line in a file. # * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. # * `list_dir`: Lists files and directories in the given directory (optionally with recursion). -# * `list_memories`: Lists memories in Serena's project-specific memory store. +# * `list_memories`: List available memories. Any memory can be read using the `read_memory` tool. # * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). -# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). # * `read_file`: Reads a file within the project directory. -# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. -# * `remove_project`: Removes a project from the Serena configuration. -# * `replace_lines`: Replaces a range of lines within a file with new content. -# * `replace_symbol_body`: Replaces the full definition of a symbol. -# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. +# * `read_memory`: Read the content of a memory file. This tool should only be used if the information +# is relevant to the current task. You can infer whether the information +# is relevant from the memory file name. +# You should not read the same memory file multiple times in the same conversation. +# * `rename_memory`: Renames or moves a memory. Moving between project and global scope is supported +# (e.g., renaming "global/foo" to "bar" moves it from global to project scope). +# * `rename_symbol`: Renames a symbol throughout the codebase using language server refactoring capabilities. +# For JB, we use a separate tool. +# * `replace_content`: Replaces content in a file (optionally using regular expressions). +# * `replace_symbol_body`: Replaces the full definition of a symbol using the language server backend. +# * `safe_delete_symbol`: # * `search_for_pattern`: Performs a search for a pattern in the project. -# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. -# * `switch_modes`: Activates modes by providing a list of their names -# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. -# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. -# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. -# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. +# * `write_memory`: Write some information (utf-8-encoded) about this project that can be useful for future tasks to a memory in md format. +# The memory name should be meaningful. excluded_tools: [] # list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default). diff --git a/docs/02-usage/050_configuration.md b/docs/02-usage/050_configuration.md index 5f5f3ad3..798daa3c 100644 --- a/docs/02-usage/050_configuration.md +++ b/docs/02-usage/050_configuration.md @@ -145,10 +145,6 @@ If you want to keep certain modes as always active, regardless of command-line p define them as *base modes* in the global or project configuration. ::: -Modes can also be _switched dynamically_ during a session. -You can instruct the LLM to use the `switch_modes` tool to activate a different set of modes (e.g., "Switch to planning and one-shot modes"). -Like command-line parameters, this only affects default modes, not base modes (which remain active). - :::{note} **Mode Compatibility**: While you can combine modes, some may be semantically incompatible (e.g., `interactive` and `one-shot`). Serena currently does not prevent incompatible combinations; it is up to the user to choose sensible mode configurations. diff --git a/src/serena/agent.py b/src/serena/agent.py index 31267135..cd616343 100644 --- a/src/serena/agent.py +++ b/src/serena/agent.py @@ -146,24 +146,20 @@ class ToolSet: tool_names = set() for fixed_tool in definition.fixed_tools: fixed_tool = get_updated_tool_name(fixed_tool) - if not registry.is_valid_tool_name(fixed_tool): - raise ValueError(f"Invalid tool name '{fixed_tool}' provided for fixed tool set") - tool_names.add(fixed_tool) + if registry.check_valid_tool_name(fixed_tool, " (in fixed tools set)"): + tool_names.add(fixed_tool) log.info(f"{definition} defined a fixed tool set with {len(tool_names)} tools: {', '.join(tool_names)}") else: included_tools = [] excluded_tools = [] for included_tool in definition.included_optional_tools: included_tool = get_updated_tool_name(included_tool) - if not registry.is_valid_tool_name(included_tool): - raise ValueError(f"Invalid tool name '{included_tool}' provided for inclusion") - if included_tool not in tool_names: + if registry.check_valid_tool_name(included_tool, " (in included optional tools)") and included_tool not in tool_names: tool_names.add(included_tool) included_tools.append(included_tool) for excluded_tool in definition.excluded_tools: excluded_tool = get_updated_tool_name(excluded_tool) - if not registry.is_valid_tool_name(excluded_tool): - raise ValueError(f"Invalid tool name '{excluded_tool}' provided for exclusion") + registry.check_valid_tool_name(excluded_tool, " (in excluded tools)") if excluded_tool in tool_names: tool_names.remove(excluded_tool) excluded_tools.append(excluded_tool) diff --git a/src/serena/resources/config/contexts/chatgpt.yml b/src/serena/resources/config/contexts/chatgpt.yml index ae1c3db6..494e9c42 100644 --- a/src/serena/resources/config/contexts/chatgpt.yml +++ b/src/serena/resources/config/contexts/chatgpt.yml @@ -11,8 +11,7 @@ prompt: | a diagram in addition to your text-based communication. Note that in the chat interface you have various rendering options for text, html, and mermaid diagrams, as has been explained to you in your initial instructions. excluded_tools: [] -included_optional_tools: - - switch_modes +included_optional_tools: [] tool_description_overrides: find_symbol: | diff --git a/src/serena/resources/config/contexts/claude-code.yml b/src/serena/resources/config/contexts/claude-code.yml index 118ed8b4..c7da899e 100644 --- a/src/serena/resources/config/contexts/claude-code.yml +++ b/src/serena/resources/config/contexts/claude-code.yml @@ -12,7 +12,6 @@ excluded_tools: - create_text_file - read_file - execute_shell_command - - prepare_for_new_conversation - replace_content tool_description_overrides: {} diff --git a/src/serena/resources/config/contexts/codex.yml b/src/serena/resources/config/contexts/codex.yml index a492e8f9..ccad93b5 100644 --- a/src/serena/resources/config/contexts/codex.yml +++ b/src/serena/resources/config/contexts/codex.yml @@ -13,7 +13,6 @@ excluded_tools: - create_text_file - read_file - execute_shell_command - - prepare_for_new_conversation - replace_content diff --git a/src/serena/resources/config/contexts/desktop-app.yml b/src/serena/resources/config/contexts/desktop-app.yml index 8d49cec5..aad51ac8 100644 --- a/src/serena/resources/config/contexts/desktop-app.yml +++ b/src/serena/resources/config/contexts/desktop-app.yml @@ -9,7 +9,6 @@ prompt: | To illustrate complex relationships, consider creating diagrams in addition to your text-based communication (depending on the options for text, html, mermaid diagrams, etc. that you are provided with in your initial instructions). excluded_tools: [] -included_optional_tools: - - switch_modes +included_optional_tools: [] tool_description_overrides: {} diff --git a/src/serena/resources/config/contexts/ide.yml b/src/serena/resources/config/contexts/ide.yml index 4a917a56..e8806f4e 100644 --- a/src/serena/resources/config/contexts/ide.yml +++ b/src/serena/resources/config/contexts/ide.yml @@ -12,7 +12,6 @@ excluded_tools: - create_text_file - read_file - execute_shell_command - - prepare_for_new_conversation tool_description_overrides: {} diff --git a/src/serena/resources/config/prompt_templates/simple_tool_outputs.yml b/src/serena/resources/config/prompt_templates/simple_tool_outputs.yml index 41291165..c6f2c619 100644 --- a/src/serena/resources/config/prompt_templates/simple_tool_outputs.yml +++ b/src/serena/resources/config/prompt_templates/simple_tool_outputs.yml @@ -34,42 +34,3 @@ prompts: Moreover, you should create memory files for the style and conventions and a dedicated memory file for what should be done when a task is completed. **Important**: after done with the onboarding task, remember to call the `write_memory` to save the collected information! - - think_about_collected_information: | - Have you collected all the information you need for solving the current task? If not, can the missing information be acquired by using the available tools, - in particular the tools related to symbol discovery? Or do you need to ask the user for more information? - Think about it step by step and give a summary of the missing information and how it could be acquired. - - think_about_task_adherence: | - Are you deviating from the task at hand? Do you need any additional information to proceed? - Have you loaded all relevant memory files to see whether your implementation is fully aligned with the - code style, conventions, and guidelines of the project? If not, adjust your implementation accordingly - before modifying any code into the codebase. - Note that it is better to stop and ask the user for clarification - than to perform large changes which might not be aligned with the user's intentions. - If you feel like the conversation is deviating too much from the original task, apologize and suggest to the user - how to proceed. If the conversation became too long, create a summary of the current progress and suggest to the user - to start a new conversation based on that summary. - - think_about_whether_you_are_done: | - Have you already performed all the steps required by the task? Is it appropriate to run tests and linting, and if so, - have you done that already? Is it appropriate to adjust non-code files like documentation and config and have you done that already? - Should new tests be written to cover the changes? - Note that a task that is just about exploring the codebase does not require running tests or linting. - Read the corresponding memory files to see what should be done when a task is completed. - - summarize_changes: | - Summarize all the changes you have made to the codebase over the course of the conversation. - Explore the diff if needed (e.g. by using `git diff`) to ensure that you have not missed anything. - Explain whether and how the changes are covered by tests. Explain how to best use the new code, how to understand it, - which existing code it affects and interacts with. Are there any dangers (like potential breaking changes or potential new problems) - that the user should be aware of? Should any new documentation be written or existing documentation updated? - You can use tools to explore the codebase prior to writing the summary, but don't write any new code in this step until - the summary is complete. - - prepare_for_new_conversation: | - You have not yet completed the current task but we are running out of context. - {mode_prepare_for_new_conversation} - Imagine that you are handing over the task to another person who has access to the - same tools and memory files as you do, but has not been part of the conversation so far. - Write a summary that can be used in the next conversation to a memory file using the `write_memory` tool. diff --git a/src/serena/resources/project.template.yml b/src/serena/resources/project.template.yml index f6ba8cb1..9a2c92e5 100644 --- a/src/serena/resources/project.template.yml +++ b/src/serena/resources/project.template.yml @@ -69,40 +69,41 @@ read_only: false # To make sure you have the latest list of tools, and to view their descriptions, # execute `uv run scripts/print_tool_overview.py`. # -# * `activate_project`: Activates a project by name. +# * `activate_project`: Activates a project based on the project name or path. # * `check_onboarding_performed`: Checks whether project onboarding was already performed. # * `create_text_file`: Creates/overwrites a file in the project directory. -# * `delete_lines`: Deletes a range of lines within a file. -# * `delete_memory`: Deletes a memory from Serena's project-specific memory store. +# * `delete_memory`: Delete a memory file. Should only happen if a user asks for it explicitly, +# for example by saying that the information retrieved from a memory file is no longer correct +# or no longer relevant for the project. +# * `edit_memory`: Replaces content matching a regular expression in a memory. # * `execute_shell_command`: Executes a shell command. -# * `find_referencing_code_snippets`: Finds code snippets in which the symbol at the given location is referenced. -# * `find_referencing_symbols`: Finds symbols that reference the symbol at the given location (optionally filtered by type). -# * `find_symbol`: Performs a global (or local) search for symbols with/containing a given name/substring (optionally filtered by type). +# * `find_file`: Finds files in the given relative paths +# * `find_referencing_symbols`: Finds symbols that reference the given symbol using the language server backend +# * `find_symbol`: Performs a global (or local) search using the language server backend. # * `get_current_config`: Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. # * `get_symbols_overview`: Gets an overview of the top-level symbols defined in a given file. -# * `initial_instructions`: Gets the initial instructions for the current project. -# Should only be used in settings where the system prompt cannot be set, -# e.g. in clients you have no control over, like Claude Desktop. +# * `initial_instructions`: Provides instructions Serena usage (i.e. the 'Serena Instructions Manual') +# for clients that do not read the initial instructions when the MCP server is connected. # * `insert_after_symbol`: Inserts content after the end of the definition of a given symbol. -# * `insert_at_line`: Inserts content at a given line in a file. # * `insert_before_symbol`: Inserts content before the beginning of the definition of a given symbol. # * `list_dir`: Lists files and directories in the given directory (optionally with recursion). -# * `list_memories`: Lists memories in Serena's project-specific memory store. +# * `list_memories`: List available memories. Any memory can be read using the `read_memory` tool. # * `onboarding`: Performs onboarding (identifying the project structure and essential tasks, e.g. for testing or building). -# * `prepare_for_new_conversation`: Provides instructions for preparing for a new conversation (in order to continue with the necessary context). # * `read_file`: Reads a file within the project directory. -# * `read_memory`: Reads the memory with the given name from Serena's project-specific memory store. -# * `remove_project`: Removes a project from the Serena configuration. -# * `replace_lines`: Replaces a range of lines within a file with new content. -# * `replace_symbol_body`: Replaces the full definition of a symbol. -# * `restart_language_server`: Restarts the language server, may be necessary when edits not through Serena happen. +# * `read_memory`: Read the content of a memory file. This tool should only be used if the information +# is relevant to the current task. You can infer whether the information +# is relevant from the memory file name. +# You should not read the same memory file multiple times in the same conversation. +# * `rename_memory`: Renames or moves a memory. Moving between project and global scope is supported +# (e.g., renaming "global/foo" to "bar" moves it from global to project scope). +# * `rename_symbol`: Renames a symbol throughout the codebase using language server refactoring capabilities. +# For JB, we use a separate tool. +# * `replace_content`: Replaces content in a file (optionally using regular expressions). +# * `replace_symbol_body`: Replaces the full definition of a symbol using the language server backend. +# * `safe_delete_symbol`: # * `search_for_pattern`: Performs a search for a pattern in the project. -# * `summarize_changes`: Provides instructions for summarizing the changes made to the codebase. -# * `switch_modes`: Activates modes by providing a list of their names -# * `think_about_collected_information`: Thinking tool for pondering the completeness of collected information. -# * `think_about_task_adherence`: Thinking tool for determining whether the agent is still on track with the current task. -# * `think_about_whether_you_are_done`: Thinking tool for determining whether the task is truly completed. -# * `write_memory`: Writes a named memory (for future reference) to Serena's project-specific memory store. +# * `write_memory`: Write some information (utf-8-encoded) about this project that can be useful for future tasks to a memory in md format. +# The memory name should be meaningful. excluded_tools: [] # list of tools to include that would otherwise be disabled (particularly optional tools that are disabled by default). diff --git a/src/serena/tools/config_tools.py b/src/serena/tools/config_tools.py index 0e92924a..17ffe74b 100644 --- a/src/serena/tools/config_tools.py +++ b/src/serena/tools/config_tools.py @@ -51,27 +51,6 @@ class RemoveProjectTool(Tool, ToolMarkerDoesNotRequireActiveProject, ToolMarkerO return f"Successfully removed project '{project_name}' from configuration." -class SwitchModesTool(Tool, ToolMarkerOptional): - """ - Activates modes by providing a list of their names - """ - - def apply(self, modes: list[str]) -> str: - """ - Activates the desired modes, like ["editing", "interactive"] or ["planning", "one-shot"] - - :param modes: the names of the modes to activate - """ - self.agent.set_modes(modes) - - # Inform the Agent about the activated modes and the currently active tools - mode_instances = self.agent.get_active_modes() - result_str = f"Active modes: {', '.join([mode.name for mode in mode_instances])}" + "\n" - result_str += "\n".join([mode_instance.prompt for mode_instance in mode_instances]) + "\n" - result_str += f"Currently active tools: {', '.join(self.agent.get_active_tool_names())}" - return result_str - - class GetCurrentConfigTool(Tool): """ Prints the current configuration of the agent, including the active and available projects, tools, contexts, and modes. diff --git a/src/serena/tools/tools_base.py b/src/serena/tools/tools_base.py index cb2b299d..bb474349 100644 --- a/src/serena/tools/tools_base.py +++ b/src/serena/tools/tools_base.py @@ -429,6 +429,15 @@ tool_packages = ["serena.tools"] @singleton class ToolRegistry: + _deleted_tools: list[str] = [ + "think_about_collected_information", + "think_about_collected_information", + "prepare_for_new_conversation", + "summarize_changes", + "think_about_whether_you_are_done", + "switch_modes", + ] + def __init__(self) -> None: self._tool_dict: dict[str, RegisteredTool] = {} inclusion_predicate = lambda c: "apply" in c.__dict__ # include only concrete tool classes that implement apply @@ -518,3 +527,15 @@ class ToolRegistry: def is_valid_tool_name(self, tool_name: str) -> bool: return tool_name in self._tool_dict + + def check_valid_tool_name(self, tool_name: str, caller_context_for_logging: str = "") -> bool: + """Returns True if the tool name is valid, False if it is deleted, and raises ValueError if it is invalid.""" + if self.is_deleted_tool_name(tool_name): + log.warning(f"Tool name is deleted: {tool_name}{caller_context_for_logging}") + return False + if not self.is_valid_tool_name(tool_name): + raise ValueError(f"Invalid tool name: {tool_name}{caller_context_for_logging}") + return True + + def is_deleted_tool_name(self, tool_name: str) -> bool: + return tool_name in self._deleted_tools diff --git a/src/serena/tools/workflow_tools.py b/src/serena/tools/workflow_tools.py index 343f26e2..e8bc67b4 100644 --- a/src/serena/tools/workflow_tools.py +++ b/src/serena/tools/workflow_tools.py @@ -4,7 +4,7 @@ Tools supporting the general workflow of the agent import platform -from serena.tools import Tool, ToolMarkerDoesNotRequireActiveProject, ToolMarkerOptional +from serena.tools import Tool, ToolMarkerDoesNotRequireActiveProject class CheckOnboardingPerformedTool(Tool): @@ -50,74 +50,6 @@ class OnboardingTool(Tool): return self.prompt_factory.create_onboarding_prompt(system=system) -class ThinkAboutCollectedInformationTool(Tool, ToolMarkerOptional): - """ - Thinking tool for pondering the completeness of collected information. - """ - - def apply(self) -> str: - """ - Think about the collected information and whether it is sufficient and relevant. - This tool should ALWAYS be called after you have completed a non-trivial sequence of searching steps like - find_symbol, find_referencing_symbols, search_files_for_pattern, read_file, etc. - """ - return self.prompt_factory.create_think_about_collected_information() - - -class ThinkAboutTaskAdherenceTool(Tool, ToolMarkerOptional): - """ - Thinking tool for determining whether the agent is still on track with the current task. - """ - - def apply(self) -> str: - """ - Think about the task at hand and whether you are still on track. - Especially important if the conversation has been going on for a while and there - has been a lot of back and forth. - - This tool should ALWAYS be called before you insert, replace, or delete code. - """ - return self.prompt_factory.create_think_about_task_adherence() - - -class ThinkAboutWhetherYouAreDoneTool(Tool, ToolMarkerOptional): - """ - Thinking tool for determining whether the task is truly completed. - """ - - def apply(self) -> str: - """ - Whenever you feel that you are done with what the user has asked for, it is important to call this tool. - """ - return self.prompt_factory.create_think_about_whether_you_are_done() - - -class SummarizeChangesTool(Tool, ToolMarkerOptional): - """ - Provides instructions for summarizing the changes made to the codebase. - """ - - def apply(self) -> str: - """ - Summarize the changes you have made to the codebase. - This tool should always be called after you have fully completed any non-trivial coding task, - but only after the think_about_whether_you_are_done call. - """ - return self.prompt_factory.create_summarize_changes() - - -class PrepareForNewConversationTool(Tool): - """ - Provides instructions for preparing for a new conversation (in order to continue with the necessary context). - """ - - def apply(self) -> str: - """ - Instructions for preparing for a new conversation. This tool should only be called on explicit user request. - """ - return self.prompt_factory.create_prepare_for_new_conversation() - - class InitialInstructionsTool(Tool, ToolMarkerDoesNotRequireActiveProject): """ Provides instructions Serena usage (i.e. the 'Serena Instructions Manual')