feat: enhance GLM quota handling and add new quota labels for Z.AI

This commit is contained in:
Jan Leon
2026-05-06 23:02:08 +00:00
parent 5c67df5508
commit aace2fcbd0
4 changed files with 76 additions and 24 deletions

View File

@@ -515,21 +515,41 @@ async function getCrofUsage(apiKey: string) {
return { quotas };
}
function getGlmQuotaLabel(type: unknown): string | null {
const GLM_QUOTA_ORDER = ["5 Hours Quota", "Weekly Quota", "Monthly Tools", "Tokens", "Time Limit"];
function getGlmQuotaLabel(type: unknown, unit: unknown): string | null {
const normalized = typeof type === "string" ? type.trim().toUpperCase() : "";
const unitValue = toNumber(unit, -1);
switch (normalized) {
case "TOKENS_LIMIT":
case "TOKEN_LIMIT":
return "tokens";
if (unitValue === 3) return "5 Hours Quota";
if (unitValue === 6) return "Weekly Quota";
return "Tokens";
case "TIME_LIMIT":
case "TIME_USAGE_LIMIT":
return "time_limit";
if (unitValue === 5) return "Monthly Tools";
return "Time Limit";
default:
return null;
}
}
function orderGlmQuotas(quotas: Record<string, UsageQuota>): Record<string, UsageQuota> {
const ordered: Record<string, UsageQuota> = {};
for (const key of GLM_QUOTA_ORDER) {
if (quotas[key]) ordered[key] = quotas[key];
}
for (const [key, quota] of Object.entries(quotas)) {
if (!ordered[key]) ordered[key] = quota;
}
return ordered;
}
async function getGlmUsage(apiKey: string, providerSpecificData?: Record<string, unknown>) {
if (!apiKey) {
return { message: "API key not available. Add a coding plan API key to view usage." };
@@ -556,7 +576,7 @@ async function getGlmUsage(apiKey: string, providerSpecificData?: Record<string,
for (const limit of limits) {
const src = toRecord(limit);
const label = getGlmQuotaLabel(src.type);
const label = getGlmQuotaLabel(src.type, src.unit);
if (!label) continue;
const usedPercent = toNumber(src.percentage, 0);
@@ -578,7 +598,7 @@ async function getGlmUsage(apiKey: string, providerSpecificData?: Record<string,
? levelRaw.charAt(0).toUpperCase() + levelRaw.slice(1).toLowerCase()
: "Unknown";
return { plan, quotas };
return { plan, quotas: orderGlmQuotas(quotas) };
}
/**

View File

@@ -22,6 +22,9 @@ const QUOTA_LABEL_MAP: Record<string, string> = {
agentic_request_freetrial: "Agentic (Trial)",
credits: "AI Credits",
models: "Models",
"5 Hours Quota": "5 Hours",
"Weekly Quota": "Weekly",
"Monthly Tools": "Monthly Tools",
tokens: "Tokens",
time_limit: "Time Limit",
};

View File

@@ -95,15 +95,29 @@ test("MiniMax quota payloads use generic provider parsing and stale resets still
assert.equal(providerLimitUtils.formatQuotaLabel(parsed[1].name), "Weekly");
});
test("Z.AI quota labels render token and time limit usage", () => {
assert.equal(providerLimitUtils.formatQuotaLabel("tokens"), "Tokens");
assert.equal(providerLimitUtils.formatQuotaLabel("time_limit"), "Time Limit");
test("Z.AI quota labels render 5h, weekly and monthly tool usage", () => {
assert.equal(providerLimitUtils.formatQuotaLabel("5 Hours Quota"), "5 Hours");
assert.equal(providerLimitUtils.formatQuotaLabel("Weekly Quota"), "Weekly");
assert.equal(providerLimitUtils.formatQuotaLabel("Monthly Tools"), "Monthly Tools");
const future = new Date(Date.now() + 5 * 60_000).toISOString();
const parsed = providerLimitUtils.parseQuotaData("zai", {
quotas: {
tokens: { used: 18, total: 100, remaining: 82, remainingPercentage: 82, resetAt: future },
time_limit: {
"5 Hours Quota": {
used: 15,
total: 100,
remaining: 85,
remainingPercentage: 85,
resetAt: future,
},
"Weekly Quota": {
used: 4,
total: 100,
remaining: 96,
remainingPercentage: 96,
resetAt: future,
},
"Monthly Tools": {
used: 0,
total: 100,
remaining: 100,
@@ -113,9 +127,11 @@ test("Z.AI quota labels render token and time limit usage", () => {
},
});
assert.equal(parsed.length, 2);
assert.equal(parsed[0].name, "tokens");
assert.equal(parsed[0].remainingPercentage, 82);
assert.equal(parsed[1].name, "time_limit");
assert.equal(parsed[1].remainingPercentage, 100);
assert.equal(parsed.length, 3);
assert.equal(parsed[0].name, "5 Hours Quota");
assert.equal(parsed[0].remainingPercentage, 85);
assert.equal(parsed[1].name, "Weekly Quota");
assert.equal(parsed[1].remainingPercentage, 96);
assert.equal(parsed[2].name, "Monthly Tools");
assert.equal(parsed[2].remainingPercentage, 100);
});

View File

@@ -902,11 +902,21 @@ test("usage service covers Qwen, Qoder, GLM, Z.AI and GLMT branches", async () =
limits: [
{
type: "TOKENS_LIMIT",
percentage: "64",
unit: 3,
usage: 15,
currentValue: 85,
percentage: "15",
nextResetTime: Date.now() + 120_000,
},
{
type: "TOKENS_LIMIT",
unit: 6,
percentage: "64",
nextResetTime: Date.now() + 604_800_000,
},
{
type: "TIME_LIMIT",
unit: 5,
percentage: "7",
nextResetTime: Date.now() + 300_000,
},
@@ -930,18 +940,21 @@ test("usage service covers Qwen, Qoder, GLM, Z.AI and GLMT branches", async () =
providerSpecificData: { apiRegion: "invalid-region" },
});
assert.equal(glm.plan, "Pro");
assert.equal(glm.quotas.tokens.used, 64);
assert.equal(glm.quotas.tokens.remaining, 36);
assert.equal(glm.quotas.time_limit.used, 7);
assert.equal(glm.quotas.time_limit.remaining, 93);
assert.equal(glm.quotas["5 Hours Quota"].used, 15);
assert.equal(glm.quotas["5 Hours Quota"].remaining, 85);
assert.equal(glm.quotas["Weekly Quota"].used, 64);
assert.equal(glm.quotas["Weekly Quota"].remaining, 36);
assert.equal(glm.quotas["Monthly Tools"].used, 7);
assert.equal(glm.quotas["Monthly Tools"].remaining, 93);
const zai: any = await usageService.getUsageForProvider({
provider: "zai",
apiKey: "glm-key",
});
assert.equal(zai.plan, "Pro");
assert.equal(zai.quotas.tokens.used, 64);
assert.equal(zai.quotas.time_limit.remaining, 93);
assert.equal(zai.quotas["5 Hours Quota"].used, 15);
assert.equal(zai.quotas["Weekly Quota"].remaining, 36);
assert.equal(zai.quotas["Monthly Tools"].remaining, 93);
const glmt: any = await usageService.getUsageForProvider({
provider: "glmt",
@@ -949,8 +962,8 @@ test("usage service covers Qwen, Qoder, GLM, Z.AI and GLMT branches", async () =
providerSpecificData: { apiRegion: "international" },
});
assert.equal(glmt.plan, "Pro");
assert.equal(glmt.quotas.tokens.used, 64);
assert.equal(glmt.quotas.tokens.remaining, 36);
assert.equal(glmt.quotas["5 Hours Quota"].used, 15);
assert.equal(glmt.quotas["Weekly Quota"].remaining, 36);
globalThis.fetch = async () => new Response("nope", { status: 401 });
await assert.rejects(