Project server:

- query_project: Support use of project root instead of project name
  - list_queryable_projects: Return both project names and project roots

Resolves #1388
This commit is contained in:
Dominik Jain authored and Dominik Jain committed 2026-04-21 17:48:12 +02:00
1 parent 4e0e7cd668
commit a6877c4419
3 files changed
+25 -21

No files matched your search

+3
View File
@@ -22,6 +22,9 @@ Status of the `main` branch. Changes prior to the next official version change w
- Fix: restricted `insert_after_symbol` to raise if used on an assignment or similar (can't reliably determine the symbol range)
- Fix: Failure to collect project ignore spec now logs the error and downstream tasks fail fast, fixing hanging LS initialisation
- Improve loading of `project.yml` files: Gracefully handle user errors involving incorrect use of None/empty instead of list
- Project server:
- `query_project`: Support use of project root instead of project name #1388
- `list_queryable_projects`: Return both project names and project roots
* JetBrains:
- `Move` and `SafeDelete` tools: transform empty string to None (counteracts client errors)
+17 -14
View File
@@ -53,7 +53,7 @@ class ProjectServer:
serena_config.language_backend = LanguageBackend.LSP
self._agent = SerenaAgent(serena_config=serena_config)
self._loaded_projects_by_name: dict[str, "Project"] = {}
self._loaded_projects_by_root: dict[str, "Project"] = {}
# create the Flask application
self._app = Flask(__name__)
@@ -69,20 +69,23 @@ class ProjectServer:
query_request = QueryProjectRequest.model_validate(request.get_json())
return self._query_project(query_request)
def _get_project(self, project_name: str) -> "Project":
def _get_project(self, project_root_or_name: str) -> "Project":
"""Gets the project with the given name, loading it if necessary."""
if project_name in self._loaded_projects_by_name:
return self._loaded_projects_by_name[project_name]
else:
serena_config = self._agent.serena_config
registered_project = serena_config.get_registered_project(project_name)
if registered_project is None:
raise ValueError(f"Project '{project_name}' is not registered with Serena.")
with LogTime(f"Loading project '{project_name}'"):
project = registered_project.get_project_instance(serena_config)
project.create_language_server_manager()
self._loaded_projects_by_name[project_name] = project
return project
serena_config = self._agent.serena_config
registered_project = serena_config.get_registered_project(project_root_or_name)
if registered_project is None:
raise ValueError(f"Project '{project_root_or_name}' is not registered with Serena.")
key = str(registered_project.project_root)
if key in self._loaded_projects_by_root:
return self._loaded_projects_by_root[key]
with LogTime(f"Loading project '{project_root_or_name}'"):
project = registered_project.get_project_instance(serena_config)
project.create_language_server_manager()
self._loaded_projects_by_root[key] = project
return project
def _query_project(self, req: QueryProjectRequest) -> str:
"""Handle a /query_project request by invoking the agent on the specified project and tool."""
+5 -7
View File
@@ -16,6 +16,7 @@ class ListQueryableProjectsTool(Tool, ToolMarkerOptional, ToolMarkerDoesNotRequi
Lists available projects that can be queried with `query_project_tool`.
:param symbol_access: whether to return only projects for which symbol access is available. Default: true
:return: project names and roots
"""
# determine relevant projects
registered_projects = self.agent.serena_config.projects
@@ -31,12 +32,9 @@ class ListQueryableProjectsTool(Tool, ToolMarkerOptional, ToolMarkerDoesNotRequi
else:
relevant_projects = registered_projects
# return project names, excluding the active project (if any)
project_names = [p.project_name for p in relevant_projects]
active_project = self.agent.get_active_project()
if active_project is not None:
project_names = [n for n in project_names if n != active_project.project_name]
return self._to_json(project_names)
# return project names and roots
result = {p.project_name: str(p.project_root) for p in relevant_projects}
return self._to_json(result)
class QueryProjectTool(Tool, ToolMarkerOptional, ToolMarkerDoesNotRequireActiveProject):
@@ -50,7 +48,7 @@ class QueryProjectTool(Tool, ToolMarkerOptional, ToolMarkerDoesNotRequireActiveP
Queries a project by executing a read-only Serena tool. The tool will be executed in the context of the project.
Use this to query information from projects other than the activated project.
:param project_name: the name of the project to query
:param project_name: the name of the project to query (or root path)
:param tool_name: the name of the tool to execute in the other project. The tool must be read-only.
:param tool_params_json: the parameters to pass to the tool, encoded as a JSON string
"""