巡检发现:
- 2196c77 workflow 整文件替换回退破坏(AiChat+Ideas 12项功能)
- B-260615-03 truncated 标志已落地
- AR-8-scroll scrollToBottom smooth 已补
- CR-260615-09 .ai-md 残余:4详情页各21处 scoped .ai-md
(全局 ai-md.css 75行已建,旧副本待清理但非阻塞)
190 lines
5.9 KiB
Markdown
190 lines
5.9 KiB
Markdown
# AI 文件操作工具能力手册
|
||
|
||
> 最后更新:2026-06-15 | 基于全量测试验证
|
||
|
||
---
|
||
|
||
## 工具总览
|
||
|
||
| 工具 | 用途 | 可靠性 |
|
||
|------|------|--------|
|
||
| `read_file` | 读取文件内容(全文/分页) | ✅ 高 |
|
||
| `write_file` | 创建/覆盖写入文件(纯文本) | ✅ 高 |
|
||
| `list_directory` | 列出目录内容(含递归/深度控制) | ✅ 高 |
|
||
| `run_command` | 执行 shell 命令 | ⚠️ 可执行,但 stdout 不可用 |
|
||
|
||
---
|
||
|
||
## read_file
|
||
|
||
读取文件内容,支持分页。
|
||
|
||
### 参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `path` | string | ✅ | 文件路径,支持 `/` 和 `\` |
|
||
| `offset` | number | ❌ | 起始行(0 基索引),默认 0 |
|
||
| `limit` | number | ❌ | 读取行数,默认全部 |
|
||
|
||
### 行为规则
|
||
|
||
- `offset` 是 **0 基索引**:offset=0 → 第 1 行,offset=10 → 第 11 行
|
||
- `offset` 超出总行数 → 返回空内容,**不报错**
|
||
- `limit` 超出剩余行数 → 返回到末尾,**不报错**
|
||
- 空文件 → 返回 `{ content: "", lines: 0, size: 0 }`
|
||
- 不存在的文件 → 报错 `os error 2`
|
||
- 二进制文件 → 返回 `{ binary: true, content: null, error: "文件非 UTF-8 文本" }`
|
||
- 路径越界(项目目录外)→ 被拦截
|
||
|
||
### 返回结构
|
||
|
||
```json
|
||
{
|
||
"content": "文件文本内容",
|
||
"lines": 30, // 总行数(始终是全量值,非当前页行数)
|
||
"size": 145, // 总字节数(始终是全量值)
|
||
"path": "..."
|
||
}
|
||
```
|
||
|
||
> ⚠️ `lines` 和 `size` 始终返回**全量值**,不受 offset/limit 影响。
|
||
|
||
---
|
||
|
||
## write_file
|
||
|
||
创建或覆盖写入文件,纯文本模式。
|
||
|
||
### 参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `path` | string | ✅ | 文件路径 |
|
||
| `content` | string | ✅ | 文本内容(UTF-8) |
|
||
|
||
### 行为规则
|
||
|
||
- **自动创建多级父目录**:路径中不存在的目录会自动创建
|
||
- **覆盖已有文件**:直接覆盖,无确认机制(⚠️ 注意安全)
|
||
- 返回 `old_size`(覆盖前大小,新建时为 null)和 `bytes_written`(写入大小)
|
||
- 支持 emoji、引号、反斜杠、中文等特殊字符
|
||
- 路径分隔符 `/` 和 `\` 均可
|
||
- 中文路径/文件名含空格 → 正常工作
|
||
- 空内容(`content=""`)→ 创建 0 字节文件
|
||
- **无法写入二进制数据**(NULL 字节等会被当文本处理)
|
||
- 路径越界(项目目录外)→ 被拦截
|
||
|
||
### 局部修改的正确做法
|
||
|
||
write_file 是全量覆盖,局部修改需三步:
|
||
|
||
```
|
||
1. read_file 获取完整内容
|
||
2. AI 在内存中替换目标行/文本
|
||
3. write_file 写回完整内容
|
||
```
|
||
|
||
---
|
||
|
||
## list_directory
|
||
|
||
列出目录内容,支持递归和深度控制。
|
||
|
||
### 参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `path` | string | ✅ | 目录路径 |
|
||
| `recursive` | boolean | ❌ | 是否递归,默认 false |
|
||
| `max_depth` | number | ❌ | 递归最大深度(配合 recursive) |
|
||
| `skip_noise_dirs` | boolean | ❌ | 跳过 node_modules/.git 等,默认 false |
|
||
|
||
### 返回结构
|
||
|
||
```json
|
||
{
|
||
"entries": [
|
||
{ "name": "src", "type": "directory", "size": 0, "depth": 0 },
|
||
{ "name": "main.ts", "type": "file", "size": 466, "depth": 0 }
|
||
],
|
||
"truncated": false
|
||
}
|
||
```
|
||
|
||
### 行为规则
|
||
|
||
- `type` 取值:`"directory"` | `"file"`
|
||
- `depth`:0 = 根层级,1 = 一级子目录,以此类推
|
||
- 不存在的目录 → 报错 `os error 3`
|
||
- `truncated: false` 表示结果完整未截断
|
||
|
||
---
|
||
|
||
## run_command
|
||
|
||
执行 shell 命令。
|
||
|
||
### 参数
|
||
|
||
| 参数 | 类型 | 必填 | 说明 |
|
||
|------|------|------|------|
|
||
| `command` | string | ✅ | shell 命令(非交互式) |
|
||
| `working_dir` | string | ❌ | 工作目录 |
|
||
| `timeout_secs` | number | ❌ | 超时秒数,默认 60 |
|
||
|
||
### ⚠️ 已知问题
|
||
|
||
**stdout 始终返回空字符串**(已确认是普遍问题):
|
||
- `echo`、`Write-Output` 等输出无法被捕获
|
||
- 命令本身**能正常执行**(cp/mv/rm/重定向写文件均验证通过)
|
||
- stderr 大部分场景也为空
|
||
|
||
### 可靠使用的场景
|
||
|
||
| 场景 | 可靠性 | 示例 |
|
||
|------|--------|------|
|
||
| 删除文件 `rm` | ✅ | `rm -f path/to/file` |
|
||
| 复制文件 `cp` | ✅ | `cp src.txt dst.txt` |
|
||
| 移动/重命名 `mv` | ✅ | `mv old.txt new.txt` |
|
||
| 创建目录 `mkdir` | ✅ | `mkdir -p deep/nested/dir` |
|
||
| 写入文件(重定向) | ✅ | `echo content > file.txt` |
|
||
| 二进制写入 `printf` | ✅ | `printf '\x89PNG' > file.png` |
|
||
| 超时控制 | ✅ | `timeout_secs=3` 正确中断 |
|
||
| 工作目录切换 | ✅ | `working_dir` 生效,相对路径可用 |
|
||
| 获取命令输出 | ❌ | stdout/stderr 不可用 |
|
||
|
||
---
|
||
|
||
## 快速参考:常见操作怎么做
|
||
|
||
| 我想要... | 工具调用 |
|
||
|-----------|---------|
|
||
| 读文件全文 | `read_file(path)` |
|
||
| 读第 10~15 行 | `read_file(path, offset=9, limit=6)` |
|
||
| 创建新文件 | `write_file(path, content)` |
|
||
| 修改文件中某几行 | `read_file` → AI 替换 → `write_file` |
|
||
| 追加内容到文件末尾 | `read_file` → 拼接 → `write_file` |
|
||
| 删除文件 | `run_command("rm -f path")` |
|
||
| 重命名文件 | `run_command("mv old new")` |
|
||
| 列出项目结构 | `list_directory(path, recursive=true, max_depth=3)` |
|
||
| 搜索文件内容 | 分页 `read_file` 逐段扫描(无原生搜索) |
|
||
| 搜索文件名 | `list_directory` 递归 + AI 过滤(无原生 glob) |
|
||
| 写入二进制文件 | `run_command("printf '\x89...' > file")` |
|
||
| 获取文件大小/行数 | `read_file`(必须读内容,无轻量元信息工具) |
|
||
|
||
---
|
||
|
||
## 待实现能力(已建任务)
|
||
|
||
| 能力 | 任务 ID | 优先级 |
|
||
|------|---------|--------|
|
||
| 文件内容搜索 `search_in_file` | F-FILE-01 | P1 |
|
||
| 文件局部更新 `patch_file` | F-FILE-02 | P1 |
|
||
| 文件元信息 `file_info` | F-FILE-03 | P1 |
|
||
| run_command stdout 修复 | F-FILE-07 | P1 |
|
||
| 追加写入 `append_file` | F-FILE-04 | P2 |
|
||
| 文件名搜索 `search_files` | F-FILE-05 | P2 |
|
||
| Base64 二进制写入 | F-FILE-06 | P2 |
|
||
| 文件差异对比 `diff_file` | F-FILE-08 | P3 |
|