docs: 巡检简报+todo 回写(2026-06-15 第2轮)

巡检发现:
- 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行已建,旧副本待清理但非阻塞)
This commit is contained in:
2026-06-15 17:23:57 +08:00
parent 672d677046
commit f30df333b3
17 changed files with 2184 additions and 15 deletions

189
docs/ai-file-ops-manual.md Normal file
View File

@@ -0,0 +1,189 @@
# 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 |