vibecodingmachine-cli 2026.3.14-1537 ā 2026.6.17-1956
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 +7 -7
- package/bin/commands/agent-commands.js +15 -15
- package/bin/commands/auto-commands.js +3 -3
- package/bin/commands/command-aliases.js +13 -4
- package/bin/config/cli-config.js +15 -5
- package/bin/update/update-checker.js +5 -5
- package/bin/vibecodingmachine.js +2 -2
- package/package.json +2 -2
- package/src/commands/agents/add.js +5 -5
- package/src/commands/agents/check.js +19 -19
- package/src/commands/agents/list.js +24 -24
- package/src/commands/agents/remove.js +4 -4
- package/src/commands/agents-check.js +1 -1
- package/src/commands/analyze-file-sizes.js +43 -43
- package/src/commands/auto-direct/auto-provider-manager.js +19 -19
- package/src/commands/auto-direct/auto-start-phases.js +493 -0
- package/src/commands/auto-direct/auto-status-display.js +35 -35
- package/src/commands/auto-direct/auto-utils.js +50 -50
- package/src/commands/auto-direct/cline-installer.js +56 -0
- package/src/commands/auto-direct/code-processor.js +27 -27
- package/src/commands/auto-direct/file-scanner.js +19 -19
- package/src/commands/auto-direct/ide-completion-waiter.js +485 -0
- package/src/commands/auto-direct/ide-fallback-runner.js +226 -0
- package/src/commands/auto-direct/ide-provider-runner.js +103 -0
- package/src/commands/auto-direct/iteration-handlers.js +189 -0
- package/src/commands/auto-direct/iteration-runner.js +485 -0
- package/src/commands/auto-direct/provider-config.js +38 -7
- package/src/commands/auto-direct/provider-manager.js +132 -6
- package/src/commands/auto-direct/requirement-manager.js +169 -104
- package/src/commands/auto-direct/requirement-mover.js +350 -0
- package/src/commands/auto-direct/spec-handlers.js +155 -0
- package/src/commands/auto-direct/spec-ide-runner.js +318 -0
- package/src/commands/auto-direct/spec-processing.js +203 -0
- package/src/commands/auto-direct/status-display.js +9 -9
- package/src/commands/auto-direct/utils.js +83 -1
- package/src/commands/auto-direct-refactored.js +1 -413
- package/src/commands/auto-direct.js +127 -4119
- package/src/commands/auto-execution.js +21 -21
- package/src/commands/auto-status-helpers.js +0 -2
- package/src/commands/auto.js +22 -22
- package/src/commands/check-compliance.js +65 -65
- package/src/commands/computers.js +39 -39
- package/src/commands/continuous-scan.js +19 -19
- package/src/commands/ide.js +4 -4
- package/src/commands/locale.js +7 -7
- package/src/commands/refactor-file.js +59 -59
- package/src/commands/requirements/commands.js +17 -17
- package/src/commands/requirements/default-handlers.js +30 -30
- package/src/commands/requirements/disable.js +3 -3
- package/src/commands/requirements/enable.js +3 -3
- package/src/commands/requirements/utils.js +6 -6
- package/src/commands/requirements-refactored.js +3 -3
- package/src/commands/requirements-remote.js +38 -38
- package/src/commands/requirements.js +3 -3
- package/src/commands/settings.js +111 -0
- package/src/commands/specs/count.js +60 -0
- package/src/commands/specs/disable.js +3 -3
- package/src/commands/specs/enable.js +3 -3
- package/src/commands/status.js +10 -10
- package/src/commands/sync.js +25 -25
- package/src/commands/timeout.js +35 -35
- package/src/trui/TruiInterface.js +2 -2
- package/src/trui/agents/AgentInterface.js +4 -4
- package/src/trui/agents/handlers/CommandHandler.js +4 -4
- package/src/trui/agents/handlers/ContextManager.js +1 -1
- package/src/trui/agents/handlers/DisplayHandler.js +11 -11
- package/src/trui/agents/handlers/HelpHandler.js +1 -1
- package/src/utils/agent-selector.js +6 -6
- package/src/utils/antigravity-installer.js +4 -4
- package/src/utils/asset-cleanup.js +1 -1
- package/src/utils/auth.js +9 -12
- package/src/utils/clarification-actions.js +4 -4
- package/src/utils/cline-js-handler.js +5 -5
- package/src/utils/compliance-check.js +6 -6
- package/src/utils/config.js +12 -12
- package/src/utils/display-formatters-complete.js +2 -2
- package/src/utils/display-formatters-extracted.js +2 -2
- package/src/utils/display-formatters.js +2 -2
- package/src/utils/feedback-handler.js +2 -2
- package/src/utils/first-run.js +7 -7
- package/src/utils/ide-detection.js +1 -1
- package/src/utils/ide-handlers.js +6 -6
- package/src/utils/interactive/clarification-actions.js +3 -3
- package/src/utils/interactive/core-ui.js +7 -7
- package/src/utils/interactive/file-backup.js +6 -6
- package/src/utils/interactive/file-import-export.js +49 -49
- package/src/utils/interactive/file-operations.js +3 -3
- package/src/utils/interactive/file-validation.js +41 -41
- package/src/utils/interactive/interactive-prompts.js +41 -41
- package/src/utils/interactive/requirement-actions.js +5 -5
- package/src/utils/interactive/requirement-crud.js +4 -4
- package/src/utils/interactive/requirements-navigation.js +10 -10
- package/src/utils/interactive-broken.js +6 -6
- package/src/utils/interactive.js +37 -37
- package/src/utils/keyboard-handler.js +4 -4
- package/src/utils/prompt-helper.js +6 -6
- package/src/utils/provider-checker/agent-checker.js +1 -1
- package/src/utils/provider-checker/agent-runner.js +203 -314
- package/src/utils/provider-checker/agents-file-lock.js +134 -0
- package/src/utils/provider-checker/agents-manager.js +224 -36
- package/src/utils/provider-checker/cli-installer.js +28 -28
- package/src/utils/provider-checker/cli-utils.js +2 -2
- package/src/utils/provider-checker/cursor-approval-clicker.js +108 -0
- package/src/utils/provider-checker/format-utils.js +4 -4
- package/src/utils/provider-checker/ide-installer-helper.js +96 -0
- package/src/utils/provider-checker/ide-manager.js +19 -8
- package/src/utils/provider-checker/ide-quota-checker.js +120 -0
- package/src/utils/provider-checker/ide-utils.js +2 -2
- package/src/utils/provider-checker/node-detector.js +4 -4
- package/src/utils/provider-checker/node-utils.js +5 -5
- package/src/utils/provider-checker/opencode-checker.js +107 -73
- package/src/utils/provider-checker/process-utils.js +1 -1
- package/src/utils/provider-checker/provider-validator.js +11 -11
- package/src/utils/provider-checker/quota-checker.js +5 -5
- package/src/utils/provider-checker/quota-detector.js +5 -5
- package/src/utils/provider-checker/requirements-manager.js +6 -6
- package/src/utils/provider-checker/test-requirements.js +1 -1
- package/src/utils/provider-checker/vscode-approval-clicker.js +328 -0
- package/src/utils/provider-checker-new.js +6 -6
- package/src/utils/provider-checker.js +6 -6
- package/src/utils/provider-checkers/ide-manager.js +13 -13
- package/src/utils/provider-checkers/node-executable-finder.js +4 -4
- package/src/utils/provider-checkers/provider-checker-core.js +5 -5
- package/src/utils/provider-checkers/provider-checker-main.js +17 -17
- package/src/utils/provider-registry.js +5 -6
- package/src/utils/provider-utils.js +12 -12
- package/src/utils/quota-detectors.js +32 -32
- package/src/utils/requirement-action-handlers.js +12 -12
- package/src/utils/requirement-actions/requirement-operations.js +3 -3
- package/src/utils/requirement-actions.js +1 -1
- package/src/utils/requirement-file-operations.js +5 -5
- package/src/utils/requirement-helpers.js +1 -1
- package/src/utils/requirement-management.js +5 -5
- package/src/utils/requirement-navigation.js +2 -2
- package/src/utils/requirement-organization.js +3 -3
- package/src/utils/rui-trui-adapter.js +14 -14
- package/src/utils/simple-trui.js +3 -3
- package/src/utils/status-helpers-extracted.js +3 -3
- package/src/utils/trui-clarifications.js +11 -11
- package/src/utils/trui-debug.js +3 -2
- package/src/utils/trui-devin.js +217 -0
- package/src/utils/trui-feedback.js +7 -7
- package/src/utils/trui-kiro-integration.js +34 -34
- package/src/utils/trui-main-handlers.js +20 -21
- package/src/utils/trui-main-menu.js +19 -19
- package/src/utils/trui-nav-agents.js +59 -8
- package/src/utils/trui-nav-requirements.js +3 -3
- package/src/utils/trui-nav-settings.js +10 -10
- package/src/utils/trui-nav-specifications.js +1 -1
- package/src/utils/trui-navigation-backup.js +11 -11
- package/src/utils/trui-navigation.js +9 -9
- package/src/utils/trui-provider-health.js +25 -25
- package/src/utils/trui-provider-manager.js +28 -28
- package/src/utils/trui-quick-menu.js +2 -2
- package/src/utils/trui-req-actions-backup.js +21 -21
- package/src/utils/trui-req-actions.js +20 -20
- package/src/utils/trui-req-editor.js +10 -10
- package/src/utils/trui-req-file-ops.js +3 -3
- package/src/utils/trui-req-tree.js +7 -7
- package/src/utils/trui-windsurf.js +103 -103
- package/src/utils/user-tracking.js +15 -15
- package/src/utils/trui-req-tree-old.js +0 -719
|
@@ -0,0 +1,493 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auto Start Phase Handlers
|
|
3
|
+
*
|
|
4
|
+
* Extracted from auto-direct.js handleAutoStart function for constitutional compliance
|
|
5
|
+
* Contains initialization and processing loop logic for autonomous mode
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const fs = require('fs-extra');
|
|
11
|
+
const { spawn } = require('child_process');
|
|
12
|
+
const vibecodingmachineCore = require('vibecodingmachine-core');
|
|
13
|
+
const {
|
|
14
|
+
AppleScriptManager,
|
|
15
|
+
t,
|
|
16
|
+
RequirementFileParser,
|
|
17
|
+
RequirementSequencer,
|
|
18
|
+
DefaultRequirementManager,
|
|
19
|
+
JSONStorage
|
|
20
|
+
} = vibecodingmachineCore;
|
|
21
|
+
|
|
22
|
+
const { getEffectiveRepoPath, getAutoConfig, setAutoConfig, getStages } = require('../../utils/config');
|
|
23
|
+
const { getRequirementsPath } = require('vibecodingmachine-core');
|
|
24
|
+
const { createKeyboardHandler } = require('../../utils/keyboard-handler');
|
|
25
|
+
const { startAutoMode, updateAutoModeStatus } = require('../../utils/auto-mode');
|
|
26
|
+
|
|
27
|
+
// Import modular functions
|
|
28
|
+
const { isRateLimitMessage } = require('./utils');
|
|
29
|
+
const {
|
|
30
|
+
updateRequirementsStatus,
|
|
31
|
+
getCurrentRequirement,
|
|
32
|
+
countTodoRequirements
|
|
33
|
+
} = require('./requirement-manager');
|
|
34
|
+
const {
|
|
35
|
+
printStatusCard
|
|
36
|
+
} = require('./status-display');
|
|
37
|
+
const {
|
|
38
|
+
runIteration,
|
|
39
|
+
runSpecIdeIteration
|
|
40
|
+
} = require('./iteration-handlers');
|
|
41
|
+
const {
|
|
42
|
+
countSpecCheckboxes,
|
|
43
|
+
getNextSpecTask,
|
|
44
|
+
loadEnabledIncompleteSpecs,
|
|
45
|
+
processDefaultRequirement
|
|
46
|
+
} = require('./spec-handlers');
|
|
47
|
+
const {
|
|
48
|
+
acquireProviderConfig
|
|
49
|
+
} = require('./provider-config');
|
|
50
|
+
const {
|
|
51
|
+
handleSpecPlanning,
|
|
52
|
+
handleTasksRegeneration
|
|
53
|
+
} = require('./spec-processing');
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Initialize auto mode - authentication, config, keyboard handler, repository setup
|
|
57
|
+
*
|
|
58
|
+
* @param {Object} options - Command line options
|
|
59
|
+
* @param {Object} sharedRefs - Shared references for keyboard handler and status
|
|
60
|
+
* @returns {Promise<Object>} Initialized state object
|
|
61
|
+
*/
|
|
62
|
+
async function initializeAutoMode(options, sharedRefs) {
|
|
63
|
+
// STRICT AUTH CHECK
|
|
64
|
+
const auth = require('../../utils/auth');
|
|
65
|
+
const isAuth = await auth.isAuthenticated();
|
|
66
|
+
if (!isAuth) {
|
|
67
|
+
console.log(chalk.cyan('\nš Opening browser for authentication...\n'));
|
|
68
|
+
try {
|
|
69
|
+
await auth.login();
|
|
70
|
+
console.log(chalk.green('\nā Authentication successful!\n'));
|
|
71
|
+
} catch (error) {
|
|
72
|
+
console.log(chalk.red('\nā Authentication failed:'), error.message);
|
|
73
|
+
process.exit(1);
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
console.log(chalk.bold.cyan('\n' + t('auto.direct.title') + '\n'));
|
|
78
|
+
console.log(chalk.gray('ā'.repeat(80)));
|
|
79
|
+
console.log();
|
|
80
|
+
|
|
81
|
+
const repoPath = await getEffectiveRepoPath();
|
|
82
|
+
if (!repoPath) {
|
|
83
|
+
console.log(chalk.red('ā No repository configured'));
|
|
84
|
+
console.log(chalk.gray(t('auto.direct.config.repo.not.set')));
|
|
85
|
+
throw new Error('No repository configured');
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Create keyboard handler for 'x' key exit
|
|
89
|
+
sharedRefs.keyboardHandler = createKeyboardHandler({
|
|
90
|
+
onExit: () => {
|
|
91
|
+
updateAutoModeStatus(repoPath, { running: false });
|
|
92
|
+
console.log(chalk.gray('Auto mode stopped'));
|
|
93
|
+
if (sharedRefs.storedStatusTitle && sharedRefs.storedStatus) {
|
|
94
|
+
printStatusCard(sharedRefs.storedStatusTitle, sharedRefs.storedStatus, 'stopped');
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// Start keyboard handler
|
|
100
|
+
sharedRefs.keyboardHandler.start();
|
|
101
|
+
|
|
102
|
+
// Ensure keyboard handler is cleaned up on exit
|
|
103
|
+
const cleanup = () => {
|
|
104
|
+
if (sharedRefs.keyboardHandler) {
|
|
105
|
+
sharedRefs.keyboardHandler.stop();
|
|
106
|
+
}
|
|
107
|
+
};
|
|
108
|
+
|
|
109
|
+
process.on('exit', cleanup);
|
|
110
|
+
process.on('SIGINT', () => {
|
|
111
|
+
cleanup();
|
|
112
|
+
process.exit(0);
|
|
113
|
+
});
|
|
114
|
+
process.on('SIGTERM', () => {
|
|
115
|
+
cleanup();
|
|
116
|
+
process.exit(0);
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
// Start Auto Mode status tracking
|
|
120
|
+
const config = await getAutoConfig();
|
|
121
|
+
|
|
122
|
+
// Save extension to config if provided
|
|
123
|
+
if (options.extension) {
|
|
124
|
+
config.extension = options.extension;
|
|
125
|
+
await setAutoConfig(config);
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
await startAutoMode(repoPath, { ide: options.ide || config.ide });
|
|
129
|
+
|
|
130
|
+
// Load configured stages
|
|
131
|
+
const configuredStages = await getStages();
|
|
132
|
+
|
|
133
|
+
// Initialize requirement monitoring for default requirement management
|
|
134
|
+
const requirementsPath = await getRequirementsPath(repoPath);
|
|
135
|
+
const storage = new JSONStorage();
|
|
136
|
+
const parser = new RequirementFileParser();
|
|
137
|
+
const defaultManager = new DefaultRequirementManager(storage);
|
|
138
|
+
const sequencer = new RequirementSequencer(parser, defaultManager);
|
|
139
|
+
|
|
140
|
+
// Start monitoring requirements file for changes
|
|
141
|
+
const stopMonitoring = sequencer.monitorRequirements(requirementsPath, async (changeType, change) => {
|
|
142
|
+
if (changeType === 'regular-requirements-added') {
|
|
143
|
+
console.log(chalk.bold.yellow('\nš New regular requirements detected'));
|
|
144
|
+
console.log(chalk.gray('Default requirement will be paused to process regular requirements first\n'));
|
|
145
|
+
} else if (changeType === 'regular-requirements-completed') {
|
|
146
|
+
console.log(chalk.bold.green('\nā
All regular requirements completed'));
|
|
147
|
+
console.log(chalk.gray('Default requirement will be resumed\n'));
|
|
148
|
+
}
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
console.log(chalk.white(t('auto.repository')), chalk.cyan(repoPath));
|
|
152
|
+
|
|
153
|
+
// Use the agent that was already determined by provider preferences
|
|
154
|
+
const effectiveAgent = options.ide;
|
|
155
|
+
|
|
156
|
+
// Get provider configuration ā options.provider forces a specific provider
|
|
157
|
+
let providerConfig = await acquireProviderConfig(null, null, options.provider || null);
|
|
158
|
+
if (!providerConfig) {
|
|
159
|
+
throw new Error('No provider configuration available');
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
console.log(chalk.white('Provider:'), chalk.cyan(providerConfig.displayName));
|
|
163
|
+
|
|
164
|
+
// Get max chats
|
|
165
|
+
const unlimited = !options.maxChats && !config.maxChats && config.neverStop;
|
|
166
|
+
const maxChats = unlimited ? Number.MAX_SAFE_INTEGER : (options.maxChats || config.maxChats || 1);
|
|
167
|
+
console.log(chalk.white(`${t('auto.direct.config.max.iterations')}`), unlimited ? chalk.cyan('ā (never stop)') : chalk.cyan(maxChats));
|
|
168
|
+
|
|
169
|
+
// Update initial status
|
|
170
|
+
await updateAutoModeStatus(repoPath, { chatCount: 0, maxChats: unlimited ? 0 : maxChats });
|
|
171
|
+
console.log();
|
|
172
|
+
console.log(chalk.gray('ā'.repeat(80)));
|
|
173
|
+
|
|
174
|
+
// Calculate initial total for consistent display throughout the session
|
|
175
|
+
const initialTodoCount = await countTodoRequirements(repoPath);
|
|
176
|
+
const initialEffectiveMax = unlimited ? initialTodoCount : Math.min(maxChats, initialTodoCount);
|
|
177
|
+
|
|
178
|
+
return {
|
|
179
|
+
repoPath,
|
|
180
|
+
config,
|
|
181
|
+
configuredStages,
|
|
182
|
+
effectiveAgent,
|
|
183
|
+
providerConfig,
|
|
184
|
+
unlimited,
|
|
185
|
+
maxChats,
|
|
186
|
+
initialTodoCount,
|
|
187
|
+
initialEffectiveMax,
|
|
188
|
+
stopMonitoring,
|
|
189
|
+
sequencer,
|
|
190
|
+
defaultManager,
|
|
191
|
+
requirementsPath
|
|
192
|
+
};
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* Process incomplete specs loop - iterates through all enabled incomplete specs
|
|
197
|
+
*
|
|
198
|
+
* @param {Object} state - Current state object
|
|
199
|
+
* @returns {Promise<Object>} Result with completedCount and failedCount
|
|
200
|
+
*/
|
|
201
|
+
async function processSpecsLoop(state) {
|
|
202
|
+
let completedCount = 0;
|
|
203
|
+
let failedCount = 0;
|
|
204
|
+
|
|
205
|
+
const incompleteSpecs = await loadEnabledIncompleteSpecs(state.repoPath);
|
|
206
|
+
if (incompleteSpecs.length === 0) {
|
|
207
|
+
return { completedCount, failedCount, specsProcessed: false };
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
console.log(chalk.bold.cyan(`\nš Processing ${incompleteSpecs.length} incomplete spec(s) before requirements...\n`));
|
|
211
|
+
|
|
212
|
+
for (const spec of incompleteSpecs) {
|
|
213
|
+
// Initialize IDE attempts tracking for this spec
|
|
214
|
+
spec.totalIdeAttempts = 0;
|
|
215
|
+
|
|
216
|
+
const { done: doneStart, total: totalStart } = countSpecCheckboxes(spec.path);
|
|
217
|
+
console.log(chalk.bold.magenta(`\n${'ā'.repeat(80)}`));
|
|
218
|
+
console.log(chalk.bold.magenta(` š SPEC: ${spec.directory} (${spec.title || spec.directory})`));
|
|
219
|
+
if (totalStart > 0) {
|
|
220
|
+
const pctStart = Math.round((doneStart / totalStart) * 100);
|
|
221
|
+
console.log(chalk.bold.magenta(` Progress: ${doneStart}/${totalStart} tasks (${pctStart}%) complete`));
|
|
222
|
+
} else {
|
|
223
|
+
console.log(chalk.bold.magenta(' No tasks.md yet ā will plan and implement'));
|
|
224
|
+
}
|
|
225
|
+
console.log(chalk.bold.magenta(`${'ā'.repeat(80)}\n`));
|
|
226
|
+
|
|
227
|
+
let specProviderAttempts = 0;
|
|
228
|
+
const MAX_SPEC_TASK_ATTEMPTS = 3;
|
|
229
|
+
let lastSpecTaskText = null;
|
|
230
|
+
let sameTaskAttempts = 0;
|
|
231
|
+
|
|
232
|
+
// If spec has no tasks.md yet, add a special planning task
|
|
233
|
+
if (!spec.hasTasks) {
|
|
234
|
+
const planResult = await handleSpecPlanning(spec, state.providerConfig, state.repoPath);
|
|
235
|
+
if (planResult.success) {
|
|
236
|
+
completedCount++;
|
|
237
|
+
spec.hasTasks = fs.existsSync(path.join(spec.path, 'tasks.md'));
|
|
238
|
+
} else {
|
|
239
|
+
failedCount++;
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Verify tasks.md has checkbox-format tasks
|
|
245
|
+
const { done: doneCheck, total: totalCheck } = countSpecCheckboxes(spec.path);
|
|
246
|
+
if (totalCheck === 0 && spec.hasTasks) {
|
|
247
|
+
const regenResult = await handleTasksRegeneration(spec, state.providerConfig);
|
|
248
|
+
if (!regenResult.success) {
|
|
249
|
+
failedCount++;
|
|
250
|
+
continue;
|
|
251
|
+
}
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Loop until spec is done or stalled
|
|
255
|
+
while (true) {
|
|
256
|
+
const task = getNextSpecTask(spec.path);
|
|
257
|
+
if (!task) {
|
|
258
|
+
const { done: doneFinal, total: totalFinal } = countSpecCheckboxes(spec.path);
|
|
259
|
+
console.log(chalk.bold.green(`\nā
Spec "${spec.directory}" complete! (${doneFinal}/${totalFinal} tasks)\n`));
|
|
260
|
+
break;
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
// Detect same task repeated
|
|
264
|
+
if (task.text === lastSpecTaskText) {
|
|
265
|
+
sameTaskAttempts++;
|
|
266
|
+
if (sameTaskAttempts >= MAX_SPEC_TASK_ATTEMPTS) {
|
|
267
|
+
console.log(chalk.red(`\nā Task "${task.text}" not completing after ${MAX_SPEC_TASK_ATTEMPTS} attempts ā skipping spec\n`));
|
|
268
|
+
break;
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
sameTaskAttempts = 0;
|
|
272
|
+
lastSpecTaskText = task.text;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
const { done: doneCurrent, total: totalCurrent } = countSpecCheckboxes(spec.path);
|
|
276
|
+
const pctCurrent = totalCurrent > 0 ? Math.round((doneCurrent / totalCurrent) * 100) : 0;
|
|
277
|
+
|
|
278
|
+
console.log(chalk.cyan(`\nš Task ${doneCurrent + 1}/${totalCurrent || '?'}: ${task.text}`));
|
|
279
|
+
console.log(chalk.gray(` Spec progress: ${doneCurrent}/${totalCurrent} (${pctCurrent}%)\n`));
|
|
280
|
+
|
|
281
|
+
// Route spec tasks differently depending on provider type
|
|
282
|
+
let result;
|
|
283
|
+
if (state.providerConfig.type === 'ide') {
|
|
284
|
+
result = await runSpecIdeIteration(spec, task.text, task.line, state.providerConfig);
|
|
285
|
+
} else {
|
|
286
|
+
const specTaskText = [
|
|
287
|
+
task.text,
|
|
288
|
+
`[Spec: ${spec.directory} ā task ${doneCurrent + 1}/${totalCurrent || '?'}]`,
|
|
289
|
+
`[After implementing, mark the task done in ${spec.path}/tasks.md:`,
|
|
290
|
+
` change: ${task.line}`,
|
|
291
|
+
` to: - [x] ${task.text}]`
|
|
292
|
+
].join('\n');
|
|
293
|
+
const specRequirement = { text: specTaskText, package: null, disabled: false };
|
|
294
|
+
result = await runIteration(specRequirement, state.providerConfig, state.repoPath);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
if (result.success) {
|
|
298
|
+
specProviderAttempts = 0;
|
|
299
|
+
spec.totalIdeAttempts = 0;
|
|
300
|
+
completedCount++;
|
|
301
|
+
const { done, total } = countSpecCheckboxes(spec.path);
|
|
302
|
+
const pct = total > 0 ? Math.round((done / total) * 100) : 0;
|
|
303
|
+
console.log(chalk.bold.green(`š Spec progress: ${done}/${total} tasks (${pct}%) complete`));
|
|
304
|
+
} else {
|
|
305
|
+
const isRateLimitError = isRateLimitMessage(result.error);
|
|
306
|
+
const isMaxAttemptsExceeded = result.error === 'max_ide_attempts_exceeded';
|
|
307
|
+
const isNoProgress = result.error === 'no_progress';
|
|
308
|
+
|
|
309
|
+
let errorType = 'Error';
|
|
310
|
+
if (isRateLimitError) errorType = 'Rate limit';
|
|
311
|
+
else if (isMaxAttemptsExceeded) errorType = 'Max IDE attempts exceeded';
|
|
312
|
+
else if (isNoProgress) errorType = 'No progress';
|
|
313
|
+
|
|
314
|
+
if (result.totalAttempts) {
|
|
315
|
+
spec.totalIdeAttempts = result.totalAttempts;
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
specProviderAttempts++;
|
|
319
|
+
failedCount++;
|
|
320
|
+
|
|
321
|
+
if (isMaxAttemptsExceeded) {
|
|
322
|
+
console.log(chalk.red(`\nā ${errorType} ā auto mode stopped\n`));
|
|
323
|
+
return { completedCount, failedCount, specsProcessed: true, shouldExit: true };
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
if (specProviderAttempts > MAX_SPEC_TASK_ATTEMPTS) {
|
|
327
|
+
console.log(chalk.red(`\nā Max provider attempts reached ā moving to next spec\n`));
|
|
328
|
+
break;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (isNoProgress) {
|
|
332
|
+
console.log(chalk.yellow(`ā ļø ${errorType} on ${state.providerConfig.displayName}, switching IDE...`));
|
|
333
|
+
} else {
|
|
334
|
+
console.log(chalk.yellow(`ā ļø ${errorType} on spec task, switching provider...`));
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
const newProviderConfig = await acquireProviderConfig(state.providerConfig.provider, state.providerConfig.model);
|
|
338
|
+
if (newProviderConfig) {
|
|
339
|
+
state.providerConfig = newProviderConfig;
|
|
340
|
+
console.log(chalk.green(`ā Switched to: ${state.providerConfig.displayName}\n`));
|
|
341
|
+
} else {
|
|
342
|
+
console.log(chalk.red(`ā No alternative providers available\n`));
|
|
343
|
+
break;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
console.log(chalk.bold.cyan('\nš All specs processed. Continuing to requirements...\n'));
|
|
350
|
+
console.log(chalk.gray('ā'.repeat(80)));
|
|
351
|
+
|
|
352
|
+
return { completedCount, failedCount, specsProcessed: true };
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
/**
|
|
356
|
+
* Process requirements loop - iterates through regular requirements
|
|
357
|
+
*
|
|
358
|
+
* @param {Object} state - Current state object
|
|
359
|
+
* @param {number} completedCount - Number of completed items (from specs phase)
|
|
360
|
+
* @param {number} failedCount - Number of failed items (from specs phase)
|
|
361
|
+
* @returns {Promise<Object>} Result with updated counts
|
|
362
|
+
*/
|
|
363
|
+
async function processRequirementsLoop(state, completedCount, failedCount) {
|
|
364
|
+
let providerAttempts = 0;
|
|
365
|
+
let lastRequirementText = null;
|
|
366
|
+
const MAX_PROVIDER_ATTEMPTS = 3;
|
|
367
|
+
|
|
368
|
+
for (let i = 0; i < state.maxChats; i++) {
|
|
369
|
+
const requirement = await getCurrentRequirement(state.repoPath);
|
|
370
|
+
if (!requirement) {
|
|
371
|
+
// No regular requirements - check for default requirement
|
|
372
|
+
const shouldProcessDefault = await state.sequencer.shouldProcessDefault(state.requirementsPath);
|
|
373
|
+
|
|
374
|
+
if (shouldProcessDefault) {
|
|
375
|
+
console.log(chalk.bold.cyan('\nā Default Requirement Mode'));
|
|
376
|
+
console.log(chalk.gray('All regular requirements completed, processing default requirement...\n'));
|
|
377
|
+
await processDefaultRequirement(state.sequencer, state.defaultManager, state.providerConfig, state.repoPath);
|
|
378
|
+
} else {
|
|
379
|
+
if (completedCount > 0 || failedCount > 0) {
|
|
380
|
+
console.log(chalk.bold.yellow('\nš All requirements completed!'));
|
|
381
|
+
} else {
|
|
382
|
+
console.log(chalk.bold.yellow('\nš No requirements to process.'));
|
|
383
|
+
}
|
|
384
|
+
console.log(chalk.gray(`${t('auto.direct.no.more.todo.items')}\n`));
|
|
385
|
+
}
|
|
386
|
+
break;
|
|
387
|
+
}
|
|
388
|
+
|
|
389
|
+
// Check if this is a new requirement or retry
|
|
390
|
+
if (requirement.text !== lastRequirementText) {
|
|
391
|
+
providerAttempts = 0;
|
|
392
|
+
lastRequirementText = requirement.text;
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
providerAttempts++;
|
|
396
|
+
|
|
397
|
+
// Check if maximum attempts exceeded
|
|
398
|
+
if (providerAttempts > MAX_PROVIDER_ATTEMPTS) {
|
|
399
|
+
console.log(chalk.red(`\nā Maximum provider attempts (${MAX_PROVIDER_ATTEMPTS}) reached for this requirement`));
|
|
400
|
+
console.log(chalk.yellow(' All available providers have failed or are rate limited'));
|
|
401
|
+
console.log(chalk.gray(' Skipping this requirement and moving to next...\n'));
|
|
402
|
+
|
|
403
|
+
failedCount++;
|
|
404
|
+
providerAttempts = 0;
|
|
405
|
+
lastRequirementText = null;
|
|
406
|
+
continue;
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
// Calculate current requirement number
|
|
410
|
+
const currentReqNumber = completedCount + failedCount + 1;
|
|
411
|
+
|
|
412
|
+
console.log(chalk.bold.magenta(`\n${'ā'.repeat(80)}`));
|
|
413
|
+
console.log(chalk.bold.magenta(` ${t('auto.direct.requirement.header', { current: currentReqNumber, total: state.initialEffectiveMax })}`));
|
|
414
|
+
console.log(chalk.bold.magenta(`${'ā'.repeat(80)}\n`));
|
|
415
|
+
|
|
416
|
+
await updateAutoModeStatus(state.repoPath, { chatCount: currentReqNumber });
|
|
417
|
+
|
|
418
|
+
// Run iteration with full workflow
|
|
419
|
+
const result = await runIteration(requirement, state.providerConfig, state.repoPath);
|
|
420
|
+
|
|
421
|
+
if (result.success) {
|
|
422
|
+
completedCount++;
|
|
423
|
+
providerAttempts = 0;
|
|
424
|
+
lastRequirementText = null;
|
|
425
|
+
console.log(chalk.bold.green(`ā
Requirement ${currentReqNumber}/${state.initialEffectiveMax} COMPLETE`));
|
|
426
|
+
console.log(chalk.gray('Moving to next requirement...\n'));
|
|
427
|
+
|
|
428
|
+
// Check if restart CLI is enabled
|
|
429
|
+
if (state.config.restartCLI && i < state.maxChats - 1) {
|
|
430
|
+
await handleCliRestart(state.maxChats, i);
|
|
431
|
+
} else if (i < state.maxChats - 1) {
|
|
432
|
+
await new Promise(resolve => setTimeout(resolve, 2000));
|
|
433
|
+
}
|
|
434
|
+
} else {
|
|
435
|
+
const isRateLimitError = isRateLimitMessage(result.error);
|
|
436
|
+
const errorType = isRateLimitError ? 'Rate limit' : 'Error';
|
|
437
|
+
const failedProvider = state.providerConfig.displayName;
|
|
438
|
+
|
|
439
|
+
console.log(chalk.yellow(`ā ļø ${errorType} detected, switching to next provider in your list...\n`));
|
|
440
|
+
|
|
441
|
+
const newProviderConfig = await acquireProviderConfig(state.providerConfig.provider, state.providerConfig.model);
|
|
442
|
+
if (newProviderConfig) {
|
|
443
|
+
state.providerConfig = newProviderConfig;
|
|
444
|
+
console.log(chalk.yellow(`ā ļø ${failedProvider} hit ${errorType.toLowerCase()}`));
|
|
445
|
+
console.log(chalk.green(`ā Switched to: ${state.providerConfig.displayName}\n`));
|
|
446
|
+
i--;
|
|
447
|
+
continue;
|
|
448
|
+
} else {
|
|
449
|
+
console.log(chalk.red('ā No alternative providers available\n'));
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
failedCount++;
|
|
453
|
+
console.log(chalk.bold.red(`ā Requirement ${currentReqNumber}/${state.initialEffectiveMax} FAILED`));
|
|
454
|
+
console.log(chalk.red(`Error: ${result.error}\n`));
|
|
455
|
+
console.log(chalk.yellow('Continuing to next requirement...\n'));
|
|
456
|
+
}
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
return { completedCount, failedCount };
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
/**
|
|
463
|
+
* Handle CLI restart for long-running sessions
|
|
464
|
+
*/
|
|
465
|
+
async function handleCliRestart(maxChats, currentIteration) {
|
|
466
|
+
const { stopAutoMode } = require('../../utils/auto-mode');
|
|
467
|
+
console.log(chalk.cyan('š Restarting CLI to pick up latest changes...\n'));
|
|
468
|
+
|
|
469
|
+
const remainingIterations = maxChats - (currentIteration + 1);
|
|
470
|
+
const cliScriptPath = path.join(__dirname, '../../../bin/vibecodingmachine.js');
|
|
471
|
+
const args = ['auto:direct', '--max-chats', remainingIterations.toString()];
|
|
472
|
+
|
|
473
|
+
const child = spawn(process.execPath, [cliScriptPath, ...args], {
|
|
474
|
+
stdio: 'inherit',
|
|
475
|
+
cwd: process.cwd(),
|
|
476
|
+
env: process.env
|
|
477
|
+
});
|
|
478
|
+
|
|
479
|
+
child.on('error', (err) => {
|
|
480
|
+
console.error(chalk.red(t('auto.direct.config.restart.error')), err.message);
|
|
481
|
+
});
|
|
482
|
+
|
|
483
|
+
child.unref();
|
|
484
|
+
await new Promise(resolve => setTimeout(resolve, 300));
|
|
485
|
+
await stopAutoMode('restarting');
|
|
486
|
+
process.exit(0);
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
module.exports = {
|
|
490
|
+
initializeAutoMode,
|
|
491
|
+
processSpecsLoop,
|
|
492
|
+
processRequirementsLoop
|
|
493
|
+
};
|