@nclamvn/vibecode-cli 2.2.0 → 3.0.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/bin/vibecode.js +101 -2
- package/package.json +3 -1
- package/src/commands/config.js +42 -4
- package/src/commands/deploy.js +728 -0
- package/src/commands/favorite.js +412 -0
- package/src/commands/feedback.js +473 -0
- package/src/commands/go.js +170 -4
- package/src/commands/history.js +249 -0
- package/src/commands/images.js +465 -0
- package/src/commands/preview.js +554 -0
- package/src/commands/voice.js +580 -0
- package/src/commands/watch.js +3 -20
- package/src/index.js +49 -2
- package/src/services/image-service.js +513 -0
- package/src/utils/history.js +357 -0
- package/src/utils/notifications.js +343 -0
|
@@ -0,0 +1,473 @@
|
|
|
1
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
2
|
+
// VIBECODE CLI - Feedback Command
|
|
3
|
+
// Interactive feedback mode for incremental changes
|
|
4
|
+
// ═══════════════════════════════════════════════════════════════════════════════
|
|
5
|
+
|
|
6
|
+
import { spawn } from 'child_process';
|
|
7
|
+
import fs from 'fs/promises';
|
|
8
|
+
import path from 'path';
|
|
9
|
+
import chalk from 'chalk';
|
|
10
|
+
import readline from 'readline';
|
|
11
|
+
import net from 'net';
|
|
12
|
+
import { BackupManager } from '../core/backup.js';
|
|
13
|
+
import { spawnClaudeCode, buildPromptWithContext } from '../providers/index.js';
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Feedback command entry point
|
|
17
|
+
*/
|
|
18
|
+
export async function feedbackCommand(options = {}) {
|
|
19
|
+
const cwd = process.cwd();
|
|
20
|
+
|
|
21
|
+
// Check if valid project
|
|
22
|
+
const isValid = await isValidProject(cwd);
|
|
23
|
+
if (!isValid) {
|
|
24
|
+
console.log(chalk.red(`
|
|
25
|
+
╭────────────────────────────────────────────────────────────────────╮
|
|
26
|
+
│ ❌ NOT A VALID PROJECT │
|
|
27
|
+
│ │
|
|
28
|
+
│ Run this command inside a project with package.json, or use: │
|
|
29
|
+
│ vibecode go "description" --feedback │
|
|
30
|
+
│ │
|
|
31
|
+
╰────────────────────────────────────────────────────────────────────╯
|
|
32
|
+
`));
|
|
33
|
+
return;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// Initialize
|
|
37
|
+
const projectName = path.basename(cwd);
|
|
38
|
+
const backup = new BackupManager(cwd);
|
|
39
|
+
const changeHistory = [];
|
|
40
|
+
let devProcess = null;
|
|
41
|
+
let changeCount = 0;
|
|
42
|
+
const port = parseInt(options.port) || 3000;
|
|
43
|
+
|
|
44
|
+
console.log(chalk.cyan(`
|
|
45
|
+
╭────────────────────────────────────────────────────────────────────╮
|
|
46
|
+
│ 💬 VIBECODE FEEDBACK MODE │
|
|
47
|
+
│ │
|
|
48
|
+
│ Project: ${projectName.padEnd(52)}│
|
|
49
|
+
│ │
|
|
50
|
+
│ Commands: │
|
|
51
|
+
│ • Type your changes in natural language │
|
|
52
|
+
│ • 'undo' - Revert last change │
|
|
53
|
+
│ • 'history' - Show change history │
|
|
54
|
+
│ • 'preview' - Open/refresh preview │
|
|
55
|
+
│ • 'status' - Show current status │
|
|
56
|
+
│ • 'files' - List recently changed files │
|
|
57
|
+
│ • 'done' or 'exit' - End session │
|
|
58
|
+
│ │
|
|
59
|
+
╰────────────────────────────────────────────────────────────────────╯
|
|
60
|
+
`));
|
|
61
|
+
|
|
62
|
+
// Start dev server if preview mode
|
|
63
|
+
if (options.preview) {
|
|
64
|
+
console.log(chalk.yellow(' 🚀 Starting preview server...\n'));
|
|
65
|
+
devProcess = await startDevServer(cwd, port);
|
|
66
|
+
const serverReady = await waitForServer(port);
|
|
67
|
+
|
|
68
|
+
if (serverReady) {
|
|
69
|
+
await openBrowser(`http://localhost:${port}`);
|
|
70
|
+
console.log(chalk.green(` ✅ Preview ready at http://localhost:${port}\n`));
|
|
71
|
+
} else {
|
|
72
|
+
console.log(chalk.yellow(` ⚠️ Server may still be starting...\n`));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
// Create readline interface
|
|
77
|
+
const rl = readline.createInterface({
|
|
78
|
+
input: process.stdin,
|
|
79
|
+
output: process.stdout,
|
|
80
|
+
prompt: chalk.green('feedback> ')
|
|
81
|
+
});
|
|
82
|
+
|
|
83
|
+
rl.prompt();
|
|
84
|
+
|
|
85
|
+
rl.on('line', async (line) => {
|
|
86
|
+
const input = line.trim();
|
|
87
|
+
const inputLower = input.toLowerCase();
|
|
88
|
+
|
|
89
|
+
// Exit commands
|
|
90
|
+
if (inputLower === 'done' || inputLower === 'exit' || inputLower === 'quit' || inputLower === 'q') {
|
|
91
|
+
await endSession(devProcess, changeCount, rl);
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// Undo command
|
|
96
|
+
if (inputLower === 'undo') {
|
|
97
|
+
if (changeHistory.length === 0) {
|
|
98
|
+
console.log(chalk.yellow(' No changes to undo.\n'));
|
|
99
|
+
} else {
|
|
100
|
+
const lastChange = changeHistory.pop();
|
|
101
|
+
try {
|
|
102
|
+
await backup.restoreBackup(lastChange.backupId);
|
|
103
|
+
changeCount--;
|
|
104
|
+
console.log(chalk.green(` ↩️ Reverted: "${lastChange.description}"\n`));
|
|
105
|
+
|
|
106
|
+
if (options.preview) {
|
|
107
|
+
console.log(chalk.gray(' 🔄 Preview will refresh automatically.\n'));
|
|
108
|
+
}
|
|
109
|
+
} catch (error) {
|
|
110
|
+
console.log(chalk.red(` ❌ Undo failed: ${error.message}\n`));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
rl.prompt();
|
|
114
|
+
return;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
// History command
|
|
118
|
+
if (inputLower === 'history') {
|
|
119
|
+
if (changeHistory.length === 0) {
|
|
120
|
+
console.log(chalk.gray(' No changes yet.\n'));
|
|
121
|
+
} else {
|
|
122
|
+
console.log(chalk.cyan('\n 📜 Change History:\n'));
|
|
123
|
+
changeHistory.forEach((change, i) => {
|
|
124
|
+
const time = new Date(change.timestamp).toLocaleTimeString();
|
|
125
|
+
console.log(chalk.gray(` ${i + 1}. [${time}] ${change.description}`));
|
|
126
|
+
});
|
|
127
|
+
console.log('');
|
|
128
|
+
}
|
|
129
|
+
rl.prompt();
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
// Preview command
|
|
134
|
+
if (inputLower === 'preview') {
|
|
135
|
+
if (!devProcess) {
|
|
136
|
+
console.log(chalk.yellow(' 🚀 Starting preview server...\n'));
|
|
137
|
+
devProcess = await startDevServer(cwd, port);
|
|
138
|
+
await waitForServer(port);
|
|
139
|
+
}
|
|
140
|
+
await openBrowser(`http://localhost:${port}`);
|
|
141
|
+
console.log(chalk.green(` ✅ Preview opened at http://localhost:${port}\n`));
|
|
142
|
+
rl.prompt();
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
// Status command
|
|
147
|
+
if (inputLower === 'status') {
|
|
148
|
+
console.log(chalk.cyan(`\n 📊 Session Status:`));
|
|
149
|
+
console.log(chalk.gray(` ─────────────────────────────────────`));
|
|
150
|
+
console.log(chalk.white(` Project: ${projectName}`));
|
|
151
|
+
console.log(chalk.white(` Changes: ${changeCount}`));
|
|
152
|
+
console.log(chalk.white(` Preview: ${devProcess ? chalk.green('Running') : chalk.gray('Not running')}`));
|
|
153
|
+
console.log(chalk.white(` Undoable: ${changeHistory.length}`));
|
|
154
|
+
console.log('');
|
|
155
|
+
rl.prompt();
|
|
156
|
+
return;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Files command
|
|
160
|
+
if (inputLower === 'files') {
|
|
161
|
+
await showRecentFiles(cwd);
|
|
162
|
+
rl.prompt();
|
|
163
|
+
return;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Help command
|
|
167
|
+
if (inputLower === 'help' || inputLower === '?') {
|
|
168
|
+
showHelp();
|
|
169
|
+
rl.prompt();
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Clear command
|
|
174
|
+
if (inputLower === 'clear') {
|
|
175
|
+
console.clear();
|
|
176
|
+
console.log(chalk.cyan(` 💬 Feedback Mode - ${changeCount} changes applied\n`));
|
|
177
|
+
rl.prompt();
|
|
178
|
+
return;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
// Empty or too short input
|
|
182
|
+
if (!input || input.length < 3) {
|
|
183
|
+
rl.prompt();
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Process change request
|
|
188
|
+
console.log(chalk.yellow('\n 🔄 Processing change...\n'));
|
|
189
|
+
|
|
190
|
+
try {
|
|
191
|
+
// Create backup before change
|
|
192
|
+
const backupId = await backup.createBackup(`feedback-${changeCount + 1}`);
|
|
193
|
+
|
|
194
|
+
// Build prompt for Claude
|
|
195
|
+
const prompt = buildChangePrompt(cwd, input);
|
|
196
|
+
|
|
197
|
+
// Build full prompt with context
|
|
198
|
+
const fullPrompt = await buildPromptWithContext(prompt, cwd);
|
|
199
|
+
|
|
200
|
+
// Execute change with Claude
|
|
201
|
+
const result = await spawnClaudeCode(fullPrompt, { cwd });
|
|
202
|
+
|
|
203
|
+
// Record change
|
|
204
|
+
const description = input.substring(0, 50) + (input.length > 50 ? '...' : '');
|
|
205
|
+
changeHistory.push({
|
|
206
|
+
description,
|
|
207
|
+
backupId,
|
|
208
|
+
timestamp: new Date().toISOString(),
|
|
209
|
+
files: result.filesChanged || []
|
|
210
|
+
});
|
|
211
|
+
changeCount++;
|
|
212
|
+
|
|
213
|
+
console.log(chalk.green(`\n ✅ Change #${changeCount} applied: "${description}"`));
|
|
214
|
+
|
|
215
|
+
if (options.preview) {
|
|
216
|
+
console.log(chalk.gray(' 🔄 Preview refreshing...\n'));
|
|
217
|
+
} else {
|
|
218
|
+
console.log('');
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
} catch (error) {
|
|
222
|
+
console.log(chalk.red(`\n ❌ Error: ${error.message}`));
|
|
223
|
+
console.log(chalk.gray(' Try rephrasing your request or be more specific.\n'));
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
rl.prompt();
|
|
227
|
+
});
|
|
228
|
+
|
|
229
|
+
rl.on('close', () => {
|
|
230
|
+
if (devProcess) {
|
|
231
|
+
devProcess.kill();
|
|
232
|
+
}
|
|
233
|
+
process.exit(0);
|
|
234
|
+
});
|
|
235
|
+
|
|
236
|
+
// Handle Ctrl+C
|
|
237
|
+
process.on('SIGINT', async () => {
|
|
238
|
+
await endSession(devProcess, changeCount, rl);
|
|
239
|
+
});
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* End feedback session
|
|
244
|
+
*/
|
|
245
|
+
async function endSession(devProcess, changeCount, rl) {
|
|
246
|
+
console.log(chalk.cyan(`\n
|
|
247
|
+
╭────────────────────────────────────────────────────────────────────╮
|
|
248
|
+
│ 👋 FEEDBACK SESSION ENDED │
|
|
249
|
+
│ │
|
|
250
|
+
│ Total changes applied: ${String(changeCount).padEnd(38)}│
|
|
251
|
+
│ │
|
|
252
|
+
│ Your changes have been saved. Use 'vibecode undo' to rollback. │
|
|
253
|
+
│ │
|
|
254
|
+
╰────────────────────────────────────────────────────────────────────╯
|
|
255
|
+
`));
|
|
256
|
+
|
|
257
|
+
if (devProcess) {
|
|
258
|
+
devProcess.kill();
|
|
259
|
+
}
|
|
260
|
+
rl.close();
|
|
261
|
+
process.exit(0);
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Build change prompt for Claude
|
|
266
|
+
*/
|
|
267
|
+
function buildChangePrompt(cwd, request) {
|
|
268
|
+
return `
|
|
269
|
+
# Incremental Change Request
|
|
270
|
+
|
|
271
|
+
## Project: ${path.basename(cwd)}
|
|
272
|
+
|
|
273
|
+
## User Request:
|
|
274
|
+
${request}
|
|
275
|
+
|
|
276
|
+
## Instructions:
|
|
277
|
+
1. Make ONLY the requested change - nothing more, nothing less
|
|
278
|
+
2. Preserve ALL existing functionality and code
|
|
279
|
+
3. Keep changes minimal and surgically precise
|
|
280
|
+
4. Update any related files if absolutely necessary
|
|
281
|
+
5. Do NOT remove, modify, or refactor unrelated code
|
|
282
|
+
6. Do NOT add comments explaining changes
|
|
283
|
+
7. Do NOT create backup files
|
|
284
|
+
|
|
285
|
+
## Critical Rules:
|
|
286
|
+
- This is an INCREMENTAL change, not a rebuild
|
|
287
|
+
- Make the smallest possible change to fulfill the request
|
|
288
|
+
- Maintain exact code style and formatting of existing code
|
|
289
|
+
- If the request is unclear, make a reasonable interpretation
|
|
290
|
+
- Do NOT add extra features or "improvements"
|
|
291
|
+
|
|
292
|
+
## Apply the change now.
|
|
293
|
+
`;
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
/**
|
|
297
|
+
* Check if directory is a valid project
|
|
298
|
+
*/
|
|
299
|
+
async function isValidProject(cwd) {
|
|
300
|
+
try {
|
|
301
|
+
await fs.access(path.join(cwd, 'package.json'));
|
|
302
|
+
return true;
|
|
303
|
+
} catch {
|
|
304
|
+
return false;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
/**
|
|
309
|
+
* Start development server
|
|
310
|
+
*/
|
|
311
|
+
async function startDevServer(cwd, port = 3000) {
|
|
312
|
+
// Detect project type and appropriate dev command
|
|
313
|
+
let devCmd = 'npm run dev';
|
|
314
|
+
|
|
315
|
+
try {
|
|
316
|
+
const pkgPath = path.join(cwd, 'package.json');
|
|
317
|
+
const pkg = JSON.parse(await fs.readFile(pkgPath, 'utf-8'));
|
|
318
|
+
const scripts = pkg.scripts || {};
|
|
319
|
+
|
|
320
|
+
if (scripts.dev) {
|
|
321
|
+
devCmd = 'npm run dev';
|
|
322
|
+
} else if (scripts.start) {
|
|
323
|
+
devCmd = 'npm run start';
|
|
324
|
+
}
|
|
325
|
+
} catch {}
|
|
326
|
+
|
|
327
|
+
return new Promise((resolve) => {
|
|
328
|
+
const child = spawn('sh', ['-c', devCmd], {
|
|
329
|
+
cwd,
|
|
330
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
331
|
+
env: { ...process.env, PORT: String(port) },
|
|
332
|
+
detached: false
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
child.stdout.on('data', () => {});
|
|
336
|
+
child.stderr.on('data', () => {});
|
|
337
|
+
|
|
338
|
+
// Give it time to start
|
|
339
|
+
setTimeout(() => resolve(child), 2000);
|
|
340
|
+
});
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
/**
|
|
344
|
+
* Wait for server to be ready
|
|
345
|
+
*/
|
|
346
|
+
async function waitForServer(port, maxAttempts = 30) {
|
|
347
|
+
for (let i = 0; i < maxAttempts; i++) {
|
|
348
|
+
const isReady = await checkPort(port);
|
|
349
|
+
if (isReady) return true;
|
|
350
|
+
await sleep(500);
|
|
351
|
+
}
|
|
352
|
+
return false;
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Check if port is in use (server running)
|
|
357
|
+
*/
|
|
358
|
+
function checkPort(port) {
|
|
359
|
+
return new Promise((resolve) => {
|
|
360
|
+
const socket = new net.Socket();
|
|
361
|
+
socket.setTimeout(500);
|
|
362
|
+
socket.on('connect', () => { socket.destroy(); resolve(true); });
|
|
363
|
+
socket.on('timeout', () => { socket.destroy(); resolve(false); });
|
|
364
|
+
socket.on('error', () => { socket.destroy(); resolve(false); });
|
|
365
|
+
socket.connect(port, '127.0.0.1');
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
/**
|
|
370
|
+
* Open URL in browser
|
|
371
|
+
*/
|
|
372
|
+
async function openBrowser(url) {
|
|
373
|
+
try {
|
|
374
|
+
const open = (await import('open')).default;
|
|
375
|
+
await open(url);
|
|
376
|
+
} catch {
|
|
377
|
+
// Fallback
|
|
378
|
+
const { exec } = await import('child_process');
|
|
379
|
+
const { promisify } = await import('util');
|
|
380
|
+
const execAsync = promisify(exec);
|
|
381
|
+
|
|
382
|
+
const platform = process.platform;
|
|
383
|
+
const commands = {
|
|
384
|
+
darwin: `open "${url}"`,
|
|
385
|
+
win32: `start "" "${url}"`,
|
|
386
|
+
linux: `xdg-open "${url}"`
|
|
387
|
+
};
|
|
388
|
+
|
|
389
|
+
if (commands[platform]) {
|
|
390
|
+
try {
|
|
391
|
+
await execAsync(commands[platform]);
|
|
392
|
+
} catch {}
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
/**
|
|
398
|
+
* Show recently changed files
|
|
399
|
+
*/
|
|
400
|
+
async function showRecentFiles(cwd) {
|
|
401
|
+
console.log(chalk.cyan('\n 📁 Recent Files:\n'));
|
|
402
|
+
|
|
403
|
+
try {
|
|
404
|
+
const { exec } = await import('child_process');
|
|
405
|
+
const { promisify } = await import('util');
|
|
406
|
+
const execAsync = promisify(exec);
|
|
407
|
+
|
|
408
|
+
// Get recently modified files (last 5 minutes)
|
|
409
|
+
const { stdout } = await execAsync(
|
|
410
|
+
`find . -type f -mmin -5 -not -path "*/node_modules/*" -not -path "*/.git/*" -not -path "*/.next/*" -not -path "*/dist/*" 2>/dev/null | head -20`,
|
|
411
|
+
{ cwd }
|
|
412
|
+
);
|
|
413
|
+
|
|
414
|
+
const files = stdout.trim().split('\n').filter(f => f);
|
|
415
|
+
|
|
416
|
+
if (files.length === 0) {
|
|
417
|
+
console.log(chalk.gray(' No recently modified files.\n'));
|
|
418
|
+
} else {
|
|
419
|
+
files.forEach(file => {
|
|
420
|
+
console.log(chalk.gray(` ${file}`));
|
|
421
|
+
});
|
|
422
|
+
console.log('');
|
|
423
|
+
}
|
|
424
|
+
} catch {
|
|
425
|
+
console.log(chalk.gray(' Could not list files.\n'));
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
/**
|
|
430
|
+
* Show help
|
|
431
|
+
*/
|
|
432
|
+
function showHelp() {
|
|
433
|
+
console.log(chalk.cyan(`
|
|
434
|
+
📖 Feedback Mode Commands:
|
|
435
|
+
─────────────────────────────────────────────────────────────────
|
|
436
|
+
|
|
437
|
+
${chalk.white('Natural language')} Describe the change you want
|
|
438
|
+
${chalk.green('undo')} Revert the last change
|
|
439
|
+
${chalk.green('history')} Show all changes made this session
|
|
440
|
+
${chalk.green('preview')} Open preview in browser
|
|
441
|
+
${chalk.green('status')} Show session status
|
|
442
|
+
${chalk.green('files')} Show recently modified files
|
|
443
|
+
${chalk.green('clear')} Clear the screen
|
|
444
|
+
${chalk.green('done')} / ${chalk.green('exit')} End the session
|
|
445
|
+
|
|
446
|
+
${chalk.gray('Examples:')}
|
|
447
|
+
${chalk.gray('> Change the header color to blue')}
|
|
448
|
+
${chalk.gray('> Add a contact form section')}
|
|
449
|
+
${chalk.gray('> Remove the pricing table')}
|
|
450
|
+
${chalk.gray('> Make the logo bigger')}
|
|
451
|
+
`));
|
|
452
|
+
}
|
|
453
|
+
|
|
454
|
+
/**
|
|
455
|
+
* Sleep helper
|
|
456
|
+
*/
|
|
457
|
+
function sleep(ms) {
|
|
458
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
/**
|
|
462
|
+
* Start feedback mode for use in go.js
|
|
463
|
+
*/
|
|
464
|
+
export async function startFeedbackMode(projectPath, options = {}) {
|
|
465
|
+
const originalCwd = process.cwd();
|
|
466
|
+
|
|
467
|
+
try {
|
|
468
|
+
process.chdir(projectPath);
|
|
469
|
+
await feedbackCommand(options);
|
|
470
|
+
} finally {
|
|
471
|
+
process.chdir(originalCwd);
|
|
472
|
+
}
|
|
473
|
+
}
|
package/src/commands/go.js
CHANGED
|
@@ -42,6 +42,11 @@ import { runTests } from '../core/test-runner.js';
|
|
|
42
42
|
import { analyzeErrors } from '../core/error-analyzer.js';
|
|
43
43
|
import { ensureDir, appendToFile } from '../utils/files.js';
|
|
44
44
|
import { getTemplate, getCategoryIcon } from '../templates/index.js';
|
|
45
|
+
import { autoGenerateImages } from './images.js';
|
|
46
|
+
import { autoDeploy } from './deploy.js';
|
|
47
|
+
import { startFeedbackMode } from './feedback.js';
|
|
48
|
+
import { notifyBuildComplete, notifyDeployComplete } from '../utils/notifications.js';
|
|
49
|
+
import { addToHistory } from '../utils/history.js';
|
|
45
50
|
|
|
46
51
|
const execAsync = promisify(exec);
|
|
47
52
|
|
|
@@ -255,13 +260,91 @@ export async function goCommand(description, options = {}) {
|
|
|
255
260
|
console.log(renderProgressBar(100));
|
|
256
261
|
console.log();
|
|
257
262
|
|
|
263
|
+
// Generate images if requested
|
|
264
|
+
if (options.withImages) {
|
|
265
|
+
console.log(chalk.cyan('\n 📸 Generating project images...\n'));
|
|
266
|
+
try {
|
|
267
|
+
const imageResults = await autoGenerateImages(projectPath, {
|
|
268
|
+
template: null,
|
|
269
|
+
theme: 'tech'
|
|
270
|
+
});
|
|
271
|
+
results.imagesGenerated = imageResults.downloaded.length;
|
|
272
|
+
console.log(chalk.green(` ✅ ${results.imagesGenerated} images generated\n`));
|
|
273
|
+
} catch (error) {
|
|
274
|
+
console.log(chalk.yellow(` ⚠️ Image generation failed: ${error.message}\n`));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
|
|
258
278
|
// Show summary
|
|
259
279
|
const duration = ((Date.now() - startTime) / 1000 / 60).toFixed(1);
|
|
260
280
|
showMagicSummary(projectName, projectPath, duration, results, options);
|
|
261
281
|
|
|
262
|
-
//
|
|
263
|
-
|
|
282
|
+
// Add to history
|
|
283
|
+
await addToHistory(`vibecode go "${desc}"`, desc, {
|
|
284
|
+
projectName,
|
|
285
|
+
projectPath,
|
|
286
|
+
duration,
|
|
287
|
+
filesCreated: results.filesCreated,
|
|
288
|
+
testsPassed: results.allPassed
|
|
289
|
+
});
|
|
290
|
+
|
|
291
|
+
// Send notification if enabled
|
|
292
|
+
if (options.notify) {
|
|
293
|
+
notifyBuildComplete(results.allPassed, projectName);
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
// Auto preview if requested
|
|
297
|
+
if (options.preview) {
|
|
298
|
+
console.log(chalk.cyan('\n 🚀 Starting preview...\n'));
|
|
299
|
+
await new Promise(resolve => setTimeout(resolve, 1000)); // Wait for files to settle
|
|
300
|
+
|
|
301
|
+
try {
|
|
302
|
+
const { autoPreview } = await import('./preview.js');
|
|
303
|
+
await autoPreview(projectPath, {
|
|
304
|
+
qr: options.qr,
|
|
305
|
+
port: options.port
|
|
306
|
+
});
|
|
307
|
+
} catch (error) {
|
|
308
|
+
console.log(chalk.yellow(` ⚠️ Preview failed: ${error.message}`));
|
|
309
|
+
console.log(chalk.gray(` Run manually: cd ${projectName} && vibecode preview\n`));
|
|
310
|
+
}
|
|
311
|
+
} else if (options.open) {
|
|
264
312
|
await openProject(projectPath);
|
|
313
|
+
} else {
|
|
314
|
+
// Show preview hint
|
|
315
|
+
console.log(chalk.gray(` 💡 Quick preview: ${chalk.cyan(`cd ${projectName} && vibecode preview`)}\n`));
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
// Auto deploy if requested
|
|
319
|
+
if (options.deploy) {
|
|
320
|
+
console.log(chalk.cyan('\n 🚀 Deploying to cloud...\n'));
|
|
321
|
+
try {
|
|
322
|
+
const deployResult = await autoDeploy(projectPath, {
|
|
323
|
+
platform: options.deployPlatform || 'vercel',
|
|
324
|
+
preview: false
|
|
325
|
+
});
|
|
326
|
+
if (deployResult?.url) {
|
|
327
|
+
results.deployUrl = deployResult.url;
|
|
328
|
+
if (options.notify) {
|
|
329
|
+
notifyDeployComplete(true, options.deployPlatform || 'Vercel', deployResult.url);
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
} catch (error) {
|
|
333
|
+
console.log(chalk.yellow(` ⚠️ Deploy failed: ${error.message}`));
|
|
334
|
+
console.log(chalk.gray(` Run manually: cd ${projectName} && vibecode deploy\n`));
|
|
335
|
+
if (options.notify) {
|
|
336
|
+
notifyDeployComplete(false, options.deployPlatform || 'Vercel');
|
|
337
|
+
}
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
// Enter feedback mode if requested
|
|
342
|
+
if (options.feedback) {
|
|
343
|
+
console.log(chalk.cyan('\n 💬 Entering feedback mode...\n'));
|
|
344
|
+
await startFeedbackMode(projectPath, {
|
|
345
|
+
preview: options.preview || true,
|
|
346
|
+
port: options.port || '3000'
|
|
347
|
+
});
|
|
265
348
|
}
|
|
266
349
|
|
|
267
350
|
} catch (error) {
|
|
@@ -568,13 +651,92 @@ ${prompt}
|
|
|
568
651
|
console.log(renderProgressBar(100));
|
|
569
652
|
console.log();
|
|
570
653
|
|
|
654
|
+
// Generate images if requested
|
|
655
|
+
if (options.withImages) {
|
|
656
|
+
console.log(chalk.cyan('\n 📸 Generating project images...\n'));
|
|
657
|
+
try {
|
|
658
|
+
const imageResults = await autoGenerateImages(projectPath, {
|
|
659
|
+
template: templateId,
|
|
660
|
+
theme: 'tech'
|
|
661
|
+
});
|
|
662
|
+
results.imagesGenerated = imageResults.downloaded.length;
|
|
663
|
+
console.log(chalk.green(` ✅ ${results.imagesGenerated} images generated\n`));
|
|
664
|
+
} catch (error) {
|
|
665
|
+
console.log(chalk.yellow(` ⚠️ Image generation failed: ${error.message}\n`));
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
571
669
|
// Show summary
|
|
572
670
|
const duration = ((Date.now() - startTime) / 1000 / 60).toFixed(1);
|
|
573
671
|
showTemplateSummary(template, projectName, projectPath, duration, results, options);
|
|
574
672
|
|
|
575
|
-
//
|
|
576
|
-
|
|
673
|
+
// Add to history
|
|
674
|
+
await addToHistory(`vibecode go --template ${templateId}`, template.name, {
|
|
675
|
+
template: templateId,
|
|
676
|
+
projectName,
|
|
677
|
+
projectPath,
|
|
678
|
+
duration,
|
|
679
|
+
filesCreated: results.filesCreated,
|
|
680
|
+
testsPassed: results.allPassed
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
// Send notification if enabled
|
|
684
|
+
if (options.notify) {
|
|
685
|
+
notifyBuildComplete(results.allPassed, projectName);
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
// Auto preview if requested
|
|
689
|
+
if (options.preview) {
|
|
690
|
+
console.log(chalk.cyan('\n 🚀 Starting preview...\n'));
|
|
691
|
+
await sleep(1000); // Wait for files to settle
|
|
692
|
+
|
|
693
|
+
try {
|
|
694
|
+
const { autoPreview } = await import('./preview.js');
|
|
695
|
+
await autoPreview(projectPath, {
|
|
696
|
+
qr: options.qr,
|
|
697
|
+
port: options.port
|
|
698
|
+
});
|
|
699
|
+
} catch (error) {
|
|
700
|
+
console.log(chalk.yellow(` ⚠️ Preview failed: ${error.message}`));
|
|
701
|
+
console.log(chalk.gray(` Run manually: cd ${projectName} && vibecode preview\n`));
|
|
702
|
+
}
|
|
703
|
+
} else if (options.open) {
|
|
577
704
|
await openProject(projectPath);
|
|
705
|
+
} else {
|
|
706
|
+
// Show preview hint
|
|
707
|
+
console.log(chalk.gray(` 💡 Quick preview: ${chalk.cyan(`cd ${projectName} && vibecode preview`)}\n`));
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
// Auto deploy if requested
|
|
711
|
+
if (options.deploy) {
|
|
712
|
+
console.log(chalk.cyan('\n 🚀 Deploying to cloud...\n'));
|
|
713
|
+
try {
|
|
714
|
+
const deployResult = await autoDeploy(projectPath, {
|
|
715
|
+
platform: options.deployPlatform || 'vercel',
|
|
716
|
+
preview: false
|
|
717
|
+
});
|
|
718
|
+
if (deployResult?.url) {
|
|
719
|
+
results.deployUrl = deployResult.url;
|
|
720
|
+
if (options.notify) {
|
|
721
|
+
notifyDeployComplete(true, options.deployPlatform || 'Vercel', deployResult.url);
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
} catch (error) {
|
|
725
|
+
console.log(chalk.yellow(` ⚠️ Deploy failed: ${error.message}`));
|
|
726
|
+
console.log(chalk.gray(` Run manually: cd ${projectName} && vibecode deploy\n`));
|
|
727
|
+
if (options.notify) {
|
|
728
|
+
notifyDeployComplete(false, options.deployPlatform || 'Vercel');
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
// Enter feedback mode if requested
|
|
734
|
+
if (options.feedback) {
|
|
735
|
+
console.log(chalk.cyan('\n 💬 Entering feedback mode...\n'));
|
|
736
|
+
await startFeedbackMode(projectPath, {
|
|
737
|
+
preview: options.preview || true,
|
|
738
|
+
port: options.port || '3000'
|
|
739
|
+
});
|
|
578
740
|
}
|
|
579
741
|
|
|
580
742
|
} catch (error) {
|
|
@@ -586,6 +748,10 @@ ${prompt}
|
|
|
586
748
|
}
|
|
587
749
|
}
|
|
588
750
|
|
|
751
|
+
function sleep(ms) {
|
|
752
|
+
return new Promise(resolve => setTimeout(resolve, ms));
|
|
753
|
+
}
|
|
754
|
+
|
|
589
755
|
/**
|
|
590
756
|
* Show template mode header
|
|
591
757
|
*/
|