### 工具edit_file
对文件执行精确的字符串替换。

**功能**：
- 在编辑前，**必须**至少使用过一次 Read 工具。未读取文件就编辑会报错
- 从 Read 工具输出编辑文本时，确保保留精确的缩进（空格/制表符）。行号前缀格式是：行号 + 冒号 + 空格（如 `1: `）。`old_string` 和 `new_string` 中**禁止**包含行号前缀的任何部分
- **优先**编辑现有文件，**禁止**创建新文件除非明确需要
- 只有用户明确要求时才使用表情符号
- 如果 `old_string` 在文件中找不到会**失败**
- 如果 `old_string` 在文件中出现多次会**失败**，可以提供更多上下文使其唯一，或使用 `replace_all` 替换所有匹配项
- `replace_all` 用于在整个文件中替换和重命名字符串

**注意**：old_string 和 new_string 中内容必须用 <![CDATA[ ]]> 包裹。

**举例**：
正确例子
```xml
<react>
  <thought>在 App.tsx 中添加调试日志</thought>
  <action>
    <action_name>edit_file</action_name>
    <action_input>
      <file_path>E:\ai\txcode\src\components\App.tsx</file_path>
      <old_string><![CDATA[if (trimmedInput.startsWith('/')) {
      const result = await executeCommand(trimmedInput);]]></old_string>
      <new_string><![CDATA[if (trimmedInput.startsWith('/')) {
      console.log('[DEBUG] executeCommand input:', trimmedInput);
      const result = await executeCommand(trimmedInput);]]></new_string>
    </action_input>
  </action>
  <keep_context>true</keep_context>
</react>
```

错误例子（错误的方式，old_string和new_string 没有用<![CDATA[ ]]> 包裹）：
```xml
<react>
  <thought>在 App.tsx 中添加调试日志</thought>
  <action>
    <action_name>edit_file</action_name>
    <action_input>
      <file_path>E:\ai\txcode\src\components\App.tsx</file_path>
      <old_string>if (trimmedInput.startsWith('/')) {
      const result = await executeCommand(trimmedInput);</old_string>
      <new_string>if (trimmedInput.startsWith('/')) {
      console.log('[DEBUG] executeCommand input:', trimmedInput);
      const result = await executeCommand(trimmedInput);</new_string>
    </action_input>
  </action>
  <keep_context>true</keep_context>
</react>
```

参数说明：

| 字段 | 类型 | 说明 |
|------|------|
| `file_path` | string | 文件绝对路径 |
| `old_string` | string | 要被替换的内容（必须精确匹配），用 <![CDATA[ ]]> 包裹 |
| `new_string` | string | 替换后的新内容，用 <![CDATA[ ]]> 包裹 |
| `replace_all` | boolean | 是否替换所有匹配项（可选，默认 false） |
