fix(quota): show all Z.ai usage windows
This commit is contained in:
@@ -4,8 +4,6 @@ import {
|
||||
normalizeAuthEntry,
|
||||
buildResult,
|
||||
toUsageWindow,
|
||||
toNumber,
|
||||
toTimestamp,
|
||||
resolveWindowSeconds,
|
||||
resolveWindowLabel,
|
||||
normalizeTimestamp
|
||||
@@ -57,14 +55,13 @@ export const fetchQuota = async () => {
|
||||
|
||||
const payload = await response.json();
|
||||
const limits = Array.isArray(payload?.data?.limits) ? payload.data.limits : [];
|
||||
const tokensLimit = limits.find((limit) => limit?.type === 'TOKENS_LIMIT');
|
||||
const windowSeconds = resolveWindowSeconds(tokensLimit);
|
||||
const windowLabel = resolveWindowLabel(windowSeconds);
|
||||
const resetAt = tokensLimit?.nextResetTime ? normalizeTimestamp(tokensLimit.nextResetTime) : null;
|
||||
const usedPercent = typeof tokensLimit?.percentage === 'number' ? tokensLimit.percentage : null;
|
||||
|
||||
const windows = {};
|
||||
if (tokensLimit) {
|
||||
for (const tokensLimit of limits.filter((limit) => limit?.type === 'TOKENS_LIMIT')) {
|
||||
const windowSeconds = resolveWindowSeconds(tokensLimit);
|
||||
const windowLabel = resolveWindowLabel(windowSeconds);
|
||||
const resetAt = tokensLimit?.nextResetTime ? normalizeTimestamp(tokensLimit.nextResetTime) : null;
|
||||
const usedPercent = typeof tokensLimit?.percentage === 'number' ? tokensLimit.percentage : null;
|
||||
|
||||
windows[windowLabel] = toUsageWindow({
|
||||
usedPercent,
|
||||
windowSeconds,
|
||||
@@ -72,6 +69,15 @@ export const fetchQuota = async () => {
|
||||
});
|
||||
}
|
||||
|
||||
const mcpToolsTimeLimit = limits.find((limit) => limit?.type === 'TIME_LIMIT');
|
||||
if (mcpToolsTimeLimit) {
|
||||
windows['MCP Tools'] = toUsageWindow({
|
||||
usedPercent: typeof mcpToolsTimeLimit.percentage === 'number' ? mcpToolsTimeLimit.percentage : null,
|
||||
windowSeconds: 30 * 24 * 60 * 60,
|
||||
resetAt: mcpToolsTimeLimit.nextResetTime ? normalizeTimestamp(mcpToolsTimeLimit.nextResetTime) : null
|
||||
});
|
||||
}
|
||||
|
||||
return buildResult({
|
||||
providerId,
|
||||
providerName,
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
import { afterEach, describe, expect, it, vi } from 'vitest';
|
||||
|
||||
vi.mock('../../opencode/auth.js', () => ({
|
||||
readAuthFile: () => ({ 'zai-coding-plan': { key: 'test-token' } }),
|
||||
}));
|
||||
|
||||
import { fetchQuota } from './zai.js';
|
||||
|
||||
afterEach(() => {
|
||||
vi.unstubAllGlobals();
|
||||
});
|
||||
|
||||
const mockResponse = (body) => ({
|
||||
ok: true,
|
||||
status: 200,
|
||||
json: async () => body,
|
||||
});
|
||||
|
||||
describe('Z.ai quota provider', () => {
|
||||
it('surfaces 5-hour, weekly, and MCP quota windows', async () => {
|
||||
vi.stubGlobal('fetch', vi.fn().mockResolvedValue(mockResponse({
|
||||
data: {
|
||||
limits: [
|
||||
{ type: 'TOKENS_LIMIT', unit: 3, number: 5, percentage: 0 },
|
||||
{ type: 'TOKENS_LIMIT', unit: 6, number: 1, percentage: 100, nextResetTime: 1785659659993 },
|
||||
{ type: 'TIME_LIMIT', unit: 5, number: 1, percentage: 0, nextResetTime: 1787128459979 },
|
||||
],
|
||||
},
|
||||
})));
|
||||
|
||||
const result = await fetchQuota();
|
||||
const windows = result.usage.windows;
|
||||
|
||||
expect(result.ok).toBe(true);
|
||||
expect(windows['5h']).toMatchObject({
|
||||
usedPercent: 0,
|
||||
remainingPercent: 100,
|
||||
windowSeconds: 5 * 60 * 60,
|
||||
resetAt: null,
|
||||
});
|
||||
expect(windows.weekly).toMatchObject({
|
||||
usedPercent: 100,
|
||||
remainingPercent: 0,
|
||||
windowSeconds: 7 * 24 * 60 * 60,
|
||||
resetAt: 1785659659993,
|
||||
});
|
||||
expect(windows['MCP Tools']).toMatchObject({
|
||||
usedPercent: 0,
|
||||
remainingPercent: 100,
|
||||
windowSeconds: 30 * 24 * 60 * 60,
|
||||
resetAt: 1787128459979,
|
||||
});
|
||||
});
|
||||
});
|
||||
Reference in New Issue
Block a user