Files
kbdb-graph-plugin/docs/3-specs/blocks-edit-api/design.md
T
Leo efe8e165cf feat: KBDB-graph 插件獨立 — 全面改寫成走基本盤 API(API-as-Wall)
按 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>
2026-06-14 20:59:41 +08:00

7.6 KiB
Raw Blame History

KBDB — Blocks Edit API

建立2026-05-06 狀態:草稿,待 richblack review 依賴matrix/kbdb/CLAUDE.md(萬物皆 Block 架構,2026-02-28 鎖定) 驅動需求polaris/mira/.agents/specs/mira-app/design.md(前端 inline edit 直寫 KBDB 的需求)


0. 背景

KBDB v3「萬物皆 Block」架構鎖定後,現役 routes 涵蓋 Block CRUD 多數操作,但缺少編輯既有 block 的 PATCH endpoints。具體缺口:

操作 現役狀態
POST /blocks/ingest(建立) 已有
GET /blocks/{id}(讀取單筆) 已有
GET /blocks/(列表 / 查詢) 已有
DELETE /blocks/{id}(刪除) 已有
PATCH /blocks/{id}(部分更新)
POST /triplets/(建立) 已有
PATCH /triplets/{id} / DELETE /triplets/{id}
PUT /templates/{name} 已有
PATCH /tasks/{id}/status 已有

→ 沒有 PATCH/UPDATE block 內容的 API,前端「inline edit 寫回 KBDB」做不了。

src/routes/blocks.ts.bak 有 PUT /:id 的舊實作可參考,但已被 v3 取代並停用。不直接複用 .bak 檔案,按 v3 規範重寫。


1. 範圍

本 SDD 涵蓋兩件事:

  1. 補三組 endpointPATCH /blocks/{id}, PATCH /triplets/{id}, DELETE /triplets/{id}
  2. 建三個 templatesdata-source-config, source-skill, wiki-page(為 mira-app 準備)

