技术速递|借助语言服务器为 GitHub Copilot CLI 赋予真正的代码智能

技术速递|借助语言服务器为 GitHub Copilot CLI 赋予真正的代码智能

​ 作者:Bruno Borges

排版:Alan Wang

通过安装和配置 LSP(Language Server Protocol)服务器,为 GitHub Copilot CLI 提供真正的代码智能,用基于语言服务的语义理解取代简单粗暴的 grep 搜索和反编译分析。

图片

曾经见过 GitHub Copilot CLI 将一个 JAR 文件解压到临时目录,随后在 .class 文件中执行 grep 搜索,并从原始字节码中一点点拼凑出 API 签名吗?这个智能体确实足够“机智”,但在没有语言服务器的情况下,这已经是它所能做到的最好方式了。

语言服务器协议(Language Server Protocol,LSP)是驱动 VS Code 等编辑器中“转到定义”、“查找引用”以及“类型解析”等功能的标准协议。它同样适用于终端环境。LSP Setup Skill 可以自动为 Copilot CLI 安装并配置 LSP Server,让智能体能够获得关于代码的精确、结构化信息,而不是依赖基于文本搜索的启发式方法。

在本文中,你将了解这个 Skill 的底层工作原理,查看它生成的配置格式,并学会如何为目前支持的 14 种编程语言完成配置。

问题:基于启发式的代码理解

在没有 LSP Server 的情况下,GitHub Copilot CLI 中的智能体只能通过文本搜索和二进制文件提取的方式,逆向推导 API 信息。对于一个 Java 项目来说,这个过程可能如下所示:

# Find the dependency JAR 
find ~/.m2/repository -name "*httpclient*.jar"# Extract it to a temp directory 
mkdir /tmp/httpclient && cd /tmp/httpclient 
jar xf ~/.m2/repository/org/apache/httpcomponents/httpclient/4.5.14/httpclient-4.5.14.jar # Search extracted classfilesforamethod
grep -r "execute" --include="*.class" .

对于 Python,智能体可能会直接 catsite-packages 中的文件;对于 TypeScript,它会遍历 node_modules。这些基于文本的方法在简单场景下能够工作,但它们实际上只是针对原始文本进行模式匹配,而不是真正的语义分析,因此无法正确理解泛型、函数重载以及传递类型,更无法直接解析编译后的字节码。这正是语言服务器能够弥补的能力缺口。

LSP Server 从结构层面解决了这一问题。当智能体针对某个符号发送一个 textDocument/definition 请求时,语言服务器会返回该符号的精确源码位置、完整解析后的类型以及函数签名。

什么是Agent Skill?

Agent Skill 是一组可复用的指令集合,用于扩展 AI 编码智能体的能力。Skill 采用带有 YAML Frontmatter 的 Markdown 文件定义,并遵循统一的结构,包括:触发描述、分步骤工作流、参考数据以及行为约束。

LSP Setup Skill 正是利用这种结构,引导智能体完成一个多步骤安装流程,包括检测操作系统、选择正确的软件包管理器、生成合法配置文件以及验证最终结果。

LSP Setup Skill 的工作原理

当 Skill 被触发时,它会执行一个包含七个步骤的工作流。

  1. 语言选择

智能体会调用 ask_user,并提供一组选项,确定用户希望为哪一种语言启用 LSP 支持。这个选择将决定后续所有步骤。

  1. 操作系统检测

智能体执行 uname -s(或者在 Windows 上检查 $env:OS / %OS%)来确定目标平台。不同操作系统对应不同的安装命令。例如,在 macOS 上使用:brew install jdtls,而在 Linux 上则需要从 eclipse.org 下载对应组件。

  1. 查询 LSP Server

Skill 内置了一个参考文件(references/lsp-servers.md),其中整理了 14 种编程语言的配置数据,包括针对不同操作系统的安装命令,可执行文件名称,以及可直接使用的配置片段等。智能体会读取这个文件,并选择对应语言的配置项。

4.** 配置作用范围**

智能体会询问配置应该应用于哪个范围:

用户级配置:~/.copilot/lsp-config.json 适用于所有代码仓库。

仓库级配置:仓库根目录下的 lsp.json 或 .github/lsp.json 仅作用于当前项目。

当两种配置同时存在时,仓库级配置拥有更高优先级。

  1. 安装

智能体执行对应语言的安装命令。例如:

# TypeScript on any OS 
npm install -g typescript typescript-language-server # Java on macOS 
brew install jdtls # Rust on any OS 
rustup component add rust-analyzer

** 6. 配置**

智能体会向所选配置文件写入(或合并)一个新的配置项。配置格式采用 lspServers 对象,每一个 Key 对应一个语言服务器标识符:

{ 
  "lspServers": { 
    "java": { 
      "command": "jdtls", 
      "args": [], 
      "fileExtensions": { 
        ".java": "java"
      } 
    } 
  } 
}

Skill 会强制遵循以下规则:

  • command 必须存在于 $PATH 中,或者使用绝对路径;
  • args 通常包含 "--stdio",用于标准输入输出通信(部分服务器,例如 jdtls,会在内部自行处理);
  • fileExtensions 将每一个文件扩展名(包含前导 .)映射到对应语言标识符;
  • 配置文件中已有的配置项会被保留,智能体执行的是合并),而不是覆盖。

7. 验证

智能体执行:which (Windows 下使用 where.exe)确认语言服务器可以正常访问。随后再验证配置文件是否为格式正确的 JSON。

支持的语言

Skill 内置了一组针对多种编程语言预定义好的 Language Server。如果编码智能体遇到的是一个尚未内置映射的语言,它会自动搜索合适的语言服务器,并引导用户完成手动配置。

配置完成之后会发生什么?

配置好 LSP Server 之后,CLI 智能体将能够:

  • 跨依赖解析类型,无需再对 JAR 文件或 node_modules 执行 grep 搜索;
  • 跳转到第三方库中的定义,即使源码没有包含在当前仓库中;
  • 查找整个项目中某个符号的所有引用
  • 查看任意函数、类或类型的悬停文档

这意味着,智能体将花费更少时间进行工具调用,并且第一次生成代码时就能得到更准确的结果。对于开发者来说,这意味着无需再等待智能体为了回答一个 IDE 本来就知道的问题而去反编译 JAR 文件或者遍历 node_modules,也能减少由于错误理解函数签名而导致的错误推理。智能体能够以与你在编辑器中执行“转到定义”相同的结构化方式理解代码,因此你可以放心地把规模更大、更复杂、更棘手的任务交给它处理。

开始使用

1.下载 Skill:访问Awesome Copilot 的 LSP Setup Skill 页面,点击 Download 按钮下载 ZIP 文件。
2.将 ZIP 解压到 ~/.copilot/skills/ 目录:

unzip lsp-setup.zip -d ~/.copilot/skills/

3.重启 GitHub Copilot CLI:如果 Copilot CLI 已经在运行,请先执行 /exit,然后重新启动 copilot,使其加载新的 Skill。

4.让智能体配置语言服务器,例如:“set up LSP for Java” 或者:“enable code intelligence for Python”

5.验证:完成安装和配置之后,再次重启 Copilot CLI(执行 /exit 后重新启动),运行 /lsp 检查语言服务器状态,并尝试对某个依赖中的符号执行“转到定义”,验证配置是否生效。

该 Skill 是 Awesome Copilot 项目的一部分,且已开源,欢迎提交贡献和反馈。