aiwf 0.3.21 → 0.3.23
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +3 -2
- package/src/cli/index.js +39 -336
- package/src/lib/installer.js +310 -90
- package/src/utils/messages.js +24 -0
- package/src/DEPENDENCY_MAP.md +0 -90
- package/src/cli/cache-cli.js +0 -459
- package/src/cli/checkpoint-cli.js +0 -417
- package/src/cli/language-cli.js +0 -286
- package/src/cli/sprint-cli.js +0 -287
- package/src/commands/ai-tool.js +0 -383
- package/src/commands/compress.js +0 -60
- package/src/commands/create-project.js +0 -160
- package/src/commands/evaluate.js +0 -459
- package/src/commands/persona.js +0 -309
- package/src/commands/sprint-task.js +0 -262
- package/src/commands/token.js +0 -312
- package/src/lib/ai-persona-manager.js +0 -711
- package/src/lib/cache-system.js +0 -332
- package/src/lib/context-engine.js +0 -568
- package/src/lib/github-integration.js +0 -402
- package/src/lib/memory-profiler.js +0 -471
- package/src/lib/metrics-collector.js +0 -885
- package/src/lib/offline-detector.js +0 -386
- package/src/lib/resource-loader-enhanced.js +0 -399
- package/src/lib/resource-loader.js +0 -250
- package/src/lib/resources/commands/ai-persona.js +0 -602
- package/src/lib/resources/commands/compress-context.js +0 -389
- package/src/lib/resources/commands/evaluate.js +0 -246
- package/src/lib/resources/commands/persona-context-apply.js +0 -562
- package/src/lib/resources/commands/token-tracking.js +0 -443
- package/src/lib/resources/config/commit-patterns.js +0 -103
- package/src/lib/resources/config/language.json +0 -6
- package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
- package/src/lib/resources/personas/analyst.json +0 -44
- package/src/lib/resources/personas/architect/best_practices.md +0 -136
- package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
- package/src/lib/resources/personas/architect.json +0 -44
- package/src/lib/resources/personas/backend/best_practices.md +0 -766
- package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
- package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
- package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
- package/src/lib/resources/personas/developer.json +0 -44
- package/src/lib/resources/personas/developer.md +0 -37
- package/src/lib/resources/personas/evaluation_criteria.json +0 -137
- package/src/lib/resources/personas/frontend/best_practices.md +0 -445
- package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
- package/src/lib/resources/personas/persona-index.json +0 -31
- package/src/lib/resources/personas/reviewer.json +0 -44
- package/src/lib/resources/personas/security/best_practices.md +0 -307
- package/src/lib/resources/personas/security/knowledge_base.md +0 -498
- package/src/lib/resources/personas/tester.json +0 -44
- package/src/lib/resources/templates/README.md +0 -78
- package/src/lib/resources/templates/api-server/config.json +0 -64
- package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
- package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
- package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
- package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
- package/src/lib/resources/templates/api-server/template/.env.example +0 -29
- package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
- package/src/lib/resources/templates/api-server/template/README.md +0 -171
- package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
- package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
- package/src/lib/resources/templates/api-server/template/package.json +0 -61
- package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
- package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
- package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
- package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
- package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
- package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
- package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
- package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
- package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
- package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
- package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
- package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
- package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
- package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
- package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
- package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
- package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
- package/src/lib/resources/templates/npm-library/config.json +0 -61
- package/src/lib/resources/templates/npm-library/template/LICENSE +0 -21
- package/src/lib/resources/templates/npm-library/template/README.md +0 -201
- package/src/lib/resources/templates/npm-library/template/package.json +0 -78
- package/src/lib/resources/templates/web-app/config.json +0 -53
- package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
- package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
- package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
- package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
- package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
- package/src/lib/resources/templates/web-app/template/README.md +0 -151
- package/src/lib/resources/templates/web-app/template/index.html +0 -14
- package/src/lib/resources/templates/web-app/template/package.json +0 -44
- package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
- package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
- package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
- package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
- package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
- package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
- package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
- package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
- package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
- package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
- package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
- package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
- package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
- package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
- package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
- package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
- package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
- package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
- package/src/lib/resources/utils/background-monitor.js +0 -223
- package/src/lib/resources/utils/compression-metrics.js +0 -1031
- package/src/lib/resources/utils/compression-strategies.js +0 -557
- package/src/lib/resources/utils/content-normalizer.js +0 -455
- package/src/lib/resources/utils/context-compressor.js +0 -583
- package/src/lib/resources/utils/context-rule-parser.js +0 -180
- package/src/lib/resources/utils/context-token-monitor.js +0 -463
- package/src/lib/resources/utils/context-update-manager.js +0 -502
- package/src/lib/resources/utils/git-utils.js +0 -220
- package/src/lib/resources/utils/importance-classifier.js +0 -645
- package/src/lib/resources/utils/information-filter.js +0 -710
- package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
- package/src/lib/resources/utils/prompt-injector.js +0 -242
- package/src/lib/resources/utils/simplified-evaluator.js +0 -119
- package/src/lib/resources/utils/text-summarizer.js +0 -492
- package/src/lib/resources/utils/token-counter.js +0 -177
- package/src/lib/resources/utils/token-monitor.js +0 -484
- package/src/lib/resources/utils/token-reporter.js +0 -452
- package/src/lib/resources/utils/token-storage.js +0 -433
- package/src/lib/resources/utils/token-tracker.js +0 -283
- package/src/lib/state/priority-calculator.js +0 -217
- package/src/lib/state/state-index.js +0 -155
- package/src/lib/state/task-scanner.js +0 -328
- package/src/lib/task-analyzer.js +0 -599
- package/src/lib/template-cache-system.js +0 -559
- package/src/lib/template-downloader.js +0 -467
- package/src/lib/template-version-manager.js +0 -491
- package/src/lib/token-optimizer.js +0 -517
- package/src/utils/engineering-guard.js +0 -399
package/src/cli/language-cli.js
DELETED
|
@@ -1,286 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* 언어 관리 CLI 명령어
|
|
5
|
-
* AIWF 프레임워크의 언어 설정을 관리하는 CLI 도구입니다.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { Command } from 'commander';
|
|
9
|
-
import chalk from 'chalk';
|
|
10
|
-
import prompts from 'prompts';
|
|
11
|
-
import {
|
|
12
|
-
detectLanguage,
|
|
13
|
-
loadUserLanguageConfig,
|
|
14
|
-
saveUserLanguageConfig,
|
|
15
|
-
switchLanguage,
|
|
16
|
-
getLanguageStatus,
|
|
17
|
-
getLocalizedMessage,
|
|
18
|
-
SUPPORTED_LANGUAGES,
|
|
19
|
-
DEFAULT_LANGUAGE
|
|
20
|
-
} from '../utils/language-utils.js';
|
|
21
|
-
|
|
22
|
-
const program = new Command();
|
|
23
|
-
|
|
24
|
-
// 다국어 CLI 메시지
|
|
25
|
-
const CLI_MESSAGES = {
|
|
26
|
-
ko: {
|
|
27
|
-
LANGUAGE_STATUS_TITLE: '🌐 AIWF 언어 설정 상태',
|
|
28
|
-
DETECTED_LANGUAGE: '감지된 언어',
|
|
29
|
-
CONFIGURED_LANGUAGE: '설정된 언어',
|
|
30
|
-
EFFECTIVE_LANGUAGE: '사용 중인 언어',
|
|
31
|
-
AUTO_DETECT: '자동 감지',
|
|
32
|
-
FALLBACK_LANGUAGE: '폴백 언어',
|
|
33
|
-
SUPPORTED_LANGUAGES: '지원 언어',
|
|
34
|
-
CONFIG_PATH: '설정 파일 경로',
|
|
35
|
-
ENABLED: '활성화',
|
|
36
|
-
DISABLED: '비활성화',
|
|
37
|
-
NOT_SET: '설정되지 않음',
|
|
38
|
-
SELECT_LANGUAGE: '사용할 언어를 선택하세요:',
|
|
39
|
-
ENABLE_AUTO_DETECT: '자동 언어 감지를 활성화하시겠습니까?',
|
|
40
|
-
LANGUAGE_CHANGED: '언어가 성공적으로 변경되었습니다',
|
|
41
|
-
OPERATION_CANCELLED: '작업이 취소되었습니다',
|
|
42
|
-
CURRENT_LANGUAGE: '현재 언어',
|
|
43
|
-
PREVIOUS_LANGUAGE: '이전 언어',
|
|
44
|
-
NEW_LANGUAGE: '새 언어'
|
|
45
|
-
},
|
|
46
|
-
en: {
|
|
47
|
-
LANGUAGE_STATUS_TITLE: '🌐 AIWF Language Configuration Status',
|
|
48
|
-
DETECTED_LANGUAGE: 'Detected Language',
|
|
49
|
-
CONFIGURED_LANGUAGE: 'Configured Language',
|
|
50
|
-
EFFECTIVE_LANGUAGE: 'Effective Language',
|
|
51
|
-
AUTO_DETECT: 'Auto Detection',
|
|
52
|
-
FALLBACK_LANGUAGE: 'Fallback Language',
|
|
53
|
-
SUPPORTED_LANGUAGES: 'Supported Languages',
|
|
54
|
-
CONFIG_PATH: 'Configuration Path',
|
|
55
|
-
ENABLED: 'Enabled',
|
|
56
|
-
DISABLED: 'Disabled',
|
|
57
|
-
NOT_SET: 'Not Set',
|
|
58
|
-
SELECT_LANGUAGE: 'Select language to use:',
|
|
59
|
-
ENABLE_AUTO_DETECT: 'Enable automatic language detection?',
|
|
60
|
-
LANGUAGE_CHANGED: 'Language changed successfully',
|
|
61
|
-
OPERATION_CANCELLED: 'Operation cancelled',
|
|
62
|
-
CURRENT_LANGUAGE: 'Current Language',
|
|
63
|
-
PREVIOUS_LANGUAGE: 'Previous Language',
|
|
64
|
-
NEW_LANGUAGE: 'New Language'
|
|
65
|
-
}
|
|
66
|
-
};
|
|
67
|
-
|
|
68
|
-
/**
|
|
69
|
-
* 로컬라이즈된 CLI 메시지 가져오기
|
|
70
|
-
*/
|
|
71
|
-
function getCliMessage(key, language = DEFAULT_LANGUAGE) {
|
|
72
|
-
return CLI_MESSAGES[language]?.[key] || CLI_MESSAGES[DEFAULT_LANGUAGE]?.[key] || key;
|
|
73
|
-
}
|
|
74
|
-
|
|
75
|
-
/**
|
|
76
|
-
* 언어 설정 상태 표시
|
|
77
|
-
*/
|
|
78
|
-
export async function showLanguageStatus() {
|
|
79
|
-
try {
|
|
80
|
-
const status = await getLanguageStatus();
|
|
81
|
-
const currentLang = status.effectiveLanguage;
|
|
82
|
-
|
|
83
|
-
console.log(chalk.blue.bold(`\n${getCliMessage('LANGUAGE_STATUS_TITLE', currentLang)}`));
|
|
84
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
85
|
-
|
|
86
|
-
console.log(chalk.white(`${getCliMessage('DETECTED_LANGUAGE', currentLang)}: `) +
|
|
87
|
-
chalk.green(status.detectedLanguage));
|
|
88
|
-
|
|
89
|
-
console.log(chalk.white(`${getCliMessage('CONFIGURED_LANGUAGE', currentLang)}: `) +
|
|
90
|
-
(status.configuredLanguage ? chalk.green(status.configuredLanguage) :
|
|
91
|
-
chalk.gray(getCliMessage('NOT_SET', currentLang))));
|
|
92
|
-
|
|
93
|
-
console.log(chalk.white(`${getCliMessage('EFFECTIVE_LANGUAGE', currentLang)}: `) +
|
|
94
|
-
chalk.cyan.bold(status.effectiveLanguage));
|
|
95
|
-
|
|
96
|
-
console.log(chalk.white(`${getCliMessage('AUTO_DETECT', currentLang)}: `) +
|
|
97
|
-
(status.autoDetect ?
|
|
98
|
-
chalk.green(getCliMessage('ENABLED', currentLang)) :
|
|
99
|
-
chalk.yellow(getCliMessage('DISABLED', currentLang))));
|
|
100
|
-
|
|
101
|
-
console.log(chalk.white(`${getCliMessage('FALLBACK_LANGUAGE', currentLang)}: `) +
|
|
102
|
-
chalk.gray(status.fallbackLanguage));
|
|
103
|
-
|
|
104
|
-
console.log(chalk.white(`${getCliMessage('SUPPORTED_LANGUAGES', currentLang)}: `) +
|
|
105
|
-
chalk.gray(status.supportedLanguages.join(', ')));
|
|
106
|
-
|
|
107
|
-
console.log(chalk.white(`${getCliMessage('CONFIG_PATH', currentLang)}: `) +
|
|
108
|
-
chalk.gray(status.configPath));
|
|
109
|
-
|
|
110
|
-
if (status.error) {
|
|
111
|
-
console.log(chalk.red('\n⚠️ Error: ' + status.error));
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
console.log(chalk.gray('─'.repeat(50)));
|
|
115
|
-
|
|
116
|
-
} catch (error) {
|
|
117
|
-
console.error(chalk.red('Error showing language status:', error.message));
|
|
118
|
-
}
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
/**
|
|
122
|
-
* 언어 설정 변경
|
|
123
|
-
*/
|
|
124
|
-
export async function setLanguage(language = null, options = {}) {
|
|
125
|
-
try {
|
|
126
|
-
let targetLanguage = language;
|
|
127
|
-
let autoDetect = options.autoDetect;
|
|
128
|
-
|
|
129
|
-
// 언어가 지정되지 않은 경우 사용자에게 선택 요청
|
|
130
|
-
if (!targetLanguage) {
|
|
131
|
-
const currentStatus = await getLanguageStatus();
|
|
132
|
-
const currentLang = currentStatus.effectiveLanguage;
|
|
133
|
-
|
|
134
|
-
const languageResponse = await prompts({
|
|
135
|
-
type: 'select',
|
|
136
|
-
name: 'language',
|
|
137
|
-
message: getCliMessage('SELECT_LANGUAGE', currentLang),
|
|
138
|
-
choices: SUPPORTED_LANGUAGES.map(lang => ({
|
|
139
|
-
title: lang === 'ko' ? '한국어 (Korean)' : 'English',
|
|
140
|
-
value: lang
|
|
141
|
-
}))
|
|
142
|
-
});
|
|
143
|
-
|
|
144
|
-
if (!languageResponse.language) {
|
|
145
|
-
console.log(chalk.yellow(getCliMessage('OPERATION_CANCELLED', currentLang)));
|
|
146
|
-
return;
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
targetLanguage = languageResponse.language;
|
|
150
|
-
|
|
151
|
-
// 자동 감지 설정이 지정되지 않은 경우 사용자에게 묻기
|
|
152
|
-
if (autoDetect === undefined) {
|
|
153
|
-
const autoDetectResponse = await prompts({
|
|
154
|
-
type: 'confirm',
|
|
155
|
-
name: 'autoDetect',
|
|
156
|
-
message: getCliMessage('ENABLE_AUTO_DETECT', targetLanguage),
|
|
157
|
-
initial: true
|
|
158
|
-
});
|
|
159
|
-
|
|
160
|
-
autoDetect = autoDetectResponse.autoDetect;
|
|
161
|
-
}
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
// 언어 전환 실행
|
|
165
|
-
const result = await switchLanguage(targetLanguage);
|
|
166
|
-
|
|
167
|
-
if (result.success) {
|
|
168
|
-
console.log(chalk.green(`\n✅ ${getCliMessage('LANGUAGE_CHANGED', targetLanguage)}`));
|
|
169
|
-
console.log(chalk.gray(` ${getCliMessage('PREVIOUS_LANGUAGE', targetLanguage)}: ${result.previousLanguage}`));
|
|
170
|
-
console.log(chalk.gray(` ${getCliMessage('NEW_LANGUAGE', targetLanguage)}: ${result.newLanguage}`));
|
|
171
|
-
|
|
172
|
-
// 자동 감지 설정 업데이트
|
|
173
|
-
if (autoDetect !== undefined) {
|
|
174
|
-
await saveUserLanguageConfig(targetLanguage, { autoDetect });
|
|
175
|
-
console.log(chalk.gray(` ${getCliMessage('AUTO_DETECT', targetLanguage)}: ${autoDetect ? getCliMessage('ENABLED', targetLanguage) : getCliMessage('DISABLED', targetLanguage)}`));
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
} else {
|
|
179
|
-
console.error(chalk.red('\n❌ ' + result.message));
|
|
180
|
-
if (result.error) {
|
|
181
|
-
console.error(chalk.gray(' Error: ' + result.error));
|
|
182
|
-
}
|
|
183
|
-
}
|
|
184
|
-
|
|
185
|
-
} catch (error) {
|
|
186
|
-
console.error(chalk.red('Error setting language:', error.message));
|
|
187
|
-
}
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
/**
|
|
191
|
-
* 언어 설정 초기화
|
|
192
|
-
*/
|
|
193
|
-
export async function resetLanguage() {
|
|
194
|
-
try {
|
|
195
|
-
const currentStatus = await getLanguageStatus();
|
|
196
|
-
const currentLang = currentStatus.effectiveLanguage;
|
|
197
|
-
|
|
198
|
-
const confirmResponse = await prompts({
|
|
199
|
-
type: 'confirm',
|
|
200
|
-
name: 'confirm',
|
|
201
|
-
message: currentLang === 'ko' ?
|
|
202
|
-
'언어 설정을 초기화하시겠습니까? (자동 감지 모드로 돌아갑니다)' :
|
|
203
|
-
'Reset language configuration? (Will return to auto-detection mode)',
|
|
204
|
-
initial: false
|
|
205
|
-
});
|
|
206
|
-
|
|
207
|
-
if (!confirmResponse.confirm) {
|
|
208
|
-
console.log(chalk.yellow(getCliMessage('OPERATION_CANCELLED', currentLang)));
|
|
209
|
-
return;
|
|
210
|
-
}
|
|
211
|
-
|
|
212
|
-
// 설정 파일 삭제 (자동 감지 모드로 복원)
|
|
213
|
-
const fs = await import('fs/promises');
|
|
214
|
-
const { LANGUAGE_CONFIG_PATH } = await import('./language-utils.js');
|
|
215
|
-
|
|
216
|
-
try {
|
|
217
|
-
await fs.unlink(LANGUAGE_CONFIG_PATH);
|
|
218
|
-
console.log(chalk.green('\n✅ ' + (currentLang === 'ko' ?
|
|
219
|
-
'언어 설정이 초기화되었습니다' :
|
|
220
|
-
'Language configuration reset successfully')));
|
|
221
|
-
console.log(chalk.gray(' ' + (currentLang === 'ko' ?
|
|
222
|
-
'이제 시스템 언어가 자동으로 감지됩니다' :
|
|
223
|
-
'System language will now be automatically detected')));
|
|
224
|
-
} catch (error) {
|
|
225
|
-
if (error.code === 'ENOENT') {
|
|
226
|
-
console.log(chalk.yellow('\n⚠️ ' + (currentLang === 'ko' ?
|
|
227
|
-
'설정 파일이 존재하지 않습니다' :
|
|
228
|
-
'Configuration file does not exist')));
|
|
229
|
-
} else {
|
|
230
|
-
throw error;
|
|
231
|
-
}
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
} catch (error) {
|
|
235
|
-
console.error(chalk.red('Error resetting language configuration:', error.message));
|
|
236
|
-
}
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
// CLI 명령어 정의
|
|
240
|
-
program
|
|
241
|
-
.name('aiwf-lang')
|
|
242
|
-
.description('AIWF Language Management CLI / AIWF 언어 관리 CLI')
|
|
243
|
-
.version('1.0.0');
|
|
244
|
-
|
|
245
|
-
program
|
|
246
|
-
.command('status')
|
|
247
|
-
.alias('s')
|
|
248
|
-
.description('Show current language configuration / 현재 언어 설정 표시')
|
|
249
|
-
.action(showLanguageStatus);
|
|
250
|
-
|
|
251
|
-
program
|
|
252
|
-
.command('set [language]')
|
|
253
|
-
.alias('switch')
|
|
254
|
-
.description('Set or change language / 언어 설정 또는 변경')
|
|
255
|
-
.option('-a, --auto-detect [boolean]', 'Enable/disable auto detection / 자동 감지 활성화/비활성화')
|
|
256
|
-
.action(setLanguage);
|
|
257
|
-
|
|
258
|
-
program
|
|
259
|
-
.command('reset')
|
|
260
|
-
.alias('r')
|
|
261
|
-
.description('Reset language configuration to auto-detection / 언어 설정을 자동 감지로 초기화')
|
|
262
|
-
.action(resetLanguage);
|
|
263
|
-
|
|
264
|
-
// 기본 명령어 (인수 없이 실행 시)
|
|
265
|
-
program
|
|
266
|
-
.action(async () => {
|
|
267
|
-
await showLanguageStatus();
|
|
268
|
-
console.log(chalk.blue('\n💡 사용 가능한 명령어 / Available commands:'));
|
|
269
|
-
console.log(chalk.gray(' aiwf-lang status - 현재 설정 표시 / Show current configuration'));
|
|
270
|
-
console.log(chalk.gray(' aiwf-lang set - 언어 설정 / Set language'));
|
|
271
|
-
console.log(chalk.gray(' aiwf-lang reset - 설정 초기화 / Reset configuration'));
|
|
272
|
-
});
|
|
273
|
-
|
|
274
|
-
// CLI 실행
|
|
275
|
-
if (import.meta.url === `file://${process.argv[1]}`) {
|
|
276
|
-
// Deprecated 경고 표시
|
|
277
|
-
console.log(chalk.yellow('⚠️ DEPRECATED: `aiwf-lang` is deprecated.'));
|
|
278
|
-
console.log(chalk.yellow(' Please use `aiwf lang` instead:'));
|
|
279
|
-
console.log(chalk.gray(' aiwf-lang status → aiwf lang status'));
|
|
280
|
-
console.log(chalk.gray(' aiwf-lang set → aiwf lang set'));
|
|
281
|
-
console.log(chalk.gray(' aiwf-lang reset → aiwf lang reset\n'));
|
|
282
|
-
|
|
283
|
-
program.parse(process.argv);
|
|
284
|
-
}
|
|
285
|
-
|
|
286
|
-
export default program;
|
package/src/cli/sprint-cli.js
DELETED
|
@@ -1,287 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
/**
|
|
4
|
-
* AIWF 스프린트 CLI
|
|
5
|
-
* 독립 스프린트 생성 및 관리를 위한 명령어 인터페이스
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
import { Command } from 'commander';
|
|
9
|
-
import chalk from 'chalk';
|
|
10
|
-
import { createIndependentSprint } from '../commands/sprint-independent.js';
|
|
11
|
-
|
|
12
|
-
const program = new Command();
|
|
13
|
-
|
|
14
|
-
program
|
|
15
|
-
.name('aiwf-sprint')
|
|
16
|
-
.description('AIWF 독립 스프린트 관리 도구')
|
|
17
|
-
.version('0.3.12');
|
|
18
|
-
|
|
19
|
-
// 독립 스프린트 생성 명령어
|
|
20
|
-
program
|
|
21
|
-
.command('independent [name]')
|
|
22
|
-
.alias('ind')
|
|
23
|
-
.description('독립 스프린트 생성')
|
|
24
|
-
.option('--from-readme', 'README에서 TODO 추출하여 스프린트 생성')
|
|
25
|
-
.option('--from-issue <number>', 'GitHub 이슈에서 스프린트 생성')
|
|
26
|
-
.option('--minimal', '최소 엔지니어링 레벨 설정 (기본값)')
|
|
27
|
-
.option('--balanced', '균형 엔지니어링 레벨 설정')
|
|
28
|
-
.option('--complete', '완전 엔지니어링 레벨 설정')
|
|
29
|
-
.option('--description <desc>', '스프린트 설명')
|
|
30
|
-
.action(async (name, options) => {
|
|
31
|
-
try {
|
|
32
|
-
console.log(chalk.blue('🚀 독립 스프린트 생성 중...'));
|
|
33
|
-
console.log('');
|
|
34
|
-
|
|
35
|
-
// 엔지니어링 레벨 결정
|
|
36
|
-
let engineeringLevel = 'minimal';
|
|
37
|
-
if (options.balanced) engineeringLevel = 'balanced';
|
|
38
|
-
else if (options.complete) engineeringLevel = 'complete';
|
|
39
|
-
|
|
40
|
-
// 옵션 구성
|
|
41
|
-
const sprintOptions = {
|
|
42
|
-
name,
|
|
43
|
-
description: options.description,
|
|
44
|
-
engineeringLevel,
|
|
45
|
-
fromReadme: options.fromReadme,
|
|
46
|
-
fromIssue: options.fromIssue,
|
|
47
|
-
minimal: engineeringLevel === 'minimal'
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
// 독립 스프린트 생성
|
|
51
|
-
const result = await createIndependentSprint(sprintOptions);
|
|
52
|
-
|
|
53
|
-
if (result.success) {
|
|
54
|
-
console.log('');
|
|
55
|
-
console.log(chalk.green('✅ 독립 스프린트 생성 완료!'));
|
|
56
|
-
console.log('');
|
|
57
|
-
console.log(chalk.bold('📋 생성된 스프린트 정보:'));
|
|
58
|
-
console.log(` 스프린트 ID: ${chalk.cyan(result.sprintId)}`);
|
|
59
|
-
console.log(` 태스크 수: ${chalk.blue(result.tasks)}개`);
|
|
60
|
-
console.log('');
|
|
61
|
-
console.log(chalk.bold('🚀 다음 단계:'));
|
|
62
|
-
console.log(` 1. Claude Code에서 ${chalk.cyan(`/project:aiwf:yolo ${result.sprintId}`)} 실행`);
|
|
63
|
-
console.log(` 2. 또는 ${chalk.cyan(`/project:aiwf:yolo --from-independent`)} 실행`);
|
|
64
|
-
console.log('');
|
|
65
|
-
console.log(chalk.gray('💡 팁: YOLO 모드로 전체 스프린트를 자동 완성할 수 있습니다!'));
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
} catch (error) {
|
|
69
|
-
console.error(chalk.red('❌ 독립 스프린트 생성 실패:'), error.message);
|
|
70
|
-
process.exit(1);
|
|
71
|
-
}
|
|
72
|
-
});
|
|
73
|
-
|
|
74
|
-
// 스프린트 목록 보기
|
|
75
|
-
program
|
|
76
|
-
.command('list')
|
|
77
|
-
.alias('ls')
|
|
78
|
-
.description('현재 프로젝트의 모든 스프린트 목록')
|
|
79
|
-
.option('--status <status>', '상태별 필터링 (active, completed, pending)')
|
|
80
|
-
.action(async (options) => {
|
|
81
|
-
try {
|
|
82
|
-
const fs = await import('fs/promises');
|
|
83
|
-
const path = await import('path');
|
|
84
|
-
|
|
85
|
-
// 프로젝트 루트 찾기
|
|
86
|
-
let currentDir = process.cwd();
|
|
87
|
-
while (currentDir !== path.parse(currentDir).root) {
|
|
88
|
-
try {
|
|
89
|
-
await fs.access(path.join(currentDir, '.aiwf'));
|
|
90
|
-
break;
|
|
91
|
-
} catch {
|
|
92
|
-
currentDir = path.dirname(currentDir);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
const sprintsDir = path.join(currentDir, '.aiwf', '03_SPRINTS');
|
|
97
|
-
|
|
98
|
-
try {
|
|
99
|
-
const entries = await fs.readdir(sprintsDir);
|
|
100
|
-
const sprintDirs = entries.filter(entry => entry.match(/^S\d+_/));
|
|
101
|
-
|
|
102
|
-
if (sprintDirs.length === 0) {
|
|
103
|
-
console.log(chalk.yellow('📭 스프린트가 없습니다.'));
|
|
104
|
-
console.log('');
|
|
105
|
-
console.log(chalk.gray('새 독립 스프린트를 생성하려면:'));
|
|
106
|
-
console.log(chalk.blue(' aiwf-sprint independent "프로젝트 이름"'));
|
|
107
|
-
return;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
console.log(chalk.bold('📊 스프린트 목록:'));
|
|
111
|
-
console.log('');
|
|
112
|
-
|
|
113
|
-
for (const sprintDir of sprintDirs.sort()) {
|
|
114
|
-
const sprintPath = path.join(sprintsDir, sprintDir);
|
|
115
|
-
const sprintId = sprintDir.match(/^(S\d+)_/)[1];
|
|
116
|
-
|
|
117
|
-
// 스프린트 메타 파일 읽기
|
|
118
|
-
try {
|
|
119
|
-
const metaFiles = (await fs.readdir(sprintPath)).filter(f => f.includes('meta.md'));
|
|
120
|
-
if (metaFiles.length > 0) {
|
|
121
|
-
const metaContent = await fs.readFile(path.join(sprintPath, metaFiles[0]), 'utf-8');
|
|
122
|
-
const statusMatch = metaContent.match(/\*\*상태\*\*:\s*(\w+)/);
|
|
123
|
-
const typeMatch = metaContent.match(/\*\*타입\*\*:\s*([^\n]+)/);
|
|
124
|
-
|
|
125
|
-
const status = statusMatch ? statusMatch[1] : 'unknown';
|
|
126
|
-
const type = typeMatch ? typeMatch[1].trim() : 'normal';
|
|
127
|
-
|
|
128
|
-
// 상태 필터링
|
|
129
|
-
if (options.status && status !== options.status) {
|
|
130
|
-
continue;
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
const statusIcon = status === 'active' ? '🔄' :
|
|
134
|
-
status === 'completed' ? '✅' : '⏳';
|
|
135
|
-
const typeIcon = type.includes('독립') ? '🚀' : '📋';
|
|
136
|
-
|
|
137
|
-
console.log(`${statusIcon} ${typeIcon} ${chalk.cyan(sprintId)} - ${chalk.white(sprintDir.split('_').slice(1).join('_'))}`);
|
|
138
|
-
console.log(` 상태: ${chalk.yellow(status)} | 타입: ${chalk.gray(type)}`);
|
|
139
|
-
|
|
140
|
-
// 태스크 수 계산
|
|
141
|
-
const taskFiles = (await fs.readdir(sprintPath)).filter(f => f.match(/^T\d+_/));
|
|
142
|
-
console.log(` 태스크: ${chalk.blue(taskFiles.length)}개`);
|
|
143
|
-
}
|
|
144
|
-
} catch (error) {
|
|
145
|
-
console.log(`${chalk.red('❌')} ${chalk.cyan(sprintId)} - ${chalk.gray('메타데이터 읽기 실패')}`);
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
console.log('');
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
} catch (error) {
|
|
152
|
-
console.log(chalk.yellow('📭 스프린트 디렉토리가 없습니다.'));
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
} catch (error) {
|
|
156
|
-
console.error(chalk.red('❌ 스프린트 목록 조회 실패:'), error.message);
|
|
157
|
-
process.exit(1);
|
|
158
|
-
}
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// 스프린트 상태 확인
|
|
162
|
-
program
|
|
163
|
-
.command('status <sprintId>')
|
|
164
|
-
.description('특정 스프린트의 상세 상태 확인')
|
|
165
|
-
.action(async (sprintId) => {
|
|
166
|
-
try {
|
|
167
|
-
const fs = await import('fs/promises');
|
|
168
|
-
const path = await import('path');
|
|
169
|
-
|
|
170
|
-
// 프로젝트 루트 찾기
|
|
171
|
-
let currentDir = process.cwd();
|
|
172
|
-
while (currentDir !== path.parse(currentDir).root) {
|
|
173
|
-
try {
|
|
174
|
-
await fs.access(path.join(currentDir, '.aiwf'));
|
|
175
|
-
break;
|
|
176
|
-
} catch {
|
|
177
|
-
currentDir = path.dirname(currentDir);
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
|
|
181
|
-
const sprintsDir = path.join(currentDir, '.aiwf', '03_SPRINTS');
|
|
182
|
-
const entries = await fs.readdir(sprintsDir);
|
|
183
|
-
const sprintDir = entries.find(entry => entry.startsWith(`${sprintId}_`));
|
|
184
|
-
|
|
185
|
-
if (!sprintDir) {
|
|
186
|
-
console.error(chalk.red(`❌ 스프린트 ${sprintId}를 찾을 수 없습니다.`));
|
|
187
|
-
process.exit(1);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
const sprintPath = path.join(sprintsDir, sprintDir);
|
|
191
|
-
|
|
192
|
-
console.log(chalk.bold(`📊 스프린트 ${sprintId} 상태`));
|
|
193
|
-
console.log('');
|
|
194
|
-
|
|
195
|
-
// 메타 파일 읽기
|
|
196
|
-
const metaFiles = (await fs.readdir(sprintPath)).filter(f => f.includes('meta.md'));
|
|
197
|
-
if (metaFiles.length > 0) {
|
|
198
|
-
const metaContent = await fs.readFile(path.join(sprintPath, metaFiles[0]), 'utf-8');
|
|
199
|
-
|
|
200
|
-
const statusMatch = metaContent.match(/\*\*상태\*\*:\s*(\w+)/);
|
|
201
|
-
const typeMatch = metaContent.match(/\*\*타입\*\*:\s*([^\n]+)/);
|
|
202
|
-
const createdMatch = metaContent.match(/\*\*생성일\*\*:\s*([^\n]+)/);
|
|
203
|
-
|
|
204
|
-
console.log(`상태: ${chalk.yellow(statusMatch ? statusMatch[1] : 'unknown')}`);
|
|
205
|
-
console.log(`타입: ${chalk.blue(typeMatch ? typeMatch[1].trim() : 'normal')}`);
|
|
206
|
-
console.log(`생성일: ${chalk.gray(createdMatch ? createdMatch[1].trim() : 'unknown')}`);
|
|
207
|
-
console.log('');
|
|
208
|
-
}
|
|
209
|
-
|
|
210
|
-
// 태스크 목록
|
|
211
|
-
const taskFiles = (await fs.readdir(sprintPath)).filter(f => f.match(/^T\d+_/));
|
|
212
|
-
console.log(chalk.bold(`📋 태스크 목록 (${taskFiles.length}개):`));
|
|
213
|
-
console.log('');
|
|
214
|
-
|
|
215
|
-
for (const taskFile of taskFiles.sort()) {
|
|
216
|
-
const taskContent = await fs.readFile(path.join(sprintPath, taskFile), 'utf-8');
|
|
217
|
-
const taskId = taskFile.match(/^(T\d+)_/)[1];
|
|
218
|
-
const statusMatch = taskContent.match(/\*\*상태\*\*:\s*(\w+)/);
|
|
219
|
-
const titleMatch = taskContent.match(/^#\s+T\d+:\s*(.+)$/m);
|
|
220
|
-
|
|
221
|
-
const status = statusMatch ? statusMatch[1] : 'pending';
|
|
222
|
-
const title = titleMatch ? titleMatch[1].trim() : taskFile;
|
|
223
|
-
|
|
224
|
-
const statusIcon = status === 'completed' ? '✅' :
|
|
225
|
-
status === 'in_progress' ? '🔄' : '⏳';
|
|
226
|
-
|
|
227
|
-
console.log(`${statusIcon} ${chalk.cyan(taskId)} - ${chalk.white(title)}`);
|
|
228
|
-
console.log(` 상태: ${chalk.yellow(status)}`);
|
|
229
|
-
console.log('');
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
} catch (error) {
|
|
233
|
-
console.error(chalk.red('❌ 스프린트 상태 확인 실패:'), error.message);
|
|
234
|
-
process.exit(1);
|
|
235
|
-
}
|
|
236
|
-
});
|
|
237
|
-
|
|
238
|
-
// 도움말 명령어
|
|
239
|
-
program
|
|
240
|
-
.command('help')
|
|
241
|
-
.description('AIWF 스프린트 명령어 도움말')
|
|
242
|
-
.action(() => {
|
|
243
|
-
console.log(chalk.bold('🚀 AIWF 스프린트 CLI 도움말'));
|
|
244
|
-
console.log('');
|
|
245
|
-
console.log(chalk.yellow('📋 주요 명령어:'));
|
|
246
|
-
console.log('');
|
|
247
|
-
console.log(` ${chalk.cyan('aiwf-sprint independent [name]')} - 독립 스프린트 생성`);
|
|
248
|
-
console.log(` ${chalk.cyan('aiwf-sprint list')} - 스프린트 목록 보기`);
|
|
249
|
-
console.log(` ${chalk.cyan('aiwf-sprint status <id>')} - 스프린트 상태 확인`);
|
|
250
|
-
console.log('');
|
|
251
|
-
console.log(chalk.yellow('🔧 독립 스프린트 옵션:'));
|
|
252
|
-
console.log('');
|
|
253
|
-
console.log(` ${chalk.blue('--from-readme')} - README TODO에서 자동 추출`);
|
|
254
|
-
console.log(` ${chalk.blue('--from-issue <번호>')} - GitHub 이슈에서 생성`);
|
|
255
|
-
console.log(` ${chalk.blue('--minimal')} - 최소 엔지니어링 레벨 (기본값)`);
|
|
256
|
-
console.log(` ${chalk.blue('--balanced')} - 균형 엔지니어링 레벨`);
|
|
257
|
-
console.log(` ${chalk.blue('--complete')} - 완전 엔지니어링 레벨`);
|
|
258
|
-
console.log('');
|
|
259
|
-
console.log(chalk.yellow('💡 사용 예시:'));
|
|
260
|
-
console.log('');
|
|
261
|
-
console.log(` ${chalk.gray('# README TODO로 독립 스프린트 생성')}`);
|
|
262
|
-
console.log(` ${chalk.blue('aiwf-sprint independent --from-readme')}`);
|
|
263
|
-
console.log('');
|
|
264
|
-
console.log(` ${chalk.gray('# GitHub 이슈로 스프린트 생성')}`);
|
|
265
|
-
console.log(` ${chalk.blue('aiwf-sprint independent --from-issue 123')}`);
|
|
266
|
-
console.log('');
|
|
267
|
-
console.log(` ${chalk.gray('# 균형 레벨로 커스텀 스프린트 생성')}`);
|
|
268
|
-
console.log(` ${chalk.blue('aiwf-sprint independent "API 개발" --balanced')}`);
|
|
269
|
-
console.log('');
|
|
270
|
-
console.log(chalk.green('✨ 생성 후 Claude Code에서 `/project:aiwf:yolo [스프린트ID]`로 실행하세요!'));
|
|
271
|
-
});
|
|
272
|
-
|
|
273
|
-
// 에러 핸들링
|
|
274
|
-
program.on('command:*', () => {
|
|
275
|
-
console.error(chalk.red('❌ 알 수 없는 명령어입니다.'));
|
|
276
|
-
console.log('');
|
|
277
|
-
console.log(chalk.blue('도움말을 보려면: aiwf-sprint help'));
|
|
278
|
-
process.exit(1);
|
|
279
|
-
});
|
|
280
|
-
|
|
281
|
-
// CLI 실행
|
|
282
|
-
program.parse(process.argv);
|
|
283
|
-
|
|
284
|
-
// 인수가 없으면 도움말 표시
|
|
285
|
-
if (!process.argv.slice(2).length) {
|
|
286
|
-
program.outputHelp();
|
|
287
|
-
}
|