/**
 * ADR-121 Phase 8 — `AnnRouter` composition layer.
 *
 * The package now ships three ANN backings, each with a different
 * sweet spot:
 *
 *   `SearchableEmbeddingCache` (HNSW + `@ruvector/core`)
 *     - in-memory, streaming insert + delete, ANN search
 *     - sweet spot: <100k vectors, frequently mutated, low-latency
 *
 *   `RabitqSnapshot` (1-bit quantization + `@ruvector/rabitq-wasm`)
 *     - in-memory, batch-build only, 32× memory reduction with
 *       exact-L2² rerank
 *     - sweet spot: 100k-1M vectors, mostly read, memory-tight
 *
 *   `DiskannSnapshot` (DiskANN/Vamana + `@ruvector/diskann`)
 *     - on-disk via `storagePath`, batch-build (with streaming insert
 *       before build), survives process restarts
 *     - sweet spot: >1M vectors, persistent, agent-fleet-scale
 *
 * Choosing between them requires understanding the workload —
 * something a downstream caller often doesn't want to think about.
 * `AnnRouter` takes a workload descriptor (`{ corpusSize, persistent,
 * mutable }`) and routes to the right backing automatically, behind a
 * single unified `search(query, k)` interface.
 *
 * Routing rules (documented + enumerable, see `decideBacking()`):
 *
 *   persistent=true              → DiskANN (only on-disk option)
 *   corpusSize ≥ 1_000_000       → DiskANN (memory pressure)
 *   corpusSize ≥ 100_000 + !mutable → RaBitQ (batch, compressed)
 *   default (small, mutable, in-RAM)→ HNSW cache
 *
 * When the preferred backing's peer dep isn't installed, the router
 * falls back to the next-best available one and reports `degraded:
 * true` + a `degradationReason`. Operators always get *something*
 * that works (even if it's the linear-scan fallback inside the HNSW
 * cache) rather than a hard failure.
 */
export type AnnBacking = 'hnsw' | 'rabitq' | 'diskann';
export interface AnnRouterWorkload {
    /** Approximate corpus size (vectors). Used for the routing decision. */
    readonly corpusSize: number;
    /** Embedding dimension. Required. */
    readonly dimension: number;
    /**
     * Will the corpus need to survive process restarts? When true,
     * forces DiskANN regardless of size.
     */
    readonly persistent?: boolean;
    /**
     * Will the corpus be mutated after the initial batch (streaming
     * inserts, deletes)? When true, prefers HNSW over RaBitQ/DiskANN
     * (those are batch-build).
     */
    readonly mutable?: boolean;
    /**
     * On-disk storage path. Required when `persistent: true`. The
     * snapshot lives at this path and can be reopened via
     * `AnnRouter.load(workload)`.
     */
    readonly storagePath?: string;
}
export interface AnnRouterHit {
    readonly id: string;
    /** Similarity-style score in [0, 1] for HNSW, raw distance for the snapshot backings. Lower-better unless via HNSW. */
    readonly score: number;
    /** Original vector when the backing returns it (HNSW does, snapshot backings don't always). */
    readonly vector?: Float32Array;
}
export interface AnnRouterDecision {
    /** Backing selected by `decideBacking`. */
    readonly backing: AnnBacking;
    /** Free-form rationale — useful for logs + the routing smoke. */
    readonly reason: string;
    /** Was a fallback used because the preferred backing wasn't available? */
    readonly degraded: boolean;
    /** When `degraded`, why the preferred backing was unavailable. */
    readonly degradationReason?: string;
}
/**
 * Pure function exposing the routing decision. Doesn't actually
 * instantiate anything — useful for previewing what `AnnRouter.create`
 * would do, and for tests that assert routing without booting NAPI.
 */
export declare function decideBacking(workload: AnnRouterWorkload): {
    backing: AnnBacking;
    reason: string;
};
/**
 * Unified ANN-router handle. Always exposes the same `add`/`build`/
 * `search` surface regardless of which backing is live. Callers can
 * inspect `decision` to see what was picked + why.
 */
export declare class AnnRouter {
    readonly decision: AnnRouterDecision;
    private readonly workload;
    private hnsw;
    private rabitq;
    private diskann;
    private pending;
    private constructor();
    /**
     * Pick a backing, instantiate it, return the handle. The router
     * never throws on missing peer deps — it falls back to a less-
     * preferred backing and reports `degraded: true`.
     */
    static create(workload: AnnRouterWorkload): Promise<AnnRouter>;
    /**
     * Insert vectors. For HNSW this is immediate. For RaBitQ this
     * buffers until `build()`. For DiskANN this calls `add()` on the
     * underlying snapshot (also requires `build()` before search).
     */
    add(entries: ReadonlyArray<{
        id: string;
        vector: Float32Array;
    }>): Promise<void>;
    /**
     * Build the index. No-op for HNSW (streaming); required for
     * RaBitQ + DiskANN before the first `search`.
     */
    build(): Promise<void>;
    /**
     * Search the active backing. Always returns `AnnRouterHit[]` sorted
     * such that the more-relevant result comes first — HNSW returns
     * similarity-descending; RaBitQ + DiskANN return distance-ascending
     * (the lower the score, the better the match). Consumers reading
     * `score` should interpret it relative to `decision.backing`.
     */
    search(query: Float32Array, k: number): Promise<AnnRouterHit[]>;
    /**
     * Current vector count. Differs slightly by backing (HNSW returns
     * cache size; RaBitQ returns batch size; DiskANN includes tombstones).
     */
    count(): number;
    /**
     * Persist the snapshot. Only meaningful for DiskANN (the other
     * backings are in-memory). No-op + returns false otherwise.
     */
    save(): boolean;
}
//# sourceMappingURL=ann-router.d.ts.map