claude-statusline-powerline
Version:
Beautiful powerline-style statusline for Claude Code with git integration, session tracking, and cost monitoring
104 lines • 4.74 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.OrgSegment = void 0;
const token_formatting_1 = require("../utils/token-formatting");
const base_1 = require("./base");
class OrgSegment extends base_1.BaseSegment {
constructor() {
super(...arguments);
this.name = 'org';
this.priority = 35; // Between session (40) and git (30)
this.cache = null;
this.cache_expiry = null;
this.cache_duration_ms = 5 * 60 * 1000; // 5 minutes
this.fetch_initiated = false;
}
build(data, config) {
// Check if admin API key is available via environment variable
const admin_api_key = process.env.ANTHROPIC_ADMIN_KEY;
if (!admin_api_key) {
return null; // Hide segment if no API key configured
}
// Use cached data if available and not expired
if (this.cache && this.cache_expiry && new Date() < this.cache_expiry) {
return this.render_segment(this.cache, config);
}
// Try to fetch fresh data (async, won't block rendering)
if (!this.fetch_initiated) {
this.fetch_initiated = true;
this.fetch_usage_data(admin_api_key).catch(() => {
// Silently fail - segment will be hidden on error
});
}
// Return cached data if available, otherwise show loading state
if (this.cache) {
return this.render_segment(this.cache, config);
}
// Show loading indicator on first run
return this.render_loading_segment(config);
}
render_segment(usage, config) {
const total_tokens = usage.total_input_tokens + usage.total_output_tokens;
const cost_str = usage.total_cost < 0.01
? '< $0.01'
: `$${usage.total_cost.toFixed(2)}`;
const { style_override, get_icon } = this.setup_segment(config);
const theme = config.current_theme?.segments.org;
const org_icon = get_icon('organization');
const content = `${org_icon} ${(0, token_formatting_1.format_tokens)(total_tokens)} • ${cost_str} ${usage.period}`;
return this.create_segment_with_fallback(content, theme, 'org', config.separators.org, style_override);
}
render_loading_segment(config) {
const { style_override, get_icon } = this.setup_segment(config);
const theme = config.current_theme?.segments.org;
const org_icon = get_icon('organization');
const content = `${org_icon} Loading...`;
return this.create_segment_with_fallback(content, theme, 'org', config.separators.org, style_override);
}
async fetch_usage_data(admin_api_key) {
try {
// Get usage for last 24 hours
const starting_at = new Date(Date.now() - 24 * 60 * 60 * 1000);
const iso_date = starting_at.toISOString();
const response = await fetch(`https://api.anthropic.com/v1/organizations/usage_report/messages?starting_at=${iso_date}&group_by[]=model`, {
headers: {
'x-api-key': admin_api_key,
'Content-Type': 'application/json',
'anthropic-version': '2023-06-01',
},
});
if (!response.ok) {
throw new Error(`API request failed: ${response.status}`);
}
const data = await response.json();
// Aggregate usage across all models
let total_input_tokens = 0;
let total_output_tokens = 0;
for (const entry of data.data) {
total_input_tokens += entry.input_tokens || 0;
total_output_tokens += entry.output_tokens || 0;
}
// Estimate cost using average pricing (simplified for now)
const avg_input_rate = 3; // per million tokens
const avg_output_rate = 15; // per million tokens
const input_cost = (total_input_tokens / 1000000) * avg_input_rate;
const output_cost = (total_output_tokens / 1000000) * avg_output_rate;
const total_cost = input_cost + output_cost;
// Update cache
this.cache = {
total_input_tokens,
total_output_tokens,
total_cost,
period: '24h',
last_updated: new Date(),
};
this.cache_expiry = new Date(Date.now() + this.cache_duration_ms);
}
catch (error) {
// Silently fail - cache remains unchanged
console.error('Failed to fetch organizational usage:', error);
}
}
}
exports.OrgSegment = OrgSegment;
//# sourceMappingURL=org.js.map