mirror of
https://github.com/affaan-m/ECC.git
synced 2026-10-26 18:35:05 +00:00
fix: preserve opt-in usage data and publish networked callbacks
This commit is contained in:
5 files changed
+157
-17
No files matched your search
@@ -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,
|
||||
|
||||
@@ -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}`);
|
||||
|
||||
Reference in new issue
Block a user