mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-03 09:13:49 +00:00
Add a tool name replacement mapping for the generation of prompts
This commit is contained in:
1 parent
acee002dc4
commit
9abfc3d1be
8 files changed
+67
-17
No files matched your search
+3
-2
@@ -14,8 +14,9 @@ Status of the `main` branch. Changes prior to the next official version change w
|
||||
incorrect file access if a corresponding local file existed (e.g. `./antigravity` binary);
|
||||
file access is now guarded with path detection (file ending or path separator must be present)
|
||||
- Allow `query_project` tool to access read-only tools that are not enabled in the current configuration
|
||||
- Fix: JetBrains mode prompt was not provided to agents; The mode is now treated as a (background) base mode
|
||||
in `ActiveModes` which reduces the surface for issues pertaining to custom handling of modes.
|
||||
- Adjust prompt generation mechanism to use newly introduced tool name mapping `tool_names`, allowing
|
||||
prompts to directly use tool names that match the active language backend (and removing the need
|
||||
for additional prompts that explain tool name differences)
|
||||
- Improve quoting/escaping of arguments in shell executions on Windows (via `oslex` dependency)
|
||||
|
||||
* Language Servers:
|
||||
|
||||
@@ -284,6 +284,7 @@ ignore = [
|
||||
"UP042", # wants str,Enum -> StrEnum (breaking change)
|
||||
"PLW0108", # unnecessary lambda (style preference)
|
||||
"PLC0207", # split vs rsplit optimization (style preference)
|
||||
"RSE102", # wants to force use of raise with class instead of instance (style preference)
|
||||
]
|
||||
unfixable = ["F841", "F601", "F602", "B018"]
|
||||
extend-fixable = ["F401", "B905", "W291"]
|
||||
|
||||
+31
-1
@@ -647,6 +647,9 @@ class SerenaAgent:
|
||||
else:
|
||||
log.info(f"Using language backend from global configuration: {self._language_backend.name}")
|
||||
|
||||
# create the tool names mapping for prompts
|
||||
self._prompt_tool_names_mapping = self._create_prompt_tool_names_mapping(self._language_backend)
|
||||
|
||||
# create executor for starting the language server and running tools in another thread
|
||||
# This executor is used to achieve linear task execution
|
||||
self._task_executor = TaskExecutor("SerenaAgentTaskExecutor", self._task_completion_callback)
|
||||
@@ -927,9 +930,35 @@ class SerenaAgent:
|
||||
"""
|
||||
return self._active_modes
|
||||
|
||||
@staticmethod
|
||||
def _create_prompt_tool_names_mapping(language_backend: LanguageBackend) -> dict[str, str]:
|
||||
"""
|
||||
Creates a mapping from tool names to new tool names, which take into consideration
|
||||
|
||||
* legacy tool names, where the name was changed and
|
||||
* LSP tools which are functionally replaced by other tools due to the active language backend
|
||||
(e.g. "find_symbol" being replaced by "jet_brains_find_symbol" in JetBrains mode).
|
||||
|
||||
The mapping is intended to be used for the generation of prompts, such that prompts can
|
||||
refer to tool names as `{{ tool_names["find_symbol"] }}`, and the mapping will ensure that
|
||||
the correct tool name is used in the prompt based on the active language backend.
|
||||
|
||||
:return: the mapping from tool names to new tool names
|
||||
"""
|
||||
result = dict(ToolSet.LEGACY_TOOL_NAME_MAPPING)
|
||||
class_replacements = language_backend.get_lsp_tool_class_replacements()
|
||||
for tool_class in ToolRegistry().get_all_tool_classes():
|
||||
new_tool_class: type[Tool] = class_replacements.get(tool_class, tool_class)
|
||||
result[tool_class.get_name_from_cls()] = new_tool_class.get_name_from_cls()
|
||||
return result
|
||||
|
||||
def _format_prompt(self, prompt_template: str) -> str:
|
||||
template = JinjaTemplate(prompt_template)
|
||||
return template.render(available_tools=self._exposed_tools.tool_names, available_markers=self._exposed_tools.tool_marker_names)
|
||||
return template.render(
|
||||
available_tools=self._exposed_tools.tool_names,
|
||||
available_markers=self._exposed_tools.tool_marker_names,
|
||||
tool_names=self._prompt_tool_names_mapping,
|
||||
)
|
||||
|
||||
def create_connection_prompt(self) -> str:
|
||||
"""
|
||||
@@ -969,6 +998,7 @@ class SerenaAgent:
|
||||
available_tools=available_tools.tool_names,
|
||||
available_markers=available_markers,
|
||||
global_memories_list=global_memories_str,
|
||||
tool_names=self._prompt_tool_names_mapping,
|
||||
)
|
||||
|
||||
# provide the project activation message if it hasn't yet been provided
|
||||
|
||||
@@ -42,6 +42,7 @@ from ..util.dataclass import get_dataclass_default
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from ..project import Project
|
||||
from ..tools.tools_base import Tool
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
T = TypeVar("T")
|
||||
@@ -217,6 +218,28 @@ class LanguageBackend(Enum):
|
||||
def is_jetbrains(self) -> bool:
|
||||
return self == LanguageBackend.JETBRAINS
|
||||
|
||||
def get_lsp_tool_class_replacements(self) -> "dict[type[Tool], type[Tool]]":
|
||||
"""
|
||||
:return: mapping from LSP tool classes to replacement tool classes (functional replacements)
|
||||
"""
|
||||
match self:
|
||||
case LanguageBackend.LSP:
|
||||
return {}
|
||||
case LanguageBackend.JETBRAINS:
|
||||
from ..tools import jetbrains_tools, symbol_tools
|
||||
|
||||
return {
|
||||
symbol_tools.FindSymbolTool: jetbrains_tools.JetBrainsFindSymbolTool,
|
||||
symbol_tools.GetSymbolsOverviewTool: jetbrains_tools.JetBrainsGetSymbolsOverviewTool,
|
||||
symbol_tools.FindReferencingSymbolsTool: jetbrains_tools.JetBrainsFindReferencingSymbolsTool,
|
||||
symbol_tools.FindImplementationsTool: jetbrains_tools.JetBrainsFindImplementationsTool,
|
||||
symbol_tools.FindDeclarationTool: jetbrains_tools.JetBrainsFindDeclarationTool,
|
||||
symbol_tools.RenameSymbolTool: jetbrains_tools.JetBrainsRenameTool,
|
||||
symbol_tools.SafeDeleteSymbol: jetbrains_tools.JetBrainsSafeDeleteTool,
|
||||
}
|
||||
case _:
|
||||
raise NotImplementedError()
|
||||
|
||||
|
||||
class LineEnding(Enum):
|
||||
"""Line ending convention for file writes."""
|
||||
|
||||
@@ -42,6 +42,7 @@ class PromptFactory(PromptFactoryBase):
|
||||
context_system_prompt: Any,
|
||||
global_memories_list: Any,
|
||||
mode_system_prompts: Any,
|
||||
tool_names: Any,
|
||||
) -> str:
|
||||
return self._render_prompt("system_prompt", locals())
|
||||
|
||||
|
||||
@@ -1,11 +1,5 @@
|
||||
description: JetBrains tools replace language server-based tools
|
||||
prompt: |
|
||||
You have access to the very powerful JetBrains tools for symbolic operations.
|
||||
These partly replace regular tools you were informed about:
|
||||
* `jet_brains_find_symbol` replaces `find_symbol`
|
||||
* `jet_brains_find_referencing_symbols` replaces `find_referencing_symbols`
|
||||
* `jet_brains_get_symbols_overview` replaces `get_symbols_overview`
|
||||
* `jet_brains_rename` replaces `rename_symbol`
|
||||
prompt:
|
||||
excluded_tools:
|
||||
- find_symbol
|
||||
- find_referencing_symbols
|
||||
|
||||
@@ -21,9 +21,9 @@ prompt: |
|
||||
If you need to replace the definition of a symbol, use the `replace_symbol_body` tool.
|
||||
If you want to add some new code at the end of the file, use the `insert_after_symbol` tool with the last top-level symbol in the file.
|
||||
Similarly, you can use `insert_before_symbol` with the first top-level symbol in the file to insert code at the beginning of a file.
|
||||
You can understand relationships between symbols by using the `find_referencing_symbols` tool. If not explicitly requested otherwise by the user,
|
||||
You can understand relationships between symbols by using the ``{{ tool_names['find_referencing_symbols'] }}`` tool. If not explicitly requested otherwise by the user,
|
||||
you make sure that when you edit a symbol, the change is either backward-compatible or you find and update all references as needed.
|
||||
The `find_referencing_symbols` tool will give you code snippets around the references as well as symbolic information.
|
||||
The `{{ tool_names['find_referencing_symbols'] }}` tool will give you code snippets around the references as well as symbolic information.
|
||||
You can assume that all symbol editing tools are reliable, so you never need to verify the results if the tools return without error.
|
||||
|
||||
{% if 'replace_content' in available_tools %}
|
||||
|
||||
@@ -26,14 +26,14 @@ prompts:
|
||||
{% endif %}
|
||||
|
||||
{% if 'ToolMarkerSymbolicRead' in available_markers %}
|
||||
Symbols are identified by their `name_path` and `relative_path` (see the description of the `find_symbol` tool).
|
||||
You can get information about the symbols in a file by using the `get_symbols_overview` tool or use the `find_symbol` to search.
|
||||
Symbols are identified by their `name_path` and `relative_path` (see the description of the `{{ tool_names['find_symbol'] }}` tool).
|
||||
You can get information about the symbols in a file by using the `{{ tool_names['get_symbols_overview'] }}` tool or use the `{{ tool_names['find_symbol'] }}` to search.
|
||||
You only read the bodies of symbols when you need to (e.g. if you want to fully understand or edit it).
|
||||
For example, if you are working with Python code and already know that you need to read the body of the constructor of the class Foo, you can directly
|
||||
use `find_symbol` with name path pattern `Foo/__init__` and `include_body=True`. If you don't know yet which methods in `Foo` you need to read or edit,
|
||||
you can use `find_symbol` with name path pattern `Foo`, `include_body=False` and `depth=1` to get all (top-level) methods of `Foo` before proceeding
|
||||
use `{{ tool_names['find_symbol'] }}` with name path pattern `Foo/__init__` and `include_body=True`. If you don't know yet which methods in `Foo` you need to read or edit,
|
||||
you can use `{{ tool_names['find_symbol'] }}` with name path pattern `Foo`, `include_body=False` and `depth=1` to get all (top-level) methods of `Foo` before proceeding
|
||||
to read the desired methods with `include_body=True`.
|
||||
You can understand relationships between symbols by using the `find_referencing_symbols` tool.
|
||||
You can understand relationships between symbols by using the `{{ tool_names['find_referencing_symbols'] }}` tool.
|
||||
{% endif %}
|
||||
|
||||
{% if 'read_memory' in available_tools -%}
|
||||
|
||||
Reference in new issue
Block a user