From aace2fcbd02a6ccb07a5ac543dc5929bb356e42e Mon Sep 17 00:00:00 2001 From: Jan Leon Date: Wed, 6 May 2026 23:02:08 +0000 Subject: [PATCH] feat: enhance GLM quota handling and add new quota labels for Z.AI --- open-sse/services/usage.ts | 30 +++++++++++++--- .../usage/components/ProviderLimits/utils.tsx | 3 ++ tests/unit/provider-limits-ui.test.ts | 36 +++++++++++++------ tests/unit/usage-service-hardening.test.ts | 31 +++++++++++----- 4 files changed, 76 insertions(+), 24 deletions(-) diff --git a/open-sse/services/usage.ts b/open-sse/services/usage.ts index aa96d3afd0..a10e8ee746 100644 --- a/open-sse/services/usage.ts +++ b/open-sse/services/usage.ts @@ -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): Record { + const ordered: Record = {}; + + 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) { 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 = { 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", }; diff --git a/tests/unit/provider-limits-ui.test.ts b/tests/unit/provider-limits-ui.test.ts index 48c365d40a..515f63780e 100644 --- a/tests/unit/provider-limits-ui.test.ts +++ b/tests/unit/provider-limits-ui.test.ts @@ -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); }); diff --git a/tests/unit/usage-service-hardening.test.ts b/tests/unit/usage-service-hardening.test.ts index d41eaa8644..d780a911ec 100644 --- a/tests/unit/usage-service-hardening.test.ts +++ b/tests/unit/usage-service-hardening.test.ts @@ -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(