Files
Arcrun/kbdb/src/index.ts
T
Claude 55a47d7c18 kbdb(embed): add batch backfill endpoint for pre-Vectorize entries (issue #7 / T2.4 缺口)
embed 模組原本只有 embedOnWrite(寫入即嵌),對「開 Vectorize binding 之前就寫入」或
embed-on-write 當時漏掉的既有 entry 沒有回填路徑 → is_embedded=0 永遠補不回,語義查詢回 0 筆。

新增(base,對 entries 做;embedding 是 base 唯一職責,非 graph 插件):
- embed.ts: backfillEmbeddings()——找 is_embedded=0 且 isEmbeddable(metadata.embed===true) 的 entry,
  批次補嵌(單次 AI.run 陣列 + 單次 VECTORIZE.upsert 陣列 + 單次 UPDATE IN,一批≈3 subrequest)、
  設 is_embedded=1,冪等、分批(limit 1-100,回傳 processed/remaining,可重複呼叫直到清零)。
  模組未開誠實回 enabled:false(不假綠)。backfillStatus() 回 pending/embedded 計數。
- routes/embed.ts: POST /embed/backfill、GET /embed/backfill/status;模組未開回 409 + capability_hint。
- index.ts: mount /embed。
- tests/embed-backfill.test.ts: 5 vitest(off no-op / 補嵌+標記 / 冪等 / 分批 remaining / status)。

base 維持對內容語意無知(只認通用 embed 旗標,不知 triplet/wiki)。tsc exit 0、vitest 5/5。
端到端(leo21c,wrangler 直推、非 acr update):pending 5→processed 5→remaining 0,
Vectorize vectorCount 0→5,/entries/search?mode=semantic 由 0 筆→5 筆(語義排序命中)。

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BDtnGPJpAzp8UqHfAo8o1s
2026-07-05 04:37:04 +00:00

28 lines
1.2 KiB
TypeScript

// KBDB Base — atomic universal table worker (arcrun self-hosted data layer + official core).
// SDD: .agents/specs/arcrun/kbdb-base/design.md
//
// Base = D1 only (free, no credit card): entries / templates / records + LIKE search + recipe-stats.
// Optional modules (NOT in this base): embed (Vectorize+AI binding, semantic search), triplet (separate repo).
import { Hono } from 'hono';
import type { Bindings } from './types';
import { entryRoutes } from './routes/entries';
import { templateRoutes } from './routes/templates';
import { recordRoutes } from './routes/records';
import { recipeStatRoutes } from './routes/recipe-stats';
import { embedRoutes } from './routes/embed';
const app = new Hono<{ Bindings: Bindings }>();
app.get('/', (c) => c.json({ service: 'arcrun-kbdb', tier: 'base', status: 'ok' }));
app.get('/health', (c) => c.json({ ok: true }));
app.route('/entries', entryRoutes);
app.route('/templates', templateRoutes);
app.route('/records', recordRoutes);
app.route('/recipe-stats', recipeStatRoutes);
// Optional embed module admin (backfill). Route mounts unconditionally; the handler
// honestly 409s when the embed binding is off (base 對內容語意無知,只認通用 embed 旗標)。
app.route('/embed', embedRoutes);
export default app;