@nclamvn/vibecode-cli 1.5.0 → 1.7.0

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 (77) hide show
  1. package/.vibecode/learning/fixes.json +1 -0
  2. package/.vibecode/learning/preferences.json +1 -0
  3. package/bin/vibecode.js +86 -3
  4. package/docs-site/README.md +41 -0
  5. package/docs-site/blog/2019-05-28-first-blog-post.md +12 -0
  6. package/docs-site/blog/2019-05-29-long-blog-post.md +44 -0
  7. package/docs-site/blog/2021-08-01-mdx-blog-post.mdx +24 -0
  8. package/docs-site/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
  9. package/docs-site/blog/2021-08-26-welcome/index.md +29 -0
  10. package/docs-site/blog/authors.yml +25 -0
  11. package/docs-site/blog/tags.yml +19 -0
  12. package/docs-site/docs/commands/agent.md +162 -0
  13. package/docs-site/docs/commands/assist.md +71 -0
  14. package/docs-site/docs/commands/build.md +53 -0
  15. package/docs-site/docs/commands/config.md +30 -0
  16. package/docs-site/docs/commands/debug.md +173 -0
  17. package/docs-site/docs/commands/doctor.md +34 -0
  18. package/docs-site/docs/commands/go.md +128 -0
  19. package/docs-site/docs/commands/index.md +79 -0
  20. package/docs-site/docs/commands/init.md +42 -0
  21. package/docs-site/docs/commands/learn.md +82 -0
  22. package/docs-site/docs/commands/lock.md +33 -0
  23. package/docs-site/docs/commands/plan.md +29 -0
  24. package/docs-site/docs/commands/review.md +31 -0
  25. package/docs-site/docs/commands/snapshot.md +34 -0
  26. package/docs-site/docs/commands/start.md +32 -0
  27. package/docs-site/docs/commands/status.md +37 -0
  28. package/docs-site/docs/commands/undo.md +83 -0
  29. package/docs-site/docs/configuration.md +72 -0
  30. package/docs-site/docs/faq.md +83 -0
  31. package/docs-site/docs/getting-started.md +119 -0
  32. package/docs-site/docs/guides/agent-mode.md +94 -0
  33. package/docs-site/docs/guides/debug-mode.md +83 -0
  34. package/docs-site/docs/guides/magic-mode.md +107 -0
  35. package/docs-site/docs/installation.md +98 -0
  36. package/docs-site/docs/intro.md +67 -0
  37. package/docs-site/docusaurus.config.ts +141 -0
  38. package/docs-site/package-lock.json +18039 -0
  39. package/docs-site/package.json +48 -0
  40. package/docs-site/sidebars.ts +70 -0
  41. package/docs-site/src/components/HomepageFeatures/index.tsx +72 -0
  42. package/docs-site/src/components/HomepageFeatures/styles.module.css +16 -0
  43. package/docs-site/src/css/custom.css +30 -0
  44. package/docs-site/src/pages/index.module.css +23 -0
  45. package/docs-site/src/pages/index.tsx +44 -0
  46. package/docs-site/src/pages/markdown-page.md +7 -0
  47. package/docs-site/src/theme/Footer/index.tsx +127 -0
  48. package/docs-site/src/theme/Footer/styles.module.css +285 -0
  49. package/docs-site/static/.nojekyll +0 -0
  50. package/docs-site/static/img/docusaurus-social-card.jpg +0 -0
  51. package/docs-site/static/img/docusaurus.png +0 -0
  52. package/docs-site/static/img/favicon.ico +0 -0
  53. package/docs-site/static/img/logo.svg +1 -0
  54. package/docs-site/static/img/undraw_docusaurus_mountain.svg +171 -0
  55. package/docs-site/static/img/undraw_docusaurus_react.svg +170 -0
  56. package/docs-site/static/img/undraw_docusaurus_tree.svg +40 -0
  57. package/docs-site/tsconfig.json +8 -0
  58. package/package.json +5 -2
  59. package/src/agent/orchestrator.js +104 -35
  60. package/src/commands/build.js +13 -3
  61. package/src/commands/debug.js +109 -1
  62. package/src/commands/git.js +923 -0
  63. package/src/commands/go.js +9 -2
  64. package/src/commands/learn.js +294 -0
  65. package/src/commands/shell.js +486 -0
  66. package/src/commands/undo.js +281 -0
  67. package/src/commands/watch.js +556 -0
  68. package/src/commands/wizard.js +322 -0
  69. package/src/core/backup.js +325 -0
  70. package/src/core/learning.js +295 -0
  71. package/src/debug/image-analyzer.js +304 -0
  72. package/src/debug/index.js +30 -1
  73. package/src/index.js +50 -0
  74. package/src/ui/__tests__/error-translator.test.js +390 -0
  75. package/src/ui/dashboard.js +364 -0
  76. package/src/ui/error-translator.js +775 -0
  77. package/src/utils/image.js +222 -0
