Always show all 3 providers, add Kimi fallback key

This commit is contained in:
ren
2026-02-16 20:09:51 -03:00
parent b16d55a2a7
commit cc4f245a18

114
dist/index.js vendored
View File

@@ -38,6 +38,11 @@ const CONFIG = {
apiKey: process.env.MINIMAX_API_KEY || 'sk-cp-XC8cbgbVBuv1g8mMcao0ABeZu_rGEN_S22EhBUqo4lJbY_UJVqUVO5XF8hVobp8gE_39JbgQggr00TQwNdV9vP458Y_MBC_8GstvzmwhuukEGY4a2I5_L6A', apiKey: process.env.MINIMAX_API_KEY || 'sk-cp-XC8cbgbVBuv1g8mMcao0ABeZu_rGEN_S22EhBUqo4lJbY_UJVqUVO5XF8hVobp8gE_39JbgQggr00TQwNdV9vP458Y_MBC_8GstvzmwhuukEGY4a2I5_L6A',
baseUrl: 'api.minimax.io', baseUrl: 'api.minimax.io',
endpoint: '/v1/api/openplatform/coding_plan/remains' endpoint: '/v1/api/openplatform/coding_plan/remains'
},
kimi: {
apiKey: process.env.KIMI_API_KEY || 'sk-kimi-dr5bfb3Gz8yOQOJVbLd2iY3kdDPf5MPBp1Ay467FlpAhvKMcTVOyiMH8zuQz1gb2',
baseUrl: 'api.kimi.com',
endpoint: '/coding/v1/usages'
} }
}; };
@@ -141,6 +146,74 @@ async function getMinimaxUsage() {
} }
} }
// Fetch Kimi usage
async function getKimiUsage() {
if (!CONFIG.kimi.apiKey) {
return { error: 'No Kimi API key configured' };
}
try {
const response = await makeRequest({
hostname: CONFIG.kimi.baseUrl,
path: CONFIG.kimi.endpoint,
method: 'GET',
headers: {
'Authorization': `Bearer ${CONFIG.kimi.apiKey}`,
'Content-Type': 'application/json'
}
});
const usage = response?.usage;
const limits = response?.limits || [];
if (!usage) {
return { pct: 0, remainingMinutes: 0, error: 'No data' };
}
const pct = parseInt(usage.used) / parseInt(usage.limit) * 100;
let remainingMinutes = 0;
let weeklyReset = null;
if (usage.resetTime) {
const resetDate = new Date(usage.resetTime);
const now = new Date();
remainingMinutes = (resetDate - now) / 1000 / 60;
weeklyReset = resetDate;
}
const limitInfos = [];
for (const l of limits) {
if (l.detail?.resetTime) {
const resetDate = new Date(l.detail.resetTime);
const now = new Date();
const limitMins = (resetDate - now) / 1000 / 60;
if (limitMins > 0) {
const limitUsed = parseInt(l.detail.limit) - parseInt(l.detail.remaining);
const limitPct = limitUsed / parseInt(l.detail.limit) * 100;
const windowDur = l.window?.duration || 0;
const windowUnit = l.window?.timeUnit || '';
let label = '5h';
if (windowUnit === 'TIME_UNIT_MINUTE' && windowDur >= 60) {
label = `${windowDur / 60}h`;
}
limitInfos.push({
pct: limitPct,
remainingMinutes: limitMins,
label: label
});
}
}
}
return { pct, remainingMinutes, weeklyReset, limitInfos, error: null };
} catch (e) {
return { pct: 0, remainingMinutes: 0, error: e.message };
}
}
// Get color based on percentage // Get color based on percentage
function getColor(pct) { function getColor(pct) {
if (pct > 90) return colors.red; if (pct > 90) return colors.red;
@@ -174,35 +247,62 @@ function formatMinimaxStatus(minimax) {
return `${colors.purple}MiniMax${colors.reset} ${getColor(minimax.pct)}${minimax.pct.toFixed(0)}%${colors.reset}${timeStr ? ` ${timeStr}` : ''}`; return `${colors.purple}MiniMax${colors.reset} ${getColor(minimax.pct)}${minimax.pct.toFixed(0)}%${colors.reset}${timeStr ? ` ${timeStr}` : ''}`;
} }
// Format Kimi status
function formatKimiStatus(kimi) {
if (kimi.error) {
return `${colors.orange}Kimi${colors.reset} ${colors.red}offline${colors.reset}`;
}
let status = `${colors.orange}Kimi${colors.reset} ${getColor(kimi.pct)}${kimi.pct.toFixed(0)}%${colors.reset}`;
if (kimi.remainingMinutes > 0) {
status += ` ${formatTime(kimi.remainingMinutes)}`;
}
if (kimi.limitInfos && kimi.limitInfos.length > 0) {
for (const lim of kimi.limitInfos) {
status += ` ${colors.orange}${lim.label}${colors.reset}${getColor(lim.pct)}${lim.pct.toFixed(0)}%${colors.reset}`;
}
}
return status;
}
// Main function // Main function
async function main() { async function main() {
const args = process.argv.slice(2); const args = process.argv.slice(2);
const showJson = args.includes('--json'); const showJson = args.includes('--json');
const showOnlyGlm = args.includes('--glm'); const showOnlyGlm = args.includes('--glm');
const showOnlyMinimax = args.includes('--minimax'); const showOnlyMinimax = args.includes('--minimax');
const showOnlyKimi = args.includes('--kimi');
try { try {
const [glm, minimax] = await Promise.all([ const [glm, minimax, kimi] = await Promise.all([
showOnlyMinimax ? Promise.resolve({ error: 'disabled' }) : getGlmUsage(), getGlmUsage(),
showOnlyGlm ? Promise.resolve({ error: 'disabled' }) : getMinimaxUsage() getMinimaxUsage(),
getKimiUsage()
]); ]);
if (showJson) { if (showJson) {
console.log(JSON.stringify({ glm, minimax }, null, 2)); console.log(JSON.stringify({ glm, minimax, kimi }, null, 2));
return; return;
} }
// Statusline output // Statusline output - always show all 3
let parts = []; let parts = [];
if (!showOnlyMinimax && !glm.error) { if (!showOnlyMinimax && !showOnlyKimi) {
parts.push(formatGlmStatus(glm)); parts.push(formatGlmStatus(glm));
} }
if (!showOnlyGlm && !minimax.error) { if (!showOnlyGlm && !showOnlyKimi) {
parts.push(formatMinimaxStatus(minimax)); parts.push(formatMinimaxStatus(minimax));
} }
if (!showOnlyGlm && !showOnlyMinimax) {
parts.push(formatKimiStatus(kimi));
}
if (parts.length === 0) { if (parts.length === 0) {
console.log(`${colors.red}No API configured${colors.reset}`); console.log(`${colors.red}No API configured${colors.reset}`);
return; return;