# v0.19.5 Release Notes

> v0.19.4 -> v0.19.5

## Summary

Extends `read_file` with CSV/TSV dispatch, disables its `alreadyCall` cache to stop stale post-edit reads, and splits the file / error-memory toolset into dedicated `fileReader` / `fileWriter` / `errorMemory` packages under `internal/filesystem/`.
<details>
<summary>翻譯</summary>
`read_file` 以副檔名分派擴充 CSV／TSV、關掉 `alreadyCall` 快取以免 post-edit 讀到舊內容，並將 file／error-memory 相關實作拆入 `internal/filesystem/` 下的 `fileReader`／`fileWriter`／`errorMemory` 專屬套件。
</details>

## Changes

### UPDATE
- Extend `read_file` with CSV/TSV dispatch in `readFileHandler` (`.csv`/`.tsv` → `readCSVHandler`). Uses `encoding/csv` with `LazyQuotes=true` + `FieldsPerRecord=-1` for dirty input, strips UTF-8 BOM, emits a JSON 2D array (`[][]string`) so column order survives (`map`-based marshaling would sort keys alphabetically). `offset`/`limit` apply to data rows; header is always returned. No new tool — dispatch keeps LLM tool count unchanged since only tool name is visible on the first stub call.
- Harden `read_file`/`read_image`/`patch_edit`/`write_file` handlers: resolve path defaults via the shared `AbsPath` contract, detect binary headers before text reads, cap text reads at `maxReadSize=1MB`, and redirect image extensions to `read_image` with an explicit error message instead of silently falling through.

<details>
<summary>翻譯</summary>

- `read_file` 以 `readFileHandler` 副檔名分派擴充 CSV／TSV（`.csv`／`.tsv` → `readCSVHandler`）。使用 `encoding/csv` 搭配 `LazyQuotes=true` + `FieldsPerRecord=-1` 容忍髒資料、剝除 UTF-8 BOM，輸出 JSON 2D 陣列（`[][]string`）保留原始欄位順序（`map` 版 marshal 會字母序排序破壞順序）。`offset`／`limit` 作用於資料列，header 永遠回傳。不新增 tool —— 分派的原因是 LLM 首次 stub 呼叫只看得到 tool name，tool 數量越少越好。
- 加固 `read_file`／`read_image`／`patch_edit`／`write_file` handler：路徑預設走共用 `AbsPath` 契約、text 讀取前偵測 binary header、text 讀取上限 `maxReadSize=1MB`、image 副檔名直接以顯式錯誤導向 `read_image` 而非靜默落入文字路徑。

</details>

### FIX
- Disable `alreadyCall` cache for `read_file` in `internal/agents/exec/toolCall.go` (Pass 1 lookup and Pass 3 store both skip `toolName == "read_file"`). Previously, post-`patch_edit` verification reads with identical args hit cached pre-edit content and skipped `runToolExec` entirely, which suppressed the `EventToolCall` event and looked like the model hallucinating "verify read is still old content." `read_file` semantics are "current disk state" — it must never cache.
- Correct `needExclude` flag plumbing in file-write tools so `.doc/vX.Y.Z.md` writes are not blocked by `.gitignore` membership; exclusion is a listing/walking filter, not a write gate (write denials stay with `isDenied` + `denied_map.json`).

<details>
<summary>翻譯</summary>

- 於 `internal/agents/exec/toolCall.go` 關掉 `read_file` 的 `alreadyCall` 快取（Pass 1 lookup／Pass 3 store 皆以 `toolName == "read_file"` 跳過）。舊行為：`patch_edit` 後以相同 args 回讀驗證，Pass 1 會命中 pre-edit 舊內容並完全跳過 `runToolExec`，連 `EventToolCall` 都不發，表面像是模型幻覺「驗證讀回仍是舊內容」。`read_file` 語意是「當下 disk state」，永遠不該快取。
- 修正 file-write tool 的 `needExclude` 旗標傳遞，`.doc/vX.Y.Z.md` 不再因 `.gitignore` 成員資格被擋；exclusion 僅是 listing／walking 的過濾器，不是寫入 gate（寫入拒絕由 `isDenied` + `denied_map.json` 處理）。

</details>

### REFACTOR
- Extract file reading helpers into `internal/filesystem/fileReader/` (`file.go`, `csv.go`, `pdf.go`, `image.go`, `listFiles.go`, `globFiles.go`, `searchFiles.go`) and file writing into `internal/filesystem/fileWriter/` (`write.go`, `patch.go`). `internal/tools/file/*` tools collapse to thin registration/handler wrappers that delegate to these helpers; shared read/write logic is no longer duplicated between tool entry points and the filesystem layer.
- Split error-memory out of `internal/tools/file/errorMemory.go` into `internal/filesystem/errorMemory/` (`save.go`, `search.go`) and a dedicated `internal/tools/errorMemory/` tool package (`register.go`, `rememberError.go`, `searchErrorMemory.go`, `readToolError.go`). Move `toolError` package from `internal/tools/` into `internal/filesystem/errorMemory/toolError/` so storage-layer ownership matches the file-system module.
- Rename `internal/filesystem/store/` → `internal/filesystem/torii/` to reflect the ToriiDB wrapper role.
- Rename registry entries `search_history` → `search_conversation_history` and `search_content` → `search_file_content`. Stub tool first-call short-circuit means LLM sees only the name on round one — `search_history` collided semantically with git/shell history, so the tool name now carries the disambiguation instead of leaning on description.
- Unify tool registration for file tools in `internal/tools/file/register.go` and align APIs across `read_file`, `read_image`, `list_files`, `glob_files`, `search_files`, `search_file_content`, `write_file`, `patch_edit`.

<details>
<summary>翻譯</summary>

