Files
openchamber/packages/vscode/src/opencodeGoQuota.ts
T
Bohdan Triapitsyn 5917325d49 feat: switch OpenCode Go usage to API
OpenCode Go now reads quota usage with a bearer API key from OpenCode auth.json
Removes the old workspace ID and browser cookie credential flow
Deletes legacy OpenCode Go credential files during upgrade
2026-08-12 01:49:22 +03:00

27 lines
1.7 KiB
TypeScript

type OpenCodeGoCredential = { apiKey: string };
const toWindow = (usedPercent: number, resetAt: string) => ({
usedPercent: Math.min(100, Math.max(0, usedPercent)),
remainingPercent: 100 - Math.min(100, Math.max(0, usedPercent)),
windowSeconds: null,
resetAfterSeconds: Math.max(0, Math.floor((new Date(resetAt).getTime() - Date.now()) / 1000)),
resetAt: new Date(resetAt).getTime(),
resetAtFormatted: null,
resetAfterFormatted: null,
});
export const fetchOpenCodeGoUsage = async (credential: OpenCodeGoCredential) => {
const response = await fetch('https://opencode.ai/zen/go/v1/usage', { headers: { Accept: 'application/json', Authorization: `Bearer ${credential.apiKey}` }, signal: AbortSignal.timeout(15_000) });
if (response.status === 401 || response.status === 403 || (response.status >= 300 && response.status < 400)) throw new Error('OpenCode Go authentication failed');
if (!response.ok) throw new Error(`OpenCode Go usage API returned HTTP ${response.status}`);
const payload = await response.json().catch(() => null) as { usage?: Record<string, { percent?: unknown; resetsAt?: unknown }> } | null;
const windows: Record<string, ReturnType<typeof toWindow>> = {};
for (const [key, apiKey] of Object.entries({ '5h': 'rolling', weekly: 'weekly', monthly: 'monthly' })) {
const entry = payload?.usage?.[apiKey];
if (typeof entry?.percent !== 'number' || !Number.isFinite(entry.percent) || typeof entry.resetsAt !== 'string' || !Number.isFinite(new Date(entry.resetsAt).getTime())) continue;
windows[key] = toWindow(entry.percent, entry.resetsAt);
}
if (!Object.keys(windows).length) throw new Error('OpenCode Go usage data could not be parsed');
return windows;
};