Merge pull request #728 from rdself/codex/normalize-provider-limits-labels

normalize provider limits labels
This commit is contained in:
Diego Rodrigues de Sa e Souza
2026-03-28 23:06:16 -03:00
committed by GitHub
4 changed files with 77 additions and 31 deletions
@@ -4,7 +4,13 @@ import { useTranslations } from "next-intl";
import { useState, useEffect, useCallback, useMemo, useRef } from "react";
import Image from "next/image";
import { parseQuotaData, calculatePercentage, normalizePlanTier, resolvePlanValue } from "./utils";
import {
parseQuotaData,
calculatePercentage,
formatQuotaLabel,
normalizePlanTier,
resolvePlanValue,
} from "./utils";
import Card from "@/shared/components/Card";
import Badge from "@/shared/components/Badge";
import { CardSkeleton } from "@/shared/components/Loading";
@@ -26,7 +32,7 @@ const PROVIDER_CONFIG = {
kiro: { label: "Kiro AI", color: "#FF6B35" },
codex: { label: "OpenAI Codex", color: "#10A37F" },
claude: { label: "Claude Code", color: "#D97757" },
glm: { label: "GLM Coding", color: "#4A90D9" },
glm: { label: "GLM (Z.AI)", color: "#4A90D9" },
"kimi-coding": { label: "Kimi Coding", color: "#1E3A8A" },
};
@@ -42,29 +48,6 @@ const TIER_FILTERS = [
{ key: "unknown", labelKey: "tierUnknown" },
];
// Short model display names for quota bars
function getShortModelName(name) {
const map = {
"gemini-3-pro-high": "G3 Pro",
"gemini-3-pro-low": "G3 Pro Low",
"gemini-3-flash": "G3 Flash",
"gemini-2.5-flash": "G2.5 Flash",
"claude-opus-4-6-thinking": "Opus 4.6 Tk",
"claude-opus-4-5-thinking": "Opus 4.5 Tk",
"claude-opus-4-5": "Opus 4.5",
"claude-sonnet-4-5-thinking": "Sonnet 4.5 Tk",
"claude-sonnet-4-5": "Sonnet 4.5",
chat: "Chat",
completions: "Completions",
premium_interactions: "Premium",
session: "Session",
weekly: "Weekly",
agentic_request: "Agentic",
agentic_request_freetrial: "Agentic (Trial)",
};
return map[name] || name;
}
// Get bar color based on remaining percentage
function getBarColor(remainingPercentage) {
if (remainingPercentage > QUOTA_BAR_GREEN_THRESHOLD) {
@@ -624,7 +607,7 @@ export default function ProviderLimits() {
const remainingPercentage = calculatePercentage(q.used, q.total);
const colors = getBarColor(remainingPercentage);
const cd = formatCountdown(q.resetAt);
const shortName = getShortModelName(q.name);
const shortName = formatQuotaLabel(q.name);
const staleAfterReset = q.staleAfterReset === true;
return (
@@ -10,6 +10,26 @@ const PROVIDER_PLAN_FALLBACKS = new Set([
"github copilot",
]);
const QUOTA_LABEL_MAP: Record<string, string> = {
"gemini-3-pro-high": "G3 Pro",
"gemini-3-pro-low": "G3 Pro Low",
"gemini-3-flash": "G3 Flash",
"gemini-2.5-flash": "G2.5 Flash",
"claude-opus-4-6-thinking": "Opus 4.6 Tk",
"claude-opus-4-5-thinking": "Opus 4.5 Tk",
"claude-opus-4-5": "Opus 4.5",
"claude-sonnet-4-5-thinking": "Sonnet 4.5 Tk",
"claude-sonnet-4-5": "Sonnet 4.5",
chat: "Chat",
completions: "Completions",
premium_interactions: "Premium",
session: "Session",
weekly: "Weekly",
code_review: "Code Review",
agentic_request: "Agentic",
agentic_request_freetrial: "Agentic (Trial)",
};
function toRecord(value: unknown): Record<string, unknown> {
return value && typeof value === "object" && !Array.isArray(value)
? (value as Record<string, unknown>)
@@ -25,6 +45,37 @@ function normalizePlanCandidate(value: unknown) {
return trimmed;
}
function toTitleCaseWords(value: string) {
return value
.split(/[\s_-]+/)
.filter(Boolean)
.map((part) => part.charAt(0).toUpperCase() + part.slice(1))
.join(" ");
}
export function formatQuotaLabel(name: string) {
const trimmed = typeof name === "string" ? name.trim() : "";
if (!trimmed) return "";
const mapped = QUOTA_LABEL_MAP[trimmed];
if (mapped) return mapped;
if (/^session\s*\(\d+[hm]\)$/i.test(trimmed)) {
return "Session";
}
if (/^weekly\s*\(\d+d\)$/i.test(trimmed)) {
return "Weekly";
}
const weeklyModelMatch = trimmed.match(/^weekly\s+(.+?)\s*\(\d+d\)$/i);
if (weeklyModelMatch) {
return `Weekly ${toTitleCaseWords(weeklyModelMatch[1])}`;
}
return trimmed;
}
/**
* Format ISO date string to countdown format (inspired by vscode-antigravity-cockpit)
* @param {string|Date} date - ISO date string or Date object
@@ -204,6 +255,7 @@ export function parseQuotaData(provider, data) {
break;
default:
// Generic fallback for unknown providers
if (data.quotas) {
Object.entries(data.quotas).forEach(([name, quota]: [string, any]) => {
normalizedQuotas.push(normalizeQuotaEntry(name, quota));
+7 -5
View File
@@ -157,13 +157,15 @@ async function getAntigravityUsage(accessToken) {
}
/**
* Claude Usage
* Claude Usage (legacy fallback)
* Real Claude OAuth quota windows are fetched in @omniroute/open-sse/services/usage.ts.
*/
async function getClaudeUsage(accessToken) {
async function getClaudeUsage() {
try {
// Claude OAuth doesn't expose usage API directly
// Could potentially check via inference endpoint
return { message: "Claude connected. Usage tracked per request." };
return {
message:
"Claude connected. Detailed quota windows are handled by the open-sse usage service.",
};
} catch (error) {
return { message: "Unable to fetch Claude usage." };
}
+9
View File
@@ -44,3 +44,12 @@ test("remaining percentage helpers reflect remaining quota and stale resets refi
assert.equal(parsed.length, 1);
assert.equal(providerLimitUtils.calculatePercentage(parsed[0].used, parsed[0].total), 100);
});
test("quota labels normalize session and weekly windows while preserving readable titles", () => {
assert.equal(providerLimitUtils.formatQuotaLabel("session"), "Session");
assert.equal(providerLimitUtils.formatQuotaLabel("session (5h)"), "Session");
assert.equal(providerLimitUtils.formatQuotaLabel("weekly"), "Weekly");
assert.equal(providerLimitUtils.formatQuotaLabel("weekly (7d)"), "Weekly");
assert.equal(providerLimitUtils.formatQuotaLabel("weekly sonnet (7d)"), "Weekly Sonnet");
assert.equal(providerLimitUtils.formatQuotaLabel("code_review"), "Code Review");
});