从零开始构建一款开源的 Vibe Coding 产品 Week1Day4:业界调研之 Agent 横向对比
wptr33 2025-10-02 09:05 15 浏览
前情回顾
前面两天我们重点调研了了一下 Cursor 的原理和 Cursor 中一个关键的工具 edit_file 的实现,但是其他 Coding Agent 也需要稍微摸一下底,看看有没有优秀之处,下面是调研的结果。
调研的 Coding Agent 列表
VSCode 插件
1. Cline
GitHub: https://github.com/cline/cline
Website: https://cline.bot/
2. GitHub Copilot
GitHub: https://github.com/microsoft/vscode-copilot-chat
Website: https://github.com/features/copilot
IDE
1. Cursor
GitHub: https://github.com/cursor/cursor
Website: https://cursor.sh/
Command Line
1. Claude Code
GitHub: https://github.com/anthropics/claude-code
Website: https://docs.anthropic.com/en/docs/claude-code/overview
2. Gemini CLI
GitHub: https://github.com/google-gemini/gemini-cli
Website: https://developers.google.com/gemini-code-assist/docs/gemini-cli
3. Aider
GitHub: https://github.com/Aider-AI/aider
Website: https://aider.chat/
4. OpenCode
GitHub: https://github.com/opencode-ai/opencode
Tools List
横向对比
Claude Code 的工具名和 Aider 很相似,有理由相信它一开始是基于 Aider 来开发的
Cursor
搜索与发现
codebase_search - 语义搜索代码库,基于内容理解进行智能搜索
grep_search - 使用正则表达式进行精准文本搜索
file_search - 模糊搜索文件路径,快速定位目标文件
web_search - 搜索网页信息,获取在线资源
list_dir - 列出目录内容,浏览文件结构
文件系统操作
read_file - 读取文件内容,支持各种文本格式
edit_file - 编辑或创建文件,支持多种编程语言
delete_file - 删除指定文件
reapply - 重新应用之前的编辑操作(当编辑失败时使用)
指令执行
run_terminal_cmd - 执行终端命令,运行脚本和程序
知识管理
update_memory - 存储或更新项目相关记忆,保持上下文连贯性
GitHub 集成
fetch_pull_request - 获取 Pull Request 或 Commit 详细信息
fetch_github_issue - 获取 GitHub Issue 信息和讨论内容
内容生成
create_diagram - 创建 Mermaid 图表,可视化流程和架构
Trae
search_codebase - 基于语义的代码搜索
search_by_regex - 正则表达式文本搜索
view_files - 查看多文件内容
list_dir - 列出目录结构
write_to_file - 创建/覆写文件
update_file - 块替换式文件编辑
edit_file_fast_apply - 快速代码片段修改
rename_file - 文件重命名/移动
delete_file - 删除文件
run_command - 执行系统命令
check_command_status - 命令状态检查
stop_command - 终止运行中命令
open_preview - 预览网页应用
web_search - 联网搜索
finish - 结束会话
Cline
read - 读取文件内容
write - 写入或创建文件
edit - 对文件进行定向编辑
ask_question - 向用户提出后续问题
plan_mode_respond - 以计划模式进行响应
bash - 执行命令行命令
ls - 列出目录内容
grep - 使用正则表达式搜索文件
web_fetch - 获取网页内容
list_code_definition_names - 列出代码定义名称use_mcp_tool - 使用 MCP 服务器工具
access_mcp_resource - 访问 MCP 服务器资源
load_mcp_documentation - 加载 MCP 文档
new_task - 创建新任务
attempt_completion - 展示最终结果
browser_action - 浏览器自动化(取决于 supportsBrowserUse 设置)
Github Copilot
文件操作工具:
apply_patch - 应用代码补丁到文件
read_file - 读取文件内容
create_file - 创建新文件
insert_edit_into_file - 向现有文件插入编辑内容
replace_string_in_file - 替换文件中的字符串
list_dir - 列出目录内容
create_directory - 创建新目录
搜索和发现工具:
file_search - 按名称/模式查找文件
grep_search - 在文件中搜索文本内容
semantic_search - 语义代码库搜索
search_workspace_symbols - 搜索代码符号
list_code_usages - 查找代码使用引用
test_search - 查找测试文件
get_search_view_results - 获取搜索视图结果
项目结构工具:
read_project_structure - 读取整体项目结构
get_doc_info - 获取文档信息
开发工具:
run_tests - 执行测试套件
test_failure - 处理测试失败
get_errors - 获取编译/检查错误
run_vs_code_task - 运行 VSCode 任务
create_and_run_task - 创建并执行任务
版本控制工具:
get_changed_files - 获取 SCM 更改
终端和命令工具:
run_in_terminal - 执行终端命令
get_terminal_output - 获取终端输出
get_terminal_selection - 获取终端选择内容
get_terminal_last_command - 获取最后一个终端命令
run_vscode_command - 运行 VSCode 命令
扩展和环境工具:
install_extension - 安装 VSCode 扩展
get_vscode_api - 访问 VSCode API
update_user_preferences - 更新用户设置
笔记本工具:
create_new_jupyter_notebook - 创建 Jupyter 笔记本edit_notebook_file - 编辑笔记本文件
run_notebook_cell - 执行笔记本单元格
read_notebook_cell_output - 读取单元格输出
copilot_getNotebookSummary - 获取笔记本摘要
工作区和项目工具:
create_new_workspace - 创建新工作区
get_project_setup_info - 获取项目设置信息
网络和外部工具:
fetch_webpage - 获取网页内容
github_repo - 访问 GitHub 仓库
open_simple_browser - 打开简单浏览器
实用工具:
think - 内部推理工具
Gemini CLI
list_directory - 列出文件和目录
read_file - 读取文件内容
search_file_content - 使用正则表达式搜索文件内容
glob - 查找匹配模式的文件
replace - 编辑/替换文件内容
write_file - 将内容写入文件
web_fetch - 获取URL内容
read_many_files - 一次读取多个文件
run_shell_command - 执行shell命令
save_memory - 保存到长期记忆
google_web_search - 执行网络搜索
Claude Code
Bash - 执行shell命令
Read - 从文件系统读取文件
Write - 将文件写入文件系统
Edit - 编辑现有文件
MultiEdit - 对文件进行多处编辑
Glob - 文件模式匹配
Grep - 搜索文件内容
LS - 列出目录
WebSearch - 搜索网络
WebFetch - 获取网页内容
TodoRead - 读取待办事项列表
TodoWrite - 管理待办事项列表
NotebookRead - 读取Jupyter笔记本
NotebookEdit - 编辑Jupyter笔记本
exit_plan_mode - 退出规划模式
Aider
File Operations:
Read - 读取文件系统中的文件(带行号)
Edit - 在文件中进行精确的字符串替换
MultiEdit - 对单个文件进行多处编辑
Write - 写入/覆盖整个文件
NotebookRead - 读取 Jupyter 笔记本(.ipynb 文件)
NotebookEdit - 编辑 Jupyter 笔记本单元格
File Discovery & Search:
Glob - 使用模式(如 **/*.js)查找文件
Grep - 使用正则表达式搜索文件内容
LS - 列出文件和目录
System Operations:
Bash - 在持久化的shell会话中执行bash命令
Task Management:
TodoRead - 读取当前待办事项列表
TodoWrite - 创建和管理结构化任务列表
Web Operations:
WebFetch - 获取并使用AI处理网页内容
WebSearch - 搜索网络信息
Agent & Planning:
Task - 启动专门的代理处理复杂搜索
exit_plan_mode - 在展示实施计划后退出规划模式
OpenCode
bash - 命令执行
edit - 使用查找/替换进行文件编辑
fetch - HTTP内容获取
glob - 文件模式匹配
grep - 使用正则表达式进行内容搜索
ls - 目录列表
sourcegraph - 公共代码仓库搜索
view - 带行号的文件查看
patch - 多文件补丁应用
write - 文件创建/覆写
agent - 子代理生成
diagnostics (条件性) - 可用时的LSP诊断
Edit Tool 实现
Cline
参数
file_path (字符串): 要修改的文件的绝对路径
edits (数组): 编辑操作数组,每个操作包含:
old_string (字符串): 要替换的确切文本
new_string (字符串): 替换文本
输出格式
返回按顺序应用文件修改的结构化结果。支持:
diff 格式的 SEARCH/REPLACE 块:
------- SEARCH
旧内容在这里
=======
新内容在这里
+++++++REPLACE
流式 JSON 替换 用于实时更新
工具使用接口 带有 type/name/params 结构
错误处理 具有特定错误类型和验证
工具映射:MultiEdit → replace_in_file 内部映射
核心字符串匹配层次结构
精确字符串匹配(主要方式)
constexactIndex = originalContent.indexOf(currentSearchContent,lastProcessedIndex)
简单的 indexOf 子字符串搜索
时间复杂度:O(n×m),其中 n=文件长度,m=搜索模式长度
从 lastProcessedIndex 开始以保持顺序
行修剪回退匹配
functionlineTrimmedFallbackMatch(originalContent:string, searchContent:string, startIndex:number)
将两个内容分割成行
在 trim 后逐行比较以忽略空白字符
时间复杂度:O(n×m×k),其中 k=平均行长度
块锚点匹配(仅限 3+ 行)
functionblockAnchorFallbackMatch(originalContent:string, searchContent:string, startIndex:number)
使用第一行和最后一行作为"锚点"
时间复杂度:O(n×2) - 仅检查首末行
全文件搜索(最后手段)
constfullFileIndex = originalContent.indexOf(currentSearchContent,0)
从头开始搜索整个文件,用于乱序编辑
忽略 lastProcessedIndex
字符串处理细节
正则表达式模式:
constSEARCH_BLOCK_START_REGEX =/^[-]{3,} SEARCH>?$/
constSEARCH_BLOCK_END_REGEX =/^[=]{3,}$/
constREPLACE_BLOCK_END_REGEX =/^[+]{3,} REPLACE>?$/
字符索引计算:
letmatchStartIndex = 0
for(letk = 0; k < lineNumber; k++) {
matchStartIndex += originalLines[k].length + 1 // +1for\n
}
算法复杂度
时间复杂度:
最佳情况:O(n) - 单次精确匹配
平均情况:O(n×m) - 精确字符串匹配
最坏情况:O(n×m×k×4) - 所有回退策略失败
空间复杂度:
O(n + m) - 存储原始内容 + 搜索模式
O(L) 额外用于行数组,其中 L = 行数
关键特性
顺序处理:维护 lastProcessedIndex 确保编辑按文件顺序应用
贪婪匹配:取找到的第一个匹配,无回溯
无模糊匹配:仅精确字符串/修剪行匹配
基于锚点的优化:使用首末行减少大块的搜索空间
回退策略链:从最精确到最宽松的分层方法
Gemini CLI
参数
file_path (字符串,必需): 文件的绝对路径
old_string (字符串,必需): 要替换的文本
new_string (字符串,必需): 替换文本
expected_replacements(数字,可选): 预期替换次数 (默认: 1)
输出
成功: "Successfully modified file: {path} ({count} replacements)" 或带有统一差异的 FileDiff 对象
错误: 描述性消息如 "Failed to edit, could not find the string to replace"
实现原理
该工具不会重新生成整个文件,而是使用就地文本替换方式:
实现步骤
将现有文件内容读入内存 (fs.readFileSync)
使用 JavaScript 的 replaceAll 方法应用字符串替换 (第192行)
将修改后的内容写回磁盘 (fs.writeFileSync)
关键要点
使用
currentContent.replaceAll(oldString, newString)
进行替换
仅将修改后的内容写回磁盘
对于新文件,直接写入 newString
无需完整文件重新生成 - 仅进行目标文本替换
核心算法详解
基础字符串匹配 (JavaScript replaceAll)
currentContent.replaceAll(oldString, newString)
使用 JavaScript 原生的 String.replaceAll方法
时间复杂度:O(n×m),其中 n = 内容长度,m = 模式长度
算法:V8 引擎中类似 Boyer-Moore 的实现
出现次数计算算法
functioncountOccurrences(str:string, substr:string):number{
letcount =0;
letpos = str.indexOf(substr);
while(pos !==-1) {
count++;
pos = str.indexOf(substr, pos + substr.length);
}
returncount;
}
算法:防止重叠的朴素字符串搜索
时间复杂度:O(n×m) 最坏情况
空间复杂度:O(1)
智能纠正管道
阶段 1:直接匹配
尝试精确的 old_string 匹配 → 计算出现次数
如果匹配预期次数 → 继续进行
阶段 2:反转义纠正
javascript
unescapeStringForGeminiBug(inputString):
returninputString.replace(/\\+(n|t|r|'|"|`|\\|\n)/g, (match, char) => {
//转换 \\n → \n, \\" → ", 等
})
正则表达式模式:/\\+(n|t|r|'|"||\|\n)/g`
修复 LLM 生成的过度转义问题
阶段 3:AI 驱动的纠正
使用 Gemini Flash 模型在文件中查找相似文本
通过 LLM 语义理解进行模糊匹配
尝试纠正 old_string 和 new_string
阶段 4:修剪优化
javascript
trimPairIfPossible// 如果能改善匹配,移除前导/尾随空白字符
缓存策略
LRU 缓存 (最大 50 个条目)
缓存键:
${currentContent}---${originalParams.old_string}---${originalParams.new_string}
避免冗余的 LLM 调用
算法特性
该算法主要基于精确字符串匹配,配备智能回退机制来处理常见的转义问题,并在精确匹配失败时使用 AI 驱动的模糊纠正。工具具有内存效率,仅加载/处理文件内容一次并执行直接字符串替换。
Claude Code
参数
必需参数:
file_path (字符串): 文件的绝对路径
old_string (字符串): 要替换的文本
new_string (字符串): 替换文本
可选参数:
replace_all (布尔值): 替换所有出现的位置 (默认: false)
输出格式
javascript
{
filePath:string,
oldString:string,
newString:string,
originalFile:string,
structuredPatch: object,
userModified: boolean,
replaceAll:boolean
}
实现原理
Edit 工具会重新生成整个文件。基于实现模式和工具接口,它:
将整个文件作为字符串读入内存
使用 JavaScript 的 .replace 方法执行字符串替换
将完整的新内容写回文件
核心实现模式
// 读取整个文件
constcontent = fs.readFileSync(filePath,'utf8');
// 替换字符串
constnewContent = replaceAll ?
content.replaceAll(oldString, newString) :
content.replace(oldString, newString);
// 写入整个新文件
fs.writeFileSync(filePath, newContent,'utf8');
它不进行就地编辑 - 而是在内存中处理完整的文件内容并写出整个修改后的版本。
核心算法详解
字符串替换算法
functioneditFile(content, oldString, newString, replaceAll) {
if(replaceAll) {
// 替换所有出现的位置
returncontent.replaceAll(oldString, newString);
}else{
// 仅替换第一个出现的位置
constindex = content.indexOf(oldString);
if(index ===-1)thrownewError("String not found");
// 检查唯一性
if(content.indexOf(oldString, index +1) !==-1) {
thrownewError("Multiple matches found, use replace_all or provide more context");
}
returncontent.replace(oldString, newString);
}
}
关键算法细节
字符串搜索
使用 indexOf 对文件内容进行线性搜索
时间复杂度:O(n×m),其中 n=文件大小,m=搜索字符串长度
逐字节搜索 UTF-8 编码的文本
唯一性验证
当 replace_all=false 时,检查多个匹配项
扫描整个文件以计算出现次数
如果 old_string 出现超过一次则失败
替换策略
单次替换:
string.replace(oldString, newString)
- 替换第一个匹配项
全部替换:
string.replaceAll(oldString, newString)
- 替换所有匹配项
创建包含替换内容的新字符串
内存使用
将整个文件作为单个字符串加载到内存中
创建包含替换内容的新字符串 (写时复制)
内存需求:操作期间约为文件大小的 2 倍
边界情况
空的 old_string - 拒绝
old_string == new_string- 拒绝
不存在的文件 - 错误
二进制文件 - 可能损坏数据
超大文件 - 内存限制
算法特性
该算法是直接的字符串操作,而非复杂的文本解析或基于 AST 的编辑。它主要基于精确字符串匹配,通过内存中的完整文件处理来实现文本替换。
感想
看了这么多工具,我个人感觉在工具使用层面,各个 Coding Agent 没有太本质的差异,我依然保持下面这些是 Coding Agent 关键能力的想法:
一个完整的文件系统,这是给「搜索与查找工具」和「文件操作工具」来使用的;
一个完整的 windows/unix 的沙箱,这是给「run_terminal_cmd」工具用的,因为这个工具会调用各种系统命令;
联网搜索的能力,包括基于搜索引擎搜索和 Github 相关的搜索。
高效的 edit_file:大模型生成完整的代码生成会很耗时,在修改场景,看起来只会生成部分片段,这个片段的格式不是典型的 git diff 格式,是一种很模糊的格式,edit_file 也有类似于 Prompt 的内容,推测它的实现也是基于模型的。
高效的语义化索引/搜索工具:看起来是需要基于 Embedding 模型和向量数据库构建语义化搜索工具。
相关推荐
- 什么是Java中的继承?如何实现继承?
-
什么是继承?...
- Java 继承与多态:从基础到实战的深度解析
-
在面向对象编程(OOP)的三大支柱中,继承与多态是构建灵活、可复用代码的核心。无论是日常开发还是框架设计,这两个概念都扮演着至关重要的角色。本文将从基础概念出发,结合实例与图解,带你彻底搞懂Java...
- Java基础教程:Java继承概述_java的继承
-
继承概述假如我们要定义如下类:学生类,老师类和工人类,分析如下。学生类属性:姓名,年龄行为:吃饭,睡觉老师类属性:姓名,年龄,薪水行为:吃饭,睡觉,教书班主任属性:姓名,年龄,薪水行为:吃饭,睡觉,管...
- java4个技巧:从继承和覆盖,到最终的类和方法
-
日复一日,我们编写的大多数Java只使用了该语言全套功能的一小部分。我们实例化的每个流以及我们在实例变量前面加上的每个@Autowired注解都足以完成我们的大部分目标。然而,有些时候,我们必须求助于...
- java:举例说明继承的概念_java继承的理解
-
在现实生活中,继承一般指的是子女继承父辈的财产。在程序中,继承描述的是事物之间的所属关系,通过继承可以使多种事物之间形成一种关系体系。例如猫和狗都属于动物,程序中便可以描述为猫和狗继承自动物,同理,...
- 从零开始构建一款开源的 Vibe Coding 产品 Week1Day4:业界调研之 Agent 横向对比
-
前情回顾前面两天我们重点调研了了一下Cursor的原理和Cursor中一个关键的工具edit_file的实现,但是其他CodingAgent也需要稍微摸一下底,看看有没有优秀之处,下...
- 学会这几个插件,让你的Notepad++使用起来更丝滑
-
搞程序开发的小伙伴相信对Notepad++都不会陌生,是一个占用空间少、打开启动快的文件编辑器,很多程序员喜欢使用Notepad++进行纯文本编辑或者脚本开发,但是Notepad++的功能绝不止于此,...
- 将 node_modules 目录放入 Git 仓库的优点
-
推荐一篇文章Whyyoushouldcheck-inyournodedependencies[1]...
- 再度加码AI编程,腾讯发布AI CLI并宣布CodeBuddy IDE开启公测
-
“再熬一年,90%的程序员可能再也用不着写for循环。”凌晨两点半,王工还在公司敲键盘。他手里那份需求文档写了足足六页,产品经理反复改了三次。放在过去,光数据库建表、接口对接、单元测试就得写两三天。现...
- git 如何查看stash的内容_git查看ssh key
-
1.查看Stash列表首先,使用gitstashlist查看所有已保存的stash:...
- 6万星+ Git命令懒人必备!lazygit 终端UI神器,效率翻倍超顺手!
-
项目概览lazygit是一个基于终端的Git命令可视化工具,通过简易的TUI(文本用户界面)提升Git操作效率。开发者无需记忆复杂命令,即可完成分支管理、提交、合并等操作。...
- 《Gemini CLI 实战系列》(一)Gemini CLI 入门:AI 上命令行的第一步
-
谷歌的Gemini模型最近热度很高,而它的...
- deepin IDE新版发布:支持玲珑构建、增强AI智能化
-
IT之家8月7日消息,深度操作系统官方公众号昨日(8月6日)发布博文,更新推出新版deepin集成开发环境(IDE),重点支持玲珑构建。支持玲珑构建deepinIDE在本次重磅更...
- 狂揽82.7k的star,这款开源可视化神器,轻松创建流程图和图表
-
再不用Mermaid,你的技术文档可能已经在悄悄“腐烂”——图表版本对不上、同事改完没同步、评审会上被一句“这图哪来的”问得哑口无言。这不是危言耸听。GitHub2025年开发者报告显示,63%的新仓...
- 《Gemini CLI 实战系列》(五)打造专属命令行工具箱
-
在前几篇文章中,我们介绍了GeminiCLI的基础用法、效率提升、文件处理和与外部工具结合。今天我们进入第五篇...
- 一周热门
-
-
C# 13 和 .NET 9 全知道 :13 使用 ASP.NET Core 构建网站 (1)
-
程序员的开源月刊《HelloGitHub》第 71 期
-
详细介绍一下Redis的Watch机制,可以利用Watch机制来做什么?
-
如何将AI助手接入微信(打开ai手机助手)
-
假如有100W个用户抢一张票,除了负载均衡办法,怎么支持高并发?
-
SparkSQL——DataFrame的创建与使用
-
Java面试必考问题:什么是乐观锁与悲观锁
-
redission YYDS spring boot redission 使用
-
一文带你了解Redis与Memcached? redis与memcached的区别
-
如何利用Redis进行事务处理呢? 如何利用redis进行事务处理呢英文
-
- 最近发表
-
- 什么是Java中的继承?如何实现继承?
- Java 继承与多态:从基础到实战的深度解析
- Java基础教程:Java继承概述_java的继承
- java4个技巧:从继承和覆盖,到最终的类和方法
- java:举例说明继承的概念_java继承的理解
- 从零开始构建一款开源的 Vibe Coding 产品 Week1Day4:业界调研之 Agent 横向对比
- 学会这几个插件,让你的Notepad++使用起来更丝滑
- 将 node_modules 目录放入 Git 仓库的优点
- 再度加码AI编程,腾讯发布AI CLI并宣布CodeBuddy IDE开启公测
- git 如何查看stash的内容_git查看ssh key
- 标签列表
-
- git pull (33)
- git fetch (35)
- mysql insert (35)
- mysql distinct (37)
- concat_ws (36)
- java continue (36)
- jenkins官网 (37)
- mysql 子查询 (37)
- python元组 (33)
- mybatis 分页 (35)
- vba split (37)
- redis watch (34)
- python list sort (37)
- nvarchar2 (34)
- mysql not null (36)
- hmset (35)
- python telnet (35)
- python readlines() 方法 (36)
- munmap (35)
- docker network create (35)
- redis 集合 (37)
- python sftp (37)
- setpriority (34)
- c语言 switch (34)
- git commit (34)