vibecodingmachine-cli 2026.3.10-1812 ā 2026.3.14-1528
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/README.md +85 -85
- package/bin/vibecodingmachine.js +3 -0
- package/package.json +4 -3
- package/scripts/postinstall.js +161 -161
- package/src/commands/auth.js +100 -100
- package/src/commands/auto-direct.js +16 -5
- package/src/commands/auto-execution.js +25 -0
- package/src/commands/auto-requirement-management.js +8 -8
- package/src/commands/auto-status-helpers.js +5 -3
- package/src/commands/computers.js +318 -318
- package/src/commands/feature.js +123 -123
- package/src/commands/locale.js +72 -72
- package/src/commands/repo.js +163 -163
- package/src/commands/setup.js +93 -93
- package/src/commands/sync.js +287 -287
- package/src/index.js +5 -5
- package/src/utils/agent-selector.js +50 -50
- package/src/utils/asset-cleanup.js +60 -60
- package/src/utils/auto-mode-ansi-ui.js +237 -237
- package/src/utils/auto-mode-simple-ui.js +141 -141
- package/src/utils/copy-with-progress.js +167 -167
- package/src/utils/download-with-progress.js +84 -84
- package/src/utils/keyboard-handler.js +153 -153
- package/src/utils/kiro-installer.js +178 -178
- package/src/utils/logger.js +4 -4
- package/src/utils/persistent-header.js +114 -114
- package/src/utils/prompt-helper.js +63 -63
- package/src/utils/provider-checker/agent-checker.js +25 -1
- package/src/utils/provider-checker/agent-runner.js +115 -37
- package/src/utils/provider-checker/agents-manager.js +210 -0
- package/src/utils/provider-checker/provider-validator.js +5 -49
- package/src/utils/provider-checker/requirements-manager.js +86 -65
- package/src/utils/provider-checker/test-requirements.js +25 -17
- package/src/utils/status-card.js +121 -121
- package/src/utils/stdout-interceptor.js +127 -127
- package/src/utils/user-tracking.js +299 -299
package/src/commands/auth.js
CHANGED
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
const chalk = require('chalk');
|
|
2
|
-
const auth = require('../utils/auth');
|
|
3
|
-
const { t, errorReporter } = require('vibecodingmachine-core');
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* Login command
|
|
7
|
-
* @param {Object} options - Command options
|
|
8
|
-
* @param {boolean} options.headless - Force headless mode (manual URL paste)
|
|
9
|
-
*/
|
|
10
|
-
async function login(options = {}) {
|
|
11
|
-
try {
|
|
12
|
-
// Check if already authenticated
|
|
13
|
-
const isAuth = await auth.isAuthenticated();
|
|
14
|
-
if (isAuth) {
|
|
15
|
-
const profile = await auth.getUserProfile();
|
|
16
|
-
console.log(chalk.green(`\nā ${t('auth.login.already', { email: chalk.bold(profile.email) })}`));
|
|
17
|
-
return;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
// Start login flow (auto-detects headless or use explicit flag)
|
|
21
|
-
const result = await auth.login({ headless: options.headless });
|
|
22
|
-
|
|
23
|
-
// After successful authentication, start interactive mode
|
|
24
|
-
if (result) {
|
|
25
|
-
console.log(chalk.cyan(`\nš ${t('auth.starting.interactive')}\n`));
|
|
26
|
-
const { startInteractive } = require('../utils/interactive');
|
|
27
|
-
await startInteractive();
|
|
28
|
-
}
|
|
29
|
-
} catch (error) {
|
|
30
|
-
console.error(chalk.red(`\nā ${t('auth.login.failed')}:`), error.message);
|
|
31
|
-
await errorReporter.reportError(error, {
|
|
32
|
-
command: 'auth:login',
|
|
33
|
-
headless: options.headless
|
|
34
|
-
});
|
|
35
|
-
process.exit(1);
|
|
36
|
-
}
|
|
37
|
-
}
|
|
38
|
-
|
|
39
|
-
/**
|
|
40
|
-
* Logout command
|
|
41
|
-
*/
|
|
42
|
-
async function logout() {
|
|
43
|
-
try {
|
|
44
|
-
await auth.logout();
|
|
45
|
-
console.log(chalk.green(`\nā ${t('auth.logout.success')}`));
|
|
46
|
-
} catch (error) {
|
|
47
|
-
console.error(chalk.red(`\nā ${t('auth.logout.failed')}:`), error.message);
|
|
48
|
-
process.exit(1);
|
|
49
|
-
}
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
/**
|
|
53
|
-
* Status command
|
|
54
|
-
*/
|
|
55
|
-
async function status() {
|
|
56
|
-
try {
|
|
57
|
-
const isAuth = await auth.isAuthenticated();
|
|
58
|
-
|
|
59
|
-
if (!isAuth) {
|
|
60
|
-
console.log(chalk.yellow(`\n${t('auth.not.authenticated')}`));
|
|
61
|
-
console.log(t('auth.run.login', { command: chalk.cyan('vcm auth:login') }));
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
const profile = await auth.getUserProfile();
|
|
66
|
-
|
|
67
|
-
// Get usage stats
|
|
68
|
-
const canRun = await auth.canRunAutoMode();
|
|
69
|
-
|
|
70
|
-
console.log(chalk.bold(`\nš¤ ${t('profile.name')}:`));
|
|
71
|
-
console.log(` ${t('profile.name')}: ${profile.name}`);
|
|
72
|
-
console.log(` ${t('profile.email')}: ${profile.email}`);
|
|
73
|
-
console.log(` ${t('profile.tier')}: ${profile.tier === 'premium' ? chalk.green(t('profile.tier.premium')) : t('profile.tier.free')}`);
|
|
74
|
-
|
|
75
|
-
console.log(chalk.bold(`\nš ${t('profile.usage')}:`));
|
|
76
|
-
if (canRun.features && canRun.features.unlimitedIterations) {
|
|
77
|
-
console.log(` ${t('profile.daily.usage')}: ${canRun.todayUsage} ${t('profile.iterations')}`);
|
|
78
|
-
console.log(` ${t('profile.limit')}: ${chalk.green(t('profile.unlimited'))}`);
|
|
79
|
-
} else {
|
|
80
|
-
const limitColor = canRun.todayUsage >= canRun.maxIterations ? chalk.red : chalk.green;
|
|
81
|
-
console.log(` ${t('profile.daily.usage')}: ${limitColor(`${canRun.todayUsage}/${canRun.maxIterations}`)} ${t('profile.iterations')}`);
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
if (!canRun.canRun) {
|
|
85
|
-
console.log(chalk.red(`\nā ļø ${t('quota.exceeded.warning', { reason: canRun.reason })}`));
|
|
86
|
-
if (profile.tier !== 'premium') {
|
|
87
|
-
console.log(chalk.gray(t('profile.upgrade.suggestion')));
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
} catch (error) {
|
|
92
|
-
console.error(chalk.red(`\nā ${t('status.check.failed')}:`), error.message);
|
|
93
|
-
}
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
module.exports = {
|
|
97
|
-
login,
|
|
98
|
-
logout,
|
|
99
|
-
status
|
|
100
|
-
};
|
|
1
|
+
const chalk = require('chalk');
|
|
2
|
+
const auth = require('../utils/auth');
|
|
3
|
+
const { t, errorReporter } = require('vibecodingmachine-core');
|
|
4
|
+
|
|
5
|
+
/**
|
|
6
|
+
* Login command
|
|
7
|
+
* @param {Object} options - Command options
|
|
8
|
+
* @param {boolean} options.headless - Force headless mode (manual URL paste)
|
|
9
|
+
*/
|
|
10
|
+
async function login(options = {}) {
|
|
11
|
+
try {
|
|
12
|
+
// Check if already authenticated
|
|
13
|
+
const isAuth = await auth.isAuthenticated();
|
|
14
|
+
if (isAuth) {
|
|
15
|
+
const profile = await auth.getUserProfile();
|
|
16
|
+
console.log(chalk.green(`\nā ${t('auth.login.already', { email: chalk.bold(profile.email) })}`));
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
// Start login flow (auto-detects headless or use explicit flag)
|
|
21
|
+
const result = await auth.login({ headless: options.headless });
|
|
22
|
+
|
|
23
|
+
// After successful authentication, start interactive mode
|
|
24
|
+
if (result) {
|
|
25
|
+
console.log(chalk.cyan(`\nš ${t('auth.starting.interactive')}\n`));
|
|
26
|
+
const { startInteractive } = require('../utils/interactive');
|
|
27
|
+
await startInteractive();
|
|
28
|
+
}
|
|
29
|
+
} catch (error) {
|
|
30
|
+
console.error(chalk.red(`\nā ${t('auth.login.failed')}:`), error.message);
|
|
31
|
+
await errorReporter.reportError(error, {
|
|
32
|
+
command: 'auth:login',
|
|
33
|
+
headless: options.headless
|
|
34
|
+
});
|
|
35
|
+
process.exit(1);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* Logout command
|
|
41
|
+
*/
|
|
42
|
+
async function logout() {
|
|
43
|
+
try {
|
|
44
|
+
await auth.logout();
|
|
45
|
+
console.log(chalk.green(`\nā ${t('auth.logout.success')}`));
|
|
46
|
+
} catch (error) {
|
|
47
|
+
console.error(chalk.red(`\nā ${t('auth.logout.failed')}:`), error.message);
|
|
48
|
+
process.exit(1);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* Status command
|
|
54
|
+
*/
|
|
55
|
+
async function status() {
|
|
56
|
+
try {
|
|
57
|
+
const isAuth = await auth.isAuthenticated();
|
|
58
|
+
|
|
59
|
+
if (!isAuth) {
|
|
60
|
+
console.log(chalk.yellow(`\n${t('auth.not.authenticated')}`));
|
|
61
|
+
console.log(t('auth.run.login', { command: chalk.cyan('vcm auth:login') }));
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const profile = await auth.getUserProfile();
|
|
66
|
+
|
|
67
|
+
// Get usage stats
|
|
68
|
+
const canRun = await auth.canRunAutoMode();
|
|
69
|
+
|
|
70
|
+
console.log(chalk.bold(`\nš¤ ${t('profile.name')}:`));
|
|
71
|
+
console.log(` ${t('profile.name')}: ${profile.name}`);
|
|
72
|
+
console.log(` ${t('profile.email')}: ${profile.email}`);
|
|
73
|
+
console.log(` ${t('profile.tier')}: ${profile.tier === 'premium' ? chalk.green(t('profile.tier.premium')) : t('profile.tier.free')}`);
|
|
74
|
+
|
|
75
|
+
console.log(chalk.bold(`\nš ${t('profile.usage')}:`));
|
|
76
|
+
if (canRun.features && canRun.features.unlimitedIterations) {
|
|
77
|
+
console.log(` ${t('profile.daily.usage')}: ${canRun.todayUsage} ${t('profile.iterations')}`);
|
|
78
|
+
console.log(` ${t('profile.limit')}: ${chalk.green(t('profile.unlimited'))}`);
|
|
79
|
+
} else {
|
|
80
|
+
const limitColor = canRun.todayUsage >= canRun.maxIterations ? chalk.red : chalk.green;
|
|
81
|
+
console.log(` ${t('profile.daily.usage')}: ${limitColor(`${canRun.todayUsage}/${canRun.maxIterations}`)} ${t('profile.iterations')}`);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (!canRun.canRun) {
|
|
85
|
+
console.log(chalk.red(`\nā ļø ${t('quota.exceeded.warning', { reason: canRun.reason })}`));
|
|
86
|
+
if (profile.tier !== 'premium') {
|
|
87
|
+
console.log(chalk.gray(t('profile.upgrade.suggestion')));
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
} catch (error) {
|
|
92
|
+
console.error(chalk.red(`\nā ${t('status.check.failed')}:`), error.message);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
module.exports = {
|
|
97
|
+
login,
|
|
98
|
+
logout,
|
|
99
|
+
status
|
|
100
|
+
};
|
|
@@ -2771,14 +2771,25 @@ async function runSpecIdeIteration(spec, taskText, taskLine, providerConfig) {
|
|
|
2771
2771
|
instruction = `Read AGENTS.md and INSTRUCTIONS.md in the repo root for workflow guidelines. Read ${spec.path}/spec.md. ${planPromptNote}Run speckit workflow: (1) read spec.md, (2) generate plan.md, (3) generate tasks.md, (4) implement all tasks. Check off each task as you complete it. Report progress as "X/Y tasks (Z%) complete" after each task. When ALL tasks are done, create a status file at ${spec.path}/.vcm-status.json with content {"completion": 100, "status": "WAITING"} to signal completion to VCM.`;
|
|
2772
2772
|
}
|
|
2773
2773
|
|
|
2774
|
-
// Send the spec instruction to the IDE via
|
|
2775
|
-
// Uses the
|
|
2774
|
+
// Send the spec instruction to the IDE via platform-specific automation.
|
|
2775
|
+
// Uses the appropriate automation manager for the current platform.
|
|
2776
2776
|
console.log(chalk.cyan(`š¤ Sending spec instruction to ${providerConfig.displayName}...\n`));
|
|
2777
2777
|
|
|
2778
2778
|
if (ideType === 'windsurf') {
|
|
2779
2779
|
try {
|
|
2780
|
-
|
|
2781
|
-
|
|
2780
|
+
let sendResult;
|
|
2781
|
+
|
|
2782
|
+
// Use platform-specific automation
|
|
2783
|
+
if (process.platform === 'win32') {
|
|
2784
|
+
// Use Windows automation on Windows
|
|
2785
|
+
const { WindowsAutomationManager } = require('vibecodingmachine-core');
|
|
2786
|
+
const windowsManager = new WindowsAutomationManager();
|
|
2787
|
+
sendResult = await windowsManager.sendTextToWindsurf(instruction);
|
|
2788
|
+
} else {
|
|
2789
|
+
// Use AppleScript on macOS
|
|
2790
|
+
const appleScriptManager = new AppleScriptManager();
|
|
2791
|
+
sendResult = await appleScriptManager.sendText(instruction, 'windsurf');
|
|
2792
|
+
}
|
|
2782
2793
|
|
|
2783
2794
|
if (sendResult && sendResult.success) {
|
|
2784
2795
|
console.log(chalk.green(`ā Spec instruction sent to ${providerConfig.displayName}`));
|
|
@@ -2789,7 +2800,7 @@ async function runSpecIdeIteration(spec, taskText, taskLine, providerConfig) {
|
|
|
2789
2800
|
return { success: false, error: sendResult?.error || 'Unknown error' };
|
|
2790
2801
|
}
|
|
2791
2802
|
} catch (err) {
|
|
2792
|
-
console.log(chalk.red(`ā
|
|
2803
|
+
console.log(chalk.red(`ā Automation error: ${err.message}`));
|
|
2793
2804
|
return { success: false, error: err.message };
|
|
2794
2805
|
}
|
|
2795
2806
|
} else {
|
|
@@ -307,10 +307,29 @@ async function executeCreateStage(repoPath, currentTitle) {
|
|
|
307
307
|
}
|
|
308
308
|
|
|
309
309
|
// Send to IDE using Windows automation
|
|
310
|
+
console.log(chalk.cyan('š Text being sent to IDE:'));
|
|
311
|
+
console.log(chalk.gray('='.repeat(60)));
|
|
312
|
+
console.log(requirementText.trim());
|
|
313
|
+
console.log(chalk.gray('='.repeat(60)));
|
|
314
|
+
|
|
310
315
|
try {
|
|
311
316
|
const { WindowsAutomationManager } = require('vibecodingmachine-core');
|
|
312
317
|
const manager = new WindowsAutomationManager();
|
|
313
318
|
const result = await manager.sendTextToWindsurf(requirementText.trim());
|
|
319
|
+
|
|
320
|
+
// Check for rate limit
|
|
321
|
+
if (result.rateLimited) {
|
|
322
|
+
console.log(chalk.yellow(`ā ļø Rate limit detected!`));
|
|
323
|
+
console.log(chalk.yellow(`ā° Cascade will reset in: ${result.resetTime}`));
|
|
324
|
+
console.log(chalk.yellow(`š” Please wait and try again after the rate limit resets.`));
|
|
325
|
+
return {
|
|
326
|
+
success: false,
|
|
327
|
+
rateLimited: true,
|
|
328
|
+
resetTime: result.resetTime,
|
|
329
|
+
error: `Windsurf Cascade rate limit reached. Resets in: ${result.resetTime}`
|
|
330
|
+
};
|
|
331
|
+
}
|
|
332
|
+
|
|
314
333
|
console.log(chalk.green(`ā
Sent to IDE: ${result.success ? 'success' : 'failed'}`));
|
|
315
334
|
} catch (error) {
|
|
316
335
|
console.error(chalk.red(`ā Failed to send to IDE: ${error.message}`));
|
|
@@ -318,6 +337,12 @@ async function executeCreateStage(repoPath, currentTitle) {
|
|
|
318
337
|
|
|
319
338
|
// Give IDE time to process
|
|
320
339
|
await new Promise(resolve => setTimeout(resolve, 5000));
|
|
340
|
+
|
|
341
|
+
// CRITICAL: In IDE check mode, DO NOT auto-progress to CLEAN_UP
|
|
342
|
+
// We must wait for manual [DONE] detection from the IDE agent
|
|
343
|
+
console.log(chalk.blue('ā³ Waiting for IDE to update status to [DONE]...'));
|
|
344
|
+
console.log(chalk.gray(' The agent-runner will watch for status changes'));
|
|
345
|
+
return { success: true, stopAutoProgression: true };
|
|
321
346
|
} else {
|
|
322
347
|
// This would integrate with the AI provider to implement the requirement
|
|
323
348
|
// For now, we'll simulate the implementation
|
|
@@ -65,29 +65,29 @@ async function getCurrentRequirementDetails(repoPath) {
|
|
|
65
65
|
const content = await fs.readFile(reqPath, 'utf8');
|
|
66
66
|
const lines = content.split('\n');
|
|
67
67
|
|
|
68
|
-
// Find the "
|
|
69
|
-
let
|
|
68
|
+
// Find the "## Requirements" section (first item is current in-progress)
|
|
69
|
+
let requirementsSectionIndex = -1;
|
|
70
70
|
for (let i = 0; i < lines.length; i++) {
|
|
71
|
-
if (lines[i].includes('
|
|
72
|
-
|
|
71
|
+
if (lines[i].includes('## Requirements')) {
|
|
72
|
+
requirementsSectionIndex = i;
|
|
73
73
|
break;
|
|
74
74
|
}
|
|
75
75
|
}
|
|
76
76
|
|
|
77
|
-
if (
|
|
77
|
+
if (requirementsSectionIndex === -1) {
|
|
78
78
|
return { title: 'No current requirement found', status: 'UNKNOWN' };
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
// Look for the first requirement after the section header (current in-progress item)
|
|
82
|
-
for (let i =
|
|
82
|
+
for (let i = requirementsSectionIndex + 1; i < lines.length; i++) {
|
|
83
83
|
const line = lines[i].trim();
|
|
84
84
|
if (line.startsWith('- ')) {
|
|
85
85
|
const title = line.substring(2).trim();
|
|
86
86
|
|
|
87
|
-
// Look for status in the next few lines
|
|
87
|
+
// Look for status in the next few lines (supports both formats)
|
|
88
88
|
let status = 'UNKNOWN';
|
|
89
89
|
for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
|
|
90
|
-
if (lines[j].includes('š¦ Current Status')) {
|
|
90
|
+
if (lines[j].includes('š¦ Status:') || lines[j].includes('š¦ Current Status:')) {
|
|
91
91
|
const statusMatch = lines[j].match(/\[([A-Z_]+)\]/);
|
|
92
92
|
if (statusMatch) {
|
|
93
93
|
status = statusMatch[1];
|
|
@@ -80,11 +80,13 @@ async function updateRequirementsStatus(repoPath, newStatus, responseText) {
|
|
|
80
80
|
let content = await fs.readFile(reqPath, 'utf8');
|
|
81
81
|
const lines = content.split('\n');
|
|
82
82
|
|
|
83
|
-
// Find the status line and update it
|
|
83
|
+
// Find the status line and update it (supports both old and new formats)
|
|
84
84
|
let statusUpdated = false;
|
|
85
85
|
for (let i = 0; i < lines.length; i++) {
|
|
86
|
-
if (lines[i].includes('š¦ Current Status')) {
|
|
87
|
-
|
|
86
|
+
if (lines[i].includes('š¦ Status:') || lines[i].includes('š¦ Current Status:')) {
|
|
87
|
+
// Use the same format that was found
|
|
88
|
+
const prefix = lines[i].includes('š¦ Status:') ? 'š¦ Status:' : 'š¦ Current Status:';
|
|
89
|
+
lines[i] = `${prefix} [${newStatus}]`;
|
|
88
90
|
statusUpdated = true;
|
|
89
91
|
break;
|
|
90
92
|
}
|