/** * The first five minutes, decided without touching a disk. * * Everything since 1.41 raised the ceiling. This lowers the floor: from * `npx @trazum/cli` to a finding worth money, without reading a page of * documentation. Twenty-one commands is a wall to somebody who has none of * them yet, and that wall is why a good tool gets closed inside a minute. * * **The proposal is a document, not a side effect.** What `init` would write * is decided here, from observations the CLI collected, and returned as a * value. So every rule below is testable without a filesystem, and `--dry-run` * is the same code path minus the write rather than a second implementation * that drifts from the first. * * **A key with no evidence is not written.** A generated config full of * guessed thresholds is a config nobody trusts and everybody deletes — and it * is worse than an empty one, because it looks like a decision somebody made. * Every key that lands carries the observation that justified it; every key * that does not carries what would settle it. Both are typed values, because a * first run that explains itself only in prose cannot be checked by a test. * * **Measurement is not policy.** A log says what your traffic *was* — how many * calls, which model, how long the outputs ran. Those are measurements and * this file writes them. A budget says what your traffic *may cost*, which no * log can answer: picking "the measured month plus twenty per cent" would be * this tool inventing a threshold and then grading somebody against it. So * `spend` is always declined, and the measured figure is handed over so the * person who *can* set a budget has the number in front of them. */ import type { TrazumConfig } from './config-schema.js'; import type { Detection, EvidenceKind } from './detect.js'; import type { HostEnvironment } from './host.js'; import type { SliceLevers } from './levers.js'; import type { PricingCatalogue } from './pricing.js'; import type { UsageProfileReport } from './usage.js'; import type { Locale } from './i18n/index.js'; /** A source file that was read, and what `detectFromSource` made of it. */ export interface ProviderSighting { file: string; detection: Detection; } /** * Something that might hold usage, found lying around. * * `where` is a path for the file kinds and the **name** of an environment * variable for a credential — never its value. That rule has held since the * connector shipped in 1.41 and it holds here: a first-run summary is the * single most likely thing somebody pastes into a chat window. */ export interface UsageSighting { kind: 'log-file' | 'log-directory' | 'store' | 'connector-credential'; where: string; /** The provider this source belongs to, when the sighting names one. */ provider: string | null; } /** Everything the CLI saw, handed over as data. */ export interface InitObservations { host: HostEnvironment; /** Every source file read, strongest evidence first within each file. */ sightings: ProviderSighting[]; /** Prompt files the walk found. */ promptFiles: string[]; /** Usage sources found. Empty is a real answer and is reported as one. */ usage: UsageSighting[]; /** * The profile of a usage source that was found **and** parsed. * * Null covers two different situations and the proposal keeps them apart: * nothing was found, or something was found and could not be read. The * caller says which by what it puts in `usage`. */ measured: UsageProfileReport | null; /** The locale the environment asked for, when it asked for one. */ locale: Locale | null; /** A config already sitting in the working directory. */ existing: { path: string; config: TrazumConfig; } | null; } /** Every config key `init` is allowed to have an opinion about. */ export type InitKey = 'locale' | 'extensions' | 'usage.model' | 'usage.callsPerMonth' | 'usage.avgOutputTokens' | 'usage.cacheHitRate' | 'usage.batchEligible' | 'labels' | 'spend.maxUsd'; /** Why a key was written, in a shape a test can assert on. */ export type InitJustification = { key: 'locale'; value: Locale; from: 'environment'; } | { key: 'extensions'; value: string[]; from: 'walk'; files: number; } | { key: 'usage.model'; value: string; from: 'measured'; /** Share of the measured bill this model carries, 0-1. */ share: number; } | { key: 'usage.model'; value: string; from: 'source'; file: string; line: number; evidence: EvidenceKind; } | { key: 'usage.callsPerMonth'; value: number; from: 'measured'; calls: number; days: number; } | { key: 'usage.avgOutputTokens'; value: number; from: 'measured'; outputTokens: number; calls: number; } | { key: 'usage.cacheHitRate'; value: number; from: 'measured'; cacheReadTokens: number; inputTokens: number; }; /** * Why a key was left out, and what would settle it. * * A refusal never arrives bare — the rule the guard established in 1.45, here * applied to a file rather than to a call. "No provider written" with nothing * after it is indistinguishable from a bug. */ export type InitDecline = { key: 'usage.model'; why: 'no-evidence'; } | { key: 'usage.model'; why: 'conflicting-evidence'; files: string[]; } | { key: 'usage.model'; why: 'provider-only'; provider: string; file: string; } | { key: 'usage.callsPerMonth'; why: 'nothing-measured'; } | { key: 'usage.callsPerMonth'; why: 'window-too-short'; days: number; calls: number; } | { key: 'usage.callsPerMonth'; why: 'undated-calls'; undated: number; calls: number; } | { key: 'usage.avgOutputTokens'; why: 'nothing-measured'; } | { key: 'usage.cacheHitRate'; why: 'nothing-measured'; } | { key: 'usage.cacheHitRate'; why: 'not-recorded'; } | { key: 'usage.batchEligible'; why: 'only-you-know'; } | { key: 'labels'; why: 'unprovable'; labels: number; } | { key: 'spend.maxUsd'; why: 'a-budget-is-a-policy'; measuredUsd: number | null; days: number | null; }; /** * The single most valuable thing the first run found, with its arithmetic. * * One finding, not a ranked table. `doctor` and `plan` exist for the table, * and a first run that opens with fourteen rows has told somebody nothing — * they came to find out whether this is worth an afternoon. */ export interface InitHeadline { slice: SliceLevers; /** Which lever the figure is. `route+batch` is computed, never summed. */ lever: 'route' | 'batch' | 'route+batch'; savingUsd: number; /** Always measured. Nothing in a headline rests on a call that never happened. */ provenance: 'measured'; /** Days of measurement behind it, so the figure has a unit a reader can check. */ days: number; } export type NoHeadline = 'nothing-measured' | 'nothing-could-be-priced' | 'no-lever-clears-the-floor'; export interface InitProposal { schemaVersion: 1; /** Exactly the keys that were justified, and nothing else. */ config: TrazumConfig; justified: InitJustification[]; declined: InitDecline[]; headline: InitHeadline | null; /** Set when `headline` is null, so "nothing found" is never bare. */ noHeadline: NoHeadline | null; /** * The config already there, and which of its keys this proposal would * change. Named before anything is written: an `init` that silently replaces * a config somebody tuned is the worst possible first impression. */ overwrites: { path: string; keys: InitKey[]; } | null; } /** * The shortest measured span that may be stated as a monthly rate. * * Four weeks, so every weekday appears the same number of times. Three days of * traffic multiplied by ten is a forecast wearing a measurement's clothes, and * this repository has refused that since the series shipped in 1.40. */ export declare const MIN_RATE_DAYS = 28; /** The share of the bill a headline must clear to be worth being the headline. */ export declare const HEADLINE_FLOOR_SHARE = 0.01; export interface InitOptions { catalogue: PricingCatalogue; on?: Date; } export declare function proposeInit(observations: InitObservations, options: InitOptions): InitProposal; //# sourceMappingURL=init.d.ts.map