/**
 * Embedding-retrieval fast-path for pre-call tool routing (ITEM B / L2).
 *
 * For large tool catalogs, ranking by semantic similarity is far cheaper than
 * an LLM router call and benchmarks at sub-10 ms when embedding vectors are
 * cached. This module is intentionally PURE with no provider imports: the
 * caller injects an `embedFn` so the retriever stays testable and free of
 * circular dependencies.
 *
 * Hybrid scoring formula:
 *   score = weights.cosine * cosineSimilarity(queryVec, toolVec)
 *         + weights.bm25   * bm25Score(query, toolText)
 *
 * Both components are independently normalized to [0, 1] before combination
 * so neither scale dominates.
 *
 * Fail-safe contract:
 *   `ToolEmbeddingIndex.rank()` and `selectRelevantToolNames()` propagate any
 *   error thrown by the injected `embedFn`. The CALLER (tool-routing
 *   orchestration) is responsible for catching that error and degrading
 *   gracefully to the LLM-router / server-granularity path.
 *
 * Determinism:
 *   All public functions are deterministic given the same inputs and embedFn.
 *   No Math.random(), no argless Date, no global mutable state outside the
 *   instance-level vector cache (which is keyed by text content).
 */
import type { ToolRetrievalItem, ToolRetrievalRankedResult, ToolRetrievalSelectOptions, ToolRetrievalWeights } from "../types/index.js";
/**
 * Cosine similarity between two vectors.
 *
 * Returns 0 when either vector is zero-length, has zero magnitude, or the
 * lengths differ — all of which indicate the comparison is meaningless.
 */
export declare function cosineSimilarity(a: number[], b: number[]): number;
/**
 * An in-process index that ranks tool catalog items by hybrid semantic +
 * lexical relevance to a query.
 *
 * Embedding vectors for tool descriptions are computed lazily on the first
 * `rank()` call and cached by description text, so subsequent turns that
 * share the same catalog pay only the cost of embedding the query itself.
 *
 * ### Fail-safe
 * Any error thrown by `embedFn` propagates out of `rank()`. The CALLER must
 * catch it and degrade to the LLM-router path; `ToolEmbeddingIndex` itself
 * never silently swallows embedFn errors.
 *
 * ### Thread-safety
 * The internal cache is a plain `Map`. Node.js is single-threaded so there
 * are no data races, but if the same index instance is used concurrently
 * (e.g. two turns in parallel) both calls will race to populate the cache;
 * the last writer wins (same content either way because `embedFn` is
 * deterministic for a given text).
 */
export declare class ToolEmbeddingIndex {
    private readonly items;
    private readonly embedFn;
    private bm25CorpusCache?;
    /**
     * Cached embedding vectors keyed by the item's `text` field.
     * Populated on first `rank()` call for texts not yet seen.
     *
     * Callers can share a single Map across multiple index instances (e.g.
     * across turns in the same NeuroLink session) so tool vectors are computed
     * once and reused. Pass the shared Map via the constructor's third argument.
     */
    private readonly vectorCache;
    constructor(items: ToolRetrievalItem[], embedFn: (texts: string[]) => Promise<number[][]>, 
    /**
     * Optional shared vector cache. When supplied, cached vectors from
     * previous turns are reused and any newly-computed vectors are stored
     * into this same Map, making it warm for the next call.
     */
    sharedVectorCache?: Map<string, number[]>);
    /**
     * Returns the top-K catalog items ranked by hybrid score descending.
     *
     * @throws If `embedFn` throws — propagated verbatim so the caller can fail
     *   open. No wrapping, no swallowing.
     */
    rank(query: string, opts: {
        topK: number;
        weights?: ToolRetrievalWeights;
        timeoutMs?: number;
    }): Promise<ToolRetrievalRankedResult[]>;
}
/**
 * Selects the most relevant tool names from a catalog given a query.
 *
 * Creates a temporary `ToolEmbeddingIndex`, runs `rank()`, and returns just
 * the tool names. Use `ToolEmbeddingIndex` directly when you want to reuse
 * cached tool vectors across multiple queries (e.g. multiple turns with the
 * same catalog).
 *
 * @throws If `opts.embedFn` throws — propagated so the caller can degrade to
 *   the LLM-router path.
 *
 * @example
 * ```ts
 * const tools = await selectRelevantToolNames(
 *   "show me yesterday's sales",
 *   catalog.flatMap(server => server.toolNames.map(name => ({
 *     name,
 *     text: `${server.description} — ${name}`,
 *   }))),
 *   { topK: 5, embedFn: myEmbedFn },
 * );
 * // => ["analytics_getSales", "analytics_getRevenue", ...]
 * ```
 */
export declare function selectRelevantToolNames(query: string, items: ToolRetrievalItem[], opts: ToolRetrievalSelectOptions): Promise<string[]>;
