/**
 * EmbeddingProvider — Shared local embedding service using Transformers.js (ONNX).
 *
 * Loads all-MiniLM-L6-v2 (384-dim) once and provides embeddings to any memory
 * system (SemanticMemory, MemoryIndex, TopicMemory). Also handles loading the
 * sqlite-vec extension into better-sqlite3 connections.
 *
 * Design decisions:
 *   - Singleton: Model (~80MB) is loaded once, shared across all consumers
 *   - Lazy init: Model downloads on first embed() call, not on construction
 *   - Graceful degradation: If model fails to load, embed() throws but callers
 *     can catch and fall back to FTS5-only search
 *   - Batch support: embedBatch() is more efficient than sequential embed() calls
 */
type Database = import('better-sqlite3').Database;
/**
 * ONNX Runtime session options for the embedding pipeline. Caps the intra/inter-op
 * thread pools to 1: all-MiniLM-L6 is tiny and memory embeds are sporadic, so one
 * thread is plenty — and it stops the multi-thread ORT pool from busy-spinning
 * ~50% of a core while the model sits RESIDENT between embeds. This is the
 * fleet-wide idle-CPU root (task #17): profiled on a live agent server, the
 * default (unbounded) pool kept ~6 extra threads busy-spinning; verified via a
 * thread-count probe that this cap drops the resident pool (18→12 threads) with
 * identical 384-dim output. The existing idle-unload only helps a truly-idle
 * agent; this fixes the resident case (semantic-search queries re-arm the timer).
 */
export declare const ONNX_SESSION_OPTIONS: {
    readonly intraOpNumThreads: 1;
    readonly interOpNumThreads: 1;
};
export interface EmbeddingProviderConfig {
    /** Model name for @huggingface/transformers (default: 'Xenova/all-MiniLM-L6-v2') */
    modelName?: string;
    /** Embedding dimension (default: 384 for all-MiniLM-L6-v2) */
    dimensions?: number;
    /** Maximum text length to embed in characters (default: 8192) */
    maxTextLength?: number;
    /**
     * Idle-unload window in ms. After this long with no embed() call, the loaded
     * ONNX pipeline is disposed to free its thread pool, which busy-spins even
     * when idle (measured: ~3.6% of a core on a quiet box, up to ~44% on a
     * contended one — pure waste while an agent isn't doing memory work). The
     * next embed() lazily reloads (~1-3s, verified-identical output). Default
     * 300000 (5 min). Set 0 to disable (keep the model resident forever — the
     * prior behavior).
     */
    idleUnloadMs?: number;
    /**
     * Test/advanced seam: factory that produces the feature-extraction pipeline.
     * Defaults to the real `@huggingface/transformers` import. Tests inject a mock
     * (a callable with a `dispose()`) to exercise the idle-unload lifecycle
     * without loading the 80MB model.
     */
    pipelineFactory?: (modelName: string) => Promise<any>;
}
export declare class EmbeddingProvider {
    private pipeline;
    private loading;
    private readonly modelName;
    readonly dimensions: number;
    private readonly maxTextLength;
    private readonly idleUnloadMs;
    private readonly pipelineFactory?;
    private vecExtensionLoaded;
    /** In-flight embed() calls — the idle-unload timer never disposes while > 0. */
    private inFlight;
    /** Rolling idle-unload timer (reset on every embed); unref'd so it can't keep the process alive. */
    private idleTimer;
    constructor(config?: EmbeddingProviderConfig);
    /**
     * Ensure the model is loaded. Safe to call multiple times — only loads once.
     */
    initialize(): Promise<void>;
    private loadModel;
    /**
     * Whether the model is loaded and ready for embedding.
     */
    get isReady(): boolean;
    /**
     * Arm (or re-arm) the rolling idle-unload timer. Called after every embed so
     * the window restarts on each use — an actively-embedding agent keeps the
     * model resident; one that goes quiet for `idleUnloadMs` unloads it.
     */
    private scheduleIdleUnload;
    /**
     * Dispose the loaded pipeline if it's idle — frees the ONNX thread pool that
     * busy-spins even when no embedding is happening. Guarded on inFlight so a
     * long-running batch that outlasts the window is never disposed mid-flight;
     * its completion re-arms the timer.
     */
    private maybeUnload;
    /**
     * Explicitly release the model + cancel the idle timer (shutdown / tests).
     * Idempotent.
     */
    dispose(): Promise<void>;
    /**
     * Generate a normalized embedding for a single text string.
     * Lazy-initializes the model on first call.
     */
    embed(text: string): Promise<Float32Array>;
    /**
     * Generate normalized embeddings for multiple texts.
     * More efficient than sequential embed() calls for large batches.
     */
    embedBatch(texts: string[]): Promise<Float32Array[]>;
    /**
     * Load the sqlite-vec extension into a better-sqlite3 database connection.
     * Safe to call multiple times on the same connection — tracks loaded state.
     *
     * @returns true if loaded successfully, false if sqlite-vec unavailable
     */
    loadVecExtension(db: Database): boolean;
    private _sqliteVecModule;
    /**
     * Pre-load the sqlite-vec module. Must be called before loadVecExtension().
     * Safe to call multiple times — only loads once.
     *
     * @returns true if sqlite-vec is available, false if not installed
     */
    loadVecModule(): Promise<boolean>;
    /**
     * Serialize a Float32Array to a Buffer for sqlite-vec storage.
     * sqlite-vec expects embeddings as raw binary blobs.
     */
    static toBuffer(embedding: Float32Array): Buffer;
    /**
     * Deserialize a Buffer back to a Float32Array.
     */
    static fromBuffer(buffer: Buffer): Float32Array;
    /**
     * Compute cosine similarity between two embeddings.
     * Assumes both are already L2-normalized (as produced by embed()).
     */
    static cosineSimilarity(a: Float32Array, b: Float32Array): number;
}
export {};
//# sourceMappingURL=EmbeddingProvider.d.ts.map