fix(edge): meter and size-cap knowledge embeddings in embed-chunks and search-knowledge

This commit is contained in:
Yun Chan 2026-09-28 00:53:48 +09:00
parent b35676c75c
commit 1afaea7214
12 changed files with 1111 additions and 270 deletions

View file

@ -0,0 +1,70 @@
// server/supabase/functions/embed-chunks/supabase-knowledge-store.ts
// KnowledgeIndexStore adapter over the service-role Supabase client.
import type { createClient } from '@supabase/supabase-js'
import { type KnowledgeChunkRow, type KnowledgeIndexStore, KnowledgeStorageError } from './handler.ts'
type SupabaseClient = ReturnType<typeof createClient>
export function createSupabaseKnowledgeStore(client: SupabaseClient): KnowledgeIndexStore {
return {
async documentOwner(documentId) {
const { data, error } = await client
.from('knowledge_documents')
.select('id,user_id')
.eq('id', documentId)
.maybeSingle()
if (error) throw new KnowledgeStorageError()
const row = data as { user_id?: unknown } | null
return row && typeof row.user_id === 'string' ? row.user_id : null
},
async countChunks(documentId, pendingOnly) {
let query = client
.from('knowledge_chunks')
.select('id', { count: 'exact', head: true })
.eq('document_id', documentId)
if (pendingOnly) query = query.is('embedding', null)
const { count, error } = await query
if (error) throw new KnowledgeStorageError()
return count
},
async listPendingChunks(documentId, limit) {
const { data, error } = await client
.from('knowledge_chunks')
.select('id,content')
.eq('document_id', documentId)
.is('embedding', null)
.order('chunk_index', { ascending: true })
.limit(limit)
if (error) throw new KnowledgeStorageError()
return (data ?? []) as KnowledgeChunkRow[]
},
async saveEmbedding(documentId, chunkId, embedding) {
const { error } = await client
.from('knowledge_chunks')
.update({ embedding })
.eq('id', chunkId)
.eq('document_id', documentId)
return !error
},
async clearIndexed(documentId, userId) {
let query = client
.from('knowledge_documents')
.update({ indexed: false, indexed_at: null })
.eq('id', documentId)
if (userId !== null) query = query.eq('user_id', userId)
const { error } = await query
return !error
},
async markIndexed(documentId, userId) {
const { data, error } = await client
.from('knowledge_documents')
.update({ indexed: true, indexed_at: new Date().toISOString() })
.eq('id', documentId)
.eq('user_id', userId)
.select('id')
.maybeSingle()
return !error && Boolean(data)
},
}
}