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.
Files changed (140) hide show
  1. package/package.json +3 -2
  2. package/src/cli/index.js +39 -336
  3. package/src/lib/installer.js +310 -90
  4. package/src/utils/messages.js +24 -0
  5. package/src/DEPENDENCY_MAP.md +0 -90
  6. package/src/cli/cache-cli.js +0 -459
  7. package/src/cli/checkpoint-cli.js +0 -417
  8. package/src/cli/language-cli.js +0 -286
  9. package/src/cli/sprint-cli.js +0 -287
  10. package/src/commands/ai-tool.js +0 -383
  11. package/src/commands/compress.js +0 -60
  12. package/src/commands/create-project.js +0 -160
  13. package/src/commands/evaluate.js +0 -459
  14. package/src/commands/persona.js +0 -309
  15. package/src/commands/sprint-task.js +0 -262
  16. package/src/commands/token.js +0 -312
  17. package/src/lib/ai-persona-manager.js +0 -711
  18. package/src/lib/cache-system.js +0 -332
  19. package/src/lib/context-engine.js +0 -568
  20. package/src/lib/github-integration.js +0 -402
  21. package/src/lib/memory-profiler.js +0 -471
  22. package/src/lib/metrics-collector.js +0 -885
  23. package/src/lib/offline-detector.js +0 -386
  24. package/src/lib/resource-loader-enhanced.js +0 -399
  25. package/src/lib/resource-loader.js +0 -250
  26. package/src/lib/resources/commands/ai-persona.js +0 -602
  27. package/src/lib/resources/commands/compress-context.js +0 -389
  28. package/src/lib/resources/commands/evaluate.js +0 -246
  29. package/src/lib/resources/commands/persona-context-apply.js +0 -562
  30. package/src/lib/resources/commands/token-tracking.js +0 -443
  31. package/src/lib/resources/config/commit-patterns.js +0 -103
  32. package/src/lib/resources/config/language.json +0 -6
  33. package/src/lib/resources/personas/PERSONA_INDEX.md +0 -57
  34. package/src/lib/resources/personas/analyst.json +0 -44
  35. package/src/lib/resources/personas/architect/best_practices.md +0 -136
  36. package/src/lib/resources/personas/architect/knowledge_base.md +0 -377
  37. package/src/lib/resources/personas/architect.json +0 -44
  38. package/src/lib/resources/personas/backend/best_practices.md +0 -766
  39. package/src/lib/resources/personas/backend/knowledge_base.md +0 -1070
  40. package/src/lib/resources/personas/data_analyst/best_practices.md +0 -594
  41. package/src/lib/resources/personas/data_analyst/knowledge_base.md +0 -1057
  42. package/src/lib/resources/personas/developer.json +0 -44
  43. package/src/lib/resources/personas/developer.md +0 -37
  44. package/src/lib/resources/personas/evaluation_criteria.json +0 -137
  45. package/src/lib/resources/personas/frontend/best_practices.md +0 -445
  46. package/src/lib/resources/personas/frontend/knowledge_base.md +0 -729
  47. package/src/lib/resources/personas/persona-index.json +0 -31
  48. package/src/lib/resources/personas/reviewer.json +0 -44
  49. package/src/lib/resources/personas/security/best_practices.md +0 -307
  50. package/src/lib/resources/personas/security/knowledge_base.md +0 -498
  51. package/src/lib/resources/personas/tester.json +0 -44
  52. package/src/lib/resources/templates/README.md +0 -78
  53. package/src/lib/resources/templates/api-server/config.json +0 -64
  54. package/src/lib/resources/templates/api-server/template/.aiwf/config.json +0 -56
  55. package/src/lib/resources/templates/api-server/template/.aiwf/feature-ledger.json +0 -42
  56. package/src/lib/resources/templates/api-server/template/.aiwf/personas/backend-engineer.json +0 -40
  57. package/src/lib/resources/templates/api-server/template/.aiwf/scripts/cli.js +0 -111
  58. package/src/lib/resources/templates/api-server/template/.env.example +0 -29
  59. package/src/lib/resources/templates/api-server/template/.eslintrc.json +0 -23
  60. package/src/lib/resources/templates/api-server/template/README.md +0 -171
  61. package/src/lib/resources/templates/api-server/template/jest.config.js +0 -26
  62. package/src/lib/resources/templates/api-server/template/nodemon.json +0 -9
  63. package/src/lib/resources/templates/api-server/template/package.json +0 -61
  64. package/src/lib/resources/templates/api-server/template/src/app.ts +0 -60
  65. package/src/lib/resources/templates/api-server/template/src/config/swagger.ts +0 -38
  66. package/src/lib/resources/templates/api-server/template/src/controllers/aiwfController.ts +0 -54
  67. package/src/lib/resources/templates/api-server/template/src/controllers/authController.ts +0 -128
  68. package/src/lib/resources/templates/api-server/template/src/controllers/statusController.ts +0 -28
  69. package/src/lib/resources/templates/api-server/template/src/index.ts +0 -28
  70. package/src/lib/resources/templates/api-server/template/src/middleware/aiwfMiddleware.ts +0 -50
  71. package/src/lib/resources/templates/api-server/template/src/middleware/authMiddleware.ts +0 -41
  72. package/src/lib/resources/templates/api-server/template/src/middleware/errorHandler.ts +0 -42
  73. package/src/lib/resources/templates/api-server/template/src/middleware/notFoundHandler.ts +0 -14
  74. package/src/lib/resources/templates/api-server/template/src/middleware/requestLogger.ts +0 -20
  75. package/src/lib/resources/templates/api-server/template/src/routes/aiwf.ts +0 -31
  76. package/src/lib/resources/templates/api-server/template/src/routes/index.ts +0 -13
  77. package/src/lib/resources/templates/api-server/template/src/routes/v1/index.ts +0 -67
  78. package/src/lib/resources/templates/api-server/template/src/utils/logger.ts +0 -37
  79. package/src/lib/resources/templates/api-server/template/tests/app.test.ts +0 -40
  80. package/src/lib/resources/templates/api-server/template/tsconfig.json +0 -43
  81. package/src/lib/resources/templates/npm-library/config.json +0 -61
  82. package/src/lib/resources/templates/npm-library/template/LICENSE +0 -21
  83. package/src/lib/resources/templates/npm-library/template/README.md +0 -201
  84. package/src/lib/resources/templates/npm-library/template/package.json +0 -78
  85. package/src/lib/resources/templates/web-app/config.json +0 -53
  86. package/src/lib/resources/templates/web-app/template/.aiwf/config.json +0 -54
  87. package/src/lib/resources/templates/web-app/template/.aiwf/feature-ledger.json +0 -37
  88. package/src/lib/resources/templates/web-app/template/.aiwf/personas/fullstack-developer.json +0 -40
  89. package/src/lib/resources/templates/web-app/template/.aiwf/scripts/cli.js +0 -110
  90. package/src/lib/resources/templates/web-app/template/.eslintrc.cjs +0 -20
  91. package/src/lib/resources/templates/web-app/template/README.md +0 -151
  92. package/src/lib/resources/templates/web-app/template/index.html +0 -14
  93. package/src/lib/resources/templates/web-app/template/package.json +0 -44
  94. package/src/lib/resources/templates/web-app/template/postcss.config.js +0 -6
  95. package/src/lib/resources/templates/web-app/template/public/vite.svg +0 -1
  96. package/src/lib/resources/templates/web-app/template/src/App.tsx +0 -21
  97. package/src/lib/resources/templates/web-app/template/src/components/Layout.tsx +0 -57
  98. package/src/lib/resources/templates/web-app/template/src/components/aiwf/ContextStatus.tsx +0 -107
  99. package/src/lib/resources/templates/web-app/template/src/components/aiwf/TokenUsage.tsx +0 -71
  100. package/src/lib/resources/templates/web-app/template/src/index.css +0 -60
  101. package/src/lib/resources/templates/web-app/template/src/main.tsx +0 -10
  102. package/src/lib/resources/templates/web-app/template/src/pages/AiwfDashboard.tsx +0 -57
  103. package/src/lib/resources/templates/web-app/template/src/pages/HomePage.tsx +0 -89
  104. package/src/lib/resources/templates/web-app/template/src/pages/NotFound.tsx +0 -25
  105. package/src/lib/resources/templates/web-app/template/src/stores/aiwfStore.ts +0 -126
  106. package/src/lib/resources/templates/web-app/template/src/types/global.d.ts +0 -9
  107. package/src/lib/resources/templates/web-app/template/src/vite-env.d.ts +0 -1
  108. package/src/lib/resources/templates/web-app/template/tailwind.config.js +0 -30
  109. package/src/lib/resources/templates/web-app/template/tsconfig.json +0 -37
  110. package/src/lib/resources/templates/web-app/template/tsconfig.node.json +0 -10
  111. package/src/lib/resources/templates/web-app/template/vite.config.ts +0 -23
  112. package/src/lib/resources/utils/background-monitor.js +0 -223
  113. package/src/lib/resources/utils/compression-metrics.js +0 -1031
  114. package/src/lib/resources/utils/compression-strategies.js +0 -557
  115. package/src/lib/resources/utils/content-normalizer.js +0 -455
  116. package/src/lib/resources/utils/context-compressor.js +0 -583
  117. package/src/lib/resources/utils/context-rule-parser.js +0 -180
  118. package/src/lib/resources/utils/context-token-monitor.js +0 -463
  119. package/src/lib/resources/utils/context-update-manager.js +0 -502
  120. package/src/lib/resources/utils/git-utils.js +0 -220
  121. package/src/lib/resources/utils/importance-classifier.js +0 -645
  122. package/src/lib/resources/utils/information-filter.js +0 -710
  123. package/src/lib/resources/utils/persona-aware-compressor.js +0 -598
  124. package/src/lib/resources/utils/prompt-injector.js +0 -242
  125. package/src/lib/resources/utils/simplified-evaluator.js +0 -119
  126. package/src/lib/resources/utils/text-summarizer.js +0 -492
  127. package/src/lib/resources/utils/token-counter.js +0 -177
  128. package/src/lib/resources/utils/token-monitor.js +0 -484
  129. package/src/lib/resources/utils/token-reporter.js +0 -452
  130. package/src/lib/resources/utils/token-storage.js +0 -433
  131. package/src/lib/resources/utils/token-tracker.js +0 -283
  132. package/src/lib/state/priority-calculator.js +0 -217
  133. package/src/lib/state/state-index.js +0 -155
  134. package/src/lib/state/task-scanner.js +0 -328
  135. package/src/lib/task-analyzer.js +0 -599
  136. package/src/lib/template-cache-system.js +0 -559
  137. package/src/lib/template-downloader.js +0 -467
  138. package/src/lib/template-version-manager.js +0 -491
  139. package/src/lib/token-optimizer.js +0 -517
  140. package/src/utils/engineering-guard.js +0 -399
