import { type DetectedHeading } from './headings.js';
import { type TreeBudget, type TreeLlm } from './llm.js';
import type { DocumentTree, DocumentTreeInput, TreeUnit } from './types.js';
export interface BuildDocumentTreeOptions {
    documentId: string;
    /**
     * The model for summaries, the document description, and structuring documents with no usable
     * outline. Omit it and the build is LLM-free: outline/headings or page groups, with the start of
     * each section's text as its summary.
     */
    llm?: TreeLlm;
    /** Deepest level kept (1 = top-level sections only). Deeper headings become `keyItems`. Default 4. */
    maxDepth?: number;
    /**
     * Hard per-document limits for every LLM call of the build. Defaults: 60 calls, 400k input
     * tokens, 40k output tokens, 5 minutes overall, 60 s per call. Running out is not an error: the
     * structure step falls back to page groups, and remaining summaries use the section's own text.
     */
    budget?: TreeBudget;
    /** Summarize nodes with the LLM. Default `true` when `llm` is set. */
    summaries?: boolean;
    /** A node whose text is shorter than this is its own summary (no LLM call). Default 600 chars. */
    summaryMinChars?: number;
    /** Text of a node sent to the summarizer, at most. Default 8 000 chars. */
    summaryInputChars?: number;
    /** Concurrent summary calls. Default 4. */
    concurrency?: number;
    /** Write a one-paragraph description of the document. Default `true` when `llm` is set. */
    describe?: boolean;
    /**
     * Find headings in the text (markdown headers, `PART 52`, `Item 7.`, `3.2 Scope`…) when there is
     * no outline and sections carry no titles. `'markdown'` only trusts markdown headers. Default `true`.
     */
    detectHeadings?: boolean | 'markdown';
    /** At least this many headings for a detected structure to be used. Default 3. */
    minHeadings?: number;
    /** Ask the LLM for the structure when nothing deterministic worked. Default `true` when `llm` is set. */
    llmStructure?: boolean;
    /** Characters of text per structuring call. Default 24 000. */
    structureWindowChars?: number;
    /**
     * Structuring calls allowed. A document needing more windows than this is not sent at all —
     * it goes straight to page groups instead of spending a budget it cannot finish. Default 12.
     */
    maxStructureCalls?: number;
    /** Units per page-group node (flat trees, and splitting long leaves). Default 5. */
    groupSize?: number;
    /** A leaf spanning more units than this is split into page groups. Default 10. */
    maxLeafUnits?: number;
    /** Children per level before page groups are grouped again (flat trees). Default 12. */
    maxChildren?: number;
    /** The previous tree of this document: an unchanged input returns it as is; changed nodes are re-summarized, the rest reuse their summaries. */
    previous?: DocumentTree;
    metadata?: Record<string, unknown>;
    source?: string;
    signal?: AbortSignal;
}
export interface BuiltDocumentTree {
    tree: DocumentTree;
    /** The units the node ranges index — persist them with the tree ({@link import('./store.js').DocumentTreeStore.put}). */
    units: TreeUnit[];
    /** `true` when `previous` had the same fingerprint and was returned without building. */
    unchanged: boolean;
}
/** Turn the input into units (pages or sections) plus any headings it declares. */
export declare function toUnits(input: DocumentTreeInput): {
    units: TreeUnit[];
    declared: DetectedHeading[] | undefined;
    kind: 'pages' | 'sections';
};
/** The text a node spans (children included), joined in reading order. */
export declare function spanText(units: readonly TreeUnit[], start: number, end: number): string;
/** Run `work` over `items` with at most `limit` in flight. */
export declare function mapLimit<T, R>(items: readonly T[], limit: number, work: (item: T, index: number) => Promise<R>): Promise<R[]>;
/**
 * Build a document's navigation tree: a hierarchical table of contents whose nodes carry a title,
 * the page (or section) range they span, and a summary.
 *
 * Structure, cheapest first, never looping:
 *
 * 1. the `outline` the input declares (PDF bookmarks);
 * 2. section titles/levels (`sections` input), or headings detected in the text;
 * 3. the LLM, window by window (only when a document has no usable outline, and only if every
 *    window fits `maxStructureCalls` and the budget up front);
 * 4. page groups — always works; the fallback for any failure above.
 *
 * Then summaries: top levels first (they matter most for navigation), each node's text sent once,
 * within the budget; what the budget leaves unsummarized gets the start of its own text. With a
 * `previous` tree, an unchanged input is returned as is (zero calls), and nodes whose title and text
 * are unchanged keep their summary.
 *
 * The result is deterministic for a deterministic model: node ids are depth-first positions, and
 * nothing depends on timing except which summaries a timed-out build got to.
 */
export declare function buildDocumentTree(input: DocumentTreeInput, options: BuildDocumentTreeOptions): Promise<BuiltDocumentTree>;
//# sourceMappingURL=build.d.ts.map