/**
 * Asset Index Service — the live, in-process drain for image captioning and
 * document-sidecar extraction.
 *
 * P3b shipped the derive/persist/migration logic (`sweepAssetIndex`) but wired
 * it only to a one-shot boot pass. On a long-lived server (Railway tenants run
 * for days/weeks) that meant a freshly-uploaded image stayed filename-only —
 * not content-searchable — until the next restart. This service closes that gap
 * the same way `SessionManager` closes the commit-batching gap: a long-lived
 * object with a periodic timer, an `enqueue()` the upload paths call, a
 * crash-resilient persisted queue, and a `recoverOnBoot()` that drains anything
 * left unfinished.
 *
 * Shape (mirrors SessionManager deliberately so the lifecycle is familiar):
 *  - `enqueue(assetId)` — fired by VectorService.onAssetPending the moment an
 *    indexable IMAGE assets.db row is seeded `pending` (every image-upload path
 *    funnels through ensureInitialAssetIndexState). Just records the assetId.
 *  - periodic `setInterval` tick — drains the queued ids through
 *    `sweepAssetIndex({ onlyAssets })`, bounded + gated exactly as the boot pass.
 *    Idle when the queue is empty, so an idle server does zero vision work.
 *  - persisted queue (`pending-asset-index.json`, atomic tmp+rename) — survives
 *    a crash; `recoverOnBoot()` replays it AND runs the full unfiltered sweep
 *    (which re-derives anything missing/stale in LanceDB regardless of the
 *    queue), so nothing is lost even if the process died mid-drain.
 *  - `shutdown()` — drains what's queued, then tears down the timer.
 *
 * Config (caption model, the `captioning.enabled` gate, the repo list) is
 * resolved FRESH each tick via the injected `resolveConfig` thunk, so flipping
 * the model or the gate in Settings takes effect without a restart — the same
 * live-resolution property VectorService already has for the Voyage key.
 */
import { type SweepWorkspaceManager, type AssetIndexSweepResult } from '../services/asset-index-sweep.js';
import type { CaptionModelConfig, CaptionCompleteFn } from '../services/asset-caption-service.js';
/** Per-tick configuration, resolved fresh so Settings changes take effect live. */
export interface AssetIndexConfig {
    repos: Array<{
        name: string;
        path?: string;
    }>;
    captionConfig: CaptionModelConfig | null;
    captioningEnabled: boolean;
}
export interface AssetIndexQueueDeps {
    workspaceManager: SweepWorkspaceManager & {
        getWorkspacePath(): string;
    };
    /** Resolve the live config each drain (model/key/gate/repos). */
    resolveConfig: () => AssetIndexConfig;
    /** Drain cadence. Default 15s. */
    intervalMs?: number;
    /** Bounded fan-out per drain. Default 2 (vision is metered). */
    concurrency?: number;
    log?: (msg: string) => void;
    /** Test seam: inject the vision model call used during a drain. */
    completeFn?: CaptionCompleteFn;
}
export declare class AssetIndexQueue {
    private deps;
    private queue;
    private timer;
    private draining;
    private pendingPath;
    private intervalMs;
    private log;
    constructor(deps: AssetIndexQueueDeps);
    /** Start the periodic drain. Idempotent. */
    start(): void;
    /**
     * Record that an image asset needs caption/OCR indexing, keyed by its
     * immutable assetId. Fired by VectorService.onAssetPending once the
     * assets.db image row is written (covers import, manager/editor upload, and
     * presign finalize). Cheap + synchronous; the derive happens on the next tick.
     */
    enqueue(assetId: string): void;
    /** Current queue depth — exposed for the health endpoint / tests. */
    get queueDepth(): number;
    /**
     * Boot recovery: replay the persisted queue, then run the FULL unfiltered
     * sweep so anything missing/stale in LanceDB (legacy assets, a drain that
     * died mid-flight) is re-derived regardless of whether it's still queued.
     * Fire-and-forget at boot — it can take minutes and must not block listen().
     *
     * Holds the same `draining` guard a tick uses, so the (slow) boot sweep can't
     * run concurrently with a periodic drain and conflict on the LanceDB writer.
     * Only the ids that were queued WHEN THE SWEEP STARTED are removed afterward —
     * uploads that arrive during the minutes-long sweep stay queued for the next
     * tick rather than being silently dropped.
     */
    recoverOnBoot(): Promise<AssetIndexSweepResult>;
    /** Drain the currently-queued ids. Re-entrancy guarded. */
    private drainTick;
    /** Resolve live config and run the sweep over `onlyAssets` (undefined = all). */
    private runSweep;
    /** Graceful shutdown — drain what's queued, then stop the timer. */
    shutdown(): Promise<void>;
    private persist;
    private loadPersisted;
}
