get_symbols_overview
Retrieve a high-level overview of top-level code symbols in a file, providing essential insights for understanding its structure. Ideal for initial analysis when exploring unfamiliar files.
Instructions
Use this tool to get a high-level understanding of the code symbols in a file. This should be the first tool to call when you want to understand a new file, unless you already know what you are looking for. Returns a JSON object containing info about top-level symbols in the file.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| max_answer_chars | No | If the overview is longer than this number of characters, no content will be returned. Don't adjust unless there is really no other way to get the content required for the task. | |
| relative_path | Yes | The relative path to the file to get the overview of. |
Implementation Reference
- src/serena/tools/symbol_tools.py:48-77 (handler)Primary handler for the 'get_symbols_overview' tool. The apply method fetches top-level symbols from the specified file using the language server symbol retriever and returns a JSON overview.class GetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead): """ Gets an overview of the top-level symbols defined in a given file. """ def apply(self, relative_path: str, max_answer_chars: int = -1) -> str: """ Use this tool to get a high-level understanding of the code symbols in a file. This should be the first tool to call when you want to understand a new file, unless you already know what you are looking for. :param relative_path: the relative path to the file to get the overview of :param max_answer_chars: if the overview is longer than this number of characters, no content will be returned. -1 means the default value from the config will be used. Don't adjust unless there is really no other way to get the content required for the task. :return: a JSON object containing info about top-level symbols in the file """ symbol_retriever = self.create_language_server_symbol_retriever() file_path = os.path.join(self.project.project_root, relative_path) # The symbol overview is capable of working with both files and directories, # but we want to ensure that the user provides a file path. if not os.path.exists(file_path): raise FileNotFoundError(f"File or directory {relative_path} does not exist in the project.") if os.path.isdir(file_path): raise ValueError(f"Expected a file path, but got a directory path: {relative_path}. ") result = symbol_retriever.get_symbol_overview(relative_path)[relative_path] result_json_str = self._to_json([dataclasses.asdict(i) for i in result]) return self._limit_length(result_json_str, max_answer_chars)
- src/serena/tools/tools_base.py:359-430 (registration)ToolRegistry automatically discovers and registers all subclasses of Tool in the serena.tools package, mapping GetSymbolsOverviewTool to the name 'get_symbols_overview'. This is used by the agent to instantiate and expose tools.class ToolRegistry: def __init__(self) -> None: self._tool_dict: dict[str, RegisteredTool] = {} for cls in iter_subclasses(Tool): if not cls.__module__.startswith("serena.tools"): continue is_optional = issubclass(cls, ToolMarkerOptional) name = cls.get_name_from_cls() if name in self._tool_dict: raise ValueError(f"Duplicate tool name found: {name}. Tool classes must have unique names.") self._tool_dict[name] = RegisteredTool(tool_class=cls, is_optional=is_optional, tool_name=name) def get_tool_class_by_name(self, tool_name: str) -> type[Tool]: return self._tool_dict[tool_name].tool_class def get_all_tool_classes(self) -> list[type[Tool]]: return list(t.tool_class for t in self._tool_dict.values()) def get_tool_classes_default_enabled(self) -> list[type[Tool]]: """ :return: the list of tool classes that are enabled by default (i.e. non-optional tools). """ return [t.tool_class for t in self._tool_dict.values() if not t.is_optional] def get_tool_classes_optional(self) -> list[type[Tool]]: """ :return: the list of tool classes that are optional (i.e. disabled by default). """ return [t.tool_class for t in self._tool_dict.values() if t.is_optional] def get_tool_names_default_enabled(self) -> list[str]: """ :return: the list of tool names that are enabled by default (i.e. non-optional tools). """ return [t.tool_name for t in self._tool_dict.values() if not t.is_optional] def get_tool_names_optional(self) -> list[str]: """ :return: the list of tool names that are optional (i.e. disabled by default). """ return [t.tool_name for t in self._tool_dict.values() if t.is_optional] def get_tool_names(self) -> list[str]: """ :return: the list of all tool names. """ return list(self._tool_dict.keys()) def print_tool_overview( self, tools: Iterable[type[Tool] | Tool] | None = None, include_optional: bool = False, only_optional: bool = False ) -> None: """ Print a summary of the tools. If no tools are passed, a summary of the selection of tools (all, default or only optional) is printed. """ if tools is None: if only_optional: tools = self.get_tool_classes_optional() elif include_optional: tools = self.get_all_tool_classes() else: tools = self.get_tool_classes_default_enabled() tool_dict: dict[str, type[Tool] | Tool] = {} for tool_class in tools: tool_dict[tool_class.get_name_from_cls()] = tool_class for tool_name in sorted(tool_dict.keys()): tool_class = tool_dict[tool_name] print(f" * `{tool_name}`: {tool_class.get_tool_description().strip()}") def is_valid_tool_name(self, tool_name: str) -> bool: return tool_name in self._tool_dict
- Helper function used by symbol tools to sanitize symbol dictionaries by removing redundant fields like 'location' and 'name'.def _sanitize_symbol_dict(symbol_dict: dict[str, Any]) -> dict[str, Any]: """ Sanitize a symbol dictionary inplace by removing unnecessary information. """ # We replace the location entry, which repeats line information already included in body_location # and has unnecessary information on column, by just the relative path. symbol_dict = copy(symbol_dict) s_relative_path = symbol_dict.get("location", {}).get("relative_path") if s_relative_path is not None: symbol_dict["relative_path"] = s_relative_path symbol_dict.pop("location", None) # also remove name, name_path should be enough symbol_dict.pop("name") return symbol_dict
- JetBrains-specific handler for a similar tool (jetbrains_get_symbols_overview), using the JetBrains plugin client.class JetBrainsGetSymbolsOverviewTool(Tool, ToolMarkerSymbolicRead, ToolMarkerOptional): """ Retrieves an overview of the top-level symbols within a specified file using the JetBrains backend """ def apply( self, relative_path: str, max_answer_chars: int = -1, ) -> str: """ Gets an overview of the top-level symbols in the given file. Calling this is often a good idea before more targeted reading, searching or editing operations on the code symbols. Before requesting a symbol overview, it is usually a good idea to narrow down the scope of the overview by first understanding the basic directory structure of the repository that you can get from memories or by using the `list_dir` and `find_file` tools (or similar). :param relative_path: the relative path to the file to get the overview of :param max_answer_chars: max characters for the JSON result. If exceeded, no content is returned. -1 means the default value from the config will be used. :return: a JSON object containing the symbols """ with JetBrainsPluginClient.from_project(self.project) as client: response_dict = client.get_symbols_overview( relative_path=relative_path, ) result = self._to_json(response_dict) return self._limit_length(result, max_answer_chars)