vibecodingmachine-cli 2025.12.6-1702 → 2025.12.24-2348
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/vibecodingmachine.js +260 -52
- package/logs/audit/2025-12-24.jsonl +2 -0
- package/package.json +2 -2
- package/reproduce_issue.js +160 -0
- package/src/commands/auth.js +19 -19
- package/src/commands/auto-direct.js +133 -93
- package/src/commands/auto.js +165 -67
- package/src/commands/computers.js +62 -59
- package/src/commands/locale.js +73 -0
- package/src/commands/repo.js +0 -1
- package/src/commands/requirements-remote.js +14 -9
- package/src/commands/requirements.js +29 -3
- package/src/commands/setup.js +14 -13
- package/src/commands/status.js +17 -18
- package/src/commands/sync.js +72 -71
- package/src/utils/agent-selector.js +50 -0
- package/src/utils/antigravity-installer.js +212 -0
- package/src/utils/antigravity-js-handler.js +60 -0
- package/src/utils/asset-cleanup.js +0 -1
- package/src/utils/auth.js +149 -2
- package/src/utils/auto-mode-ansi-ui.js +0 -1
- package/src/utils/auto-mode-simple-ui.js +1 -1
- package/src/utils/compliance-check.js +166 -0
- package/src/utils/config.js +27 -1
- package/src/utils/copy-with-progress.js +167 -0
- package/src/utils/download-with-progress.js +84 -0
- package/src/utils/first-run.js +189 -71
- package/src/utils/interactive.js +419 -362
- package/src/utils/kiro-installer.js +56 -24
- package/src/utils/persistent-header.js +1 -3
- package/src/utils/provider-registry.js +43 -5
- package/src/utils/user-tracking.js +300 -0
- package/tests/requirements-navigator-buildtree-await.test.js +28 -0
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const Table = require('cli-table3');
|
|
3
3
|
const SyncEngine = require('vibecodingmachine-core/src/sync/sync-engine');
|
|
4
|
+
const { t } = require('vibecodingmachine-core');
|
|
4
5
|
|
|
5
6
|
/**
|
|
6
7
|
* Display all registered computers with their status
|
|
@@ -15,8 +16,8 @@ async function listComputers(options = {}) {
|
|
|
15
16
|
const computers = await fetchAllComputers(syncEngine);
|
|
16
17
|
|
|
17
18
|
if (computers.length === 0) {
|
|
18
|
-
console.log(chalk.yellow('
|
|
19
|
-
console.log(chalk.gray('
|
|
19
|
+
console.log(chalk.yellow(`\n${t('computers.no.computers')}\n`));
|
|
20
|
+
console.log(chalk.gray(`${t('computers.will.appear')}\n`));
|
|
20
21
|
return;
|
|
21
22
|
}
|
|
22
23
|
|
|
@@ -38,12 +39,12 @@ async function listComputers(options = {}) {
|
|
|
38
39
|
// Create table
|
|
39
40
|
const table = new Table({
|
|
40
41
|
head: [
|
|
41
|
-
chalk.cyan('
|
|
42
|
-
chalk.cyan('
|
|
43
|
-
chalk.cyan('
|
|
44
|
-
chalk.cyan('
|
|
45
|
-
chalk.cyan('
|
|
46
|
-
chalk.cyan('
|
|
42
|
+
chalk.cyan(t('computers.table.computer')),
|
|
43
|
+
chalk.cyan(t('computers.table.focus')),
|
|
44
|
+
chalk.cyan(t('computers.table.status')),
|
|
45
|
+
chalk.cyan(t('computers.table.requirement')),
|
|
46
|
+
chalk.cyan(t('computers.table.progress')),
|
|
47
|
+
chalk.cyan(t('computers.table.last.sync'))
|
|
47
48
|
],
|
|
48
49
|
colWidths: [25, 30, 12, 35, 10, 15]
|
|
49
50
|
});
|
|
@@ -51,11 +52,12 @@ async function listComputers(options = {}) {
|
|
|
51
52
|
// Add rows
|
|
52
53
|
for (const computer of filteredComputers) {
|
|
53
54
|
const statusIcon = getStatusIcon(computer.status);
|
|
54
|
-
const
|
|
55
|
+
const statusKey = `computers.status.${computer.status || 'unknown'}`;
|
|
56
|
+
const statusText = `${statusIcon} ${t(statusKey)}`;
|
|
55
57
|
const progress = computer.progress ? `${computer.progress}%` : '-';
|
|
56
|
-
const lastSync = computer.lastSyncTime
|
|
58
|
+
const lastSync = computer.lastSyncTime
|
|
57
59
|
? formatTimeSince(computer.lastSyncTime)
|
|
58
|
-
: 'never';
|
|
60
|
+
: t('computers.never');
|
|
59
61
|
|
|
60
62
|
table.push([
|
|
61
63
|
computer.hostname || computer.computerId,
|
|
@@ -73,17 +75,17 @@ async function listComputers(options = {}) {
|
|
|
73
75
|
const activeCount = computers.filter(c => c.status === 'active').length;
|
|
74
76
|
const idleCount = computers.filter(c => c.status === 'idle').length;
|
|
75
77
|
const errorCount = computers.filter(c => c.status === 'error').length;
|
|
76
|
-
|
|
77
|
-
console.log(chalk.gray(
|
|
78
|
-
console.log(chalk.green(`
|
|
79
|
-
console.log(chalk.yellow(`
|
|
78
|
+
|
|
79
|
+
console.log(chalk.gray(t('computers.total', { count: computers.length })));
|
|
80
|
+
console.log(chalk.green(` ${t('computers.active', { count: activeCount })}`));
|
|
81
|
+
console.log(chalk.yellow(` ${t('computers.idle', { count: idleCount })}`));
|
|
80
82
|
if (errorCount > 0) {
|
|
81
|
-
console.log(chalk.red(`
|
|
83
|
+
console.log(chalk.red(` ${t('computers.error', { count: errorCount })}`));
|
|
82
84
|
}
|
|
83
85
|
console.log('');
|
|
84
86
|
|
|
85
87
|
} catch (error) {
|
|
86
|
-
console.error(chalk.red(
|
|
88
|
+
console.error(chalk.red(`\n✗ ${t('computers.fetch.failed')}`), error.message);
|
|
87
89
|
throw error;
|
|
88
90
|
} finally {
|
|
89
91
|
syncEngine.stop();
|
|
@@ -93,7 +95,7 @@ async function listComputers(options = {}) {
|
|
|
93
95
|
/**
|
|
94
96
|
* Show detailed status of a specific computer
|
|
95
97
|
*/
|
|
96
|
-
async function showComputerStatus(computerId
|
|
98
|
+
async function showComputerStatus(computerId) {
|
|
97
99
|
const syncEngine = new SyncEngine();
|
|
98
100
|
|
|
99
101
|
try {
|
|
@@ -102,44 +104,45 @@ async function showComputerStatus(computerId, options = {}) {
|
|
|
102
104
|
const computer = await fetchComputer(syncEngine, computerId);
|
|
103
105
|
|
|
104
106
|
if (!computer) {
|
|
105
|
-
console.log(chalk.red(`\n✗
|
|
107
|
+
console.log(chalk.red(`\n✗ ${t('computers.not.found', { id: computerId })}\n`));
|
|
106
108
|
return;
|
|
107
109
|
}
|
|
108
110
|
|
|
109
111
|
// Display computer details
|
|
110
|
-
console.log('\n' + chalk.bold.cyan('
|
|
112
|
+
console.log('\n' + chalk.bold.cyan(t('computers.details.title')));
|
|
111
113
|
console.log(chalk.gray('─'.repeat(60)));
|
|
112
|
-
console.log(chalk.white('
|
|
113
|
-
console.log(chalk.white('
|
|
114
|
-
console.log(chalk.white('
|
|
115
|
-
console.log(chalk.white('
|
|
116
|
-
|
|
117
|
-
console.log(chalk.white('
|
|
114
|
+
console.log(chalk.white(t('computers.details.hostname').padEnd(17)) + (computer.hostname || computer.computerId));
|
|
115
|
+
console.log(chalk.white(t('computers.details.id').padEnd(17)) + computer.computerId);
|
|
116
|
+
console.log(chalk.white(t('computers.details.focus').padEnd(17)) + (computer.focusArea || '-'));
|
|
117
|
+
console.log(chalk.white(t('computers.details.os').padEnd(17)) + (computer.os || '-'));
|
|
118
|
+
const statusKey = `computers.status.${computer.status || 'unknown'}`;
|
|
119
|
+
console.log(chalk.white(t('computers.details.status').padEnd(17)) + getStatusIcon(computer.status) + ' ' + t(statusKey));
|
|
120
|
+
console.log(chalk.white(t('computers.details.last.sync').padEnd(17)) + (computer.lastSyncTime ? formatTimeSince(computer.lastSyncTime) : t('computers.never')));
|
|
118
121
|
console.log('');
|
|
119
122
|
|
|
120
123
|
// Current work
|
|
121
|
-
console.log(chalk.bold.cyan('
|
|
124
|
+
console.log(chalk.bold.cyan(t('computers.work.title')));
|
|
122
125
|
console.log(chalk.gray('─'.repeat(60)));
|
|
123
|
-
console.log(chalk.white('
|
|
124
|
-
console.log(chalk.white('
|
|
125
|
-
console.log(chalk.white('
|
|
126
|
-
console.log(chalk.white('
|
|
126
|
+
console.log(chalk.white(t('computers.work.requirement').padEnd(17)) + (computer.currentRequirement || t('computers.work.none')));
|
|
127
|
+
console.log(chalk.white(t('computers.work.progress').padEnd(17)) + (computer.progress ? `${computer.progress}%` : '-'));
|
|
128
|
+
console.log(chalk.white(t('computers.work.time.active').padEnd(17)) + (computer.timeActive || '-'));
|
|
129
|
+
console.log(chalk.white(t('computers.work.ide').padEnd(17)) + (computer.ide || '-'));
|
|
127
130
|
console.log('');
|
|
128
131
|
|
|
129
132
|
// Statistics
|
|
130
133
|
if (computer.stats) {
|
|
131
|
-
console.log(chalk.bold.cyan('
|
|
134
|
+
console.log(chalk.bold.cyan(t('computers.stats.title')));
|
|
132
135
|
console.log(chalk.gray('─'.repeat(60)));
|
|
133
|
-
console.log(chalk.white('
|
|
134
|
-
console.log(chalk.white('
|
|
135
|
-
console.log(chalk.white('
|
|
136
|
-
console.log(chalk.white('
|
|
137
|
-
console.log(chalk.white('
|
|
136
|
+
console.log(chalk.white(t('computers.stats.total').padEnd(21)) + (computer.stats.total || 0));
|
|
137
|
+
console.log(chalk.white(t('computers.stats.completed').padEnd(21)) + chalk.green(computer.stats.completed || 0));
|
|
138
|
+
console.log(chalk.white(t('computers.stats.in.progress').padEnd(21)) + chalk.yellow(computer.stats.inProgress || 0));
|
|
139
|
+
console.log(chalk.white(t('computers.stats.to.verify').padEnd(21)) + chalk.blue(computer.stats.toVerify || 0));
|
|
140
|
+
console.log(chalk.white(t('computers.stats.completion.rate').padEnd(21)) + (computer.stats.completionRate || '0%'));
|
|
138
141
|
console.log('');
|
|
139
142
|
}
|
|
140
143
|
|
|
141
144
|
} catch (error) {
|
|
142
|
-
console.error(chalk.red(
|
|
145
|
+
console.error(chalk.red(`\n✗ ${t('computers.status.fetch.failed')}`), error.message);
|
|
143
146
|
throw error;
|
|
144
147
|
} finally {
|
|
145
148
|
syncEngine.stop();
|
|
@@ -149,7 +152,7 @@ async function showComputerStatus(computerId, options = {}) {
|
|
|
149
152
|
/**
|
|
150
153
|
* Register current computer with focus area
|
|
151
154
|
*/
|
|
152
|
-
async function registerComputer(focusArea
|
|
155
|
+
async function registerComputer(focusArea) {
|
|
153
156
|
const syncEngine = new SyncEngine();
|
|
154
157
|
|
|
155
158
|
try {
|
|
@@ -167,15 +170,15 @@ async function registerComputer(focusArea, options = {}) {
|
|
|
167
170
|
};
|
|
168
171
|
|
|
169
172
|
await saveComputer(syncEngine, computerData);
|
|
170
|
-
|
|
171
|
-
console.log(chalk.green(
|
|
172
|
-
console.log(chalk.white('
|
|
173
|
-
console.log(chalk.white('
|
|
174
|
-
console.log(chalk.white('
|
|
173
|
+
|
|
174
|
+
console.log(chalk.green(`\n✓ ${t('computers.register.success')}\n`));
|
|
175
|
+
console.log(chalk.white(t('computers.register.id').padEnd(14)) + computerData.computerId);
|
|
176
|
+
console.log(chalk.white(t('computers.register.hostname').padEnd(14)) + computerData.hostname);
|
|
177
|
+
console.log(chalk.white(t('computers.register.focus').padEnd(14)) + computerData.focusArea);
|
|
175
178
|
console.log('');
|
|
176
179
|
|
|
177
180
|
} catch (error) {
|
|
178
|
-
console.error(chalk.red(
|
|
181
|
+
console.error(chalk.red(`\n✗ ${t('computers.register.failed')}`), error.message);
|
|
179
182
|
throw error;
|
|
180
183
|
} finally {
|
|
181
184
|
syncEngine.stop();
|
|
@@ -185,7 +188,7 @@ async function registerComputer(focusArea, options = {}) {
|
|
|
185
188
|
/**
|
|
186
189
|
* Update focus area for current computer
|
|
187
190
|
*/
|
|
188
|
-
async function updateFocus(newFocusArea
|
|
191
|
+
async function updateFocus(newFocusArea) {
|
|
189
192
|
const syncEngine = new SyncEngine();
|
|
190
193
|
|
|
191
194
|
try {
|
|
@@ -194,8 +197,8 @@ async function updateFocus(newFocusArea, options = {}) {
|
|
|
194
197
|
const computer = await fetchComputer(syncEngine, syncEngine.computerId);
|
|
195
198
|
|
|
196
199
|
if (!computer) {
|
|
197
|
-
console.log(chalk.yellow(
|
|
198
|
-
await registerComputer(newFocusArea
|
|
200
|
+
console.log(chalk.yellow(`\n⚠ ${t('computers.not.registered')}\n`));
|
|
201
|
+
await registerComputer(newFocusArea);
|
|
199
202
|
return;
|
|
200
203
|
}
|
|
201
204
|
|
|
@@ -203,14 +206,14 @@ async function updateFocus(newFocusArea, options = {}) {
|
|
|
203
206
|
computer.lastSyncTime = Date.now();
|
|
204
207
|
|
|
205
208
|
await saveComputer(syncEngine, computer);
|
|
206
|
-
|
|
207
|
-
console.log(chalk.green(
|
|
208
|
-
console.log(chalk.white('
|
|
209
|
-
console.log(chalk.white('
|
|
209
|
+
|
|
210
|
+
console.log(chalk.green(`\n✓ ${t('computers.focus.updated')}\n`));
|
|
211
|
+
console.log(chalk.white(t('computers.focus.computer').padEnd(14)) + computer.hostname);
|
|
212
|
+
console.log(chalk.white(t('computers.focus.new').padEnd(14)) + newFocusArea);
|
|
210
213
|
console.log('');
|
|
211
214
|
|
|
212
215
|
} catch (error) {
|
|
213
|
-
console.error(chalk.red(
|
|
216
|
+
console.error(chalk.red(`\n✗ ${t('computers.focus.update.failed')}`), error.message);
|
|
214
217
|
throw error;
|
|
215
218
|
} finally {
|
|
216
219
|
syncEngine.stop();
|
|
@@ -232,16 +235,16 @@ function getStatusIcon(status) {
|
|
|
232
235
|
function formatTimeSince(timestamp) {
|
|
233
236
|
const now = Date.now();
|
|
234
237
|
const diff = now - timestamp;
|
|
235
|
-
|
|
238
|
+
|
|
236
239
|
const seconds = Math.floor(diff / 1000);
|
|
237
240
|
const minutes = Math.floor(seconds / 60);
|
|
238
241
|
const hours = Math.floor(minutes / 60);
|
|
239
242
|
const days = Math.floor(hours / 24);
|
|
240
|
-
|
|
241
|
-
if (days > 0) return
|
|
242
|
-
if (hours > 0) return
|
|
243
|
-
if (minutes > 0) return
|
|
244
|
-
return
|
|
243
|
+
|
|
244
|
+
if (days > 0) return t('computers.time.days.ago', { count: days });
|
|
245
|
+
if (hours > 0) return t('computers.time.hours.ago', { count: hours });
|
|
246
|
+
if (minutes > 0) return t('computers.time.minutes.ago', { count: minutes });
|
|
247
|
+
return t('computers.time.seconds.ago', { count: seconds });
|
|
245
248
|
}
|
|
246
249
|
|
|
247
250
|
function truncate(str, maxLength) {
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const { t, getCurrentLocale, setLocale, getAvailableLocales, detectLocale } = require('vibecodingmachine-core');
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Show current locale information
|
|
6
|
+
*/
|
|
7
|
+
async function show() {
|
|
8
|
+
const current = getCurrentLocale();
|
|
9
|
+
const detected = detectLocale();
|
|
10
|
+
const available = getAvailableLocales();
|
|
11
|
+
|
|
12
|
+
console.log(chalk.bold(`\n🌍 ${t('app.name')} - Locale Information`));
|
|
13
|
+
console.log(chalk.gray('Current locale:'), chalk.cyan(current));
|
|
14
|
+
console.log(chalk.gray('Detected locale:'), chalk.cyan(detected));
|
|
15
|
+
console.log(chalk.gray('Available locales:'), chalk.cyan(available.join(', ')));
|
|
16
|
+
|
|
17
|
+
// Test some translations
|
|
18
|
+
console.log(chalk.bold('\n📝 Sample Translations:'));
|
|
19
|
+
console.log(` ${t('auth.login')}`);
|
|
20
|
+
console.log(` ${t('status.title')}`);
|
|
21
|
+
console.log(` ${t('setup.title')}`);
|
|
22
|
+
console.log();
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Set locale
|
|
27
|
+
* @param {string} locale - Locale to set
|
|
28
|
+
*/
|
|
29
|
+
async function set(locale) {
|
|
30
|
+
const available = getAvailableLocales();
|
|
31
|
+
|
|
32
|
+
if (!available.includes(locale)) {
|
|
33
|
+
console.log(chalk.red(`\n✗ Unsupported locale: ${locale}`));
|
|
34
|
+
console.log(chalk.gray('Available locales:'), chalk.cyan(available.join(', ')));
|
|
35
|
+
return;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
setLocale(locale);
|
|
39
|
+
console.log(chalk.green(`\n✓ Locale set to: ${chalk.cyan(locale)}`));
|
|
40
|
+
|
|
41
|
+
// Show sample translation
|
|
42
|
+
console.log(chalk.gray('Sample:'), t('app.name'));
|
|
43
|
+
console.log();
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
/**
|
|
47
|
+
* Test locale detection and translations
|
|
48
|
+
*/
|
|
49
|
+
async function test() {
|
|
50
|
+
console.log(chalk.bold(`\n🧪 Testing Locale System`));
|
|
51
|
+
|
|
52
|
+
const available = getAvailableLocales();
|
|
53
|
+
|
|
54
|
+
for (const locale of available) {
|
|
55
|
+
console.log(chalk.bold(`\n--- ${locale.toUpperCase()} ---`));
|
|
56
|
+
setLocale(locale);
|
|
57
|
+
|
|
58
|
+
console.log(`${t('app.name')}`);
|
|
59
|
+
console.log(`${t('auth.login')}`);
|
|
60
|
+
console.log(`${t('status.title')}`);
|
|
61
|
+
console.log(`${t('setup.title')}`);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Reset to detected locale
|
|
65
|
+
setLocale(detectLocale());
|
|
66
|
+
console.log();
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = {
|
|
70
|
+
show,
|
|
71
|
+
set,
|
|
72
|
+
test
|
|
73
|
+
};
|
package/src/commands/repo.js
CHANGED
|
@@ -2,11 +2,12 @@ const chalk = require('chalk');
|
|
|
2
2
|
const fs = require('fs-extra');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const inquirer = require('inquirer');
|
|
5
|
+
const { t } = require('vibecodingmachine-core');
|
|
5
6
|
|
|
6
7
|
/**
|
|
7
8
|
* List requirements for a specific computer
|
|
8
9
|
*/
|
|
9
|
-
async function listRemoteRequirements(computerId
|
|
10
|
+
async function listRemoteRequirements(computerId) {
|
|
10
11
|
try {
|
|
11
12
|
const repoPath = process.cwd();
|
|
12
13
|
const reqFilename = `REQUIREMENTS-${computerId}.md`;
|
|
@@ -21,7 +22,7 @@ async function listRemoteRequirements(computerId, options = {}) {
|
|
|
21
22
|
const content = await fs.readFile(reqPath, 'utf8');
|
|
22
23
|
const sections = parseRequirements(content);
|
|
23
24
|
|
|
24
|
-
console.log(chalk.bold.cyan(`\n📋
|
|
25
|
+
console.log(chalk.bold.cyan(`\n📋 ${t('requirements.for.computer', { computerId })}\n`));
|
|
25
26
|
|
|
26
27
|
// Show counts
|
|
27
28
|
console.log(chalk.white('Summary:'));
|
|
@@ -60,7 +61,7 @@ async function listRemoteRequirements(computerId, options = {}) {
|
|
|
60
61
|
/**
|
|
61
62
|
* Add a requirement to another computer's requirements file
|
|
62
63
|
*/
|
|
63
|
-
async function addRemoteRequirement(computerId, requirementText
|
|
64
|
+
async function addRemoteRequirement(computerId, requirementText) {
|
|
64
65
|
try {
|
|
65
66
|
const repoPath = process.cwd();
|
|
66
67
|
const reqFilename = `REQUIREMENTS-${computerId}.md`;
|
|
@@ -168,9 +169,9 @@ async function manageRemoteRequirements(computerId) {
|
|
|
168
169
|
]);
|
|
169
170
|
|
|
170
171
|
switch (action) {
|
|
171
|
-
case 'view':
|
|
172
|
+
case 'view': {
|
|
172
173
|
await listRemoteRequirements(computerId);
|
|
173
|
-
console.log(chalk.gray('
|
|
174
|
+
console.log(chalk.gray(t('interactive.press.enter.continue')));
|
|
174
175
|
await new Promise(resolve => {
|
|
175
176
|
const readline = require('readline');
|
|
176
177
|
const rl = readline.createInterface({
|
|
@@ -184,8 +185,9 @@ async function manageRemoteRequirements(computerId) {
|
|
|
184
185
|
});
|
|
185
186
|
await manageRemoteRequirements(computerId);
|
|
186
187
|
break;
|
|
188
|
+
}
|
|
187
189
|
|
|
188
|
-
case 'add':
|
|
190
|
+
case 'add': {
|
|
189
191
|
const { requirement } = await inquirer.prompt([
|
|
190
192
|
{
|
|
191
193
|
type: 'input',
|
|
@@ -196,7 +198,7 @@ async function manageRemoteRequirements(computerId) {
|
|
|
196
198
|
|
|
197
199
|
if (requirement) {
|
|
198
200
|
await addRemoteRequirement(computerId, requirement);
|
|
199
|
-
console.log(chalk.gray('
|
|
201
|
+
console.log(chalk.gray(t('interactive.press.enter.continue')));
|
|
200
202
|
await new Promise(resolve => {
|
|
201
203
|
const readline = require('readline');
|
|
202
204
|
const rl = readline.createInterface({
|
|
@@ -211,8 +213,9 @@ async function manageRemoteRequirements(computerId) {
|
|
|
211
213
|
}
|
|
212
214
|
await manageRemoteRequirements(computerId);
|
|
213
215
|
break;
|
|
216
|
+
}
|
|
214
217
|
|
|
215
|
-
case 'edit':
|
|
218
|
+
case 'edit': {
|
|
216
219
|
const repoPath = process.cwd();
|
|
217
220
|
const reqFilename = `REQUIREMENTS-${computerId}.md`;
|
|
218
221
|
const reqPath = path.join(repoPath, '.vibecodingmachine', reqFilename);
|
|
@@ -237,9 +240,11 @@ async function manageRemoteRequirements(computerId) {
|
|
|
237
240
|
}
|
|
238
241
|
await manageRemoteRequirements(computerId);
|
|
239
242
|
break;
|
|
243
|
+
}
|
|
240
244
|
|
|
241
|
-
case 'back':
|
|
245
|
+
case 'back': {
|
|
242
246
|
break;
|
|
247
|
+
}
|
|
243
248
|
}
|
|
244
249
|
}
|
|
245
250
|
|
|
@@ -130,7 +130,7 @@ async function add(name, pkg, description) {
|
|
|
130
130
|
|
|
131
131
|
// Find the TODO section
|
|
132
132
|
const todoSectionHeader = '## ⏳ Requirements not yet completed';
|
|
133
|
-
if (!content.includes(
|
|
133
|
+
if (!content.includes('Requirements not yet completed')) {
|
|
134
134
|
content += '\n\n' + todoSectionHeader + '\n';
|
|
135
135
|
}
|
|
136
136
|
|
|
@@ -142,8 +142,8 @@ async function add(name, pkg, description) {
|
|
|
142
142
|
for (let i = 0; i < lines.length; i++) {
|
|
143
143
|
newLines.push(lines[i]);
|
|
144
144
|
|
|
145
|
-
// Insert right after the TODO section header
|
|
146
|
-
if (!inserted && lines[i].includes(
|
|
145
|
+
// Insert right after the TODO section header
|
|
146
|
+
if (!inserted && lines[i].startsWith('##') && lines[i].includes('Requirements not yet completed')) {
|
|
147
147
|
// Add requirement header
|
|
148
148
|
newLines.push(`### ${name}`);
|
|
149
149
|
|
|
@@ -338,10 +338,36 @@ async function rename(oldTitle, newTitle, description) {
|
|
|
338
338
|
}
|
|
339
339
|
}
|
|
340
340
|
|
|
341
|
+
async function working() {
|
|
342
|
+
try {
|
|
343
|
+
const { reqPath } = await getReqPathOrExit();
|
|
344
|
+
if (!await fs.pathExists(reqPath)) {
|
|
345
|
+
console.log(chalk.yellow('No REQUIREMENTS.md found.'));
|
|
346
|
+
return;
|
|
347
|
+
}
|
|
348
|
+
const { getCurrentRequirement } = require('vibecodingmachine-core');
|
|
349
|
+
// Note: Core's getCurrentRequirement returns "Working on: X" or default text.
|
|
350
|
+
// It assumes process.cwd() or similar.
|
|
351
|
+
// But wait, Core's getCurrentRequirement takes 'repoPath'.
|
|
352
|
+
// And imported from core index.cjs might need repoPath.
|
|
353
|
+
|
|
354
|
+
// Let's manually implement it to be safe and use getReqPathOrExit's resolved path
|
|
355
|
+
// OR use the core helper but pass the correct repo path.
|
|
356
|
+
const { repoPath } = await getReqPathOrExit();
|
|
357
|
+
const coreResult = await getCurrentRequirement(repoPath);
|
|
358
|
+
console.log(chalk.cyan(coreResult));
|
|
359
|
+
|
|
360
|
+
} catch (error) {
|
|
361
|
+
console.error(chalk.red('Error getting working requirement:'), error.message);
|
|
362
|
+
process.exit(1);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
|
|
341
366
|
module.exports = {
|
|
342
367
|
list,
|
|
343
368
|
add,
|
|
344
369
|
current,
|
|
370
|
+
working,
|
|
345
371
|
next,
|
|
346
372
|
edit,
|
|
347
373
|
watch,
|
package/src/commands/setup.js
CHANGED
|
@@ -3,9 +3,10 @@ const path = require('path');
|
|
|
3
3
|
const os = require('os');
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const inquirer = require('inquirer');
|
|
6
|
+
const { t } = require('vibecodingmachine-core');
|
|
6
7
|
|
|
7
8
|
async function setupAlias() {
|
|
8
|
-
console.log(chalk.bold.cyan(
|
|
9
|
+
console.log(chalk.bold.cyan(`\n🛠️ ${t('setup.alias.title')}\n`));
|
|
9
10
|
|
|
10
11
|
// Detect shell
|
|
11
12
|
const shell = process.env.SHELL;
|
|
@@ -29,14 +30,14 @@ async function setupAlias() {
|
|
|
29
30
|
shellName = 'fish';
|
|
30
31
|
configFile = path.join(os.homedir(), '.config', 'fish', 'config.fish');
|
|
31
32
|
} else {
|
|
32
|
-
console.log(chalk.yellow(`⚠️
|
|
33
|
-
console.log(chalk.gray('
|
|
34
|
-
console.log(chalk.cyan('
|
|
33
|
+
console.log(chalk.yellow(`⚠️ ${t('setup.shell.unsupported', { shell })}`));
|
|
34
|
+
console.log(chalk.gray(`${t('setup.manual.alias')}\n`));
|
|
35
|
+
console.log(chalk.cyan(` ${t('cli.alias.manual')}`));
|
|
35
36
|
return;
|
|
36
37
|
}
|
|
37
38
|
|
|
38
|
-
console.log(chalk.gray(
|
|
39
|
-
console.log(chalk.gray(
|
|
39
|
+
console.log(chalk.gray(t('setup.alias.detected', { shell: chalk.cyan(shellName) })));
|
|
40
|
+
console.log(chalk.gray(t('setup.alias.config', { file: chalk.cyan(configFile) })));
|
|
40
41
|
|
|
41
42
|
// Check if config file exists
|
|
42
43
|
if (!fs.existsSync(configFile)) {
|
|
@@ -56,7 +57,7 @@ async function setupAlias() {
|
|
|
56
57
|
|
|
57
58
|
// Check if alias already exists
|
|
58
59
|
if (content.includes('alias vcm="vibecodingmachine"') || content.includes("alias vcm='vibecodingmachine'")) {
|
|
59
|
-
console.log(chalk.green(
|
|
60
|
+
console.log(chalk.green(`\n✓ ${t('setup.alias.exists')}`));
|
|
60
61
|
return;
|
|
61
62
|
}
|
|
62
63
|
|
|
@@ -65,13 +66,13 @@ async function setupAlias() {
|
|
|
65
66
|
{
|
|
66
67
|
type: 'confirm',
|
|
67
68
|
name: 'confirm',
|
|
68
|
-
message:
|
|
69
|
+
message: t('setup.alias.confirm', { file: path.basename(configFile) }),
|
|
69
70
|
default: true
|
|
70
71
|
}
|
|
71
72
|
]);
|
|
72
73
|
|
|
73
74
|
if (!confirm) {
|
|
74
|
-
console.log(chalk.yellow('
|
|
75
|
+
console.log(chalk.yellow(`\n${t('setup.alias.cancelled')}`));
|
|
75
76
|
return;
|
|
76
77
|
}
|
|
77
78
|
|
|
@@ -80,11 +81,11 @@ async function setupAlias() {
|
|
|
80
81
|
|
|
81
82
|
try {
|
|
82
83
|
fs.appendFileSync(configFile, aliasCommand, 'utf8');
|
|
83
|
-
console.log(chalk.green(`\n✓
|
|
84
|
-
console.log(chalk.gray('
|
|
85
|
-
console.log(chalk.cyan(` source
|
|
84
|
+
console.log(chalk.green(`\n✓ ${t('setup.alias.added', { file: path.basename(configFile) })}`));
|
|
85
|
+
console.log(chalk.gray(`\n${t('setup.alias.restart')}`));
|
|
86
|
+
console.log(chalk.cyan(` ${t('setup.alias.source', { file: configFile })}`));
|
|
86
87
|
} catch (error) {
|
|
87
|
-
console.log(chalk.red(`\n✗
|
|
88
|
+
console.log(chalk.red(`\n✗ ${t('setup.alias.error', { error: error.message })}`));
|
|
88
89
|
}
|
|
89
90
|
}
|
|
90
91
|
|
package/src/commands/status.js
CHANGED
|
@@ -4,7 +4,7 @@ const os = require('os');
|
|
|
4
4
|
const chalk = require('chalk');
|
|
5
5
|
const { getRepoPath } = require('../utils/config');
|
|
6
6
|
const { checkAutoModeStatus } = require('../utils/auto-mode');
|
|
7
|
-
const { getRequirementsPath } = require('vibecodingmachine-core');
|
|
7
|
+
const { getRequirementsPath, t } = require('vibecodingmachine-core');
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
10
|
* Format IDE name for display
|
|
@@ -13,16 +13,16 @@ const { getRequirementsPath } = require('vibecodingmachine-core');
|
|
|
13
13
|
*/
|
|
14
14
|
function formatIDEName(ide) {
|
|
15
15
|
const ideNames = {
|
|
16
|
-
'cline': '
|
|
17
|
-
'cursor': '
|
|
18
|
-
'vscode': '
|
|
19
|
-
'windsurf': '
|
|
16
|
+
'cline': t('ide.cline'),
|
|
17
|
+
'cursor': t('ide.cursor'),
|
|
18
|
+
'vscode': t('ide.vscode'),
|
|
19
|
+
'windsurf': t('ide.windsurf')
|
|
20
20
|
};
|
|
21
21
|
return ideNames[ide] || ide;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
24
|
function formatPath(fullPath) {
|
|
25
|
-
if (!fullPath) return 'not
|
|
25
|
+
if (!fullPath) return t('status.not.set');
|
|
26
26
|
const homeDir = os.homedir();
|
|
27
27
|
if (fullPath.startsWith(homeDir)) {
|
|
28
28
|
return fullPath.replace(homeDir, '~');
|
|
@@ -32,13 +32,13 @@ function formatPath(fullPath) {
|
|
|
32
32
|
|
|
33
33
|
async function show() {
|
|
34
34
|
const repoPath = await getRepoPath();
|
|
35
|
-
console.log(chalk.bold('
|
|
36
|
-
console.log(chalk.gray('
|
|
35
|
+
console.log(chalk.bold(`\n${t('status.title')}`));
|
|
36
|
+
console.log(chalk.gray(`${t('status.repository')}:`), chalk.cyan(formatPath(repoPath)));
|
|
37
37
|
const status = await checkAutoModeStatus();
|
|
38
|
-
console.log(chalk.gray('
|
|
38
|
+
console.log(chalk.gray(`${t('status.auto.mode')}:`), status.running ? chalk.green(t('status.running')) : chalk.yellow(t('status.stopped')));
|
|
39
39
|
if (status.running) {
|
|
40
|
-
console.log(chalk.gray('
|
|
41
|
-
console.log(chalk.gray('
|
|
40
|
+
console.log(chalk.gray(`${t('status.ide')}:`), chalk.cyan(formatIDEName(status.ide || 'cline')));
|
|
41
|
+
console.log(chalk.gray(`${t('status.chats')}:`), chalk.cyan(status.chatCount || 0));
|
|
42
42
|
}
|
|
43
43
|
console.log();
|
|
44
44
|
}
|
|
@@ -46,30 +46,29 @@ async function show() {
|
|
|
46
46
|
async function progress() {
|
|
47
47
|
const repoPath = await getRepoPath();
|
|
48
48
|
if (!repoPath) {
|
|
49
|
-
console.log(chalk.yellow('
|
|
49
|
+
console.log(chalk.yellow(t('status.no.repo')));
|
|
50
50
|
return;
|
|
51
51
|
}
|
|
52
52
|
// Use getRequirementsPath to get the hostname-specific file
|
|
53
53
|
const reqPath = await getRequirementsPath(repoPath);
|
|
54
54
|
if (!reqPath || !await fs.pathExists(reqPath)) {
|
|
55
|
-
console.log(chalk.yellow('
|
|
55
|
+
console.log(chalk.yellow(t('status.no.requirements')));
|
|
56
56
|
return;
|
|
57
57
|
}
|
|
58
58
|
const content = await fs.readFile(reqPath, 'utf8');
|
|
59
59
|
const current = content.match(/## \uD83D\uDEA6 Current Status\n([A-Z_ ]+)/);
|
|
60
|
-
console.log(chalk.bold('
|
|
61
|
-
console.log(chalk.gray('
|
|
60
|
+
console.log(chalk.bold(`\n${t('status.progress')}`));
|
|
61
|
+
console.log(chalk.gray(`${t('status.current.status')}:`), chalk.cyan(current ? current[1] : t('status.unknown')));
|
|
62
62
|
console.log();
|
|
63
63
|
}
|
|
64
64
|
|
|
65
65
|
async function logs(cmd) {
|
|
66
66
|
const lines = parseInt((cmd && cmd.lines) || '50', 10);
|
|
67
|
-
const repoPath = await getRepoPath();
|
|
68
67
|
const defaultLog = path.join(process.cwd(), 'logs', 'security', 'security-2025-10-29.log');
|
|
69
68
|
const logPath = await fs.pathExists(defaultLog) ? defaultLog : null;
|
|
70
|
-
console.log(chalk.bold('
|
|
69
|
+
console.log(chalk.bold(`\n${t('logs.recent')}`));
|
|
71
70
|
if (!logPath) {
|
|
72
|
-
console.log(chalk.gray('
|
|
71
|
+
console.log(chalk.gray(t('logs.none')));
|
|
73
72
|
return;
|
|
74
73
|
}
|
|
75
74
|
const content = await fs.readFile(logPath, 'utf8');
|