From 711af5dbf2dc78c165eedad4af556db9e21e4690 Mon Sep 17 00:00:00 2001 From: richblack Date: Thu, 14 May 2026 14:18:43 +0800 Subject: [PATCH] =?UTF-8?q?feat(arcrun):=20kbdb=5Fget=20=E5=8A=A0=20type/s?= =?UTF-8?q?ource/user=5Fid=20filter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 之前只支援 block_id / page_name,撈「source=km-writer-direct 的 note」這類 跨 page 查詢做不到。Wiki UI 7B.3g 跟 mira_feed_watcher 都要用 client-side filter 繞,違反「邊用 arcrun 邊修」原則。 擴 contract:保留既有 block_id (mode A) + page_name (mode B),新增純 filter mode C:type / source / user_id 任意組合。同時 page_name + filter 也允許組合。 驗證:source=km-writer-direct&type=note&limit=5 撈到 leo 5 筆未處理河道貼文。 對應 SDD: arcrun.md 三-B 新零件 checklist + tasks.md 7B.3h(mira_feed_watcher 正在組)。 --- .../kbdb_get/component.contract.yaml | 40 ++++++++++++----- registry/components/kbdb_get/main.go | 43 +++++++++++++++---- 2 files changed, 64 insertions(+), 19 deletions(-) diff --git a/registry/components/kbdb_get/component.contract.yaml b/registry/components/kbdb_get/component.contract.yaml index f5586da..a560803 100644 --- a/registry/components/kbdb_get/component.contract.yaml +++ b/registry/components/kbdb_get/component.contract.yaml @@ -23,13 +23,22 @@ input_schema: description: KBDB partner key(pk_live_xxx 或 ak_xxx) block_id: type: string - description: 取單一 block。給 block_id 走 GET /blocks/{id},與 page_name 二擇一 + description: 模式 A — 取單一 block by id(指定後其他 filter 都忽略) page_name: type: string - description: 按 page_name 查列表。走 GET /blocks?page_name=...&limit=N + description: 模式 B — 按 page_name 查列表(可疊 type / source / user_id filter) + type: + type: string + description: filter — block type(如 wiki-page / wiki-paragraph / triplet / note) + source: + type: string + description: filter — block source(如 km-writer-direct / ai-canon-wiki) + user_id: + type: string + description: filter — block user_id(如 inkstone_mira_tools) limit: type: integer - description: page_name 模式下的最大筆數,預設 50 + description: 列表模式 limit,預設 50 default: 50 kbdb_url: type: string @@ -54,16 +63,25 @@ gherkin_tests: - scenario: "缺 api_key" given: '{"page_name":"x"}' then_contains: '{"success":false' - - scenario: "block_id 與 page_name 都沒給" + - scenario: "沒給任何查詢條件" given: '{"api_key":"pk_live_x"}' then_contains: '{"success":false' -tags: [data, storage, kbdb, get, query, primitive] -description: "從 KBDB 讀 block。支援兩種模式:(1) block_id 取單一 block;(2) page_name 取列表。透過 host function http_request 呼叫 KBDB GET /blocks 或 /blocks/:id。Mira wiki 合成 / 各 source workflow 讀草稿 / 查 wiki schema 都走這條。" + - scenario: "用 type filter 列 wiki-page" + given: '{"api_key":"ak_x","type":"wiki-page"}' + then_contains: 'blocks' +tags: [data, storage, kbdb, get, query, filter, primitive] +description: "從 KBDB 讀 block。三種模式:(A) block_id 取單一;(B) page_name 取列表(可疊 filter);(C) 純 type / source / user_id filter(不需 page_name)。透過 host function http_request 呼叫 KBDB GET /blocks 或 /blocks/:id。Mira wiki_synthesis / feed watcher / 各 source workflow 都走這條。" config_example: | - read_schema: # 取單一 block - api_key: "{{secret.kbdb_key}}" - page_name: "mira-wiki-schema" - read_drafts: # 取列表 - api_key: "{{secret.kbdb_key}}" + read_schema: # 模式 A — 單一 block by id + api_key: "{{api_key}}" + block_id: "26c51776-d07c-4490-9836-95e554d64549" + read_drafts: # 模式 B — page_name 列表 + api_key: "{{api_key}}" page_name: "{{prev.entity_name}}" limit: 100 + list_unprocessed_raws: # 模式 C — 純 filter(mira_feed_watcher 用) + api_key: "{{api_key}}" + source: "km-writer-direct" + type: "note" + user_id: "inkstone_mira_post" + limit: 50 diff --git a/registry/components/kbdb_get/main.go b/registry/components/kbdb_get/main.go index 5e822db..232595b 100644 --- a/registry/components/kbdb_get/main.go +++ b/registry/components/kbdb_get/main.go @@ -25,9 +25,13 @@ func hostHttpRequest( type Input struct { KBDBUrl string `json:"kbdb_url"` // optional APIKey string `json:"api_key"` // 必填 - BlockID string `json:"block_id"` // 與 page_name 二擇一 - PageName string `json:"page_name"` // 與 block_id 二擇一 - Limit int `json:"limit"` // optional, default 50 + BlockID string `json:"block_id"` // 模式 A:單一 block by id(最優先) + PageName string `json:"page_name"` // 模式 B:page_name 為主,可疊 type/source/user_id filter + // 模式 C:純 filter 查詢,至少要有 type / source / user_id 其中一個(page_name 不必填) + Type string `json:"type"` // 例:wiki-page / wiki-paragraph / triplet / note + Source string `json:"source"` // 例:km-writer-direct / ai-canon-wiki + UserID string `json:"user_id"` // 例:inkstone_mira_tools + Limit int `json:"limit"` // optional, default 50 } var dummy [1]byte @@ -78,8 +82,10 @@ func main() { writeError("api_key 必填") return } - if input.BlockID == "" && input.PageName == "" { - writeError("block_id 或 page_name 必填其一") + // 至少要有一個查詢條件 + hasFilter := input.Type != "" || input.Source != "" || input.UserID != "" + if input.BlockID == "" && input.PageName == "" && !hasFilter { + writeError("至少要有一個查詢條件:block_id / page_name / type / source / user_id") return } @@ -93,13 +99,34 @@ func main() { limit = 50 } - // 構造 URL:block_id 模式走 /blocks/:id(單一),page_name 模式走 /blocks?page_name=...&limit=N + // 構造 URL:block_id 模式走 /blocks/:id(單一),其餘走 /blocks?...query 列表 var url string if input.BlockID != "" { url = kbdbURL + "/blocks/" + urlEncode(input.BlockID) } else { - url = kbdbURL + "/blocks?page_name=" + urlEncode(input.PageName) + - "&limit=" + strconv.Itoa(limit) + // list 模式:page_name / type / source / user_id 任意組合 + params := []string{} + if input.PageName != "" { + params = append(params, "page_name="+urlEncode(input.PageName)) + } + if input.Type != "" { + params = append(params, "type="+urlEncode(input.Type)) + } + if input.Source != "" { + params = append(params, "source="+urlEncode(input.Source)) + } + if input.UserID != "" { + params = append(params, "user_id="+urlEncode(input.UserID)) + } + params = append(params, "limit="+strconv.Itoa(limit)) + + url = kbdbURL + "/blocks?" + for i, p := range params { + if i > 0 { + url += "&" + } + url += p + } } headers := map[string]string{