微信扫码
添加专属顾问
揭秘Cline AI如何将自然语言指令转化为可执行代码,从源码角度解析其高效工作流程。 核心内容: 1. Cline AI的基本使用与本地调试方法 2. 自然语言指令的解析与任务生成机制 3. 内置命令与mention功能的实现原理
阿里妹导读
文章揭示了Cline如何将简单的自然语言指令转化为具体的编程任务,并执行相应的代码修改或生成操作。
本篇文章从源码角度来看一下从我们输入指令到 Cline 输出的过程到底是怎样的,这样对我们后续使用 Cline 会有更好的帮助。
Cline 是一个非常好用的 AI 开发助手。关于 Cline 可以戳官方文档了解。
https://cline.bot/
启动 Cline
访问 Cline 的 Github 仓库 README:
https://github.com/cline/cline?tab=readme-ov-file#contributing
# Local Development Instructionsgit clone https://github.com/cline/cline.gitcode clinenpm run install:all
在 VSCode 里 F5 或者 Run->Start Debugging 开始调试 Cline VSCode 插件。此时会新开一个 VSCode 窗口,这个窗口里加载就是我们调试版本的 Cline 插件。
这里可能遇到一些问题,一个是仓库里提到的,如果构建有问题,需要安装 esbuild Problem Matchers插件:https://marketplace.visualstudio.com/items
另外项目的 Webview 里需要安装 electron 这个巨无霸,可能会很慢,可以设置为国内源:
electron_mirror=https://npmmirror.com/mirrors/electron/electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/shamefully-hoist=true
Step by Step Debug
VSCode 对自家插件的调试做的非常好,不管是 VSCode 主进程还是 Webview 容器,下面就一步一步的开始调试。
前端输入
我们准备一段简单的输入:创建一个新任务,实现快速排序算法,并插入到 utils 文件内。
/newtask 实现快速排序算法,写入 @/src/utils/index.ts 文件
这里使用了 Cline 的内置的两个功能:内置命令 Command /newtask 以及 mention @ 功能指定了写入的文件。Command 可以理解为指定特定任务的 prompts,方便执行一些高频操作的任务,Cline 内置了诸如新建任务、创建 Rule、创建 Github Issue 等 Command。@ 功能可以指定模型特别关注的上下文,比如指定的文件内容,指定的目录内容。
输入框内输入上述内容,点击发送,代码文件:
webview-ui/src/components/chat/ChatView.tsx,发送消息的方法为handleSendMessage,Webview 内只负责收集输入信息,实际任务处理的逻辑都会发送至 VSCode 的主进程内,VSCode 主进程处理过程中,会实时的发送消息回 Webview。
// 文件位置 webview-ui/src/services/grpc-client-base.tswindow.addEventListener("message", handleResponse)// Send the requestconst encodedRequest = encodeRequest(request)vscode.postMessage({type: "grpc_request",grpc_request: {service: service.fullName,method: method.name, // method 为 newTaskmessage: encodedRequest, // message 为输入的文本、图片、文件消息等request_id: requestId,is_streaming: false,},})
message 的格式:
我们这里没有添加图片和文件,files 和 images 为空。
files =(0) [ ]images =(0) [ ]text ='/newtask 创建一个快速排序算法,写入 @/src/utils/index.ts 文件'
VSCode 主进程接收 grpc_request 消息进行处理。
VSCode 主进程接收消息
主进程处理的内容位于:src/core/controller/grpc-handler.ts:
/** * Handle a gRPC request from the webview * @param service The service name * @param method The method name * @param message The request message * @param requestId The request ID for response correlation * @param isStreaming Whether this is a streaming request * @returns The response message or error for unary requests, void for streaming requests */ async handleRequest( service: string, method: string, message: any, requestId: string, isStreaming: boolean = false, ): Promise<{ message?: any error?: string request_id: string } | void> {}可以看到,参数和 Webview 传过来的一致。
任务初始化
经过各种封装,最终处理的任务落到了src/core/controller/index.ts 的 initTask 方法内一个超级大的 Task 类的初始化:
this.task = new Task( this.context, this.MCPHub, this.workspaceTracker, (historyItem) => this.updateTaskHistory(historyItem), () => this.postStateToWebview(), (message) => this.postMessageToWebview(message), (taskId) => this.reinitExistingTaskFromId(taskId), () => this.cancelTask(), apiConfiguration, autoApprovalSettings, browserSettings, chatSettings, shellIntegrationTimeout, terminalReuseEnabled ?? true, enableCheckpointsSetting ?? true, customInstructions, task, images, files, historyItem,)
Task 类位于src/core/task/index.ts,在一系列的初始化后:
初始化的代码没有过度深究,从类名来看,包括了后续任务执行中可能使用到的工具:浏览器、命令行、Url、DiffView 等;mcp 的配置;autoApprove 的配置等等。
终于进入到实际的逻辑处理:
首先,根据用户配置的模型提供商信息创建 AI 的 api handler:
// Now that taskId is initialized, we can build the API handlerthis.api = buildApiHandler(effectiveApiConfiguration)
然后,进入到 startTask 方法:
say 方法会在聊天面板新增一条消息,比如下面的代码,将用户的输入信息显示在聊天面板:
await this.say("text", task, images, files)构建 User Prompt
接下来,构建 userContent:
// 为用户输入的消息添加一个 task 标签。let userContent: UserContent = [{type: "text",text: `<task>\n${task}\n</task>`,},...imageBlocks,]/**text ='<task>\n/newtask 创建一个快速排序算法,写入 @/src/utils/index.ts 文件\n</task>'type ='text'* /
如果用户提供了文件(Cline 支持用户上传文本文件),背后其实是访问文本文本,也用来构造 userContent。
if (files && files.length > 0) { const fileContentString = await processFilesIntoText(files) if (fileContentString) { userContent.push({ type: "text", text: fileContentString, }) }}继续构造 Prompts
用过 Cline 的话,我们会知道 Cline 会循环处理任务,所以 User Prompts 构造完成后,进入到 initiateTaskLoop 方法,真正执行任务的方法为 recursivelyMakeClineRequests:
进一步处理用户的输入信息:
const [parsedUserContent, environmentDetails, clinerulesError] = await this.loadContext(userContent, includeFileDetails)
这样处理之后,用户输入重新组装为 parsedUserContent,内容比较长,这里不贴了,大致格式为:
<explicit_instructions type="new_task"></explicit_instructions><task>用户输入</task><fileContent>src/utils/index.ts内的文件</fileContent>
再次看一下我们的输入:/newtask 实现快速排序算法,写入 @/src/utils/index.ts 文件,上面三段一一对应:<explicit_instructions type="new_task"> 对应 /newtask 命令,这是 Cline 的内置 prompt,@/src/utils/index.ts 添加了该文件内容作为上下文。
同时将 environmentDetails 也添加到 userContent,environmentDetails 有工作目录、当前时间、当前打开的 Tab 等。
userContent = parsedUserContent// add environment details as its own text block, separate from tool resultsuserContent.push({ type: "text", text: environmentDetails })怪不得 Cline 这么耗 Token!
模型请求
继续进入 attemptApiRequest 方法,首先构造 System prompt:
const isClaude4ModelFamily = await this.isClaude4ModelFamily()let systemPrompt = await SYSTEM_PROMPT(cwd, supportsBrowserUse, this.mcpHub, this.browserSettings, isClaude4ModelFamily)
比较有意思的是,Cline 针对 Claude4 定制了不同的 System Prompt。
System Prompt 里会告诉模型我们当前已经提供了哪些工具以及这些工具该如何调用(参数和规则),比如本次任务要将模型生成的代码写入已有文件,那么就需要使用到
replace_in_file这个工具,这里贴一下 System Prompt 里关于replace_in_file的内容。
## replace_in_fileDescription: Request to replace sections of content in an existing file using SEARCH/REPLACE blocks that define exact changes to specific parts of the file. This tool should be used when you need to make targeted changes to specific parts of a file.Parameters:- path: (required) The path of the file to modify(relative to the current working directory ${cwd.toPosix()})- diff: (required) One or more SEARCH/REPLACE blocks following this exact format: \`\`\` ------- SEARCH [exact content to find]======= [new content to replace with] +++++++ REPLACE \`\`\` Critical rules: 1. SEARCH content must match the associated file section to find EXACTLY: * Match character-for-character including whitespace, indentation, line endings * Include all comments, docstrings, etc. 2. SEARCH/REPLACE blocks will ONLY replace the first match occurrence. * Including multiple unique SEARCH/REPLACE blocks if you need to make multiple changes. * Include *just* enough lines in each SEARCH section to uniquely match each set of lines that need to change. * When using multiple SEARCH/REPLACE blocks, list them in the order they appear in the file. 3. Keep SEARCH/REPLACE blocks concise: * Break large SEARCH/REPLACE blocks into a series of smaller blocks that each change a small portion of the file. * Include just the changing lines, and a few surrounding lines if needed for uniqueness. * Do not include long runs of unchanging lines in SEARCH/REPLACE blocks. * Each line must be complete. Never truncate lines mid-way through as this can cause matching failures. 4. Special operations: * To move code: Use two SEARCH/REPLACE blocks (one to delete from original + one to insert at new location) * To delete code: Use empty REPLACE sectionUsage:<replace_in_file><path>File path here</path><diff>Search and replace blocks here</diff> </replace_in_file>同时,System Prompt 也继续追加了用户的偏好语言,方便按照用户偏好的语言进行输出。
接下来发送请求:
let stream = this.api.createMessage(systemPrompt, contextManagementMetadata.truncatedConversationHistory)
针对模型的输出,需要进一步处理,是直接展示在聊天面板,还是需要调用工具处理,这部分逻辑在src/core/assistant-message/parse-assistant-message.ts 的 parseAssistantMessageV2 方法内。
针对我们本次创建排序算法的任务,下面是一个模型输出样例:
<thinking>\n我需要在`src/utils/index.ts`文件中添加一个快速排序算法。首先,我已经看到了文件的内容,这是一个工具函数集合文件,包含了各种实用函数,如rpx转换、vw计算、类型检查、日志记录等。\n\n我需要在这个文件中添加一个快速排序算法实现。快速排序是一种高效的排序算法,基于分治法的思想。我将实现一个通用的快速排序函数,可以对数组进行排序。\n\n我将使用`replace_in_file`工具来修改文件,在文件末尾添加快速排序算法的实现。我需要确保添加的代码与现有代码风格保持一致,并提供适当的类型注解和注释。\n\n我将在文件末尾添加快速排序算法的实现,包括:\n1. 一个主快速排序函数,接受一个数组和可选的比较函数\n2. 一个辅助函数用于分区操作\n\n让我使用`replace_in_file`工具来修改文件。\n</thinking>\n\n<replace_in_file>\n<path>src/utils/index.ts</path>\n<diff>\n------- SEARCH\nexport const jump2UpdateApp = () => {\n if (is… (a, b) => {\n if (a < b) return-1;\n if (a > b) return1;\n return0;\n}): T[ ] => {\n // 创建数组副本,不修改原数组\n const result = [...arr];\n \n // 内部快速排序实现\n const _quickSort = (arr: T[ ], left: number, right: number) => {\n if (left < right) {\n const pivotIndex = partition(arr, left, right);\n _quickSort(arr, left, pivotIndex - 1);\n _quickSort(arr, pivotIndex + 1, right);\n }\n };\n \n // 分区操作\n const partition = (arr: T[ ], left: number, right: number): number => {\n // 选择最右边的元素作为基parseAssistantMessageV2 方法会解析上述输出内容,主要是从模型输出中解析出使用哪些工具以及工具的参数,比如这里我们发现模型输出中有 <replace_in_file>,那就说明这次需要使用 replace_in_file 工具。
接下来调用 presentAssistantMessage 方法真正将模型消息展示给用户,一方面展示文本消息,类似下图:
一方面执行上一步解析出的 tool,将模型生成代码以 diff 的方式写入文件,这里借助 VSCode 的能力创建 diffView。自此这个任务算是完成了。
总结
抛开 Cline 中用户交互和工程处理的部分,我们发现最核心的其实只有两件事情:
1、prompt 组装。这其中包括了 System Prompt、VSCode 和系统的环境信息、内置 Command、内置的 @ 引用(文件、目录信息)、用户的输入(文本、图片、文本文件),当然还有我们之前介绍的 Rules 以及我们提到过的 Workflow(本质是用户自定义的 Command)。这些内容共同组装称为 Prompt 发送给模型,力求给模型足够多的上下文信息,获得更加准确的结果。
2、tools 调用。首先在 System Prompt 定义了模型可以调用的 Tool(包括内置的和本文未涉及的 MCP Server ),在模型输出时指定调用的 Tool 和需要的参数,以此进一步增强模型的能力。
两者共同合作完成用户的编码的任务。
由此我们可以看到 Agent 开发中最重要的三点:
2. 丰富的创意和合适的落地场景;
3. 丝滑的体验。
53AI,企业落地大模型首选服务商
产品:场景落地咨询+大模型应用平台+行业解决方案
承诺:免费POC验证,效果达标后再合作。零风险落地应用大模型,已交付160+中大型企业
2026-06-30
Context 即 Agent:下一场 AI 产品战争,是上下文之争
2026-06-30
解析Agent Loop(智能体循环)的三层分级体系
2026-06-30
Cursor、OpenClaw 同时出手,“口袋编程”时代来了:程序员只用“动嘴”!
2026-06-30
从文本到多模态:大模型非结构化数据加工与质量控制实践
2026-06-30
从Anthropic的B端战略,给迷茫中的扣子一些建议
2026-06-30
Claude最新:创始人实操手册:打造 AI 原生初创公司(中文版)
2026-06-30
本体+AI驱动的AI智能体工厂-从设计到实现
2026-06-30
微信AI,能避开豆包手机的窘境吗?
2026-04-15
2026-04-07
2026-04-07
2026-04-24
2026-04-17
2026-04-05
2026-04-02
2026-04-05
2026-04-14
2026-04-24
欢迎您使用【53AI 官方网站】(以下简称“本网站”或“我们”)。本《会员服务协议》(以下简称“本协议”)是您(以下简称“会员”或“用户”)与【深圳市博思协创网络科技有限公司】之间关于注册、登录及使用本网站会员服务所订立的法律协议。
在您注册或登录前,请务必审慎阅读、充分理解各条款内容,特别是免除或限制责任的条款、知识产权条款、争议解决条款等。此类条款将以加粗形式提示您注意。 当您通过微信公众号授权、手机验证码验证或其他方式成功登录本网站时,即视为您已完全理解并同意接受本协议的全部内容。
一、 定义
本网站:指由【深圳市博思协创网络科技有限公司】运营的,域名为【53ai.com】的网站及相关移动端页面。
会员服务:指本网站向注册会员提供的知识库文章查阅、内容检索及其他相关增值服务。
知识库内容:指本网站发布的包括但不限于文字、图表、数据、研究报告、行业分析等数字化内容资源。
二、 账号注册与登录
登录方式:本网站支持以下登录方式,您可根据实际情况选择:
微信公众号授权登录:您同意将您的微信OpenID信息授权给本网站,用于创建或关联会员账号。
手机验证码登录:您需提供真实有效的手机号码,并通过短信验证码完成身份验证与登录/注册。
账号安全:您的账号仅限您本人使用,禁止赠与、借用、租用、转让或售卖。因您保管不善导致的账号被盗、密码泄露等损失,由您自行承担。
实名认证:根据相关法律法规要求,我们可能要求您在特定功能下完成实名认证。如您拒绝提供,可能无法使用部分或全部服务。
未成年人保护:若您未满18周岁,请在法定监护人的陪同下阅读本协议,并在征得监护人同意后使用本服务。
三、 服务内容与规范
知识库查阅权限:会员登录后,有权按照其会员等级对应的权限范围,在线浏览、检索本网站知识库中的相关文章及内容。
服务变更:我们有权根据业务发展需要,调整、变更或终止部分服务内容,并将以网站公告、公众号消息等方式提前通知。
禁止行为:您在使用服务时不得实施以下行为:
利用技术手段批量爬取、下载、转存知识库内容;
将知识库内容用于商业目的或未经授权地向第三方传播;
干扰本网站正常运行或侵犯其他用户合法权益;
发布违法违规信息或从事违反公序良俗的活动。
四、 知识产权声明
权利归属:本网站知识库中的排版设计、软件代码等内容的知识产权均归【公司全称】或原权利人所有,受《中华人民共和国著作权法》等法律保护。
有限许可:本网站授予会员一项非独占、不可转让、不可转授权的普通许可,仅限于个人学习、研究之目的在线查阅知识库内容。
侵权追责:未经书面许可,任何单位或个人不得以任何形式复制、转载、摘编、镜像、汇编或以其他方式使用上述内容。一经发现,我们保留追究其法律责任的权利。
五、 个人信息保护
我们重视对您个人信息的保护。关于我们如何收集、使用、存储和保护您的个人信息,请单独阅读 《隐私政策》。
您通过微信公众号授权或手机号验证所提供的信息,我们将严格按照《个人信息保护法》的规定处理,仅用于身份识别、服务提供及安全验证等必要用途。
您可以随时通过网站设置或联系客服行使查阅、更正、删除个人信息及撤回授权同意的权利。
六、 免责声明
内容准确性:知识库内容仅供参考,不构成专业建议。我们不对其完整性、准确性、时效性作任何明示或暗示的保证,您应自行判断并承担使用风险。
不可抗力:因自然灾害、政策法规变化、网络故障、第三方平台接口异常(如微信接口维护、运营商短信通道故障)等不可抗力导致的服务中断或延迟,我们不承担违约责任。
第三方链接:本网站可能包含指向第三方网站的链接,该等网站的内容和服务不受我们控制,请您自行甄别风险。
七、 违约责任
如您违反本协议约定,我们有权视情节采取警告、限制功能、暂停服务、注销账号等措施,并保留要求赔偿损失的权利。
如因您的违约行为导致我们遭受行政处罚、第三方索赔或商誉损失,您应承担全部赔偿责任(包括但不限于罚款、赔偿金、律师费、公证费等)。
八、 法律适用与争议解决
本协议的订立、执行和解释均适用中华人民共和国大陆地区法律。
因本协议产生的或与本协议有关的任何争议,双方应友好协商解决;协商不成的,任何一方均可向【公司所在地】有管辖权的人民法院提起诉讼。
九、 其他
本协议构成双方就本服务达成的完整协议,取代此前任何口头或书面约定。
本协议任一条款被认定为无效或不可执行的,不影响其他条款的效力。
我们对本协议享有最终解释权,并在法律允许的范围内保留随时修改的权利。修改后的协议一经公布即生效,继续使用服务即视为同意修订内容。