@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.
@@ -0,0 +1,249 @@
1
+ // ═══════════════════════════════════════════════════════════════════════════════
2
+ // VIBECODE CLI - History Command
3
+ // View and manage command history
4
+ // ═══════════════════════════════════════════════════════════════════════════════
5
+
6
+ import chalk from 'chalk';
7
+ import inquirer from 'inquirer';
8
+ import { spawn } from 'child_process';
9
+ import {
10
+ loadHistory,
11
+ clearHistory,
12
+ searchHistory,
13
+ getHistoryItem,
14
+ getHistoryStats
15
+ } from '../utils/history.js';
16
+
17
+ /**
18
+ * History command entry point
19
+ */
20
+ export async function historyCommand(options = {}) {
21
+ // Clear history
22
+ if (options.clear) {
23
+ const { confirm } = await inquirer.prompt([{
24
+ type: 'confirm',
25
+ name: 'confirm',
26
+ message: 'Clear all command history?',
27
+ default: false
28
+ }]);
29
+
30
+ if (confirm) {
31
+ await clearHistory();
32
+ console.log(chalk.green('\n ✅ History cleared\n'));
33
+ }
34
+ return;
35
+ }
36
+
37
+ // Search history
38
+ if (options.search) {
39
+ return searchHistoryCommand(options.search);
40
+ }
41
+
42
+ // Run command from history
43
+ if (options.run) {
44
+ return runFromHistory(options.run);
45
+ }
46
+
47
+ // Show stats
48
+ if (options.stats) {
49
+ return showHistoryStats();
50
+ }
51
+
52
+ // Show history (default)
53
+ return showHistory(options);
54
+ }
55
+
56
+ /**
57
+ * Display command history
58
+ */
59
+ async function showHistory(options) {
60
+ const history = await loadHistory();
61
+ const limit = parseInt(options.limit) || 20;
62
+
63
+ console.log(chalk.cyan(`
64
+ ╭────────────────────────────────────────────────────────────────────╮
65
+ │ 📜 COMMAND HISTORY │
66
+ ╰────────────────────────────────────────────────────────────────────╯
67
+ `));
68
+
69
+ if (history.length === 0) {
70
+ console.log(chalk.gray(' No history yet.\n'));
71
+ console.log(chalk.gray(' Run some commands first:\n'));
72
+ console.log(chalk.gray(' vibecode go "Your project description"\n'));
73
+ return;
74
+ }
75
+
76
+ const items = history.slice(0, limit);
77
+
78
+ for (let i = 0; i < items.length; i++) {
79
+ const item = items[i];
80
+ const date = new Date(item.timestamp).toLocaleDateString();
81
+ const time = new Date(item.timestamp).toLocaleTimeString([], {
82
+ hour: '2-digit',
83
+ minute: '2-digit'
84
+ });
85
+
86
+ // Truncate long commands
87
+ const displayCmd = item.command.length > 60
88
+ ? item.command.substring(0, 57) + '...'
89
+ : item.command;
90
+
91
+ console.log(
92
+ chalk.yellow(` ${(i + 1).toString().padStart(2)}. `) +
93
+ chalk.white(displayCmd)
94
+ );
95
+ console.log(chalk.gray(` ${date} ${time}`));
96
+
97
+ if (item.description && item.description !== item.command) {
98
+ const displayDesc = item.description.length > 50
99
+ ? item.description.substring(0, 47) + '...'
100
+ : item.description;
101
+ console.log(chalk.gray(` ${displayDesc}`));
102
+ }
103
+
104
+ if (item.projectName) {
105
+ console.log(chalk.gray(` → ${item.projectName}`));
106
+ }
107
+
108
+ console.log('');
109
+ }
110
+
111
+ console.log(chalk.gray(` Showing ${items.length} of ${history.length} items\n`));
112
+ console.log(chalk.gray(` Commands:`));
113
+ console.log(chalk.gray(` ${chalk.cyan('vibecode history --run <n>')} Re-run command`));
114
+ console.log(chalk.gray(` ${chalk.cyan('vibecode history --search <q>')} Search history`));
115
+ console.log(chalk.gray(` ${chalk.cyan('vibecode history --clear')} Clear history\n`));
116
+ }
117
+
118
+ /**
119
+ * Search history and display results
120
+ */
121
+ async function searchHistoryCommand(query) {
122
+ const results = await searchHistory(query);
123
+
124
+ console.log(chalk.cyan(`\n 🔍 Search results for "${query}":\n`));
125
+
126
+ if (results.length === 0) {
127
+ console.log(chalk.gray(' No matches found.\n'));
128
+ return;
129
+ }
130
+
131
+ for (let i = 0; i < Math.min(results.length, 20); i++) {
132
+ const item = results[i];
133
+ const date = new Date(item.timestamp).toLocaleDateString();
134
+
135
+ const displayCmd = item.command.length > 55
136
+ ? item.command.substring(0, 52) + '...'
137
+ : item.command;
138
+
139
+ console.log(chalk.yellow(` ${i + 1}. `) + chalk.white(displayCmd));
140
+ console.log(chalk.gray(` ${date}`));
141
+
142
+ if (item.description && item.description !== item.command) {
143
+ const displayDesc = item.description.length > 50
144
+ ? item.description.substring(0, 47) + '...'
145
+ : item.description;
146
+ console.log(chalk.gray(` ${displayDesc}`));
147
+ }
148
+ console.log('');
149
+ }
150
+
151
+ if (results.length > 20) {
152
+ console.log(chalk.gray(` ... and ${results.length - 20} more\n`));
153
+ }
154
+ }
155
+
156
+ /**
157
+ * Re-run a command from history
158
+ */
159
+ async function runFromHistory(index) {
160
+ const item = await getHistoryItem(parseInt(index));
161
+
162
+ if (!item) {
163
+ console.log(chalk.red(`\n ❌ History item #${index} not found.\n`));
164
+ return;
165
+ }
166
+
167
+ console.log(chalk.cyan(`\n 🔄 Re-running command:\n`));
168
+ console.log(chalk.white(` ${item.command}\n`));
169
+
170
+ if (item.description) {
171
+ console.log(chalk.gray(` ${item.description}\n`));
172
+ }
173
+
174
+ const { confirm } = await inquirer.prompt([{
175
+ type: 'confirm',
176
+ name: 'confirm',
177
+ message: 'Execute this command?',
178
+ default: true
179
+ }]);
180
+
181
+ if (!confirm) {
182
+ console.log(chalk.gray('\n Cancelled.\n'));
183
+ return;
184
+ }
185
+
186
+ console.log(chalk.cyan('\n Executing...\n'));
187
+
188
+ const child = spawn('sh', ['-c', item.command], {
189
+ stdio: 'inherit',
190
+ cwd: process.cwd(),
191
+ shell: true
192
+ });
193
+
194
+ child.on('close', (code) => {
195
+ if (code === 0) {
196
+ console.log(chalk.green('\n ✅ Command completed successfully\n'));
197
+ } else {
198
+ console.log(chalk.yellow(`\n ⚠️ Command exited with code ${code}\n`));
199
+ }
200
+ });
201
+
202
+ child.on('error', (error) => {
203
+ console.log(chalk.red(`\n ❌ Error: ${error.message}\n`));
204
+ });
205
+ }
206
+
207
+ /**
208
+ * Show history statistics
209
+ */
210
+ async function showHistoryStats() {
211
+ const stats = await getHistoryStats();
212
+ const history = await loadHistory();
213
+
214
+ console.log(chalk.cyan(`
215
+ ╭────────────────────────────────────────────────────────────────────╮
216
+ │ 📊 HISTORY STATISTICS │
217
+ ╰────────────────────────────────────────────────────────────────────╯
218
+ `));
219
+
220
+ console.log(chalk.white(` Total commands: ${stats.total}`));
221
+
222
+ if (stats.oldest) {
223
+ console.log(chalk.gray(` Oldest: ${new Date(stats.oldest).toLocaleString()}`));
224
+ }
225
+
226
+ if (stats.newest) {
227
+ console.log(chalk.gray(` Newest: ${new Date(stats.newest).toLocaleString()}`));
228
+ }
229
+
230
+ // Count command types
231
+ if (history.length > 0) {
232
+ const types = {};
233
+ for (const item of history) {
234
+ const cmd = item.command.split(' ')[1] || 'other';
235
+ types[cmd] = (types[cmd] || 0) + 1;
236
+ }
237
+
238
+ console.log(chalk.white('\n Command breakdown:'));
239
+ const sorted = Object.entries(types).sort((a, b) => b[1] - a[1]);
240
+ for (const [cmd, count] of sorted.slice(0, 5)) {
241
+ const bar = '█'.repeat(Math.min(count, 20));
242
+ console.log(chalk.gray(` ${cmd.padEnd(12)} ${chalk.cyan(bar)} ${count}`));
243
+ }
244
+ }
245
+
246
+ console.log('');
247
+ }
248
+
249
+ export default historyCommand;