/** * Maximal Marginal Relevance (MMR) re-ranking — Phase 2. * * Ported from upstream `extensions/memory-core/src/memory/mmr.ts` with * minor adaptation for our `MemoryEntry` shape (content vs snippet, id vs * path+startLine). Behavior is identical: normalize scores, iteratively * pick the item that maximizes `λ * relevance - (1-λ) * max_similarity` * using Jaccard on tokenized content. * * @see Carbonell & Goldstein, "The Use of MMR, Diversity-Based Reranking" (1998) */ export interface MMRConfig { /** Opt-in. Upstream default is false. */ enabled: boolean; /** 0 = max diversity, 1 = max relevance. Upstream default 0.7. */ lambda: number; } export declare const DEFAULT_MMR_CONFIG: MMRConfig; /** * Tokenize content into a set for Jaccard similarity. * * ASCII: alphanumeric + underscore runs, lowercased. * CJK: each char becomes a unigram; consecutive pairs become a bigram. * Non-adjacent CJK chars (e.g. `我a好`) do NOT form a bigram. */ export declare function tokenize(text: string): Set; export declare function jaccardSimilarity(a: Set, b: Set): number; export declare function textSimilarity(a: string, b: string): number; export declare function computeMMRScore(relevance: number, maxSimilarity: number, lambda: number): number; export interface MMRItem { id: string; score: number; content: string; } /** * Re-rank items using MMR. Returns a new array in MMR order. */ export declare function mmrRerank(items: T[], config?: Partial): T[]; /** * Adapter: apply MMR to an array of MemoryEntry-shaped hits. * * Uses (path|id|index) as the stable ID so two hits from the same file at * different content still get distinct MMR identities. */ export declare function applyMMRToMemoryHits(results: T[], config?: Partial): T[];