Cursor 开源平替 Cline 到底是如何实现的?本文带你刨根问底

Cline源码学习

提示词上下文管理工具调用为核心的工具。 查找参考内容用工具, MCP 是工具,操作文件的是工具,执行任务是工具。

前言

Cline 是一个基于 VS Code 的智能助手插件,它通过 AI 技术为开发者提供智能化的任务处理能力。在现代软件开发中,开发者经常需要在多个工具间切换,处理大量重复性工作,同时还要维持对代码和业务的深入理解。这不仅降低了开发效率,还增加了认知负担。

Cline 正是为解决这些问题而设计。它将 AI 能力与开发工具深度集成,提供了一个统一的智能化开发环境。通过智能理解开发者意图,自动化执行开发任务,并保持对项目上下文的持续理解,Cline 显著提升了开发效率和体验。

概述

Cline 插件采用模块化设计,主要由以下核心组件构成:

  • ClineProvider:负责状态管理和 UI 交互
  • Cline:核心业务逻辑处理
  • 外部服务集成:包括 AI 服务、认证服务等
  • 工具系统:提供文件操作、命令执行等能力

通过这些组件的协同工作,Cline 实现了四个核心目标:

  1. 工具统一
    • 在 VS Code 中集成文件操作、命令执行、浏览器控制等能力
    • 提供统一的界面来执行各种开发任务
    • 减少工具切换带来的认知负担
  2. 智能自动化
    • 通过 AI 理解开发者意图
    • 自动完成重复性工作
    • 智能化的代码理解和生成
  3. 上下文保持
    • 维护对项目结构的持续理解
    • 在任务执行过程中保持状态连贯
    • 支持长时间运行的复杂任务
  4. 安全可控
    • 提供操作确认机制
    • 支持任务的暂停和恢复
    • 实现关键操作的回滚能力

一、整体架构概览

  • VS Code Extension Layer
    • extension.ts: 插件入口点
    • 用户界面组件:
      • Webview Panel
      • Sidebar
      • Commands
  • Core System
    • ClineProvider: 状态管理和视图控制
    • Cline: 核心业务逻辑
    • 核心模块:
      • assistant-message:消息处理
      • ignore:忽略规则
      • prompts:提示管理
      • sliding-window:对话管理
      • webview:UI 交互
  • State Management
    • Global State:全局状态
    • Workspace State:工作区状态
    • Secrets Storage:密钥存储
  • External Services
    • AI Services:
      • Anthropic API
      • OpenAI API
      • OpenRouter
    • Authentication:认证服务
    • Browser Control:浏览器控制

1.1 核心架构图

graph TB subgraph VSCode[VS Code Extension] EXT[extension.ts] subgraph UI[User Interface] WP[Webview Panel] SB[Sidebar] CMD[Commands] end end subgraph Core[Core System] CP[ClineProvider] CL[Cline] subgraph Modules[Core Modules] AM[assistant-message] IG[ignore] PR[prompts] SW[sliding-window] WV[webview] end end subgraph State[State Management] GS[Global State] WS[Workspace State] SS[Secrets Storage] end subgraph Services[External Services] AI[AI Services] subgraph APIs ANT[Anthropic API] OAI[OpenAI API] OR[OpenRouter] end AUTH[Authentication] BROW[Browser Control] end %% Main Flow EXT -->|activates| CP EXT -->|registers| UI CP -->|initializes| CL %% Core Interactions CP -->|manages| State CL -->|uses| Modules %% UI Flow UI -->|communicates via| CP CP -->|updates| UI %% Service Integration CL -->|calls| APIs CP -->|manages| AUTH CL -->|controls| BROW classDef vscode fill:#e1f3ff,stroke:#333,stroke-width:2px classDef core fill:#ffe1e1,stroke:#333,stroke-width:2px classDef state fill:#e1ffe1,stroke:#333,stroke-width:2px classDef service fill:#fff0db,stroke:#333,stroke-width:2px class VSCode,UI vscode class Core,Modules core class State state class Services,APIs service

1.3 插件入口

