refactor: Remove semantic search and vector embedding functionality

Removes @xenova/transformers dependency, vector storage tables, embedding generation, and semantic search APIs. Simplifies context building to use only FTS search. Eliminates visualizer server, postinstall model download, and related CLI commands. Reduces package size and complexity while maintaining core static analysis capabilities.
This commit is contained in:
Colby McHenry
2026-04-07 14:59:48 -05:00
parent 7507605be5
commit 453c39d774
16 changed files with 12 additions and 4424 deletions
+6 -33
View File
@@ -1,7 +1,7 @@
/**
* Context Builder
*
* Builds rich context for tasks by combining semantic search with graph traversal.
* Builds rich context for tasks by combining FTS search with graph traversal.
* Outputs structured context ready to inject into Claude.
*/
@@ -22,7 +22,6 @@ import {
} from '../types';
import { QueryBuilder } from '../db/queries';
import { GraphTraverser } from '../graph';
import { VectorManager } from '../vectors';
import { formatContextAsMarkdown, formatContextAsJson } from './formatter';
import { logDebug } from '../errors';
import { validatePathWithinRoot } from '../utils';
@@ -185,18 +184,15 @@ export class ContextBuilder {
private projectRoot: string;
private queries: QueryBuilder;
private traverser: GraphTraverser;
private vectorManager: VectorManager | null;
constructor(
projectRoot: string,
queries: QueryBuilder,
traverser: GraphTraverser,
vectorManager: VectorManager | null
traverser: GraphTraverser
) {
this.projectRoot = projectRoot;
this.queries = queries;
this.traverser = traverser;
this.vectorManager = vectorManager;
}
/**
@@ -394,21 +390,7 @@ export class ContextBuilder {
exactMatches = exactMatches.slice(0, Math.ceil(opts.searchLimit * 3));
}
// Step 3: Try semantic search if vector manager is available
let semanticResults: SearchResult[] = [];
if (this.vectorManager && this.vectorManager.isInitialized()) {
try {
semanticResults = await this.vectorManager.search(query, {
limit: opts.searchLimit,
kinds: opts.nodeKinds && opts.nodeKinds.length > 0 ? opts.nodeKinds : undefined,
});
logDebug('Semantic search results', { count: semanticResults.length });
} catch (error) {
logDebug('Semantic search failed, falling back to text search', { query, error: String(error) });
}
}
// Step 4: Always run text search for natural language term matching
// Step 3: Run text search for natural language term matching
// This catches file-name and node-name matches that semantic search may miss,
// which is critical for template-heavy codebases (e.g., Liquid/Shopify themes)
// where file names are the primary identifiers.
@@ -457,7 +439,7 @@ export class ContextBuilder {
logDebug('Text search failed', { query, error: String(error) });
}
// Step 5: Merge results, prioritizing exact matches, then text (path-boosted), then semantic
// Step 4: Merge results, prioritizing exact matches, then text (path-boosted)
const seenIds = new Set<string>();
let searchResults: SearchResult[] = [];
@@ -477,14 +459,6 @@ export class ContextBuilder {
}
}
// Add semantic results
for (const result of semanticResults) {
if (!seenIds.has(result.node.id)) {
seenIds.add(result.node.id);
searchResults.push(result);
}
}
const queryLower = query.toLowerCase();
const isTestQuery = queryLower.includes('test') || queryLower.includes('spec');
@@ -1121,10 +1095,9 @@ export class ContextBuilder {
export function createContextBuilder(
projectRoot: string,
queries: QueryBuilder,
traverser: GraphTraverser,
vectorManager: VectorManager | null
traverser: GraphTraverser
): ContextBuilder {
return new ContextBuilder(projectRoot, queries, traverser, vectorManager);
return new ContextBuilder(projectRoot, queries, traverser);
}
// Re-export formatter