- 將檔案讀取 helper 抽出至 `internal/filesystem/fileReader/`（`file.go`、`csv.go`、`pdf.go`、`image.go`、`listFiles.go`、`globFiles.go`、`searchFiles.go`），檔案寫入抽出至 `internal/filesystem/fileWriter/`（`write.go`、`patch.go`）。`internal/tools/file/*` 收斂為薄的註冊／handler 殼層委派給這些 helper；共用的讀寫邏輯不再在 tool 入口與 filesystem 層之間重複。
- 將 error-memory 從 `internal/tools/file/errorMemory.go` 拆出至 `internal/filesystem/errorMemory/`（`save.go`、`search.go`）與獨立的 `internal/tools/errorMemory/` tool package（`register.go`、`rememberError.go`、`searchErrorMemory.go`、`readToolError.go`）。`toolError` package 從 `internal/tools/` 搬至 `internal/filesystem/errorMemory/toolError/`，儲存層歸屬與 filesystem 模組對齊。
- `internal/filesystem/store/` 更名為 `internal/filesystem/torii/`，反映 ToriiDB wrapper 定位。
- 註冊名 `search_history` → `search_conversation_history`、`search_content` → `search_file_content`。Stub tool 首呼叫短路機制意味著 LLM 第一輪只看得到 name，`search_history` 與 git／shell history 語意衝突，語意辨識從 description 上移至 tool name 本身。
- 統一 `internal/tools/file/register.go` 中 file tool 的註冊路徑，對齊 `read_file`、`read_image`、`list_files`、`glob_files`、`search_files`、`search_file_content`、`write_file`、`patch_edit` 的 API。

</details>

***

## Files Changed

| File | Status | Tag |
|------|--------|-----|
| `internal/filesystem/fileReader/file.go` | Added | REFACTOR |
| `internal/filesystem/fileReader/csv.go` | Added | UPDATE |
| `internal/filesystem/fileReader/pdf.go` | Added (renamed from `internal/tools/file/readPDF.go`) | REFACTOR |
| `internal/filesystem/fileReader/image.go` | Added | REFACTOR |
| `internal/filesystem/fileReader/listFiles.go` | Added | REFACTOR |
| `internal/filesystem/fileReader/globFiles.go` | Added | REFACTOR |
| `internal/filesystem/fileReader/searchFiles.go` | Added | REFACTOR |
| `internal/filesystem/fileWriter/write.go` | Added | REFACTOR |
| `internal/filesystem/fileWriter/patch.go` | Added | REFACTOR |
| `internal/filesystem/errorMemory/save.go` | Added | REFACTOR |
| `internal/filesystem/errorMemory/search.go` | Added | REFACTOR |
| `internal/filesystem/errorMemory/toolError/toolError.go` | Added (moved) | REFACTOR |
| `internal/filesystem/torii/torii.go` | Added (renamed from `store/store.go`) | REFACTOR |
| `internal/tools/errorMemory/register.go` | Added | REFACTOR |
| `internal/tools/errorMemory/rememberError.go` | Added | REFACTOR |
| `internal/tools/errorMemory/searchErrorMemory.go` | Added | REFACTOR |
| `internal/tools/errorMemory/readToolError.go` | Added | REFACTOR |
| `internal/tools/file/searchFiles.go` | Added | REFACTOR |
| `internal/tools/file/errorMemory.go` | Deleted | REFACTOR |
| `internal/tools/file/readImage.go` | Deleted (moved to `fileReader/image.go`) | REFACTOR |
| `internal/tools/file/searchContent.go` | Deleted (renamed to `search_file_content`) | REFACTOR |
| `internal/tools/file/readFile.go` | Modified | UPDATE / FIX |
| `internal/tools/file/patchEdit.go` | Modified | FIX |
| `internal/tools/file/writeFile.go` | Modified | FIX |
| `internal/tools/file/listFiles.go` | Modified | REFACTOR |
| `internal/tools/file/globFiles.go` | Modified | REFACTOR |
| `internal/tools/file/register.go` | Modified | REFACTOR |
| `internal/tools/register.go` | Modified | REFACTOR |
| `internal/tools/searchConversationHistory.go` | Added (renamed from `searchHistory.go`) | REFACTOR |
| `internal/agents/exec/toolCall.go` | Modified | FIX |
| `internal/agents/exec/execute.go` | Modified | REFACTOR |
| `internal/filesystem/absPath.go` | Modified | FIX |
| `internal/tools/fetchPage/fetchPage.go` | Modified | REFACTOR |
| `internal/tools/fetchPage/skipped.go` | Modified | REFACTOR |
| `internal/tools/external/googleRSS/fetch.go` | Modified | REFACTOR |
| `internal/tools/external/searchWeb/fetch.go` | Modified | REFACTOR |
| `internal/tools/external/yahooFinance/fetch.go` | Modified | REFACTOR |
| `internal/tools/runCommand.go` | Modified | REFACTOR |
| `internal/utils/utils.go` | Modified | REFACTOR |
| `cmd/app/main.go` | Modified | REFACTOR |
| `configs/prompts/system_prompt.md` | Modified | DOC |
| `configs/prompts/discord_system_prompt.md` | Modified | DOC |
| `configs/prompts/skill_execution.md` | Modified | DOC |
| `README.md` | Modified | DOC |
| `doc/README.zh.md` | Modified | DOC |
| `doc/architecture.md` | Modified | DOC |
| `doc/architecture.zh.md` | Modified | DOC |
| `doc/doc.md` | Modified | DOC |
| `doc/doc.zh.md` | Modified | DOC |
| `extensions/skills/project-agenvoy/SKILL.md` | Deleted | REMOVE |

***

Generated by [SKILL](https://github.com/pardnchiu/skill-version-generate)
