/** * The search tools' `structuredContent`: a lean projection of the parsed * search result (#106). * * The text block is the complete rendering and stays untouched; this module * shapes only the structured payload, which is what the widget renders, what * claude.ai delivers to it, and what Claude Code shows the model instead of * the text whenever a tool returns both (measured 2026-09-04). */ import type { Document, SearchResult, StructuredDocument } from './types.js'; /** * Project a parsed document to the shape declared in `StructuredDocumentSchema`. * * Drops the three fields that repeat `titel` (`kurztitel`, `citation.kurztitel`) * and the two renditions nobody reads (`content_urls.xml`/`rtf`). The rest is * copied as is — including the court fields of a decision, whose *presence* * is what tells the widget a decision from a law, so a `null` there must * survive the projection. */ export declare function toStructuredDocument(doc: Document): StructuredDocument; /** * Default character budget for a search tool's serialized `structuredContent`. * * The binding limit is Claude Code, which measures exactly this serialized * payload against `MAX_MCP_OUTPUT_TOKENS` (25 000 tokens by default) and * replaces the whole result with a file pointer when it is over. Measured * live on 2026-09-08 against production: 58 659 and 59 362 characters * (Judikatur pages of 50) were rejected, 46 311 and 41 515 were accepted — * so the previous default of 60 000 let pages through that the client then * dropped (#106). 45 000 sits just below the smallest accepted Judikatur * page (46 311) and well under the smallest rejected one, leaving a margin * for content that tokenizes worse than court decisions. claude.ai has no * observed size limit: its widget rendered 138 050 characters completely, * and the model there reads the text block rather than this payload * (reporter measurement, 2026-09-04). The widget's 64 000-character * snapshot cap (`ui/shared/widget-state.ts`) and the text block's own * 25 000-character cap are separate. */ export declare const DEFAULT_STRUCTURED_CONTENT_BUDGET = 45000; /** * The budget in effect: `RIS_STRUCTURED_CONTENT_BUDGET` when it is a positive * integer, else the default. Read per call so a test can stub it. */ export declare function structuredContentBudget(): number; /** A search page as it is delivered: text source, structured payload, and what happened. */ export interface StructuredSearchPage { /** The page for the text renderer — sliced to the delivered size on a downgrade. */ result: SearchResult; /** The `structuredContent` payload, within budget wherever a smaller page size exists. */ structured: Record; /** Requested and delivered page size, or null when the page went out as requested. */ downgrade: { from: number; to: number; } | null; /** German notice describing the downgrade; also carried as `structured.notice`. */ notice: string | null; } /** * Fit a parsed search page into the structured-content budget. * * A page within budget goes out as it is. One over budget is delivered at the * largest smaller RIS page size whose offset arithmetic stays exact — the hit * the page starts at, `(seite − 1) · limit`, must be a multiple of the new size, * or the next page would skip or repeat hits — with `page`, `page_size`, * `has_more`, `documents` and the `query` echo rewritten to that size and a * German notice added. Page 1 therefore accepts any smaller size; deeper pages * fall back to a divisor, and 10 always is one. * * This is deliberately not a cut of `documents[]`: clients page with * `query.limit`, RIS pages with `DokumenteProSeite`, and a page cut to an * arbitrary count would make the next page start past the hits it dropped * (#106). The price is the upstream fetch of the hits that are not delivered. * * Without a usable `limit`/`seite` in the echo there is nothing to re-page * with, and the page is projected but not fitted. */ export declare function fitStructuredSearchPage(result: SearchResult, queryEcho: Record, budget?: number): StructuredSearchPage; //# sourceMappingURL=structured-search.d.ts.map