代码语义导航
lsp 工具让模型向语言服务器查询定义、引用、符号和调用层级,而不是靠搜索文本;模型改完文件后,服务器报告的错误和警告也会送回给它。Mework 会使用在 PATH 上找到的常见语言服务器,lsp.json 可以添加或替换服务器。
打开工具
这个工具在对话设置的工具页 文件与搜索 分组里,名为 代码语义导航(lsp)。内置的 mework 预设会打开它。它支持的操作和参数见 lsp 工具页。
语言服务器没有设置页,也不按对话选择:只要对话开了这个工具,就由认领该文件的服务器来回答。
Mework 自动发现的服务器
以下服务器的命令在 Mework 的 PATH 上时才会启用。
| 名称 | 命令 | 文件 |
|---|---|---|
rust-analyzer |
rust-analyzer |
.rs |
typescript-language-server |
typescript-language-server --stdio |
.ts、.mts、.cts、.tsx、.js、.mjs、.cjs、.jsx |
pyright |
pyright-langserver --stdio |
.py、.pyi |
gopls |
gopls |
.go |
clangd |
clangd |
.c、.h、.cpp、.cc、.cxx、.hpp、.hxx、.hh(需要 compile_commands.json) |
lua-language-server |
lua-language-server |
.lua |
bash-language-server |
bash-language-server start |
.sh、.bash |
lsp.json
| 层级 | 文件 |
|---|---|
| 全局 | ~/.mework/lsp.json(Windows:%USERPROFILE%\.mework\lsp.json) |
| 工作区 | <工作区>/.mework/lsp.json |
{
"lspServers": {
"zls": {
"command": "zls",
"extensionToLanguage": { ".zig": "zig" }
},
"pyright": {
"command": "basedpyright-langserver",
"args": ["--stdio"],
"extensionToLanguage": { ".py": "python", ".pyi": "python" }
}
}
}这份文件添加了一个 Zig 服务器,其中的 pyright 条目替换了同名的内置服务器。格式与 Claude Code 插件声明语言服务器的格式相同。
- 服务器名只能用 ASCII 字母、数字、
-和_。 - 文件不是合法 JSON,或者服务器没有写在
lspServers下时,整份文件都会被忽略。文件开头带 UTF-8 字节顺序标记(BOM)没有关系。单个条目有错时只拒绝这一条,文件其余部分照常生效。
| 键 | 作用 | 默认值 |
|---|---|---|
command |
必填。要启动的程序,直接运行,从不经过 shell。参数请写进 args;绝对路径里可以有空格。 |
— |
extensionToLanguage |
必填,不能为空。把文件扩展名映射到发给服务器的语言 id(rs、.rs、.RS 视为相同)。服务器负责哪些文件,只由这张表决定。 |
— |
args |
参数,字符串数组。 | 无 |
env |
在 Mework 完整环境的基础上,为这个服务器额外设置的变量。 | 无 |
initializationOptions |
服务器启动时发给它。 | {} |
settings |
服务器的设置,启动后发送,服务器来要时也会提供。 | 无 |
workspaceFolder |
服务器建立索引的文件夹,用绝对路径。 | 对话的工作区 |
startupTimeout |
允许服务器启动的毫秒数。 | 30000 |
shutdownTimeout |
允许服务器关闭的毫秒数。 | 5000 |
restartOnCrash |
服务器崩溃时是否重启。 | true |
maxRestarts |
最多重启几次。 | 3 |
diagnostics |
设为 false 时不再报告错误和警告,导航照常可用。 |
true |
description |
对服务器的说明。 | 无 |
transport |
只支持 "stdio"。 |
"stdio" |
command、args、env 的值和 workspaceFolder 里的 ${VAR} 与 ${VAR:-默认值} 会用 Mework 的环境变量替换。变量未设置又没有默认值时,条目被拒绝。
哪个服务器回答
按以下顺序查找,第一个认领该文件扩展名的服务器负责回答:
- 工作区的
lsp.json; ~/.mework/lsp.json;- 内置服务器。
同一份文件里如果有两个服务器认领同一个扩展名,写在前面的那个生效。名称与较低层级重复的条目会整个替换掉那一条,包括它的扩展名。
启动与改动
- 服务器在第一次调用它负责的文件时启动。它建立索引期间,最初几次回答可能很慢或为空。
- 每台机器、每个文件夹、每个名称只运行一个服务器,该工作区里的所有对话共用,一直运行到 Mework 退出。
- 对
lsp.json里某个服务器条目的修改,在下一次lsp调用时生效:配置改过的运行中服务器会按新设置重启,启动失败的服务器在配置改动后会重新尝试启动。 - 每个请求限时 30 秒,不受
startupTimeout影响。 - 启动失败时,错误信息里带有服务器写到 stderr 的最后一行。
编辑后的诊断
write 或 edit 改动了某个正在运行的服务器已经打开的文件后,Mework 会把改动告诉服务器。编辑本身不会启动服务器。
服务器针对这个文件夹报告的新问题(错误、警告、信息和提示;无论是刚编辑的文件还是其他文件)会在模型下一步之前送达,时间线上显示为 送达了语言服务器诊断 卡片。
- 每个问题只报告一次,每个文件最多 10 条,总共最多 30 条。
- 只有对话打开了
write或edit时才会送达诊断。 - 在服务器条目里写
"diagnostics": false可以关闭该服务器的诊断。
审批
lsp 调用视为读取 filePath:
- 在工作区内从不询问;在工作区外,只有 手动 级别会询问。
- 如果工作区有自己的
.mework/lsp.json,每次lsp调用在 手动 和 允许编辑 下都会询问,因为这个文件可以启动任意程序。 ~/.mework/lsp.json和内置服务器不会增加审批卡。- 审批卡提供 总是允许。
参见安全级别。
限制
- 超过 10 MB 的文件会被拒绝。
- 在 Git 忽略的文件里的结果,不会出现在定义、引用、实现和工作区符号搜索的结果中。
远程机器
WSL 或 SSH 机器上的工作区,语言服务器在那台机器上运行,配置也从那里读取:依次是工作区的 .mework/lsp.json、远程用户主目录下的 ~/.mework/lsp.json,以及在那台机器 PATH 上找到的内置服务器。本机的 lsp.json 不会用到。
排查问题
调用失败,说没有能处理这种文件的语言服务器。 安装一个内置服务器,让它的命令出现在 PATH 上;或者在 lsp.json 里为这个扩展名添加条目。
最初几次调用什么都没返回。 服务器还在建立索引,稍后再试。clangd 还需要 compile_commands.json。
缺少某个定义或引用。 它可能在 Git 忽略的文件里。
诊断始终没有送达。 检查 write 或 edit 是否打开、服务器是否已经在运行(对该文件做任意一次 lsp 调用就会启动它),以及 diagnostics 是否设成了 false。
每次调用都要审批。 工作区里有 .mework/lsp.json(或旧的 .naiword/lsp.json)。