package tools import ( "context" "github.com/google/uuid" "git.warky.dev/wdevs/amcs/internal/ai" "git.warky.dev/wdevs/amcs/internal/config" "git.warky.dev/wdevs/amcs/internal/store" thoughttypes "git.warky.dev/wdevs/amcs/internal/types" ) const ( RetrievalModeSemantic = "semantic" RetrievalModeText = "text" ) // semanticSearch runs vector similarity search if embeddings exist for the // primary embedding model in the given scope, otherwise falls back to Postgres // full-text search. Search always uses the primary model so query vectors // match rows stored under the primary model name. // It returns the results and the retrieval mode used ("semantic" or "text"). func semanticSearch( ctx context.Context, db *store.DB, embeddings *ai.EmbeddingRunner, search config.SearchConfig, query string, limit int, threshold float64, projectID *int64, excludeID *uuid.UUID, ) ([]thoughttypes.SearchResult, string, error) { model := embeddings.PrimaryModel() hasEmbeddings, err := db.HasEmbeddingsForModel(ctx, model, projectID) if err != nil { return nil, "", err } if hasEmbeddings { embedding, err := embeddings.EmbedPrimary(ctx, query) if err != nil { return nil, "", err } results, err := db.SearchSimilarThoughts(ctx, embedding, model, threshold, limit, projectID, excludeID) return results, RetrievalModeSemantic, err } results, err := db.SearchThoughtsText(ctx, query, limit, projectID, excludeID) return results, RetrievalModeText, err }