UNPKG

aiwf

Version:

AI Workflow Framework for Claude Code with multi-language support (Korean/English)

443 lines (390 loc) 14.2 kB
import { TokenCounter } from '../utils/token-counter.js'; import { TokenTracker } from '../utils/token-tracker.js'; import { TokenStorage } from '../utils/token-storage.js'; import { TokenReporter } from '../utils/token-reporter.js'; import { TokenMonitor } from '../utils/token-monitor.js'; /** * 토큰 추적 시스템 명령어 인터페이스 */ export class TokenTrackingCommands { constructor() { this.counter = new TokenCounter(); this.tracker = new TokenTracker(); this.storage = new TokenStorage(); this.reporter = new TokenReporter(); this.monitor = new TokenMonitor(); } /** * 텍스트 또는 파일의 토큰 수를 계산합니다 * @param {Object} options - 옵션 * @param {string} options.text - 분석할 텍스트 * @param {string} options.file - 분석할 파일 경로 * @param {string} options.dir - 분석할 디렉토리 경로 * @returns {Object} 토큰 카운트 결과 */ async countTokens(options = {}) { try { if (options.text) { const tokens = this.counter.countTokens(options.text); return { type: 'text', tokens, characters: options.text.length, ratio: options.text.length > 0 ? (tokens / options.text.length).toFixed(3) : 0 }; } if (options.file) { const tokens = this.counter.countFileTokens(options.file); const stats = await import('fs').then(fs => fs.promises.stat(options.file)); return { type: 'file', path: options.file, tokens, size: stats.size, ratio: stats.size > 0 ? (tokens / stats.size).toFixed(3) : 0 }; } if (options.dir) { const tokens = this.counter.countDirectoryTokens(options.dir); const files = this.counter.getMarkdownFiles(options.dir); return { type: 'directory', path: options.dir, tokens, fileCount: files.length, avgTokensPerFile: files.length > 0 ? Math.round(tokens / files.length) : 0 }; } throw new Error('텍스트, 파일 또는 디렉토리 중 하나를 지정해야 합니다.'); } catch (error) { console.error('토큰 카운트 중 오류 발생:', error); return null; } } /** * 명령어 실행을 추적합니다 * @param {Object} options - 옵션 * @param {string} options.command - 실행된 명령어 * @param {string} options.input - 입력 텍스트 * @param {string} options.output - 출력 텍스트 * @returns {Object} 추적 결과 */ async trackCommand(options = {}) { try { const result = this.tracker.trackCommand( options.command || 'unknown', options.input || '', options.output || '' ); if (result) { // 모니터링 시스템에 체크 const violations = this.monitor.checkThresholds(); return { ...result, violations, sessionStats: this.tracker.getSessionStats() }; } return null; } catch (error) { console.error('명령어 추적 중 오류 발생:', error); return null; } } /** * 현재 세션의 토큰 사용량 보고서를 생성합니다 * @returns {Object} 세션 보고서 */ async generateSessionReport() { try { const report = this.tracker.generateReport(); if (report) { console.log('\n=== 세션 토큰 사용량 보고서 ==='); console.log(`세션 ID: ${report.sessionId}`); console.log(`세션 시간: ${report.sessionDuration}`); console.log(`실행 명령어: ${report.totalCommands}개`); console.log(`총 토큰: ${report.totalTokens.toLocaleString()}`); console.log(`명령어당 평균 토큰: ${report.avgTokensPerCommand.toLocaleString()}`); console.log(`시작 시간: ${report.startTime}`); console.log(`마지막 업데이트: ${report.lastUpdated}`); if (report.compressionStats) { console.log('\n--- 압축 통계 ---'); console.log(`원본 토큰: ${report.compressionStats.originalTokens.toLocaleString()}`); console.log(`압축 토큰: ${report.compressionStats.compressedTokens.toLocaleString()}`); console.log(`절약 토큰: ${report.compressionStats.savedTokens.toLocaleString()}`); console.log(`압축률: ${report.compressionStats.compressionRatio}`); console.log(`효율성: ${report.compressionStats.efficiency}`); } if (report.recentCommands.length > 0) { console.log('\n--- 최근 명령어 ---'); report.recentCommands.forEach((cmd, idx) => { console.log(`${idx + 1}. ${cmd.command}: ${cmd.totalTokens} 토큰`); }); } console.log('\n========================\n'); } return report; } catch (error) { console.error('세션 보고서 생성 중 오류 발생:', error); return null; } } /** * 프로젝트 토큰 분석을 수행합니다 * @param {Object} options - 옵션 * @param {string} options.path - 프로젝트 경로 * @param {boolean} options.detailed - 상세 분석 여부 * @returns {Object} 분석 결과 */ async analyzeProject(options = {}) { try { const report = this.reporter.generateProjectAnalysisReport(options.path || '.'); if (!report) { return null; } console.log('\n=== 프로젝트 토큰 분석 ==='); console.log(`프로젝트 경로: ${report.projectPath}`); console.log(`총 토큰: ${report.analysis.totalTokens.toLocaleString()}`); console.log(`분석 시간: ${new Date(report.generatedAt).toLocaleString()}`); console.log('\n--- 디렉토리별 분석 ---'); Object.entries(report.analysis.directoryBreakdown).forEach(([dir, data]) => { console.log(`${dir}: ${data.tokens.toLocaleString()} 토큰 (${data.percentage}%)`); }); if (options.detailed) { console.log('\n--- 상세 파일 분석 ---'); Object.entries(report.analysis.directoryBreakdown).forEach(([dir, data]) => { if (data.files.length > 0) { console.log(`\n${dir}:`); data.files.slice(0, 5).forEach(file => { console.log(` - ${file.path}: ${file.tokens.toLocaleString()} 토큰`); }); } }); } if (report.analysis.compressionOpportunities.length > 0) { console.log('\n--- 압축 기회 ---'); report.analysis.compressionOpportunities.forEach(op => { console.log(`${op.priority.toUpperCase()}: ${op.description}`); console.log(` 예상 절약: ${op.potentialSavings.toLocaleString()} 토큰`); }); } if (report.analysis.recommendations.length > 0) { console.log('\n--- 권장사항 ---'); report.analysis.recommendations.forEach(rec => { console.log(`${rec.priority.toUpperCase()}: ${rec.title}`); console.log(` ${rec.description}`); console.log(` 명령어: ${rec.action}`); }); } console.log('\n========================\n'); return report; } catch (error) { console.error('프로젝트 분석 중 오류 발생:', error); return null; } } /** * 사용량 보고서를 생성합니다 * @param {Object} options - 옵션 * @param {string} options.type - 보고서 타입 (daily, weekly, monthly) * @param {boolean} options.save - 파일 저장 여부 * @returns {Object} 보고서 데이터 */ async generateUsageReport(options = {}) { try { const report = this.reporter.generateUsageReport(options.type || 'daily'); if (!report) { return null; } this.reporter.printReport(report); if (options.save) { const filename = `usage_report_${options.type || 'daily'}_${Date.now()}.json`; this.reporter.saveReportToFile(report, filename); } return report; } catch (error) { console.error('사용량 보고서 생성 중 오류 발생:', error); return null; } } /** * 모니터링을 설정합니다 * @param {Object} options - 옵션 * @param {boolean} options.enable - 모니터링 활성화 여부 * @param {Object} options.thresholds - 임계값 설정 * @param {boolean} options.start - 실시간 모니터링 시작 여부 * @returns {Object} 설정 결과 */ async setupMonitoring(options = {}) { try { if (options.enable !== undefined) { this.monitor.setEnabled(options.enable); } if (options.thresholds) { this.monitor.setThresholds(options.thresholds); } if (options.start) { this.monitor.startMonitoring(); } return { success: true, status: this.monitor.getStatus() }; } catch (error) { console.error('모니터링 설정 중 오류 발생:', error); return { success: false, error: error.message }; } } /** * 모니터링 상태를 조회합니다 * @returns {Object} 모니터링 상태 */ async getMonitoringStatus() { try { this.monitor.displayDashboard(); return this.monitor.getStatus(); } catch (error) { console.error('모니터링 상태 조회 중 오류 발생:', error); return null; } } /** * 알림을 관리합니다 * @param {Object} options - 옵션 * @param {string} options.action - 액션 (list, acknowledge, clear) * @param {string} options.alertId - 알림 ID (acknowledge 시 필요) * @returns {Object} 알림 관리 결과 */ async manageAlerts(options = {}) { try { switch (options.action) { case 'list': const unacknowledged = this.monitor.getUnacknowledgedAlerts(); console.log(`미확인 알림: ${unacknowledged.length}개`); unacknowledged.forEach(alert => { const emoji = alert.level === 'critical' ? '🚨' : alert.level === 'warning' ? '⚠️' : 'ℹ️'; console.log(`${emoji} [${alert.id}] ${alert.message}`); }); return unacknowledged; case 'acknowledge': if (options.alertId) { this.monitor.acknowledgeAlert(options.alertId); } else { this.monitor.acknowledgeAllAlerts(); } return { success: true }; case 'clear': this.monitor.cleanupOldAlerts(); return { success: true }; default: throw new Error('올바른 액션을 지정해주세요: list, acknowledge, clear'); } } catch (error) { console.error('알림 관리 중 오류 발생:', error); return { success: false, error: error.message }; } } /** * 압축 전후 토큰 수를 기록합니다 * @param {Object} options - 옵션 * @param {number} options.originalTokens - 원본 토큰 수 * @param {number} options.compressedTokens - 압축 토큰 수 * @returns {Object} 압축 추적 결과 */ async trackCompression(options = {}) { try { if (!options.originalTokens || !options.compressedTokens) { throw new Error('원본 토큰 수와 압축 토큰 수를 모두 지정해야 합니다.'); } this.tracker.trackCompression(options.originalTokens, options.compressedTokens); const saved = options.originalTokens - options.compressedTokens; const ratio = ((saved / options.originalTokens) * 100).toFixed(2); console.log(`압축 완료: ${saved.toLocaleString()} 토큰 절약 (${ratio}%)`); return { originalTokens: options.originalTokens, compressedTokens: options.compressedTokens, savedTokens: saved, compressionRatio: ratio }; } catch (error) { console.error('압축 추적 중 오류 발생:', error); return null; } } /** * 세션 데이터를 정리합니다 * @param {Object} options - 옵션 * @param {number} options.daysToKeep - 보관할 일수 * @returns {Object} 정리 결과 */ async cleanupSessions(options = {}) { try { const daysToKeep = options.daysToKeep || 7; this.tracker.cleanupOldSessions(daysToKeep); return { success: true, daysToKeep }; } catch (error) { console.error('세션 정리 중 오류 발생:', error); return { success: false, error: error.message }; } } /** * 토큰 추적 시스템을 초기화합니다 * @returns {Object} 초기화 결과 */ async resetSystem() { try { this.storage.resetData(); this.monitor.cleanupOldAlerts(); console.log('토큰 추적 시스템이 초기화되었습니다.'); return { success: true }; } catch (error) { console.error('시스템 초기화 중 오류 발생:', error); return { success: false, error: error.message }; } } /** * 토큰 추적 시스템의 상태를 조회합니다 * @returns {Object} 시스템 상태 */ async getSystemStatus() { try { const sessionStats = this.tracker.getSessionStats(); const monitoringStatus = this.monitor.getStatus(); const alertStats = this.monitor.getAlertStats(); return { session: sessionStats, monitoring: monitoringStatus, alerts: alertStats, timestamp: Date.now() }; } catch (error) { console.error('시스템 상태 조회 중 오류 발생:', error); return null; } } /** * 리소스를 정리합니다 */ cleanup() { if (this.counter) { this.counter.cleanup(); } if (this.tracker) { this.tracker.cleanup(); } if (this.reporter) { this.reporter.cleanup(); } if (this.monitor) { this.monitor.stopMonitoring(); } } } /** * 토큰 추적 명령어 팩토리 */ export function createTokenTrackingCommands() { return new TokenTrackingCommands(); } export default TokenTrackingCommands;