Files
Arcrun/kbdb/src/types.ts
T
uncle6me-web 674e1b4fa2 fix(kbdb): D69 節流世代核對+標庫共用 D1 額度,補「挑哪一批」的統一 SelectionCriteria(Arcrun#85)
leo 逐行複核 fix/embed-backfill-d68 後點出的破口+二次裁決(票上全文見 Leo/Arcrun#85):

一、向量化優先序(今天寫的立刻/本週在跑的先跑/有查詢紀錄的庫優先/半年前慢慢跑)表達
不出來——策略要能從外面(工作流)指定,不能焊死在資料層。新增 embed.ts 的
`SelectionCriteria`(owner_id/source/library/since/until),backfillEmbeddings 與
reconcileEmbedGeneration 共用同一套形狀;「按庫」那一層現在有資料可用即可運作(見下)。

二、世代核對(reconcileEmbedGeneration)不打 AI 但逐筆寫 D1,47 萬筆候選 ≈ 4.7 倍 D1
100,000 rows/日免費額度,先前零保護。新增 actions/maintenance-quota.ts(單一 entries
列/日的共用計數器,精神同 execution-log.ts/embed.ts 既有慣例,不新增表)。

三、leo 二度裁決:「標庫」與「時間分層」其實是一件事,判定標準要從第一天同時容納兩者,
不能先做一半再回頭改。新增 actions/library-backfill.ts 的 backfillEntryLibraryTags——
呼叫端(ingest/daemon/Arcrun#87)決定要貼哪個庫、用 page_names(Gitea 原稿卡名精準
點名,leo 定案的正解)或 source_prefix/page_name_prefix 過渡 fallback 篩選候選,base
只負責安全、節流地寫入。owner_id 刻意必填(leo 點出「補錯 owner 等於白做」——實查卡片
掛在 owner_id=bfezv28v,換成 'leo' 查卻是空的)。

D69:reconcile 與標庫 backfill 共用同一顆「今天還剩多少 D1 寫入額度」計數器(不共用的話
其中一個會把另一個的閘繞過去);新增 POST /entries/backfill-library + GET .../status,
擴充 POST /embed/backfill 與 /embed/reconcile 吃 library/since/until 參數。

測試:92 → 39 個新增/擴充案例覆蓋 since/until/library 篩選、reconcile 額度真的擋
(含「拿掉 cap 會變紅」反向驗證)、標庫 backfill 冪等/owner_id 必填/page_names 精準比對、
以及兩個操作共用同一顆額度計數器的跨模組驗證(雙向:先 reconcile 耗盡再標庫、反之亦然)。
kbdb 全套 192 個測試綠燈,tsc --noEmit 除既有 auth.test.ts 舊缺陷外無新增錯誤。

紅線:未併 main、未部署、未動任何實例的 is_embedded 旗標(只在本地 SQLite 測試治具跑過)。

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-11 18:39:55 +08:00

90 lines
3.7 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// KBDB Base types. Base depends on D1 only.
// Optional modules add their own bindings (embed: VECTORIZE+AI). Base never references them.
export type Bindings = {
DB: D1Database;
ENVIRONMENT: string;
// Auth guard (t115 二修, fail-closed): provisioned by the installer automatically.
// NOT set → writes (POST/PATCH/DELETE/PUT) rejected 401; reads pass with a warning
// (upgrade-window grace so read-only workflows don't break before both workers are
// updated together).
// SET → all non-health routes require `Authorization: Bearer <token>`.
// cypher-executor sends this via kbdbBase(); portal/webhooks/recipes send it inline.
KBDB_INTERNAL_TOKEN?: string;
// Optional embed module (issue #7 / SDD T2.4). Present ONLY when the self-host opened
// semantic search (kbdb_embed:true → deploy injects [[vectorize]] + [ai]). Base never
// requires them; code checks `if (env.VECTORIZE && env.AI)` before touching embed.
VECTORIZE?: VectorizeIndex;
AI?: Ai;
// 嵌入模型(Arcrun#59)。未設=用 embed.ts 的預設。設成別的模型時,**Vectorize index 的
// dimensions 必須跟著對**(維度不合 upsert 會被 CF 拒絕),且換模型必須換 index:
// 不同模型的向量不可共存於同一個 index(比對出來是垃圾),詳見 embed.ts 檔頭。
EMBED_MODEL?: string;
// execution_log 每日軟上限(KV 額度事故修復,2026-08-07A2 自我降級,見
// kbdb/src/actions/execution-log.ts DEFAULT_DAILY_LIMIT 說明)。未設 → 20000
// D1 100,000 rows written/日的 20%,留 80% 給知識卡 entries)。
EXECUTION_LOG_DAILY_WRITE_LIMIT?: string;
// embed backfill 每日軟上限(D682026-08-11:補算向量照時間新到舊、且每天有額度上限)。
// backfill 與「寫入即嵌」「萃取」共用同一份 Workers AI 每日 10,000 免費 neurons(見頂層
// wiki ops-facts.md);backfill 是背景低優先動作,自設軟上限不把當天額度燒光。未設 → 見
// kbdb/src/embed.ts DEFAULT_BACKFILL_DAILY_LIMIT 說明(含選值算式,非拍腦袋)。
EMBED_BACKFILL_DAILY_LIMIT?: string;
// 背景維護寫入(reconcile 世代核對 + 標庫 backfill)共用的 D1 每日寫入軟上限
// Arcrun#85 D69 修法,2026-08-11:兩者都是「多筆 D1 row write、不打 AI」的操作,
// 各自不設防都會單獨燒穿 D1 100,000 rows/日免費額度——reconcile 47 萬筆 candidate
// ≈ 4.7 倍全日額度,已在票上實測;標庫 backfill 同樣是逐筆 D1 write,若各管各的,
// 補標庫時會把 reconcile 的閘繞過去。兩者共用同一顆「今天還剩多少」計數器。
// 未設 → 見 kbdb/src/actions/maintenance-quota.ts DEFAULT_MAINTENANCE_DAILY_WRITE_LIMIT。
KBDB_MAINTENANCE_DAILY_WRITE_LIMIT?: string;
};
export type EntryType =
| 'block'
| 'value'
| 'template'
| 'slot'
| 'project'
| 'workflow'
| 'recipe_stat'
| 'execution_log'
| 'execution_log_usage'
| 'embed_backfill_usage'
| 'kbdb_maintenance_usage';
export interface Entry {
id: string;
content: string | null;
entry_type: EntryType | string;
owner_id: string | null;
parent_id: string | null;
page_name: string | null;
refs_json: string;
tags_json: string;
task_status: string | null;
content_hash: string | null;
is_embedded: number;
confidence: number | null;
metadata_json: string | null;
created_at: number;
updated_at: number;
}
export interface Template {
id: string;
name: string;
description: string | null;
slots_json: string;
created_by: string | null;
created_at: number;
updated_at: number;
}
export interface EntryValue {
id: string;
record_id: string;
template_id: string;
slot_name: string;
entry_id: string;
created_at: number;
}