Lzh on GitHub

apply_diff

掌握 `apply_diff` 工具,使用模糊匹配和行提示在 Roo Code 中进行精确的代码更改,并支持多文件。

apply_diff 工具通过精确指定要替换的内容,对文件进行精确、细致的更改。它采用一种复杂的策略来查找和应用更改,同时保持适当的代码格式和结构。

参数

该工具接受以下参数:

  • path (必需):要修改的文件的路径,相对于当前工作目录。
  • diff (必需):定义更改的搜索/替换块,使用特定于活动 diff 策略的格式。
  • start_line (可选):搜索内容开始位置的提示。注意:此顶级参数未被当前主要策略使用,该策略依赖于 diff 内容中的 :start_line:
  • end_line (可选):搜索内容结束位置的提示。注意:此顶级参数未被当前主要策略使用。

功能

此工具使用模糊匹配,通过行号提示来精确查找和替换内容,从而对现有文件应用有针对性的更改。与简单的搜索和替换不同,它根据提供的内容和位置提示来识别要替换的精确块。

使用时机

  • 当 Roo 需要对现有代码进行精确更改而无需重写整个文件时。
  • 在重构特定代码部分时保持周围上下文。
  • 在以细致的精度修复现有代码中的错误时。
  • 在实施仅修改文件某些部分的特性增强时。

主要功能

  • 使用由 :start_line: 提示引导的模糊匹配(归一化字符串的 Levenshtein 距离),具有可配置的置信度阈值(通常为 0.8-1.0)。
  • 使用 BUFFER_LINES(默认 40)提供匹配周围的上下文。
  • 在提示的起始行周围的可配置上下文窗口(bufferLines)内执行由内而外的搜索。
  • 通过替换精确块来被动地保留代码格式和缩进。
  • 在应用前以 diff 视图显示更改供用户审查和编辑。
  • 跟踪每个文件的连续错误(consecutiveMistakeCountForApplyDiff)以防止重复失败。
  • 根据 .rooignore 规则验证文件访问。
  • 有效处理多行编辑。

局限性

  • 最适合使用独特、有特色的代码部分以进行可靠识别。
  • 对于非常大的文件或高度重复的代码模式,性能可能会有所不同。
  • 如果内容含糊不清,模糊匹配有时可能会选择不正确的位置。
  • 每个 diff 策略都有特定的格式要求。
  • 复杂的编辑可能需要仔细选择策略或手动审查。

工作原理

调用 apply_diff 工具时,它遵循此过程:

  1. 参数验证:验证必需的 pathdiff 参数。
  2. RooIgnore 检查:验证目标文件路径是否被 .rooignore 规则允许。
  3. 文件分析:加载目标文件内容。
  4. 匹配查找:使用模糊匹配算法(归一化字符串的 Levenshtein 距离),由上下文窗口(BUFFER_LINES)内的 :start_line: 提示引导,由内而外搜索以根据置信度阈值定位目标内容。
  5. 变更准备:通过替换已识别的块来生成建议的更改。
  6. 用户交互
  • 在 diff 视图中显示更改。
  • 允许用户审查并可能编辑建议的更改。
  • 等待用户批准或拒绝。
  1. 变更应用:如果获得批准,则将更改(可能包括用户编辑)应用到文件。
  2. 错误处理:如果发生错误(例如,匹配失败、部分应用),则增加该文件的 consecutiveMistakeCountForApplyDiff 并报告失败类型。
  3. 反馈:返回结果,包括任何用户反馈或错误详细信息。

Diff 格式要求

<diff> 参数需要一种特定格式,支持在单个请求中进行一个或多个更改。每个更改块都需要一个原始内容的行号提示。

  • 要求SEARCH 块内容需要精确匹配(在模糊阈值内),包括空格和缩进。每个块内的 :start_line: 行号提示是强制性的。:end_line: 提示是可选的(但解析器支持)。文件内容中像 <<<<<<< 这样的标记必须在 SEARCH 块中进行转义(\\)。

<diff> 块的示例格式:

<<<<<<< SEARCH
:start_line:10
:end_line:12
-------
    // Old calculation logic
    const result = value * 0.9;
    return result;
=======
    // Updated calculation logic with logging
    console.log(`Calculating for value: ${value}`);
    const result = value * 0.95; // Adjusted factor
    return result;
>>>>>>> REPLACE

<<<<<<< SEARCH
:start_line:25
:end_line:25
-------
    const defaultTimeout = 5000;
=======
    const defaultTimeout = 10000; // Increased timeout
>>>>>>> REPLACE

实验性:多文件编辑 (MULTI_FILE_APPLY_DIFF)

apply_diff 的一个实验性版本允许在单个工具调用中对多个文件应用更改。此功能通过 MULTI_FILE_APPLY_DIFF 实验标志激活。

实验模式的主要功能

  • 多文件操作:在一个请求中编辑多个文件,简化复杂的重构任务。
  • 批量审批 UI:当目标为多个文件时,会出现一个单一的 UI,供用户一次性批准或拒绝所有更改,或单独管理每个文件的权限。
  • 新的 XML 格式:引入了一种使用 <args><file> 标签的新、更结构化的 XML 格式来处理多个操作。
  • 向后兼容性:实验性工具仍与旧版单文件 pathdiff 参数格式兼容。

工作原理(实验性)

  1. 实验检查:工具首先检查是否启用了 MULTI_FILE_APPLY_DIFF 实验。如果未启用,则回退到旧版的 apply_diff 实现。
  2. 参数解析:它解析新的 <args> XML 格式以识别所有目标文件及其相应的 diff 操作。它还可以处理旧版的 path/diff 参数。
  3. 验证和审批
  • 验证所有目标文件是否存在且可访问(未被 .rooignore 阻止)。
  • 如果正在修改多个文件,则向用户显示一个批量审批对话框。
  1. Diff 应用:对于每个已批准的文件,它使用 MultiFileSearchReplaceDiffStrategy 应用指定的 diff。此策略可以对单个文件应用多个、不重叠的更改。
  2. 结果:它返回一个整合的结果消息,总结所有尝试的操作的结果。

新的 Diff 格式(实验性)

实验模式在 <apply_diff> 工具调用中使用新的 XML 结构。

  • <args>:所有文件操作的容器。
  • <file>:每个要修改的文件的块。包含 <path> 和一个或多个 <diff> 标签。
  • <path>:文件的相对路径。
  • <diff>:包含更改的块。
    • <content>SEARCH/REPLACE 块。
    • <start_line>:(可选) 行号提示。

示例:在一个调用中修改两个文件

<apply_diff>
  <args>
    <file>
      <path>src/services/auth.service.ts</path>
      <diff>
        <content>
          <<<<<<< SEARCH
                  :start_line:50
          -------
          const token_expiration = '15m';
          >>>>>>> REPLACE
        </content>
      </diff>
    </file>
    <file>
      <path>src/config/auth.config.ts</path>
      <diff>
        <content>
          <<<<<<< SEARCH
                  :start_line:12
          -------
          rateLimit: 5,
          =======
          rateLimit: 10,
          >>>>>>> REPLACE
        </content>
      </diff>
    </file>
  </args>
</apply_diff>