import { type SpotlightRank, type SpotlightReason } from "@oh-my-pi/pi-tui/chat/spotlight"; import type { CallContext, Scorer, ShapeInput, ShapeSink } from "../types.js"; import type { ShapeState } from "./state.js"; /** One shaping call: its input, the agent's context, the scorer and sink, the session state and the call's counters. */ export interface Run { input: ShapeInput; ctx: CallContext; scorer: Scorer; state: ShapeState; sink: ShapeSink; signal?: AbortSignal; /** Directory bash and eval ran in; paths of code windows resolve against it. */ cwd: string; stats: Record; /** The subject's own lines: a read's window lines (unprefixed), else the result text's lines. */ base: readonly string[]; /** Spotlight's latest score per {@link base} line, null while unscored; reported as the result's heat. */ heat: (number | null)[]; /** * Why each {@link base} line was shown or hidden, as the latest step that decided on it recorded it (undefined * while none did); reported as the result's `why` where it agrees with what the shaped text shows. */ why: (SpotlightReason | undefined)[]; /** How the latest step that cut by rank ranked the {@link base} lines; reported as the result's rank. */ rank?: SpotlightRank; /** Normalised lines this call's cuts hid; they join {@link ShapeState.hidden} only if the shaped text is kept. */ hid: Set; /** Code spans this call folded, per absolute path; they join {@link ShapeState.folded} only if the text is kept. */ folds: Map; /** A cut's saved copy, as its footer names it; written only if the shaped text is kept. */ copy?: string; /** {@link base} indexed by line text, built on first use. */ baseIndex?: Map; } /** The {@link Run.base} line that item `i` of a scored list is, or null for none. */ export type Origin = (i: number) => number | null; /** Items that are base lines `offset`, `offset + 1`, …. */ export declare function shifted(offset: number): Origin; /** Items matched to the base lines they equal, in order (see {@link alignLines}). */ export declare function alignedTo(run: Run, lines: readonly string[]): Origin; export declare function bump(run: Run, key: string, by?: number): void; /** * Spotlight's score per line of `lines` (null for blank lines, which are not sent), or null when any request did not * answer or the scorer is score-free (nothing is sent): callers then fall back to a rule that needs no scores. Scores * of different chunks are compared as if they came from one request. The scores * land on the base lines `origin` names (by default the base lines the scored lines equal; `null` for lines that are * none, such as compacted data). */ export declare function scoreLines(run: Run, lines: readonly string[], origin?: Origin | null): Promise<(number | null)[] | null>; /** Records why a step showed or hid each of its items on the base lines `origin` names (undefined: not decided). */ export declare function noteWhy(run: Run, origin: Origin | null, why: readonly (SpotlightReason | undefined)[]): void; /** One step's cut by rank over its items, as {@link noteRank} records it. */ export interface RankCut { /** The parts a score adds up, in order. */ parts: string[]; /** The highest score an item can reach. */ max: number; /** Per part, its value on each item (items the step did not score: 0). */ values: readonly (readonly number[])[]; /** Per item, why the step showed or hid it: items chosen on their score are `a`. */ why: readonly (SpotlightReason | undefined)[]; /** The cutoff when no item of a base line was chosen on its score. */ floor: number; /** Characters the step could show and showed, as it counts them. */ budget?: number; used?: number; /** The last item chosen on its score and the characters it cost. */ last?: { item: number; chars: number; }; } /** * Records a step's cut by rank over the base lines `origin` names (base lines it did not rank are 0): the cutoff is * the lowest score among the base lines it chose on their score. */ export declare function noteRank(run: Run, origin: Origin | null, cut: RankCut): void; /** Each span's hottest line score (0 for spans without one), as a share of the best span; all 0 when none scored. */ export declare function spanShares(scores: readonly (number | null)[], spans: readonly { from: number; to: number; }[]): number[]; /** The no-score order: lines nearer either end of the output rank higher (head + tail), in (0, 1]. */ export declare function headTail(n: number): number[];