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
|
@@ -5,21 +5,33 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
const chalk = require('chalk');
|
|
8
|
-
const { DirectLLMManager } = require('vibecodingmachine-core');
|
|
9
|
-
|
|
8
|
+
const { DirectLLMManager, AppleScriptManager, t, detectLocale, setLocale } = require('vibecodingmachine-core');
|
|
9
|
+
|
|
10
|
+
// Initialize locale detection for auto mode
|
|
11
|
+
const detectedLocale = detectLocale();
|
|
12
|
+
setLocale(detectedLocale);
|
|
13
|
+
const { getRepoPath, getAutoConfig, setAutoConfig, getStages, DEFAULT_STAGES } = require('../utils/config');
|
|
10
14
|
const { getRequirementsPath, readRequirements } = require('vibecodingmachine-core');
|
|
11
15
|
const fs = require('fs-extra');
|
|
12
16
|
const path = require('path');
|
|
13
17
|
const { spawn } = require('child_process');
|
|
14
18
|
const chokidar = require('chokidar');
|
|
19
|
+
const stringWidth = require('string-width');
|
|
20
|
+
const { getProviderPreferences, getProviderDefinition } = require('../utils/provider-registry');
|
|
21
|
+
const { createKeyboardHandler } = require('../utils/keyboard-handler');
|
|
22
|
+
const logger = require('../utils/logger');
|
|
23
|
+
const ProviderManager = require('vibecodingmachine-core/src/ide-integration/provider-manager.cjs');
|
|
24
|
+
const { checkAntigravityRateLimit, handleAntigravityRateLimit } = require('../utils/antigravity-js-handler');
|
|
25
|
+
|
|
15
26
|
// Status management will use in-process tracking instead of external file
|
|
16
27
|
const CLI_ENTRY_POINT = path.join(__dirname, '../../bin/vibecodingmachine.js');
|
|
17
|
-
const { getProviderPreferences, getProviderDefinition } = require('../utils/provider-registry');
|
|
18
28
|
|
|
19
29
|
// CRITICAL: Shared ProviderManager instance to track rate limits across all function calls
|
|
20
|
-
const ProviderManager = require('vibecodingmachine-core/src/ide-integration/provider-manager.cjs');
|
|
21
30
|
const sharedProviderManager = new ProviderManager();
|
|
22
31
|
|
|
32
|
+
// Configured stages (will be loaded in handleAutoStart)
|
|
33
|
+
let configuredStages = DEFAULT_STAGES;
|
|
34
|
+
|
|
23
35
|
/**
|
|
24
36
|
* Get timestamp for logging
|
|
25
37
|
*/
|
|
@@ -33,6 +45,25 @@ function getTimestamp() {
|
|
|
33
45
|
}) + ' MST';
|
|
34
46
|
}
|
|
35
47
|
|
|
48
|
+
/**
|
|
49
|
+
* Translate workflow stage names
|
|
50
|
+
*/
|
|
51
|
+
function translateStage(stage) {
|
|
52
|
+
const stageMap = {
|
|
53
|
+
'PREPARE': 'workflow.stage.prepare',
|
|
54
|
+
'REPRODUCE': 'workflow.stage.reproduce',
|
|
55
|
+
'CREATE UNIT TEST': 'workflow.stage.create.unit.test',
|
|
56
|
+
'ACT': 'workflow.stage.act',
|
|
57
|
+
'CLEAN UP': 'workflow.stage.clean.up',
|
|
58
|
+
'VERIFY': 'workflow.stage.verify',
|
|
59
|
+
'RUN UNIT TESTS': 'workflow.stage.run.unit.tests',
|
|
60
|
+
'DONE': 'workflow.stage.done'
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
const key = stageMap[stage];
|
|
64
|
+
return key ? t(key) : stage;
|
|
65
|
+
}
|
|
66
|
+
|
|
36
67
|
/**
|
|
37
68
|
* Strip ANSI escape codes from a string
|
|
38
69
|
*/
|
|
@@ -46,7 +77,6 @@ function stripAnsi(str) {
|
|
|
46
77
|
* Uses string-width library for accurate Unicode width calculation
|
|
47
78
|
*/
|
|
48
79
|
function getVisualWidth(str) {
|
|
49
|
-
const stringWidth = require('string-width');
|
|
50
80
|
return stringWidth(str);
|
|
51
81
|
}
|
|
52
82
|
|
|
@@ -111,7 +141,8 @@ async function updateRequirementsStatus(repoPath, status) {
|
|
|
111
141
|
break;
|
|
112
142
|
}
|
|
113
143
|
|
|
114
|
-
|
|
144
|
+
// Check against configured stages
|
|
145
|
+
if (inStatusSection && configuredStages.includes(line.trim())) {
|
|
115
146
|
statusLineIndex = i;
|
|
116
147
|
break;
|
|
117
148
|
}
|
|
@@ -143,7 +174,7 @@ async function updateRequirementsStatus(repoPath, status) {
|
|
|
143
174
|
await fs.writeFile(reqPath, lines.join('\n'));
|
|
144
175
|
} catch (error) {
|
|
145
176
|
// Silently fail - don't break execution if status update fails
|
|
146
|
-
console.error(chalk.gray(`
|
|
177
|
+
console.error(chalk.gray(` ${t('auto.direct.status.update.warning')} ${error.message}`));
|
|
147
178
|
}
|
|
148
179
|
}
|
|
149
180
|
|
|
@@ -160,28 +191,24 @@ let storedStatus = '';
|
|
|
160
191
|
* Now uses persistent header that stays at top while output scrolls
|
|
161
192
|
*/
|
|
162
193
|
function printStatusCard(currentTitle, currentStatus) {
|
|
163
|
-
const stages =
|
|
164
|
-
const stageMap = {
|
|
165
|
-
|
|
166
|
-
'ACT': 1,
|
|
167
|
-
'CLEAN UP': 2,
|
|
168
|
-
'VERIFY': 3,
|
|
169
|
-
'DONE': 4
|
|
170
|
-
};
|
|
194
|
+
const stages = configuredStages;
|
|
195
|
+
const stageMap = {};
|
|
196
|
+
stages.forEach((s, i) => stageMap[s] = i);
|
|
171
197
|
|
|
172
198
|
const currentIndex = stageMap[currentStatus] || 0;
|
|
173
199
|
|
|
174
200
|
// Build workflow line with visual prominence for current stage
|
|
175
201
|
const stageParts = stages.map((stage, idx) => {
|
|
202
|
+
const translatedStage = translateStage(stage);
|
|
176
203
|
if (idx < currentIndex) {
|
|
177
204
|
// Completed stages - grey with checkmark
|
|
178
|
-
return chalk.grey(`ā
${
|
|
205
|
+
return chalk.grey(`ā
${translatedStage}`);
|
|
179
206
|
} else if (idx === currentIndex) {
|
|
180
207
|
// CURRENT stage - BRIGHT WHITE with hammer
|
|
181
|
-
return chalk.bold.white(`šØ ${
|
|
208
|
+
return chalk.bold.white(`šØ ${translatedStage}`);
|
|
182
209
|
} else {
|
|
183
210
|
// Future stages - grey with hourglass
|
|
184
|
-
return chalk.grey(`ā³ ${
|
|
211
|
+
return chalk.grey(`ā³ ${translatedStage}`);
|
|
185
212
|
}
|
|
186
213
|
});
|
|
187
214
|
|
|
@@ -192,9 +219,10 @@ function printStatusCard(currentTitle, currentStatus) {
|
|
|
192
219
|
const boxWidth = Math.max(terminalWidth - 4, 80); // Leave 4 chars margin, minimum 80
|
|
193
220
|
|
|
194
221
|
// Truncate title if needed to fit in box
|
|
195
|
-
const
|
|
222
|
+
const workingOnLabel = `šÆ ${t('auto.direct.requirement.working.on')} `;
|
|
223
|
+
const maxTitleWidth = boxWidth - stringWidth(workingOnLabel) - 2; // Leave room for label
|
|
196
224
|
const titleShort = currentTitle?.substring(0, maxTitleWidth) + (currentTitle?.length > maxTitleWidth ? '...' : '');
|
|
197
|
-
const titleLine = chalk.cyan(
|
|
225
|
+
const titleLine = chalk.cyan(workingOnLabel) + chalk.white(titleShort);
|
|
198
226
|
|
|
199
227
|
// Build the status box content
|
|
200
228
|
const statusBoxContent =
|
|
@@ -249,7 +277,7 @@ async function getCurrentRequirement(repoPath) {
|
|
|
249
277
|
// Skip empty titles
|
|
250
278
|
if (title && title.length > 0) {
|
|
251
279
|
// Read package and description (optional)
|
|
252
|
-
let
|
|
280
|
+
let pkg = null;
|
|
253
281
|
let description = '';
|
|
254
282
|
let j = i + 1;
|
|
255
283
|
|
|
@@ -262,7 +290,7 @@ async function getCurrentRequirement(repoPath) {
|
|
|
262
290
|
}
|
|
263
291
|
// Check for PACKAGE line
|
|
264
292
|
if (nextLine.startsWith('PACKAGE:')) {
|
|
265
|
-
|
|
293
|
+
pkg = nextLine.replace(/^PACKAGE:\s*/, '').trim();
|
|
266
294
|
} else if (nextLine && !nextLine.startsWith('PACKAGE:')) {
|
|
267
295
|
// Description line (not empty, not package)
|
|
268
296
|
if (description) {
|
|
@@ -277,7 +305,7 @@ async function getCurrentRequirement(repoPath) {
|
|
|
277
305
|
return {
|
|
278
306
|
text: title,
|
|
279
307
|
fullLine: lines[i],
|
|
280
|
-
package:
|
|
308
|
+
package: pkg,
|
|
281
309
|
description: description
|
|
282
310
|
};
|
|
283
311
|
}
|
|
@@ -286,7 +314,7 @@ async function getCurrentRequirement(repoPath) {
|
|
|
286
314
|
|
|
287
315
|
return null;
|
|
288
316
|
} catch (err) {
|
|
289
|
-
console.error('
|
|
317
|
+
console.error(t('auto.direct.requirement.read.error'), err.message);
|
|
290
318
|
return null;
|
|
291
319
|
}
|
|
292
320
|
}
|
|
@@ -333,7 +361,7 @@ async function countTodoRequirements(repoPath) {
|
|
|
333
361
|
|
|
334
362
|
return count;
|
|
335
363
|
} catch (err) {
|
|
336
|
-
console.error('
|
|
364
|
+
console.error(t('auto.direct.requirement.count.error'), err.message);
|
|
337
365
|
return 0;
|
|
338
366
|
}
|
|
339
367
|
}
|
|
@@ -412,7 +440,7 @@ async function moveRequirementToVerify(repoPath, requirementText) {
|
|
|
412
440
|
}
|
|
413
441
|
|
|
414
442
|
if (requirementStartIndex === -1) {
|
|
415
|
-
console.log(chalk.yellow(`ā ļø
|
|
443
|
+
console.log(chalk.yellow(`ā ļø ${t('auto.direct.requirement.not.found.todo', { requirement: requirementText.substring(0, 60) + '...' })}`));
|
|
416
444
|
return false;
|
|
417
445
|
}
|
|
418
446
|
|
|
@@ -448,7 +476,7 @@ async function moveRequirementToVerify(repoPath, requirementText) {
|
|
|
448
476
|
|
|
449
477
|
// If no more TODO requirements, log message
|
|
450
478
|
if (!hasMoreTodoRequirements) {
|
|
451
|
-
console.log(chalk.green('
|
|
479
|
+
console.log(chalk.green(`š ${t('auto.direct.requirement.no.more.todo')}`));
|
|
452
480
|
}
|
|
453
481
|
|
|
454
482
|
|
|
@@ -533,7 +561,7 @@ async function moveRequirementToVerify(repoPath, requirementText) {
|
|
|
533
561
|
|
|
534
562
|
// Safety check: verifyIndex should be valid
|
|
535
563
|
if (verifyIndex === -1) {
|
|
536
|
-
console.error('
|
|
564
|
+
console.error(t('auto.direct.verify.section.create.failed'));
|
|
537
565
|
return false;
|
|
538
566
|
}
|
|
539
567
|
}
|
|
@@ -616,7 +644,7 @@ async function moveRequirementToVerify(repoPath, requirementText) {
|
|
|
616
644
|
console.log(chalk.green(`ā
Moved requirement to TO VERIFY BY HUMAN: ${requirementText.substring(0, 80)}...`));
|
|
617
645
|
return true;
|
|
618
646
|
} catch (err) {
|
|
619
|
-
console.error('
|
|
647
|
+
console.error(t('auto.direct.requirement.move.verify.error'), err.message);
|
|
620
648
|
console.error('ā ļø Requirement may have been lost. Please check the requirements file.');
|
|
621
649
|
return false;
|
|
622
650
|
}
|
|
@@ -647,7 +675,7 @@ async function moveRequirementToRecycle(repoPath, requirementText) {
|
|
|
647
675
|
}
|
|
648
676
|
|
|
649
677
|
if (requirementIndex === -1) {
|
|
650
|
-
console.log(chalk.yellow('
|
|
678
|
+
console.log(chalk.yellow(`ā ļø ${t('auto.direct.requirement.not.found')}`));
|
|
651
679
|
return false;
|
|
652
680
|
}
|
|
653
681
|
|
|
@@ -677,7 +705,7 @@ async function moveRequirementToRecycle(repoPath, requirementText) {
|
|
|
677
705
|
await fs.writeFile(reqPath, lines.join('\n'));
|
|
678
706
|
return true;
|
|
679
707
|
} catch (err) {
|
|
680
|
-
console.error('
|
|
708
|
+
console.error(t('auto.direct.requirement.move.error'), err.message);
|
|
681
709
|
return false;
|
|
682
710
|
}
|
|
683
711
|
}
|
|
@@ -859,19 +887,19 @@ async function acquireProviderConfig(excludeProvider = null) {
|
|
|
859
887
|
}
|
|
860
888
|
|
|
861
889
|
if (selection.status === 'no_providers') {
|
|
862
|
-
console.log(chalk.red(
|
|
890
|
+
console.log(chalk.red(`\nā ${t('auto.direct.provider.none.available')}\n`));
|
|
863
891
|
return null;
|
|
864
892
|
}
|
|
865
893
|
|
|
866
894
|
if (selection.status === 'no_enabled') {
|
|
867
|
-
console.log(chalk.red(
|
|
895
|
+
console.log(chalk.red(`\nā ${t('auto.direct.provider.all.disabled')}\n`));
|
|
868
896
|
return null;
|
|
869
897
|
}
|
|
870
898
|
|
|
871
899
|
if (selection.status === 'all_rate_limited') {
|
|
872
|
-
console.log(chalk.yellow(
|
|
900
|
+
console.log(chalk.yellow(`\nā ļø ${t('auto.direct.provider.all.rate.limited')}`));
|
|
873
901
|
if (selection.disabledProviders && selection.disabledProviders.length > 0) {
|
|
874
|
-
console.log(chalk.gray('
|
|
902
|
+
console.log(chalk.gray(` ${t('auto.direct.provider.enable.tip')}`));
|
|
875
903
|
}
|
|
876
904
|
const waitMs = selection.nextResetMs || 60000;
|
|
877
905
|
const waitMinutes = Math.max(1, Math.ceil(waitMs / 60000));
|
|
@@ -987,7 +1015,7 @@ async function applyFileChange(change, repoPath) {
|
|
|
987
1015
|
let content = await fs.readFile(fullPath, 'utf8');
|
|
988
1016
|
|
|
989
1017
|
// Try exact match first
|
|
990
|
-
console.log(chalk.gray(` š
|
|
1018
|
+
console.log(chalk.gray(` š ${t('auto.direct.files.trying.exact')}`));
|
|
991
1019
|
if (content.includes(change.search)) {
|
|
992
1020
|
const newContent = content.replace(change.search, change.replace);
|
|
993
1021
|
await fs.writeFile(fullPath, newContent, 'utf8');
|
|
@@ -997,7 +1025,7 @@ async function applyFileChange(change, repoPath) {
|
|
|
997
1025
|
console.log(chalk.gray(` ā Exact match failed`));
|
|
998
1026
|
|
|
999
1027
|
// Try with normalized whitespace (fuzzy match)
|
|
1000
|
-
console.log(chalk.gray(` š
|
|
1028
|
+
console.log(chalk.gray(` š ${t('auto.direct.files.trying.fuzzy')}`));
|
|
1001
1029
|
const normalizedSearch = normalizeWhitespace(change.search);
|
|
1002
1030
|
const lines = content.split('\n');
|
|
1003
1031
|
const searchLines = change.search.split('\n');
|
|
@@ -1125,7 +1153,7 @@ async function findRelevantFiles(requirement, repoPath) {
|
|
|
1125
1153
|
relevantFiles.push('packages/cli/src/utils/interactive.js');
|
|
1126
1154
|
}
|
|
1127
1155
|
} catch (error) {
|
|
1128
|
-
console.log(chalk.yellow(`ā ļø
|
|
1156
|
+
console.log(chalk.yellow(`ā ļø ${t('auto.direct.files.error')} ${error.message}`));
|
|
1129
1157
|
}
|
|
1130
1158
|
|
|
1131
1159
|
return relevantFiles;
|
|
@@ -1298,7 +1326,7 @@ async function readFileSnippets(files, repoPath, requirement) {
|
|
|
1298
1326
|
|
|
1299
1327
|
async function runIdeProviderIteration(providerConfig, repoPath) {
|
|
1300
1328
|
return new Promise((resolve) => {
|
|
1301
|
-
console.log(chalk.cyan(`āļø
|
|
1329
|
+
console.log(chalk.cyan(`āļø ${t('auto.direct.provider.launching', { provider: providerConfig.displayName })}\n`));
|
|
1302
1330
|
|
|
1303
1331
|
const args = [CLI_ENTRY_POINT, 'auto:start', '--ide', providerConfig.ide || providerConfig.provider, '--max-chats', String(providerConfig.maxChats || 1)];
|
|
1304
1332
|
const child = spawn(process.execPath, args, {
|
|
@@ -1334,11 +1362,14 @@ async function runIdeProviderIteration(providerConfig, repoPath) {
|
|
|
1334
1362
|
resolve({ success: true, output: combinedOutput });
|
|
1335
1363
|
} else {
|
|
1336
1364
|
const message = `${providerConfig.displayName} exited with code ${code}`;
|
|
1365
|
+
const antigravityRateLimit = checkAntigravityRateLimit(combinedOutput);
|
|
1366
|
+
|
|
1337
1367
|
resolve({
|
|
1338
1368
|
success: false,
|
|
1339
1369
|
error: combinedOutput ? `${message}\n${combinedOutput}` : message,
|
|
1340
1370
|
output: combinedOutput,
|
|
1341
|
-
rateLimited: isRateLimitMessage(combinedOutput)
|
|
1371
|
+
rateLimited: isRateLimitMessage(combinedOutput) || antigravityRateLimit.isRateLimited,
|
|
1372
|
+
antigravityRateLimited: antigravityRateLimit.isRateLimited
|
|
1342
1373
|
});
|
|
1343
1374
|
}
|
|
1344
1375
|
});
|
|
@@ -1362,9 +1393,9 @@ async function waitForIdeCompletion(repoPath, requirementText, ideType = '', tim
|
|
|
1362
1393
|
let quotaHandled = false;
|
|
1363
1394
|
const checkIntervalMs = 2000; // Check every 2 seconds
|
|
1364
1395
|
|
|
1365
|
-
console.log(chalk.gray(
|
|
1366
|
-
console.log(chalk.gray(`
|
|
1367
|
-
console.log(chalk.gray(`
|
|
1396
|
+
console.log(chalk.gray(`\nā³ ${t('auto.direct.ide.waiting')}`));
|
|
1397
|
+
console.log(chalk.gray(` ${t('auto.direct.ide.monitoring', { filename: path.basename(reqPath) })}`));
|
|
1398
|
+
console.log(chalk.gray(` ${t('auto.direct.ide.timeout', { minutes: Math.floor(timeoutMs / 60000) })}\n`));
|
|
1368
1399
|
|
|
1369
1400
|
const watcher = chokidar.watch(reqPath, {
|
|
1370
1401
|
persistent: true,
|
|
@@ -1435,26 +1466,15 @@ async function waitForIdeCompletion(repoPath, requirementText, ideType = '', tim
|
|
|
1435
1466
|
// Check 3: Quota limit detection for Antigravity (after 2 minutes of waiting)
|
|
1436
1467
|
const elapsed = Date.now() - startTime;
|
|
1437
1468
|
if (ideType === 'antigravity' && !quotaHandled && elapsed >= 120000) {
|
|
1438
|
-
console.log(chalk.yellow('\nā ļø
|
|
1439
|
-
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1444
|
-
|
|
1445
|
-
|
|
1446
|
-
|
|
1447
|
-
quotaHandled = true;
|
|
1448
|
-
// Reset start time to give new model time to work
|
|
1449
|
-
startTime = Date.now();
|
|
1450
|
-
} else {
|
|
1451
|
-
console.log(chalk.yellow(`ā ļø Could not switch models: ${result.error}\n`));
|
|
1452
|
-
quotaHandled = true; // Don't try again
|
|
1453
|
-
}
|
|
1454
|
-
} catch (error) {
|
|
1455
|
-
console.error(chalk.red(`Error handling quota limit: ${error.message}\n`));
|
|
1456
|
-
quotaHandled = true; // Don't try again
|
|
1457
|
-
}
|
|
1469
|
+
console.log(chalk.yellow('\nā ļø Antigravity quota limit detected after 2 minutes\n'));
|
|
1470
|
+
console.log(chalk.cyan(' Switching to next available IDE agent...\n'));
|
|
1471
|
+
watcher.close();
|
|
1472
|
+
resolve({
|
|
1473
|
+
success: false,
|
|
1474
|
+
reason: 'antigravity-quota',
|
|
1475
|
+
antigravityRateLimited: true // This triggers switching to next provider
|
|
1476
|
+
});
|
|
1477
|
+
return;
|
|
1458
1478
|
}
|
|
1459
1479
|
|
|
1460
1480
|
// Check 4: Timeout
|
|
@@ -1469,7 +1489,7 @@ async function waitForIdeCompletion(repoPath, requirementText, ideType = '', tim
|
|
|
1469
1489
|
if (Date.now() - lastCheckTime >= 30000) {
|
|
1470
1490
|
const elapsedMin = Math.floor(elapsed / 60000);
|
|
1471
1491
|
const remainingMin = Math.floor((timeoutMs - elapsed) / 60000);
|
|
1472
|
-
console.log(chalk.gray(`
|
|
1492
|
+
console.log(chalk.gray(` ${t('auto.direct.ide.still.waiting', { elapsed: elapsedMin, remaining: remainingMin })}`));
|
|
1473
1493
|
lastCheckTime = Date.now();
|
|
1474
1494
|
}
|
|
1475
1495
|
} catch (error) {
|
|
@@ -1503,7 +1523,7 @@ async function runIdeFallbackIteration(requirement, providerConfig, repoPath, pr
|
|
|
1503
1523
|
// Update console and requirements file with PREPARE status
|
|
1504
1524
|
printStatusCard(requirement.text, 'PREPARE');
|
|
1505
1525
|
await updateRequirementsStatus(repoPath, 'PREPARE');
|
|
1506
|
-
console.log(chalk.gray('
|
|
1526
|
+
console.log(chalk.gray(`${t('auto.direct.ide.skipping.context')}\n`));
|
|
1507
1527
|
|
|
1508
1528
|
// Update console and requirements file with ACT status
|
|
1509
1529
|
printStatusCard(requirement.text, 'ACT');
|
|
@@ -1511,17 +1531,27 @@ async function runIdeFallbackIteration(requirement, providerConfig, repoPath, pr
|
|
|
1511
1531
|
const ideResult = await runIdeProviderIteration(providerConfig, repoPath);
|
|
1512
1532
|
|
|
1513
1533
|
if (!ideResult.success) {
|
|
1534
|
+
if (ideResult.antigravityRateLimited) {
|
|
1535
|
+
await handleAntigravityRateLimit();
|
|
1536
|
+
return { success: false, error: 'Antigravity rate limit detected, retrying with next provider.', shouldRetry: true };
|
|
1537
|
+
}
|
|
1514
1538
|
// CRITICAL: Mark provider as unavailable for ANY error so acquireProviderConfig() will skip it
|
|
1515
1539
|
providerManager.markRateLimited(providerConfig.provider, providerConfig.model, ideResult.output || ideResult.error || 'IDE provider failed');
|
|
1516
1540
|
return { success: false, error: ideResult.error || 'IDE provider failed' };
|
|
1517
1541
|
}
|
|
1518
1542
|
|
|
1519
|
-
console.log(chalk.green('
|
|
1543
|
+
console.log(chalk.green(`ā ${t('auto.direct.ide.prompt.sent')}`));
|
|
1520
1544
|
|
|
1521
1545
|
// Wait for IDE agent to complete the work (IDE will update status to DONE itself)
|
|
1522
1546
|
const completionResult = await waitForIdeCompletion(repoPath, requirement.text, providerConfig.ide || providerConfig.provider);
|
|
1523
1547
|
|
|
1524
1548
|
if (!completionResult.success) {
|
|
1549
|
+
if (completionResult.antigravityRateLimited) {
|
|
1550
|
+
console.log(chalk.yellow(`ā ļø ${t('auto.direct.provider.quota.exhausted', { provider: 'Antigravity' })}\n`));
|
|
1551
|
+
providerManager.markRateLimited(providerConfig.provider, providerConfig.model, 'Quota limit reached');
|
|
1552
|
+
return { success: false, error: 'Antigravity quota limit', shouldRetry: true };
|
|
1553
|
+
}
|
|
1554
|
+
|
|
1525
1555
|
const errorMsg = completionResult.reason === 'timeout'
|
|
1526
1556
|
? 'IDE agent timed out'
|
|
1527
1557
|
: 'IDE agent failed to complete';
|
|
@@ -1530,7 +1560,7 @@ async function runIdeFallbackIteration(requirement, providerConfig, repoPath, pr
|
|
|
1530
1560
|
}
|
|
1531
1561
|
|
|
1532
1562
|
printStatusCard(requirement.text, 'VERIFY');
|
|
1533
|
-
console.log(chalk.green('
|
|
1563
|
+
console.log(chalk.green(`ā
${t('auto.direct.provider.completed')}\n`));
|
|
1534
1564
|
|
|
1535
1565
|
printStatusCard(requirement.text, 'DONE');
|
|
1536
1566
|
const duration = Date.now() - startTime;
|
|
@@ -1538,7 +1568,7 @@ async function runIdeFallbackIteration(requirement, providerConfig, repoPath, pr
|
|
|
1538
1568
|
|
|
1539
1569
|
const moved = await moveRequirementToVerify(repoPath, requirement.text);
|
|
1540
1570
|
if (moved) {
|
|
1541
|
-
console.log(chalk.green(
|
|
1571
|
+
console.log(chalk.green(`ā ${t('auto.direct.status.verification.pending')}`));
|
|
1542
1572
|
} else {
|
|
1543
1573
|
console.log(chalk.yellow('ā ļø Requirement still pending verification in REQUIREMENTS file'));
|
|
1544
1574
|
}
|
|
@@ -1569,15 +1599,15 @@ async function runIteration(requirement, providerConfig, repoPath) {
|
|
|
1569
1599
|
|
|
1570
1600
|
console.log(chalk.bold.white('š REQUIREMENT:'));
|
|
1571
1601
|
console.log(chalk.cyan(` ${requirement.text}\n`));
|
|
1572
|
-
console.log(chalk.gray('
|
|
1573
|
-
console.log(chalk.gray('
|
|
1602
|
+
console.log(chalk.gray(t('auto.direct.summary.provider')), chalk.white(providerConfig.displayName));
|
|
1603
|
+
console.log(chalk.gray(t('auto.repository')), chalk.white(repoPath));
|
|
1574
1604
|
console.log();
|
|
1575
1605
|
|
|
1576
|
-
console.log(chalk.cyan('
|
|
1606
|
+
console.log(chalk.cyan(`š ${t('auto.direct.files.searching')}...\n`));
|
|
1577
1607
|
const relevantFiles = await findRelevantFiles(requirement.text, repoPath);
|
|
1578
1608
|
|
|
1579
1609
|
if (relevantFiles.length > 0) {
|
|
1580
|
-
console.log(chalk.white('
|
|
1610
|
+
console.log(chalk.white(`${t('auto.direct.files.found', { count: relevantFiles.length })}:`));
|
|
1581
1611
|
relevantFiles.forEach((file, i) => {
|
|
1582
1612
|
console.log(chalk.gray(` ${i + 1}. ${file}`));
|
|
1583
1613
|
});
|
|
@@ -1841,17 +1871,17 @@ Now implement the requirement. Remember: COPY THE SEARCH BLOCK EXACTLY!`;
|
|
|
1841
1871
|
|
|
1842
1872
|
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
1843
1873
|
|
|
1844
|
-
console.log(chalk.bold.green(
|
|
1845
|
-
console.log(chalk.white('
|
|
1846
|
-
console.log(chalk.white('
|
|
1847
|
-
console.log(chalk.white('
|
|
1848
|
-
console.log(chalk.white('
|
|
1874
|
+
console.log(chalk.bold.green(`ā
${t('auto.direct.requirement.completed')}\n`));
|
|
1875
|
+
console.log(chalk.white(`${t('auto.direct.requirement.title')}`), chalk.cyan(requirement.text));
|
|
1876
|
+
console.log(chalk.white(t('auto.direct.summary.files.modified')), chalk.cyan(changes.length));
|
|
1877
|
+
console.log(chalk.white(t('auto.direct.summary.status')), chalk.green(t('auto.direct.summary.moving.to.verify')));
|
|
1878
|
+
console.log(chalk.white(t('auto.direct.summary.time')), chalk.gray(`${elapsed}s`));
|
|
1849
1879
|
console.log();
|
|
1850
1880
|
|
|
1851
1881
|
// Move requirement to TO VERIFY section
|
|
1852
1882
|
const moved = await moveRequirementToVerify(repoPath, requirement.text);
|
|
1853
1883
|
if (moved) {
|
|
1854
|
-
console.log(chalk.green(
|
|
1884
|
+
console.log(chalk.green(`ā ${t('auto.direct.status.verification.pending')}`));
|
|
1855
1885
|
} else {
|
|
1856
1886
|
console.log(chalk.yellow('ā ļø Could not automatically move requirement'));
|
|
1857
1887
|
}
|
|
@@ -1886,22 +1916,32 @@ async function handleAutoStart(options) {
|
|
|
1886
1916
|
}
|
|
1887
1917
|
}
|
|
1888
1918
|
|
|
1889
|
-
console.log(chalk.bold.cyan('\n
|
|
1919
|
+
console.log(chalk.bold.cyan('\n' + t('auto.direct.title') + '\n'));
|
|
1890
1920
|
console.log(chalk.gray('ā'.repeat(80)));
|
|
1891
1921
|
console.log();
|
|
1892
1922
|
|
|
1893
1923
|
// Get repo path
|
|
1924
|
+
// Load configured stages
|
|
1925
|
+
configuredStages = await getStages();
|
|
1926
|
+
|
|
1894
1927
|
const repoPath = await getRepoPath();
|
|
1895
1928
|
if (!repoPath) {
|
|
1896
1929
|
console.log(chalk.red('ā No repository configured'));
|
|
1897
|
-
console.log(chalk.gray('
|
|
1930
|
+
console.log(chalk.gray(t('auto.direct.config.repo.not.set')));
|
|
1898
1931
|
return;
|
|
1899
1932
|
}
|
|
1900
1933
|
|
|
1901
|
-
console.log(chalk.white('
|
|
1934
|
+
console.log(chalk.white(t('auto.repository')), chalk.cyan(repoPath));
|
|
1902
1935
|
|
|
1903
|
-
// Get
|
|
1904
|
-
|
|
1936
|
+
// Get effective agent using centralized selector
|
|
1937
|
+
const { getEffectiveAgent } = require('../utils/agent-selector');
|
|
1938
|
+
const { PROVIDER_DEFINITIONS } = require('../utils/provider-registry');
|
|
1939
|
+
const PROVIDER_DEFINITION_MAP = new Map(PROVIDER_DEFINITIONS.map(def => [def.id, def]));
|
|
1940
|
+
|
|
1941
|
+
const { effectiveAgent } = await getEffectiveAgent(options, PROVIDER_DEFINITIONS, PROVIDER_DEFINITION_MAP);
|
|
1942
|
+
|
|
1943
|
+
// Get provider configuration for the selected agent
|
|
1944
|
+
let providerConfig = await acquireProviderConfig(effectiveAgent);
|
|
1905
1945
|
if (!providerConfig) {
|
|
1906
1946
|
return;
|
|
1907
1947
|
}
|
|
@@ -1912,7 +1952,7 @@ async function handleAutoStart(options) {
|
|
|
1912
1952
|
const config = await getAutoConfig();
|
|
1913
1953
|
const unlimited = !options.maxChats && !config.maxChats && config.neverStop;
|
|
1914
1954
|
const maxChats = unlimited ? Number.MAX_SAFE_INTEGER : (options.maxChats || config.maxChats || 1);
|
|
1915
|
-
console.log(chalk.white('
|
|
1955
|
+
console.log(chalk.white(`${t('auto.direct.config.max.iterations')}`), unlimited ? chalk.cyan('ā (never stop)') : chalk.cyan(maxChats));
|
|
1916
1956
|
console.log();
|
|
1917
1957
|
console.log(chalk.gray('ā'.repeat(80)));
|
|
1918
1958
|
|
|
@@ -1929,7 +1969,7 @@ async function handleAutoStart(options) {
|
|
|
1929
1969
|
const requirement = await getCurrentRequirement(repoPath);
|
|
1930
1970
|
if (!requirement) {
|
|
1931
1971
|
console.log(chalk.bold.yellow('\nš All requirements completed!'));
|
|
1932
|
-
console.log(chalk.gray('
|
|
1972
|
+
console.log(chalk.gray(`${t('auto.direct.no.more.todo.items')}\n`));
|
|
1933
1973
|
break;
|
|
1934
1974
|
}
|
|
1935
1975
|
|
|
@@ -1938,7 +1978,7 @@ async function handleAutoStart(options) {
|
|
|
1938
1978
|
const currentReqNumber = completedCount + failedCount + 1;
|
|
1939
1979
|
|
|
1940
1980
|
console.log(chalk.bold.magenta(`\n${'ā'.repeat(80)}`));
|
|
1941
|
-
console.log(chalk.bold.magenta(`
|
|
1981
|
+
console.log(chalk.bold.magenta(` ${t('auto.direct.requirement.header', { current: currentReqNumber, total: initialEffectiveMax })}`));
|
|
1942
1982
|
console.log(chalk.bold.magenta(`${'ā'.repeat(80)}\n`));
|
|
1943
1983
|
|
|
1944
1984
|
// Run iteration with full workflow
|
|
@@ -1971,7 +2011,7 @@ async function handleAutoStart(options) {
|
|
|
1971
2011
|
|
|
1972
2012
|
// Handle child errors (but don't wait for completion)
|
|
1973
2013
|
child.on('error', (err) => {
|
|
1974
|
-
console.error(chalk.red('
|
|
2014
|
+
console.error(chalk.red(t('auto.direct.config.restart.error')), err.message);
|
|
1975
2015
|
});
|
|
1976
2016
|
|
|
1977
2017
|
// Don't wait for child - unref so parent can exit
|
|
@@ -2027,20 +2067,20 @@ async function handleAutoStart(options) {
|
|
|
2027
2067
|
console.log(chalk.bold.magenta(`${'ā'.repeat(80)}\n`));
|
|
2028
2068
|
|
|
2029
2069
|
const totalProcessed = completedCount + failedCount;
|
|
2030
|
-
console.log(chalk.white('
|
|
2031
|
-
console.log(chalk.white('
|
|
2070
|
+
console.log(chalk.white(t('auto.direct.summary.total.requirements')), chalk.cyan(totalProcessed));
|
|
2071
|
+
console.log(chalk.white(t('auto.direct.summary.completed')), chalk.green(`${completedCount} ā`));
|
|
2032
2072
|
if (failedCount > 0) {
|
|
2033
|
-
console.log(chalk.white('
|
|
2073
|
+
console.log(chalk.white(t('auto.direct.summary.failed')), chalk.red(`${failedCount} ā`));
|
|
2034
2074
|
}
|
|
2035
|
-
console.log(chalk.white('
|
|
2075
|
+
console.log(chalk.white(t('auto.direct.summary.provider')), chalk.cyan(providerConfig.displayName));
|
|
2036
2076
|
console.log();
|
|
2037
2077
|
|
|
2038
2078
|
if (completedCount > 0) {
|
|
2039
|
-
console.log(chalk.bold.green(`š ${
|
|
2079
|
+
console.log(chalk.bold.green(`š ${t('auto.direct.summary.final.message', { count: completedCount, plural: completedCount > 1 ? 's' : '' })}`));
|
|
2040
2080
|
}
|
|
2041
2081
|
|
|
2042
2082
|
} catch (error) {
|
|
2043
|
-
console.error(chalk.red('\n
|
|
2083
|
+
console.error(chalk.red('\n' + t('auto.fatal.error')), error.message);
|
|
2044
2084
|
if (error.stack) {
|
|
2045
2085
|
console.log(chalk.gray(error.stack));
|
|
2046
2086
|
}
|