aiwf
Version:
AI Workflow Framework for Claude Code with multi-language support (Korean/English)
246 lines (204 loc) • 6.74 kB
JavaScript
/**
* 경량화된 평가 명령어
* 선택적으로 사용할 수 있는 간단한 평가 도구
*/
import { SimplifiedEvaluator } from '../utils/simplified-evaluator.js';
import { getBackgroundMonitor } from '../utils/background-monitor.js';
import fs from 'fs/promises';
import path from 'path';
import chalk from 'chalk';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
/**
* evaluate 명령어 실행
*/
export async function executeEvaluate(args = []) {
const option = args[0];
try {
switch (option) {
case '--detailed':
case '-d':
return await detailedEvaluation();
case '--history':
case '-h':
return await showHistory();
case '--stats':
case '-s':
return await showStats();
default:
return await quickEvaluation();
}
} catch (error) {
console.error(chalk.red('오류:'), error.message);
}
}
/**
* 빠른 평가 (기본)
*/
async function quickEvaluation() {
console.log(chalk.cyan('🔍 최근 응답 평가'));
console.log(chalk.gray('━'.repeat(50)));
// 현재 페르소나 확인
const currentPersona = await getCurrentPersona();
if (!currentPersona) {
console.log(chalk.yellow('활성화된 페르소나가 없습니다.'));
console.log('페르소나를 먼저 활성화하세요: aiwf persona [architect|security|frontend|backend|data_analyst]');
return;
}
console.log(`현재 페르소나: ${chalk.yellow(currentPersona)}`);
// 최근 통계 표시
const monitor = getBackgroundMonitor();
const stats = monitor.getRecentStats(currentPersona);
if (stats.message) {
console.log(stats.message);
return;
}
console.log(`평균 점수: ${chalk.green(stats.averageScore)}`);
console.log(`평가 횟수: ${stats.totalEvaluations}`);
console.log(`추세: ${getTrendEmoji(stats.trend)} ${getKoreanTrend(stats.trend)}`);
// 간단한 팁
if (parseFloat(stats.averageScore) < 0.6) {
console.log('');
console.log(chalk.yellow('💡 팁: 페르소나 특성을 더 활용해보세요!'));
} else if (parseFloat(stats.averageScore) > 0.8) {
console.log('');
console.log(chalk.green('🎉 훌륭해요! 페르소나를 잘 활용하고 있습니다.'));
}
}
/**
* 상세 평가
*/
async function detailedEvaluation() {
console.log(chalk.cyan('📊 상세 평가 분석'));
console.log(chalk.gray('━'.repeat(50)));
const monitor = getBackgroundMonitor();
const stats = monitor.getRecentStats();
if (stats.message) {
console.log(stats.message);
return;
}
console.log(chalk.white('전체 통계:'));
console.log(`- 총 평가: ${stats.totalEvaluations}회`);
console.log(`- 평균 점수: ${stats.averageScore}`);
console.log(`- 추세: ${getTrendEmoji(stats.trend)} ${getKoreanTrend(stats.trend)}`);
console.log('');
console.log(chalk.white('페르소나별 성과:'));
Object.entries(stats.personaStats).forEach(([persona, data]) => {
const score = parseFloat(data.avgScore);
const scoreColor = score >= 0.8 ? 'green' : score >= 0.6 ? 'yellow' : 'red';
console.log(`- ${getKoreanPersonaName(persona)}: ${chalk[scoreColor](data.avgScore)} (${data.count}회)`);
});
// 개선 제안
console.log('');
console.log(chalk.white('개선 제안:'));
Object.entries(stats.personaStats).forEach(([persona, data]) => {
if (parseFloat(data.avgScore) < 0.6) {
const evaluator = new SimplifiedEvaluator();
const feedback = evaluator.getGentleFeedback(persona, parseFloat(data.avgScore));
if (feedback) {
console.log(feedback);
}
}
});
}
/**
* 평가 히스토리
*/
async function showHistory() {
console.log(chalk.cyan('📈 평가 히스토리'));
console.log(chalk.gray('━'.repeat(50)));
const monitor = getBackgroundMonitor();
const history = monitor.recentEvaluations.slice(-10); // 최근 10개
if (history.length === 0) {
console.log('평가 기록이 없습니다.');
return;
}
history.forEach((eval, index) => {
const date = new Date(eval.timestamp);
const timeStr = `${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}`;
const scoreColor = eval.score >= 0.8 ? 'green' : eval.score >= 0.6 ? 'yellow' : 'red';
console.log(`${timeStr} | ${getKoreanPersonaName(eval.persona)} | ${chalk[scoreColor](eval.score.toFixed(2))}`);
});
}
/**
* 주간 통계
*/
async function showStats() {
console.log(chalk.cyan('📊 주간 통계'));
console.log(chalk.gray('━'.repeat(50)));
const monitor = getBackgroundMonitor();
const summary = monitor.getWeeklySummary();
if (summary.message) {
console.log(summary.message);
return;
}
console.log(`평가 횟수: ${summary.evaluationCount}회`);
console.log(`평균 점수: ${summary.averageScore}`);
console.log(`추세: ${getTrendEmoji(summary.trend)} ${getKoreanTrend(summary.trend)}`);
if (summary.personaStats) {
console.log('');
console.log('페르소나별 활용도:');
const sorted = Object.entries(summary.personaStats)
.sort((a, b) => b[1].count - a[1].count);
sorted.forEach(([persona, data]) => {
const bar = '█'.repeat(Math.floor(data.count / 2));
console.log(`${getKoreanPersonaName(persona).padEnd(10)} ${bar} ${data.count}회`);
});
}
}
/**
* 현재 페르소나 가져오기
*/
async function getCurrentPersona() {
try {
const personaPath = path.join(process.cwd(), '.aiwf', 'current_persona.json');
const data = await fs.readFile(personaPath, 'utf8');
const personaData = JSON.parse(data);
return personaData.persona;
} catch {
return null;
}
}
/**
* 페르소나 이름 한글화
*/
function getKoreanPersonaName(persona) {
const names = {
architect: '아키텍트',
security: '보안 전문가',
frontend: '프론트엔드',
backend: '백엔드',
data_analyst: '데이터 분석가'
};
return names[persona] || persona;
}
/**
* 추세 이모지
*/
function getTrendEmoji(trend) {
const emojis = {
improving: '📈',
declining: '📉',
stable: '➡️'
};
return emojis[trend] || '❓';
}
/**
* 추세 한글화
*/
function getKoreanTrend(trend) {
const trends = {
improving: '개선 중',
declining: '하락 중',
stable: '안정적'
};
return trends[trend] || trend;
}
// CLI로 직접 실행하는 경우
if (import.meta.url === `file://${process.argv[1]}`) {
const args = process.argv.slice(2);
executeEvaluate(args);
}
export default executeEvaluate;