feat: add /quota slash command for GLM Coding Plan usage display#10
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a new /quota slash command that queries the GLM Coding Plan usage API directly and displays the results as a formatted plain-text card. It includes an in-memory TTL cache to debounce requests, an HTTP client, robust response parsing with percentage fallbacks, and comprehensive unit tests. The review feedback suggests several improvements to robustness and type safety: defensively handling missing or malformed properties in item.detail to prevent runtime crashes, explicitly handling HTTP 401 and 403 status codes to correctly return authentication errors, and avoiding non-null assertions (!) when checking payload data.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
| if (item.detail && item.detail.length > 0) { | ||
| const last = item.detail.length - 1; | ||
| item.detail.forEach((d, i) => { | ||
| const branch = i === last ? "└" : "├"; | ||
| const name = d.modelCode.padEnd(DETAIL_LABEL_WIDTH); | ||
| lines.push(` ${branch} ${name}${d.usage}`); | ||
| }); | ||
| } |
There was a problem hiding this comment.
Defensively handle potential missing or malformed properties in item.detail elements (such as d.modelCode or d.usage) to prevent runtime TypeError crashes if the API response structure changes or contains unexpected values.
if (item.detail && item.detail.length > 0) {
const last = item.detail.length - 1;
item.detail.forEach((d, i) => {
if (!d) return;
const branch = i === last ? "└" : "├";
const modelCode = typeof d.modelCode === "string" ? d.modelCode : "unknown";
const usage = typeof d.usage === "number" ? d.usage : 0;
const name = modelCode.padEnd(DETAIL_LABEL_WIDTH);
lines.push(` ${branch} ${name}${usage}`);
});
}| // HTTP-level rate limit. | ||
| if (envelope.status === 429 || isRateLimitedMessage(envelope.text)) { | ||
| return { kind: "rate_limited" }; | ||
| } |
There was a problem hiding this comment.
Explicitly handle HTTP 401 (Unauthorized) and 403 (Forbidden) status codes at the top of parseQuotaEnvelope. If the API gateway returns these status codes with an empty or non-JSON body, the current implementation would fall through and return unavailable instead of auth_error.
// HTTP-level rate limit or auth errors.
if (envelope.status === 429 || isRateLimitedMessage(envelope.text)) {
return { kind: "rate_limited" };
}
if (envelope.status === 401 || envelope.status === 403) {
return { kind: "auth_error" };
}| return { kind: "unavailable" }; | ||
| } | ||
|
|
||
| const limits = Array.isArray(payload.data?.limits) ? payload.data!.limits! : []; |
There was a problem hiding this comment.
Avoid using non-null assertion operators (!) by safely checking if payload.data and payload.data.limits exist. This improves type safety and readability.
| const limits = Array.isArray(payload.data?.limits) ? payload.data!.limits! : []; | |
| const limits = payload.data && Array.isArray(payload.data.limits) ? payload.data.limits : []; |
Only freshly created sessions (session/new) are eligible for auto-title on first end_turn. Resumed/loaded sessions already carry a title from their history; the previous set-once gate only guarded within-session re-entry, not the first message after a resume/load, so it would clobber the existing title. Add a titleEligibleSessions set populated only by newSession to gate the title write.
The queryQuota orchestration tests called loadZcodeCredentials() at runtime, which reads ~/.zcode/v2/config.json. Locally that file exists, but CI has no such file, so ANTHROPIC_API_KEY came back empty and fetchQuotaResponse threw 'no apiKey' before fetch was ever called — landing as 'unavailable' and the fetch spy recording zero calls. Mock the credentials module so the tests are environment-independent.
Summary
Adds a
/quotaslash command that queries the GLM Coding Plan usage API directly (no ZCode backend involvement) and renders a multi-line progress-bar card showing remaining usage across windows (5h / weekly / MCP).src/quota/module (client, parse, format, cache, types, index) — pure, testable units with a singlequeryQuota()orchestration entry point.src/handlers/slash.ts—/quotais the exception: it never calls ZCode, always returns a status line (success card or an error fallback), and never throws.SLASH_COMMANDSso it appears in the editor's/completion menu.Behavior
unavailable; 401/auth text →auth_error; 429/rate-limit text →rate_limited.api.z.aibaseURL → intl endpoint, else CN (open.bigmodel.cn). Credentials reuse the active provider's apiKey from~/.zcode/v2/config.json.remaining+currentValue→currentValue/usage→ legacypercentage), so inconsistent field sets across limit kinds still render.Tests
tests/quota.test.ts— 26 tests covering parsing (percentage fallbacks, label derivation, error states), formatting (bar rendering, detail sub-lines), TTL cache, andqueryQuotaorchestration (cache hit / fetch failure → unavailable) with injected fakes (no real network).Checklist
pnpm typecheckpnpm lint(0 errors)pnpm testpnpm build