Emigo: 复刻 Cursor - Aidermacs精神续作

如果完全能用自然语言描述还是挺方便,特别是需要频繁切换上下文的时候,比如代码大致写好了,需要微调的时候。
发现某个功能存在问题我可以直接说“xx功能里面存在bug,每次打开会刷新两次/按钮显示不全”,cursor/copilot的话会自动找到实现xx功能的文件,然后分析源码进行修改,虽然慢点,但是我可以切出去干其他事情,等他改完了看看diff就行

能否让ai自动根据代码索引去找?这样就可以避免附带一整个文件。人给它指路的时候也不需要找好了文件告诉他。只需要把当前函数告诉它,说这里有什么问题,然后它就用lsp或者tag去找当前函数中的函数变量。。。。

现在ai好像是把整个文件都读一遍。这种读整个文件都方式比较分散注意力。

aider貌似就是这样做的,带了个repo_map,aider的文档里说的 “可以不明确add文件,但是add了文件效果更好”。
不过实际体验下来,aider的自动添加上下文效果不好,经常不修改我原来的文件,而是去添加新的文件。cursor和copilot的agent对这点的处理要好很多,都会先根据输入的语义去找实现,找到了再修改

cursor和copilot是怎么作的?他们内部是不是有什么独家秘籍。

就是像上面MT说的那样,根据输入重新判断上下文吧。
用cursor/copilot的时候你看他的输出,会显示,先用了搜索工具找到一些文件,然后读某个文件,会循环每次几百行的读文件直到找到输入中我们提到的功能为止。 找到了再开始修改
缺点就是慢,每次都要去找,优点就是省心,免去了自己去操作上下文的过程

1 个赞

Hello,

今天尝试用 emigo 时发现没办法启动,会报错:

[2025-04-06 22:39:42.729] eval: Recursive load: "/Users/mirageturtle/.emacs.d/straight/build/emigo/emigo.elc", "/Users/mirageturtle/.emacs.d/straight/build/emigo/emigo.elc", "/Users/mirageturtle/.emacs.d/straight/build/emigo/emigo.elc", "/Users/mirageturtle/.emacs.d/straight/build/emigo/emigo.elc", "/Users/mirageturtle/.emacs.d/straight/build/emigo/emigo.elc"

之前刚 patch chore: fix the undefined function issue of example configuration. · MatthewZMD/emigo@c0f2350 · GitHub 的时候是没问题来着(包括「不 patch+ 手动 load」和「patch 使其 autoload」,至少启动没问题),所以我觉得应该不是 emigo 的锅。但奈何我对 Emacs 了解不够深,也不太清楚要怎么 debug 比较好,所以来论坛里求大家指点和帮助。

删掉重下看看?

删掉重下也一样的问题🤣

有什么 Debug 上的建议吗?我来自查看看。

应该是配置不知道为啥循环了,可能和elc有关,也可能和straight有关。

