# v0.5.0 Release Notes

> v0.4.5 -> v0.5.0

## Summary

Add semantic vector search backed by OpenAI embeddings. Vectors are inlined on each `Entry`, persisted through AOF, and queried via new `VSEARCH` / `VSIM` / `VGET` commands; a content-addressed embedding cache under `__torii:embed:*` de-duplicates API calls across identical texts.
<details>
<summary>翻譯</summary>
新增以 OpenAI embedding 為後端的語意向量搜尋。向量內嵌於每筆 `Entry`，透過 AOF 持久化，並經由新指令 `VSEARCH` / `VSIM` / `VGET` 查詢；以內容雜湊為 key 的 `__torii:embed:*` 快取可跨相同文字去重 API 呼叫。
</details>

## Changes

### FEAT
- Add `core/openai` package — standalone `text-embedding-3-small` client with `Client.Dim` / `Client.Model` accessors, singleton initialization, and `.env` loading via `godotenv`
- Add `Entry.Vector []float32` field with base64 little-endian float32 codec (`core/store/vector.go`); `AOFRecord.Vector *string` is replayed and re-emitted during compaction for lossless restart
- Add embedding cache under `__torii:embed:<sha256(model|dim|text)>` (`core/store/vcache.go`); `d != currentDim` is treated as MISS, and `KEYS` / `FIND` / `QUERY` / `VSEARCH` skip the `__torii:*` namespace so internal keys never leak
- Add `SET <key> <value> [NX|XX] [<seconds>] VECTOR` — main key writes synchronously, a background goroutine attaches the embedding, and `Store.Close()` joins `sync.WaitGroup` before compacting AOF
- Add `VSEARCH <text> [MATCH <pattern>] [LIMIT <n>]` — top-K cosine similarity via linear scan + min-heap (default `k = 10`), with glob-based key filtering; query vector goes through the embedding cache so cache HIT avoids the API
- Add `VSIM <key1> <key2>` — cosine similarity between two stored vectors, `(nil)` on any missing vector, explicit dim-mismatch error
- Add `VGET <key>` — returns the stored vector as a JSON array (debug helper), returns a defensive copy to prevent callers from mutating `Entry.Vector`

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

- 新增 `core/openai` 套件 — 獨立的 `text-embedding-3-small` client，提供 `Client.Dim` / `Client.Model` 存取器、singleton 初始化，並透過 `godotenv` 載入 `.env`
- 新增 `Entry.Vector []float32` 欄位搭配 base64 little-endian float32 編解碼（`core/store/vector.go`）；`AOFRecord.Vector *string` 會在 replay 與 compact 時還原／重新寫回，確保重啟無損
- 新增 `__torii:embed:<sha256(model|dim|text)>` 的 embedding 快取（`core/store/vcache.go`）；`d != currentDim` 視為 MISS，`KEYS` / `FIND` / `QUERY` / `VSEARCH` 全面跳過 `__torii:*` 前綴，內部 key 不會外露
- 新增 `SET <key> <value> [NX|XX] [<seconds>] VECTOR` — 主 key 同步寫入、背景 goroutine 補 embedding，`Store.Close()` 以 `sync.WaitGroup` 等待排空後再做 AOF compaction
- 新增 `VSEARCH <text> [MATCH <pattern>] [LIMIT <n>]` — 線性掃描 + min-heap 的 top-K cosine 相似度查詢（預設 `k = 10`），支援 glob key 過濾；查詢向量走 embedding 快取，HIT 時不打 API
- 新增 `VSIM <key1> <key2>` — 回傳兩個 key 的向量 cosine 相似度，任一缺向量回 `(nil)`，維度不符給明確錯誤訊息
- 新增 `VGET <key>` — 以 JSON 陣列輸出 stored vector（除錯用），回傳深拷貝避免外部修改汙染 `Entry.Vector`

</details>

### UPDATE
- Plain `Set()` now clears `Entry.Vector` on overwrite — a key re-set without the `VECTOR` flag drops the stale embedding since the underlying text has changed
- Extend AOF with `addToAOFWithVector` / `writeAOF` shared helpers; `vector` field is only emitted when `len(vec) > 0` to preserve backward compatibility with existing records

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

- 純 `Set()` 在覆寫時會清空 `Entry.Vector` — 同一 key 若未帶 `VECTOR` flag 重新 SET，代表底層文字已變，舊 embedding 需一併作廢
- AOF 擴充出 `addToAOFWithVector` / `writeAOF` 共用 helper；僅在 `len(vec) > 0` 才寫出 `vector` 欄位，保持與既有紀錄的向後相容

</details>

***

## Files Changed

| File | Status | Tag |
|------|--------|-----|
| `core/openai/client.go` | Added | FEAT |
| `core/openai/client_test.go` | Added | FEAT |
| `core/store/vector.go` | Added | FEAT |
| `core/store/vcache.go` | Added | FEAT |
| `core/store/vsearch.go` | Added | FEAT |
| `core/store/vsim.go` | Added | FEAT |
| `core/store/set.go` | Modified | FEAT, UPDATE |
| `core/store/exec.go` | Modified | FEAT |
| `core/store/aof.go` | Modified | FEAT, UPDATE |
| `core/store/store.go` | Modified | FEAT |
| `core/store/find.go` | Modified | FEAT |
| `core/store/keys.go` | Modified | FEAT |
| `core/store/query.go` | Modified | FEAT |
| `README.md` | Modified | DOC |
| `doc/README.zh.md` | Added | DOC |
| `doc/architecture.md` | Added | DOC |
| `doc/architecture.zh.md` | Added | DOC |
| `doc/doc.md` | Added | DOC |
| `doc/doc.zh.md` | Added | DOC |
| `go.mod` / `go.sum` | Modified | CHORE |
| `Makefile` | Modified | CHORE |
| `.gitignore` | Modified | CHORE |
| `LICENSE` | Added | CHORE |

***

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