/**
 * provider.ts - Embedding provider abstraction
 *
 * Production embeddings use a commercial OpenAI-compatible API. The `local`
 * kind remains readable only for historical config and is rejected by the factory.
 *
 * The factory in `./factory.ts` selects an implementation based on env vars,
 * a CLI flag, or `~/.config/qmd/config.json`.
 */
/**
 * Single embedding result
 */
export type ProviderEmbedding = {
    embedding: number[];
    /** Model identifier used to produce this embedding (matches content_vectors.model in DB) */
    model: string;
};
/**
 * Supported provider kinds
 */
export type ProviderKind = "local" | "openai";
/**
 * Healthcheck result for provider startup verification
 */
export type ProviderHealth = {
    ok: boolean;
    /** Model identifier reported by the provider */
    model: string;
    /** Embedding dimensions (e.g. 768 for embeddinggemma-300M) */
    dimensions?: number;
    /** Detail message (error reason on failure, status on success) */
    detail?: string;
};
/**
 * Per-call options for provider embedding
 */
export type ProviderEmbedOptions = {
    /** Optional model id override (rare; usually provider has a fixed model) */
    model?: string;
    /** Abort signal for cancellation / timeout */
    signal?: AbortSignal;
};
/**
 * Provider interface for commercial embedding adapters and historical readers.
 *
 * Implementations MUST:
 *   - Return `null` (not throw) for individual texts that fail to embed;
 *     the caller will count it as an error and continue.
 *   - Honor `options.signal` for cancellation.
 *   - Be safe to call concurrently for `embedBatch`.
 */
export interface EmbeddingProvider {
    /** Provider kind tag — useful for logging and factory introspection */
    readonly kind: ProviderKind;
    /**
     * Stable model identifier reported to the caller.
     *
     * MUST match what's stored in `content_vectors.model` for the existing
     * index — otherwise the model-id guard refuses to embed.
     */
    getModelId(): string;
    /**
     * Embedding vector dimensions. May return `undefined` before the first call
     * (some providers probe lazily). Once known, MUST stay stable.
     */
    getDimensions(): number | undefined;
    /**
     * Healthcheck — verifies the provider is reachable and the model is loaded.
     * Should NOT throw — return `{ ok: false, detail: ... }` on failure.
     *
     * For HTTP providers: ping `/health` endpoint.
     */
    healthcheck(signal?: AbortSignal): Promise<ProviderHealth>;
    /**
     * Embed a single text. Returns `null` on per-call failure.
     */
    embed(text: string, options?: ProviderEmbedOptions): Promise<ProviderEmbedding | null>;
    /**
     * Embed multiple texts in a batch (more efficient than calling `embed` N times).
     *
     * Output array length MUST equal input array length. Failed entries are `null`.
     * Implementations are responsible for chunking large batches per their
     * upstream limits (e.g. OpenAI provider chunks to 64).
     */
    embedBatch(texts: string[], options?: ProviderEmbedOptions): Promise<(ProviderEmbedding | null)[]>;
    /**
     * Optional: most recent error message from a swallowed per-chunk failure.
     *
     * Per-chunk errors are intentionally swallowed (slot becomes `null`) so a
     * single bad text does not abort a 1000-doc embed run. Callers that need
     * to surface a meaningful error (e.g. the dimension-probe call site in
     * `store.ts` when even the first chunk fails) can read this field to
     * include the underlying cause (HTTP status, malformed JSON, timeout,
     * abort reason, …) in their own error message.
     *
     * Returns `undefined` when the most recent call succeeded or no call has
     * happened yet. Implementations MUST clear it on success.
     *
     * Optional so 3rd-party `EmbeddingProvider` implementations remain source-
     * compatible; callers must guard with `provider.getLastError?.()`.
     */
    getLastError?(): string | undefined;
    /** Release any held resources (HTTP keep-alive sockets, model handles, …) */
    dispose(): Promise<void>;
}
/**
 * Error thrown when the provider's reported model id does not match the
 * model id baked into existing `content_vectors` rows. Forces user to
 * re-embed (`qmd embed -f`) or pin the matching model id.
 */
export declare class ModelMismatchError extends Error {
    readonly providerModel: string;
    readonly existingModels: string[];
    constructor(providerModel: string, existingModels: string[]);
}
/**
 * Verify that the provider's model id is compatible with the existing
 * `content_vectors` entries. Pass-through (no-op) if the table is empty
 * (fresh DB) or if the model id appears in the distinct set.
 *
 * Caller passes `existingModels` (typically result of
 * `SELECT DISTINCT model FROM content_vectors`).
 */
export declare function assertModelCompatible(providerModel: string, existingModels: string[]): void;
