feat(arcrun): kbdb_get 加 type/source/user_id filter

之前只支援 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
正在組)。
This commit is contained in:
2026-05-14 14:18:43 +08:00
parent 9560485937
commit 711af5dbf2
2 changed files with 64 additions and 19 deletions
@@ -23,13 +23,22 @@ input_schema:
description: KBDB partner keypk_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 — 純 filtermira_feed_watcher 用)
api_key: "{{api_key}}"
source: "km-writer-direct"
type: "note"
user_id: "inkstone_mira_post"
limit: 50
+34 -7
View File
@@ -25,8 +25,12 @@ 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 二擇一
BlockID string `json:"block_id"` // 模式 A:單一 block by id(最優先)
PageName string `json:"page_name"` // 模式 Bpage_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
}
@@ -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
}
// 構造 URLblock_id 模式走 /blocks/:id(單一),page_name 模式走 /blocks?page_name=...&limit=N
// 構造 URLblock_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{