@adonis-agora/agent
Version:
Governed, durable-backed AI agent (chat + tool-calling + governance) for AdonisJS — part of the Agora ecosystem.
96 lines • 5.25 kB
TypeScript
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