tsx 复制代码
export function activate(context: vscode.ExtensionContext) {
    // 1. 创建输出通道
    outputChannel = vscode.window.createOutputChannel("Cline");

    // 2. 初始化日志系统
    Logger.initialize(outputChannel);

    // 3. 创建侧边栏提供者
    const sidebarProvider = new ClineProvider(context, outputChannel);

    // 4. 注册侧边栏视图
    context.subscriptions.push(
        vscode.window.registerWebviewViewProvider(
            ClineProvider.sideBarId,
            sidebarProvider,
            {
                webviewOptions: {
                    retainContextWhenHidden: true
                }
            }
        )
    );
}

// 注册了多个VS Code命令:
- "cline.plusButtonClicked" // 新建对话
- "cline.mcpButtonClicked"  // MCP按钮
- "cline.popoutButtonClicked" // 弹出到新标签页
- "cline.settingsButtonClicked" // 设置
- "cline.historyButtonClicked"  // 历史记录
- "cline.accountLoginClicked"   // 账号登录

1.4 ClineProvider.ts

graph TB subgraph ClineProvider[ClineProvider.ts] direction TB subgraph VSCodeIntegration[VS Code Integration] WV[Webview View] WP[Webview Panel] URI[URI Handler] end subgraph StateSystem[State Management System] GS[Global State] SS[Secrets Storage] WS[Workspace State] end subgraph TaskSystem[Task Management] TI[Task Init] TC[Task Control] TH[Task History] CK[Checkpoints] end subgraph AuthSystem[Authentication & API] AM[Auth Manager] AC[API Config] MC[Model Config] MH[MCP Hub] end subgraph EventSystem[Event Handling] ML[Message Listener] EH[Event Handler] CB[Callbacks] end subgraph DataManagement[Data Management] ST[State] CF[Config] HI[History] SE[Secrets] end end %% External Systems ExtVSCode[VS Code API] ExtAuth[Auth Services] ExtAPI[External APIs] Cline[Cline.ts] %% Internal Connections StateSystem --> DataManagement TaskSystem --> StateSystem AuthSystem --> StateSystem EventSystem --> TaskSystem EventSystem --> AuthSystem VSCodeIntegration --> EventSystem %% External Connections VSCodeIntegration --> ExtVSCode AuthSystem --> ExtAuth AuthSystem --> ExtAPI TaskSystem --> Cline %% State Flow DataManagement --> ST DataManagement --> CF DataManagement --> HI DataManagement --> SE classDef default fill:#f9f9f9,stroke:#333,stroke-width:2px classDef system fill:#ffe1e1,stroke:#333,stroke-width:2px classDef external fill:#e1f3ff,stroke:#333,stroke-width:2px classDef data fill:#e1ffe1,stroke:#333,stroke-width:2px class VSCodeIntegration,StateSystem,TaskSystem,AuthSystem,EventSystem system class ExtVSCode,ExtAuth,ExtAPI,Cline external class DataManagement data

1.5 cline.ts

graph TB subgraph Cline[Cline.ts] direction TB subgraph Settings[Settings] CFG[API & System Config] end subgraph Core[Core] TM[Task Manager] FM[File Manager] BM[Browser Manager] CM[Checkpoint Manager] end subgraph Operations[Operations] TC[Task Control] FO[File Operations] AI[API Integration] TE[Tool Execution] end subgraph UI[UI Interface] COM[Communication] end end %% Main flows Settings --> Core Core --> Operations Operations --> UI %% Cross-functional flows TC -->|uses| CM FO -->|uses| FM TE -->|uses| BM AI -->|via| COM classDef settings fill:#e1f3ff,stroke:#333,stroke-width:2px classDef core fill:#ffe1e1,stroke:#333,stroke-width:2px classDef ops fill:#e1ffe1,stroke:#333,stroke-width:2px classDef ui fill:#fff0db,stroke:#333,stroke-width:2px class Settings settings class Core core class Operations ops class UI ui

1.6 提示词

