Files
claude-hud/dist/render/lines/usage.js
2026-03-23 13:36:34 +11:00

124 lines
4.4 KiB
JavaScript

import { isLimitReached } from '../../types.js';
import { getProviderLabel } from '../../stdin.js';
import { critical, warning, dim, getQuotaColor, quotaBar, RESET } from '../colors.js';
import { getAdaptiveBarWidth } from '../../utils/terminal.js';
export function renderUsageLine(ctx) {
const display = ctx.config?.display;
const colors = ctx.config?.colors;
if (display?.showUsage === false) {
return null;
}
if (!ctx.usageData?.planName) {
return null;
}
if (getProviderLabel(ctx.stdin)) {
return null;
}
const label = dim('Usage');
if (ctx.usageData.apiUnavailable) {
const errorHint = formatUsageError(ctx.usageData.apiError);
return `${label} ${warning(`${errorHint}`, colors)}`;
}
if (isLimitReached(ctx.usageData)) {
const resetTime = ctx.usageData.fiveHour === 100
? formatResetTime(ctx.usageData.fiveHourResetAt)
: formatResetTime(ctx.usageData.sevenDayResetAt);
return `${label} ${critical(`⚠ Limit reached${resetTime ? ` (resets ${resetTime})` : ''}`, colors)}`;
}
const threshold = display?.usageThreshold ?? 0;
const fiveHour = ctx.usageData.fiveHour;
const sevenDay = ctx.usageData.sevenDay;
const effectiveUsage = Math.max(fiveHour ?? 0, sevenDay ?? 0);
if (effectiveUsage < threshold) {
return null;
}
const usageBarEnabled = display?.usageBarEnabled ?? true;
const sevenDayThreshold = display?.sevenDayThreshold ?? 80;
const syncingSuffix = ctx.usageData.apiError === 'rate-limited'
? ` ${dim('(syncing...)')}`
: '';
const barWidth = getAdaptiveBarWidth();
if (fiveHour === null && sevenDay !== null) {
const weeklyOnlyPart = formatUsageWindowPart({
label: '7d',
percent: sevenDay,
resetAt: ctx.usageData.sevenDayResetAt,
colors,
usageBarEnabled,
barWidth,
forceLabel: true,
});
return `${label} ${weeklyOnlyPart}${syncingSuffix}`;
}
const fiveHourPart = formatUsageWindowPart({
label: '5h',
percent: fiveHour,
resetAt: ctx.usageData.fiveHourResetAt,
colors,
usageBarEnabled,
barWidth,
});
if (sevenDay !== null && sevenDay >= sevenDayThreshold) {
const sevenDayPart = formatUsageWindowPart({
label: '7d',
percent: sevenDay,
resetAt: ctx.usageData.sevenDayResetAt,
colors,
usageBarEnabled,
barWidth,
});
return `${label} ${fiveHourPart} | ${sevenDayPart}${syncingSuffix}`;
}
return `${label} ${fiveHourPart}${syncingSuffix}`;
}
function formatUsagePercent(percent, colors) {
if (percent === null) {
return dim('--');
}
const color = getQuotaColor(percent, colors);
return `${color}${percent}%${RESET}`;
}
function formatUsageWindowPart({ label, percent, resetAt, colors, usageBarEnabled, barWidth, forceLabel = false, }) {
const usageDisplay = formatUsagePercent(percent, colors);
const reset = formatResetTime(resetAt);
if (usageBarEnabled) {
const body = reset
? `${quotaBar(percent ?? 0, barWidth, colors)} ${usageDisplay} (resets in ${reset})`
: `${quotaBar(percent ?? 0, barWidth, colors)} ${usageDisplay}`;
return forceLabel ? `${label}: ${body}` : body;
}
return reset
? `${label}: ${usageDisplay} (resets in ${reset})`
: `${label}: ${usageDisplay}`;
}
function formatUsageError(error) {
if (!error)
return '';
if (error === 'rate-limited')
return ' (syncing...)';
if (error.startsWith('http-'))
return ` (${error.slice(5)})`;
return ` (${error})`;
}
function formatResetTime(resetAt) {
if (!resetAt)
return '';
const now = new Date();
const diffMs = resetAt.getTime() - now.getTime();
if (diffMs <= 0)
return '';
const diffMins = Math.ceil(diffMs / 60000);
if (diffMins < 60)
return `${diffMins}m`;
const hours = Math.floor(diffMins / 60);
const mins = diffMins % 60;
if (hours >= 24) {
const days = Math.floor(hours / 24);
const remHours = hours % 24;
if (remHours > 0)
return `${days}d ${remHours}h`;
return `${days}d`;
}
return mins > 0 ? `${hours}h ${mins}m` : `${hours}h`;
}
//# sourceMappingURL=usage.js.map