efe8e165cf
按 leo 鐵律(2026-06-14)把插件從「直接 SQL 操作基本盤表」改寫成 「只透過基本盤 arcrun/kbdb HTTP API 讀寫」。零建表、零 migration、零 SQL。 - 新增 src/lib/kbdb-client.ts:唯一對外通道,封裝 entries/templates/records API - 新增 src/lib/templates.ts:triplet/entity template 定義(替代建表) - 改寫 21 個違規 action(triplet/graph/entity/search)→ 走 client,圖在插件層記憶體組裝 - 移除所有 migrations、D1/Vectorize/AI 綁定;embedding/語意搜尋歸基本盤 optional 模組 - index.ts 只掛 triplets/graph/entities/search 路由;基本盤路由歸 arcrun/kbdb - 測試改走 mock client(純 node);裁剪 CLAUDE.md 只留 graph 插件 + 鐵律 - 修正 SDD design.md「讀現狀推翻鐵律」的錯誤判斷(共用 D1 → API-as-Wall) Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
58 lines
2.7 KiB
Markdown
58 lines
2.7 KiB
Markdown
# FEATURE REQUEST: KBDB 應提供 upsert block endpoint(目前只能 client 端拼 GET+PATCH/POST)
|
||
|
||
> 日期:2026-05-29
|
||
> 來源:arcrun Phase 2(降級假零件成 recipe)
|
||
> 類型:API 缺口 —— upsert 語義目前不存在於 KBDB,被迫由 client 端拼湊
|
||
> 關聯:[BUG-2026-05-29-patch-blocks-403-different-org.md](./BUG-2026-05-29-patch-blocks-403-different-org.md)(拼湊路徑的 PATCH 那段還壞著)
|
||
|
||
---
|
||
|
||
## 問題
|
||
|
||
arcrun 原本有一個 `kbdb_upsert_block` 零件,行為是「依 page_name + user_id 查找,有就更新、沒有就新建」。但它**完全是 client 端拼湊**:
|
||
|
||
```
|
||
GET /blocks?page_name=X&limit=10 # 查找
|
||
→ client 端 filter user_id 找第一筆
|
||
→ 找到:PATCH /blocks/:id # 更新
|
||
→ 沒找到:POST /blocks # 新建
|
||
```
|
||
|
||
KBDB **沒有** upsert 語義的 endpoint。實測(同一把 key):
|
||
|
||
| 探測 | HTTP |
|
||
|---|---|
|
||
| `PUT /blocks` | 404 |
|
||
| `POST /blocks/upsert` | 404 |
|
||
| `PUT /blocks/upsert` | 404 |
|
||
|
||
## 為什麼這是 KBDB 該補的、不是 arcrun 該拼的
|
||
|
||
arcrun 的設計原則是**薄殼 / 薄 API**:arcrun 只幫既有 API 套一層 recipe(endpoint + auth),**不無中生有功能**。
|
||
|
||
「先查再分支寫」這套 upsert 邏輯,是在 client 端**變出 KBDB 沒有的功能**。這有幾個壞處:
|
||
|
||
1. **競態(race condition)**:GET 和後續 PATCH/POST 之間,別人可能插入同 page_name 的 block,造成重複或覆寫。只有 KBDB server 端用單一交易(upsert / `ON CONFLICT`)才能正確。
|
||
2. **語義碎裂**:每個 client(arcrun / 其他 SDK)各自拼一套 upsert,filter 規則(怎麼算「同一筆」)可能不一致。
|
||
3. **拼湊路徑現在還壞著**:它依賴 PATCH /blocks/:id,而那個 endpoint 目前回 403(見關聯 bug)。
|
||
|
||
## 建議
|
||
|
||
KBDB 提供一個原生 upsert endpoint,例如:
|
||
|
||
```
|
||
POST /blocks/upsert
|
||
Body: { page_name, user_id, content, type, source, tags, ... }
|
||
語義:依 (page_name, user_id) 找唯一 block —— 存在則更新、不存在則建立(單一交易,server 端 ON CONFLICT)
|
||
回應:{ id, action: "created" | "updated" }
|
||
```
|
||
|
||
有了它之後:
|
||
- arcrun 端只要建一個 `recipe:kbdb_upsert` 指向 `POST /blocks/upsert`,套殼即可,跟其他 5 個 KBDB recipe 一致。
|
||
- 競態由 KBDB server 端交易保證,client 不再拼湊。
|
||
|
||
## arcrun 端現狀(等 KBDB)
|
||
|
||
- 其餘 5 個 KBDB 操作已降級成 recipe 並驗收:`kbdb_get`(200) / `kbdb_create_block`(201) / `kbdb_ingest`(201) / `kbdb_delete`(200) 綠;`kbdb_patch_block` 因上述 403 bug 待驗。
|
||
- `kbdb_upsert_block` **暫不降級、源碼暫留**,等 KBDB 出 `POST /blocks/upsert` 後改建 `recipe:kbdb_upsert` 套殼。
|