/** * The savings report as one flat table, for a spreadsheet or a stored series. * * NOT A SECOND AGGREGATION. Every figure here is one already computed for the * text and JSON renderings and copied across unchanged; this module adds no * arithmetic of its own, so a number read out of the CSV is the same number the * report printed and there is no third result to reconcile. * * ONE TABLE, WITH THE GRAIN NAMED IN TWO COLUMNS. The report is really five * tables -- nested windows and two breakdowns over the MCP tools, windows and a * model breakdown over the proxy -- and a spreadsheet wants one. So `source` * says which half of the product a row describes and `section` says at what * grain, which keeps the rows addressable without a reader having to guess from * the label. The windows NEST rather than partition (today is inside the last * seven days), so summing a column across window rows double-counts; that is a * property of the report, not of this encoding, and the header note says so. * * A HALF WITH NOTHING MEASURABLE CONTRIBUTES NO ROWS, NOT A ROW OF ZEROS. * Once it is in a spreadsheet, `tokens_saved=0` is indistinguishable from a * measured zero, and `savings_percent=0` over `tokens_before=0` is a ratio * nobody computed. The text rendering already refuses to print a table in that * state and says what to do instead; this one answers with the header alone, * which is also what lets a stored series be appended to from day one. * * AN EMPTY CELL MEANS NOT MEASURED AT THIS GRAIN, NEVER ZERO. A breakdown row * carries no before-state, because a group is a slice of operations rather than * a window over them, and an unpriced window carries no dollar figure. Writing * 0 in either place would be a measurement this command never made. */ import { type ProxyInput } from './proxy.js'; import type { SavingsReport } from './windows.js'; /** Which half of the product a row describes. */ export declare const CSV_SOURCE: Readonly<{ /** Undisclosed MCP payloads the tools never materialized. */ readonly Mcp: "mcp"; /** Request bodies the proxy rewrote on the wire. */ readonly Proxy: "proxy"; }>; export type CsvSource = (typeof CSV_SOURCE)[keyof typeof CSV_SOURCE]; /** The grain a row is taken at. */ export declare const CSV_SECTION: Readonly<{ /** A calendar window, nested inside the wider ones. */ readonly Window: "window"; /** One model's slice of every window. */ readonly ByModel: "by_model"; /** One client's slice of every window. */ readonly ByClient: "by_client"; }>; export type CsvSection = (typeof CSV_SECTION)[keyof typeof CSV_SECTION]; /** * The column order, which is the file format. Appending is safe for a reader * that addresses cells by header name; reordering or renaming is not, so this * list changes only alongside a note in the release. */ export declare const CSV_FIELDS: readonly ["source", "section", "name", "since", "operations", "tokens_before", "tokens_saved", "savings_percent", "cost_usd", "priced_operations", "eligible_operations"]; /** A cell before encoding: a number, a string, or nothing measured. */ type Cell = string | number | null; /** * One row, keyed by column so a caller cannot transpose two figures silently. */ type Row = Readonly>; /** * RFC 4180 encoding of one cell, plus the formula guard above. * * A null becomes an empty field rather than a zero -- see the module note. */ export declare function csvCell(value: Cell): string; /** * Every row of both halves, in the order the text report prints them. * * EACH HALF IS INCLUDED ONLY IF IT MEASURED SOMETHING. The MCP half needs at * least one operation with a provable before-state -- the same test the text * rendering uses to decide whether to print a table at all -- and the proxy * half needs a ledger that was READ, not merely configured. */ export declare function savingsCsvRows(report: SavingsReport, proxy: ProxyInput): readonly Row[]; /** * The header line and one line per row -- no leading comment line. * * A `#` note above the header would make the file unreadable by every tool * that opens a CSV by its first line, which is the only reason this format * exists. What the columns mean belongs in `--help` and in this module. */ export declare function renderSavingsCsv(report: SavingsReport, proxy: ProxyInput): readonly string[]; export {}; //# sourceMappingURL=csv.d.ts.map