# v0.28.18 Release Notes

> v0.28.17 -> v0.28.18

## Summary

Expands file patching into multi-target edits with line-level inserts and clearer TUI previews. Group chats now retain unmentioned messages so later turns keep ambient context.

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

擴充檔案修補為多目標編輯，支援行級插入並改善預覽。群組聊天會保留未提及的訊息，讓後續對話保有環境脈絡。

</details>

## ⚠️ Breaking Changes

### `patch_file` parameter schema replaced with multi-target edits

Top-level `old_string` / `new_string` / `replace_all` are gone. Callers must pass a `targets` array; each target is either a replace (`old_string` / `new_string`[, `replace_all`][, `row`]) or a pure insert (`insert_string` / `row`).

**Before:**
```json
{
  "path": "/abs/path/foo.go",
  "old_string": "exact text",
  "new_string": "replacement",
  "replace_all": false
}
```

**After:**
```json
{
  "path": "/abs/path/foo.go",
  "targets": [
    {
      "old_string": "exact text",
      "new_string": "replacement"
    },
    {
      "insert_string": "new independent line(s)",
      "row": 12
    }
  ]
}
```

**Migration:**
```go
// Old single-edit call
{"path": p, "old_string": old, "new_string": neu}

// New multi-target call
{"path": p, "targets": [{"old_string": old, "new_string": neu}]}

// Optional: pin an occurrence by 1-based row, or insert without replacing
{"path": p, "targets": [
  {"old_string": old, "new_string": neu, "row": 42},
  {"insert_string": "line to insert", "row": 10}
]}
```

Row-bearing targets apply highest-row-first so original line numbers stay valid; remaining targets then apply top to bottom. `insert_string` cannot combine with `old_string` / `new_string`.

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

`patch_file` 改為 `targets` 陣列：每筆目標可為取代（`old_string` / `new_string`）或純插入（`insert_string` / `row`）。舊的頂層參數需改包進 `targets`。有 `row` 的目標由高到低套用，其餘再由上到下。

</details>

### `FormatPatchDiff` returns hunk slices instead of two line slices

Diff formatting now models multi-target patches as ordered hunks so TUI previews can render each edit separately.

**Before:**
```go
func FormatPatchDiff(raw string) (oldLines, newLines []string)
```

**After:**
```go
type PatchHunk struct {
	OldLines []string
	NewLines []string
}

func FormatPatchDiff(raw string) []PatchHunk
```

**Migration:**
```go
// Old
oldLines, newLines := utils.FormatPatchDiff(args)

// New
hunks := utils.FormatPatchDiff(args)
for _, h := range hunks {
	// h.OldLines / h.NewLines
}
```

Legacy single-edit JSON (`old_string` / `new_string` only) still parses into one hunk for backward-compatible preview of old payloads.

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

`FormatPatchDiff` 改回傳 `[]PatchHunk`，以支援多目標預覽。呼叫端需改走 hunk 迴圈；僅含舊參數的 payload 仍會落成單一 hunk。

</details>

## Changes

### FEAT
- Record unmentioned group chat messages into session history (@pardnchiu) [2ddafb8]

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

- 將群組中未提及機器人的訊息寫入 session history

</details>

### BREAKING
- Expand `patch_file` for multi-target edits, row-scoped replace, and pure insert (@pardnchiu) [e1f850a]
- Return multi-hunk patch previews from `FormatPatchDiff` and restyle TUI diff blocks (@pardnchiu) [e1f850a]

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

- 擴充 `patch_file` 支援多目標編輯、依行號取代與純插入
- `FormatPatchDiff` 改回傳多 hunk，並重做 TUI 差異預覽樣式

</details>

### UPDATE
- Truncate nested `targets` string fields in tool-call arg previews (@pardnchiu) [e1f850a]
- Pad TUI patch/write diff lines to terminal width with background styles (@pardnchiu) [e1f850a]

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

- 工具呼叫參數預覽會截斷巢狀 `targets` 字串欄位
- TUI 差異列依終端寬度補齊並套用背景色

</details>

### DOC
- Document cost-effective model setup recommendations in bilingual READMEs (@pardnchiu) [e1f850a]
- Update skill tool-mapping examples for the new `patch_file` schema (@pardnchiu) [e1f850a]

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

- 於雙語 README 新增省錢模型配置建議
- 更新 skill 工具對照範例以符合新的 `patch_file` schema

</details>

## Scope

- `internal/tools/file/` — BREAKING (`patchFile.go`)
- `internal/utils/` — BREAKING, UPDATE (`utils.go`)
- `internal/runtime/tui/` — UPDATE (`handlerPopup.go`, `view.go`, `viewRender.go`)
- `internal/agents/exec/` — UPDATE (`toolCall.go`)
- `internal/runtime/telegram/`, `internal/runtime/discord/` — FEAT (`run.go`)
- `README.md`, `doc/README.zh.md`, `configs/prompts/` — DOC

***

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