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
package/src/commands/auto.js
CHANGED
|
@@ -2,18 +2,18 @@ const chalk = require('chalk');
|
|
|
2
2
|
const ora = require('ora');
|
|
3
3
|
const path = require('path');
|
|
4
4
|
const os = require('os');
|
|
5
|
-
const {
|
|
6
|
-
const {
|
|
5
|
+
const { spawn } = require('child_process');
|
|
6
|
+
const { AppleScriptManager, ClineCLIManager, AiderCLIManager, ClaudeCodeCLIManager, logIDEMessage, runContinueCLIAutoMode, t } = require('vibecodingmachine-core');
|
|
7
|
+
const { getRepoPath, getAutoConfig, setAutoConfig, getStages } = require('../utils/config');
|
|
7
8
|
const { checkAutoModeStatus, startAutoMode, stopAutoMode, updateAutoModeStatus } = require('../utils/auto-mode');
|
|
8
9
|
const logger = require('../utils/logger');
|
|
9
10
|
const { createKeyboardHandler } = require('../utils/keyboard-handler');
|
|
10
11
|
const { getProviderDefinitions, getProviderPreferences } = require('../utils/provider-registry');
|
|
11
12
|
const PROVIDER_DEFINITIONS = getProviderDefinitions();
|
|
12
|
-
const DIRECT_AGENT_IDS = PROVIDER_DEFINITIONS.filter(def => def.type === 'direct').map(def => def.id);
|
|
13
13
|
const PROVIDER_DEFINITION_MAP = new Map(PROVIDER_DEFINITIONS.map(def => [def.id, def]));
|
|
14
14
|
const { handleAutoStart: handleDirectAutoStart } = require('./auto-direct');
|
|
15
15
|
|
|
16
|
-
|
|
16
|
+
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* Get available LLM providers from config and environment variables
|
|
@@ -182,6 +182,7 @@ async function moveRequirementBackToTodo(repoPath, requirementText) {
|
|
|
182
182
|
|
|
183
183
|
for (let i = 0; i < lines.length; i++) {
|
|
184
184
|
const line = lines[i];
|
|
185
|
+
const trimmed = line.trim();
|
|
185
186
|
|
|
186
187
|
// Find verified section
|
|
187
188
|
if (line.includes('## ✅ Verified by AI screenshot')) {
|
|
@@ -199,7 +200,7 @@ async function moveRequirementBackToTodo(repoPath, requirementText) {
|
|
|
199
200
|
}
|
|
200
201
|
|
|
201
202
|
// Check if we're in verified section and this is the requirement to move
|
|
202
|
-
if (inVerifiedSection &&
|
|
203
|
+
if (inVerifiedSection && trimmed.startsWith('- ')) {
|
|
203
204
|
const lineRequirement = line.substring(2).trim();
|
|
204
205
|
// Remove date prefix if present (format: "2025-11-05: **requirement**")
|
|
205
206
|
const cleanRequirement = lineRequirement.replace(/^\d{4}-\d{2}-\d{2}:\s*\*\*/, '').replace(/\*\*$/, '').trim();
|
|
@@ -210,20 +211,21 @@ async function moveRequirementBackToTodo(repoPath, requirementText) {
|
|
|
210
211
|
requirementFound = true;
|
|
211
212
|
continue;
|
|
212
213
|
}
|
|
213
|
-
updatedLines.push(line);
|
|
214
|
-
continue;
|
|
215
214
|
}
|
|
216
215
|
|
|
217
216
|
// If we're in not yet completed section and haven't added the requirement yet, add it at the top
|
|
218
|
-
if (inNotYetCompleted && !requirementFound &&
|
|
217
|
+
if (inNotYetCompleted && !requirementFound && trimmed.startsWith('- ')) {
|
|
219
218
|
// Add the requirement before the first existing requirement
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
219
|
+
const newUpdatedLines = lines.slice(0, i);
|
|
220
|
+
newUpdatedLines.push(`- ${requirementText}`);
|
|
221
|
+
newUpdatedLines.push('');
|
|
222
|
+
newUpdatedLines.push(...lines.slice(i));
|
|
223
|
+
await fs.writeFile(reqPath, newUpdatedLines.join('\n'));
|
|
224
|
+
return { success: true };
|
|
223
225
|
}
|
|
224
226
|
|
|
225
227
|
// Reset section flags when hitting new sections
|
|
226
|
-
if (
|
|
228
|
+
if (trimmed.startsWith('##')) {
|
|
227
229
|
inVerifiedSection = false;
|
|
228
230
|
inNotYetCompleted = false;
|
|
229
231
|
}
|
|
@@ -234,6 +236,7 @@ async function moveRequirementBackToTodo(repoPath, requirementText) {
|
|
|
234
236
|
// If requirement wasn't found in verified section, try to add it to not yet completed anyway
|
|
235
237
|
if (!requirementFound) {
|
|
236
238
|
// Find the not yet completed section and add requirement at the top
|
|
239
|
+
const newUpdatedLines = lines.slice();
|
|
237
240
|
for (let i = 0; i < updatedLines.length; i++) {
|
|
238
241
|
if (updatedLines[i].includes('## ⏳ Requirements not yet completed')) {
|
|
239
242
|
// Find the first requirement line after this section
|
|
@@ -243,18 +246,13 @@ async function moveRequirementBackToTodo(repoPath, requirementText) {
|
|
|
243
246
|
insertIndex++;
|
|
244
247
|
}
|
|
245
248
|
updatedLines.splice(insertIndex, 0, `- ${requirementText}`, '');
|
|
246
|
-
|
|
247
|
-
|
|
249
|
+
await fs.writeFile(reqPath, updatedLines.join('\n'));
|
|
250
|
+
return { success: true };
|
|
248
251
|
}
|
|
249
252
|
}
|
|
250
253
|
}
|
|
251
254
|
|
|
252
|
-
|
|
253
|
-
await fs.writeFile(reqPath, updatedLines.join('\n'));
|
|
254
|
-
return { success: true };
|
|
255
|
-
} else {
|
|
256
|
-
return { success: false, error: 'Requirement not found in verified section' };
|
|
257
|
-
}
|
|
255
|
+
return { success: false, error: 'Requirement not found in verified section' };
|
|
258
256
|
} catch (error) {
|
|
259
257
|
return { success: false, error: error.message };
|
|
260
258
|
}
|
|
@@ -279,10 +277,8 @@ async function moveRequirementToFeedback(repoPath, requirementText, questions, f
|
|
|
279
277
|
|
|
280
278
|
const content = await fs.readFile(reqPath, 'utf8');
|
|
281
279
|
const lines = content.split('\n');
|
|
282
|
-
const updatedLines = [];
|
|
283
280
|
|
|
284
281
|
let inTodoSection = false;
|
|
285
|
-
let inFeedbackSection = false;
|
|
286
282
|
let requirementRemoved = false;
|
|
287
283
|
let feedbackAdded = false;
|
|
288
284
|
|
|
@@ -292,15 +288,13 @@ async function moveRequirementToFeedback(repoPath, requirementText, questions, f
|
|
|
292
288
|
// Find TODO section
|
|
293
289
|
if (trimmed.startsWith('##') && trimmed.includes('Requirements not yet completed')) {
|
|
294
290
|
inTodoSection = true;
|
|
295
|
-
inFeedbackSection = false;
|
|
296
|
-
updatedLines.push(line);
|
|
297
291
|
continue;
|
|
298
292
|
}
|
|
299
293
|
|
|
300
294
|
// Find "Requirements needing manual feedback" section
|
|
301
295
|
if (trimmed.startsWith('##') && (trimmed.includes('Requirements needing manual feedback') || trimmed.includes('❓ Requirements needing'))) {
|
|
302
296
|
inTodoSection = false;
|
|
303
|
-
|
|
297
|
+
const updatedLines = lines.slice(0, lines.indexOf(line));
|
|
304
298
|
updatedLines.push(line);
|
|
305
299
|
|
|
306
300
|
// Add blank line if not already present
|
|
@@ -328,13 +322,14 @@ async function moveRequirementToFeedback(repoPath, requirementText, questions, f
|
|
|
328
322
|
updatedLines.push('');
|
|
329
323
|
feedbackAdded = true;
|
|
330
324
|
}
|
|
331
|
-
|
|
325
|
+
updatedLines.push(...lines.slice(lines.indexOf(line) + 1));
|
|
326
|
+
await fs.writeFile(reqPath, updatedLines.join('\n'));
|
|
327
|
+
return { success: true };
|
|
332
328
|
}
|
|
333
329
|
|
|
334
330
|
// Stop sections at next header
|
|
335
331
|
if (trimmed.startsWith('##')) {
|
|
336
332
|
inTodoSection = false;
|
|
337
|
-
inFeedbackSection = false;
|
|
338
333
|
}
|
|
339
334
|
|
|
340
335
|
// Remove requirement from TODO section (match first occurrence)
|
|
@@ -694,8 +689,6 @@ async function start(options) {
|
|
|
694
689
|
if (global.pendingUpdate) {
|
|
695
690
|
const updateSpinner = ora('Installing update...').start();
|
|
696
691
|
try {
|
|
697
|
-
const { spawn } = require('child_process');
|
|
698
|
-
|
|
699
692
|
// Install update using npm
|
|
700
693
|
await new Promise((resolve, reject) => {
|
|
701
694
|
const npmInstall = spawn('npm', ['install', '-g', 'vibecodingmachine-cli'], {
|
|
@@ -708,7 +701,6 @@ async function start(options) {
|
|
|
708
701
|
console.log(chalk.green('\n✓ Restarting with new version...\n'));
|
|
709
702
|
|
|
710
703
|
// Restart CLI with same arguments
|
|
711
|
-
const { spawn } = require('child_process');
|
|
712
704
|
const args = process.argv.slice(2);
|
|
713
705
|
spawn(process.argv[0], [process.argv[1], ...args], {
|
|
714
706
|
stdio: 'inherit',
|
|
@@ -731,7 +723,7 @@ async function start(options) {
|
|
|
731
723
|
}
|
|
732
724
|
}
|
|
733
725
|
|
|
734
|
-
const spinner = ora('
|
|
726
|
+
const spinner = ora(t('auto.starting.mode')).start();
|
|
735
727
|
|
|
736
728
|
try {
|
|
737
729
|
const repoPath = await getRepoPath();
|
|
@@ -741,15 +733,32 @@ async function start(options) {
|
|
|
741
733
|
throw new Error('No repository configured');
|
|
742
734
|
}
|
|
743
735
|
|
|
744
|
-
//
|
|
736
|
+
// Get provider preferences and definitions
|
|
745
737
|
const savedConfig = await getAutoConfig();
|
|
746
738
|
const prefs = await getProviderPreferences();
|
|
747
|
-
|
|
748
|
-
|
|
749
|
-
const
|
|
750
|
-
const
|
|
751
|
-
|
|
752
|
-
|
|
739
|
+
|
|
740
|
+
// Get all available providers in the order specified in preferences
|
|
741
|
+
const availableProviders = [];
|
|
742
|
+
for (const id of prefs.order) {
|
|
743
|
+
if (prefs.enabled[id] !== false && PROVIDER_DEFINITION_MAP.has(id)) {
|
|
744
|
+
availableProviders.push(id);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
// If no providers are available, use the first one from definitions as fallback
|
|
749
|
+
if (availableProviders.length === 0) {
|
|
750
|
+
availableProviders.push(PROVIDER_DEFINITIONS[0]?.id || 'claude-code');
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
// Use the first available provider by default, unless overridden by options
|
|
754
|
+
let effectiveAgent = options.ide || availableProviders[0];
|
|
755
|
+
|
|
756
|
+
// If the requested agent isn't available, use the first available one
|
|
757
|
+
if (!availableProviders.includes(effectiveAgent)) {
|
|
758
|
+
effectiveAgent = availableProviders[0];
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
const providerDef = PROVIDER_DEFINITION_MAP.get(effectiveAgent);
|
|
753
762
|
|
|
754
763
|
const resolvedNeverStop = (() => {
|
|
755
764
|
if (options.neverStop !== undefined) return options.neverStop;
|
|
@@ -893,8 +902,15 @@ async function start(options) {
|
|
|
893
902
|
await startAutoMode(repoPath, config);
|
|
894
903
|
}
|
|
895
904
|
|
|
905
|
+
// Get configured stages
|
|
906
|
+
const stages = await getStages();
|
|
907
|
+
const stagesList = stages.join(' → ');
|
|
908
|
+
const defaultInstructionText = `Follow INSTRUCTIONS.md from .vibecodingmachine directory.
|
|
909
|
+
|
|
910
|
+
CRITICAL FOR IDE AGENTS: You MUST work through ALL configured stages (${stagesList}) without stopping. Update the "🚦 Current Status" section in the REQUIREMENTS file as you progress through each stage. DO NOT stop after acknowledging stages - you must COMPLETE the work and set status to DONE in the requirements file. The CLI is monitoring the file and waiting for you to finish.`;
|
|
911
|
+
|
|
896
912
|
// Send initial instruction to IDE or Continue/Cline CLI
|
|
897
|
-
const textToSend = options.text ||
|
|
913
|
+
const textToSend = options.text || defaultInstructionText;
|
|
898
914
|
|
|
899
915
|
if (config.ide === 'continue') {
|
|
900
916
|
// Use Continue CLI with command-line approach
|
|
@@ -1017,14 +1033,9 @@ async function start(options) {
|
|
|
1017
1033
|
'DONE': '⏳'
|
|
1018
1034
|
};
|
|
1019
1035
|
|
|
1020
|
-
|
|
1021
|
-
const stageMap = {
|
|
1022
|
-
|
|
1023
|
-
'ACT': 1,
|
|
1024
|
-
'CLEAN UP': 2,
|
|
1025
|
-
'VERIFY': 3,
|
|
1026
|
-
'DONE': 4
|
|
1027
|
-
};
|
|
1036
|
+
// Build stage map dynamically
|
|
1037
|
+
const stageMap = {};
|
|
1038
|
+
stages.forEach((s, i) => stageMap[s] = i);
|
|
1028
1039
|
|
|
1029
1040
|
const currentIndex = stageMap[currentStatus] || 0;
|
|
1030
1041
|
const workflowLine = stages.map((stage, idx) => {
|
|
@@ -1064,29 +1075,64 @@ async function start(options) {
|
|
|
1064
1075
|
let title = null;
|
|
1065
1076
|
let status = 'PREPARE';
|
|
1066
1077
|
let inTodoSection = false;
|
|
1078
|
+
let inCurrentSection = false;
|
|
1067
1079
|
|
|
1068
1080
|
for (let i = 0; i < lines.length; i++) {
|
|
1069
1081
|
const line = lines[i].trim();
|
|
1070
1082
|
|
|
1083
|
+
// Check if we're in the Current section
|
|
1084
|
+
if (line.includes('## 🔨 Current In Progress Requirement') ||
|
|
1085
|
+
line.includes('Current In Progress Requirement')) {
|
|
1086
|
+
inCurrentSection = true;
|
|
1087
|
+
inTodoSection = false;
|
|
1088
|
+
continue;
|
|
1089
|
+
}
|
|
1090
|
+
|
|
1071
1091
|
// Check if we're in the TODO section
|
|
1072
1092
|
if (line.includes('## ⏳ Requirements not yet completed') ||
|
|
1073
1093
|
(line.includes('Requirements not yet completed') && line.startsWith('##'))) {
|
|
1074
1094
|
inTodoSection = true;
|
|
1095
|
+
inCurrentSection = false;
|
|
1075
1096
|
continue;
|
|
1076
1097
|
}
|
|
1077
1098
|
|
|
1078
|
-
// If we hit another section header, stop looking
|
|
1079
|
-
if (inTodoSection && line.startsWith('##') && !line.startsWith('###')) {
|
|
1080
|
-
|
|
1099
|
+
// If we hit another section header, stop looking in current section/todo section logic
|
|
1100
|
+
if ((inTodoSection || inCurrentSection) && line.startsWith('##') && !line.startsWith('###')) {
|
|
1101
|
+
if (inCurrentSection) {
|
|
1102
|
+
// If we finished current section and found nothing, move to next sections (which might be TODO)
|
|
1103
|
+
inCurrentSection = false;
|
|
1104
|
+
continue;
|
|
1105
|
+
}
|
|
1106
|
+
if (inTodoSection) {
|
|
1107
|
+
break;
|
|
1108
|
+
}
|
|
1081
1109
|
}
|
|
1082
1110
|
|
|
1083
|
-
// If we're in
|
|
1084
|
-
if (
|
|
1085
|
-
|
|
1086
|
-
|
|
1087
|
-
|
|
1088
|
-
|
|
1089
|
-
break;
|
|
1111
|
+
// If we're in Current section, look for bullet or header
|
|
1112
|
+
if (inCurrentSection) {
|
|
1113
|
+
if (line.startsWith('- ')) {
|
|
1114
|
+
title = line.substring(2).trim();
|
|
1115
|
+
// Remove bold if present
|
|
1116
|
+
title = title.replace(/\*\*/g, '');
|
|
1117
|
+
if (title) break;
|
|
1118
|
+
}
|
|
1119
|
+
if (line.startsWith('###')) {
|
|
1120
|
+
title = line.replace(/^###\s*/, '').trim();
|
|
1121
|
+
if (title) break;
|
|
1122
|
+
}
|
|
1123
|
+
}
|
|
1124
|
+
|
|
1125
|
+
// If we're in TODO section and find a requirement header (###) or bullet
|
|
1126
|
+
if (inTodoSection) {
|
|
1127
|
+
if (line.startsWith('###')) {
|
|
1128
|
+
title = line.replace(/^###\s*/, '').trim();
|
|
1129
|
+
if (title) break;
|
|
1130
|
+
}
|
|
1131
|
+
// Also support bullet points in TODO if that's a format used
|
|
1132
|
+
if (line.startsWith('- ')) {
|
|
1133
|
+
title = line.substring(2).trim();
|
|
1134
|
+
title = title.replace(/\*\*/g, '');
|
|
1135
|
+
if (title) break;
|
|
1090
1136
|
}
|
|
1091
1137
|
}
|
|
1092
1138
|
}
|
|
@@ -3025,7 +3071,7 @@ Example BAD questions (never ask these):
|
|
|
3025
3071
|
// Ask if user wants to stop with countdown
|
|
3026
3072
|
const readline = require('readline');
|
|
3027
3073
|
console.log(chalk.yellow('\n⏸️ Continue to next requirement or stop?'));
|
|
3028
|
-
console.log(chalk.gray('
|
|
3074
|
+
console.log(chalk.gray(` ${t('auto.press.any.key.stop')}`));
|
|
3029
3075
|
|
|
3030
3076
|
let countdown = 10;
|
|
3031
3077
|
let dots = '.'.repeat(countdown);
|
|
@@ -3116,7 +3162,7 @@ Example BAD questions (never ask these):
|
|
|
3116
3162
|
// Ask if user wants to stop with countdown
|
|
3117
3163
|
const readline = require('readline');
|
|
3118
3164
|
console.log(chalk.yellow('\n⏸️ Continue to next requirement or stop?'));
|
|
3119
|
-
console.log(chalk.gray('
|
|
3165
|
+
console.log(chalk.gray(` ${t('auto.press.any.key.stop')}`));
|
|
3120
3166
|
|
|
3121
3167
|
let countdown = 10;
|
|
3122
3168
|
let dots = '.'.repeat(countdown);
|
|
@@ -4724,7 +4770,7 @@ Example BAD questions (never ask these):
|
|
|
4724
4770
|
return;
|
|
4725
4771
|
}
|
|
4726
4772
|
} else if (ideAppPath) {
|
|
4727
|
-
spinner.succeed(
|
|
4773
|
+
spinner.succeed(t('auto.ide.is.installed', { ide: config.ide }));
|
|
4728
4774
|
}
|
|
4729
4775
|
|
|
4730
4776
|
// Launch the IDE if it's not already running
|
|
@@ -4739,7 +4785,7 @@ Example BAD questions (never ask these):
|
|
|
4739
4785
|
config.ide === 'vscode' ? 'Code' : config.ide}"`,
|
|
4740
4786
|
{ encoding: 'utf8', stdio: 'pipe' }).trim();
|
|
4741
4787
|
if (isRunning) {
|
|
4742
|
-
console.log(chalk.gray(` ${
|
|
4788
|
+
console.log(chalk.gray(` ${t('auto.ide.is.running', { ide: config.ide, pid: isRunning.split('\n')[0] })}`));
|
|
4743
4789
|
}
|
|
4744
4790
|
} catch (err) {
|
|
4745
4791
|
// Not running, launch it
|
|
@@ -4783,8 +4829,8 @@ Example BAD questions (never ask these):
|
|
|
4783
4829
|
console.log(chalk.gray(' Consider using'), chalk.cyan('Cline IDE'), chalk.gray('instead (set with'), chalk.cyan('vcm'), chalk.gray('menu)'));
|
|
4784
4830
|
} else {
|
|
4785
4831
|
logIDEMessage(config.ide, textToSend);
|
|
4786
|
-
spinner.succeed('
|
|
4787
|
-
console.log(chalk.green(
|
|
4832
|
+
spinner.succeed(t('auto.direct.ide.autonomous.started'));
|
|
4833
|
+
console.log(chalk.green(`\n✓ ${t('auto.coding.autonomously')}`));
|
|
4788
4834
|
}
|
|
4789
4835
|
} catch (sendError) {
|
|
4790
4836
|
logIDEMessage(config.ide, `[ERROR] ${textToSend}`);
|
|
@@ -4807,12 +4853,12 @@ Example BAD questions (never ask these):
|
|
|
4807
4853
|
};
|
|
4808
4854
|
return ideNames[ide] || ide;
|
|
4809
4855
|
};
|
|
4810
|
-
console.log(chalk.gray(
|
|
4856
|
+
console.log(chalk.gray(` ${t('auto.ide.label')}`), chalk.cyan(formatIDEName(config.ide)));
|
|
4811
4857
|
|
|
4812
4858
|
if (config.neverStop) {
|
|
4813
4859
|
console.log(chalk.gray(' Mode:'), chalk.cyan('Never stop'));
|
|
4814
4860
|
} else if (config.maxChats) {
|
|
4815
|
-
console.log(chalk.gray('
|
|
4861
|
+
console.log(chalk.gray(` ${t('auto.max.chats.label')}`), chalk.cyan(config.maxChats));
|
|
4816
4862
|
}
|
|
4817
4863
|
} catch (error) {
|
|
4818
4864
|
spinner.stop();
|
|
@@ -4868,7 +4914,7 @@ async function status() {
|
|
|
4868
4914
|
if (config.neverStop) {
|
|
4869
4915
|
console.log(chalk.gray(' Mode:'), chalk.cyan('Never stop'));
|
|
4870
4916
|
} else if (config.maxChats) {
|
|
4871
|
-
console.log(chalk.gray('
|
|
4917
|
+
console.log(chalk.gray(` ${t('auto.max.chats.label')}`), chalk.cyan(config.maxChats));
|
|
4872
4918
|
const remaining = config.maxChats - (autoStatus.chatCount || 0);
|
|
4873
4919
|
console.log(chalk.gray(' Remaining:'), chalk.cyan(remaining));
|
|
4874
4920
|
}
|
|
@@ -4912,9 +4958,61 @@ async function config(options) {
|
|
|
4912
4958
|
}
|
|
4913
4959
|
}
|
|
4914
4960
|
|
|
4961
|
+
async function listAgents() {
|
|
4962
|
+
const ProviderManager = require('vibecodingmachine-core/src/ide-integration/provider-manager.cjs');
|
|
4963
|
+
const providerManager = new ProviderManager();
|
|
4964
|
+
|
|
4965
|
+
console.log(chalk.blue('\n📋 Available IDE Agents and Quota Status:\n'));
|
|
4966
|
+
|
|
4967
|
+
// Get all provider definitions
|
|
4968
|
+
const providers = getProviderDefinitions();
|
|
4969
|
+
|
|
4970
|
+
// Check each provider's quota status
|
|
4971
|
+
for (const provider of providers) {
|
|
4972
|
+
const rateLimitInfo = providerManager.getRateLimitInfo(provider.id);
|
|
4973
|
+
|
|
4974
|
+
let statusIcon = '✅';
|
|
4975
|
+
let statusText = chalk.green('Available');
|
|
4976
|
+
let quotaInfo = '';
|
|
4977
|
+
|
|
4978
|
+
if (rateLimitInfo.isRateLimited) {
|
|
4979
|
+
statusIcon = '⚠️';
|
|
4980
|
+
statusText = chalk.yellow('Quota Limit');
|
|
4981
|
+
|
|
4982
|
+
if (rateLimitInfo.resetTime) {
|
|
4983
|
+
const resetDate = new Date(rateLimitInfo.resetTime);
|
|
4984
|
+
const now = new Date();
|
|
4985
|
+
const minutesRemaining = Math.ceil((resetDate - now) / (1000 * 60));
|
|
4986
|
+
|
|
4987
|
+
if (minutesRemaining > 60) {
|
|
4988
|
+
const hoursRemaining = Math.ceil(minutesRemaining / 60);
|
|
4989
|
+
quotaInfo = chalk.gray(` (resets in ${hoursRemaining}h)`);
|
|
4990
|
+
} else if (minutesRemaining > 0) {
|
|
4991
|
+
quotaInfo = chalk.gray(` (resets in ${minutesRemaining}m)`);
|
|
4992
|
+
} else {
|
|
4993
|
+
quotaInfo = chalk.gray(' (resetting soon)');
|
|
4994
|
+
}
|
|
4995
|
+
}
|
|
4996
|
+
|
|
4997
|
+
if (rateLimitInfo.reason) {
|
|
4998
|
+
quotaInfo += chalk.gray(` - ${rateLimitInfo.reason}`);
|
|
4999
|
+
}
|
|
5000
|
+
}
|
|
5001
|
+
|
|
5002
|
+
console.log(`${statusIcon} ${chalk.cyan(provider.name)} ${statusText}${quotaInfo}`);
|
|
5003
|
+
if (provider.description) {
|
|
5004
|
+
console.log(` ${chalk.gray(provider.description)}`);
|
|
5005
|
+
}
|
|
5006
|
+
}
|
|
5007
|
+
|
|
5008
|
+
console.log(chalk.gray('\n💡 Tip: Auto mode will automatically skip quota-limited agents\n'));
|
|
5009
|
+
}
|
|
5010
|
+
|
|
4915
5011
|
module.exports = {
|
|
4916
5012
|
start,
|
|
4917
5013
|
stop,
|
|
4918
5014
|
status,
|
|
4919
|
-
config
|
|
5015
|
+
config,
|
|
5016
|
+
listAgents,
|
|
5017
|
+
PROVIDER_DEFINITIONS
|
|
4920
5018
|
};
|