import { readAuthFile } from '../../opencode/auth.js'; import { getAuthEntry, normalizeAuthEntry, buildResult, toUsageWindow, toNumber, toTimestamp, durationToLabel, durationToSeconds } from '../utils/index.js'; export const providerId = 'kimi-for-coding'; export const providerName = 'Kimi for Coding'; export const aliases = ['kimi-for-coding', 'kimi']; 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' }); } try { const response = await fetch('https://api.kimi.com/coding/v1/usages', { method: 'GET', headers: { Authorization: `Bearer ${apiKey}`, 'Content-Type': 'application/json' } }); if (!response.ok) { return buildResult({ providerId, providerName, ok: false, configured: true, error: `API error: ${response.status}` }); } const payload = await response.json(); const windows = {}; const usage = payload?.usage ?? null; if (usage) { const limit = toNumber(usage.limit); const remaining = toNumber(usage.remaining); const usedPercent = limit && remaining !== null ? Math.max(0, Math.min(100, 100 - (remaining / limit) * 100)) : null; windows.weekly = toUsageWindow({ usedPercent, windowSeconds: null, resetAt: toTimestamp(usage.resetTime) }); } const limits = Array.isArray(payload?.limits) ? payload.limits : []; for (const limit of limits) { const window = limit?.window; const detail = limit?.detail; const rawLabel = durationToLabel(window?.duration, window?.timeUnit); const windowSeconds = durationToSeconds(window?.duration, window?.timeUnit); const label = windowSeconds === 5 * 60 * 60 ? `Rate Limit (${rawLabel})` : rawLabel; const total = toNumber(detail?.limit); const remaining = toNumber(detail?.remaining); const usedPercent = total && remaining !== null ? Math.max(0, Math.min(100, 100 - (remaining / total) * 100)) : null; windows[label] = toUsageWindow({ usedPercent, windowSeconds, resetAt: toTimestamp(detail?.resetTime) }); } return buildResult({ providerId, providerName, ok: true, configured: true, usage: { windows } }); } catch (error) { return buildResult({ providerId, providerName, ok: false, configured: true, error: error instanceof Error ? error.message : 'Request failed' }); } };