UNPKG

@sema-agent/core

Version:

Stateless, task-oriented AI agent core

58 lines (57 loc) • 3.73 kB
/** * The ONE folding engine every listing frame renders through — the `<skills>` block, the skills drift * frame's add arm, the agent-type roster and its drift frame's add arm. A listing is an intact-class * turn attachment (`turn-attachments.ts` `ATTACHMENT_DELIVERY_CLASS`): the delivery lane never clips * it, so this engine is the frame's whole bound, byte-exact over the caller's `frame` (headers, fences, * markers, joiners included). * * Three honesty tiers over ONE set of items, each chosen with the LATER tiers' fixed overhead already * reserved so the final render never blows the budget it was sized against: * A. everything fits → every item gets its full line; * B. reserve the cap marker + EVERY item's name-only line first, then spend the remaining slack on * full lines in PRIORITY order (`rank` ascending; absent ⇒ index), admitting each full line whose * incremental cost still fits and skipping (not stopping at) the ones that do not — every item stays * listed, the low-priority ones lose their detail; * C. even all-name-only overflows → the longest name-only prefix that fits, closed by the caller's * overflow count line. * Pure: the same items, spec and frame always render the same bytes. */ export interface ListingFoldSpec<T> { /** The whole frame's byte budget, honoured as given. */ blockMaxBytes: number; /** One item's full line (tier A, and tier B's admitted lines). */ full: (item: T) => string; /** One item's name-only line (tier B's degraded form, tier C's listed prefix). */ nameOnly: (item: T) => string; /** The raw name reported for an item the budget degraded (host-facing data, not prompt text). */ nameOf: (item: T) => string; /** Priority for keeping the full line: ascending, 0 = first. Absent ⇒ the item's index. */ rank?: (item: T, index: number) => number; /** The marker line that opens a degraded (tier B/C) body. */ capMarker: string; /** Tier C's closing line for `n` items that could not be listed at all. */ overflowLine: (n: number) => string; /** Renders body lines into the lane's frame; its fixed cost is priced once by rendering it empty. */ frame: (lines: readonly string[]) => string; } /** What one fold produced: the frame, and which items the budget degraded (display order). */ export interface ListingFoldRender { text: string; /** Items listed WITHOUT their full line. */ nameOnly: readonly string[]; /** Items the frame could not list at all (tier C's overflow tail). */ dropped: readonly string[]; } export declare function foldListingWithin<T>(items: ReadonlyArray<T>, spec: ListingFoldSpec<T>): ListingFoldRender | undefined; /** The removal arm's FLOOR — the departure fact with none of the names; constant-size, which is what * keeps the fact from being starved by a budget the names cannot fit. */ export declare function removalArmFloor(header: string, count: number): string; /** * A listing frame's REMOVAL arm rendered INSIDE a byte budget: every departed name when they fit, * otherwise the longest prefix that does, closed by an honest count line — tier C over a list whose * lines have one form, so there is no name-only tier between them. Names are neutralized on the way * out: the announced map holds raw names from the commit half. Cost of the bound, stated: a name that * does not fit is never announced (the commit half advances past it), so the model can still hold an * entry that is gone — one failed call, against a frame that would otherwise never fit its budget. */ export declare function foldRemovalArmWithin(removed: readonly string[], header: string, maxBytes: number): string;