lsp — 给 Agent 一双「语言服务器」的眼睛
导语
@piex-dev/lsp 让 agent 能问 IDE 同一类问题;更关键的是 edit 之后自动看到 ERROR,不必靠模型记得再调诊断。
简介
没有 LSP 时,agent 理解代码主要靠 read、grep、模型脑补类型与引用。文件一多、重构一深就翻车:改了函数签名漏改调用点、类型错误要手动跑 tsc/cargo check、「符号定义在哪」全靠猜。@piex-dev/lsp 把 LSP 能力做成 pi 工具,让模型在改代码前后主动问语言服务器。
技术原理
最值钱的能力:diagnostics(有哪些 error/warning)、definition/references(改一处影响哪里)、hover(符号类型)、symbols(结构大纲)、format(统一风格)。按文件后缀在 defaults.json 匹配 server,用 root markers 找 workspace root,spawn 子进程跑 stdio JSON-RPC,同一 root + server 会话内缓存避免冷启动。诊断靠 server 主动推 publishDiagnostics,客户端按 URI 缓存——edit 后立刻能问「还有没有红线」,形成改→验→再改闭环。
编辑器/Agent Language Server
| |
| initialize |
| textDocument/* |
| ---------------------> |
| publishDiagnostics |
| <--------------------- |
使用说明
安装
pi install npm:@piex-dev/lsp
仓库源码:extensions/lsp
前提条件
扩展是客户端,不是 server 分发器。语言服务器本体要本机可执行(如 typescript-language-server、rust-analyzer、pyright、gopls)。defaults.json 已为约 50 个 server 写好启动命令与参数。
配置
默认配置在 extensions/lsp/defaults.json,每个 server 含 command / fileTypes / rootMarkers / initOptions / settings / isLinter。单 server 命令可用环境变量 PI_<NAME>_LSP_COMMAND 覆盖;写后诊断可用 PI_LSP_DIAGNOSTICS_ON_EDIT=0 关闭。
验证
cd extensions/lsp && npm install && bun test # mock server 单测
pi -e ./extensions/lsp/src/lsp.ts -p "what is 1+1" --no-session # 冒烟
实现方案
lsp.ts 是客户端 + 路由 + 工具 + 写后诊断 hook;defaults.json 配约 50 个 server。写后诊断钩住 edit/write(含 hashline):sync 磁盘 → 等 publishDiagnostics → 仅 ERROR、每文件 cap 20,附结果末尾。
| action | 作用 |
|---|---|
diagnostics | 匹配多 server,聚合诊断 |
definition/type_definition/implementation | 导航 |
references/hover/symbols/workspace_symbols | 读智能 |
rename | 默认 preview;apply=true 写盘 |
code_actions | 列表或按 index apply |
format | TextEdit 写回 |
status/reload | 运维 |
正确性要点:诊断 settle(最后一条 publish 后静默 N ms,默认 800ms);LSP 3.17 pull 诊断(diagnosticProvider 声明才拉);resolveProvider 门控;重叠 TextEdit 区间相交拒绝;stderr 捕获进错误消息(cap 16KB);which 含 node_modules/.bin、.venv/bin;Windows .bat/.cmd 经 cmd.exe /d /s /c 包装。
设计参考
| 项目 | 机制 | piex 取舍 |
|---|---|---|
| oh-my-pi lsp | 完整 LSP 客户端:多 server 路由、didChange、完整 action 面、诊断聚合 | 采纳:JSON-RPC client、defaults.json 驱动、按需启动/会话复用。不采纳:Bun 运行时、大面铺满 action |
| OpenCode 写后诊断 | tool_result hook edit/write → 等 publishDiagnostics → 仅 ERROR、每文件 cap | 采纳整套模式:sync → wait → only ERROR → cap 20。PI_LSP_DIAGNOSTICS_ON_EDIT=0 可关 |
| VS Code LSP | initialize + settings/didChangeConfiguration + workspace/configuration | 借鉴:initOptions/settings 下发路径;full-text didChange;which 查 .bin/.venv |
| pi-extensions pi-lsp | 诊断 settle、pull 诊断、stderr 捕获、门控、重叠 edit 检测、cmd.exe 包装、命令覆盖 | 采纳全部协议细节(融入常驻进程架构);不采纳:spawn-per-call、仅两工具 |
核心取舍:优先写后 ERROR 闭环(学 OpenCode),诊断优于导航暴露;linter 不抢 primary server 的导航角色。
迭代记录
路线图
| 状态 | 项 |
|---|---|
| ✅ | init/settings、didChange、多 server、写后 ERROR、rename/code_actions |
| ✅ | 诊断 settle、pull 诊断、resolveProvider 门控、重叠 edit 防护、stderr 捕获 |
| ✅ | mock server 单测 |
| 下一步 | 项目级 .lsp.json 覆盖;模块拆分(client/config/edits) |
| 下一步 | indexing/ready 状态,避免冷启动假阴性;目录级批量诊断 |
| 暂缓 | lspmux、自动下载 LS、completion、TUI、整仓 CLI diagnostics |
版本记录
| 版本 | 日期 | 变更 |
|---|---|---|
| 0.2.0 | 2026-07-19 | 早期版本:多 server 路由、didChange、诊断聚合;push 诊断到即返;盲调 codeAction/resolve;server 退出只给 exit code,stderr 丢失 |
| 0.3.0 | 2026-07-21 | push settle 静默期 + LSP 3.17 pull 诊断双轨;resolveProvider/diagnosticProvider 声明才调;stderr 捕获进超时/退出错误;.bat/.cmd 经 cmd.exe 包装;PI_<NAME>_LSP_COMMAND 覆盖;重叠 TextEdit 检测防写坏文件 |
0.2.0 教训:intelephense 这类 server 先推空再推真,到即返把有错文件报成干净;server 崩溃只有 exit code,排障全靠猜。0.3.0 补齐协议细节。
附录:pi LSP 生态能力逐项对比
四个项目(omp / OpenCode / pi-extensions pi-lsp / piex lsp)的客观能力差异。
| 能力 | omp | OpenCode | pi-extensions | piex |
|---|---|---|---|---|
| 工具面 | 14 action | 实验性,默认关 | 2(diagnostics+fix) | 13 action |
| 进程模型 | 会话内复用 | 会话内复用 | spawn-per-call | 会话内复用 |
| push settle 静默期 | ❌ | ❌ | ✅ | ✅(800ms) |
| LSP 3.17 pull 诊断 | ❌ | ❌ | ✅ | ✅ |
| 写后诊断 | writethrough | edit 注入 ERROR | ❌ | tool_result 附 ERROR |
| stderr 捕获 | ❌ | ❌ | ✅ | ✅(cap 16KB) |
| 重叠 TextEdit 防护 | ❌ | ❌ | ✅ | ✅(限 cwd) |
| Windows .bat/.cmd | — | — | ✅ cmd.exe | ✅ |
| rename / format | ✅ | ❌ | ❌ | ✅(preview 默认) |
| 单测 | — | — | ❌ | ✅(mock server) |
源稿 Markdown: docs/packages/lsp.md