/**
 * Episodic memory recall — weighted score combination (cosine + recency + importance).
 *
 * Despite the file name (RRF — Reciprocal Rank Fusion), the algorithm used
 * for CC v3.1 is a **linear combination of normalized components**:
 *
 *   score(e) = α · cosine_sim(q, e.embedding)
 *            + β · exp(-Δt / τ)               // recency decay
 *            + γ · importance(e)               // [0,1]
 *
 *   defaults: α=0.5, β=0.3, γ=0.2, τ=14 days
 *
 * This shape was chosen over pure RRF because the three signals are
 * heterogeneous (similarity, time, salience) and combining them via rank
 * fusion would erase the magnitude information that callers care about
 * (e.g. "near-perfect cosine match" vs "loosely related").
 *
 * Pluggable scorers — callers provide functions mapping an entry to each
 * component so the algorithm is decoupled from storage details (embedding
 * column, importance field name, etc.).
 *
 * @see ../ports/brain.ts — EpisodicMemoryEntry
 * @see ADR-ECO-034 §"AgentPersona via Brain Tier 3 semantic" (companion)
 * @public
 */
import type { EpisodicMemoryEntry } from "../ports/brain.js";
/** Default weights — sum to 1.0. */
export declare const DEFAULT_RRF_WEIGHTS: {
    readonly cosine: 0.5;
    readonly recency: 0.3;
    readonly importance: 0.2;
};
/** Default recency half-life (14 days in ms). */
export declare const DEFAULT_RECENCY_HALFLIFE_MS: number;
export interface RrfWeights {
    cosine: number;
    recency: number;
    importance: number;
}
export interface RrfOptions {
    weights?: Partial<RrfWeights>;
    /** Half-life for recency decay (default: 14 days). */
    recencyHalflifeMs?: number;
    /** Cap on returned entries (default: unbounded). */
    topK?: number;
    /** Override "now" for deterministic tests. */
    now?: () => number;
}
export interface ScoreComponents {
    cosine: number;
    recency: number;
    importance: number;
}
export interface ScoredEntry<T> {
    entry: T;
    score: number;
    components: ScoreComponents;
}
export interface RrfScorers<T> {
    /** Cosine similarity ∈ [-1, 1] — non-finite values clamped to 0. */
    cosine: (entry: T) => number;
    /** Timestamp (ms epoch) used for recency decay. Negative → drop the entry. */
    timestamp: (entry: T) => number;
    /** Salience ∈ [0, 1]. Out-of-range values clamped. */
    importance: (entry: T) => number;
}
/**
 * Cosine similarity between two equal-length numeric vectors.
 *
 * Returns 0 if either vector is empty / zero-norm / mismatched length —
 * never throws. This makes the function safe to compose into scorers that
 * may receive partial entries.
 */
export declare function cosineSimilarity(a: number[], b: number[]): number;
/**
 * Recency score in [0, 1]: exp(-ln(2) · Δt / halflife).
 *   - 1.0 at Δt = 0
 *   - 0.5 at Δt = halflife
 *   - approaches 0 as Δt → ∞
 *
 * `nowMs` and `timestampMs` are epoch ms. Future timestamps (Δt < 0) clamp
 * to 1.0 (treated as "right now").
 */
export declare function recencyScore(nowMs: number, timestampMs: number, halflifeMs: number): number;
/**
 * Score a batch of entries via the weighted combination. The result is sorted
 * by descending score and trimmed to `topK` when set.
 *
 * Negative timestamps (per `scorers.timestamp`) cause the entry to be dropped
 * entirely — this is the cheap way for a scorer to signal "skip" (e.g. row
 * lacks the field).
 */
export declare function scoreEntries<T>(entries: T[], scorers: RrfScorers<T>, opts?: RrfOptions): ScoredEntry<T>[];
/**
 * The agent-sdk EpisodicMemoryEntry does NOT carry an embedding column —
 * embeddings live in the storage layer (Postgres pgvector). To enable
 * pluggable cosine scoring, the caller may attach an embedding via the
 * `embedding` field on `metadata`, or supply a custom resolver.
 */
export type EpisodicCosineFn = (entry: EpisodicMemoryEntry) => number;
export interface RecallRrfOptions extends RrfOptions {
    /**
     * Cosine scorer — defaults to 0 (no embedding). Provide when you have a
     * pre-computed (entry × query) similarity for each entry.
     */
    cosine?: EpisodicCosineFn;
}
/**
 * Rank EpisodicMemoryEntry[] by weighted score. Convenience over scoreEntries
 * with the standard projection (timestamp = entry.timestamp,
 * importance = metadata.importance ?? 0.5).
 */
export declare function recallEpisodicRrf(entries: EpisodicMemoryEntry[], opts?: RecallRrfOptions): ScoredEntry<EpisodicMemoryEntry>[];
//# sourceMappingURL=episodic-rrf.d.ts.map