From 6941af6aabefa7220a2289c9024f89aa9b7cfe88 Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Tue, 26 May 2026 14:58:54 +0200 Subject: [PATCH 1/3] Bumped pythonnet, added serena-agent cli alias command The latter enables running uvx serena-agent as entrypoint, otherwise one needs uvx --from serena-agent serena --- pyproject.toml | 3 ++- uv.lock | 15 ++++++++------- 2 files changed, 10 insertions(+), 8 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index a9b53049..a544f193 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -52,7 +52,7 @@ dependencies = [ "filelock==3.25.2", "cryptography==46.0.7", "regex==2026.2.28", - "pythonnet==3.1.0-rc0 ; sys_platform == 'win32'", + "pythonnet==3.1.0 ; sys_platform == 'win32'", ] @@ -64,6 +64,7 @@ explicit = true [project.scripts] serena = "serena.cli:top_level" +serena-agent = "serena.cli:top_level" serena-hooks = "serena.hooks:hook_commands" [project.license] diff --git a/uv.lock b/uv.lock index 41fab003..7c3141fb 100644 --- a/uv.lock +++ b/uv.lock @@ -421,14 +421,14 @@ wheels = [ [[package]] name = "clr-loader" -version = "0.2.10" +version = "0.3.1" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "cffi" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/18/24/c12faf3f61614b3131b5c98d3bf0d376b49c7feaa73edca559aeb2aee080/clr_loader-0.2.10.tar.gz", hash = "sha256:81f114afbc5005bafc5efe5af1341d400e22137e275b042a8979f3feb9fc9446", size = 83605, upload-time = "2026-01-03T23:13:06.984Z" } +sdist = { url = "https://files.pythonhosted.org/packages/e4/46/7eea92b6aa2d68af78e049cbecec5f757f1aad44ecdecdc16bbad7eead51/clr_loader-0.3.1.tar.gz", hash = "sha256:2e073e9aaf49d1ae2f56ecba27987ad5fb68be4bcd9dd34a5bed8f0e4e128366", size = 86805, upload-time = "2026-04-18T17:49:44.287Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/c8/61/cf819f8e8bb4d4c74661acf2498ba8d4a296714be3478d21eaabf64f5b9b/clr_loader-0.2.10-py3-none-any.whl", hash = "sha256:ebbbf9d511a7fe95fa28a95a4e04cd195b097881dfe66158dc2c281d3536f282", size = 56483, upload-time = "2026-01-03T23:13:05.439Z" }, + { url = "https://files.pythonhosted.org/packages/5e/da/ec1a6e36624000b6df0dd61183c42342ee5814c073315e802cadaad04d2f/clr_loader-0.3.1-py3-none-any.whl", hash = "sha256:cbad189de20d202a7d621956b0fc38049e13c9bf7ca2923441eff725cd121aa1", size = 55730, upload-time = "2026-04-18T17:49:42.99Z" }, ] [[package]] @@ -2347,14 +2347,15 @@ wheels = [ [[package]] name = "pythonnet" -version = "3.1.0rc0" +version = "3.1.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "clr-loader" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/a2/59/4295652a9a93a2bd6755ecce2dc32e3d3c704e7b8ef301946ee65c818a59/pythonnet-3.1.0rc0.tar.gz", hash = "sha256:5f0f505e100233d70864b00dc5f5dd760603cfd94ac64da5c8b0e15ed95af939", size = 241025, upload-time = "2026-02-25T10:46:53.632Z" } +sdist = { url = "https://files.pythonhosted.org/packages/05/57/da1992e44663b71365c6e842c8d7fa453d4ec45fb99a68cfee5b7e944d3c/pythonnet-3.1.0.tar.gz", hash = "sha256:7b34c382905d10a371509ffafd64cae0416305c28817738a9cd138336f4e9991", size = 250599, upload-time = "2026-05-23T20:30:21.578Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/1a/3d/a378aa74085fc6f72923d5e39fc30efbc97541cfd49b3fe0a35f20d09ff7/pythonnet-3.1.0rc0-py3-none-any.whl", hash = "sha256:286ccf23d08e1cc2b5200bb91d0ee649436d2e8386fec36a85193c66d0ff8b5b", size = 293150, upload-time = "2026-02-25T10:46:48.535Z" }, + { url = "https://files.pythonhosted.org/packages/ac/4b/52414f442624d2589f5374a48c08d5ae94f24bea67fc13a20a752884e5b7/pythonnet-3.1.0-cp310.cp311.cp312.cp313.cp314-none-any.whl", hash = "sha256:698dd88edc198819ad63b624a6ebe76208c7b46e4fe13626f65e484f0358d6ba", size = 217578, upload-time = "2026-05-23T20:30:19.527Z" }, + { url = "https://files.pythonhosted.org/packages/db/67/031124fdcb937c266a3265118525bbf6dc13b8c79786d6a7290aecb6e7bb/pythonnet-3.1.0-cp310.cp311.cp312.cp313.cp314-none-win32.win_amd64.whl", hash = "sha256:7bdd4de03df3547a48122a3989265c8b31d5be0d19dadffa009eec7df8085e0b", size = 1644898, upload-time = "2026-05-23T20:30:16.213Z" }, ] [[package]] @@ -2962,7 +2963,7 @@ requires-dist = [ { name = "pytest-xdist", marker = "extra == 'dev'", specifier = "==3.8.0" }, { name = "python-dotenv", specifier = "==1.2.2" }, { name = "python-multipart", specifier = "==0.0.27" }, - { name = "pythonnet", marker = "sys_platform == 'win32'", specifier = "==3.1.0rc0" }, + { name = "pythonnet", marker = "sys_platform == 'win32'", specifier = "==3.1.0" }, { name = "pywebview", specifier = "==6.2" }, { name = "pyyaml", specifier = "==6.0.2" }, { name = "regex", specifier = "==2026.2.28" }, From 1122166b7cfa8458fafcad99651ba40997f98be3 Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Tue, 26 May 2026 15:31:56 +0200 Subject: [PATCH 2/3] Remove pyright and fortls from serena-agent package, instead install with uvx on the fly Added a dedicated LSDependencyProvider for that --- CHANGELOG.md | 2 + pyproject.toml | 2 - src/solidlsp/language_servers/common.py | 37 ++++++++++++++ .../fortran_language_server.py | 38 +++++++-------- .../language_servers/pyright_server.py | 22 +++++---- src/solidlsp/language_servers/ty_server.py | 34 ++++--------- src/solidlsp/ls.py | 45 ++++++++++++++++- uv.lock | 48 ------------------- 8 files changed, 124 insertions(+), 104 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4411a500..088d77d9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ Status of the `main` branch. Changes prior to the next official version change w * General: - Not existing paths return `False` on is ignored checks (instead of raising an error) + - Add `serena-agent` CLI command so that `uvx serena-agent` can be used as entrypoint. + - Fortls and pyright are now installed on the fly instead of being bundled in the serena-agent package. # v1.5.1 (2026-05-18) diff --git a/pyproject.toml b/pyproject.toml index a544f193..5d856691 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -18,8 +18,6 @@ classifiers = [ ] dependencies = [ "requests==2.33.0", - "pyright==1.1.403", - "fortls==3.2.2", "overrides==7.7.0", "python-dotenv==1.2.2", "mcp==1.27.0", diff --git a/src/solidlsp/language_servers/common.py b/src/solidlsp/language_servers/common.py index 20017630..16a97411 100644 --- a/src/solidlsp/language_servers/common.py +++ b/src/solidlsp/language_servers/common.py @@ -3,6 +3,7 @@ from __future__ import annotations import logging import os import platform +import shutil import subprocess from collections.abc import Iterable, Mapping, Sequence from dataclasses import dataclass, replace @@ -154,6 +155,42 @@ class RuntimeDependencyCollection: ) +DEFAULT_UVX_PYTHON_VERSION = "3.13" + + +def build_uvx_launch_command( + package: str, + version: str, + entrypoint: str, + extra_args: Sequence[str] = (), + python_version: str = DEFAULT_UVX_PYTHON_VERSION, +) -> list[str]: + """Build a command that runs a pinned PyPI package's console script on demand via ``uvx`` / ``uv x``. + + Resolution order: + 1. Prefer ``uvx`` (env var ``UVX`` or PATH lookup). + 2. Fall back to ``uv x`` if only ``uv`` is on PATH. + 3. Raise ``RuntimeError`` if neither is available. + + :param package: PyPI package name (e.g. ``"pyright"``). + :param version: Pinned package version. + :param entrypoint: Console script provided by the package (e.g. ``"pyright-langserver"``). + :param extra_args: Arguments appended after the entrypoint (e.g. ``("--stdio",)``). + :param python_version: Python interpreter version passed via ``-p`` (uv will fetch it if missing). + """ + base_args = ["-p", python_version, "--from", f"{package}=={version}", entrypoint, *extra_args] + + uvx_path = os.environ.get("UVX") or shutil.which("uvx") + if uvx_path is not None: + return [uvx_path, *base_args] + + uv_path = shutil.which("uv") + if uv_path is not None: + return [uv_path, "x", *base_args] + + raise RuntimeError("Could not find 'uvx' or 'uv' in PATH. Install uv (https://docs.astral.sh/uv/).") + + def build_npm_install_command(package_name: str, version: str, registry: str | None = None) -> list[str]: """Build a pinned npm install command for a package in a Serena-managed install directory.""" command = ["npm", "install", "--prefix", "./"] diff --git a/src/solidlsp/language_servers/fortran_language_server.py b/src/solidlsp/language_servers/fortran_language_server.py index a80efc68..45d7071b 100644 --- a/src/solidlsp/language_servers/fortran_language_server.py +++ b/src/solidlsp/language_servers/fortran_language_server.py @@ -6,19 +6,26 @@ import logging import os import pathlib import re -import shutil from overrides import override from solidlsp import ls_types -from solidlsp.ls import DocumentSymbols, LSPConstants, LSPFileBuffer, SolidLanguageServer +from solidlsp.ls import ( + DocumentSymbols, + LanguageServerDependencyProvider, + LanguageServerDependencyProviderUvx, + LSPConstants, + LSPFileBuffer, + SolidLanguageServer, +) from solidlsp.ls_config import LanguageServerConfig from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams -from solidlsp.lsp_protocol_handler.server import ProcessLaunchInfo from solidlsp.settings import SolidLSPSettings log = logging.getLogger(__name__) +FORTLS_VERSION = "3.2.2" + class FortranLanguageServer(SolidLanguageServer): """Fortran Language Server implementation using fortls.""" @@ -170,24 +177,17 @@ class FortranLanguageServer(SolidLanguageServer): return DocumentSymbols(fixed_root_symbols) - @staticmethod - def _check_fortls_installation() -> str: - """Check if fortls is available.""" - fortls_path = shutil.which("fortls") - if fortls_path is None: - raise RuntimeError("fortls is not installed or not in PATH.\nInstall it with: pip install fortls") - return fortls_path - def __init__(self, config: LanguageServerConfig, repository_root_path: str, solidlsp_settings: SolidLSPSettings): - # Check fortls installation - fortls_path = self._check_fortls_installation() + super().__init__(config, repository_root_path, None, "fortran", solidlsp_settings) - # Command to start fortls language server - # fortls uses stdio for LSP communication by default - fortls_cmd = f"{fortls_path}" - - super().__init__( - config, repository_root_path, ProcessLaunchInfo(cmd=fortls_cmd, cwd=repository_root_path), "fortran", solidlsp_settings + def _create_dependency_provider(self) -> LanguageServerDependencyProvider: + return LanguageServerDependencyProviderUvx( + self._custom_settings, + self._ls_resources_dir, + package="fortls", + entrypoint="fortls", + default_version=FORTLS_VERSION, + version_setting_key="fortls_version", ) @staticmethod diff --git a/src/solidlsp/language_servers/pyright_server.py b/src/solidlsp/language_servers/pyright_server.py index 7f774836..d4aa1265 100644 --- a/src/solidlsp/language_servers/pyright_server.py +++ b/src/solidlsp/language_servers/pyright_server.py @@ -6,19 +6,20 @@ import logging import os import pathlib import re -import sys import threading from typing import cast from overrides import override -from solidlsp.ls import LanguageServerDependencyProvider, LanguageServerDependencyProviderSinglePath, SolidLanguageServer +from solidlsp.ls import LanguageServerDependencyProvider, LanguageServerDependencyProviderUvx, SolidLanguageServer from solidlsp.ls_config import LanguageServerConfig from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.settings import SolidLSPSettings log = logging.getLogger(__name__) +PYRIGHT_VERSION = "1.1.403" + class PyrightServer(SolidLanguageServer): """ @@ -44,14 +45,15 @@ class PyrightServer(SolidLanguageServer): self.found_source_files = False def _create_dependency_provider(self) -> LanguageServerDependencyProvider: - return self.DependencyProvider(self._custom_settings, self._ls_resources_dir) - - class DependencyProvider(LanguageServerDependencyProviderSinglePath): - def _get_or_install_core_dependency(self) -> str: - return sys.executable - - def _create_launch_command(self, core_path: str) -> list[str]: - return [core_path, "-m", "pyright.langserver", "--stdio"] + return LanguageServerDependencyProviderUvx( + self._custom_settings, + self._ls_resources_dir, + package="pyright", + entrypoint="pyright-langserver", + default_version=PYRIGHT_VERSION, + version_setting_key="pyright_version", + extra_args=("--stdio",), + ) @override def is_ignored_dirname(self, dirname: str) -> bool: diff --git a/src/solidlsp/language_servers/ty_server.py b/src/solidlsp/language_servers/ty_server.py index 0adb8f64..1e0832f0 100644 --- a/src/solidlsp/language_servers/ty_server.py +++ b/src/solidlsp/language_servers/ty_server.py @@ -10,12 +10,11 @@ You can pass the following entries in ``ls_specific_settings["python_ty"]``: import logging import os import pathlib -import shutil from typing import cast from typing_extensions import override -from solidlsp.ls import LanguageServerDependencyProvider, SolidLanguageServer +from solidlsp.ls import LanguageServerDependencyProvider, LanguageServerDependencyProviderUvx, SolidLanguageServer from solidlsp.ls_config import LanguageServerConfig from solidlsp.lsp_protocol_handler.lsp_types import InitializeParams from solidlsp.settings import SolidLSPSettings @@ -44,28 +43,15 @@ class TyLanguageServer(SolidLanguageServer): ) def _create_dependency_provider(self) -> LanguageServerDependencyProvider: - return self.DependencyProvider(self._custom_settings, self._ls_resources_dir) - - class DependencyProvider(LanguageServerDependencyProvider): - def create_launch_command(self) -> list[str]: - # respecting an explicit override - ls_path = self._custom_settings.get("ls_path") - if ls_path is not None: - return [ls_path, "server"] - - ty_version = self._custom_settings.get("ty_version", TY_VERSION) - - # preferring uvx for on-demand execution - uvx_path = os.environ.get("UVX") or shutil.which("uvx") - if uvx_path is not None: - return [uvx_path, "--from", f"ty=={ty_version}", "ty", "server"] - - # falling back to uv's uvx-compatible subcommand when only `uv` is available - uv_path = shutil.which("uv") - if uv_path is not None: - return [uv_path, "x", "--from", f"ty=={ty_version}", "ty", "server"] - - raise RuntimeError("Could not find 'uvx' or 'uv' in PATH.\nInstall uv or provide ls_specific_settings.python_ty.ls_path.") + return LanguageServerDependencyProviderUvx( + self._custom_settings, + self._ls_resources_dir, + package="ty", + entrypoint="ty", + default_version=TY_VERSION, + version_setting_key="ty_version", + extra_args=("server",), + ) @override def is_ignored_dirname(self, dirname: str) -> bool: diff --git a/src/solidlsp/ls.py b/src/solidlsp/ls.py index 64bf112c..ecf1dea7 100644 --- a/src/solidlsp/ls.py +++ b/src/solidlsp/ls.py @@ -8,7 +8,7 @@ import shutil import threading from abc import ABC, abstractmethod from collections import defaultdict -from collections.abc import Callable, Hashable, Iterator +from collections.abc import Callable, Hashable, Iterator, Sequence from contextlib import contextmanager from copy import copy from pathlib import Path, PurePath @@ -22,6 +22,7 @@ from sensai.util.string import ToStringMixin from serena.util.file_system import match_path from serena.util.text_utils import MatchedConsecutiveLines from solidlsp import ls_types +from solidlsp.language_servers.common import build_uvx_launch_command from solidlsp.ls_config import FilenameMatcher, Language, LanguageServerConfig from solidlsp.ls_exceptions import SolidLSPException from solidlsp.ls_process import LanguageServerInterface, StdioLanguageServer @@ -333,6 +334,48 @@ class LanguageServerDependencyProviderSinglePath(LanguageServerDependencyProvide """ +class LanguageServerDependencyProviderUvx(LanguageServerDependencyProvider): + """ + Dependency provider for language servers distributed as a PyPI package, run on demand via ``uvx`` / ``uv x``. + + The pinned package version can be overridden by the user via the LS-specific setting given by + ``version_setting_key``. Alternatively, the LS-specific setting "ls_path" can be set to the path of an + already-installed language server executable, in which case it is launched directly, bypassing uv entirely. + """ + + def __init__( + self, + custom_settings: "SolidLSPSettings.CustomLSSettings", + ls_resources_dir: str, + *, + package: str, + entrypoint: str, + default_version: str, + version_setting_key: str, + extra_args: Sequence[str] = (), + ): + """ + :param package: the PyPI package name (e.g. ``"pyright"``) + :param entrypoint: the console script provided by the package (e.g. ``"pyright-langserver"``) + :param default_version: the package version to pin unless overridden + :param version_setting_key: the LS-specific setting key through which the user can override the version + :param extra_args: arguments appended after the entrypoint (e.g. ``("--stdio",)``) + """ + super().__init__(custom_settings, ls_resources_dir) + self._package = package + self._entrypoint = entrypoint + self._default_version = default_version + self._version_setting_key = version_setting_key + self._extra_args = tuple(extra_args) + + def create_launch_command(self) -> list[str]: + ls_path = self._custom_settings.get("ls_path") + if ls_path is not None: + return [ls_path, *self._extra_args] + version = self._custom_settings.get(self._version_setting_key, self._default_version) + return build_uvx_launch_command(self._package, version, self._entrypoint, self._extra_args) + + class SolidLanguageServer(ABC): """ High-level abstraction for language server interaction, which wraps the underlying low-level LSP interface diff --git a/uv.lock b/uv.lock index 7c3141fb..953f8a9c 100644 --- a/uv.lock +++ b/uv.lock @@ -671,19 +671,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7f/9c/34f6962f9b9e9c71f6e5ed806e0d0ff03c9d1b0b2340088a0cf4bce09b18/flask-3.1.3-py3-none-any.whl", hash = "sha256:f4bcbefc124291925f1a26446da31a5178f9483862233b23c0c96a20701f670c", size = 103424, upload-time = "2026-02-19T05:00:56.027Z" }, ] -[[package]] -name = "fortls" -version = "3.2.2" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "json5" }, - { name = "packaging" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/c1/2b/db1e5cd07fc9e74a2e4fb8f65946f8fd79ef72211001af00982a04d977d5/fortls-3.2.2.tar.gz", hash = "sha256:b43b2b8cbd447ae848c63b8f008c2df96fd48c3a967b33f6ed64b3421496883b", size = 7085222, upload-time = "2025-03-16T18:03:11.377Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/a9/7e/41a55a49e764243fd72b1ed202a95d9a9193586d8665bdc94e4df92050e4/fortls-3.2.2-py3-none-any.whl", hash = "sha256:b7ae8378ce9741064b8340d3f1fbbbf7ab697285e174a0208fed98485c4edfe3", size = 278359, upload-time = "2025-03-16T18:03:09.969Z" }, -] - [[package]] name = "gitdb" version = "4.0.12" @@ -1135,15 +1122,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7d/4f/1195bbac8e0c2acc5f740661631d8d750dc38d4a32b23ee5df3cde6f4e0d/joblib-1.5.1-py3-none-any.whl", hash = "sha256:4719a31f054c7d766948dcd83e9613686b27114f190f717cec7eaa2084f8a74a", size = 307746, upload-time = "2025-05-23T12:04:35.124Z" }, ] -[[package]] -name = "json5" -version = "0.13.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/77/e8/a3f261a66e4663f22700bc8a17c08cb83e91fbf086726e7a228398968981/json5-0.13.0.tar.gz", hash = "sha256:b1edf8d487721c0bf64d83c28e91280781f6e21f4a797d3261c7c828d4c165bf", size = 52441, upload-time = "2026-01-01T19:42:14.99Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/d7/9e/038522f50ceb7e74f1f991bf1b699f24b0c2bbe7c390dd36ad69f4582258/json5-0.13.0-py3-none-any.whl", hash = "sha256:9a08e1dd65f6a4d4c6fa82d216cf2477349ec2346a38fd70cc11d2557499fbcc", size = 36163, upload-time = "2026-01-01T19:42:13.962Z" }, -] - [[package]] name = "jsonschema" version = "4.26.0" @@ -1616,15 +1594,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/a0/c4/c2971a3ba4c6103a3d10c4b0f24f461ddc027f0f09763220cf35ca1401b3/nest_asyncio-1.6.0-py3-none-any.whl", hash = "sha256:87af6efd6b5e897c81050477ef65c62e2b2f35d51703cae01aff2905b1852e1c", size = 5195, upload-time = "2024-01-21T14:25:17.223Z" }, ] -[[package]] -name = "nodeenv" -version = "1.10.0" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/24/bf/d1bda4f6168e0b2e9e5958945e01910052158313224ada5ce1fb2e1113b8/nodeenv-1.10.0.tar.gz", hash = "sha256:996c191ad80897d076bdfba80a41994c2b47c68e224c542b48feba42ba00f8bb", size = 55611, upload-time = "2025-12-20T14:08:54.006Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/88/b2/d0896bdcdc8d28a7fc5717c305f1a861c26e18c05047949fb371034d98bd/nodeenv-1.10.0-py2.py3-none-any.whl", hash = "sha256:5bb13e3eed2923615535339b3c620e76779af4cb4c6a90deccc9e36b274d3827", size = 23438, upload-time = "2025-12-20T14:08:52.782Z" }, -] - [[package]] name = "overrides" version = "7.7.0" @@ -2235,19 +2204,6 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2d/86/637cda4983dc0936b73a385f3906256953ac434537b812814cb0b6d231a2/pyobjc_framework_webkit-12.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:1aaa3bf12c7b68e1a36c0b294d2728e06f2cc220775e6dc4541d5046290e4dc8", size = 50680, upload-time = "2025-11-14T10:07:23.331Z" }, ] -[[package]] -name = "pyright" -version = "1.1.403" -source = { registry = "https://pypi.org/simple" } -dependencies = [ - { name = "nodeenv" }, - { name = "typing-extensions" }, -] -sdist = { url = "https://files.pythonhosted.org/packages/fe/f6/35f885264ff08c960b23d1542038d8da86971c5d8c955cfab195a4f672d7/pyright-1.1.403.tar.gz", hash = "sha256:3ab69b9f41c67fb5bbb4d7a36243256f0d549ed3608678d381d5f51863921104", size = 3913526, upload-time = "2025-07-09T07:15:52.882Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/49/b6/b04e5c2f41a5ccad74a1a4759da41adb20b4bc9d59a5e08d29ba60084d07/pyright-1.1.403-py3-none-any.whl", hash = "sha256:c0eeca5aa76cbef3fcc271259bbd785753c7ad7bcac99a9162b4c4c7daed23b3", size = 5684504, upload-time = "2025-07-09T07:15:50.958Z" }, -] - [[package]] name = "pystray" version = "0.19.5" @@ -2867,7 +2823,6 @@ dependencies = [ { name = "dotenv" }, { name = "filelock" }, { name = "flask" }, - { name = "fortls" }, { name = "jinja2" }, { name = "joblib" }, { name = "lsprotocol" }, @@ -2877,7 +2832,6 @@ dependencies = [ { name = "psutil" }, { name = "pydantic" }, { name = "pygls" }, - { name = "pyright" }, { name = "pystray" }, { name = "python-dotenv" }, { name = "python-multipart" }, @@ -2938,7 +2892,6 @@ requires-dist = [ { name = "dotenv", specifier = "==0.9.9" }, { name = "filelock", specifier = "==3.25.2" }, { name = "flask", specifier = "==3.1.3" }, - { name = "fortls", specifier = "==3.2.2" }, { name = "google-genai", marker = "extra == 'google'", specifier = "==1.27.0" }, { name = "jinja2", specifier = "==3.1.6" }, { name = "jinja2", marker = "extra == 'dev'", specifier = "==3.1.6" }, @@ -2956,7 +2909,6 @@ requires-dist = [ { name = "pygls", specifier = "==2.1.1" }, { name = "pyinstrument", marker = "extra == 'dev'", specifier = "==5.1.1" }, { name = "pyjwt", marker = "extra == 'dev'", specifier = "==2.12.0" }, - { name = "pyright", specifier = "==1.1.403" }, { name = "pystray", specifier = "==0.19.5" }, { name = "pytest", marker = "extra == 'dev'", specifier = "==8.4.1" }, { name = "pytest-timeout", marker = "extra == 'dev'", specifier = "==2.4.0" }, From 75738f48386bd2a5fd2c9f1287149c6e8dc5d4e1 Mon Sep 17 00:00:00 2001 From: Michael Panchenko Date: Tue, 26 May 2026 15:33:16 +0200 Subject: [PATCH 3/3] Add identifier as comment to readme Needed for Serena to be listed in GitHub's mcp registry --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 30d7c297..e733d4ec 100644 --- a/README.md +++ b/README.md @@ -261,3 +261,5 @@ Please refer to the [user guide](https://oraios.github.io/serena/02-usage/000_in A significant part of Serena, especially support for various languages, was contributed by the open source community. We are very grateful for the many contributors who made this possible and who played an important role in making Serena what it is today. + +