UNPKG

@ace-sdk/cli

Version:

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

187 lines • 6.91 kB
/** * Health diagnostics command */ import { existsSync } from 'fs'; import { homedir } from 'os'; import { join } from 'path'; import { globalOptions } from '../cli.js'; import { getConfig } from '../types/config.js'; import { ACEServerClient } from '../services/server-client.js'; import { Logger } from '../services/logger.js'; import chalk from 'chalk'; /** * Run diagnostics on ACE configuration and connectivity */ export async function doctorCommand() { const logger = new Logger(globalOptions); const results = []; // Check 1: Config file exists let spinner = logger.spinner('Checking configuration file...'); const configPath = join(homedir(), '.ace', 'config.json'); if (existsSync(configPath)) { results.push({ check: 'Config File', status: 'pass', message: `Found at ${configPath}` }); spinner?.succeed('Configuration file found'); } else { results.push({ check: 'Config File', status: 'fail', message: 'Configuration file not found. Run "ce-ace config" to set up.' }); spinner?.fail('Configuration file not found'); } // Check 2: Config is valid spinner = logger.spinner('Validating configuration...'); let config; try { config = getConfig(); results.push({ check: 'Config Validity', status: 'pass', message: 'Configuration is valid', details: { serverUrl: config.serverUrl, projectId: config.projectId, hasApiToken: !!config.apiToken } }); spinner?.succeed('Configuration is valid'); } catch (error) { results.push({ check: 'Config Validity', status: 'fail', message: error instanceof Error ? error.message : String(error) }); spinner?.fail('Configuration is invalid'); } // Check 3: Server connectivity if (config) { spinner = logger.spinner('Testing server connectivity...'); try { const client = new ACEServerClient(config, logger); // Try to get playbook analytics (minimal request) await client.getAnalytics(); results.push({ check: 'Server Connectivity', status: 'pass', message: `Connected to ${config.serverUrl}` }); spinner?.succeed('Server is reachable'); } catch (error) { results.push({ check: 'Server Connectivity', status: 'fail', message: error instanceof Error ? error.message : String(error), details: { serverUrl: config.serverUrl } }); spinner?.fail('Cannot reach server'); } // Check 4: API token validity spinner = logger.spinner('Validating API token...'); try { const client = new ACEServerClient(config, logger); // Getting playbook also validates the token await client.getPlaybook({ forceRefresh: false, include_metadata: false }); results.push({ check: 'API Token', status: 'pass', message: 'API token is valid' }); spinner?.succeed('API token is valid'); } catch (error) { const errorMsg = error instanceof Error ? error.message : String(error); if (errorMsg.includes('401') || errorMsg.includes('unauthorized')) { results.push({ check: 'API Token', status: 'fail', message: 'API token is invalid or expired' }); spinner?.fail('API token is invalid'); } else { results.push({ check: 'API Token', status: 'warn', message: 'Could not validate API token', details: { error: errorMsg } }); spinner?.warn('Could not validate API token'); } } // Check 5: Project/org existence spinner = logger.spinner('Verifying project access...'); try { const client = new ACEServerClient(config, logger); const analytics = await client.getAnalytics(); results.push({ check: 'Project Access', status: 'pass', message: `Project ${config.projectId} is accessible`, details: { totalBullets: analytics.total_bullets || 0 } }); spinner?.succeed('Project is accessible'); } catch (error) { results.push({ check: 'Project Access', status: 'fail', message: `Cannot access project ${config.projectId}`, details: { error: error instanceof Error ? error.message : String(error) } }); spinner?.fail('Project is not accessible'); } } // Output results if (logger.isJson()) { logger.output({ timestamp: new Date().toISOString(), results, summary: { total: results.length, passed: results.filter(r => r.status === 'pass').length, failed: results.filter(r => r.status === 'fail').length, warnings: results.filter(r => r.status === 'warn').length } }); } else { logger.info(chalk.bold('\nšŸ“Š Diagnostic Results\n')); results.forEach(result => { const symbol = result.status === 'pass' ? chalk.green('āœ“') : result.status === 'fail' ? chalk.red('āœ—') : chalk.yellow('⚠'); logger.info(`${symbol} ${chalk.bold(result.check)}: ${result.message}`); if (result.details && logger.isVerbose()) { logger.debug(` ${JSON.stringify(result.details, null, 2)}`); } }); const passed = results.filter(r => r.status === 'pass').length; const failed = results.filter(r => r.status === 'fail').length; const warned = results.filter(r => r.status === 'warn').length; logger.info(''); logger.info(chalk.bold('Summary:')); logger.info(` ${chalk.green('āœ“')} Passed: ${passed}`); if (failed > 0) logger.info(` ${chalk.red('āœ—')} Failed: ${failed}`); if (warned > 0) logger.info(` ${chalk.yellow('⚠')} Warnings: ${warned}`); logger.info(''); if (failed > 0) { process.exit(1); } } } //# sourceMappingURL=doctor.js.map