分为几个部分:

  1. 角色定义:定义角色信息
  2. 工具调用:
    1. 工具定义
    2. 内置工具列表:
      1. 文件操作:读文件,写文件(覆盖),替换文件内容(diff形式),查文件,list 文件,list代码定义
      2. 浏览器操作:浏览器操作(使用 puppeteer访问和点击操作,执行操作并且返回截图和控制台日志)
      3. 终端操作:执行命令
      4. MCP 操作:MCP 工具调用和资源请求
      5. 基础操作:询问用户问题,输出命令结果(用于展示任务完成后的结果,标志结束)
      6. 规划模式:规划模式定义(帮助用户规划和脑暴解决方案)
    3. 调用例子和调用指南
  3. MCP 服务:MCP 定义, 动态注入 MCP服务器列表,MCP 创建示例和指南
  4. 替换文件和创建文件的区别:两者的定义和使用场景以及优势,考虑改写之后用户编辑器的自动格式化(直接输出最终状态),工作流程的一些建议
  5. ACT模式和 PLAN 模式:让 AI 理解 act 模式和 plan 模式,act 模式可以调用除plan_mode_response 工具之外的所有工具,而 plan 模式则使用plan_mode_response
  6. 能力:指定 AI 具有什么能力,比如能调用哪些工具以及这些工具是干什么的
  7. 规则:指定 AI 需要遵守的规则,能做什么,不能做什么
  8. 系统信息:操作系统、默认 shell,home 目录,当前工作目录
  9. 目标:宏观指定AI 完成任务的步骤
  10. 用户自定义指南 源代码位置:github.com/cline/cline...

二、核心执行流程

2.1 任务执行流程

  1. 任务初始化
    • 用户通过 Webview 界面输入任务
    • Webview 将消息传递给 ClineProvider
    • ClineProvider 创建和初始化 Cline 实例
  2. 任务执行循环
    • Cline 向 AI 服务发送请求
    • AI 服务返回响应和可能的工具调用
    • Cline 解析响应并执行相应的工具
    • 需要用户确认的操作会请求用户确认
    • 工具执行结果返回给 Cline
    • Cline 将结果返回给 AI 服务继续处理
  3. 任务完成
    • 当所有必要的步骤都完成后
    • Cline 向用户返回最终结果
    • 任务执行完成
sequenceDiagram participant User participant Webview participant ClineProvider participant Cline participant Tools participant AI User->>Webview: 输入任务 Webview->>ClineProvider: 发送消息 ClineProvider->>Cline: 创建实例 activate Cline loop Task Loop Cline->>AI: 发送请求 AI-->>Cline: 返回响应 Cline->>Tools: 执行工具 Tools->>User: 请求确认 User-->>Tools: 确认执行 Tools-->>Cline: 返回结果 Cline->>AI: 返回执行结果 end Cline-->>User: 任务完成 deactivate Cline

2.2 工具执行流程

flowchart TD A[AI 请求] --> B{AI 进行工具类型判断} B -->|Command| C[命令执行] B -->|File| D[文件操作] B -->|API| E[API 调用] B -->|Browser| F[浏览器操作] C --> G{需要确认?} G -->|Yes| H[用户确认] G -->|No| I[直接执行] H --> I I --> J[收集结果] D --> K[权限检查] K --> L[执行操作] L --> J E --> M[验证参数] M --> N[调用 API] N --> J F --> O[浏览器会话] O --> P[执行动作] P --> J J --> Q[返回给 AI]

三、核心组件实现

3.1 ClineProvider Cline 核心类

tsx 复制代码
class ClineProvider implements vscode.WebviewViewProvider {
    private cline?: Cline
    private view?: vscode.WebviewView
    private context: vscode.ExtensionContext

    // 核心管理功能
    async initClineWithTask(task?: string)
    async handleMessage(message: Message)
    async updateState(state: State)
    
    // 定义全局文件名
		export const GlobalFileNames = {
			apiConversationHistory: "api_conversation_history.json", // API对话历史
			uiMessages: "ui_messages.json", // UI消息
			openRouterModels: "openrouter_models.json", // OpenRouter模型
			mcpSettings: "cline_mcp_settings.json", // MCP设置
			clineRules: ".clinerules", // Cline规则
		}
}
tsx 复制代码
class ClineProvider {
    constructor(context: vscode.ExtensionContext) {
        this.context = context
        this.cline = undefined  // 延迟初始化
    }

