/** * Embedder resolution — the single provider-selection path shared by every * consumer (analyze, watch, orient, search_code, search_specs, generate, view). * * Kept in its own module (separate from `embedding-service.ts`) so the remote * `EmbeddingService` can be unit-mocked without also having to stub this shared * logic: `resolveEmbedder` calls the real (or mocked) `EmbeddingService` * internally, so a mock of `fromEnv`/`fromConfig` continues to drive it. */ import type { Embedder } from './embedding-service.js'; import type { OpenLoreConfig } from '../../types/index.js'; /** Honest, served retrieval mode — first-class keyword default or a semantic upgrade. */ export type RetrievalMode = 'keyword' | 'keyword+vocabulary' | 'local-semantic' | 'remote-semantic'; export declare function isKeywordRetrievalMode(mode: RetrievalMode | string): boolean; /** * The optional semantic upgrade, phrased for a human. Printed only by `openlore status` * and `openlore doctor`; agent payloads report `retrievalMode` and never carry it * (spec `config` RetrievalUpgradeHintsAreForHumans). */ export declare const SEMANTIC_UPGRADE_HINT = "optional: \"openlore embed --local\" adds on-device semantic ranking (no API key)"; /** * Resolve the active embedder from environment and config, in priority order: * 1. config `embedding.provider: 'local'` → on-device {@link LocalEmbeddingService} * (an explicit, just-written intent — e.g. `openlore embed --local` — wins over * ambient `EMBED_*` env so the command is never silently overridden) * 2. `EMBED_*` environment variables (remote OpenAI-compatible endpoint) * 3. config remote endpoint (`embedding.baseUrl` + `embedding.model`) * Returns null when nothing is configured — the first-class keyword (BM25) * default, never an error. Sharing one resolver means the configured provider is * honoured identically at build time and query time. * * Dependencies are imported dynamically (matching the rest of the codebase) so * the remote `EmbeddingService` stays unit-mockable via `vi.doMock`. */ export declare function resolveEmbedder(cfg?: OpenLoreConfig | null, /** * The analysis directory being queried. Given, an unconfigured repository whose index * carries background-built local vectors resolves to the local embedder that built them. */ outputDir?: string): Promise; /** * May OpenLore add local vectors in the background (change: * enable-local-semantic-search-in-background)? Only when the repository names no provider * at all: `embedding.provider: "none"`, `embed --off` (a `null` block) and any configured * provider each decide for themselves. */ export declare function backgroundSemanticAllowed(cfg?: OpenLoreConfig | null): boolean; /** True when the optional on-device embedder package can be loaded. Resolves, never imports. */ export declare function localEmbedderInstalled(): boolean; /** Does the code index carry vectors a local model built? */ export declare function indexCarriesLocalVectors(outputDir: string): boolean; /** * The retrieval mode implied by the active embedder: `keyword` when there is no * embedder, otherwise `local-semantic` / `remote-semantic` per its origin * (local-provider model names are prefixed `local:`). Used for honest, low-noise * mode reporting in query handlers and CLI summaries. */ export declare function embedderMode(embedSvc: Embedder | null | undefined): RetrievalMode; /** * Does the on-disk index for `outputDir` carry vectors? The capability the index * REALIZED, as opposed to the one its configuration asks for. */ export declare function indexCarriesVectors(outputDir: string, kind?: 'code' | 'spec'): boolean; /** * Is a semantic provider configured for this repository? Mirrors `resolveEmbedder`'s * priority order (explicit local provider, then `EMBED_*`, then a config endpoint) but * answers from configuration ALONE — it constructs no service, downloads no weights and * opens no socket, so it is safe on a hot path such as the index-reuse gate. * * This is "what was asked for". Pair it with {@link indexCarriesVectors} ("what was * produced") to detect a configured-but-unrealized semantic index. */ export declare function semanticProviderConfigured(cfg?: OpenLoreConfig | null): boolean; /** Whether the realized index agrees with the configured provider, and how it disagrees. */ export type IndexCapabilityAgreement = /** Configuration and index agree — both semantic, or both keyword. */ { agrees: true; } /** A provider is configured, but the index carries no vectors: the ask never happened. */ | { agrees: false; mismatch: 'configured-but-unrealized'; } /** The index carries vectors no configured provider can query. */ | { agrees: false; mismatch: 'vectors-without-provider'; }; /** * Compare what the configuration asks for against what the index realized. * * Deliberately NOT a timestamp comparison: a build that silently fell back to a * keyword index is as recent as a successful one, so only the index's own recorded * capability can tell the two apart (spec `analyzer` * IndexReuseRequiresCapabilityAgreement). */ export declare function indexCapabilityAgreement(cfg: OpenLoreConfig | null | undefined, outputDir: string, kind?: 'code' | 'spec'): IndexCapabilityAgreement; /** * The retrieval mode actually SERVED for a query — honest about what the index can * do, not just what is configured. Returns `keyword` whenever no embedder is * resolved OR the on-disk index has no vectors (e.g. it was built keyword-only, or * a local build fell back after a missing optional dependency), even if config * still names a semantic provider. `kind` selects which index sidecar to consult. */ export declare function servedRetrievalMode(embedSvc: Embedder | null | undefined, outputDir: string, kind?: 'code' | 'spec', vocabularyExpansion?: boolean): RetrievalMode; //# sourceMappingURL=embedder.d.ts.map