UNPKG

@ace-sdk/cli

Version:

ACE CLI - Command-line tool for intelligent pattern learning and playbook management

275 lines 9.59 kB
/** * Usage Display Utilities for ACE CLI * * Functions for formatting and displaying subscription usage information. * * @package @ace-sdk/cli * @since v2.8.0 */ import chalk from 'chalk'; // ============================================================================= // Progress Bar Formatting // ============================================================================= /** * Format a usage metric as a progress bar * * @param used - Current usage * @param limit - Maximum limit * @param width - Bar width in characters (default: 20) * @returns Formatted progress bar string * * @example * ```typescript * formatUsageBar(80, 100); * // Returns: "████████████████░░░░ 80 / 100 (80%)" * ``` */ export function formatUsageBar(used, limit, width = 20) { // Handle unlimited (limit = -1 or 0) if (limit <= 0) { return `${chalk.dim('unlimited')} ${formatNumber(used)} used`; } const percentage = Math.min(100, Math.round((used / limit) * 100)); const filled = Math.round((percentage / 100) * width); const empty = width - filled; // Color based on usage level let barColor = chalk.green; let warningIcon = ''; if (percentage >= 90) { barColor = chalk.red; warningIcon = ' 🔴'; } else if (percentage >= 80) { barColor = chalk.yellow; warningIcon = ' ⚠️'; } const bar = barColor('█'.repeat(filled)) + chalk.dim('░'.repeat(empty)); const numbers = `${formatNumber(used)} / ${formatNumber(limit)} (${percentage}%)`; return `${bar} ${numbers}${warningIcon}`; } /** * Format a number with thousands separators */ export function formatNumber(num) { return num.toLocaleString('en-US'); } // ============================================================================= // Plan Name Formatting // ============================================================================= /** * Format plan name for display * * @param type - Subscription type (individual/team) * @param tier - Plan tier (free/basic/pro) * @returns Formatted plan name * * @example * ```typescript * formatPlanName('individual', 'pro'); * // Returns: "Individual PRO" * ``` */ export function formatPlanName(type, tier) { const typeDisplay = type.charAt(0).toUpperCase() + type.slice(1); const tierDisplay = tier.toUpperCase(); return `${typeDisplay} ${tierDisplay}`; } /** * Get colored plan badge */ export function getPlanBadge(type, tier) { const name = formatPlanName(type, tier); switch (tier) { case 'pro': return chalk.bgMagenta.white.bold(` ${name} `); case 'basic': return chalk.bgBlue.white.bold(` ${name} `); default: return chalk.bgGray.white(` ${name} `); } } // ============================================================================= // Status Formatting // ============================================================================= /** * Format subscription status for display */ export function formatStatus(status) { switch (status) { case 'active': return chalk.green('Active'); case 'trialing': return chalk.cyan('Trial'); case 'read_only': return chalk.yellow('Read-Only'); case 'blocked': return chalk.red('Blocked'); default: return status; } } /** * Get status icon */ export function getStatusIcon(status) { switch (status) { case 'active': return '✅'; case 'trialing': return '🧪'; case 'read_only': return '⚠️'; case 'blocked': return '🚫'; default: return '❓'; } } // ============================================================================= // Features Formatting // ============================================================================= /** * Format feature availability */ export function formatFeatures(features) { const items = []; if (features.teams) { items.push(chalk.green('✅ Teams')); } if (features.sharing) { items.push(chalk.green('✅ Sharing')); } if (features.apiAccess) { items.push(chalk.green('✅ API Access')); } if (features.prioritySupport) { items.push(chalk.green('✅ Priority Support')); } if (items.length === 0) { return chalk.dim('No premium features'); } return items.join(' '); } // ============================================================================= // Full Status Display // ============================================================================= /** * Display complete usage status * * @param usage - Usage information */ export function displayUsageStatus(usage) { const statusIcon = getStatusIcon(usage.status); const planBadge = getPlanBadge(usage.subscriptionType, usage.planTier); console.log(); console.log(chalk.bold(`Subscription: ${planBadge} ${statusIcon} ${formatStatus(usage.status)}`)); console.log(); // Usage metrics console.log(chalk.bold('Usage:')); console.log(` ${chalk.cyan('Patterns:'.padEnd(18))}${formatUsageBar(usage.patterns.used, usage.patterns.limit)}`); console.log(` ${chalk.cyan('Total Patterns:'.padEnd(18))}${formatUsageBar(usage.patternsTotal.used, usage.patternsTotal.limit)}`); console.log(` ${chalk.cyan('Projects:'.padEnd(18))}${formatUsageBar(usage.projects.used, usage.projects.limit)}`); console.log(` ${chalk.cyan('Domains:'.padEnd(18))}${formatUsageBar(usage.domains.used, usage.domains.limit)}`); console.log(` ${chalk.cyan('Templates:'.padEnd(18))}${formatUsageBar(usage.templates.used, usage.templates.limit)}`); console.log(` ${chalk.cyan('API Calls:'.padEnd(18))}${formatUsageBar(usage.apiCalls.used, usage.apiCalls.limit)}`); console.log(` ${chalk.cyan('Traces Today:'.padEnd(18))}${formatUsageBar(usage.tracesToday.used, usage.tracesToday.limit)}`); console.log(); // Reset info console.log(chalk.dim(' ℹ️ API Calls reset on billing cycle. Traces reset daily at midnight UTC.')); console.log(); // Features console.log(chalk.bold('Features:'), formatFeatures(usage.features)); console.log(); // Team info (if applicable) if (usage.team) { console.log(chalk.bold('Team:')); console.log(` ${chalk.cyan('Organization:')} ${usage.team.orgName}`); console.log(` ${chalk.cyan('Seats:'.padEnd(18))}${formatUsageBar(usage.team.seatsUsed, usage.team.seatsLimit)}`); console.log(); } // Warnings displayWarnings(usage); } /** * Display warnings based on usage status */ export function displayWarnings(usage) { // Read-only mode warning if (usage.status === 'read_only') { console.log(chalk.yellow.bold('⚠️ Account is in READ-ONLY mode due to payment failure.')); console.log(chalk.yellow(' Update payment: https://ace-ai.app/settings/billing')); console.log(); } // Blocked account warning if (usage.status === 'blocked') { console.log(chalk.red.bold('🚫 Account is BLOCKED.')); console.log(chalk.red(' Resolve at: https://ace-ai.app/settings/billing')); console.log(); } // Trial ending warning (if trialing and would show usage) if (usage.status === 'trialing') { console.log(chalk.cyan('🧪 You are on a trial period.')); console.log(chalk.cyan(' Upgrade: https://ace-ai.app/pricing')); console.log(); } // Near-limit warnings const nearLimitResources = []; if (isNearLimit(usage.patterns)) { nearLimitResources.push('Patterns (per-project)'); } if (isNearLimit(usage.patternsTotal)) { nearLimitResources.push('Patterns (total)'); } if (isNearLimit(usage.projects)) { nearLimitResources.push('Projects'); } if (isNearLimit(usage.apiCalls)) { nearLimitResources.push('API Calls'); } if (isNearLimit(usage.tracesToday)) { nearLimitResources.push('Daily Traces'); } if (nearLimitResources.length > 0) { console.log(chalk.yellow.bold('⚠️ Approaching limits:')); nearLimitResources.forEach(resource => { console.log(chalk.yellow(` • ${resource}`)); }); console.log(chalk.yellow(' Upgrade: https://ace-ai.app/pricing')); console.log(); } } /** * Check if a metric is near its limit (>80%) */ function isNearLimit(metric, threshold = 80) { if (metric.limit <= 0) return false; return (metric.used / metric.limit) * 100 >= threshold; } // ============================================================================= // JSON Output // ============================================================================= /** * Format usage info for JSON output */ export function formatUsageJson(usage) { return { plan: usage.plan, subscription_type: usage.subscriptionType, plan_tier: usage.planTier, status: usage.status, usage: { patterns: usage.patterns, patterns_total: usage.patternsTotal, projects: usage.projects, domains: usage.domains, templates: usage.templates, api_calls: usage.apiCalls, traces_today: usage.tracesToday }, features: usage.features, team: usage.team || null, upgrade_url: 'https://ace-ai.app/pricing' }; } //# sourceMappingURL=usage-display.js.map