    async initClineWithTask(task?: string) {
        await this.clearTask()  // 清理现有任务

        // 获取配置
        const config = await this.getState()

        // 创建新实例
        this.cline = new Cline(
            this,
            config.apiConfiguration,
            config.autoApprovalSettings,
            config.browserSettings,
            config.chatSettings,
            config.customInstructions
        )
    }
}
tsx 复制代码
export class Cline {
    // 核心属性
    readonly taskId: string;
    api: ApiHandler;
    private terminalManager: TerminalManager;
    private urlContentFetcher: UrlContentFetcher;
    browserSession: BrowserSession;

    // 状态控制
    private didEditFile: boolean = false;
    private abort: boolean = false;
    private consecutiveMistakeCount: number = 0;

    // 历史记录
    apiConversationHistory: Anthropic.MessageParam[] = [];
    clineMessages: ClineMessage[] = [];

    // 配置系统
    autoApprovalSettings: AutoApprovalSettings;
    private browserSettings: BrowserSettings;
    private chatSettings: ChatSettings;

    // 任务执行核心方法
    async startTask(task?: string, images?: string[]): Promise<void> {
        // 初始化状态
        this.clineMessages = [];
        this.apiConversationHistory = [];

        // 更新界面
        await this.providerRef.deref()?.postStateToWebview();

        // 显示任务
        await this.say("text", task, images);

        // 标记初始化完成
        this.isInitialized = true;

        // 构建初始消息
        let imageBlocks = formatResponse.imageBlocks(images);

        // 启动任务循环
        await this.initiateTaskLoop(
            [{
                type: "text",
                text: `<task>\\n${task}\\n</task>`,
            },
            ...imageBlocks],
            true // isNewTask 标记
        );
    }
}

3.2 任务循环实现

tsx 复制代码
private async initiateTaskLoop(
    userContent: UserContent,
    isNewTask: boolean
): Promise<void> {
    let nextUserContent = userContent;
    let includeFileDetails = true;

    while (!this.abort) {
        // 核心请求处理
        const didEndLoop = await this.recursivelyMakeClineRequests(
            nextUserContent,
            includeFileDetails,
            isNewTask
        );

        includeFileDetails = false;

        if (didEndLoop) {
            break;
        } else {
            // 处理未使用工具的情况
            nextUserContent = [{
                type: "text",
                text: formatResponse.noToolsUsed(),
            }];
            this.consecutiveMistakeCount++;
        }
    }
}

3.3 任务结束的条件

tsx 复制代码
// 1. this.abort 为 true 的情况:
- 用户手动中止
- 发生严重错误
- Cline 实例被销毁

// 2. didEndLoop 为 true 的情况:
- 任务成功完成(使用 attempt_completion 工具)
- 达到最大错误次数
- 任务被标记为完成

// 3. 其他终止条件:
- 连续错误次数过多
- API 调用失败
- 工具执行失败

四、请求处理系统

4.1 递归请求处理

tsx 复制代码
private async recursivelyMakeClineRequests(
    userContent: UserContent,
    includeFileDetails: boolean,
    isNewTask: boolean
): Promise<boolean> {
    // 1. 错误检查
    if (this.consecutiveMistakeCount >= MAX_CONSECUTIVE_MISTAKES) {
        throw new Error("Too many consecutive mistakes")
    }

    try {
        // 2. 准备消息
        const messages = this.prepareMessages(userContent, includeFileDetails)

        // 3. 发送 API 请求
        const response = await this.api.sendRequest(messages)

        // 4. 处理响应
        if (response.type === "completion") {
            return true  // 任务完成
        } else if (response.type === "tool_use") {
            await this.handleToolUse(response.tool)
            return false  // 继续执行
        }
    } catch (error) {
        this.handleError(error)
        return true
    }
}

4.2 消息准备

tsx 复制代码
private prepareMessages(
    userContent: UserContent,
    includeFileDetails: boolean
): MessageParam[] {
    // 1. 构建基础消息
    const messages = [...this.apiConversationHistory]

    // 2. 添加环境详情
    if (includeFileDetails) {
        messages.push({
            type: "environment_details",
            content: this.getEnvironmentDetails()
        })
    }

    // 3. 添加用户内容
    messages.push({
        type: "user_content",
        content: userContent
    })

    return messages
}

