fix(usage): derive window names and unify pin selection (#5903)

* fix(usage): derive window names and unify pin selection

Quota slots do not identify a period. Derive numeric windows and IDs from reported duration and quota scope; keep unknown lengths neutral. Resolve source defaults and explicit pins through one model, with a persisted empty selection distinct from defaults.

* fix(plugins): declare the duration helper host requirement

* fix(usage): verify persisted selections at the storage boundary
This commit is contained in:
Mohamed Boudra
2026-10-02 11:18:13 +01:00
committed by GitHub
parent 6c985769be
commit 73d25317a4
27 changed files with 815 additions and 172 deletions
+21
View File
@@ -4,6 +4,7 @@ import {
toneFromUsedPct,
usedPctOf,
windowFromUsedPct,
windowFromReportedDuration,
} from "./usage.js";
test("shared usage tones preserve the app threshold contract", () => {
@@ -84,3 +85,23 @@ describe("balanceToneFromRemaining", () => {
expect(balanceToneFromRemaining(null)).toBe("default");
});
});
test.each([
[18000, "five_hour", "5-hour", "5h"],
[604800, "weekly", "Weekly", "wk"],
[7200, "7200s", "2-hour", "2h"],
[86400, "86400s", "1-day", "1d"],
[90, "90s", "90-second", "90s"],
[null, "primary", "Primary limit", ""],
])(
"duration %s owns the window's identity and both names",
(durationSeconds, id, label, shortLabel) => {
expect(
windowFromReportedDuration({
durationSeconds: durationSeconds as number | null,
unknown: { id: "primary", label: "Primary limit", shortLabel: "" },
utilizationPct: 11,
}),
).toMatchObject({ id, label, shortLabel, usedPct: 11 });
},
);
+49
View File
@@ -96,6 +96,55 @@ export function windowFromUsedPct(input: {
return window;
}
/**
* Numeric provider windows have one identity and vocabulary, independent of response slots.
* Pass null when the provider omits the duration; reset countdowns are not window lengths.
* Named API fields (weekly, monthly, etc.) use windowFromUsedPct instead.
*/
export function windowFromReportedDuration(input: {
durationSeconds: number | null;
/** Stable quota identity and provider name for a model- or feature-scoped limit. */
scope?: { id: string; label: string };
/** Neutral identity and names when the provider does not report a positive duration. */
unknown: { id: string; label: string; shortLabel: string };
utilizationPct: number | null | undefined;
resetsAt?: string | null;
summary?: boolean;
tone?: UsageWindow["tone"];
}): UsageWindow {
const duration = input.durationSeconds;
const name =
duration !== null && Number.isFinite(duration) && duration > 0
? durationWindowName(duration)
: input.unknown;
const scope = input.scope;
return windowFromUsedPct({
id: scope ? `${scope.id}:${name.id}` : name.id,
label: scope ? `${scope.label} · ${name.label}` : name.label,
shortLabel: scope
? `${scope.label}${name.shortLabel ? ` ${name.shortLabel}` : ""}`
: name.shortLabel,
utilizationPct: input.utilizationPct,
resetsAt: input.resetsAt,
summary: input.summary,
tone: input.tone,
});
}
function durationWindowName(seconds: number): { id: string; label: string; shortLabel: string } {
if (seconds === 604800) return { id: "weekly", label: "Weekly", shortLabel: "wk" };
const id = seconds === 18000 ? "five_hour" : `${seconds}s`;
const units = [
[86400, "day", "d"],
[3600, "hour", "h"],
[60, "minute", "m"],
[1, "second", "s"],
] as const;
const unit = units.find(([size]) => seconds % size === 0) ?? units[units.length - 1]!;
const amount = seconds / unit[0];
return { id, label: `${amount}-${unit[1]}`, shortLabel: `${amount}${unit[2]}` };
}
/**
* The tone scale for anything measured against a known limit, windows and balances alike.
*