Always show all 3 providers, add Kimi fallback key
This commit is contained in:
114
dist/index.js
vendored
114
dist/index.js
vendored
@@ -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;
|
||||||
|
|||||||
Reference in New Issue
Block a user