mirror of
https://github.com/tiennm99/serena.git
synced 2026-10-13 18:16:10 +00:00
Added an indexing command as uv script
This commit is contained in:
1 parent
2e3eda72ba
commit
918ff32dcc
3 files changed
+27
-3
No files matched your search
@@ -40,6 +40,7 @@ dependencies = [
|
||||
|
||||
[project.scripts]
|
||||
serena-mcp-server = "serena.mcp:start_mcp_server"
|
||||
index-project = "serena.agent:index_project"
|
||||
|
||||
[project.license]
|
||||
text = "MIT"
|
||||
|
||||
@@ -1607,7 +1607,7 @@ class LanguageServer:
|
||||
"""
|
||||
parsed_files = await self.request_parsed_files()
|
||||
files_processed = 0
|
||||
for relative_file_path in tqdm.tqdm(parsed_files, disable=not progress_bar):
|
||||
for relative_file_path in tqdm.tqdm(parsed_files, disable=not progress_bar, desc="Indexing (files)"):
|
||||
await self.request_document_symbols(relative_file_path, include_body=False)
|
||||
await self.request_document_symbols(relative_file_path, include_body=True)
|
||||
files_processed += 1
|
||||
@@ -2205,7 +2205,7 @@ class SyncLanguageServer:
|
||||
self.language_server.logger.log("Async shutdown tasks completed, returning to main thread", logging.DEBUG)
|
||||
# Note: NOT calling loop.stop() here - let main thread do it
|
||||
|
||||
def stop(self, shutdown_timeout: float = 5.0) -> None:
|
||||
def stop(self, shutdown_timeout: float = 2.0) -> None:
|
||||
"""
|
||||
Stops the language server and robustly cleans up all associated resources,
|
||||
including the asyncio event loop, to prevent hangs on process exit.
|
||||
@@ -2230,26 +2230,30 @@ class SyncLanguageServer:
|
||||
|
||||
if not is_windows:
|
||||
# 2. Graceful shutdown for Linux/Unix - try proper async cleanup first
|
||||
self.language_server.logger.log("Starting graceful shutdown", logging.INFO)
|
||||
shutdown_future = None
|
||||
if self.loop and self.loop.is_running():
|
||||
shutdown_future = asyncio.run_coroutine_threadsafe(self._shutdown_and_stop_loop(), self.loop)
|
||||
|
||||
# 3. Wait for the background thread to exit
|
||||
if self.loop_thread:
|
||||
self.language_server.logger.log("Waiting for event loop thread to exit", logging.INFO)
|
||||
self.loop_thread.join(timeout=shutdown_timeout)
|
||||
if self.loop_thread.is_alive():
|
||||
self.language_server.logger.log("Event loop thread did not terminate within timeout", logging.WARNING)
|
||||
|
||||
# 4. Wait for the shutdown coroutine to complete if it was scheduled
|
||||
if shutdown_future:
|
||||
self.language_server.logger.log("Waiting for async shutdown to complete", logging.INFO)
|
||||
try:
|
||||
shutdown_future.result(timeout=2.0)
|
||||
shutdown_future.result(timeout=shutdown_timeout)
|
||||
self.language_server.logger.log("Graceful async shutdown completed", logging.DEBUG)
|
||||
except Exception as e:
|
||||
self.language_server.logger.log(f"Async shutdown failed: {e}", logging.WARNING)
|
||||
|
||||
# 5. Close the loop properly after graceful shutdown
|
||||
if self.loop and not self.loop.is_closed():
|
||||
self.language_server.logger.log("Closing event loop", logging.INFO)
|
||||
try:
|
||||
self.loop.close()
|
||||
self.language_server.logger.log("Event loop closed successfully", logging.DEBUG)
|
||||
|
||||
@@ -23,6 +23,7 @@ from pathlib import Path
|
||||
from types import TracebackType
|
||||
from typing import TYPE_CHECKING, Any, Literal, Self, TypeVar, Union, cast
|
||||
|
||||
import click
|
||||
import yaml
|
||||
from mcp.server.fastmcp.utilities.func_metadata import FuncMetadata, func_metadata
|
||||
from overrides import override
|
||||
@@ -656,6 +657,7 @@ def create_ls_for_project(
|
||||
trace_lsp_communication=trace_lsp_communication,
|
||||
)
|
||||
ls_logger = MultilspyLogger(log_level=log_level)
|
||||
logging.basicConfig(format=LOG_DEFAULT_FORMAT, level=log_level, force=True)
|
||||
log.info(f"Creating language server instance for {project_instance.project_root}.")
|
||||
return SyncLanguageServer.create(
|
||||
multilspy_config,
|
||||
@@ -665,6 +667,23 @@ def create_ls_for_project(
|
||||
)
|
||||
|
||||
|
||||
@click.command()
|
||||
@click.argument("project", type=click.Path(exists=True))
|
||||
@click.option("--log-level", type=click.Choice(["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]), default="WARNING")
|
||||
def index_project(project: str, log_level: str = "INFO") -> None:
|
||||
"""
|
||||
Index a project by saving the symbols of files to Serena's language server cache.
|
||||
|
||||
:param project: the project to index
|
||||
"""
|
||||
log_level_int = logging.getLevelNamesMapping()[log_level.upper()]
|
||||
project = os.path.abspath(project)
|
||||
log.info(f"Indexing project {project}")
|
||||
ls = create_ls_for_project(project, log_level=log_level_int)
|
||||
with ls.start_server():
|
||||
ls.index_repository()
|
||||
|
||||
|
||||
class SerenaAgent:
|
||||
def __init__(
|
||||
self,
|
||||
|
||||
Reference in new issue
Block a user