@@ -31,6 +31,8 @@ import {
31
31
  getCoderPackTemplate
32
32
  } from '../config/templates.js';
33
33
  import { printBox, printError, printSuccess } from '../ui/output.js';
34
+ import { StepProgress, updateProgress, completeProgress } from '../ui/dashboard.js';
35
+ import { BackupManager } from '../core/backup.js';
34
36
  import {
35
37
  spawnClaudeCode,
36
38
  isClaudeCodeAvailable,
@@ -78,6 +80,11 @@ export async function goCommand(description, options = {}) {
78
80
  // Show magic header
79
81
  showMagicHeader(description, projectName);
80
82
 
83
+ // Create backup of current directory before go command
84
+ // (backup in parent directory since we're creating a new project)
85
+ const backup = new BackupManager(process.cwd());
86
+ await backup.createBackup('go-magic');
87
+
81
88
  // Define steps
82
89
  const steps = [
83
90
  { name: 'INIT', label: 'Creating project', weight: 5 },
@@ -304,12 +311,12 @@ function generateProjectName(description) {
304
311
  /**
305
312
  * Render progress bar
306
313
  */
307
- function renderProgressBar(percent) {
314
+ function renderProgressBar(percent, label = '') {
308
315
  const width = 40;
309
316
  const filled = Math.round(width * percent / 100);
310
317
  const empty = width - filled;
311
318
  const bar = chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
312
- return `[${bar}] ${String(percent).padStart(3)}%`;
319
+ return `[${bar}] ${String(percent).padStart(3)}%${label ? ' ' + label : ''}`;
313
320
  }
314
321
 
315
322
  /**
@@ -0,0 +1,294 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════════
2
+ // VIBECODE CLI - Learn Command
3
+ // Phase H5: View and manage AI learnings
4
+ // ═══════════════════════════════════════════════════════════════════════════════
5
+
6
+ import chalk from 'chalk';
7
+ import inquirer from 'inquirer';
8
+ import fs from 'fs/promises';
9
+ import path from 'path';
10
+ import { LearningEngine } from '../core/learning.js';
11
+
12
+ /**
13
+ * Learn Command - View and manage AI learnings
14
+ *
15
+ * Usage:
16
+ * vibecode learn - Interactive menu
17
+ * vibecode learn --stats - Show learning statistics
18
+ * vibecode learn --clear - Clear all learnings
19
+ * vibecode learn --export - Export learnings to file
20
+ */
21
+ export async function learnCommand(options = {}) {
22
+ const learning = new LearningEngine();
23
+
24
+ if (options.stats) {
25
+ await showStats(learning);
26
+ return;
27
+ }
28
+
29
+ if (options.clear) {
30
+ await clearLearnings(learning, options.force);
31
+ return;
32
+ }
33
+
34
+ if (options.export) {
35
+ await exportLearnings(learning);
36
+ return;
37
+ }
38
+
39
+ // Default: show interactive menu
40
+ await interactiveLearn(learning);
41
+ }
42
+
43
+ /**
44
+ * Show learning statistics
45
+ */
46
+ async function showStats(learning) {
47
+ const stats = await learning.getStats();
48
+
49
+ console.log(chalk.cyan(`
50
+ ╭────────────────────────────────────────────────────────────────────╮
51
+ │ 📊 LEARNING STATISTICS │
52
+ ╰────────────────────────────────────────────────────────────────────╯
53
+ `));
54
+
55
+ console.log(chalk.white(` 📁 Project Learnings`));
56
+ console.log(chalk.gray(` Tổng fixes: ${stats.local.total}`));
57
+ console.log(chalk.gray(` Thành công: ${stats.local.success} (${stats.local.rate}%)`));
58
+ console.log('');
59
+
60
+ console.log(chalk.white(` 🌍 Global Learnings`));
61
+ console.log(chalk.gray(` Tổng fixes: ${stats.global.total}`));
62
+ console.log(chalk.gray(` Thành công: ${stats.global.success} (${stats.global.rate}%)`));
63
+ console.log('');
64
+
65
+ if (Object.keys(stats.byCategory).length > 0) {
66
+ console.log(chalk.white(` 📂 Theo Error Category`));
67
+ for (const [cat, data] of Object.entries(stats.byCategory)) {
68
+ const rate = data.total > 0 ? (data.success / data.total * 100).toFixed(0) : 0;
69
+ const bar = renderMiniBar(data.success, data.total);
70
+ console.log(chalk.gray(` ${cat.padEnd(12)} ${bar} ${data.success}/${data.total} (${rate}%)`));
71
+ }
72
+ console.log('');
73
+ }
74
+
75
+ console.log(chalk.white(` ⚙️ Preferences đã lưu: ${stats.preferences}`));
76
+
77
+ if (stats.lastLearning) {
78
+ const lastDate = new Date(stats.lastLearning).toLocaleString('vi-VN');
79
+ console.log(chalk.gray(` 📅 Learning gần nhất: ${lastDate}`));
80
+ }
81
+
82
+ console.log('');
83
+ }
84
+
85
+ /**
86
+ * Render a mini progress bar
87
+ */
88
+ function renderMiniBar(value, total) {
89
+ const width = 10;
90
+ const filled = total > 0 ? Math.round(width * value / total) : 0;
91
+ const empty = width - filled;
92
+ return chalk.green('█'.repeat(filled)) + chalk.gray('░'.repeat(empty));
93
+ }
94
+
95
+ /**
96
+ * Clear all local learnings
97
+ */
98
+ async function clearLearnings(learning, force) {
99
+ const stats = await learning.getStats();
100
+
101
+ if (stats.local.total === 0) {
102
+ console.log(chalk.yellow('\n📭 Không có learnings nào để xoá.\n'));
103
+ return;
104
+ }
105
+
106
+ if (!force) {
107
+ console.log(chalk.yellow(`\n⚠️ Sắp xoá ${stats.local.total} learnings của project này.\n`));
108
+
109
+ const { confirm } = await inquirer.prompt([
110
+ {
111
+ type: 'confirm',
112
+ name: 'confirm',
113
+ message: 'Xác nhận xoá tất cả learnings?',
114
+ default: false
115
+ }
116
+ ]);
117
+
118
+ if (!confirm) {
119
+ console.log(chalk.gray('\n👋 Đã huỷ.\n'));
120
+ return;
121
+ }
122
+ }
123
+
124
+ await learning.clearLocal();
125
+ console.log(chalk.green(`\n✅ Đã xoá ${stats.local.total} learnings.\n`));
126
+ }
127
+
128
+ /**
129
+ * Export learnings to file
130
+ */
131
+ async function exportLearnings(learning) {
132
+ const stats = await learning.getStats();
133
+ const fixes = await learning.loadJson(
134
+ path.join(learning.localPath, 'fixes.json'),
135
+ []
136
+ );
137
+ const prefs = await learning.loadJson(
138
+ path.join(learning.localPath, 'preferences.json'),
139
+ {}
140
+ );
141
+
142
+ if (fixes.length === 0 && Object.keys(prefs).length === 0) {
143
+ console.log(chalk.yellow('\n📭 Không có learnings nào để export.\n'));
144
+ return;
145
+ }
146
+
147
+ const exportData = {
148
+ exportedAt: new Date().toISOString(),
149
+ projectPath: learning.projectPath,
150
+ stats,
151
+ fixes: fixes.map(f => ({
152
+ id: f.id,
153
+ errorType: f.errorType,
154
+ errorCategory: f.errorCategory,
155
+ success: f.success,
156
+ userFeedback: f.userFeedback,
157
+ projectType: f.projectType,
158
+ timestamp: f.timestamp
159
+ })),
160
+ preferences: prefs
161
+ };
162
+
163
+ const exportPath = `vibecode-learnings-${Date.now()}.json`;
164
+ await fs.writeFile(exportPath, JSON.stringify(exportData, null, 2));
165
+
166
+ console.log(chalk.green(`\n✅ Đã export ${fixes.length} learnings → ${exportPath}\n`));
167
+ }
168
+
169
+ /**
170
+ * Interactive learning menu
171
+ */
172
+ async function interactiveLearn(learning) {
173
+ const stats = await learning.getStats();
174
+
175
+ const successBar = renderMiniBar(stats.local.success, stats.local.total);
176
+
177
+ console.log(chalk.cyan(`
178
+ ╭────────────────────────────────────────────────────────────────────╮
179
+ │ 🧠 VIBECODE LEARNING │
180
+ │ │
181
+ │ AI học từ feedback của bạn để cải thiện suggestions. │
182
+ │ │
183
+ │ Success rate: ${successBar} ${String(stats.local.rate + '%').padEnd(30)}│
184
+ │ Total learnings: ${String(stats.local.total).padEnd(44)}│
185
+ │ │
186
+ ╰────────────────────────────────────────────────────────────────────╯
187
+ `));
188
+
189
+ const { action } = await inquirer.prompt([
190
+ {
191
+ type: 'list',
192
+ name: 'action',
193
+ message: 'Bạn muốn làm gì?',
194
+ choices: [
195
+ { name: '📊 Xem thống kê chi tiết', value: 'stats' },
196
+ { name: '📤 Export learnings', value: 'export' },
197
+ { name: '🗑️ Xoá learnings', value: 'clear' },
198
+ new inquirer.Separator(),
199
+ { name: '👋 Thoát', value: 'exit' }
200
+ ]
201
+ }
202
+ ]);
203
+
204
+ switch (action) {
205
+ case 'stats':
206
+ await showStats(learning);
207
+ break;
208
+ case 'export':
209
+ await exportLearnings(learning);
210
+ break;
211
+ case 'clear':
212
+ await clearLearnings(learning, false);
213
+ break;
214
+ }
215
+ }
216
+
217
+ /**
218
+ * Ask for feedback after a fix
219
+ * Called from debug/fix commands
220
+ */
221
+ export async function askFeedback(fixInfo) {
222
+ console.log('');
223
+ const { feedback } = await inquirer.prompt([
224
+ {
225
+ type: 'list',
226
+ name: 'feedback',
227
+ message: 'Fix này có đúng không?',
228
+ choices: [
229
+ { name: '✅ Đúng, hoạt động tốt', value: 'success' },
230
+ { name: '❌ Không đúng', value: 'failed' },
231
+ { name: '🔄 Đúng một phần', value: 'partial' },
232
+ { name: '⏭️ Bỏ qua', value: 'skip' }
233
+ ]
234
+ }
235
+ ]);
236
+
237
+ if (feedback === 'skip') {
238
+ return null;
239
+ }
240
+
241
+ const learning = new LearningEngine();
242
+ let userCorrection = null;
243
+
244
+ if (feedback === 'failed' || feedback === 'partial') {
245
+ const { correction } = await inquirer.prompt([
246
+ {
247
+ type: 'input',
248
+ name: 'correction',
249
+ message: 'Mô tả ngắn vấn đề hoặc cách fix đúng (Enter để bỏ qua):',
250
+ }
251
+ ]);
252
+ userCorrection = correction || null;
253
+ }
254
+
255
+ await learning.recordFix({
256
+ errorType: fixInfo.errorType,
257
+ errorMessage: fixInfo.errorMessage,
258
+ errorCategory: fixInfo.errorCategory,
259
+ fixApplied: fixInfo.fixApplied,
260
+ success: feedback === 'success',
261
+ userFeedback: feedback,
262
+ userCorrection
263
+ });
264
+
265
+ if (feedback === 'success') {
266
+ console.log(chalk.green(' ✅ Đã ghi nhận. Cảm ơn!\n'));
267
+ } else {
268
+ console.log(chalk.yellow(' 📝 Đã ghi nhận feedback.\n'));
269
+ }
270
+
271
+ return feedback;
272
+ }
273
+
274
+ /**
275
+ * Show learning-based suggestion (if available)
276
+ */
277
+ export async function showLearningSuggestion(errorType, errorCategory) {
278
+ const learning = new LearningEngine();
279
+ const suggestion = await learning.getSuggestion(errorType, errorCategory);
280
+
281
+ if (suggestion && suggestion.confidence > 0.6) {
282
+ const confidencePercent = (suggestion.confidence * 100).toFixed(0);
283
+ console.log(chalk.cyan(` 💡 Dựa trên ${suggestion.basedOn} fixes trước (độ tin cậy: ${confidencePercent}%)`));
284
+
285
+ if (suggestion.suggestion) {
286
+ const shortSuggestion = suggestion.suggestion.substring(0, 100);
287
+ console.log(chalk.gray(` Gợi ý: ${shortSuggestion}${suggestion.suggestion.length > 100 ? '...' : ''}`));
288
+ }
289
+ console.log('');
290
+ return suggestion;
291
+ }
292
+
293
+ return null;
294
+ }