第6章 IDE 集成与 LSP
Language Server Protocol、Tree-sitter、VS Code Extension API、Cursor 内核、Continue.dev/Cline 架构,以及自己写一个 Code Agent IDE 插件的实战指南
第6章 🔌 IDE 集成与 LSP
一句话:IDE = Code Agent 的容器。Cursor/Continue/Cline 都是”VS Code 内核 + AI 层”;理解 LSP(Language Server Protocol)是看懂他们怎么”读懂代码”的钥匙;Tree-sitter 是 Aider repo map / 各种代码索引的底层引擎。这一章给你完整 IDE Agent 工程师视角。
📑 目录
- 一、为什么 IDE 是 Code Agent 的天然容器
- 二、LSP(Language Server Protocol)
- 三、Tree-sitter
- 四、VS Code Extension API
- 五、Cursor 内核架构
- 六、Continue.dev 架构
- 七、Cline / Roo Code 架构
- 八、自己写一个 Code Agent IDE 插件
- 九、JetBrains 插件简介
一、为什么 IDE 是 Code Agent 的天然容器
CLI Agent(Claude Code / Codex / Aider)优势:可控、可程序化、易部署。 IDE Agent(Cursor / Copilot / Continue)优势:实时上下文感知:
| IDE 提供给 Agent 的能力 | 价值 |
|---|---|
| 当前文件、当前光标位置 | 知道用户在看哪 |
| 选中文本 | 知道用户想改什么 |
| 编辑器历史 | 知道刚才改了什么 |
| Git 状态 | 知道哪些文件 dirty |
| 终端输出 | 知道测试 / build 结果 |
| Diagnostics(LSP 错误) | 知道哪里有 bug |
| 工作区 / 多项目 | 知道全局结构 |
CLI Agent 也能拿到这些(用 file system + git + LSP),但 IDE 是”自带这些”——开发者不需要为每个查询写代码。
二、LSP(Language Server Protocol)
官方文档:https://microsoft.github.io/language-server-protocol/
2.1 核心思想
LSP(2016 微软提出)解决一个 N×M 问题:
- N 种 IDE × M 种语言 = N×M 个集成
- 改成 N+M:每种语言出一个 Language Server,每个 IDE 实现一个 LSP Client
┌─────────────────┐
│ VS Code │
│ IntelliJ │
│ Vim / Neovim │
│ Emacs │
│ Sublime │
└────────┬────────┘
│ LSP (JSON-RPC)
▼
┌─────────────────┐
│ Pyright (Python)│
│ rust-analyzer │
│ gopls (Go) │
│ tsserver (TS) │
│ clangd (C++) │
└─────────────────┘
2.2 LSP 提供哪些能力
LSP 协议定义了 ~30 种请求/通知:
| 请求 | 功能 | 例子 |
|---|---|---|
textDocument/completion | 自动补全 | 输入 app. 给候选 |
textDocument/definition | 跳转定义 | F12 跳到函数源码 |
textDocument/references | 找引用 | 找哪里调用了这个函数 |
textDocument/hover | 鼠标悬停 | 显示类型 / docstring |
textDocument/diagnostic | 错误诊断 | 标红线 |
textDocument/rename | 重命名 | 改一处改全局 |
workspace/symbol | 全局符号搜索 | Cmd+T |
2.3 LSP 对 Code Agent 的价值
Cursor / Continue / Cline 都用 LSP ——它们让 agent 通过 LSP 拿到精确语义信息:
// Agent 想了解"这个函数被谁调用了"
// 不用 grep,直接 LSP textDocument/references
const refs = await lspClient.sendRequest('textDocument/references', {
textDocument: { uri: 'file:///src/utils.py' },
position: { line: 42, character: 10 }
});
// → 返回 [Location(file=main.py, line=18), ...]
Grep vs LSP:Grep 是 textual,LSP 是 semantic。同名变量/方法 grep 会误中,LSP 不会。
2.4 LSP 的局限
- 只对单语言:不能跨语言(JS 调 Python 的边界)
- 冷启动慢:大 repo 索引可能要几分钟
- 协议本身不简单:实现 LSP client 是工程量
三、Tree-sitter
官方:https://tree-sitter.github.io/tree-sitter/
3.1 核心思想
Tree-sitter = 增量式 parser generator,生成 AST(抽象语法树)。
特点:
- 快:增量更新(改一个字符不重新 parse 整个文件)
- 准:基于 grammar 文件,语法精确
- 多语言:支持 200+ 语言(Python/JS/TS/Go/Rust/C++/…)
- 无依赖:C 库,可嵌入任何应用
3.2 与 LSP 的对比
| 维度 | LSP | Tree-sitter |
|---|---|---|
| 提供 | 语义(types / refs / defs) | 语法(AST 结构) |
| 速度 | 中(server 启动) | 极快(C native) |
| 准确度 | 极高(完整语义) | 中(语法层) |
| 部署 | 每语言一个 server | 一个库支持所有语言 |
| 适用 | IDE / agent semantic | 索引 / repo map / highlighting |
3.3 谁在用 Tree-sitter
- Aider repo map:用 tree-sitter 抽函数签名 ⭐
- GitHub 代码搜索:用 tree-sitter 做 navigable code
- Neovim:用 tree-sitter 做 syntax highlighting
- Cursor / Continue.dev:索引层用 tree-sitter
3.4 在 Code Agent 中的典型用法
# 用 tree-sitter 提取所有函数签名
import tree_sitter_python as tspython
from tree_sitter import Language, Parser
PY_LANGUAGE = Language(tspython.language())
parser = Parser(PY_LANGUAGE)
with open('src/main.py', 'rb') as f:
tree = parser.parse(f.read())
# 遍历 AST 找 function_definition 节点
def extract_functions(node, source):
if node.type == 'function_definition':
name_node = node.child_by_field_name('name')
params_node = node.child_by_field_name('parameters')
yield {
'name': source[name_node.start_byte:name_node.end_byte].decode(),
'params': source[params_node.start_byte:params_node.end_byte].decode(),
'line': node.start_point[0] + 1,
}
for child in node.children:
yield from extract_functions(child, source)
# 输出
# [{'name': 'main', 'params': '()', 'line': 12}, ...]
四、VS Code Extension API
VS Code 是当前 IDE Agent 生态最丰富的宿主。Extension API 提供:
4.1 关键 API 类别
| 类别 | API | 用途 |
|---|---|---|
| Editor | vscode.window.activeTextEditor | 当前编辑器 |
| Document | vscode.workspace.openTextDocument | 文件读写 |
| Selection | editor.selection | 用户选中范围 |
| Decoration | editor.setDecorations | 高亮 / 浮窗 |
| Command | vscode.commands.registerCommand | 注册命令 |
| Webview | vscode.window.createWebviewPanel | 自定义 UI(chat 面板) |
| StatusBar | vscode.window.createStatusBarItem | 状态栏 |
| Diagnostics | vscode.languages.createDiagnosticCollection | 错误标记 |
4.2 典型 Code Agent 插件结构
// extension.ts
import * as vscode from 'vscode';
export function activate(context: vscode.ExtensionContext) {
// 注册 "AI Edit" 命令
let disposable = vscode.commands.registerCommand('ai.edit', async () => {
const editor = vscode.window.activeTextEditor;
if (!editor) return;
// 1. 拿当前选中
const selection = editor.selection;
const selected = editor.document.getText(selection);
// 2. 弹输入框
const instruction = await vscode.window.showInputBox({
prompt: '描述要改什么'
});
if (!instruction) return;
// 3. 调 LLM
const newCode = await callLLM(selected, instruction);
// 4. 应用 diff
await editor.edit(builder => {
builder.replace(selection, newCode);
});
});
context.subscriptions.push(disposable);
}
这就是 Cursor Cmd+K / Continue Cmd+I 的极简版(实际上有 diff 预览、撤销、模型路由等更多东西)。
五、Cursor 内核架构
Cursor 是 fork 自 VS Code —— 90% 内核与 VS Code 相同,但加了:
5.1 加了什么
VS Code 原生 ──┬── 加 Tab(自家补全)
├── 加 Cmd+K(Inline 编辑)
├── 加 Composer(Multi-file Agent)
├── 加 Background Agent(长任务)
├── 加 Indexing(向量索引)
├── 加 BugBot(PR review)
└── 加 自家 model gateway(快速路由)
5.2 核心创新点
- 自家 Tab 模型:不用 GPT/Claude,而是自训的小模型(估计 1B-3B),延迟 < 100ms
- Indexing 系统:repo embedding + tree-sitter 双索引
- Composer Action 集合:类似 OpenHands 但更精简,优化 IDE 内体验
- Apply Patch UX:每个 diff 显示前用户审批
5.3 与 VS Code 兼容性
Cursor 大部分 VS Code 扩展可直接用(因为 fork 内核)。但 Cursor 锁了一些核心 API,深度定制扩展可能失败。
六、Continue.dev 架构
Continue.dev 是 VS Code / JetBrains 插件,不 fork 内核——靠纯插件 API 实现 Cursor 体验。
6.1 架构层次
┌───────────────────────────────────────┐
│ VS Code / JetBrains │
│ │
│ ┌─────────────────────────────────┐ │
│ │ Continue Plugin │ │
│ │ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Provider Layer │ │ │
│ │ │ (LLM API adapters) │ │ │
│ │ │ OpenAI/Claude/Gemini/ │ │ │
│ │ │ Ollama/Together/Etc │ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Indexing Layer │ │ │
│ │ │ embedding + tree-sitter │ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ Context Provider Layer │ │ │
│ │ │ @file / @docs / @repo │ │ │
│ │ └─────────────────────────┘ │ │
│ │ │ │
│ │ ┌─────────────────────────┐ │ │
│ │ │ UI Layer (Webview) │ │ │
│ │ │ Chat / Edit / Diff │ │ │
│ │ └─────────────────────────┘ │ │
│ └─────────────────────────────────┘ │
└───────────────────────────────────────┘
6.2 核心:config.json
Continue 的核心是用户可改的 ~/.continue/config.json:
{
"models": [
{
"title": "Claude Sonnet 4.5",
"provider": "anthropic",
"model": "claude-sonnet-4-5",
"apiKey": "sk-ant-..."
},
{
"title": "Local Llama",
"provider": "ollama",
"model": "llama3:70b"
}
],
"tabAutocompleteModel": {
"title": "Codestral",
"provider": "mistral",
"model": "codestral-latest"
},
"embeddingsProvider": {
"provider": "openai",
"model": "text-embedding-3-large"
},
"contextProviders": [
{ "name": "code", "params": {} },
{ "name": "docs", "params": {} },
{ "name": "diff", "params": {} },
{ "name": "terminal", "params": {} },
{ "name": "problems", "params": {} }
]
}
极致灵活:Tab 用 Codestral、Chat 用 Claude、Embedding 用 OpenAI——每个角色独立模型。
七、Cline / Roo Code 架构
Cline 是纯 VS Code 插件,与 Continue 同级,但工作模式不同。
7.1 Plan-Act 双模
模式 1 — Plan
Agent 先列出待改文件 + 步骤
↓ 用户审批
模式 2 — Act
Agent 每个 action 都需用户 approve
- read_file → approve
- write_file → 显示 diff,approve
- run_command → 显示命令,approve
7.2 安全设计
每个文件操作 / 命令都需要用户显式批准——比 Cursor / OpenHands 都更保守,适合对生产 repo 操作高风险的场景。
7.3 MCP 集成
Cline 是最早大量集成 MCP 的 IDE Agent ——可直接挂 GitHub MCP / 数据库 MCP 等。详见模块六 Agent Runtime 第 7 章。
7.4 Roo Code 的差异
Roo Code = Cline fork,主要加了:
- 多 mode(Code / Architect / Ask)
- 更细的 prompt 自定义
- 更友好的 UI
八、自己写一个 Code Agent IDE 插件
Walkthrough:用 Continue.dev 作为基座 + 自定义 Context Provider 和 Model。
8.1 项目结构
my-code-agent/
├── package.json
├── extension.ts
├── llm/
│ └── customProvider.ts
├── context/
│ └── customContextProvider.ts
└── tools/
└── runShell.ts
8.2 关键代码
注册命令(extension.ts):
import * as vscode from 'vscode';
import { runAgent } from './llm/customProvider';
export function activate(context: vscode.ExtensionContext) {
context.subscriptions.push(
vscode.commands.registerCommand('myCodeAgent.fixIssue', async () => {
const issue = await vscode.window.showInputBox({
prompt: 'Issue 描述'
});
if (!issue) return;
// 进度条
vscode.window.withProgress(
{ location: vscode.ProgressLocation.Notification, title: 'AI 思考中...' },
async (progress) => {
const result = await runAgent(issue);
// 应用 patch
for (const edit of result.edits) {
const doc = await vscode.workspace.openTextDocument(edit.file);
const editor = await vscode.window.showTextDocument(doc);
await editor.edit(builder => {
builder.replace(edit.range, edit.newText);
});
}
vscode.window.showInformationMessage(`已应用 ${result.edits.length} 个改动`);
}
);
})
);
}
Custom Provider(llm/customProvider.ts):
import Anthropic from '@anthropic-ai/sdk';
const client = new Anthropic({ apiKey: process.env.ANTHROPIC_API_KEY });
export async function runAgent(issue: string) {
const response = await client.messages.create({
model: 'claude-sonnet-4-5',
max_tokens: 4096,
tools: [
{
name: 'read_file',
description: '读取文件',
input_schema: { type: 'object', properties: { path: { type: 'string' } } }
},
{
name: 'write_file',
description: '写入文件',
input_schema: { type: 'object', properties: {
path: { type: 'string' },
content: { type: 'string' }
}}
},
{
name: 'run_command',
description: '运行 shell 命令',
input_schema: { type: 'object', properties: { command: { type: 'string' } } }
}
],
messages: [{ role: 'user', content: `修这个 issue: ${issue}` }]
});
// ... agent loop:接收 tool_use → 执行 → 反馈回 LLM ...
return { edits: [] }; // 简化
}
完整实现 ~500 行,类似 Continue 但极简。
8.3 推荐的工程化路径
不要从零写——fork Continue.dev,在它基础上改:
- 加自家 Tool / Context Provider
- 改 prompt 模板
- 加企业内部 LLM 路由
这样 Indexing / Tree-sitter / UI 都已经有,你专注业务逻辑。
九、JetBrains 插件简介
JetBrains 系列(IntelliJ / PyCharm / GoLand / WebStorm)有自家插件 SDK:
9.1 与 VS Code Extension 的对比
| 维度 | VS Code | JetBrains |
|---|---|---|
| 语言 | TypeScript | Kotlin / Java |
| 架构 | Process out-of-VSCode | Plugin in JVM |
| API 丰富度 | 中(主要交互层) | 极高(深入 IDE 内核) |
| 学习曲线 | 平 | 陡 |
| 生态 | 庞大(50K+ 插件) | 中(数千) |
9.2 主流 JetBrains AI 插件
- JetBrains AI Assistant / Junie(官方)
- GitHub Copilot for JetBrains
- Continue.dev for JetBrains(2024 起)
- Cursor / Cline 没 JetBrains 版(VS Code 限定)
9.3 JetBrains 用户的最佳组合
- 主力:JetBrains AI / Junie(官方)
- 补全:Copilot for JetBrains
- 自定义:Continue.dev(开源、自带 model)
✅ 自我检验清单
- 能解释 LSP 是什么、解决了什么 N×M 问题
- 能区分 LSP(语义)与 Tree-sitter(语法)的不同用途
- 能说出 VS Code Extension API 的 5 个关键类别
- 能解释 Cursor 与 Continue.dev 的架构差异(fork vs 插件)
- 能说出 Cline / Roo Code 的 Plan-Act 双模设计
- 能 walkthrough 一个简易 IDE Agent 插件的核心代码
📚 参考资料
协议 / 工具
- LSP — https://microsoft.github.io/language-server-protocol/
- Tree-sitter — https://tree-sitter.github.io/tree-sitter/
- VS Code Extension API — https://code.visualstudio.com/api
- JetBrains Plugin SDK — https://plugins.jetbrains.com/docs/intellij/
项目
- Cursor 内核架构(fork VS Code,公开讨论较少)
- Continue.dev — https://github.com/continuedev/continue
- Cline — https://github.com/cline/cline
- Aider tree-sitter 用法 — https://github.com/Aider-AI/aider/tree/main/aider/queries
业界博客
- Cursor Engineering Blog
- Continue.dev 设计文档
- Anthropic Code MCP 集成讨论
下一章:第7章 Code Agent 训练 SFT 与 RL —— 代码基座模型时间线(StarCoder/CodeLlama/DeepSeek-Coder/Qwen-Coder)、SWE-RL(Meta)、SWE-Gym(PKU)、Code-R1 等专项工作,以及与模块七 Agentic RL 的衔接。