import type { Id } from '../../resources/ResourceInterface.ts';
/**
 * Represents a Hierarchical Navigable Small World (HNSW) index for approximate nearest neighbor search.
 * This implementation is based on hierarchical graph navigation to efficiently index and search high-dimensional vectors.
 * A HNSW is basically a multi-dimensional skip list. Each node has (potentially) higher levels that are used for quickly
 * traversing the graph get in the neighborhood of the node, and then lower levels are used to more accurately find the
 * closest neighbors.
 *
 * This implementation is based on the paper "Efficient and Robust Approximate Nearest Neighbor Search in High Dimensions"
 * (mostly influenced AI's contributions)
 */
export declare class HierarchicalNavigableSmallWorld {
    static useObjectStore: boolean;
    static searchOnlyOptions: string[];
    indexStore: any;
    M: number;
    efConstruction: number;
    efConstructionSearch: number;
    mL: number;
    optimizeRouting: number;
    nodesVisitedCount: number;
    idIncrementer: BigInt64Array | undefined;
    distance: (a: number[], b: number[]) => number;
    int8: boolean;
    efSearchConfigured: boolean;
    private convertedNodes;
    constructor(indexStore: any, options: any);
    index(primaryKey: Id, vector: number[], existingVector?: number[], options?: any): void;
    private safeGetSync;
    private getEntryPoint;
    /**
     * Search one layer of the skip-list using HNSW algorithm for creating a candidate list and navigating the graph
     * TODO: This should be async, but we can't really do that with lmdb-js's transaction system right now. Should be
     * doable with RocksDB. We could also create an async version for searching.
     * @param queryVector
     * @param entryPointId
     * @param entryPoint
     * @param ef
     * @param level
     * @param distanceFunction
     * @param options
     * @private
     */
    private searchLayer;
    /**
     * This the main entry from Harper's query functionality, where we actually search for an ordered list of nearest
     * neighbors, using the provided sort/order definition object and performing the multi-layer skip-list search.
     * This returns an iterable of the nearest neighbors to the provided target vector, with nearest ordered first.
     * @param target
     * @param value
     * @param descending
     * @param distance
     * @param comparator
     * @param context
     */
    search({ target, value, descending, distance, comparator, ef, }: {
        target: number[];
        value: number;
        descending: boolean;
        distance: string;
        comparator: string;
        ef?: number;
    }, context: any): {
        key: string;
        distance: number;
    }[];
    /**
     * Exact distance between a query and a record's FULL-precision vector, mirroring search()'s metric
     * selection. Used to rerank quantized (int8) results: graph traversal navigates on approximate
     * (quantized) distances, but the caller has the exact record vector and can restore exact ordering
     * and $distance.
     */
    exactDistance(searchCondition: {
        target: number[];
        distance?: string;
    }, recordVector: number[] | Int8Array): number;
    /**
     * Post-load rescoring hook called by search.ts after full records have been loaded.
     * Handles two quantized (int8) cases:
     *   - 'sort': recompute exact distances and re-sort for correct nearest-neighbor ordering.
     *   - 'lt'/'le': recompute exact distances and re-filter by the threshold value (over-fetch
     *     was applied before the search to ensure enough candidates).
     * Returns null when rescoring doesn't apply so the caller uses the loaded iterable as-is.
     */
    rescoreResults(loaded: any[], searchCondition: {
        target: number[];
        distance?: string;
        value?: any;
    }, comparator: string, attributeName: string): any[] | null;
    private checkSymmetry;
    private addConnection;
    validateConnectivity(startLevel?: number): {
        isFullyConnected: boolean;
        averageConnections: number;
    };
    get totalNodes(): number;
    /**
     * This is used by the query planner to determine what order to apply conditions. It is our best guess at an estimated count.
     * This unit is typically the number of records that need to be accessed to satisfy the query. We know that we will visit
     * a minimum of efConstructionSearch nodes and a maximum of the total nodes (in absolute worst case).
     * The original paper described the complexity as polylogarithmic. From my testing, the
     * best and simplest guess at the number of nodes that need to be accessed is the geometric mean of the total number of nodes
     * and the efConstruction parameter (for search), which clearly constrains the estimate to the correct range and is
     * similar to polylogarithmic for realistic values.
     *
     * @returns
     */
    estimateCountAsSort(): number;
    /**
     * This is used to resolve the vector property, which should be resolved to the distance when used in a sort comparator
     * We also want to cache distance calculations so they can be accessed efficently later
     * @param vector
     * @param context
     * @param entry
     */
    propertyResolver(vector: number[], context: any, entry: any): any;
}
