资讯动态

Serena 贡献指南:从 PR 规范到新增语言服务器的完整开发工作流

发布时间:2026/9/10 21:34:40 来源:尧图企业网站定制
Serena 贡献指南从 PR 规范到新增语言服务器的完整开发工作流【免费下载链接】serenaA powerful MCP toolkit for coding, providing semantic retrieval and editing capabilities - the IDE for your agent项目地址: https://gitcode.com/GitHub_Trending/ser/serena本文围绕 Serena一个基于 MCP 的编程工具箱为 Agent 提供语义检索与编辑能力的贡献流程展开系统讲解提交 PR 的边界与规范、开发环境的搭建、代码质量工具的用法以及如何在无 LLM 环境下直接测试 Serena 工具。读完本文你将掌握一套可复现的开发流程并具备向 Serena 仓库新增一门语言服务器支持的能力。贡献范围什么可以直接提 PR什么需要先讨论Serena 对社区贡献持开放态度但为了控制维护成本明确区分了「可直接提交 PR」与「需先开 issue 讨论」两类改动见 CONTRIBUTING.md。可直接通过 Pull Request 提交的贡献类型隔离的增量添加不改变 Serena 现有行为仅沿既有设计方向扩展例如新增一个语言服务器支持小型 bug 修复范围明确、影响面可控文档改进修正文档错误、补充使用细节。除此之外的改动官方建议先开 issue 与维护者讨论方案再动手实现避免大改版 PR 因方向不符被驳回。无论哪种类型每个 PR 都必须有明确的范围界定——一个 PR 只覆盖单一逻辑变更或一组紧密相关的变更这与仓库内.serena/memories/creating_pull_requests.md查看中关于 PR 创建的约定保持一致。新增语言服务器一条最典型的贡献路径「添加新语言服务器支持」是 CONTRIBUTING.md 中点名的典型贡献方向其完整操作手册记录在记忆文件 adding_new_language_support_guide.md 中CONTRIBUTING.md 原文即指向该记忆。这条路径共分五步语言服务器实现——在src/solidlsp/language_servers/下新建语言专属的服务类语言注册——在枚举与配置中登记新语言测试仓库——在test/resources/repos/下创建最小测试项目测试套件——编写覆盖符号、引用、跨文件引用的测试文档更新——同步 README、语言列表、CHANGELOG。用 DependencyProvider 模式提供启动命令所有语言服务器都通过DependencyProvider模式处理运行时依赖的安装/发现、启动命令构建以及可选的环境变量设置。实现时在super().__init__()中为process_launch_info传入None由基类通过_create_dependency_provider()创建def _create_dependency_provider(self) - LanguageServerDependencyProvider: return self.DependencyProvider(self._custom_settings, self._ls_resources_dir)传入的_ls_resources_dir是已安装依赖的存放目录。按场景从以下四个基类中选择最贴切的一个基类适用场景参考实现LanguageServerDependencyProviderUvx以 PyPI 包形式分发、通过uvx/uv x按需运行的语言服务器无需实现安装步骤只需指定包名、锁定版本、入口点和可选extra_args版本可由用户通过version_setting_key覆盖PyrightServerLanguageServerDependencyProviderBaseCommand启动命令由「基础命令」构建而来用户可通过自定义设置覆盖基础命令实现_create_default_base_command()与_create_launch_command_from_base_command()LanguageServerDependencyProviderSinglePath单个核心依赖可执行文件或 JAR且该路径不直接作为基础命令使用TypeScriptLanguageServer、Intelephense、ClojureLSP、ClangdLanguageServerLanguageServerDependencyProvider根基类处理多依赖或复杂自定义设置的场景无用户级启动命令覆盖支持EclipseJDTLS、CSharpLanguageServer、MatlabLanguageServer实现要点如需为启动命令设置环境变量重写create_launch_command_env基类默认返回{}涉及安装依赖等子进程调用时不要直接使用subprocess.run应使用 subprocess_util.py 中的subprocess_run辅助函数——它会应用安全默认设置例如将子进程的 stdin 重定向到DEVNULL避免干扰父进程的 stdin。下载运行时依赖与校验和机制依赖下载使用solidlsp.dependency_provider中的DownloadedDependency它把 URL、归档类型、允许主机和校验和验证封装在单个download_to()调用中dep DownloadedDependency( urlfhttps://example.org/foo-{version}-{platform}.zip, archive_typezip, # 可选 FileUtils.ArchiveType 用于解压 allowed_hostsFOO_ALLOWED_HOSTS, # 可选允许主机列表 ) dep.download_to(target_dir)校验和存放在以 URL 为键的数据库src/solidlsp/resources/downloaded_dependency_hashes.json中由DownloadedDependencyHashDatabase管理。实现新服务器时需遵循的配套约定用工厂类方法_create_dep_*构建每个依赖接受可选版本参数缺省回退到锁定的DEFAULT_*常量添加update_dep_hashes()类方法将所有依赖注册进DownloadedDependencyHashDatabase的更新上下文并把调用挂接到 update_downloaded_dependency_hashes.py 脚本运行后提交 JSON 变更提升任何锁定版本后必须重跑该脚本并在版本常量旁加 NOTE 注释——过期的校验和数据库会导致本地下载不经验证并在 CI 中失败仅当依赖的哈希在设计上无法固定如用户提供的版本覆盖时才传verifiedFalse。注意部分早期语言服务器仍在常量中本地定义哈希并直接调用FileUtils.download_and_extract_archive_verified这是遗留做法新代码不要沿用。LSP 初始化只返回服务器专属参数重写_create_base_initialize_params提供初始化参数时processId、rootPath、rootUri、clientInfo、workspaceFolders等公共键由InitializeParamsBuilder见 initialize_params.py统一填充你的覆写绝不能设置这些键只需返回服务器专属的capabilities与initializationOptionsdef _create_base_initialize_params(self) - dict: Return language-specific initialization parameters (server-specific keys only). return { capabilities: { # Language-specific capabilities }, # initializationOptions: {...}, # if the server needs them } def _start_server(self): Start the language server with custom handlers. # Set up notification handlers self.server.on_notification(window/logMessage, self._handle_log_message) # Start server and initialize. Do NOT call _create_base_initialize_params directly; # _create_initialize_params() wraps it with the builder to add the common keys. self.server.start() init_response self.server.send.initialize(self._create_initialize_params()) self.server.notify.initialized({})几个容易被忽略的细节workspaceFolders由构建器根据语言服务器配置索引文件夹 ls_additional_workspace_folders解析不要自己拼文件夹列表若某个服务器需要在initializationOptions内嵌套文件夹列表如EclipseJDTLS/KotlinLanguageServer在该处显式设置即可——只有顶层workspaceFolders由构建器管理若要完全抑制顶层workspaceFolders重写_create_initialize_params_builder用set_workspace_foldersFalse构造DefaultInitializeParamsBuilder_start_server返回后服务器应处于完全可用状态若需等待特定通知或响应才就绪就在此处实现等待逻辑参考EclipseJDTLS._start_server。以 PyrightServer 为实例它通过LanguageServerDependencyProviderUvx指定packagepyright、entrypointpyright-langserver、default_versionPYRIGHT_VERSION和extra_args(--stdio,)在_start_server中注册window/logMessage等通知处理器并监听 Pyright 输出的 Found X source files 日志信号用analysis_complete事件等待初始工作区分析完成超时 60 秒从而避免僵尸进程与过早返回空结果。注册语言从枚举到文件匹配在 ls_config.py 的LanguageServerId枚举中加入新成员并同步实现get_source_fn_matcher()返回FilenameMatcher登记文件扩展名与get_ls_class()延迟导入并返回服务器类class LanguageServerId(str, Enum): # Existing languages... NEW_LANGUAGE new_language def get_source_fn_matcher(self) - FilenameMatcher: match self: # Existing cases... case self.NEW_LANGUAGE: return FilenameMatcher(.newlang, .nl) # File extensions def get_ls_class(self) - type[SolidLanguageServer]: match self: # Existing cases... case self.NEW_LANGUAGE: from solidlsp.language_servers.new_language_server import NewLanguageServer return NewLanguageServer测试仓库与测试套件在test/resources/repos/new_language/test_repo/创建最小项目源文件应覆盖类/类型供符号测试、函数/方法供引用查找、导入/依赖供跨文件操作与嵌套结构供层级符号测试四类元素。测试是评审的主要部分测试质量直接决定 PR 通过顺畅度规则如下符号与引用测试必须断言期望的符号名和引用确实被找到——仅断言返回非空列表或结果非 None 是不合格的测试不允许被跳过唯一例外是基于包是否可用或不支持的 OS 进行跳过测试应能跑在 CI 上检查是否有合适的 GitHub Action 安装依赖。参照 test_php_basic.py 的结构在test/solidlsp/new_language/test_new_language_basic.py中至少覆盖查找符号、文件内引用、跨文件引用。并在 pyproject.toml 的[tool.pytest.ini_options].markers下声明新的语言标记——该文件已为数十种语言Clojure、Crystal、CUE、Python、Go、Java、Kotlin、Rust、TypeScript、Scala、C、mSL、BSL、Angular、Ada、QML、Gleam、Wolfram 等预注册了 pytest 标记。文档同步清单新增语言支持后需更新四处README.md——将语言加入支持列表020_programming-languages.md——加入语言并注明特殊注意事项、兼容性或安装要求项目模板中注释的语言服务器列表——运行uv run python scripts/print_language_list.py把输出粘贴覆盖到 project.template.yml 的既有列表去掉脚本为每行填充的尾部空格CHANGELOG.md——记录新语言支持。提交 PR先写 CHANGELOG提交 PR 前必须将相关变更新功能、修复记录到 CHANGELOG.md。要点风格简洁按 CHANGELOG 既有分区归类Language Servers、Tools、JetBrains、CLI、Memories、Dashboard、Hooks、General、Security。从 CHANGELOG.md 的实际条目看格式为逐条缩进列表如- Fix: .../- Add ...并可在括号中标注关联 issue 号如#1817、#1966。细节与背景信息应写入 commit message 而非 changelog见 creating_pull_requests.md。Python 开发环境搭建Serena 使用uv管理 Python 环境。按以下三步创建带完整开发依赖的虚拟环境uv venv -p 3.13激活环境按操作系统选择Linux/Unix/macOS 或 Windows 的 Git Bashsource .venv/bin/activateWindows 非 Git Bash.venv\Scripts\activate.batcmd/ps或source .venv/Scripts/activategit-bash安装带全部 extras 的依赖包uv sync --extra dev关于版本约束项目在 pyproject.toml 中声明requires-python 3.11, 3.15Python 3.11/3.12/3.13/3.14 均列在分类器中devextra 聚合了 pytest、ruff、poethepoet、ty、syrupy、sphinx 文档工具链等其中部分传递依赖为应对安全告警做了精确锁定文件内注释注明 Transitive deps pinned for security (dependabot alerts)且因uvx从 git 安装会忽略 lock 文件故采用精确版本号。将 Serena 安装为本地工具如需把 Serena 作为命令行工具全局安装uv tool install --reinstall -p 3.13 .-p 3.13指定工具使用 Python 3.13 运行--reinstall强制重装以覆盖已有版本。安装后会注册三个入口点见 pyproject.toml 的[project.scripts]serena与serena-agent指向serena.cli:top_levelserena-hooks指向serena.hooks:hook_commands。Poe 任务格式化与类型检查Serena 用poepoethepoet执行开发任务。CONTRIBUTING.md 列出的两个核心任务poe format——运行代码自动格式化poe type-check——运行类型检查查看 pyproject.toml 的[tool.poe.tasks]定义这两个命令背后是完整的质量门禁流水线format ruff 自动修复ruff check --fix ruff 格式化ruff format作用于src scripts testtype-checkty check src/serena src/solidlspty check test --exclude test/resources另有两个文档构建任务doc-generate-files自动生成文档文件 目录 Jupyter Book 配置与doc-build先清理再生成并执行 sphinx 构建。需要留意 pyproject.toml 中两个工程细节一是[tool.poe.executor]被显式设为type simple——注释说明如果使用默认的 uv executorpoe 会尝试通过 uv 重建环境而环境中已有正在运行的进程例如 Serena MCP 服务器时重建会失败二是[tool.ty.rules]中对unresolved-import、possibly-missing-submodule采用ignore以容忍可选的 extrasagno、google-genai与平台专属模块如 macOS 的 AppKit在默认 dev 环境中不可解析[tool.ty.overrides]则针对test/**放宽了多条类型规则因为测试代码大量使用 pytest fixtures 与 MagicMockty 对这些的建模比 mypy 更严格。不依赖 LLM 直接测试工具执行Serena 的全部代码——包括各类工具——都可以在没有 LLM、也没有 MCP 细节的情况下直接执行如需调试 MCP 协议也可使用 mcp inspector。官方示例脚本是 demo_run_tools.py它在本仓库自身上运行各类工具from serena.agent import SerenaAgent from serena.config.serena_config import LanguageBackend, SerenaConfig from serena.constants import REPO_ROOT serena_config SerenaConfig.from_config_file() serena_config.web_dashboard False serena_config.language_backend LanguageBackend.LSP project Path(REPO_ROOT) agent SerenaAgent(projectstr(project), serena_configserena_config) find_symbol_tool agent.get_tool(JetBrainsFindSymbolTool) find_refs_tool agent.get_tool(FindReferencingSymbolsTool) find_file_tool agent.get_tool(FindFileTool) search_pattern_tool agent.get_tool(SearchForPatternTool) overview_tool agent.get_tool(JetBrainsGetSymbolsOverviewTool) safe_delete_tool agent.get_tool(JetBrainsSafeDeleteTool) inline_symbol agent.get_tool(JetBrainsInlineSymbol) diagnostics_in_file_tool agent.get_tool(GetDiagnosticsForFileTool) jb_inspections_tool agent.get_tool(JetBrainsRunInspectionsTool) result agent.execute_task( lambda: diagnostics_in_file_tool.apply( relative_pathtest/resources/repos/clojure/test_repo/src/test_app/diagnostics_sample.clj, ) ) pprint(json.loads(result))脚本的关键用法拆解SerenaConfig.from_config_file()读取配置文件随后可编程覆写字段——这里关闭 Web 仪表盘、把语言后端设为 LSPSerenaAgent(project...)以本仓库根目录为项目上下文实例化 Agentagent.get_tool(SomeToolClass)按类型取出工具实例agent.execute_task(lambda: tool.apply(...))包一层 lambda 执行工具调用其结果以 JSON 字符串返回可用json.loads解析后打印。这为开发调试提供了一条极简路径无需配置任何模型提供商即可在仓库目录内直接触发find_symbol、find_referencing_symbols、search_for_pattern、get_diagnostics_for_file等工具验证语言服务器索引与诊断输出是否符合预期。类似的演示脚本还有 demo_find_defining_symbol.py、demo_find_implementing_symbol.py 与 demo_diagnostics.py可用于深入验证具体工具的语义检索行为。总结Serena 的贡献流程可以概括为一条清晰的「先对齐、后编码、再验证」链路先依据 CONTRIBUTING.md 判断改动是否在可直接提交 PR 的范围内隔离扩展、小修复、文档涉及新语言服务器时对照记忆指南走「实现 → 注册 → 测试仓库 → 测试套件 → 文档」五步环境侧用uv一套命令完成环境创建与工具安装poe format/poe type-check作为提交前的质量闸门最后通过 demo_run_tools.py 这类脚本在无 LLM 条件下直接驱动工具让每次改动都能被独立验证。这套流程既保证了单个 PR 的聚焦与可评审性也让社区贡献者能快速、可靠地把新能力合入项目。【免费下载链接】serenaA powerful MCP toolkit for coding, providing semantic retrieval and editing capabilities - the IDE for your agent项目地址: https://gitcode.com/GitHub_Trending/ser/serena创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价