/** * 窗口预测 (window-forecast) — will the 5h / weekly Command Code window run OUT * before it resets? * * The rest of the coding-plan family answers 「用了多少」 (额度管理 projects the * MONTH, 窗口 draws the three used-percents). None of them answers the question a * long task actually dies on: 「还有 40 分钟就重置了,可按现在的速度 20 分钟后就触及限额」. * * 「窗口预测」 blue title (13px) * 「118%」 headAfter.big — the WORSE of the two windows' * projected occupancy at its reset (20px) * 「5h · 预计 1h14m 后触及限额」 legend — WHICH window that figure is, and * its verdict (grey 10px) * ────────────────────────────── hairline, then the three rows on the floor * 「5h 118% 预计」 * 「周 63% 预计」 * 「额度重置 2h0m」 the NEARER of the two resets * * WHAT IS PROJECTED (`projectWindow`, pure + exported so it can be reviewed): * The provider reports `used` / `cap` and the wall-clock `resetAt` per window, * so the window's natural start is `resetAt − length` (5h / 7d — the provider's * OWN definition, never "since this session started", which is a different and * unverifiable clock) and the pace is `used ÷ elapsed` over that span: * * fiveHour: used 6, cap 10, resets in 1h → start 4h ago, rate 1.5/h * projected = 6 + 1.5×1 = 7.5 → 75% ⇒ 重置前不会触及限额 * time to cap = (10 − 6) ÷ 1.5 = 2h40m > 1h left * weekly: used 30, cap 40, resets in 2d → start 5d ago, rate 6/day * projected = 30 + 6×2 = 42 → 105% ⇒ 会触及限额 * time to cap = (40 − 30) ÷ 6 = 1d16h < 2d left * ⇒ head figure 105% (the worse of the two), legend 「周 · 预计 1d16h 后触及限额」, * rows 75% / 105%. Every number on the card comes out of that one function. * * DEGRADATION — 「宁可 — 不猜」, the family's rule. A window whose reading cannot * support a projection prints `—` muted and never borrows another window's pace: * - `used` / `cap` / `resetAt` missing or non-finite, or `cap <= 0`; * - `resetAt` in the past — a stale payload; the window has already rolled and * extrapolating to a past instant is meaningless; * - `elapsed <= 0` (the reset is further out than the window is long: a clock or * timezone artefact) — the spec's own line — and `elapsed < MIN_ELAPSED_MS`, * its near-degenerate case: extrapolating the first seconds of a fresh window * multiplies one call's cost into a four-digit percent. * Both windows unprojectable ⇒ `render` returns null (the card has nothing to * say). An absent payload with a recorded host error also returns null: 「未配置 * Command Code」 is cc-whoami's and 额度管理's sentence, and a third copy of it * would add no fact (SPECS §7's dedup rule). * * TONE DIRECTION — this is OCCUPANCY, so HIGH IS BAD (danger / warn) — the * OPPOSITE of the cache hit rate. Thresholds: `> 1.0` danger (the cap really is * reached before the reset) and `> 0.9` warn. The 10% band is deliberate: the * projection is a straight-line extrapolation, and one burst of long turns eats * 10% of a window, so a window at 91% "in theory safe" deserves amber before it * turns red. The FIGURE carries the same two rungs (`valueTone` gained `warn` with * this batch), so the head never reads calmer than the rows below it — and the * renderer still never guesses a tone from a ratio: the widget decides. * * SCOPE — `stats.commandCode.credits.windowLimits` only, the FOURTH official * slice of ONE Command Code account (the payload's first pool member). `used` / * `cap` are Command Code CREDITS, never tokens. `usageData` (OpenCode's own * rolling / weekly / monthly percentages) is deliberately NOT mixed in: the two * are different accounts in different units, and blending them would print a * precise-looking number that is exactly wrong at the moment the card matters. */ import { defineWidget } from '../../client/lib/contract/helpers'; import type { CommandCodeWindow, WidgetRenderMeta, WidgetStats } from '../../client/lib/contract/types'; export type WindowKey = 'fiveHour' | 'weekly'; /** What one window's reading supports. `null` = not projectable (print `—`). */ export interface WindowForecast { /** projected ÷ cap at the reset; `> 1` ⇒ the cap is reached first. */ ratio: number; /** ms from `now` until the cap is reached (0 = already at / over it). */ fillMs: number; /** ms from `now` to the window's reset (always > 0 when a forecast exists — * a reset in the past is one of the unprojectable cases). */ resetMs: number; } /** * Project ONE window to its reset, or `null` when the reading cannot carry a * projection (every case is listed in the header). Pure: the caller passes the * clock, so the arithmetic is reviewable without a session. * * @param win - the window slice (`used` / `cap` / `resetAt`, epoch ms). * @param lengthMs - the window's own length (5h / 7d). * @param now - epoch ms of the reading. */ export declare function projectWindow(win: CommandCodeWindow | null | undefined, lengthMs: number, now: number): WindowForecast | null; /** * The card's duration ladder for its two countdowns (time-to-full, time-to-reset). * * Under an hour it IS the shared `fmtDuration` (`45.2s` / `12m30s`). Above it, the * shared formatter only has minutes and seconds — a 2h11m wait prints `131m0s` * and a weekly window `10080m0s`, eight characters that overrun the ~126px grey * legend line and ellipsize it, which reads as a truncated error rather than a * countdown. So the two upper rungs (`2h11m`, `6d23h`) are added HERE, in this * unit, instead of changing a formatter every other card reads. Both of this * card's durations go through this one function, so their units always agree. */ export declare function fmtSpan(ms: number): string; declare function windowForecastRender(stats: WidgetStats, meta?: WidgetRenderMeta): ReturnType['render']>>; declare const _default: { id: string; name: () => string; desc: () => string; builtin: true; group: string; sizes: "2x2"[]; simToggle: () => string; render: typeof windowForecastRender; example: { stats: Partial; sim: {}; simSteps: ({ aheadMs?: undefined; } | { aheadMs: number; })[]; }; }; export default _default;