@ace-sdk/cli
Version:
ACE CLI - Command-line tool for intelligent pattern learning and playbook management
113 lines • 5.65 kB
JavaScript
/**
* Playbook status command
*/
import { globalOptions } from '../cli.js';
import { createContext } from '../types/config.js';
import { ACEServerClient } from '../services/server-client.js';
import { Logger } from '../services/logger.js';
import chalk from 'chalk';
import { isSubscriptionError, QuotaExceededError, PaymentRequiredError, AccountBlockedError } from '@ace-sdk/core';
import { displayUsageStatus, formatUsageJson } from '../utils/usage-display.js';
/**
* Show playbook statistics
*/
export async function statusCommand() {
const logger = new Logger(globalOptions);
let spinner = logger.spinner('Fetching playbook status...');
try {
// Create context using 4-tier precedence (flags > env > .claude/settings.json > error)
const context = await createContext({ org: globalOptions.org, project: globalOptions.project });
const client = new ACEServerClient(context, logger);
const status = await client.getAnalytics();
spinner?.succeed('Status retrieved');
// Get subscription usage from response headers (v2.8.0+)
const usage = client.getLastUsage();
if (logger.isJson()) {
// Include both playbook stats and subscription usage in JSON output
const output = {
playbook: status,
subscription: usage ? formatUsageJson(usage) : null
};
logger.output(output);
}
else {
// Show subscription usage first (if available)
if (usage) {
displayUsageStatus(usage);
}
logger.info(chalk.bold('📊 Playbook Status\n'));
// Handle both total_patterns (new) and total_bullets (legacy)
const totalCount = status.total_patterns ?? status.total_bullets ?? 0;
logger.info(` ${chalk.cyan('Total Patterns:')} ${totalCount}`);
logger.info(` ${chalk.cyan('Project ID:')} ${context.projectId}`);
if (status.by_section) {
logger.info(chalk.bold('\n📑 By Section:\n'));
Object.entries(status.by_section).forEach(([section, count]) => {
const label = section.replace(/_/g, ' ').replace(/\b\w/g, l => l.toUpperCase());
logger.info(` ${chalk.dim('•')} ${label}: ${count}`);
});
}
if (status.top_helpful && status.top_helpful.length > 0) {
logger.info(chalk.bold('\n⭐ Top Helpful Patterns:\n'));
status.top_helpful.slice(0, 5).forEach((bullet, index) => {
logger.info(` ${chalk.green(index + 1)}. ${chalk.bold(`[+${bullet.helpful}]`)} ${bullet.content.substring(0, 60)}...`);
});
}
if (status.top_harmful && status.top_harmful.length > 0) {
logger.info(chalk.bold('\n⚠️ Top Harmful Patterns:\n'));
status.top_harmful.slice(0, 3).forEach((bullet, index) => {
logger.info(` ${chalk.red(index + 1)}. ${chalk.bold(`[-${bullet.harmful}]`)} ${bullet.content.substring(0, 60)}...`);
});
}
logger.info('');
}
}
catch (error) {
spinner?.fail('Failed to fetch status');
// Handle subscription-related errors with helpful messages (v2.8.0+)
if (isSubscriptionError(error)) {
if (logger.isJson()) {
logger.error(JSON.stringify({
error: error.name,
message: error.message,
upgrade_url: 'upgradeUrl' in error ? error.upgradeUrl : 'https://ace-ai.app/pricing'
}));
}
else {
if (error instanceof QuotaExceededError) {
logger.error(chalk.yellow(`\n⚠️ Quota exceeded: ${error.message}`));
logger.error(chalk.dim(` ${error.resource}: ${error.current.toLocaleString()} / ${error.limit.toLocaleString()} (${error.percentage}%)`));
logger.error(chalk.cyan(` Upgrade: ${error.upgradeUrl}\n`));
}
else if (error instanceof PaymentRequiredError) {
logger.error(chalk.yellow(`\n⚠️ Account is in read-only mode`));
logger.error(chalk.dim(` ${error.message}`));
if (error.isUrgent) {
logger.error(chalk.red(` ⚠️ URGENT: Account will be blocked in ${error.daysUntilBlock} days!`));
}
else {
logger.error(chalk.dim(` Days until block: ${error.daysUntilBlock}`));
}
logger.error(chalk.cyan(` Update payment: ${error.upgradeUrl}\n`));
}
else if (error instanceof AccountBlockedError) {
logger.error(chalk.red(`\n🚫 Account is blocked`));
logger.error(chalk.dim(` ${error.message}`));
logger.error(chalk.cyan(` Resolve at: ${error.upgradeUrl}\n`));
}
else {
logger.error(chalk.red(`\n❌ ${error.message}\n`));
}
}
process.exit(1);
}
if (logger.isJson()) {
logger.error(JSON.stringify({ error: error instanceof Error ? error.message : String(error) }));
}
else {
logger.error(chalk.red(`\n❌ Error: ${error instanceof Error ? error.message : String(error)}\n`));
}
process.exit(1);
}
}
//# sourceMappingURL=status.js.map