4.3 API 通信系统

tsx 复制代码
class ApiHandler {
    async *attemptApiRequest(previousApiReqIndex: number) {
        // 1. 系统提示准备
        let systemPrompt = await SYSTEM_PROMPT(
            cwd,
            this.api.getModel().info.supportsComputerUse,
            mcpHub,
            this.browserSettings
        );

        // 2. 上下文预处理
        const { truncatedHistory, deletedRange } = this.truncateHistoryToFitContext(
            previousApiReqIndex
        );

        // 3. 流式通信
        const stream = this.api.createMessage(systemPrompt, truncatedHistory);
        yield* this.handleStreamResponse(stream);
    }

    private truncateHistoryToFitContext(previousIndex: number) {
        const totalTokens = this.calculateTokensUsage();

        switch (this.contextWindow) {
            case 64_000: // deepseek models
                this.maxAllowedSize = this.contextWindow - 27_000;
                break;
            case 128_000: // most models
                this.maxAllowedSize = this.contextWindow - 30_000;
                break;
        }

        if (totalTokens >= this.maxAllowedSize) {
            return this.performTruncation();
        }

        return { truncatedHistory: this.history };
    }
}

4.4 工具

tsx 复制代码
export const toolUseNames = [
	"execute_command",
	"read_file",
	"write_to_file",
	"replace_in_file",
	"search_files",
	"list_files",
	"list_code_definition_names",
	"browser_action",
	"use_mcp_tool",
	"access_mcp_resource",
	"ask_followup_question",
	"plan_mode_response",
	"attempt_completion",
] as const

4.5 终端命令执行工具

tsx 复制代码
async executeCommandTool(command: string): Promise<[boolean, ToolResponse]> {
    // 1. 终端管理
    const terminalInfo = await this.terminalManager.getOrCreateTerminal(cwd)
    terminalInfo.terminal.show()

    // 2. 执行命令
    const process = this.terminalManager.runCommand(terminalInfo, command)

    // 3. 输出处理
    process.on("line", (line) => {
        result += line + "\\n"
        if (!didContinue) {
            sendCommandOutput(line)
        } else {
            this.say("command_output", line)
        }
    })

    // 4. 等待完成
    await process

    // 5. 返回结果
    return [completed, formatResult(result)]
}

4.6文件操作工具

tsx 复制代码
class FileOperations implements Tool {
    // 文件读取
    async readFile(path: string): Promise<string> {
        return fs.readFile(path, 'utf8');
    }

    // 文件写入
    async writeFile(path: string, content: string): Promise<void> {
        await this.ensureDirectoryExists(path);
        await fs.writeFile(path, content);
    }

    // 文件替换
    async replaceInFile(path: string, diff: string): Promise<void> {
        const content = await this.readFile(path);
        const newContent = await constructNewFileContent(diff, content);
        await this.writeFile(path, newContent);
    }

    // 文件列表
    async listFiles(path: string, recursive: boolean): Promise<string[]> {
        if (recursive) {
            return this.recursiveListFiles(path);
        }
        return fs.readdir(path);
    }
}

五、安全机制实现

5.1 文件操作安全

tsx 复制代码
class FileOperationApproval {
    async checkFileAccess(operation: FileOperation): Promise<boolean> {
        // 1. 路径安全检查
        if (!this.isPathSafe(operation.path)) {
            return false;
        }

        // 2. 操作权限检查
        if (!this.hasPermission(operation.type)) {
            return false;
        }

        // 3. 内容安全检查
        if (operation.type === 'write' && !this.isContentSafe(operation.content)) {
            return false;
        }

        return true;
    }

    private isPathSafe(path: string): boolean {
        // 检查路径是否在工作目录内
        // 防止目录遍历攻击
        const normalizedPath = normalizePath(path);
        return isWithinWorkspace(normalizedPath);
    }
}

5.2 命令执行安全

