vibecodingmachine-cli 2026.2.20-438 → 2026.2.26-1739
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/auth/auth-compliance.js +126 -0
- package/bin/cli-program.js +104 -0
- package/bin/cli-setup.js +52 -0
- package/bin/commands/agent-commands.js +310 -0
- package/bin/commands/auto-commands.js +70 -0
- package/bin/commands/command-aliases.js +118 -0
- package/bin/commands/repo-commands.js +39 -0
- package/bin/commands/rui-commands.js +152 -0
- package/bin/config/cli-config.js +394 -0
- package/bin/init/environment-setup.js +84 -0
- package/bin/update/update-checker.js +126 -0
- package/bin/vibecodingmachine-new.js +50 -0
- package/bin/vibecodingmachine.js +29 -663
- package/package.json +8 -2
- package/src/commands/agents/add.js +277 -0
- package/src/commands/agents/check.js +380 -0
- package/src/commands/agents/list.js +471 -0
- package/src/commands/agents/remove.js +351 -0
- package/src/commands/analyze-file-sizes.js +428 -0
- package/src/commands/auto-direct/code-processor.js +282 -0
- package/src/commands/auto-direct/file-scanner.js +266 -0
- package/src/commands/auto-direct/provider-config.js +178 -0
- package/src/commands/auto-direct/provider-manager.js +219 -0
- package/src/commands/auto-direct/requirement-manager.js +172 -0
- package/src/commands/auto-direct/status-display.js +91 -0
- package/src/commands/auto-direct/utils.js +106 -0
- package/src/commands/auto-direct.js +875 -488
- package/src/commands/auto-execution.js +342 -0
- package/src/commands/auto-provider-management.js +102 -0
- package/src/commands/auto-requirement-management.js +161 -0
- package/src/commands/auto-status-helpers.js +141 -0
- package/src/commands/auto.js +105 -5155
- package/src/commands/check-compliance.js +536 -0
- package/src/commands/continuous-scan.js +119 -0
- package/src/commands/ide.js +16 -4
- package/src/commands/refactor-file.js +486 -0
- package/src/commands/requirements.js +301 -2
- package/src/commands/timeout.js +290 -0
- package/src/trui/TruiInterface.js +108 -0
- package/src/trui/agents/AgentInterface.js +580 -0
- package/src/utils/antigravity-installer.js +60 -6
- package/src/utils/clarification-actions.js +290 -0
- package/src/utils/config.js +123 -2
- package/src/utils/first-run.js +5 -5
- package/src/utils/ide-handlers.js +212 -0
- package/src/utils/interactive/clarification-actions.js +348 -0
- package/src/utils/interactive/core-ui.js +265 -0
- package/src/utils/interactive/file-backup.js +237 -0
- package/src/utils/interactive/file-import-export.js +305 -0
- package/src/utils/interactive/file-operations.js +49 -0
- package/src/utils/interactive/file-validation.js +276 -0
- package/src/utils/interactive/interactive-prompts.js +480 -0
- package/src/utils/interactive/requirement-actions.js +127 -0
- package/src/utils/interactive/requirement-crud.js +356 -0
- package/src/utils/interactive/requirements-navigation.js +286 -0
- package/src/utils/interactive.js +390 -3459
- package/src/utils/provider-checker/agent-checker.js +250 -0
- package/src/utils/provider-checker/agent-runner.js +450 -0
- package/src/utils/provider-checker/cli-installer.js +123 -0
- package/src/utils/provider-checker/cli-utils.js +15 -0
- package/src/utils/provider-checker/format-utils.js +32 -0
- package/src/utils/provider-checker/ide-manager.js +72 -0
- package/src/utils/provider-checker/ide-utils.js +71 -0
- package/src/utils/provider-checker/node-detector.js +56 -0
- package/src/utils/provider-checker/node-utils.js +61 -0
- package/src/utils/provider-checker/process-spawn.js +22 -0
- package/src/utils/provider-checker/process-utils.js +37 -0
- package/src/utils/provider-checker/provider-validator.js +160 -0
- package/src/utils/provider-checker/quota-checker.js +54 -0
- package/src/utils/provider-checker/quota-detector.js +44 -0
- package/src/utils/provider-checker/requirements-manager.js +94 -0
- package/src/utils/provider-checker/test-requirements.js +95 -0
- package/src/utils/provider-checker/time-formatter.js +18 -0
- package/src/utils/provider-checker-new.js +14 -0
- package/src/utils/provider-checker.js +12 -407
- package/src/utils/provider-checkers/ide-manager.js +128 -0
- package/src/utils/provider-checkers/node-executable-finder.js +51 -0
- package/src/utils/provider-checkers/provider-checker-core.js +172 -0
- package/src/utils/provider-checkers/provider-checker-main.js +107 -0
- package/src/utils/provider-manager.js +60 -4
- package/src/utils/provider-registry.js +26 -3
- package/src/utils/provider-utils.js +173 -0
- package/src/utils/quota-detectors.js +212 -0
- package/src/utils/requirement-action-handlers.js +288 -0
- package/src/utils/requirement-actions/clarification-actions.js +229 -0
- package/src/utils/requirement-actions/confirmation-prompts.js +93 -0
- package/src/utils/requirement-actions/file-operations.js +92 -0
- package/src/utils/requirement-actions/helpers.js +40 -0
- package/src/utils/requirement-actions/requirement-operations.js +335 -0
- package/src/utils/requirement-actions.js +46 -856
- package/src/utils/requirement-file-operations.js +259 -0
- package/src/utils/requirement-helpers.js +128 -0
- package/src/utils/requirement-management.js +279 -0
- package/src/utils/requirement-navigation.js +146 -0
- package/src/utils/requirement-organization.js +271 -0
- package/src/utils/simple-trui.js +75 -1
- package/src/utils/trui-navigation.js +28 -2
- package/src/utils/trui-req-tree.js +196 -11
- package/src/utils/trui-specifications.js +31 -1
- package/src/utils/interactive-backup.js +0 -5664
- package/src/utils/trui-provider-manager.js +0 -182
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { spawn } = require('child_process');
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
const chokidar = require('chokidar');
|
|
7
|
+
const { getNodeExecutable } = require('./node-executable-finder');
|
|
8
|
+
const { isIdeInstalled, getIdeProcess, launchIde, IDE_INFO } = require('./ide-manager');
|
|
9
|
+
|
|
10
|
+
const CLI_ENTRY_POINT = path.resolve(path.join(__dirname, '../../../bin/vibecodingmachine.js'));
|
|
11
|
+
|
|
12
|
+
// Timeout constants
|
|
13
|
+
const DIRECT_TIMEOUT_MS = 60000; // 1 minute for direct providers
|
|
14
|
+
const IDE_TIMEOUT_MS = 300000; // 5 minutes for IDE providers
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Get result file path for provider check
|
|
18
|
+
*/
|
|
19
|
+
function getResultFilePath(repoPath) {
|
|
20
|
+
return path.join(repoPath, '.vibecodingmachine', 'agent-check-result.txt');
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* Remove test requirement file
|
|
25
|
+
*/
|
|
26
|
+
function removeTestRequirement(reqPath) {
|
|
27
|
+
if (fs.existsSync(reqPath)) {
|
|
28
|
+
let content = fs.readFileSync(reqPath, 'utf8');
|
|
29
|
+
// Remove the test requirement if it exists
|
|
30
|
+
content = content.replace(/^## 🚦 Current Status\n\nAGENT_CHECK[^\n]*\n\n?/gm, '');
|
|
31
|
+
fs.writeFileSync(reqPath, content);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Check if provider is reachable
|
|
37
|
+
*/
|
|
38
|
+
async function checkProviderReachable(providerId, config, repoPath) {
|
|
39
|
+
const def = config.providers[providerId];
|
|
40
|
+
if (!def) {
|
|
41
|
+
return { status: 'error', message: `Provider ${providerId} not found in config` };
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
const checkedAt = new Date().toISOString();
|
|
45
|
+
const resultFile = getResultFilePath(repoPath);
|
|
46
|
+
|
|
47
|
+
// For IDE providers, check if IDE is installed and running
|
|
48
|
+
if (def.type === 'ide') {
|
|
49
|
+
if (!isIdeInstalled(providerId)) {
|
|
50
|
+
return { status: 'error', message: `${IDE_INFO[providerId]?.app || providerId} is not installed`, checkedAt };
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const processInfo = getIdeProcess(providerId);
|
|
54
|
+
if (!processInfo) {
|
|
55
|
+
// Try to launch the IDE
|
|
56
|
+
const launched = await launchIde(providerId);
|
|
57
|
+
if (!launched) {
|
|
58
|
+
return { status: 'error', message: `${IDE_INFO[providerId]?.app || providerId} is not running and could not be launched`, checkedAt };
|
|
59
|
+
}
|
|
60
|
+
// Give IDE time to start
|
|
61
|
+
await new Promise(r => setTimeout(r, 5000));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return new Promise((resolve) => {
|
|
66
|
+
let resolved = false;
|
|
67
|
+
let child = null;
|
|
68
|
+
|
|
69
|
+
async function done(result) {
|
|
70
|
+
if (resolved) return;
|
|
71
|
+
resolved = true;
|
|
72
|
+
try {
|
|
73
|
+
if (watcher) watcher.close();
|
|
74
|
+
} catch {}
|
|
75
|
+
clearTimeout(timeout);
|
|
76
|
+
clearInterval(cancelCheckInterval);
|
|
77
|
+
try {
|
|
78
|
+
if (child) child.kill();
|
|
79
|
+
} catch {}
|
|
80
|
+
resolve(result);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function checkResult() {
|
|
84
|
+
if (!resolved && fs.existsSync(resultFile)) {
|
|
85
|
+
try {
|
|
86
|
+
const content = fs.readFileSync(resultFile, 'utf8');
|
|
87
|
+
if (content.includes('VCM_CHECK_OK')) {
|
|
88
|
+
done({ status: 'success', message: 'End-to-end check passed', checkedAt });
|
|
89
|
+
}
|
|
90
|
+
} catch {}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const watcher = chokidar.watch(resultFile, { persistent: true, ignoreInitial: false, disableGlobbing: true });
|
|
95
|
+
watcher.on('add', checkResult);
|
|
96
|
+
watcher.on('change', checkResult);
|
|
97
|
+
|
|
98
|
+
const timeout = setTimeout(() => {
|
|
99
|
+
let diagnosis = '';
|
|
100
|
+
if (def.type === 'ide') {
|
|
101
|
+
const info = IDE_INFO[providerId] || IDE_INFO[def.ide] || null;
|
|
102
|
+
const processInfo = getIdeProcess(providerId);
|
|
103
|
+
diagnosis = processInfo ? 'IDE is running but check timed out' : 'IDE process not found';
|
|
104
|
+
} else {
|
|
105
|
+
diagnosis = 'Provider check timed out';
|
|
106
|
+
}
|
|
107
|
+
done({ status: 'timeout', message: `Check timed out (${def.type === 'ide' ? '5min' : '1min'}). ${diagnosis}`, checkedAt });
|
|
108
|
+
}, def.type === 'ide' ? IDE_TIMEOUT_MS : DIRECT_TIMEOUT_MS);
|
|
109
|
+
|
|
110
|
+
const cancelCheckInterval = setInterval(() => {
|
|
111
|
+
if (resolved) return;
|
|
112
|
+
// Additional periodic checks can be added here
|
|
113
|
+
}, 10000);
|
|
114
|
+
|
|
115
|
+
// Prepare environment
|
|
116
|
+
const env = { ...process.env };
|
|
117
|
+
env.NODE_BINARY_PATH = getNodeExecutable();
|
|
118
|
+
if (repoPath) {
|
|
119
|
+
env.VCM_CHECK_REPO = repoPath;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Run the check
|
|
123
|
+
try {
|
|
124
|
+
const nodePath = getNodeExecutable();
|
|
125
|
+
const args = [CLI_ENTRY_POINT, 'check-provider', providerId];
|
|
126
|
+
|
|
127
|
+
child = spawn(nodePath, args, {
|
|
128
|
+
stdio: 'ignore',
|
|
129
|
+
env,
|
|
130
|
+
cwd: repoPath || process.cwd(),
|
|
131
|
+
detached: true
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
child.on('error', (error) => {
|
|
135
|
+
done({ status: 'error', message: `Failed to start check: ${error.message}`, checkedAt });
|
|
136
|
+
});
|
|
137
|
+
|
|
138
|
+
child.on('exit', (code, signal) => {
|
|
139
|
+
if (!resolved) {
|
|
140
|
+
if (signal === 'SIGTERM' || signal === 'SIGKILL') {
|
|
141
|
+
// Expected termination
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
144
|
+
if (code === 0) {
|
|
145
|
+
// Success, but we should have gotten the result via file
|
|
146
|
+
setTimeout(() => {
|
|
147
|
+
if (!resolved) {
|
|
148
|
+
checkResult();
|
|
149
|
+
if (!resolved) {
|
|
150
|
+
done({ status: 'partial', message: 'Check completed but no result file found', checkedAt });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, 2000);
|
|
154
|
+
} else {
|
|
155
|
+
done({ status: 'error', message: `Check failed with exit code ${code}`, checkedAt });
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
});
|
|
159
|
+
|
|
160
|
+
} catch (error) {
|
|
161
|
+
done({ status: 'error', message: `Failed to execute check: ${error.message}`, checkedAt });
|
|
162
|
+
}
|
|
163
|
+
});
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
module.exports = {
|
|
167
|
+
checkProviderReachable,
|
|
168
|
+
getResultFilePath,
|
|
169
|
+
removeTestRequirement,
|
|
170
|
+
DIRECT_TIMEOUT_MS,
|
|
171
|
+
IDE_TIMEOUT_MS
|
|
172
|
+
};
|
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
const { checkProviderReachable, getResultFilePath, removeTestRequirement } = require('./provider-checker-core');
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Check a single provider
|
|
9
|
+
*/
|
|
10
|
+
async function checkProvider(providerId, config, repoPath, onProgress, signal) {
|
|
11
|
+
if (signal?.aborted) {
|
|
12
|
+
return { status: 'skipped', message: 'Check aborted' };
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
try {
|
|
16
|
+
// Ensure .vibecodingmachine directory exists
|
|
17
|
+
if (repoPath) {
|
|
18
|
+
const vcmDir = path.join(repoPath, '.vibecodingmachine');
|
|
19
|
+
if (!fs.existsSync(vcmDir)) {
|
|
20
|
+
fs.mkdirSync(vcmDir, { recursive: true });
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Add test requirement
|
|
25
|
+
if (repoPath) {
|
|
26
|
+
const { getRequirementsPath } = require('vibecodingmachine-core');
|
|
27
|
+
let reqPath;
|
|
28
|
+
try {
|
|
29
|
+
reqPath = await getRequirementsPath(repoPath);
|
|
30
|
+
} catch {
|
|
31
|
+
reqPath = path.join(repoPath, '.vibecodingmachine', 'REQUIREMENTS.md');
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
if (fs.existsSync(reqPath)) {
|
|
35
|
+
const content = fs.readFileSync(reqPath, 'utf8');
|
|
36
|
+
if (!content.includes('AGENT_CHECK')) {
|
|
37
|
+
fs.appendFileSync(reqPath, '\n## 🚦 Current Status\n\nAGENT_CHECK - Provider connectivity check\n\n');
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Perform the check
|
|
43
|
+
const result = await checkProviderReachable(providerId, config, repoPath);
|
|
44
|
+
return result;
|
|
45
|
+
|
|
46
|
+
} catch (error) {
|
|
47
|
+
return {
|
|
48
|
+
status: 'error',
|
|
49
|
+
message: `Check failed: ${error.message}`,
|
|
50
|
+
error: error.stack
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Check all providers
|
|
57
|
+
*/
|
|
58
|
+
async function checkAllProviders(config, repoPath, onProgress, signal) {
|
|
59
|
+
const results = {};
|
|
60
|
+
const providerIds = Object.keys(config.providers || {});
|
|
61
|
+
|
|
62
|
+
for (const id of providerIds) {
|
|
63
|
+
if (signal?.aborted) break;
|
|
64
|
+
|
|
65
|
+
if (onProgress) onProgress(id, 'starting');
|
|
66
|
+
results[id] = await checkProvider(id, config, repoPath, onProgress, signal);
|
|
67
|
+
if (onProgress) onProgress(id, 'done', results[id]);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// Final cleanup — remove requirement if still pending (all agents failed or skipped)
|
|
71
|
+
if (repoPath) {
|
|
72
|
+
const { getRequirementsPath } = require('vibecodingmachine-core');
|
|
73
|
+
let reqPath;
|
|
74
|
+
try {
|
|
75
|
+
reqPath = await getRequirementsPath(repoPath);
|
|
76
|
+
} catch {
|
|
77
|
+
reqPath = path.join(repoPath, '.vibecodingmachine', 'REQUIREMENTS.md');
|
|
78
|
+
}
|
|
79
|
+
try {
|
|
80
|
+
removeTestRequirement(reqPath);
|
|
81
|
+
} catch {}
|
|
82
|
+
try {
|
|
83
|
+
fs.unlinkSync(getResultFilePath(repoPath));
|
|
84
|
+
} catch {}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
return results;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Format a checkedAt ISO timestamp for display.
|
|
92
|
+
* e.g. "April 12, 2025 at 4:23 pm"
|
|
93
|
+
*/
|
|
94
|
+
function formatCheckedAt(checkedAt) {
|
|
95
|
+
if (!checkedAt) return '';
|
|
96
|
+
const d = new Date(checkedAt);
|
|
97
|
+
if (isNaN(d.getTime())) return checkedAt;
|
|
98
|
+
const months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
|
|
99
|
+
const timePart = d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }).toLowerCase();
|
|
100
|
+
return `${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()} at ${timePart}`;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
module.exports = {
|
|
104
|
+
checkProvider,
|
|
105
|
+
checkAllProviders,
|
|
106
|
+
formatCheckedAt
|
|
107
|
+
};
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const chalk = require('chalk');
|
|
2
2
|
const readline = require('readline');
|
|
3
3
|
const { t } = require('vibecodingmachine-core');
|
|
4
|
-
const { getProviderDefinitions, getProviderPreferences, saveProviderPreferences, getProviderCache, setProviderCache } = require('../utils/provider-registry');
|
|
4
|
+
const { getProviderDefinitions, getProviderPreferences, saveProviderPreferences, getProviderCache, setProviderCache, getDefaultProviderOrder } = require('../utils/provider-registry');
|
|
5
5
|
const { checkVSCodeExtension, checkAppOrBinary } = require('./ide-detection');
|
|
6
6
|
const { formatIDEName, getAgentDisplayName } = require('./display-formatters');
|
|
7
7
|
const { IDEHealthTracker } = require('vibecodingmachine-core');
|
|
@@ -19,7 +19,7 @@ async function showProviderManagerMenu() {
|
|
|
19
19
|
const definitions = getProviderDefinitions();
|
|
20
20
|
const defMap = new Map(definitions.map(def => [def.id, def]));
|
|
21
21
|
const prefs = await getProviderPreferences();
|
|
22
|
-
let order = prefs.order.slice();
|
|
22
|
+
let order = Array.isArray(prefs.order) ? prefs.order.slice() : getDefaultProviderOrder();
|
|
23
23
|
let enabled = { ...prefs.enabled };
|
|
24
24
|
let selectedIndex = 0;
|
|
25
25
|
let dirty = false;
|
|
@@ -104,7 +104,7 @@ async function showProviderManagerMenu() {
|
|
|
104
104
|
console.log(chalk.bold.cyan('⚙ ' + t('provider.title') + '\n'));
|
|
105
105
|
|
|
106
106
|
// Header
|
|
107
|
-
console.log(chalk.gray('Use ↑↓ to move, Space to toggle, → to configure, X/ESC to exit\n'));
|
|
107
|
+
console.log(chalk.gray('Use ↑↓ to move, Space to toggle, </> to reorder (< down, > up), → to configure, !/1 to check agents, X/ESC to exit\n'));
|
|
108
108
|
|
|
109
109
|
// Display providers
|
|
110
110
|
order.forEach((id, index) => {
|
|
@@ -123,6 +123,17 @@ async function showProviderManagerMenu() {
|
|
|
123
123
|
statusIcon = isEnabled ? '🟢' : '🔴';
|
|
124
124
|
statusColor = isEnabled ? chalk.green : chalk.red;
|
|
125
125
|
statusText = isEnabled ? 'Enabled' : 'Disabled';
|
|
126
|
+
} else {
|
|
127
|
+
// Show enabled/disabled state even for uninstalled agents
|
|
128
|
+
if (isEnabled) {
|
|
129
|
+
statusIcon = '🟡';
|
|
130
|
+
statusColor = chalk.yellow;
|
|
131
|
+
statusText = 'Enabled (not installed)';
|
|
132
|
+
} else {
|
|
133
|
+
statusIcon = '⚪';
|
|
134
|
+
statusColor = chalk.gray;
|
|
135
|
+
statusText = 'Disabled (not installed)';
|
|
136
|
+
}
|
|
126
137
|
}
|
|
127
138
|
|
|
128
139
|
const prefix = isSelected ? chalk.cyan('❯ ') : ' ';
|
|
@@ -174,6 +185,27 @@ async function showProviderManagerMenu() {
|
|
|
174
185
|
}
|
|
175
186
|
|
|
176
187
|
switch (key.name) {
|
|
188
|
+
case '!':
|
|
189
|
+
case '1':
|
|
190
|
+
// Run agents check command
|
|
191
|
+
isMenuActive = false;
|
|
192
|
+
if (dirty) {
|
|
193
|
+
await saveProviderPreferences({ order, enabled });
|
|
194
|
+
await setProviderCache(Object.fromEntries(installationStatus));
|
|
195
|
+
}
|
|
196
|
+
// Trigger agents check after returning
|
|
197
|
+
setTimeout(() => {
|
|
198
|
+
console.clear();
|
|
199
|
+
console.log(chalk.bold.cyan('🔍 Checking agents...\n'));
|
|
200
|
+
require('../commands/agents-check')().then(() => {
|
|
201
|
+
process.exit(0);
|
|
202
|
+
}).catch((err) => {
|
|
203
|
+
console.log(chalk.red('Agents check error: ' + err.message));
|
|
204
|
+
process.exit(1);
|
|
205
|
+
});
|
|
206
|
+
}, 100);
|
|
207
|
+
return;
|
|
208
|
+
|
|
177
209
|
case 'escape':
|
|
178
210
|
case 'x':
|
|
179
211
|
isMenuActive = false;
|
|
@@ -191,6 +223,30 @@ async function showProviderManagerMenu() {
|
|
|
191
223
|
selectedIndex = Math.min(order.length - 1, selectedIndex + 1);
|
|
192
224
|
break;
|
|
193
225
|
|
|
226
|
+
case 'left':
|
|
227
|
+
case '<':
|
|
228
|
+
// Move selected provider down in order
|
|
229
|
+
if (selectedIndex < order.length - 1) {
|
|
230
|
+
const temp = order[selectedIndex];
|
|
231
|
+
order[selectedIndex] = order[selectedIndex + 1];
|
|
232
|
+
order[selectedIndex + 1] = temp;
|
|
233
|
+
selectedIndex++;
|
|
234
|
+
dirty = true;
|
|
235
|
+
}
|
|
236
|
+
break;
|
|
237
|
+
|
|
238
|
+
case 'right':
|
|
239
|
+
case '>':
|
|
240
|
+
// Move selected provider up in order
|
|
241
|
+
if (selectedIndex > 0) {
|
|
242
|
+
const temp = order[selectedIndex];
|
|
243
|
+
order[selectedIndex] = order[selectedIndex - 1];
|
|
244
|
+
order[selectedIndex - 1] = temp;
|
|
245
|
+
selectedIndex--;
|
|
246
|
+
dirty = true;
|
|
247
|
+
}
|
|
248
|
+
break;
|
|
249
|
+
|
|
194
250
|
case 'space':
|
|
195
251
|
case 'return':
|
|
196
252
|
const currentId = order[selectedIndex];
|
|
@@ -198,7 +254,7 @@ async function showProviderManagerMenu() {
|
|
|
198
254
|
dirty = true;
|
|
199
255
|
break;
|
|
200
256
|
|
|
201
|
-
case '
|
|
257
|
+
case 'c':
|
|
202
258
|
// Configure selected provider
|
|
203
259
|
const selectedId = order[selectedIndex];
|
|
204
260
|
const def = defMap.get(selectedId);
|
|
@@ -110,6 +110,14 @@ const PROVIDER_DEFINITIONS = [
|
|
|
110
110
|
defaultModel: 'cline-cli',
|
|
111
111
|
estimatedSpeed: 55000
|
|
112
112
|
},
|
|
113
|
+
{
|
|
114
|
+
id: 'opencode',
|
|
115
|
+
name: 'OpenCode CLI',
|
|
116
|
+
type: 'direct',
|
|
117
|
+
category: 'llm',
|
|
118
|
+
defaultModel: 'opencode-cli',
|
|
119
|
+
estimatedSpeed: 40000
|
|
120
|
+
},
|
|
113
121
|
{
|
|
114
122
|
id: 'replit',
|
|
115
123
|
name: 'Replit Agent',
|
|
@@ -157,6 +165,7 @@ function getProviderDisplayName(id) {
|
|
|
157
165
|
'vscode': 'ide.agent.vscode',
|
|
158
166
|
'cline': 'ide.agent.cline',
|
|
159
167
|
'claude-code': 'ide.agent.claude.code',
|
|
168
|
+
'opencode': 'ide.agent.opencode',
|
|
160
169
|
'antigravity': 'ide.agent.antigravity',
|
|
161
170
|
'github-copilot': 'ide.agent.github.copilot',
|
|
162
171
|
'amazon-q': 'ide.agent.amazon.q',
|
|
@@ -185,12 +194,13 @@ function mergeProviderPreferences(autoConfig) {
|
|
|
185
194
|
|
|
186
195
|
const defaultOrder = getDefaultProviderOrder();
|
|
187
196
|
const cleanedOrder = order.filter(id => getProviderDefinition(id));
|
|
188
|
-
defaultOrder.forEach(id => {
|
|
197
|
+
defaultOrder.forEach((id, index) => {
|
|
189
198
|
if (!cleanedOrder.includes(id)) {
|
|
190
199
|
cleanedOrder.push(id);
|
|
191
200
|
}
|
|
192
201
|
if (enabled[id] === undefined) {
|
|
193
|
-
|
|
202
|
+
// Enable the first provider by default (antigravity)
|
|
203
|
+
enabled[id] = index === 0;
|
|
194
204
|
}
|
|
195
205
|
});
|
|
196
206
|
|
|
@@ -205,12 +215,23 @@ async function getProviderPreferences() {
|
|
|
205
215
|
async function saveProviderPreferences(order, enabled) {
|
|
206
216
|
await setAutoConfig({
|
|
207
217
|
providerPreferences: {
|
|
208
|
-
order: order.slice(),
|
|
218
|
+
order: Array.isArray(order) ? order.slice() : [],
|
|
209
219
|
enabled: { ...enabled }
|
|
210
220
|
}
|
|
211
221
|
});
|
|
212
222
|
}
|
|
213
223
|
|
|
224
|
+
async function getProviderCache() {
|
|
225
|
+
const autoConfig = await getAutoConfig();
|
|
226
|
+
return autoConfig.providerCache || {};
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
async function setProviderCache(cache) {
|
|
230
|
+
await setAutoConfig({
|
|
231
|
+
providerCache: { ...cache }
|
|
232
|
+
});
|
|
233
|
+
}
|
|
234
|
+
|
|
214
235
|
module.exports = {
|
|
215
236
|
getProviderDefinitions,
|
|
216
237
|
getProviderDefinition,
|
|
@@ -219,6 +240,8 @@ module.exports = {
|
|
|
219
240
|
mergeProviderPreferences,
|
|
220
241
|
getProviderPreferences,
|
|
221
242
|
saveProviderPreferences,
|
|
243
|
+
getProviderCache,
|
|
244
|
+
setProviderCache,
|
|
222
245
|
PROVIDER_DEFINITIONS
|
|
223
246
|
};
|
|
224
247
|
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Provider Utils Module
|
|
3
|
+
*
|
|
4
|
+
* Contains utility functions for provider checking.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
const { spawn, execSync } = require('child_process');
|
|
8
|
+
const fs = require('fs');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
|
|
11
|
+
const CLI_ENTRY_POINT = path.resolve(path.join(__dirname, '../../bin/vibecodingmachine.js'));
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Get the Node.js executable path
|
|
15
|
+
* When running in Electron, process.execPath points to electron executable, not node
|
|
16
|
+
*/
|
|
17
|
+
function getNodeExecutable() {
|
|
18
|
+
// First try to get the actual node executable from process.env
|
|
19
|
+
if (process.env.NODE_BINARY_PATH) {
|
|
20
|
+
return process.env.NODE_BINARY_PATH;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// Try to find node in PATH
|
|
24
|
+
try {
|
|
25
|
+
const nodeCmd = process.platform === 'win32' ? 'where node' : 'which node';
|
|
26
|
+
const nodePath = execSync(nodeCmd, { encoding: 'utf8' }).trim().split('\n')[0];
|
|
27
|
+
if (nodePath && fs.existsSync(nodePath)) {
|
|
28
|
+
return nodePath;
|
|
29
|
+
}
|
|
30
|
+
} catch (_) {}
|
|
31
|
+
|
|
32
|
+
// Fallback: try common node installation paths
|
|
33
|
+
const commonPaths = process.platform === 'win32'
|
|
34
|
+
? [
|
|
35
|
+
'C:\\Program Files\\nodejs\\node.exe',
|
|
36
|
+
'C:\\Program Files (x86)\\nodejs\\node.exe',
|
|
37
|
+
path.join(process.env.PROGRAMFILES || '', 'nodejs', 'node.exe'),
|
|
38
|
+
path.join(process.env['PROGRAMFILES(X86)'] || '', 'nodejs', 'node.exe')
|
|
39
|
+
]
|
|
40
|
+
: [
|
|
41
|
+
'/usr/bin/node',
|
|
42
|
+
'/usr/local/bin/node',
|
|
43
|
+
'/opt/homebrew/bin/node'
|
|
44
|
+
];
|
|
45
|
+
|
|
46
|
+
for (const nodePath of commonPaths) {
|
|
47
|
+
if (nodePath && fs.existsSync(nodePath)) {
|
|
48
|
+
return nodePath;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Last resort: use process.execPath (might be electron but worth trying)
|
|
53
|
+
console.warn('[AGENT CHECK] Could not find node executable, falling back to process.execPath');
|
|
54
|
+
return process.execPath;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Get result file path for provider check
|
|
59
|
+
*/
|
|
60
|
+
function getResultFilePath(repoPath) {
|
|
61
|
+
return path.join(repoPath, '.vibecodingmachine', 'agent-check-results.json');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Remove test requirement from requirements file
|
|
66
|
+
*/
|
|
67
|
+
function removeTestRequirement(reqPath) {
|
|
68
|
+
if (!fs.existsSync(reqPath)) return;
|
|
69
|
+
|
|
70
|
+
const content = fs.readFileSync(reqPath, 'utf8');
|
|
71
|
+
const lines = content.split('\n');
|
|
72
|
+
|
|
73
|
+
// Find and remove the test requirement
|
|
74
|
+
const startIdx = lines.findIndex(line => line.includes('### AGENT CHECK TEST'));
|
|
75
|
+
if (startIdx !== -1) {
|
|
76
|
+
let endIdx = startIdx + 1;
|
|
77
|
+
while (endIdx < lines.length && !lines[endIdx].startsWith('###') && !lines[endIdx].startsWith('##')) {
|
|
78
|
+
endIdx++;
|
|
79
|
+
}
|
|
80
|
+
lines.splice(startIdx, endIdx - startIdx);
|
|
81
|
+
fs.writeFileSync(reqPath, lines.join('\n'));
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Format a checkedAt ISO timestamp for display.
|
|
87
|
+
* e.g. "April 12, 2025 at 4:23 pm"
|
|
88
|
+
*/
|
|
89
|
+
function formatCheckedAt(checkedAt) {
|
|
90
|
+
if (!checkedAt) return '';
|
|
91
|
+
const d = new Date(checkedAt);
|
|
92
|
+
if (isNaN(d.getTime())) return checkedAt;
|
|
93
|
+
const months = ['January','February','March','April','May','June','July','August','September','October','November','December'];
|
|
94
|
+
const timePart = d.toLocaleTimeString('en-US', { hour: 'numeric', minute: '2-digit', hour12: true }).toLowerCase();
|
|
95
|
+
return `${months[d.getMonth()]} ${d.getDate()}, ${d.getFullYear()} at ${timePart}`;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Create a test requirement for checking
|
|
100
|
+
*/
|
|
101
|
+
function createTestRequirement(reqPath) {
|
|
102
|
+
const testReq = `### AGENT CHECK TEST
|
|
103
|
+
|
|
104
|
+
**Status:** NOT WORKING
|
|
105
|
+
**Response from last chat:** Testing provider connectivity...
|
|
106
|
+
|
|
107
|
+
---
|
|
108
|
+
|
|
109
|
+
This is a temporary test requirement used to verify agent providers are working.
|
|
110
|
+
It will be automatically removed after the check completes.
|
|
111
|
+
`;
|
|
112
|
+
|
|
113
|
+
try {
|
|
114
|
+
// Ensure directory exists
|
|
115
|
+
fs.mkdirSync(path.dirname(reqPath), { recursive: true });
|
|
116
|
+
|
|
117
|
+
// Read existing content
|
|
118
|
+
let content = '';
|
|
119
|
+
if (fs.existsSync(reqPath)) {
|
|
120
|
+
content = fs.readFileSync(reqPath, 'utf8');
|
|
121
|
+
} else {
|
|
122
|
+
content = '# Requirements\n\n';
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
// Add test requirement
|
|
126
|
+
if (!content.includes('### AGENT CHECK TEST')) {
|
|
127
|
+
content += '\n' + testReq;
|
|
128
|
+
fs.writeFileSync(reqPath, content);
|
|
129
|
+
}
|
|
130
|
+
} catch (error) {
|
|
131
|
+
console.warn('[AGENT CHECK] Could not create test requirement:', error.message);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* Parse provider check result from file
|
|
137
|
+
*/
|
|
138
|
+
function parseResultFile(resultFile) {
|
|
139
|
+
try {
|
|
140
|
+
if (!fs.existsSync(resultFile)) {
|
|
141
|
+
return null;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
const content = fs.readFileSync(resultFile, 'utf8');
|
|
145
|
+
const lines = content.trim().split('\n');
|
|
146
|
+
|
|
147
|
+
// Find the result line (should be the last non-empty line)
|
|
148
|
+
for (let i = lines.length - 1; i >= 0; i--) {
|
|
149
|
+
const line = lines[i].trim();
|
|
150
|
+
if (line && !line.startsWith('[') && !line.startsWith('Agent check')) {
|
|
151
|
+
try {
|
|
152
|
+
return JSON.parse(line);
|
|
153
|
+
} catch {
|
|
154
|
+
// Not JSON, continue searching
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
} catch (error) {
|
|
159
|
+
console.warn('[AGENT CHECK] Error parsing result file:', error.message);
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
return null;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
module.exports = {
|
|
166
|
+
getNodeExecutable,
|
|
167
|
+
getResultFilePath,
|
|
168
|
+
removeTestRequirement,
|
|
169
|
+
formatCheckedAt,
|
|
170
|
+
createTestRequirement,
|
|
171
|
+
parseResultFile,
|
|
172
|
+
CLI_ENTRY_POINT
|
|
173
|
+
};
|