@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.
- package/.vibecode/learning/fixes.json +1 -0
- package/.vibecode/learning/preferences.json +1 -0
- package/bin/vibecode.js +86 -3
- package/docs-site/README.md +41 -0
- package/docs-site/blog/2019-05-28-first-blog-post.md +12 -0
- package/docs-site/blog/2019-05-29-long-blog-post.md +44 -0
- package/docs-site/blog/2021-08-01-mdx-blog-post.mdx +24 -0
- package/docs-site/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- package/docs-site/blog/2021-08-26-welcome/index.md +29 -0
- package/docs-site/blog/authors.yml +25 -0
- package/docs-site/blog/tags.yml +19 -0
- package/docs-site/docs/commands/agent.md +162 -0
- package/docs-site/docs/commands/assist.md +71 -0
- package/docs-site/docs/commands/build.md +53 -0
- package/docs-site/docs/commands/config.md +30 -0
- package/docs-site/docs/commands/debug.md +173 -0
- package/docs-site/docs/commands/doctor.md +34 -0
- package/docs-site/docs/commands/go.md +128 -0
- package/docs-site/docs/commands/index.md +79 -0
- package/docs-site/docs/commands/init.md +42 -0
- package/docs-site/docs/commands/learn.md +82 -0
- package/docs-site/docs/commands/lock.md +33 -0
- package/docs-site/docs/commands/plan.md +29 -0
- package/docs-site/docs/commands/review.md +31 -0
- package/docs-site/docs/commands/snapshot.md +34 -0
- package/docs-site/docs/commands/start.md +32 -0
- package/docs-site/docs/commands/status.md +37 -0
- package/docs-site/docs/commands/undo.md +83 -0
- package/docs-site/docs/configuration.md +72 -0
- package/docs-site/docs/faq.md +83 -0
- package/docs-site/docs/getting-started.md +119 -0
- package/docs-site/docs/guides/agent-mode.md +94 -0
- package/docs-site/docs/guides/debug-mode.md +83 -0
- package/docs-site/docs/guides/magic-mode.md +107 -0
- package/docs-site/docs/installation.md +98 -0
- package/docs-site/docs/intro.md +67 -0
- package/docs-site/docusaurus.config.ts +141 -0
- package/docs-site/package-lock.json +18039 -0
- package/docs-site/package.json +48 -0
- package/docs-site/sidebars.ts +70 -0
- package/docs-site/src/components/HomepageFeatures/index.tsx +72 -0
- package/docs-site/src/components/HomepageFeatures/styles.module.css +16 -0
- package/docs-site/src/css/custom.css +30 -0
- package/docs-site/src/pages/index.module.css +23 -0
- package/docs-site/src/pages/index.tsx +44 -0
- package/docs-site/src/pages/markdown-page.md +7 -0
- package/docs-site/src/theme/Footer/index.tsx +127 -0
- package/docs-site/src/theme/Footer/styles.module.css +285 -0
- package/docs-site/static/.nojekyll +0 -0
- package/docs-site/static/img/docusaurus-social-card.jpg +0 -0
- package/docs-site/static/img/docusaurus.png +0 -0
- package/docs-site/static/img/favicon.ico +0 -0
- package/docs-site/static/img/logo.svg +1 -0
- package/docs-site/static/img/undraw_docusaurus_mountain.svg +171 -0
- package/docs-site/static/img/undraw_docusaurus_react.svg +170 -0
- package/docs-site/static/img/undraw_docusaurus_tree.svg +40 -0
- package/docs-site/tsconfig.json +8 -0
- package/package.json +5 -2
- package/src/agent/orchestrator.js +104 -35
- package/src/commands/build.js +13 -3
- package/src/commands/debug.js +109 -1
- package/src/commands/git.js +923 -0
- package/src/commands/go.js +9 -2
- package/src/commands/learn.js +294 -0
- package/src/commands/shell.js +486 -0
- package/src/commands/undo.js +281 -0
- package/src/commands/watch.js +556 -0
- package/src/commands/wizard.js +322 -0
- package/src/core/backup.js +325 -0
- package/src/core/learning.js +295 -0
- package/src/debug/image-analyzer.js +304 -0
- package/src/debug/index.js +30 -1
- package/src/index.js +50 -0
- package/src/ui/__tests__/error-translator.test.js +390 -0
- package/src/ui/dashboard.js +364 -0
- package/src/ui/error-translator.js +775 -0
- package/src/utils/image.js +222 -0
package/src/commands/go.js
CHANGED
|
@@ -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
|
+
}
|