@@ -1,459 +0,0 @@
1
- #!/usr/bin/env node
2
-
3
- import { Command } from 'commander';
4
- import chalk from 'chalk';
5
- import ora from 'ora';
6
- import prompts from 'prompts';
7
- import { TemplateCache } from '../lib/template-cache-system.js';
8
- import { OfflineDetector } from '../lib/offline-detector.js';
9
- import { TemplateDownloader } from '../lib/template-downloader.js';
10
- import { TemplateVersionManager } from '../lib/template-version-manager.js';
11
-
12
- /**
13
- * 캐시 관리 CLI 명령어
14
- * - aiwf cache download: 선택적 템플릿 다운로드
15
- * - aiwf cache list: 캐시 목록 조회
16
- * - aiwf cache clean: 캐시 정리
17
- * - aiwf cache update: 업데이트 확인
18
- * - aiwf cache status: 캐시 상태 확인
19
- */
20
- class CacheCLI {
21
- constructor() {
22
- this.cache = new TemplateCache();
23
- this.offlineDetector = new OfflineDetector();
24
- this.downloader = new TemplateDownloader();
25
- this.versionManager = new TemplateVersionManager();
26
-
27
- // 의존성 주입
28
- this.offlineDetector.setCache(this.cache);
29
- this.downloader.setCache(this.cache);
30
- this.downloader.setOfflineDetector(this.offlineDetector);
31
- this.versionManager.setCache(this.cache);
32
- this.versionManager.setDownloader(this.downloader);
33
- this.versionManager.setOfflineDetector(this.offlineDetector);
34
- }
35
-
36
- /**
37
- * CLI 초기화
38
- */
39
- async init() {
40
- await this.cache.init();
41
- await this.offlineDetector.start();
42
- await this.versionManager.init();
43
- }
44
-
45
- /**
46
- * 템플릿 다운로드 명령어
47
- */
48
- async downloadCommand(options = {}) {
49
- const spinner = ora('Scanning available templates...').start();
50
-
51
- try {
52
- const templates = await this.downloader.scanAvailableTemplates();
53
- spinner.stop();
54
-
55
- if (options.all) {
56
- return await this.downloadAllTemplates();
57
- }
58
-
59
- if (options.type) {
60
- return await this.downloadTemplatesByType(options.type);
61
- }
62
-
63
- // 대화형 선택
64
- return await this.interactiveDownload(templates);
65
-
66
- } catch (error) {
67
- spinner.fail(chalk.red(`Failed to scan templates: ${error.message}`));
68
- process.exit(1);
69
- }
70
- }
71
-
72
- /**
73
- * 모든 템플릿 다운로드
74
- */
75
- async downloadAllTemplates() {
76
- const spinner = ora('Downloading all templates...').start();
77
-
78
- try {
79
- const result = await this.downloader.downloadAllTemplates();
80
- spinner.stop();
81
-
82
- this.displayDownloadResults(result);
83
- return result;
84
-
85
- } catch (error) {
86
- spinner.fail(chalk.red(`Download failed: ${error.message}`));
87
- process.exit(1);
88
- }
89
- }
90
-
91
- /**
92
- * 타입별 템플릿 다운로드
93
- */
94
- async downloadTemplatesByType(type) {
95
- const spinner = ora(`Downloading ${type} templates...`).start();
96
-
97
- try {
98
- const result = await this.downloader.downloadTemplatesByType(type);
99
- spinner.stop();
100
-
101
- this.displayDownloadResults(result);
102
- return result;
103
-
104
- } catch (error) {
105
- spinner.fail(chalk.red(`Download failed: ${error.message}`));
106
- process.exit(1);
107
- }
108
- }
109
-
110
- /**
111
- * 대화형 다운로드
112
- */
113
- async interactiveDownload(templates) {
114
- const choices = [];
115
-
116
- // AI 도구 선택지
117
- if (Object.keys(templates['ai-tools']).length > 0) {
118
- choices.push({
119
- title: chalk.cyan('AI Tools'),
120
- value: 'ai-tools-all',
121
- description: 'All AI development tools'
122
- });
123
-
124
- for (const [name, info] of Object.entries(templates['ai-tools'])) {
125
- choices.push({
126
- title: ` ${name}`,
127
- value: `ai-tools:${name}`,
128
- description: info.description || 'AI development tool'
129
- });
130
- }
131
- }
132
-
133
- // 프로젝트 템플릿 선택지
134
- if (Object.keys(templates['projects']).length > 0) {
135
- choices.push({
136
- title: chalk.green('Project Templates'),
137
- value: 'projects-all',
138
- description: 'All project templates'
139
- });
140
-
141
- for (const [name, info] of Object.entries(templates['projects'])) {
142
- choices.push({
143
- title: ` ${name}`,
144
- value: `projects:${name}`,
145
- description: info.description || 'Project template'
146
- });
147
- }
148
- }
149
-
150
- const response = await prompts({
151
- type: 'multiselect',
152
- name: 'templates',
153
- message: 'Select templates to download:',
154
- choices,
155
- hint: 'Space to select, Enter to confirm'
156
- });
157
-
158
- if (!response.templates || response.templates.length === 0) {
159
- console.log(chalk.yellow('No templates selected.'));
160
- return;
161
- }
162
-
163
- const selections = this.parseSelections(response.templates, templates);
164
-
165
- const spinner = ora('Downloading selected templates...').start();
166
-
167
- // 다운로드 진행률 표시
168
- let currentTemplate = '';
169
- this.downloader.on('templateStart', ({ type, name }) => {
170
- currentTemplate = `${type}/${name}`;
171
- spinner.text = `Downloading ${currentTemplate}...`;
172
- });
173
-
174
- this.downloader.on('progress', ({ completed, total, percentage }) => {
175
- spinner.text = `Downloaded ${completed}/${total} templates (${percentage.toFixed(1)}%)`;
176
- });
177
-
178
- try {
179
- const result = await this.downloader.downloadSelectedTemplates(selections);
180
- spinner.stop();
181
-
182
- this.displayDownloadResults(result);
183
- return result;
184
-
185
- } catch (error) {
186
- spinner.fail(chalk.red(`Download failed: ${error.message}`));
187
- process.exit(1);
188
- }
189
- }
190
-
191
- /**
192
- * 선택사항 파싱
193
- */
194
- parseSelections(selections, templates) {
195
- const parsed = [];
196
-
197
- for (const selection of selections) {
198
- if (selection === 'ai-tools-all') {
199
- for (const [name, info] of Object.entries(templates['ai-tools'])) {
200
- parsed.push({
201
- type: 'ai-tools',
202
- name,
203
- version: info.version
204
- });
205
- }
206
- } else if (selection === 'projects-all') {
207
- for (const [name, info] of Object.entries(templates['projects'])) {
208
- parsed.push({
209
- type: 'projects',
210
- name,
211
- version: info.version
212
- });
213
- }
214
- } else if (selection.includes(':')) {
215
- const [type, name] = selection.split(':');
216
- const info = templates[type][name];
217
- parsed.push({
218
- type,
219
- name,
220
- version: info.version
221
- });
222
- }
223
- }
224
-
225
- return parsed;
226
- }
227
-
228
- /**
229
- * 다운로드 결과 표시
230
- */
231
- displayDownloadResults(result) {
232
- console.log('\\n' + chalk.bold('Download Results:'));
233
- console.log(chalk.green(`✅ Completed: ${result.completed}/${result.total}`));
234
-
235
- if (result.failed > 0) {
236
- console.log(chalk.red(`❌ Failed: ${result.failed}`));
237
- }
238
-
239
- // 성공한 다운로드 표시
240
- const successful = result.results.filter(r => r.success);
241
- if (successful.length > 0) {
242
- console.log('\\n' + chalk.green('Successfully downloaded:'));
243
- for (const item of successful) {
244
- console.log(` ${chalk.cyan(item.type)}/${chalk.white(item.name)} ${chalk.gray(`v${item.version}`)}`);
245
- }
246
- }
247
-
248
- // 실패한 다운로드 표시
249
- const failed = result.results.filter(r => !r.success);
250
- if (failed.length > 0) {
251
- console.log('\\n' + chalk.red('Failed downloads:'));
252
- for (const item of failed) {
253
- console.log(` ${chalk.cyan(item.type)}/${chalk.white(item.name)} ${chalk.gray(`v${item.version}`)} - ${chalk.red(item.error)}`);
254
- }
255
- }
256
- }
257
-
258
- /**
259
- * 캐시 목록 조회
260
- */
261
- async listCommand(options = {}) {
262
- try {
263
- const templates = await this.cache.listTemplates(options.type);
264
- const stats = this.cache.getStats();
265
-
266
- console.log(chalk.bold('Template Cache Status:'));
267
- console.log(`📦 Total templates: ${chalk.cyan(stats.templatesCount)}`);
268
- console.log(`💾 Total size: ${chalk.cyan(this.formatBytes(stats.totalSize))}`);
269
- console.log(`📈 Cache usage: ${chalk.cyan(stats.usagePercentage)}`);
270
- console.log(`🎯 Hit rate: ${chalk.cyan(stats.hitRate)}`);
271
-
272
- if (stats.lastUpdate) {
273
- console.log(`🕒 Last update: ${chalk.gray(new Date(stats.lastUpdate).toLocaleString())}`);
274
- }
275
-
276
- // AI 도구 목록
277
- if (templates['ai-tools'] && Object.keys(templates['ai-tools']).length > 0) {
278
- console.log('\\n' + chalk.cyan.bold('AI Tools:'));
279
- for (const [name, info] of Object.entries(templates['ai-tools'])) {
280
- console.log(` ${chalk.white(name)} ${chalk.gray(`v${info.version}`)} ${chalk.dim(`(${this.formatBytes(info.size)})`)}`);
281
- console.log(` ${chalk.gray(`Cached: ${new Date(info.cached_at).toLocaleString()}`)}`);
282
- }
283
- }
284
-
285
- // 프로젝트 템플릿 목록
286
- if (templates['projects'] && Object.keys(templates['projects']).length > 0) {
287
- console.log('\\n' + chalk.green.bold('Project Templates:'));
288
- for (const [name, info] of Object.entries(templates['projects'])) {
289
- console.log(` ${chalk.white(name)} ${chalk.gray(`v${info.version}`)} ${chalk.dim(`(${this.formatBytes(info.size)})`)}`);
290
- console.log(` ${chalk.gray(`Cached: ${new Date(info.cached_at).toLocaleString()}`)}`);
291
- }
292
- }
293
-
294
- if (stats.templatesCount === 0) {
295
- console.log('\\n' + chalk.yellow('No templates cached. Use `aiwf cache download` to cache templates.'));
296
- }
297
-
298
- } catch (error) {
299
- console.error(chalk.red(`Failed to list cache: ${error.message}`));
300
- process.exit(1);
301
- }
302
- }
303
-
304
- /**
305
- * 캐시 정리
306
- */
307
- async cleanCommand(options = {}) {
308
- try {
309
- if (options.all) {
310
- const response = await prompts({
311
- type: 'confirm',
312
- name: 'confirm',
313
- message: 'Are you sure you want to clear all cached templates?',
314
- initial: false
315
- });
316
-
317
- if (!response.confirm) {
318
- console.log(chalk.yellow('Cache clear cancelled.'));
319
- return;
320
- }
321
-
322
- const spinner = ora('Clearing cache...').start();
323
- await this.cache.clear();
324
- spinner.succeed(chalk.green('Cache cleared successfully.'));
325
-
326
- } else {
327
- const spinner = ora('Cleaning up expired cache...').start();
328
- const result = await this.cache.cleanup({
329
- maxAge: options.maxAge || 7 * 24 * 60 * 60 * 1000 // 7일
330
- });
331
-
332
- spinner.succeed(
333
- chalk.green(`Cleaned up ${result.removedCount} expired templates. `) +
334
- chalk.gray(`Freed ${this.formatBytes(result.freedSpace)}.`)
335
- );
336
- }
337
-
338
- } catch (error) {
339
- console.error(chalk.red(`Failed to clean cache: ${error.message}`));
340
- process.exit(1);
341
- }
342
- }
343
-
344
- /**
345
- * 업데이트 확인
346
- */
347
- async updateCommand(options = {}) {
348
- const spinner = ora('Checking for updates...').start();
349
-
350
- try {
351
- const updateInfo = await this.versionManager.checkForUpdates();
352
- const availableUpdates = updateInfo.updates.filter(u => u.needsUpdate);
353
-
354
- spinner.stop();
355
-
356
- if (availableUpdates.length === 0) {
357
- console.log(chalk.green('✅ All templates are up to date.'));
358
- return;
359
- }
360
-
361
- console.log(chalk.yellow(`📦 ${availableUpdates.length} updates available:`));
362
-
363
- for (const update of availableUpdates) {
364
- console.log(` ${chalk.cyan(update.type)}/${chalk.white(update.name)}: ` +
365
- `${chalk.gray(update.currentVersion || 'not cached')} → ${chalk.green(update.availableVersion)}`);
366
- }
367
-
368
- if (options.install) {
369
- const response = await prompts({
370
- type: 'confirm',
371
- name: 'confirm',
372
- message: 'Install all available updates?',
373
- initial: true
374
- });
375
-
376
- if (response.confirm) {
377
- const updateSpinner = ora('Installing updates...').start();
378
- const results = await this.versionManager.updateAllTemplates();
379
- updateSpinner.stop();
380
-
381
- const successCount = results.filter(r => r.success).length;
382
- const failCount = results.filter(r => !r.success).length;
383
-
384
- console.log(chalk.green(`✅ ${successCount} templates updated successfully`));
385
- if (failCount > 0) {
386
- console.log(chalk.red(`❌ ${failCount} templates failed to update`));
387
- }
388
- }
389
- }
390
-
391
- } catch (error) {
392
- spinner.fail(chalk.red(`Failed to check updates: ${error.message}`));
393
- process.exit(1);
394
- }
395
- }
396
-
397
- /**
398
- * 캐시 상태 확인
399
- */
400
- async statusCommand() {
401
- try {
402
- const cacheStats = this.cache.getStats();
403
- const networkInfo = this.offlineDetector.getNetworkStats();
404
- const versionStats = this.versionManager.getStats();
405
-
406
- console.log(chalk.bold('AIWF Cache System Status\\n'));
407
-
408
- // 네트워크 상태
409
- console.log(chalk.bold('Network Status:'));
410
- const statusColor = networkInfo.status === 'online' ? chalk.green : chalk.red;
411
- console.log(` Status: ${statusColor(networkInfo.status.toUpperCase())}`);
412
- console.log(` Uptime: ${chalk.cyan(networkInfo.uptime)}`);
413
- console.log(` Downtime: ${chalk.cyan(networkInfo.downtime)}`);
414
- console.log(` Offline mode: ${networkInfo.offlineMode ? chalk.yellow('enabled') : chalk.green('disabled')}`);
415
-
416
- // 캐시 통계
417
- console.log('\\n' + chalk.bold('Cache Statistics:'));
418
- console.log(` Templates: ${chalk.cyan(cacheStats.templatesCount)}`);
419
- console.log(` Total size: ${chalk.cyan(this.formatBytes(cacheStats.totalSize))}`);
420
- console.log(` Usage: ${chalk.cyan(cacheStats.usagePercentage)} of ${this.formatBytes(cacheStats.maxCacheSize)}`);
421
- console.log(` Hit rate: ${chalk.cyan(cacheStats.hitRate)}`);
422
-
423
- // 버전 관리
424
- console.log('\\n' + chalk.bold('Version Management:'));
425
- console.log(` Total templates: ${chalk.cyan(versionStats.totalTemplates)}`);
426
- console.log(` Total versions: ${chalk.cyan(versionStats.totalVersions)}`);
427
- console.log(` Cached versions: ${chalk.cyan(versionStats.cachedVersions)}`);
428
- if (versionStats.lastCheck) {
429
- console.log(` Last check: ${chalk.gray(new Date(versionStats.lastCheck).toLocaleString())}`);
430
- }
431
-
432
- } catch (error) {
433
- console.error(chalk.red(`Failed to get status: ${error.message}`));
434
- process.exit(1);
435
- }
436
- }
437
-
438
- /**
439
- * 바이트 포맷팅
440
- */
441
- formatBytes(bytes) {
442
- if (bytes === 0) return '0 Bytes';
443
-
444
- const k = 1024;
445
- const sizes = ['Bytes', 'KB', 'MB', 'GB'];
446
- const i = Math.floor(Math.log(bytes) / Math.log(k));
447
-
448
- return parseFloat((bytes / Math.pow(k, i)).toFixed(2)) + ' ' + sizes[i];
449
- }
450
-
451
- /**
452
- * CLI 종료
453
- */
454
- async cleanup() {
455
- this.offlineDetector.stop();
456
- }
457
- }
458
-
459
- export { CacheCLI };