跳到主要内容
Code Agents

第6章 IDE 集成与 LSP

Language Server Protocol、Tree-sitter、VS Code Extension API、Cursor 内核、Continue.dev/Cline 架构,以及自己写一个 Code Agent IDE 插件的实战指南

ide lsp tree-sitter vscode-extension cursor continue cline

第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 的天然容器

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 的对比

维度LSPTree-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用途
Editorvscode.window.activeTextEditor当前编辑器
Documentvscode.workspace.openTextDocument文件读写
Selectioneditor.selection用户选中范围
Decorationeditor.setDecorations高亮 / 浮窗
Commandvscode.commands.registerCommand注册命令
Webviewvscode.window.createWebviewPanel自定义 UI(chat 面板)
StatusBarvscode.window.createStatusBarItem状态栏
Diagnosticsvscode.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 核心创新点

  1. 自家 Tab 模型:不用 GPT/Claude,而是自训的小模型(估计 1B-3B),延迟 < 100ms
  2. Indexing 系统:repo embedding + tree-sitter 双索引
  3. Composer Action 集合:类似 OpenHands 但更精简,优化 IDE 内体验
  4. 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,在它基础上改:

  1. 加自家 Tool / Context Provider
  2. 改 prompt 模板
  3. 加企业内部 LLM 路由

这样 Indexing / Tree-sitter / UI 都已经有,你专注业务逻辑。


九、JetBrains 插件简介

JetBrains 系列(IntelliJ / PyCharm / GoLand / WebStorm)有自家插件 SDK:

9.1 与 VS Code Extension 的对比

维度VS CodeJetBrains
语言TypeScriptKotlin / Java
架构Process out-of-VSCodePlugin 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 插件的核心代码

📚 参考资料

协议 / 工具

项目

业界博客

  • 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 的衔接。