import type { Passage, RetrieveOptions, Retriever } from '../../spi/retriever.js';
import { type TreeBudget, type TreeLlm } from './llm.js';
import type { DocumentTreeStore } from './store.js';
export interface TreeNavigationRetrieverOptions {
    store: DocumentTreeStore;
    llm: TreeLlm;
    /**
     * A tree whose outline (titles, pages, summaries) fits in this many characters is navigated in
     * **one** call that sees the whole outline — PageIndex's tree search, the variant measured in the
     * benchmark. Bigger trees are walked level by level (a beam). Default 40 000 (~10k tokens).
     */
    singlePassMaxChars?: number;
    /** Nodes the navigator may expand or read per beam step. Default 4. */
    beamWidth?: number;
    /** Beam levels, at most. Nodes still marked "expand" at the last level are read whole. Default 4. */
    maxSteps?: number;
    /** Nodes returned per document, at most. Default 5. */
    maxNodes?: number;
    /**
     * Hard per-document limits for one navigation. Defaults: 6 calls, 60k input tokens, 4k output
     * tokens, 60 s. Running out mid-walk returns what was chosen so far (the nodes last marked for
     * expansion are read whole) and records `stoppedBy: 'budget'`.
     */
    budget?: TreeBudget;
    /** Characters of text per returned node. Default 12 000. */
    maxPassageChars?: number;
    /** Units (pages/sections) read per returned node, at most. Default 25. */
    maxUnitsPerNode?: number;
    /** Characters across all passages of one navigation (every document). Default 48 000 (~12k tokens). */
    maxContextChars?: number;
    /**
     * {@link TreeNavigationRetriever.retrieve} with no first stage: documents navigated per query. When
     * more trees pass the filter, the LLM picks this many from their titles and descriptions
     * (PageIndex's document selection). Default 3.
     */
    maxDocuments?: number;
    /** Trees shown to document selection, at most. Default 200. */
    maxSelectionCandidates?: number;
    /** Documents navigated in parallel. Default 3. */
    concurrency?: number;
}
/** One step of a navigation, for the audit trail. */
export interface NavigationStep {
    step: number;
    /** Node ids shown to the LLM this step. */
    shown: string[];
    /** Node ids it chose to open further. */
    expanded: string[];
    /** Node ids it chose to read. */
    read: string[];
    /** The LLM's stated reasoning, verbatim (capped). */
    reasoning?: string;
}
/** A node navigation chose, with the path that led to it. */
export interface NavigatedNode {
    nodeId: string;
    title: string;
    /** Ancestors from the top level down, then the node itself. */
    path: {
        id: string;
        title: string;
    }[];
    pageStart?: number;
    pageEnd?: number;
    unitStart: number;
    unitEnd: number;
}
/** The auditable record of navigating one document. */
export interface DocumentNavigation {
    documentId: string;
    title?: string;
    mode: 'single-pass' | 'beam';
    steps: NavigationStep[];
    nodes: NavigatedNode[];
    llmCalls: number;
    inputTokens: number;
    outputTokens: number;
    /** Why the walk stopped early, when it did. */
    stoppedBy?: 'budget' | 'timeout' | 'maxSteps' | 'error' | 'not-found';
    error?: string;
}
export interface NavigationResult {
    passages: Passage[];
    documents: DocumentNavigation[];
    /** Set when {@link TreeNavigationRetriever.retrieve} had the LLM pick the documents. */
    selection?: {
        candidates: number;
        selected: string[];
        reasoning?: string;
        error?: string;
    };
}
export interface NavigateOptions {
    /** Access filter applied to every tree read (vector-store semantics). */
    filter?: Record<string, unknown>;
    /** Overrides the retriever's per-document budget. */
    budget?: TreeBudget;
    signal?: AbortSignal;
}
/**
 * Tree navigation retrieval ("vectorless", reasoning-based — PageIndex's method): an LLM reads a
 * document's table of contents (titles, page ranges, summaries — no body text) and picks the
 * sections that answer the question; their text comes back as passages, with the path taken and the
 * model's reasoning recorded so the choice is auditable.
 *
 * A small tree is navigated in one call over the whole outline. A large one is walked level by
 * level: the model sees one level of candidates, opens (`expand`) the promising ones and takes
 * (`read`) the ones that already answer, until it reaches leaves, runs out of `maxSteps`, or runs
 * out of its hard per-document {@link TreeBudget} — in which case it returns what it had.
 *
 * It pays off on **long structured documents** (regulations, contracts, filings, manuals) where
 * chunk ranking struggles among hundreds of look-alike passages; on short notes it costs seconds and
 * LLM spend for nothing. Compose it behind a first stage with {@link TwoStageRetriever}, or give it
 * to the agent as a tool with {@link createNavigateDocumentTool}.
 *
 * As a plain `Retriever`, `retrieve(query, { filter })` navigates the trees that pass `filter`:
 * all of them when there are at most `maxDocuments`, otherwise the ones the LLM picks from their
 * descriptions.
 */
export declare class TreeNavigationRetriever implements Retriever {
    private readonly options;
    readonly store: DocumentTreeStore;
    private readonly llm;
    constructor(options: TreeNavigationRetrieverOptions);
    retrieve(query: string, options?: RetrieveOptions): Promise<Passage[]>;
    /** {@link retrieve} with the audit trail: which documents, which nodes, why. */
    search(query: string, options?: NavigateOptions): Promise<NavigationResult>;
    /**
     * Navigate the given documents (in parallel, up to `concurrency`) and return their passages in
     * the order given, within `maxContextChars`. Documents without a tree, or whose tree fails
     * `filter`, yield no passages and `stoppedBy: 'not-found'`.
     */
    navigate(query: string, documentIds: readonly string[], options?: NavigateOptions): Promise<NavigationResult>;
    private walk;
    private passagesOf;
}
//# sourceMappingURL=navigate.d.ts.map