import { readAuthFile } from '../../opencode/auth.js'; import { getAuthEntry, normalizeAuthEntry, buildResult, toUsageWindow, toNumber, formatMoney } from '../utils/index.js'; export const providerId = 'crof'; export const providerName = 'CrofAI'; const aliases = ['crof']; const CROF_USAGE_URL = 'https://crof.ai/usage_api/'; export const isConfigured = () => { const auth = readAuthFile(); const entry = normalizeAuthEntry(getAuthEntry(auth, aliases)); return Boolean(entry?.key || entry?.token); }; export const fetchQuota = async () => { const auth = readAuthFile(); const entry = normalizeAuthEntry(getAuthEntry(auth, aliases)); const apiKey = entry?.key ?? entry?.token; if (!apiKey) { return buildResult({ providerId, providerName, ok: false, configured: false, error: 'Not configured' }); } const timeoutSignal = AbortSignal.timeout(15_000); try { const response = await fetch(CROF_USAGE_URL, { method: 'GET', headers: { Authorization: `Bearer ${apiKey}`, 'Accept-Encoding': 'identity' }, signal: timeoutSignal }); if (!response.ok) { return buildResult({ providerId, providerName, ok: false, configured: true, error: response.status === 401 ? 'Session expired — please re-authenticate with CrofAI' : `API error: ${response.status}` }); } const payload = await response.json(); const credits = toNumber(payload?.credits); const valueLabel = credits !== null ? `$${formatMoney(credits)}` : null; const windows = { credits: toUsageWindow({ usedPercent: null, windowSeconds: null, resetAt: null, valueLabel }) }; return buildResult({ providerId, providerName, ok: true, configured: true, usage: { windows } }); } catch (error) { const isTimeout = error instanceof DOMException && error.name === 'AbortError' && timeoutSignal.aborted; const isParseError = error instanceof SyntaxError; return buildResult({ providerId, providerName, ok: false, configured: true, error: isTimeout ? 'Request timed out' : isParseError ? 'Invalid response from provider' : (error instanceof Error ? error.message : 'Request failed') }); } };