看了下 Backtrace,看上去应该是因为 调用 emigo-read-file-content 的时候触发了 load emigo(因为 emigo-read-file-content 也定义在 emigo.el 里)?

  load-with-code-conversion("/Users/mirageturtle/.emacs.d/straight/build/emigo/..." "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t)
  (emigo-read-file-content "~/Documents/secrets/my_uni_api_key")
  eval((emigo-read-file-content "~/Documents/secrets/my_uni_api_key"))
  custom-initialize-reset(emigo-api-key (funcall #'(closure (t) nil "" "")))
  custom-declare-variable(emigo-api-key (funcall #'(closure (t) nil "" "")) "API key for AI model.")
  #<subr eval-buffer>(#<buffer  *load*-908077> nil "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t)
  apply(#<subr eval-buffer> (#<buffer  *load*-908077> nil "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t))
  eval-buffer(#<buffer  *load*-908077> nil "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t)  ; Reading at buffer position 1249
  load-with-code-conversion("/Users/mirageturtle/.emacs.d/straight/build/emigo/..." "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t)
  (emigo-read-file-content "~/Documents/secrets/my_uni_api_key")
  eval((emigo-read-file-content "~/Documents/secrets/my_uni_api_key"))
  custom-initialize-reset(emigo-api-key (funcall #'(closure (t) nil "" "")))
  custom-declare-variable(emigo-api-key (funcall #'(closure (t) nil "" "")) "API key for AI model.")
  #<subr eval-buffer>(#<buffer  *load*> nil "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t)
  apply(#<subr eval-buffer> (#<buffer  *load*> nil "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t))
  eval-buffer(#<buffer  *load*> nil "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t)  ; Reading at buffer position 1249
  load-with-code-conversion("/Users/mirageturtle/.emacs.d/straight/build/emigo/..." "/Users/mirageturtle/.emacs.d/straight/build/emigo/..." nil t)
  (emigo)

OT:

似乎 requirements.txt 少了 orjson

懂了,别用emigo-read-file-content,你自己想办法把api-key的内容存进去。

对,我现在是这么搞的,:init 自己定义一下 emigo-read-file-content 看上去也可以。

前排(已经不那么前排了)强势关注 08

avante.nvim 作者 yetone 对于 cursor 的看法

https://fixupx.com/yetone/status/1910326716293329364

其实 cursor 的原理并不简单,真正实施起来那就更难了,而且它所有的工程难度恰恰就只是为了解决一个问题 ——「不要让用户手动复制粘贴代码」,所以它在用户体验上下了苦功夫,不仅在工程上要在传统代码编辑器上发明新的代码编辑的范式和工作流,还自己训练和部署了快速 edit 模型 FastApply,自己训练和部署了 cursor tab prediction 模型 Fusion,为了更好地解决 context 携带问题,在本地和服务端做了两层 RAG,这一切都不是一时半会儿能够超越的,这还没说它一路走来做的那些 shadow workspace 等等类似的实验了

我们跟 avante 作者 (曾经也是一位Emacser) 交流过的, Cursor 确实有很多优势。

难点在于 你要解决的问题依赖哪些东西应该塞到上下文中

  1. 塞太多,成本, 上下文长度都是问题

  2. 塞太少,你的问题比较难很精确的表达清楚(自然语言为了效率,牺牲了一些精准度)

一开始只能给非常小的上下文,让LLM来决定还需要哪些信息,在llm之外解决上下文选取,只能说是权宜之计。

比较赞同这个观点

你提到了先给一小部分上下文,aider 的一个好实践就是实现了函数级别的 index,需要细节的时候再发送 function body

编程里还是有很多问题,

  1. 比较难(主要是工程实践上还没探索出其他方法)
  2. 或者从 llm 本身的机制上(推理的深度)上暂时是无解的

我们总是会短期高估llm的能力,长期低估llm 从其他维度涌现新的可能性

可以关注这个:https://www.reddit.com/r/neovim/comments/1jy1oms/seeking_bounty_hunters_for_cursortabnvim_1k_of/

我重新构想了一个Emigo的Agentic workflow,借鉴 Aider 在 Architect 与 Coding 角色之间的明确分工,并结合了 Cursor、Devin 及 Lovable 等工具中的理念,强调human-in-the-loop,旨在在最大化清晰度、安全性与精确度的同时,始终让用户对每个环节保持绝对掌控。

在此流程中,一个由大上下文LLM(如 Gemini 2.5 Pro)驱动的Architect Agent通过 MCP 与 Repomapper 深入整合聊天记录、代码库及文件结构,全面理解项目。类似于 Cursor 与 Devin,它对整个代码库进行整体性推理,生成清晰的分步方案,起草伪代码,并精准定位需要修改的文件及行号。

当用户对Archietct Agent提出的方案满意并予以批准后,经过筛选且仅限于明确认可的上下文信息,会交给专注于编程的Coder Agent(如 Claude Sonnet)。该Agent仅根据批准范围执行变更,生成简洁的diff,然后发送到 Emacs 中应用。

欢迎大家来一起讨论:Emigo New Agentic Workflow Proposal · MatthewZMD/emigo · Discussion #16 · GitHub

11 个赞