From 6259cd43987e5669767b9c73f9ab4573aa5c3a60 Mon Sep 17 00:00:00 2001 From: Jeffery Date: Tue, 23 Jun 2026 16:44:43 +0800 Subject: [PATCH] =?UTF-8?q?fix(ai-review=20=E4=BD=BF=E7=94=A8=E9=87=8F):?= =?UTF-8?q?=20resolveRemainingPercent=20=E8=A6=81=E6=B1=82=E6=9C=89?= =?UTF-8?q?=E9=99=90=E6=AD=A3=E6=95=B8=E4=B8=8A=E9=99=90=EF=BC=8C=E9=81=BF?= =?UTF-8?q?=E5=85=8D=20Infinity=20=E4=B8=8A=E9=99=90=E7=AE=97=E5=87=BA=20N?= =?UTF-8?q?aN%=EF=BC=8F=E8=B2=A0=E7=99=BE=E5=88=86=E6=AF=94?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/usage.js | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/app/usage.js b/app/usage.js index 5c24bba..16778a0 100644 --- a/app/usage.js +++ b/app/usage.js @@ -211,23 +211,32 @@ function round1(n) { const RATE_KIND_LABEL = { tokens: 'token', requests: '次數' }; +/** 是否為有限正數(排除 0、負數、NaN、Infinity),避免算出 Infinity%/NaN%/負百分比。 */ +function isFinitePositive(n) { + return Number.isFinite(Number(n)) && Number(n) > 0; +} + /** * 計算「剩餘可用百分比」,依優先序擇一: - * 1. 帳號額度(quota 有上限)→ 剩餘 credits / 上限; - * 2. 速率配額(rate limit header)→ 當前視窗剩餘 / 上限; - * 皆無法取得時回傳 { percent: null, reason }。 + * 1. 帳號額度(quota 有有限正數上限)→ 剩餘 credits / 上限; + * 2. 速率配額(rate limit header,有限正數上限)→ 當前視窗剩餘 / 上限; + * 上限或剩餘為 0/負數/NaN/Infinity 等無效值時不計算,落到 { percent: null, reason }。 */ export function resolveRemainingPercent(quota, rate) { - if (quota?.available && quota.limit != null && Number(quota.limit) > 0) { + if (quota?.available && quota.limit != null && isFinitePositive(quota.limit)) { const limit = Number(quota.limit); const remaining = quota.remaining == null ? limit - num(quota.used) : Number(quota.remaining); - return { percent: round1((remaining / limit) * 100), basis: '帳號額度', remaining, limit, unit: quota.currency || '' }; + if (Number.isFinite(remaining)) { + return { percent: round1((remaining / limit) * 100), basis: '帳號額度', remaining, limit, unit: quota.currency || '' }; + } } - if (rate?.hasData && Number(rate.limit) > 0) { + if (rate?.hasData && isFinitePositive(rate.limit)) { const limit = Number(rate.limit); const remaining = Number(rate.remaining); - const kindLabel = RATE_KIND_LABEL[rate.kind] || rate.kind; - return { percent: round1((remaining / limit) * 100), basis: `速率配額(當前視窗,${kindLabel})`, remaining, limit, unit: '' }; + if (Number.isFinite(remaining)) { + const kindLabel = RATE_KIND_LABEL[rate.kind] || rate.kind; + return { percent: round1((remaining / limit) * 100), basis: `速率配額(當前視窗,${kindLabel})`, remaining, limit, unit: '' }; + } } let reason; if (quota?.available && quota.limit == null) reason = '帳號額度無上限,無法計算百分比';