不在範圍內

  • 改 schemav3 鎖定,禁止 ALTER TABLE
  • 改既有 endpoint 行為(純加新 endpoint
  • 多用戶權限細分(partner key 已能做 org 隔離,沿用即可)
  • 編輯歷史 / undo(未來 SDD

2. PATCH /blocks/{id}

2.1 用途

部分更新一個既有 block。前端 inline edit 場景:使用者點 edit icon,改 content / refs / tags,按儲存 → 送 PATCH。

2.2 規格

PATCH /blocks/{id}
Authorization: Bearer <api_key>
Content-Type: application/json

Body (所有欄位皆 optional,至少要有一個)
{
  "content": "新的內容",
  "tags": ["tag1", "tag2"],          // 完整覆寫 tags 陣列
  "refs": ["block-id-1", "block-id-2"], // 完整覆寫 refs 陣列
  "slots": { "key": "value" },       // 完整覆寫 slots 物件
  "source": "...",                   // 通常不改,但允許
  "metadata_json": { ... }           // 完整覆寫
}

Response 200:
{
  "id": "...",
  "content": "...",
  "updated_at": "2026-05-06T...",
  ...完整 block 欄位
}

Response 400:
{ "error": "no fields to update" }

Response 403:
{ "error": "block belongs to different org" }

Response 404:
{ "error": "block not found" }

2.3 行為

  • 只更新 body 內提供的欄位
  • 自動更新 updated_at
  • 自動重新計算 content_hash(如 content 變動)
  • 自動觸發 embedding 重算(如 content 變動,async
  • 權限partner key 只能改自己 org 內的 block(透過 user_id 對應),internal token 可改任何 block
  • content_hash 衝突partner key 不可修改 v3「sourcesystem 的 admin 標記資料」(沿用既有 admin-preservation 規則)

2.4 實作位置

  • Action: src/actions/update-block.ts< 100 行,按 KBDB CLAUDE.md 樂高法)
  • Route: src/routes/blocks.ts 加新 OpenAPI route
  • Test: tests/blocks-update.test.ts

3. Triplet 編輯:使用既有 PUT /records/:id + DELETE /records/:id

設計修正(2026-05-06 實作時發現)

v3 萬物皆 Block 架構下,triplet 是 tpl-triplet template 的 record(用 entry_values 存 subject/predicate/object slots)。既有 PUT /records/:idDELETE /records/:id 已涵蓋編輯/刪除需求,無需新增 PATCH /triplets/:id

→ 前端編輯異見牆上的 triplet:

  • 編輯:PUT /records/{triplet_record_id} body { values: { subject, predicate, object } }
  • 刪除:DELETE /records/{triplet_record_id}

本 SDD 不再規劃新 triplet endpoint


5. 三個新 Templates

按 KBDB v3 規範,新資料類型透過 template 定義,不動 schema

5.1 template: data-source-config

每個資料源實例對應一個此 template 的 block。Mira 的「來源篩選」、cron workflow 的「每天去抓什麼」都讀這個。

template_name: data-source-config
slots:
  - name: string             # "電子時報"、"我的 Logseq"
  - channel: string          # rss / telegram / km-writer / voice-stt / ai-comment / ai-canon
  - config: object           # channel-specific (e.g., rss: {url, schedule})
  - skill_id: string?        # 連到 source-skill block 的 id
  - enabled: bool
  - ai_comment: bool         # 是否需要 AI 加註解
  - ai_comment_style: string?  # 提示給 claude_api 的風格

5.2 template: source-skill

每個 source 累積的「分析配方」(prompt + few-shot)。可在前端編輯、版本化。

template_name: source-skill
slots:
  - name: string             # 例 "電子時報科技類分析"
  - prompt: text             # system_prompt 內容
  - examples: text?          # few-shot examplesmarkdown
  - version: int
  - based_on: string?        # 上一版的 block id

5.3 template: wiki-page

AI 從河道對話合成的定稿。

template_name: wiki-page
slots:
  - entity_name: string
  - summary: text            # markdown
  - key_blocks: array<string>  # 引用的 source block ids
  - conflicts: array<string>?  # 標記為矛盾的 block ids
  - generated_at: timestamp
  - version: int
  - based_on: string?

5.4 建立方式

不寫 SQL migrationv3 規範禁止)。改用 KBDB 既有的 POST /templates

curl -X POST https://kbdb.finally.click/templates \
  -H "Authorization: Bearer <internal_token>" \
  -d '{"name": "data-source-config", "slots": [...]}'

→ tasks.md 列為 P0 任務(用 internal token 一次性建好)。


6. 實作步驟

Phase 1:補 endpoints

  1. src/actions/update-block.ts(純函數,< 100 行,含權限檢查)
  2. tests/blocks-update.test.ts(含 happy path、403、404、no-fields 三案)
  3. src/routes/blocks.ts 的 PATCH routeOpenAPI 定義 + 呼叫 action
  4. src/routes/triplets.ts PATCHwrapper+ DELETEalias
  5. 部署 + smoke test

Phase 2:建 templates

  1. 用 internal token 呼叫 POST /templates 建三個 template
  2. 驗證:用 partner key (mira 用的) 創建一個 data-source-config block 看能否寫成功

Phase 3:補 OpenAPI spec

  1. 確認新 routes 自動進 swagger.jsonOpenAPIHono 應該自動,需驗證)

7. 風險

  • embedding 重算成本PATCH content 會觸發 vectorize 重算,頻繁 inline edit 可能拖慢。對策embedding 改為 async(行為已是 async,需確認)。
  • content_hash 計算遺漏:忘記重算會讓查重失效。對策:在 action 內統一處理,不讓 route 層管。
  • partner key 越權:必須驗 user_id 對應,不能讓 partner A 改 partner B 的 block。對策write tests 涵蓋此案。
  • 三個 templates 命名衝突:若 KBDB 已有同名 template 會 fail。對策:建立前先 GET /templates/{name} 檢查。

8. 不在範圍內

  • 編輯歷史 / undo / version diff(未來 SDD
  • Block soft deletev3 已有 hard deletesoftdelete 是 enhancement
  • Bulk PATCH(一次改多個 block,未來看需求)
  • Field-level permissions(特定欄位只能某些 user 改)
  • WebSocket 通知 block 改了(即時協作)

9. 變更紀錄

版本 日期 內容
v0 2026-05-06 初稿。對應 mira-app 的 inline edit 需求。