MCPcopy Index your code
hub / github.com/forloopcodes/contextplus / search

Method search

src/core/embeddings.ts:490–539  ·  view source on GitHub ↗
(query: string, optionsOrTopK?: number | SearchQueryOptions)

Source from the content-addressed store, hash-verified

488 }
489
490 async search(query: string, optionsOrTopK?: number | SearchQueryOptions): Promise<SearchResult[]> {
491 const options = resolveSearchOptions(optionsOrTopK);
492 const [queryVec] = await fetchEmbedding(query);
493 const queryTerms = new Set(splitCamelCase(query));
494 const scores: {
495 idx: number;
496 score: number;
497 semanticScore: number;
498 keywordScore: number;
499 matchedSymbols: string[];
500 matchedSymbolLocations: string[];
501 }[] = [];
502
503 for (let i = 0; i < this.vectors.length; i++) {
504 if (!this.vectors[i]) continue;
505 const doc = this.documents[i];
506 const semanticScore = cosine(queryVec, this.vectors[i]);
507 const matchedEntries = doc.symbolEntries ? getMatchedSymbolEntries(doc.symbolEntries, queryTerms) : [];
508 const matchedSymbols = matchedEntries.length > 0
509 ? matchedEntries.map((entry) => entry.name)
510 : getMatchedSymbols(doc.symbols, queryTerms);
511 const matchedSymbolLocations = matchedEntries.map((entry) => `${entry.name}@${formatLineRange(entry.line, entry.endLine)}`);
512 const keywordScore = computeKeywordScore(query, queryTerms, doc, matchedSymbols);
513 const score = computeCombinedScore(semanticScore, keywordScore, options);
514
515 if (options.requireSemanticMatch && semanticScore <= 0) continue;
516 if (options.requireKeywordMatch && keywordScore <= 0) continue;
517 if (Math.max(semanticScore, 0) < options.minSemanticScore) continue;
518 if (keywordScore < options.minKeywordScore) continue;
519 if (score < options.minCombinedScore) continue;
520
521 scores.push({ idx: i, score, semanticScore, keywordScore, matchedSymbols, matchedSymbolLocations });
522 }
523
524 return scores
525 .sort((a, b) => b.score - a.score || b.keywordScore - a.keywordScore || b.semanticScore - a.semanticScore)
526 .slice(0, options.topK)
527 .map(({ idx, score, semanticScore, keywordScore, matchedSymbols, matchedSymbolLocations }) => {
528 const doc = this.documents[idx];
529 return {
530 path: doc.path,
531 score: Math.round(score * 1000) / 10,
532 semanticScore: Math.round(Math.max(semanticScore, 0) * 1000) / 10,
533 keywordScore: Math.round(keywordScore * 1000) / 10,
534 header: doc.header,
535 matchedSymbols,
536 matchedSymbolLocations,
537 };
538 });
539 }
540
541 getDocumentCount(): number {
542 return this.documents.length;

Callers 2

semanticCodeSearchFunction · 0.80

Calls 9

resolveSearchOptionsFunction · 0.85
fetchEmbeddingFunction · 0.85
splitCamelCaseFunction · 0.85
getMatchedSymbolEntriesFunction · 0.85
getMatchedSymbolsFunction · 0.85
computeKeywordScoreFunction · 0.85
computeCombinedScoreFunction · 0.85
cosineFunction · 0.70
formatLineRangeFunction · 0.70

Tested by

no test coverage detected