@@ -189,27 +189,54 @@ export async function upsertRecord<T = unknown>(
189189
190190/**
191191 * Semantic search across tables
192+ *
193+ * Generates an embedding for the query, then calls the gitmem_semantic_search
194+ * RPC function directly via PostgREST.
192195 */
193196export async function semanticSearch < T = unknown > (
194197 options : SupabaseSearchOptions
195198) : Promise < T [ ] > {
196- const { query, tables, match_count = 10 , project } = options ;
199+ if ( ! isConfigured ( ) ) {
200+ throw new Error ( "Supabase not configured" ) ;
201+ }
197202
198- const args : Record < string , unknown > = {
199- query,
200- match_count,
201- } ;
203+ const { query, match_count = 10 } = options ;
204+
205+ // Generate embedding for the query
206+ const { embed } = await import ( "./embedding.js" ) ;
207+ const embedding = await embed ( query ) ;
202208
203- if ( tables && tables . length > 0 ) {
204- args . tables = tables ;
209+ if ( ! embedding ) {
210+ console . error ( "[semantic-search] No embedding provider configured — cannot run semantic search" ) ;
211+ return [ ] ;
205212 }
206213
207- if ( project ) {
208- args . project = project ;
214+ // Call the RPC function directly via PostgREST
215+ const rpcName = `${ getTableName ( "" ) . replace ( / _ $ / , "" ) } _semantic_search` ;
216+ const url = `${ SUPABASE_URL } /rest/v1/rpc/${ rpcName } ` ;
217+
218+ const response = await fetch ( url , {
219+ method : "POST" ,
220+ headers : {
221+ "Content-Type" : "application/json" ,
222+ apikey : SUPABASE_KEY ,
223+ Authorization : `Bearer ${ SUPABASE_KEY } ` ,
224+ } ,
225+ body : JSON . stringify ( {
226+ query_embedding : `[${ embedding . join ( "," ) } ]` ,
227+ match_count,
228+ similarity_threshold : 0.0 ,
229+ } ) ,
230+ signal : AbortSignal . timeout ( 15_000 ) ,
231+ } ) ;
232+
233+ if ( ! response . ok ) {
234+ const text = await response . text ( ) ;
235+ throw new Error ( `Supabase RPC error: ${ response . status } - ${ text . slice ( 0 , 200 ) } ` ) ;
209236 }
210237
211- const result = await callMcp < { results : T [ ] } > ( "semantic_search" , args ) ;
212- return result . results || [ ] ;
238+ const rows = ( await response . json ( ) ) as T [ ] ;
239+ return rows || [ ] ;
213240}
214241
215242// ============================================================================
@@ -551,23 +578,54 @@ export async function loadScarsWithEmbeddings<T = unknown>(
551578
552579/**
553580 * Scar search with severity weighting
581+ *
582+ * Generates an embedding for the query, then calls the gitmem_scar_search
583+ * RPC function directly via PostgREST. No Edge Function required.
554584 */
555585export async function scarSearch < T = unknown > (
556586 query : string ,
557587 matchCount = 5 ,
558588 project ?: Project
559589) : Promise < T [ ] > {
560- const args : Record < string , unknown > = {
561- query,
562- match_count : matchCount ,
563- } ;
590+ if ( ! isConfigured ( ) ) {
591+ throw new Error ( "Supabase not configured" ) ;
592+ }
593+
594+ // Generate embedding for the query
595+ const { embed } = await import ( "./embedding.js" ) ;
596+ const embedding = await embed ( query ) ;
597+
598+ if ( ! embedding ) {
599+ console . error ( "[scar-search] No embedding provider configured — cannot run semantic search" ) ;
600+ return [ ] ;
601+ }
602+
603+ // Call the RPC function directly via PostgREST
604+ const rpcName = `${ getTableName ( "" ) . replace ( / _ $ / , "" ) } _scar_search` ;
605+ const url = `${ SUPABASE_URL } /rest/v1/rpc/${ rpcName } ` ;
606+
607+ const response = await fetch ( url , {
608+ method : "POST" ,
609+ headers : {
610+ "Content-Type" : "application/json" ,
611+ apikey : SUPABASE_KEY ,
612+ Authorization : `Bearer ${ SUPABASE_KEY } ` ,
613+ } ,
614+ body : JSON . stringify ( {
615+ query_embedding : `[${ embedding . join ( "," ) } ]` ,
616+ match_count : matchCount ,
617+ similarity_threshold : 0.0 ,
618+ } ) ,
619+ signal : AbortSignal . timeout ( 15_000 ) ,
620+ } ) ;
564621
565- if ( project ) {
566- args . project = project ;
622+ if ( ! response . ok ) {
623+ const text = await response . text ( ) ;
624+ throw new Error ( `Supabase RPC error: ${ response . status } - ${ text . slice ( 0 , 200 ) } ` ) ;
567625 }
568626
569- const result = await callMcp < { results : T [ ] } > ( "scar_search" , args ) ;
570- return result . results || [ ] ;
627+ const rows = ( await response . json ( ) ) as T [ ] ;
628+ return rows || [ ] ;
571629}
572630
573631/**
0 commit comments