import { CliCredentials } from './config'; /** LIX is a decimal amount (the wallet column is numeric(19,4)) — never minor units. */ export declare const LIX_DP = 4; export declare const roundLix: (value: number) => number; /** Render a LIX amount for humans: trim trailing zeros but never lie about precision. */ export declare function formatLix(value: number): string; export type LixHold = { reservationId?: string; jobId?: string | null; action?: string; label?: string; lix: number; reservedAt?: string; holdUntil?: string; }; export type LixBalance = { currency: string; available: number; held: number; total: number; breakdown?: { withdrawable?: number; nonWithdrawable?: number; }; holds: LixHold[]; /** Which endpoint answered — the dedicated billing route, or the raw wallet fallback. */ source: 'lix-billing' | 'wallet'; }; /** * Read the caller's LIX balance. * * Prefers `GET /api/v1/lix-billing/balance`, which reports available/held/total and itemises open * holds. Falls back to the raw economy wallet (`GET /api/v1/wallet/me`) on 404 so the command works * against deployments where the billing route has not landed yet — and says which one answered, * because the wallet has no notion of `held` and reporting 0 held as if it were measured would hide * exactly the stranded money this command exists to reveal. */ export declare function getLixBalance(creds: CliCredentials): Promise; export declare function formatBalance(balance: LixBalance): string; /** * How a component's price relates to what you can actually be charged: * exact — the charge IS this number. * ceiling — the charge is at most this number (`maxLix === lix`). * estimate — the charge can land either side; `maxLix` is the real cap. * * `estimate` exists because `ceiling` used to be applied to music, which is billed on the duration * the provider ACCEPTS — that can exceed the duration requested, so the authorized cap sits above * the quote. The charge was never uncapped; the label oversold it. */ export type EstimateBasis = 'exact' | 'ceiling' | 'estimate'; export type QuoteComponent = { stage: string; action?: string; /** Server-owned display name. Never map action→label CLI-side; that map has already drifted once. */ label?: string; lix?: number; spark?: number; /** The most this component can be charged. Equals `lix` for exact/ceiling. */ maxLix?: number; priceType?: 'base' | 'premium' | string; estimateBasis?: EstimateBasis; }; export type GenerationQuote = { totalLix: number; baseLix: number; premiumLix: number; /** * The most this job can be charged — the number a spend guard must compare against. Guarding * `totalLix` lets someone approve a bound the charge is permitted to exceed. */ maxLix: number; components: QuoteComponent[]; quoteToken?: string; quoteId?: string; expiresAt?: string; configVersion?: string; estimateBasis: EstimateBasis; }; type QuoteResponse = { lix?: number; spark?: number; maxLix?: number; pricing?: { maxLix?: number; baseLix?: number; premiumLix?: number; totalLix?: number; baseSpark?: number; premiumSpark?: number; totalSpark?: number; }; components?: QuoteComponent[]; quoteToken?: string; quoteId?: string; expiresAt?: string; configVersion?: string; estimateBasis?: EstimateBasis; }; export declare function normalizeQuote(res: QuoteResponse): GenerationQuote; /** * Price a generation BEFORE running it. The request body is the same DTO the generation route * takes, deliberately: it prices the real request rather than a parallel model of it. */ export declare function quoteGeneration(creds: CliCredentials, input: unknown): Promise; export declare function formatQuote(quote: GenerationQuote, balance?: LixBalance | null): string; /** * What a finished job actually cost, in LIX, from either route. * * Dreamer reports `lixSpentTotal`. The asset pipeline reported `units` and never said LIX, so * nothing on that receipt stated the currency — and `units` IS LIX: the backend computes it as * `Number(job.lixSpentTotal || '0')`, same number, different name, no conversion. Read the * canonical field, fall back to the alias, and present one name. */ export declare function receiptLix(job: { lixSpentTotal?: number | string; units?: number; sparkSpentTotal?: number; }): number | null; /** One consistent cost line for both generation routes. */ export declare function formatReceipt(job: { lixSpentTotal?: number | string; units?: number; sparkSpentTotal?: number; providerCostUsd?: number; }): string | null; /** * How long this job has been working, and what happens if it never finishes. * * A cold end-to-end run watched a music generation sit at `stage: "provider"` with LIX held and * `updatedAt` frozen. Nothing in any payload distinguished "the provider is still composing" from * "the process that was calling the provider is gone", there was no stated deadline, and * `recovery.actions` was empty — so after fifteen minutes the run started the duplicate job the * tools explicitly tell you not to start. (The duplicate returned in ten seconds; the original * later surfaced as failed with no charge, i.e. the platform HAD recovered it — silently, with no * way to know that was coming.) * * The platform's actual contract: an interrupted paid provider call is never repeated, and its * hold is released by bounded automatic reconciliation. That is a good contract. It was just * invisible. Say it, with the elapsed time, so waiting is an informed decision rather than a guess. */ export declare function formatWaitState(job: { status?: string; currentStage?: string; stages?: { name: string; status: string; startedAt?: string | null; }[]; updatedAt?: string; openHoldLix?: number; }, now?: Date): string | null; export type JobSummary = { id: string; jobId?: string; status: string; kind?: string; title?: string | null; lixSpentTotal?: number | string; units?: number; openHoldLix?: number; recoverable?: boolean; awaitingApproval?: { gate: string; options?: string[]; } | null; error?: string | null; publishedItemId?: string | null; createdAt?: string; }; export type JobState = 'all' | 'unfinished' | 'failed' | 'published' | 'awaiting_approval'; export declare function listJobs(creds: CliCredentials, query?: { limit?: number; offset?: number; state?: JobState; }): Promise<{ jobs: JobSummary[]; total: number | null; }>; export declare function formatJobs(result: { jobs: JobSummary[]; total: number | null; }): string; export {};