tsx 复制代码
class CommandSecurity {
    private readonly restrictedCommands: Set<string> = new Set([
        'rm -rf',
        'format',
        'shutdown',
        // ... 其他危险命令
    ]);

    async validateCommand(command: string): Promise<boolean> {
        // 1. 检查是否是受限命令
        if (this.isRestrictedCommand(command)) {
            return false;
        }

        // 2. 检查命令权限
        if (!await this.checkCommandPermissions(command)) {
            return false;
        }

        // 3. 检查资源限制
        if (!this.checkResourceLimits(command)) {
            return false;
        }

        return true;
    }

    private isRestrictedCommand(command: string): boolean {
        return Array.from(this.restrictedCommands).some(
            restricted => command.includes(restricted)
        );
    }
}

5.3 检查点系统

三种情况:task(恢复任务消息)、workspace(恢复工作区文件)、taskAndWorkspace(同时恢复任务消息和工作区文件)

核心机制:ShadowGit(主仓库的变更不会影响到Shadow 仓库,shadow 仓库的变更会形成主仓库的未提交的更改

核心流程:

  1. 如果恢复 workspace 或 taskAndWorkspace,则会首先初始化 checkpointTracker,并通过 resetHead 直接将工作区恢复到指定 git commit。
  2. 对于 task 或 taskAndWorkspace,我们还需要恢复 task 历史消息记录,同时记录回滚的 APi 资源消耗
tsx 复制代码
class CheckpointSystem {
    private checkpoints: Map<string, Checkpoint> = new Map();

    // 创建检查点
    async createCheckpoint(): Promise<string> {
        const checkpoint = {
            id: generateId(),
            timestamp: Date.now(),
            state: await this.captureCurrentState(),
            files: await this.captureFileState()
        };

        this.checkpoints.set(checkpoint.id, checkpoint);
        return checkpoint.id;
    }

    // 恢复检查点
    async restoreCheckpoint(id: string): Promise<void> {
        const checkpoint = this.checkpoints.get(id);
        if (!checkpoint) {
            throw new Error('Checkpoint not found');
        }

        await this.restoreState(checkpoint.state);
        await this.restoreFiles(checkpoint.files);
    }
}

六、文件存储

文件存储主要分为以下几类:

Task对话流,配置文件(主要是 mcp服务器信息),mcp 服务端代码,自定义prompt(.clinerules)

Task 存储

~/Library/Application\ Support/Code/User/globalStorage/扩展名/tasks/任务ID

  • api_conversation_history.json:存储消息和上下文

  • ui_messages.json:存储 UI 上显示的信息

  • checkpoints:检查点信息

    • .git:存储记录检查点的影子仓库数据

配置信息存储

~/Library/Application\ Support/Code/User/globalStorage/扩展名/settings

  • cline_mcp_settings.json:存储 mcp 的信息,包括ID、参数,环境变量等信息

mcp服务端代码存储位置

  • ~/Documents/Cline/MCP:这个文件夹存储 mcp 服务器的代码位置

七、一些细节

TreeSitter:使用 web-tree-sitter 进行代码文件的解析和提取

相关推荐
天宇&嘘月2 小时前
web第三次作业
前端·javascript·css
小王不会写code3 小时前
axios
前端·javascript·axios
发呆的薇薇°4 小时前
vue3 配置@根路径
前端·vue.js
luckyext4 小时前
HBuilderX中,VUE生成随机数字,vue调用随机数函数
前端·javascript·vue.js·微信小程序·小程序
小小码农(找工作版)4 小时前
JavaScript 前端面试 4(作用域链、this)
前端·javascript·面试
前端没钱4 小时前
前端需要学习 Docker 吗?
前端·学习·docker
前端郭德纲4 小时前
前端自动化部署的极简方案
运维·前端·自动化
海绵宝宝_5 小时前
【HarmonyOS NEXT】获取正式应用签名证书的签名信息
android·前端·华为·harmonyos·鸿蒙·鸿蒙应用开发
码农土豆5 小时前
chrome V3插件开发,调用 chrome.action.setIcon,提示路径找不到
前端·chrome
鱼樱前端5 小时前
深入JavaScript引擎与模块加载机制:从V8原理到模块化实战
前端·javascript