/** * Pluggable embedding providers for Hippo. * * The local `@huggingface/transformers` path stays the zero-DEPENDENCY DEFAULT. Opt-in * API providers (OpenAI / Voyage / Cohere) let a user bring a frontier embedder * (e.g. text-embedding-3-large) for frontier-class retrieval. They use the native * `fetch` global (Node >= 22.5, see package.json engines — NO new dependency) and * read their key from a conventional env var. The provider is selected by * `config.embeddings.provider` (default `'local'`). * * Design contract (see docs/plans/2026-06-08-b-pluggable-embedding-provider.md): * - Local provider `id` is the BARE model string. (Historical note: this * originally guaranteed NO identity change on upgrade; since the * embed-text-format versioning in embeddings.ts (`embeddingIndexIdentity`, * `${id}#t2`, docs/plans/2026-07-09-recall-determinism.md T1), the STORED * identity carries a `#t` suffix and pre-#t2 stores get exactly one * forced reindex on their next embed-touching operation — deliberate, * because their vectors were computed over path-contaminated text.) * - API provider `id` is `${kind}:${model}`; switching to/from an API embedder * (or a dimension change) flips the identity and triggers the existing * reindex-on-change path. * - `resolveEmbeddingProvider` NEVER throws. `isAvailable()` is provider-aware * (local -> dependency installed; api -> key present). `embed()` MAY throw on * a hard transport/auth failure so a reindex can abort atomically; hot paths * wrap it and fall back to BM25. * * The exact request/response shapes for the API providers are documented from each * vendor's public embeddings API; they are unit-tested here against a mocked * `fetch` and are integration-verified in Workstream C (real API calls are * egress-blocked in the build sandbox). */ import { type EmbeddingRole } from './embeddings.js'; export type EmbeddingProviderKind = 'local' | 'openai' | 'voyage' | 'cohere'; export declare const API_PROVIDER_KINDS: readonly EmbeddingProviderKind[]; export interface EmbeddingProvider { readonly kind: EmbeddingProviderKind; readonly model: string; /** * Identity recorded in DB meta to drive reindex-on-change. * local -> bare model string (back-compat); api -> `${kind}:${model}`. */ readonly id: string; /** Known fixed output dimension, if any (undefined for local / unknown). */ readonly dimensions?: number; /** Env var holding this provider's API key (undefined for the local provider). */ readonly keyEnv?: string; /** local -> dependency installed; api -> key present. NEVER throws. */ isAvailable(): boolean; /** * Batch-embed. Returns one row per input in order; a row is `[]` when that * single item could not be embedded. MAY throw on a hard transport/auth * failure (so a reindex aborts before saving a partial index). */ embed(texts: string[], role?: EmbeddingRole): Promise; } export interface ResolveProviderOptions { /** Explicit model override (mirrors resolveEmbeddingModel's explicitModel). */ model?: string; /** Explicit provider override (mainly for tests). */ provider?: EmbeddingProviderKind; } /** * Build the active embedding provider from config (or an explicit override). * Never throws for a missing key — that surfaces via `isAvailable()` on the hot * paths and as a hard error only from the explicit `hippo embed` command. The * only hard throw is an invalid config (e.g. an insecure apiBaseUrl), a * deliberate loud failure; hot-path callers (search) wrap this in try/catch. */ export declare function resolveEmbeddingProvider(hippoRoot: string, opts?: ResolveProviderOptions): EmbeddingProvider; /** * The reindex identity for the active provider. Use this (NOT resolveEmbeddingModel) * everywhere `embeddingModelRequiresReindex` / stored-model comparisons happen. */ export declare function resolveEmbeddingIdentity(hippoRoot: string, opts?: ResolveProviderOptions): string; /** * Provider-aware availability for a store: local -> dependency installed; * api -> key present. Use at the call sites that decide whether to embed. */ export declare function isEmbeddingConfigured(hippoRoot: string): boolean; //# sourceMappingURL=embedding-provider.d.ts.map