8000 fix(quota): keep a waiting weekly window after it resets for 0.12.3 by InfinityPacer · Pull Request #51 · InfinityPacer/meterleaf · GitHub
[go: up one dir, main page]

Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,11 @@

## [未发布]

## [0.12.3] - 2026-10-24

- 周额度刚重置、新快照还没到时,账户卡片不再整行消失,改为显示「7d · 等待更新」和重置时刻,新数据到达后自动恢复。新快照要等这个账户再发出请求才会到,5h 用满时可能要等几个小时。上一周期结束超过一周仍无新快照时不再占位。
- 只需升级服务端镜像,本机采集器不用替换。数据库结构未变,升级无需先备份。

## [0.12.2] - 2026-10-24

- 账户额度卡片的每个窗口新增本周期缓存命中率。桌面端显示在「已用」下方,手机端跟在窗口标题行的已用比例后,例如「5h · 已用 58% · 命中 98.7%」。口径与统计页的缓存命中率相同,只统计缓存读取、缓存写入和普通输入都已知的请求。新周期还没有请求或窗口等待更新时不显示,不会显示成 0%。
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "meterleaf",
"version": "0.12.2",
"version": "0.12.3",
"private": true,
"type": "module",
"license": "Apache-2.0",
Expand Down
25 changes: 21 additions & 4 deletions src/web/lib/quota-display.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,28 @@ export function visibleQuotaWindows(
{ key: "fiveHour", label: "5h", window: account.fiveHour, waiting: true },
week,
];
// 周额度刚重置时,新快照要等这个账户再发出请求才会到;5h 用满时可能要等几个小时。
// 5h 有效期间保留周额度占位,但上一周期结束超过一周仍无新快照就不再占位。
if (
!week &&
account.sevenDay &&
windows.length &&
recentlyEnded(account.sevenDay, asOf)
)
return [
...windows,
{ key: "sevenDay", label: "7d", window: account.sevenDay, waiting: true },
];
return windows;
}

const WEEK_MS = 7 * 24 * 60 * 60 * 1000;

function recentlyEnded(window: AccountWindow, asOf: string) {
const endedAt = Date.parse(window.resetsAt ?? "");
return Number.isFinite(endedAt) && Date.parse(asOf) - endedAt < WEEK_MS;
}

/**
* Fable 周额度只计 Fable 请求,排在共享窗口之后。账户整体周额度用尽时所有模型都不可用,
* 紧凑视图只保留用尽的周额度;上游未上报 Fable 额度时不显示,不按套餐推断有无。
Expand All @@ -94,10 +111,10 @@ export function withFableQuotaWindow(
return [...windows, { key: "sevenDayFable", label: "Fable", window }];
// Fable 额度只随 Claude Code 的用量缓存刷新,可能晚于共享周额度很久才更新。共享周额度有效时
// 保留占位,但上一周期结束超过一周仍无新快照,就不再推定上游还在上报这个窗口。
const endedAt = Date.parse(window.resetsAt ?? "");
const recentlyEnded =
Number.isFinite(endedAt) && Date.parse(asOf) - endedAt < WEEK_MS;
if (!recentlyEnded || !windows.some(({ key }) => key === "sevenDay"))
if (
!recentlyEnded(window, asOf) ||
!windows.some(({ key, waiting }) => key === "sevenDay" && !waiting)
)
return windows;
return [
...windows,
Expand Down
51 changes: 49 additions & 2 deletions tests/quota-display.test.ts
F391
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,46 @@ test("a reported five-hour window keeps its place while waiting for a new sample
);
});

test("a just-reset weekly window waits beside an active five-hour window", () => {
// 周额度 4 小时前重置,5h 已用满,账户发不出请求,新的周快照还没到。
const expiredWeek = {
...window,
percent: 93,
resetsAt: "2026-09-08T08:00:00Z",
};
const fiveHour = { ...window, percent: 100 };
const shown = (sevenDay: AccountWindow | null, five = fiveHour) =>
visibleQuotaWindows({ fiveHour: five, sevenDay }, now).map((item) => [
item.key,
item.waiting ?? false,
]);
expect(shown(expiredWeek)).toEqual([
["fiveHour", false],
["sevenDay", true],
]);
// 占位周额度不带旧百分比,账户是否用满只看有效的 5h。
expect(
accountQuotaExhausted(
{ fiveHour: { ...window, percent: 40 }, sevenDay: expiredWeek },
now,
),
).toBe(false);
// 上一周期结束超过一周、上游从未报过周额度,或 5h 也无效时,都不占位。
expect(shown({ ...expiredWeek, resetsAt: "2026-08-31T08:00:00Z" })).toEqual([
["fiveHour", false],
]);
expect(shown(null)).toEqual([["fiveHour", false]]);
expect(shown(expiredWeek, { ...window, resetsAt: now })).toEqual([]);
// Fable 占位依赖有效的共享周额度,周额度本身在等待时不再叠加 Fable 占位。
expect(
withFableQuotaWindow(
visibleQuotaWindows({ fiveHour, sevenDay: expiredWeek }, now),
{ sevenDayFable: expiredWeek },
now,
).map((item) => item.key),
).toEqual(["fiveHour", "sevenDay"]);
});

test("an expired Fable window waits for a new sample instead of disappearing", () => {
const week = { ...window, percent: 10 };
const shown = (sevenDayFable: AccountWindow, sevenDay = week) =>
Expand Down Expand Up @@ -243,8 +283,15 @@ test("weekly reset restores five-hour visibility instead of keeping an expired e
fiveHour: { ...window, percent: 75 },
sevenDay: { ...window, resetsAt: now },
};
expect(visibleQuotaWindows(account, now).map((item) => item.key)).toEqual([
"fiveHour",
// 重置后的周额度只留不带旧百分比的占位,等新快照到达。
expect(
visibleQuotaWindows(account, now).map((item) => [
item.key,
item.waiting ?? false,
]),
).toEqual([
["fiveHour", false],
["sevenDay", true],
]);
expect(accountQuotaExhausted(account, now)).toBe(false);
});
Expand Down
Loading
0