/**
 * Content-hash cache keys for the SaaS bridge.
 *
 * The bridge dedupes work by *request shape*: two discovery or session requests
 * that describe the same thing should hit the same cache slot regardless of how
 * their fields happened to be ordered in memory. Rather than carry a recursive
 * canonical-string serializer around as the key, we fold any value into a short,
 * fixed-width SHA-256 digest of its canonical JSON. The digest *is* the key — a
 * compact, collision-resistant string that captures the whole request shape.
 *
 * Canonicalization is the only subtlety: JSON key order is incidental, so before
 * hashing we rewrite every object with its keys sorted. Arrays keep their order
 * (it is meaningful); scalars pass through; `undefined` is dropped the way
 * `JSON.stringify` already drops it. The result feeds `crypto`'s SHA-256 and we
 * keep the hex digest.
 *
 * {@link HashCache} is the tiny Map-backed store that uses these keys. It memoizes
 * *promises*, not resolved values, so concurrent callers asking for the same key
 * share one in-flight computation instead of racing to produce duplicates.
 */
/**
 * Derive a stable content-hash key from an arbitrary value.
 *
 * The value is canonicalized (so key order does not matter), JSON-encoded, and
 * reduced to a hex SHA-256 digest. Equal request shapes always yield the same
 * key; differing shapes practically never collide.
 */
export declare function hashKey(value: unknown): string;
/**
 * A minimal promise-memoizing cache keyed by content hash.
 *
 * Lookups go through {@link HashCache.take}, which either returns the
 * already-stored promise for a request shape or runs the supplied factory once
 * and stores its promise. Storing the promise (rather than awaiting first) is what
 * collapses concurrent identical requests into a single backing computation.
 */
export declare class HashCache<V> {
    private readonly slots;
    /**
     * Return the cached promise for `shape`, creating it via `factory` on first
     * request. If the factory's promise rejects, the slot is evicted so a later
     * call can retry rather than re-serving the failure forever.
     */
    take(shape: unknown, factory: () => Promise<V>): Promise<V>;
    /** Whether a slot for this request shape currently exists. */
    has(shape: unknown): boolean;
    /** Drop the slot for this request shape, if any; returns whether one existed. */
    drop(shape: unknown): boolean;
    /** Evict every entry. */
    clear(): void;
    /** How many slots are currently populated. */
    get size(): number;
}
