/** * Response Formatter Utilities * * Provides token-optimized formatting for MCP tool responses. * Based on the design document: docs/context-optimization-design.md */ /** * Detail level for response formatting * - minimal: Only essential information (lowest tokens) * - summary: Key information with counts and hints (balanced) * - detailed: Full information (original behavior) */ export type DetailLevel = "minimal" | "summary" | "detailed"; /** * Common formatting options */ import { type PresenterFormat } from "./presenter.js"; export interface FormatterOptions { /** * Backwards-compatible alias for detailLevel * @deprecated Use detailLevel instead */ mode?: DetailLevel; /** * Level of detail in the response * @default "summary" */ detailLevel?: DetailLevel; /** * Maximum number of items to include in lists * @default undefined (no limit) */ limit?: number; /** * Include hints about omitted content * @default true */ includeHints?: boolean; /** * Structured output format for detailed mode * @default "yaml" */ responseFormat?: PresenterFormat; } /** * Default formatter options */ export declare const DEFAULT_FORMATTER_OPTIONS: { detailLevel: "summary"; includeHints: true; limit: number | undefined; responseFormat: PresenterFormat | undefined; }; /** * Merge user options with defaults */ export declare function mergeFormatterOptions(options?: FormatterOptions): { detailLevel: DetailLevel; limit: number | undefined; includeHints: boolean; responseFormat?: PresenterFormat; }; /** * What `limit` removed from the structured payload. * * `json` and `yaml` render `structured` and nothing else — no markdown hint * reaches them — so a payload cut down to `limit` items has to carry the fact * itself. Without it the caller cannot tell a capped list from a short one, * which is the same defect as ignoring `limit`, one layer down. * * The counts are per collection because a single `limit` binds several: an * error report caps its entries and each of its three caveat lists, and a * reader deciding whether to ask again needs to know which one ran out. */ export interface TruncationNotice { /** The cap the caller asked for. */ limit: number; /** Only the collections that actually lost items. */ collections: Record; } interface FormatterMetadata { template?: string; context?: Record; structured?: unknown; /** * What `limit` cut from `structured`, as built by `describeTruncation`. * * Present only when something was actually removed, which is what keeps a * response for a caller who passed no `limit` byte for byte what it was. */ truncation?: TruncationNotice; } /** * Describe what a formatter's caps removed, or nothing if they removed nothing. * * Only the formatter knows which of its collections `limit` binds, so it * declares them here rather than this layer guessing at the payload's shape. * Collections that kept every item are left out: the notice exists to report a * loss, and listing intact collections would bury the one that was cut. */ export declare function describeTruncation(limit: number | undefined, collections: Record): TruncationNotice | undefined; export declare function finalizeFormattedText(text: string, opts: { responseFormat?: PresenterFormat; detailLevel: DetailLevel; }, metadata?: FormatterMetadata): string; /** * Format a hint message for omitted content */ export declare function formatOmissionHint(totalCount: number, shownCount: number, itemType: string): string; /** * Truncate array based on limit option */ export declare function limitArray(items: T[], limit: number | undefined): { items: T[]; truncated: boolean; }; export {};