fix: preserve opt-in usage data and publish networked callbacks

This commit is contained in:
haelyra committed 2026-10-11 03:53:30 -04:00
1 parent 2bfee727e2
commit 3e395c6b76
5 files changed
+157 -17

No files matched your search

+18 -7
View File
@@ -40,14 +40,15 @@ function formatDuration(isoTimestamp) {
* @param {number} remaining - Raw remaining percentage from Claude Code
* @returns {string} Colored bar string
*/
function buildContextBar(remaining) {
function buildContextBar(remaining, glyphs) {
if (remaining === null || remaining === undefined) return '';
const usableRemaining = Math.max(0, ((remaining - AUTO_COMPACT_BUFFER_PCT) / (100 - AUTO_COMPACT_BUFFER_PCT)) * 100);
const used = Math.max(0, Math.min(100, Math.round(100 - usableRemaining)));
const filled = Math.floor(used / 10);
const bar = '\u2588'.repeat(filled) + '\u2591'.repeat(10 - filled);
const bar = (glyphs?.full || '\u2588').repeat(filled)
+ (glyphs?.empty || '\u2591').repeat(10 - filled);
if (used < 50) return ` \x1b[32m${bar} ${used}%\x1b[0m`;
if (used < 65) return ` \x1b[33m${bar} ${used}%\x1b[0m`;
@@ -95,6 +96,16 @@ function getEccVersion(plugins) {
}
}
function sessionDurationMs(cost, bridge) {
if (Number.isFinite(cost.total_duration_ms) && cost.total_duration_ms >= 0) {
return cost.total_duration_ms;
}
const elapsed = bridge?.first_timestamp
? Date.now() - new Date(bridge.first_timestamp).getTime()
: 0;
return Number.isFinite(elapsed) && elapsed >= 0 ? elapsed : 0;
}
/**
* Assemble statusline output lines from Claude Code stdin data.
* @param {object} data - Parsed statusLine stdin JSON
@@ -111,8 +122,10 @@ function buildUsageLines(data, bridge, task) {
if (process.env.ECC_STATUSLINE_COMPACT === '1') {
const segments = [`\x1b[2m${data.model?.display_name || 'Claude'}\x1b[0m`];
if (task) segments.push(`\x1b[1;97m${task}\x1b[0m`);
const usage = render.buildUsageLine(data.rate_limits, null, { compact: true });
if (usage) segments.push(usage);
segments.push(`\x1b[2m${dirname}\x1b[0m`);
return [segments.join(render.SEP) + buildContextBar(remaining)];
return [segments.join(render.SEP) + buildContextBar(remaining, render.G)];
}
const usageLine = render.buildUsageLine(
@@ -120,14 +133,12 @@ function buildUsageLines(data, bridge, task) {
render.computeCacheStats(data.context_window?.current_usage)
);
const durationMs = bridge?.first_timestamp
? Date.now() - new Date(bridge.first_timestamp).getTime()
: 0;
const durationMs = sessionDurationMs(cost, bridge);
const sessionLine = render.buildSessionLine({
model: data.model?.display_name,
effort: data.effort?.level,
fastMode: data.fast_mode === true,
ctxBar: buildContextBar(remaining),
ctxBar: buildContextBar(remaining, render.G),
ctxWindowSize: data.context_window?.context_window_size,
costUsd: cost.total_cost_usd ?? bridge?.total_cost_usd ?? 0,
linesAdded: cost.total_lines_added || 0,
+9 -6
View File
@@ -124,10 +124,11 @@ function computeCacheStats(currentUsage) {
return { hitPct: Math.round((read / total) * 100) };
}
function usageSegment(label, labelColor, window) {
const pct = Math.round(window?.used_percentage ?? -1);
if (pct < 0) return '';
function usageSegment(label, labelColor, window, compact = false) {
if (!Number.isFinite(window?.used_percentage) || window.used_percentage < 0) return '';
const pct = Math.round(window.used_percentage);
const color = pctColor(pct, labelColor);
if (compact) return `${labelColor}${label}${C.reset} ${color}${pct}%${C.reset}`;
const reset = formatCountdown(window.resets_at);
const resetStr = reset ? ` ${C.dim}${G.reset}${reset}${C.reset}` : '';
return `${labelColor}${label}${C.reset} ${color}${buildBar(pct)} ${pct}%${C.reset}${resetStr}`;
@@ -137,12 +138,14 @@ function usageSegment(label, labelColor, window) {
* Line 1: rate-limit windows + prompt cache.
* Returns '' when no rate limit data is available (e.g. API-key billing).
*/
function buildUsageLine(rateLimits, cacheStats) {
function buildUsageLine(rateLimits, cacheStats, { compact = false } = {}) {
const parts = [];
const fiveHour = usageSegment('5h', C.amber, rateLimits?.five_hour);
const sevenDay = usageSegment('7d', C.terracotta, rateLimits?.seven_day);
const fiveHour = usageSegment('5h', C.amber, rateLimits?.five_hour, compact);
const sevenDay = usageSegment('7d', C.terracotta, rateLimits?.seven_day, compact);
const spendLimit = usageSegment('spend', C.amber, rateLimits?.spend_limit, compact);
if (fiveHour) parts.push(fiveHour);
if (sevenDay) parts.push(sevenDay);
if (spendLimit) parts.push(spendLimit);
if (cacheStats && parts.length > 0) {
const cacheColor = cacheStats.hitPct >= 50 ? C.green : C.dim;
parts.push(`${C.dim}cache${C.reset} ${cacheColor}${cacheStats.hitPct}%${C.reset}`);