/** * Text rendering for the savings report. * * SEPARATE FROM THE AGGREGATION ON PURPOSE. Every accuracy question in this * feature -- which rows count, what a percentage is a percentage of, whether a * price is known -- is settled in `windows.ts` and testable without parsing a * line of output. What is left here is presentation, and the one rule it has to * keep is that it must not invent a number the aggregation refused to produce: * a null cost prints as `not priced`, never as `$0.00`. */ import type { SavingsGroup, SavingsReport, SavingsWindow } from './windows.js'; import { type ProxyInput, type ProxySavingsReport, type ProxySavingsWindow } from './proxy.js'; import { type OperatorPriceTableStatus } from '../analytics/operator-prices.js'; export declare function bar(percent: number, width?: number): string; export declare function count(value: number): string; /** * Money, or the admission that there is none. * * SUB-CENT AMOUNTS ARE NOT ROUNDED TO ZERO. A day of light use genuinely is * worth a fraction of a cent, and `$0.00` would read as the feature having * done nothing rather than having done a little. */ export declare function money(amount: number | null): string; /** * One window line. * * THE PRICED FRACTION TRAVELS WITH THE PRICE. `$1.20 (8/12 priced)` is a * different claim from `$1.20`, and the second one invites a reader to treat a * partial figure as the whole bill. When every eligible operation was priced * the parenthetical is dropped, because then the two claims are the same. */ export declare function windowLine(window: SavingsWindow): string; export declare function groupLines(title: string, rows: readonly SavingsGroup[], topN: number): readonly string[]; /** * THE SHORT FORM OF "WHAT THIS READS", for `--help`. * * This replaced a note that disclaimed the proxy's absence. The disclaimer was * honest while the proxy ledger was unread, and it is the wrong text now that * it is an input: a reader who sees "requests through the proxy are not in this * ledger" concludes the proxy figures below it belong to something else. */ export declare const INPUTS_NOTE = "Reads two inputs: the MCP analytics database, and the token-optimizer-proxy wire ledger when TOKEN_OPTIMIZER_PROXY_ACCOUNTING names one."; /** * BOTH INPUTS, AND WHETHER EACH ONE WAS THERE. * * Silence about a missing input is indistinguishable from a measurement of * zero. Every state of both inputs gets a line, and the three proxy states * that an operator can act on say what the action is rather than only that * there are no numbers. */ /** * How much of an input came from days that are no longer rows. * * DISCLOSED ON THE INPUT LINE, NOT HIDDEN BEHIND EQUAL TOTALS. The fold keeps * every figure in this report exact, so nothing above this line changes when a * day ages out -- but what can still be *asked* of that day does change: it can * no longer be filtered by session or exported row by row. An operator who * queried a folded day and got nothing back would otherwise have no way to tell * "nothing happened" from "it is a total now". */ export declare function foldedNote(operations: number, days: number): string; export declare function inputLines(report: SavingsReport, proxy: ProxyInput): readonly string[]; /** * A proxy window, printed by the same function as an MCP window. * * ONE FORMAT FOR BOTH TABLES, which is why this adapts rather than reimplements * `windowLine`. The two aggregations count different things -- operations * against requests -- but a reader comparing the two sections is comparing * columns, and two hand-written formats drift into two different column layouts * the first time one of them is touched. */ export declare function asSavingsWindow(window: ProxySavingsWindow): SavingsWindow; /** * THE INSTRUMENT'S OWN ERROR, PRINTED AS A PAIR. * * Both numbers describe one identical byte sequence -- the body we sent -- so * the gap between them is encoder disagreement and nothing else. The percentage * is taken from the two sums rather than averaged over per-request ratios, * which would weight a three-hundred-token request the same as a * three-hundred-thousand-token one. */ export declare function calibrationLine(report: ProxySavingsReport): string; /** * The other half of the trade: what the saving cost in latency. * * WHY THIS LINE EXISTS AT ALL. Every figure above it is a reduction, and a * report made only of reductions argues one side of a decision. An extension * that halves the bill and adds two hundred milliseconds to every request is a * trade, and an operator cannot accept or refuse a trade they can only see one * half of -- so our own transform cost is printed beside the saving it bought, * in the same report, from the same rows. * * THE UPSTREAM FIGURE IS THE SCALE, not a second claim. Two milliseconds of * transform in front of a two-second provider call and the same two in front of * a thirty-millisecond one are different trades, and the number that separates * them is the one we do not control. * * SAYS SO WHEN IT DOES NOT KNOW. A ledger written by a proxy built before the * timings existed carries none, and the line then reports that rather than * disappearing -- an absent latency line beside a large saving reads as a * saving that cost nothing. */ /** * What the withholding arm held back, when it is on. * * SILENT WHEN IT IS OFF, because a line reading "0 units withheld" on every * report of every operator who never enabled the arm says nothing and trains * people to skip it. The arm is opt-in -- `--spill` with * `TOKEN_OPTIMIZER_COMPRESSION=aggressive` -- and this appears only once it has * actually moved something. * * It reports the count and NOT a saving. What withholding is worth depends on * how often the content is wanted back, and that rate is not in this ledger: * the numerator would be retrievals, which arrive as tool results and are * counted on the telemetry rollup rather than here. Printing a dollar figure * from the count alone would be the projection this branch has been careful not * to publish as a result. */ export declare function withheldLine(report: ProxySavingsReport): string; export declare function latencyLine(report: ProxySavingsReport): string; /** * The output-token tiers, each labelled with the evidence it actually has. * * TWO LINES, NEVER BLENDED INTO ONE. The estimated tier compares requests we * compressed against requests we happened not to, and the measured tier * compares the shaper's two randomized arms. They are different populations * answering different questions, and a single combined "output savings" figure * would be readable as neither -- so each prints under its own name, and the * weaker one prints the word `estimated` inside the sentence rather than in a * footnote a reader can skip. * * A SIGNED FIGURE, BECAUSE THE ANSWER MAY BE THAT WE COST THE OPERATOR TOKENS. * A terser context can plausibly make a model restate more of its own earlier * work, and a renderer that printed `0` or dropped the line in that case would * turn a real negative result into silence. */ export declare function outputLines(report: ProxySavingsReport): readonly string[]; /** * The deferral holdout's line, which belongs beside the calibration and not * beside the output tiers. * * IT IS THE ONLY RANDOMIZED EVIDENCE ON THE PROMPT SIDE. Everything else in the * input section is our own count of our own bytes, checked against the * provider's bill where the row allows it. Tool deferral is the one input-side * feature whose saving we cannot see at all: the schemas stay on the wire and * the provider is the party that declines to put them in the context it * charges for. So its figure comes from the difference between the billed * prompt tokens of the conversations it acted on and the conversations * randomly withheld from it. * * EMPTY UNLESS A HOLDOUT RAN, and empty is printed as nothing rather than as a * zero: an operator who never started the experiment must not read this as * "the holdout found no effect". * * THE LABEL SAYS `prompt`, NOT `output`, AND THAT IS LOAD-BEARING. The computed * prompt saving is already in the headline above; this line is a second, * independent reading of part of the same thing, and a reader who adds the two * has double-counted. The wording names it as a confirmation. */ export declare function deferralLine(report: ProxySavingsReport): string; /** * WHY THE UNCOUNTED ROWS ARE NAMED SEPARATELY FROM THE UNBILLED ONES. A request * the provider rejected is not a failed measurement -- there was no bill to * reduce -- while a billed request we could not count is exactly that, and the * two numbers lead an operator to different places. */ export declare function proxyGateNote(report: ProxySavingsReport): string; export declare function renderProxySavings(report: ProxySavingsReport, options: { readonly topN: number; }): readonly string[]; /** * WHY A GATE NOTE AND NOT JUST A NUMBER. An operator who ran a hundred * operations and sees twelve counted needs to know that the other eighty-eight * were not failures of compression but rows without a provable before-state. */ export declare function gateNote(report: SavingsReport): string; /** * The models the catalog has no price for, named. * * ONE FORMATTER FOR BOTH TABLES, taking the id list rather than either report, * so the MCP half and the proxy half cannot end up describing the same gap in * two different sentences. * * WHAT IT DOES NOT SAY is that the figures are wrong. The token columns are * measured for these rows exactly as for any other; it is only the dollar * column that cannot be filled, and the sentence has to leave a reader with * that distinction rather than a vague doubt about the whole table. */ export declare function unpricedNote(models: readonly string[]): string; /** * SECTION HEADINGS EXIST BECAUSE THERE ARE TWO INPUTS NOW. One column of * windows followed by another, unlabelled, reads as one table that repeats -- * and the two prove different things, so the figures must not be addable by * eye. The proxy section is omitted entirely when its ledger was not read; the * inputs block at the bottom is what says so. */ /** * WHERE EACH RATE CAME FROM, AND HOW TO SUPPLY A MISSING ONE. * * Three different facts share this one line because an operator reading an * unpriced model needs exactly one of them: that their own table supplied some * of these rates, that it was refused and why, or that such a table is how the * gap gets closed. A refusal is named rather than swallowed -- a typo in the * path would otherwise read as money that quietly went missing. */ export declare function priceTableNote(status: OperatorPriceTableStatus, unpricedModels: number): string; export declare function renderSavings(report: SavingsReport, options: { readonly topN: number; readonly proxy: ProxyInput; readonly priceTable: OperatorPriceTableStatus; }): string; //# sourceMappingURL=render.d.ts.map