fix(quota): stop showing misleading OpenRouter percentages (#1127)
* fix(quota): stop showing misleading OpenRouter percentages Fixes #1085 * fix(quota): clean up OpenRouter credit labels --------- Co-authored-by: Bohdan Triapitsyn <artmore@protonmail.com>
This commit is contained in:
committed by
GitHub
co-authored by
Bohdan Triapitsyn
parent
b65edc3436
commit
3fbcdbc3dc
@@ -39,7 +39,7 @@ import { cn, hasModifier } from '@/lib/utils';
|
|||||||
import { McpDropdownContent } from '@/components/mcp/McpDropdown';
|
import { McpDropdownContent } from '@/components/mcp/McpDropdown';
|
||||||
import { McpIcon } from '@/components/icons/McpIcon';
|
import { McpIcon } from '@/components/icons/McpIcon';
|
||||||
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
||||||
import { formatPercent, formatWindowLabel, QUOTA_PROVIDERS, calculatePace, calculateExpectedUsagePercent } from '@/lib/quota';
|
import { formatQuotaValueLabel, formatWindowLabel, QUOTA_PROVIDERS, calculatePace, calculateExpectedUsagePercent } from '@/lib/quota';
|
||||||
import { UsageProgressBar } from '@/components/sections/usage/UsageProgressBar';
|
import { UsageProgressBar } from '@/components/sections/usage/UsageProgressBar';
|
||||||
import { PaceIndicator } from '@/components/sections/usage/PaceIndicator';
|
import { PaceIndicator } from '@/components/sections/usage/PaceIndicator';
|
||||||
import { updateDesktopSettings } from '@/lib/persistence';
|
import { updateDesktopSettings } from '@/lib/persistence';
|
||||||
@@ -446,6 +446,7 @@ const DesktopServicesMenu = React.memo(function DesktopServicesMenu({
|
|||||||
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
||||||
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
||||||
: null;
|
: null;
|
||||||
|
const metricLabel = formatQuotaValueLabel(window.valueLabel, displayPercent);
|
||||||
return (
|
return (
|
||||||
<div key={`${group.providerId}-${label}`} className="flex flex-col gap-1.5">
|
<div key={`${group.providerId}-${label}`} className="flex flex-col gap-1.5">
|
||||||
<div className="flex min-w-0 items-center justify-between gap-3">
|
<div className="flex min-w-0 items-center justify-between gap-3">
|
||||||
@@ -458,7 +459,7 @@ const DesktopServicesMenu = React.memo(function DesktopServicesMenu({
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<span className="typography-ui-label tabular-nums text-foreground">
|
<span className="typography-ui-label tabular-nums text-foreground">
|
||||||
{formatPercent(displayPercent) === '-' ? '' : formatPercent(displayPercent)}
|
{metricLabel === '-' ? '' : metricLabel}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<UsageProgressBar
|
<UsageProgressBar
|
||||||
@@ -496,12 +497,13 @@ const DesktopServicesMenu = React.memo(function DesktopServicesMenu({
|
|||||||
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
||||||
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
||||||
: null;
|
: null;
|
||||||
|
const metricLabel = formatQuotaValueLabel(window.valueLabel, displayPercent);
|
||||||
return (
|
return (
|
||||||
<div key={`${group.providerId}-${modelName}`} className="flex flex-col gap-1.5">
|
<div key={`${group.providerId}-${modelName}`} className="flex flex-col gap-1.5">
|
||||||
<div className="flex min-w-0 items-center justify-between gap-3">
|
<div className="flex min-w-0 items-center justify-between gap-3">
|
||||||
<span className="truncate typography-micro text-muted-foreground">{getDisplayModelName(modelName)}</span>
|
<span className="truncate typography-micro text-muted-foreground">{getDisplayModelName(modelName)}</span>
|
||||||
<span className="typography-ui-label tabular-nums text-foreground">
|
<span className="typography-ui-label tabular-nums text-foreground">
|
||||||
{formatPercent(displayPercent) === '-' ? '' : formatPercent(displayPercent)}
|
{metricLabel === '-' ? '' : metricLabel}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<UsageProgressBar
|
<UsageProgressBar
|
||||||
@@ -2194,6 +2196,7 @@ export const Header: React.FC<HeaderProps> = ({
|
|||||||
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
||||||
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
||||||
: null;
|
: null;
|
||||||
|
const metricLabel = formatQuotaValueLabel(window.valueLabel, displayPercent);
|
||||||
return (
|
return (
|
||||||
<div key={`${group.providerId}-${label}`} className="flex flex-col gap-1.5">
|
<div key={`${group.providerId}-${label}`} className="flex flex-col gap-1.5">
|
||||||
<div className="flex min-w-0 items-center justify-between gap-3">
|
<div className="flex min-w-0 items-center justify-between gap-3">
|
||||||
@@ -2206,7 +2209,7 @@ export const Header: React.FC<HeaderProps> = ({
|
|||||||
) : null}
|
) : null}
|
||||||
</div>
|
</div>
|
||||||
<span className="typography-ui-label text-foreground tabular-nums">
|
<span className="typography-ui-label text-foreground tabular-nums">
|
||||||
{formatPercent(displayPercent) === '-' ? '' : formatPercent(displayPercent)}
|
{metricLabel === '-' ? '' : metricLabel}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<UsageProgressBar
|
<UsageProgressBar
|
||||||
@@ -2257,12 +2260,13 @@ export const Header: React.FC<HeaderProps> = ({
|
|||||||
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
||||||
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
||||||
: null;
|
: null;
|
||||||
|
const metricLabel = formatQuotaValueLabel(window.valueLabel, displayPercent);
|
||||||
return (
|
return (
|
||||||
<div key={`${group.providerId}-${modelName}`} className="flex flex-col gap-1.5">
|
<div key={`${group.providerId}-${modelName}`} className="flex flex-col gap-1.5">
|
||||||
<div className="flex min-w-0 items-center justify-between gap-3">
|
<div className="flex min-w-0 items-center justify-between gap-3">
|
||||||
<span className="truncate typography-micro text-muted-foreground">{getDisplayModelName(modelName)}</span>
|
<span className="truncate typography-micro text-muted-foreground">{getDisplayModelName(modelName)}</span>
|
||||||
<span className="typography-ui-label text-foreground tabular-nums">
|
<span className="typography-ui-label text-foreground tabular-nums">
|
||||||
{formatPercent(displayPercent) === '-' ? '' : formatPercent(displayPercent)}
|
{metricLabel === '-' ? '' : metricLabel}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<UsageProgressBar
|
<UsageProgressBar
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import { useI18n } from '@/lib/i18n';
|
|||||||
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
import { ProviderLogo } from '@/components/ui/ProviderLogo';
|
||||||
import { UsageProgressBar } from '@/components/sections/usage/UsageProgressBar';
|
import { UsageProgressBar } from '@/components/sections/usage/UsageProgressBar';
|
||||||
import { PaceIndicator } from '@/components/sections/usage/PaceIndicator';
|
import { PaceIndicator } from '@/components/sections/usage/PaceIndicator';
|
||||||
import { formatPercent, formatWindowLabel, QUOTA_PROVIDERS, calculatePace, calculateExpectedUsagePercent } from '@/lib/quota';
|
import { formatQuotaValueLabel, formatWindowLabel, QUOTA_PROVIDERS, calculatePace, calculateExpectedUsagePercent } from '@/lib/quota';
|
||||||
import { useQuotaAutoRefresh, useQuotaStore } from '@/stores/useQuotaStore';
|
import { useQuotaAutoRefresh, useQuotaStore } from '@/stores/useQuotaStore';
|
||||||
import { useUpdateStore } from '@/stores/useUpdateStore';
|
import { useUpdateStore } from '@/stores/useUpdateStore';
|
||||||
import { updateDesktopSettings } from '@/lib/persistence';
|
import { updateDesktopSettings } from '@/lib/persistence';
|
||||||
@@ -823,6 +823,7 @@ const VSCodeHeader: React.FC<VSCodeHeaderProps> = ({ title, showBack, onBack, on
|
|||||||
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
? 100 - calculateExpectedUsagePercent(paceInfo.elapsedRatio)
|
||||||
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
: calculateExpectedUsagePercent(paceInfo.elapsedRatio))
|
||||||
: null;
|
: null;
|
||||||
|
const metricLabel = formatQuotaValueLabel(window.valueLabel, displayPercent);
|
||||||
return (
|
return (
|
||||||
<DropdownMenuItem
|
<DropdownMenuItem
|
||||||
key={`${group.providerId}-${label}`}
|
key={`${group.providerId}-${label}`}
|
||||||
@@ -833,7 +834,7 @@ const VSCodeHeader: React.FC<VSCodeHeaderProps> = ({ title, showBack, onBack, on
|
|||||||
<span className="flex min-w-0 items-center justify-between gap-3">
|
<span className="flex min-w-0 items-center justify-between gap-3">
|
||||||
<span className="truncate typography-micro text-muted-foreground">{formatWindowLabel(label)}</span>
|
<span className="truncate typography-micro text-muted-foreground">{formatWindowLabel(label)}</span>
|
||||||
<span className="typography-ui-label text-foreground tabular-nums">
|
<span className="typography-ui-label text-foreground tabular-nums">
|
||||||
{formatPercent(displayPercent) === '-' ? '' : formatPercent(displayPercent)}
|
{metricLabel === '-' ? '' : metricLabel}
|
||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
<UsageProgressBar
|
<UsageProgressBar
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import type { UsageWindow } from '@/types';
|
import type { UsageWindow } from '@/types';
|
||||||
import { formatPercent, formatWindowLabel, calculatePace, calculateExpectedUsagePercent } from '@/lib/quota';
|
import { formatQuotaValueLabel, formatWindowLabel, calculatePace, calculateExpectedUsagePercent } from '@/lib/quota';
|
||||||
import { UsageProgressBar } from './UsageProgressBar';
|
import { UsageProgressBar } from './UsageProgressBar';
|
||||||
import { PaceIndicator } from './PaceIndicator';
|
import { PaceIndicator } from './PaceIndicator';
|
||||||
import { useQuotaStore } from '@/stores/useQuotaStore';
|
import { useQuotaStore } from '@/stores/useQuotaStore';
|
||||||
@@ -26,7 +26,7 @@ export const UsageCard: React.FC<UsageCardProps> = ({
|
|||||||
const displayMode = useQuotaStore((state) => state.displayMode);
|
const displayMode = useQuotaStore((state) => state.displayMode);
|
||||||
const displayPercent = displayMode === 'remaining' ? window.remainingPercent : window.usedPercent;
|
const displayPercent = displayMode === 'remaining' ? window.remainingPercent : window.usedPercent;
|
||||||
const barLabel = displayMode === 'remaining' ? 'remaining' : 'used';
|
const barLabel = displayMode === 'remaining' ? 'remaining' : 'used';
|
||||||
const percentLabel = window.valueLabel ?? formatPercent(displayPercent);
|
const percentLabel = formatQuotaValueLabel(window.valueLabel, displayPercent);
|
||||||
const resetLabel = window.resetAfterFormatted ?? window.resetAtFormatted ?? '';
|
const resetLabel = window.resetAfterFormatted ?? window.resetAtFormatted ?? '';
|
||||||
const windowLabel = formatWindowLabel(title);
|
const windowLabel = formatWindowLabel(title);
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ export type { QuotaProviderMeta } from './providers';
|
|||||||
export {
|
export {
|
||||||
clampPercent,
|
clampPercent,
|
||||||
formatPercent,
|
formatPercent,
|
||||||
|
formatQuotaValueLabel,
|
||||||
resolveUsageTone,
|
resolveUsageTone,
|
||||||
formatWindowLabel,
|
formatWindowLabel,
|
||||||
calculatePace,
|
calculatePace,
|
||||||
|
|||||||
@@ -12,6 +12,13 @@ export const formatPercent = (value: number | null): string => {
|
|||||||
return `${Math.round(value)}%`;
|
return `${Math.round(value)}%`;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const formatQuotaValueLabel = (
|
||||||
|
valueLabel: string | null | undefined,
|
||||||
|
percent: number | null,
|
||||||
|
): string => {
|
||||||
|
return valueLabel ?? formatPercent(percent);
|
||||||
|
};
|
||||||
|
|
||||||
export const resolveUsageTone = (percent: number | null): 'safe' | 'warn' | 'critical' => {
|
export const resolveUsageTone = (percent: number | null): 'safe' | 'warn' | 'critical' => {
|
||||||
if (percent === null) {
|
if (percent === null) {
|
||||||
return 'safe';
|
return 'safe';
|
||||||
|
|||||||
@@ -1420,10 +1420,10 @@ export const fetchOpenRouterQuota = async (): Promise<ProviderResult> => {
|
|||||||
const remaining = totalCredits !== null && totalUsage !== null
|
const remaining = totalCredits !== null && totalUsage !== null
|
||||||
? Math.max(0, totalCredits - totalUsage)
|
? Math.max(0, totalCredits - totalUsage)
|
||||||
: null;
|
: null;
|
||||||
const usedPercent = totalCredits && totalUsage !== null
|
let valueLabel: string | null = null;
|
||||||
? Math.max(0, Math.min(100, (totalUsage / totalCredits) * 100))
|
if (remaining !== null && totalUsage !== null) {
|
||||||
: null;
|
valueLabel = `$${formatMoney(remaining)} left · $${formatMoney(totalUsage)} spent`;
|
||||||
const valueLabel = remaining !== null ? `$${formatMoney(remaining)} remaining` : null;
|
}
|
||||||
|
|
||||||
return buildResult({
|
return buildResult({
|
||||||
providerId: 'openrouter',
|
providerId: 'openrouter',
|
||||||
@@ -1433,7 +1433,7 @@ export const fetchOpenRouterQuota = async (): Promise<ProviderResult> => {
|
|||||||
usage: {
|
usage: {
|
||||||
windows: {
|
windows: {
|
||||||
credits: toUsageWindow({
|
credits: toUsageWindow({
|
||||||
usedPercent,
|
usedPercent: null,
|
||||||
windowSeconds: null,
|
windowSeconds: null,
|
||||||
resetAt: null,
|
resetAt: null,
|
||||||
valueLabel,
|
valueLabel,
|
||||||
|
|||||||
@@ -59,14 +59,14 @@ export const fetchQuota = async () => {
|
|||||||
const remaining = totalCredits !== null && totalUsage !== null
|
const remaining = totalCredits !== null && totalUsage !== null
|
||||||
? Math.max(0, totalCredits - totalUsage)
|
? Math.max(0, totalCredits - totalUsage)
|
||||||
: null;
|
: null;
|
||||||
const usedPercent = totalCredits && totalUsage !== null
|
let valueLabel = null;
|
||||||
? Math.max(0, Math.min(100, (totalUsage / totalCredits) * 100))
|
if (remaining !== null && totalUsage !== null) {
|
||||||
: null;
|
valueLabel = `$${formatMoney(remaining)} left · $${formatMoney(totalUsage)} spent`;
|
||||||
const valueLabel = remaining !== null ? `$${formatMoney(remaining)} remaining` : null;
|
}
|
||||||
|
|
||||||
const windows = {
|
const windows = {
|
||||||
credits: toUsageWindow({
|
credits: toUsageWindow({
|
||||||
usedPercent,
|
usedPercent: null,
|
||||||
windowSeconds: null,
|
windowSeconds: null,
|
||||||
resetAt: null,
|
resetAt: null,
|
||||||
valueLabel
|
valueLabel
|
||||||
|
|||||||
Reference in New Issue
Block a user