资讯动态

把Cursor式diff审查引入AI文稿改写:margin-agent开源内核解析

发布时间:2026/8/27 8:15:53 来源:尧图企业网站定制
在实际的 AI 辅助写作场景里Cursor 给人最大的启发不是代码补全速度而是它把 AI 产生的结果摊开成 diff让开发者可以像 review 代码一样逐块确认。这种交互模式完全可以迁移到文稿改写AI 帮你把一段话改得更通顺、更有逻辑但不是直接替换全文而是把每一次改写的前后差异显示出来由作者决定哪些改动保留、哪些改动退回。围绕这个思路margin-agent 作为一个基于 pi 的开源内核把“AI 改稿 diff 审查”的核心流程拆成了可复用的模块。下面从交互设计、开源内核的数据建模、最小可运行命令行的实现讲到生产环境落地时需要注意的工程问题。对于经常使用 Cursor 的人来说这种体验并不陌生代码补全或重构建议出来后编辑器里用绿红高亮标出每一处新增和删除你可以逐个 accept、reject也可以把整个改动恢复到某个检查点。文稿编辑需要的正是同样的控制感。因为写文章和写代码有一点极其相似AI 的建议未必完全正确而最终为文本负责的人必须能看到每一处变化从哪里来、到哪里去。1. 先理解核心问题AI 改稿为什么要走 diff 审查1.1 全文替换模式的问题藏在“看不见的变更”里很多人第一次用 AI 改稿都是把一段文字丢给模型等它吐出一段改写后的完整文本然后复制粘贴覆盖原文。这个流程看起来很快但一旦进入真实写作场景问题立刻出现。首先是变更不可见。模型可能在第一段帮你调整了主语在第三段悄悄删掉了一个限定语在最后一段补充了一句原文根本没有的意思。你很难一眼扫出全部变化尤其是对上万字的文章。其次是无法局部接受。原文有三处需要改但模型把整个段落都重写了你可能只想要其中一半效果却很难只保留那一半。第三是版本历史丢失。覆盖之后原始版本去哪里了如果新版本引入语义偏差你只能凭记忆找回原稿。这些问题的本质不是模型不够聪明而是工作流缺少一个“变更展示与确认”的中间层。模型输出的是整段文本但人真正需要的是“改了什么”的精确说明。1.2 diff 审查模式把控制权交还给作者diff 是代码协作里最基础也最有效的工具它把一次变更拆解成若干最小差异并在文件的上下文里显示出来。margin-agent 做的事情就是把这个思路用到文稿改写里AI 先生成改写后的文本内核并不直接采用而是将原文与改写结果做一次 diff解析成多个独立的 hunk差异块再由作者对每个 hunk 分别做出接受、拒绝或跳过决定。这样改稿的流程就变成了给出原文和改写要求。模型返回改写后的完整文本。margin-agent 生成 unified diff。作者像评审代码一样逐块查看差异。只把通过的 hunk 合并回原文。这里的关键不是“自动替换”而是“可审查的变更”。AI 仍然负责产出但最终决定权回到作者手里。每一处改动都有上下文、有定位、有决策记录不再是一次黑箱覆盖。下面是全文替换模式和 diff 审查模式的对比对比维度全文替换模式diff 审查模式变更可见性低只能人工比对整段文字高每处改动以行级 diff 呈现局部接受不支持要么全用要么全弃支持按 hunk 分别决定回滚能力差覆盖后原始版本丢失好diff 可逆可保留评审记录协作记录无任何人都不知道改了什么有每次决策可追踪、可重放适用场景快速生成、内容草稿正式稿件、发布内容、多人协作1.3 Cursor 真正值得迁移的不是编辑器而是 diff 交互Cursor 这几年热度很高相关内容里讨论最多的其实是“Cursor 怎么用”“Cursor 怎么设置中文”这类入门问题。但真正让 Cursor 和普通 AI 编辑器拉开差距的是它对 diff 审查体验的打磨AI 生成不是终点把生成结果放进可确认、可反悔、可逐块操作的状态里才是生产力来源。文稿版 Cursor 并不需要复刻一个完整代码编辑器。它要复刻的是这个交互模型。margin-agent 作为内核把“AI 改写 → 生成 diff → 逐块评审 → 应用结果”这条链路抽象出来编辑器、命令行、Web 端都只是它的前端。这里要澄清一个容易误解的点diff 审查模式并不是让作者把 AI 的每处修改都检查一遍而是让作者有机会在关键位置停下来判断。实际使用中大多数 hunk 可以快速通过真正值得关注的是那些改变语义、删除内容、重排段落的大块改动。这也是 review 对代码的意义——不是不信任而是确保变更被理解。2. 产品形态把 Cursor 式 diff 交互落到文稿场景2.1 文稿 diff 和代码 diff 的差异不能被忽略如果直接把代码 diff 工具搬到文稿场景会碰到一些自然语言特有的问题。代码的最小单位是语句和表达而文稿的最小单位是句子和段落行长度差异很大。一段长句被改写后可能整行都变了diff 看起来就像一个巨大的 hunk反而不容易定位到具体词组变化。另外文稿中的换行不像代码那样有严格语义。Markdown 中一个自然段可能是连续多行也可能被空行分开中文文稿里全角标点和半角标点混用Windows 下还有 CRLF 行尾问题。这些都可能导致 diff 产生大量无关噪声。所以在 margin-agent 的设计里生成 diff 之前需要先做文本规范化统一行尾、去除行尾空格、避免把单纯的换行调整当成内容变更。否则使用者会在细碎差异里花掉大量时间最后觉得“还不如自己改”。2.2 一条完整的改稿审查链路一套可用的文稿版 Cursor 交互流程可以从用户选中文本开始。用户在编辑器里选中一段文字调用“AI 改稿”命令输入改写意图比如“更正式一点”“精简到 200 字”“补强论证逻辑”。模型返回改写结果后系统并不立刻替换原文而是把原文和改写结果交给 margin-agent。margin-agent 会做四件事规范化原文和改写结果的文本格式。生成 unified diff把差异拆成若干 hunk。为每个 hunk 提供起始行、结束行、改动前后范围等定位信息。等待上层 UI 收集用户决策再按决策应用改动。前端拿到 hunk 列表后可以像 Cursor 一样在文档里内联显示绿色表示新增红色表示删除用户对每个 hunk 按下批准或拒绝键。最后把所有 accepted 状态的 hunk 合并回文档生成新版本并写入一份评审记录。2.3 margin-agent 在这种形态里的位置很多开发者把 margin-agent 理解为又一个 AI 写作助手这个理解不够准确。它更像一个规则引擎加数据结构层只负责把“改写前文本”和“改写后文本”变成可审查的补丁不负责调用哪个模型也不负责渲染 UI更不负责存储用户文档。这种边界设计有一个直接好处上层产品可以自由替换模型、切换编辑器、改造界面而核心的 diff 解析、hunk 管理和决策状态机不用重写。如果你的目标是做一款自己的“文稿版 Cursor”margin-agent 可以成为底层内核而不是被某个编辑器绑死的插件。与 open code review、code review graph 这类工具类似margin-agent 也在做同一件事让变更过程被结构化、可视化、可记录。区别只在于 review 对象是代码还是文字。理解了这一点再看 margin-agent 的数据结构和工作流程就会容易很多。3. margin-agent 开源内核对 diff 工作流的建模3.1 内核职责不碰模型不碰 UI只碰 diffmargin-agent 的定位是“内核”这意味着它有清晰的职责边界。它接收两个字符串source_text 和 target_text前者是原始文稿后者是模型改写后的文本。它输出的是一组结构化的 diff hunk以及围绕这些 hunk 的评审状态。它不负责的事包括不内置模型模型调用由接入方完成。不提供编辑器界面交互层可以放在 VS Code、命令行或 Web。不管理用户文件文件读写由外层负责。不做语义判断只是一套“把改动拆开并追踪决策”的机制。这样设计的好处是接入成本低。你可以在任意语言、任意编辑器里调用它只要把两个字符串传进去就能得到一棵 diff 树。3.2 用 DiffSet Hunk ReviewState 描述一次改写一次完整的改稿审查过程可以用三个核心数据结构表达DiffSet 表示一次改写产生的全部差异Hunk 表示其中一块连续差异ReviewState 表示每块差异的决策状态。下面是一个 Python 数据建模示例展示 margin-agent 内部可以怎样组织这些对象from dataclasses import dataclass, field dataclass class Hunk: old_start: int # 原文本中的起止行号从 1 开始 old_count: int # 原文本中被替换的行数 new_start: int # 改写文本中的起止行号 new_count: int # 改写文本中新增的行数 lines: list # 该 hunk 的每一行带 、-、空格前缀 decision: str pending # pending / accepted / rejected / skipped dataclass class DiffSet: source_text: str target_text: str hunks: list field(default_factorylist) property def pending_count(self) - int: return sum(1 for h in self.hunks if h.decision pending) property def accepted_lines(self) - int: return sum(h.new_count for h in self.hunks if h.decision accepted)每个 Hunk 都保留 old_start、old_count、new_start、new_count这四组数字决定了“改动从哪里来、到哪里去、影响多少行”。decision 字段记录该 hunk 当前处于什么状态默认是 pending表示等待用户评审。3.3 基于 pi 的 skill 扩展方式margin-agent 基于 pi 这个 agent 运行时构建。pi 提供了 agent 运行、工具调用和 skill 机制开发者可以把一段具体的任务流程封装成 skill。margin-agent 把“文本改写评审”设计成一个 skill接收原文和改写要求调用模型但不在模型返回结果后直接结束而是把结果交给 diff 模块生成补丁再进入评审状态。下面是一段示意性代码用来表达这个接入思路。实际 pi 版本的接口可能会不同落地前需要以自己使用的 pi 版本为准# 示例基于 pi 的 skill 注册接口以实际 pi 版本为准 from margin_agent import DiffTool, ReviewState def register_text_review_skill(agent): agent.skill(text_review) def text_review(original: str, instructions: str): # 调用模型允许接入方替换为任意 LLM rewritten agent.call_llm(original, instructions) # 生成 diff 而不是直接返回改写文本 diff_set DiffTool().build(original, rewritten) # 进入评审状态机等待用户逐块确认 state ReviewState(diff_set) return state.wait_for_review()这样接入方的职责就变得很清晰只需要实现 call_llm以及把 state.wait_for_review() 展示到界面上。模型换掉不影响 diff 逻辑UI 换掉不影响状态机。3.4 为什么把评审决策做成状态机评审决策不能只用一个布尔变量表示。一个 hunk 从生成开始可能经历 pending → accepted也可能会从 accepted 被改回 pending允许用户反悔。如果某个 hunk 被拒绝后用户想重新查看它应该可以被重新开启。这就是状态机的价值。常见状态迁移是pending初始状态等待处理。accepted用户接受该 hunk后续应用时会合并进新文档。rejected用户拒绝该 hunk应用时跳过。reopened用户重新打开已处理的 hunk状态回到 pending。状态机的存在让整个 review 过程可审计、可恢复。即使中途关闭程序只要把评审记录持久化下次启动依然可以继续未完成的评审。4. 动手实现一个最小可用的文稿版 Cursor 命令行工具4.1 环境准备和项目结构为了验证 margin-agent 的 diff 审查思路可以不依赖复杂框架先用 Python 标准库实现一个命令行原型。它做的事情很简单输入原文和改写结果生成 diff逐块询问用户最后输出合并后的文稿。环境要求如下组件用途说明Python 3.10运行原型使用标准库 difflib无需额外依赖终端交互用于逐块展示 hunk 和收集决策模型接口改写文本原型阶段可以先手动准备改写结果不接模型项目结构保持精简text_review_cli/ ├── review_core.py # diff 生成、hunk 解析、hunk 应用 ├── cli.py # 命令行交互循环 └── samples/ ├── original.md └── rewritten.md原型阶段可以不接真实模型而是把模型改写后的文本先放到 rewritten.md 里。这能帮助你专注验证 diff 审查逻辑不被模型波动干扰。4.2 生成和解析 unified diff核心逻辑在 review_core.py 里。先用 difflib 生成 unified diff再解析出 hunk。这里选择 unified diff 是因为它包含文件头、 定位行以及带 、- 前缀的行信息足够完整适合做 hunk 级别的评审。import re import difflib HUNK_HEADER re.compile(r^ -(\d)(?:,(\d))? \(\d)(?:,(\d))? ) def make_unified_diff(original: str, rewritten: str, context: int 3): old_lines original.splitlines(keependsTrue) new_lines rewritten.splitlines(keependsTrue) diff_text difflib.unified_diff( old_lines, new_lines, fromfileoriginal, tofilerewritten, ncontext, ) return .join(diff_text) def parse_hunks(diff_text: str): hunks [] current None for line in diff_text.splitlines(keependsTrue): m HUNK_HEADER.match(line.strip()) if m: if current: hunks.append(current) current { old_start: int(m.group(1)), old_count: int(m.group(2) or 1), new_start: int(m.group(3)), new_count: int(m.group(4) or 1), lines: [], } elif current is not None: current[lines].append(line) if current: hunks.append(current) return hunksmake_unified_diff 返回完整的 diff 文本parse_hunks 把它拆成 hunk 列表。每个 hunk 里的 lines 保留了带前缀的原始行后续展示和决策都基于这个结构。4.3 逐块审批的交互循环cli.py 负责把 hunk 展示给用户并接收决策。为了让代码可运行这里把决策收集做成命令行输入a 表示接受r 表示拒绝s 表示跳过q 表示退出并保存当前进度。from review_core import make_unified_diff, parse_hunks def apply_hunk(source_lines: list, hunk: dict) - list: old_start hunk[old_start] - 1 old_count hunk[old_count] inserted [] for line in hunk[lines]: if line.startswith() and not line.startswith(): inserted.append(line[1:]) return ( source_lines[:old_start] inserted source_lines[old_start old_count:] ) def review_loop(original: str, rewritten: str): diff_text make_unified_diff(original, rewritten) hunks parse_hunks(diff_text) source_lines original.splitlines(keependsTrue) accepted_hunks [] for index, hunk in enumerate(hunks, start1): print(f\n--- Hunk {index}/{len(hunks)} f -{hunk[old_start]},{hunk[old_count]} f{hunk[new_start]},{hunk[new_count]} ) for line in hunk[lines]: print(line.rstrip(\n)) while True: choice input([a] accept / [r] reject / [s] skip / [q] quit: ).strip().lower() if choice a: accepted_hunks.append(hunk) break if choice in (r, s, q): if choice q: break break if choice q: break # 从后往前应用避免行号偏移 for hunk in sorted(accepted_hunks, keylambda h: h[old_start], reverseTrue): source_lines apply_hunk(source_lines, hunk) return .join(source_lines)这里最容易被忽视的是 apply_hunk 的顺序。如果从前往后应用第一个 hunk 插入新行后后续 hunk 的 old_start 就会失效造成行号错位。代码里把 accepted_hunks 按 old_start 从大到小排序从文件尾部开始应用可以避免偏移。4.4 运行验证与预期输出准备一份简单的样例。original.md 内容今天天气很好。 我们决定去公园散步。 公园里人很多。 我们玩得很开心。rewritten.md 内容假设是模型改写结果今天天气不错。 我们决定去公园散步。 公园里人虽然很多但气氛很好。 我们玩得很开心。运行python cli.py samples/original.md samples/rewritten.md终端会先显示第一个 hunk内容可能包含“今天天气很好。”被替换为“今天天气不错。”。如果输入 a第二个 hunk 会显示“公园里人很多。”处的新增行。输入 r 拒绝后最后输出的文稿里只有第一个 hunk 被应用今天天气不错。 我们决定去公园散步。 公园里人很多。 我们玩得很开心。这个结果说明评审机制生效了模型改写内容被拆成了独立差异用户只保留了想要的部分。5. 关键实现细节hunk 解析、上下文行和决策持久化5.1 为什么行级 diff 更适合文本改写文本改写中模型可能只修改一个词组但因为行太长diff 会把整行标记为删除和新增。这是行级 diff 的天然局限但它依然是当前最实用的方式原因有三点。第一行级 diff 天然支持定位。光标停在某个 hunk 上时你可以直接知道它对应原文第几行、改写后第几行。第二行级 diff 容易应用和回滚。按行删除、插入不会破坏没被修改的行。第三行级 diff 适合人和程序共同处理。编辑器插件、命令行工具、评审系统都支持统一的行概念。如果觉得行级太粗可以进一步在词级别做高亮但 margin-agent 的 hunk 结构仍然以行为单位。词级高亮只是展示层增强不会改变 hunk 的决策粒度。5.2 context 参数决定 hunk 的粗细unified diff 的 n 参数控制上下文行数。n 越大每个 hunk 周围保留的未修改行越多视觉上更容易理解但 hunk 数量会减少单块差异会变大。n 越小hunk 越聚焦但应用时对行号精确度要求更高。context 值hunk 行为合适场景0只保留实际变更行diff 最小精确展示每个修改点但可读性差1前后各保留 1 行上下文短段落、句子级改写3前后各保留 3 行上下文默认值适合普通文稿审查5 以上hunk 变大上下文完整需要理解段落整体结构时使用文稿改写建议从 context2 或 context3 开始。如果发现单块 hunk 过大可以调小 context让模型只产生更局部的小改动或者先把大段落拆成多个小段再分别改写。5.3 用 JSONL 保存评审记录评审不只是人与 AI 之间的交互过程也是内容生产的审计记录。margin-agent 推荐把每次 hunk 决策保存为 JSONL 文件一行一条记录。每条记录至少包括时间、hunk 定位、决策结果和可选原因。{ts: 2025-01-10T10:20:30Z, old_start: 1, old_count: 1, new_start: 1, new_count: 1, decision: accepted, reason: } {ts: 2025-01-10T10:20:35Z, old_start: 3, old_count: 1, new_start: 3, new_count: 2, decision: rejected, reason: 新增内容改变了原意}这份记录有两个价值。一是可以重放把同一份 original 和同一批决策重新应用能得到完全一致的输出。二是可审计团队协作时任何人都能看到某处改动是谁在什么时间决定保留或拒绝的。5.4 这块最容易踩的三个坑第一个坑是顺序应用 hunk。前面已经提过需要从后往前应用否则先插入的行会改变后续行号。第二个坑是行尾符不一致。Windows 下文件可能是 CRLFLinux 下是 LF如果规范化时把整行改写diff 可能会把整个文件都标记为变化。处理方式是在生成 diff 前统一转成 LF。第三个坑是模型输出包含 Markdown 代码块。有些模型会在回复里用 包裹 diff直接把这段文本交给解析器会出错。接入方需要在调用模型时要求只输出纯文本 diff或者在解析前剥离代码块标记。注意不要只验证程序能启动。要拿一份有中文标点、有空行、有长段落的真实文稿去测确认 diff 的 hunk 数量和行号定位都符合预期。6. 从命令行到编辑器接入更完整的 review 工作流6.1 命令行批处理与 dry-run命令行原型的价值不只是演示。在批量处理场景里margin-agent 完全可以走“非交互式”流程先生成评审报告再由编辑或审稿人在另一个环节逐块确认。比如可以设计两个命令margin-agent diff --original chapter1.md --rewritten chapter1.rewritten.md --out review.json margin-agent apply --review review.json --output chapter1.final.mddiff 命令只生成评审文件不修改原文apply 命令按照评审文件里的决策输出最终结果。这样就能接入自动化流程也方便在 CI 或内容发布前做一次 dry-run先看看会有哪些改动。dry-run 对生产环境尤其重要。执行 apply 前先用 diff 命令生成一份 hunk 清单人工确认没有大段误改再执行合并。即使某个 hunk 决策错误也可以从评审文件里找到原始范围手动恢复。6.2 在 VS Code 里复现 Cursor 式内联体验命令行工具解决了“可以用”的问题但日常写作体验还需要更顺滑的界面。以 VS Code 为例扩展可以把 margin-agent 包装成“文稿版 Cursor”在编辑器里选中一段文字右键执行“AI 改稿”。模型改写结果通过 margin-agent 生成 hunk。扩展用装饰器或内联提示把 hunk 显示在原文位置。用户通过 CodeLens 或快捷键对每个 hunk 执行 accept、reject、next、prev。最终生成的新文档可以直接替换原文也可以另存为新文件。实现时不需要重新发明编辑器。VS Code 本身提供丰富的 diff 展示、装饰器和命令机制核心工作只是把 margin-agent 的 hunk 映射到编辑器的文本范围上。如果你参考过 open code review 这类扩展会发现它在很多地方都提供了类似思路把 review 数据可视化并让操作走标准的文件修改 API。6.3 团队评审diff 变成可追踪的变更记录当一个人写稿、一个人审稿时diff 的价值已经很突出。当团队协作时diff 的价值会进一步放大。margin-agent 生成的评审记录可以提交到 Git 仓库形成一份和文稿同步的变更报告。场景单人改稿团队发布流程决策方式作者自己逐个确认编辑、校对、责任人分角色审查记录保存本地 JSONL随 Git 提交形成版本记录回滚方式手动恢复原文使用评审记录和 Git 历史双重回滚审查重点语义是否保留事实准确性、风格一致性、涉敏内容在团队场景里margin-agent 输出的 hunk 定位信息非常有用。评审人不需要打开整个文档去猜“这句话在哪里”而是直接看到 old_start 到 old_count 的范围再结合 diff 上下文判断改动是否合理。7. 常见问题排查与生产落地建议7.1 先按这条链路排查问题margin-agent 使用中常见的故障大部分集中在文本规范、行号定位和状态管理上。下面表格按“现象 → 原因 → 检查方式 → 解决方案”给出排查顺序。问题现象常见原因检查方式解决方案diff 应用后文本错乱多个 hunk 按错误顺序应用打印每次应用前后的行号范围从后往前应用 hunk中文文稿被拆出大量无关 diff行尾符或全角空格不一致检查文本文件的行尾符和空格生成 diff 前统一 LF去除行尾空格模型返回全文而不是局部改动改写指令范围过大查看模型输出是否包含大面积重写缩小改写范围要求“只改必要之处”某个 hunk 应用时越界old_count 与实际行数不匹配对比原文行数和 hunk 的 old_end在 apply 前校验行号范围评审记录无法重放记录只存了决策没存原文快照检查 JSONL 是否包含文档版本号记录中保存原文 hash 或版本号相同的 hunk 反复出现context 参数过大导致重复上下文打印解析后的 hunk 列表调整 context 或合并相邻 hunk排查时先确认输入文本是否规范再看 hunk 定位最后检查应用顺序。这个顺序可以覆盖大多数问题。7.2 学习环境和生产环境的配置差异学习环境里跑原型可以直接在 Python 脚本里读文件、输出到终端评审记录可以只保存在内存里。但进入生产环境需要补齐以下部分环境项学习原型生产环境配置硬编码在脚本里外置化通过环境变量或配置中心管理模型调用手动准备改写结果统一封装模型调用带超时、重试和成本统计日志print 输出结构化日志包含 hunk 摘要和决策来源权限本机操作接入方控制命令执行权限防止越权写文件备份无应用 diff 前备份原文档记录原文 hash监控无关注 hunk 数量、拒绝率、应用失败率等指标生产环境里最重要的原则是“可回滚”。margin-agent 的评审机制天然支持按 hunk 回滚但前提是原文档有备份评审记录有保存。没有这两样任何回滚都无从谈起。7.3 落地 margin-agent 前先过一遍检查清单不是所有文本都适合走 AI 改稿加 diff 审查。落地前建议按下面清单确认一次原文是否已经确定还是仍在自由创作阶段草稿阶段更适合直接生成全文审稿阶段才需要 diff。模型输出是否稳定如果模型经常大段重写先设计好提示词避免 hunk 数量爆炸。文本规范是否统一如果没有统一行尾和空格先做规范化。评审记录能否对应到具体版本建议在记录里保存版本号或原文 hash。应用 diff 前是否备份原文档这条必须执行不能省略。是否设置了 dry-run批量任务中先看 diff 再应用能避免大规模误改。这份清单不是一次性 checklist而是每次批量改稿前都应该跑一遍的固定流程。margin-agent 把 diff 审查机制做成了内核但真正保证内容安全的是编辑器、脚本和生产流程里的这些细节。7.4 下一步扩展方向margin-agent 目前的思路以行级 diff 为基础适合处理 Markdown、纯文本和结构化文档。要把它扩展成完整的“文稿版 Cursor”可以从这几个方向入手。一是词级对比增强。在 hunk 内部继续用词级相似度算法高亮具体变化的词组让作者更快定位到修改点。二是结构化文档支持。对 Markdown 的表格、代码块、列表和标题做更细的解析避免 diff 把一块完整结构拆碎。三是与团队 review 管道集成。把 margin-agent 的评审记录发送到内容管理平台或代码评审系统形成跨团队审稿流程。四是引入多模型对比。同一段原文由不同模型改写再把多个版本的 diff 并列展示辅助作者选择更合适的表达。这些方向都不需要改变 margin-agent 的核心建模只需要在它的 hunk 结构之上增加展示层、策略层和集成层。这也是把一个流程抽象成内核的价值所在底层把“改动”这件事建模清晰上层才有空间去生长出各种产品形态。文稿编辑想要真正获得 Cursor 式体验关键不是堆更多 AI 功能而是让每一次 AI 改写都变得可见、可确认、可回滚。margin-agent 把这条链路做成开源内核正是为了让你可以在此基础上搭出一套最适合自己写作和审稿流程的工具。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价