vibecodingmachine-cli 2026.3.14-1537 → 2026.6.17-1835
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,485 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Iteration Runner - Main Iteration Workflow
|
|
3
|
+
*
|
|
4
|
+
* Extracted from iteration-handlers.js for constitutional compliance (<555 lines per file)
|
|
5
|
+
* Contains the main runIteration function that orchestrates the PREPARE, ACT, CLEAN UP, VERIFY, DONE phases
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
const chalk = require('chalk');
|
|
9
|
+
const fs = require('fs-extra');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const vibecodingmachineCore = require('vibecodingmachine-core');
|
|
12
|
+
const { DirectLLMManager, t } = vibecodingmachineCore;
|
|
13
|
+
|
|
14
|
+
// Import modular functions
|
|
15
|
+
const { getLogTimestamp } = require('./utils');
|
|
16
|
+
const { moveRequirementToVerify } = require('./requirement-manager');
|
|
17
|
+
const { parseSearchReplaceBlocks, applyFileChange } = require('./code-processor');
|
|
18
|
+
const { findRelevantFiles, readFileSnippets } = require('./file-scanner');
|
|
19
|
+
const { printStatusCard } = require('./status-display');
|
|
20
|
+
|
|
21
|
+
// Import runIdeFallbackIteration from iteration-handlers (to avoid circular dependency)
|
|
22
|
+
let runIdeFallbackIteration = null;
|
|
23
|
+
|
|
24
|
+
// Shared variables set by parent module
|
|
25
|
+
let sharedProviderManager = null;
|
|
26
|
+
let sharedHealthTracker = null;
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Initialize module with shared instances and function references
|
|
30
|
+
*/
|
|
31
|
+
function initialize(deps) {
|
|
32
|
+
sharedProviderManager = deps.providerManager;
|
|
33
|
+
sharedHealthTracker = deps.healthTracker;
|
|
34
|
+
runIdeFallbackIteration = deps.runIdeFallbackIteration;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Run one iteration of autonomous mode with full workflow
|
|
39
|
+
* @param {Object} requirement - Requirement object
|
|
40
|
+
* @param {Object} providerConfig - Provider configuration
|
|
41
|
+
* @param {string} repoPath - Repository path
|
|
42
|
+
* @returns {Promise<{success: boolean, changes?: Array, error?: string}>}
|
|
43
|
+
*/
|
|
44
|
+
async function runIteration(requirement, providerConfig, repoPath) {
|
|
45
|
+
const startTime = Date.now();
|
|
46
|
+
const providerManager = sharedProviderManager; // Use shared instance to persist rate limit state
|
|
47
|
+
const llm = new DirectLLMManager(sharedProviderManager); // Pass shared instance
|
|
48
|
+
|
|
49
|
+
if (providerConfig.type === 'ide') {
|
|
50
|
+
return runIdeFallbackIteration(requirement, providerConfig, repoPath, providerManager, llm, startTime);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
54
|
+
// PREPARE PHASE - SEARCH AND READ ACTUAL FILES
|
|
55
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
56
|
+
printStatusCard(requirement.text, 'PREPARE', 'active');
|
|
57
|
+
|
|
58
|
+
console.log(chalk.bold.white('=� REQUIREMENT:'));
|
|
59
|
+
console.log(chalk.cyan(` ${requirement.text}\n`));
|
|
60
|
+
console.log(chalk.gray(t('auto.direct.summary.provider')), chalk.white(providerConfig.displayName));
|
|
61
|
+
console.log(chalk.gray(t('auto.repository')), chalk.white(repoPath));
|
|
62
|
+
console.log();
|
|
63
|
+
|
|
64
|
+
console.log(chalk.cyan(`= ${t('auto.direct.files.searching')}...\n`));
|
|
65
|
+
const relevantFiles = await findRelevantFiles(requirement.text, repoPath);
|
|
66
|
+
|
|
67
|
+
if (relevantFiles.length > 0) {
|
|
68
|
+
console.log(chalk.white(`${t('auto.direct.files.found', { count: relevantFiles.length })}:`));
|
|
69
|
+
relevantFiles.forEach((file, i) => {
|
|
70
|
+
console.log(chalk.gray(` ${i + 1}. ${file}`));
|
|
71
|
+
});
|
|
72
|
+
console.log();
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
console.log(chalk.cyan('=� Reading file context...\n'));
|
|
76
|
+
const fileSnippets = await readFileSnippets(relevantFiles, repoPath, requirement.text);
|
|
77
|
+
|
|
78
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
79
|
+
|
|
80
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
81
|
+
// ACT PHASE - GET STRUCTURED CHANGES FROM LLM
|
|
82
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
83
|
+
printStatusCard(requirement.text, 'ACT', 'active');
|
|
84
|
+
|
|
85
|
+
console.log(chalk.cyan(` ${getLogTimestamp()} - > Asking LLM for implementation...\n`));
|
|
86
|
+
console.log(chalk.gray(' '.repeat(80)));
|
|
87
|
+
console.log(chalk.yellow('=� LLM Response (streaming):'));
|
|
88
|
+
console.log(chalk.gray(' '.repeat(80)));
|
|
89
|
+
|
|
90
|
+
// Build context with actual file snippets (use relative paths)
|
|
91
|
+
let contextSection = '';
|
|
92
|
+
if (fileSnippets.length > 0) {
|
|
93
|
+
contextSection = '\n\nCURRENT CODE CONTEXT:\n';
|
|
94
|
+
fileSnippets.forEach(({ file, snippet, startLine }) => {
|
|
95
|
+
// Convert to relative path if absolute
|
|
96
|
+
let displayPath = file;
|
|
97
|
+
if (path.isAbsolute(file)) {
|
|
98
|
+
displayPath = path.relative(repoPath, file);
|
|
99
|
+
}
|
|
100
|
+
contextSection += `\n--- ${displayPath} (around line ${startLine}) ---\n${snippet}\n`;
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
// Check if requirement involves removing menu items or UI elements
|
|
105
|
+
const isRemovalRequirement = /remove|delete|eliminate/i.test(requirement.text) &&
|
|
106
|
+
(/menu|item|option|setting|button|ui|element/i.test(requirement.text));
|
|
107
|
+
|
|
108
|
+
let removalInstructions = '';
|
|
109
|
+
if (isRemovalRequirement) {
|
|
110
|
+
removalInstructions = `
|
|
111
|
+
|
|
112
|
+
� CRITICAL: THIS IS A REMOVAL REQUIREMENT �
|
|
113
|
+
|
|
114
|
+
When removing menu items, UI elements, or settings, you MUST:
|
|
115
|
+
|
|
116
|
+
1. **FIND ALL OCCURRENCES**: Search the CURRENT CODE CONTEXT for:
|
|
117
|
+
- The exact text/identifier mentioned in the requirement
|
|
118
|
+
- Variations (e.g., "Restart CLI", "restart CLI", "restartCLI", "setting:restart-cli")
|
|
119
|
+
- Both display code (where it's shown) AND handler code (where it's processed)
|
|
120
|
+
|
|
121
|
+
2. **REMOVE ALL CODE, NOT JUST TOGGLE**:
|
|
122
|
+
- DELETE the code that displays/creates the menu item (e.g., items.push() calls)
|
|
123
|
+
- DELETE the handler code that processes the action (e.g., case 'setting:restart-cli': blocks)
|
|
124
|
+
- DELETE any configuration/state code related to the item (e.g., const restartCLI = ...)
|
|
125
|
+
- DELETE any variable declarations or references to the item
|
|
126
|
+
|
|
127
|
+
3. **MULTIPLE FILES MAY BE AFFECTED**:
|
|
128
|
+
- If you find references in multiple files, you MUST provide multiple FILE/SEARCH/REPLACE blocks
|
|
129
|
+
- Each file needs its own FILE/SEARCH/REPLACE block
|
|
130
|
+
- Remove ALL occurrences across ALL files shown in the context
|
|
131
|
+
|
|
132
|
+
4. **VERIFICATION**:
|
|
133
|
+
- After removal, the code should compile/run without errors
|
|
134
|
+
- The removed item should not appear anywhere in the codebase
|
|
135
|
+
- All related handlers and configuration should be removed
|
|
136
|
+
|
|
137
|
+
EXAMPLE for removing "Restart CLI after each completed requirement":
|
|
138
|
+
- Remove: items.push({ type: 'setting', name: \`...Restart CLI...\`, value: 'setting:restart-cli' })
|
|
139
|
+
- Remove: case 'setting:restart-cli': { ... } handler block
|
|
140
|
+
- Remove: const restartCLI = ... variable declaration
|
|
141
|
+
- Remove: Any other references to restartCLI or 'setting:restart-cli'
|
|
142
|
+
|
|
143
|
+
`;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
const prompt = `You are implementing a code change. Your task is to provide a SEARCH/REPLACE block that will modify the code.
|
|
147
|
+
|
|
148
|
+
REQUIREMENT TO IMPLEMENT:
|
|
149
|
+
${requirement.text}
|
|
150
|
+
${removalInstructions}
|
|
151
|
+
${contextSection}
|
|
152
|
+
|
|
153
|
+
YOUR TASK:
|
|
154
|
+
1. Read the CURRENT CODE CONTEXT carefully
|
|
155
|
+
2. Find the EXACT location where changes are needed
|
|
156
|
+
3. COPY AT LEAST 10 LINES EXACTLY as they appear (including indentation, spacing, comments)
|
|
157
|
+
4. Show what the code should look like after your changes
|
|
158
|
+
${isRemovalRequirement ? '5. **REMOVE ALL CODE** related to the item - do NOT comment it out, DELETE it completely' : ''}
|
|
159
|
+
|
|
160
|
+
OUTPUT FORMAT:
|
|
161
|
+
|
|
162
|
+
For modifying existing files:
|
|
163
|
+
FILE: <exact path from the "---" line - must be relative to repo root>
|
|
164
|
+
SEARCH: \`\`\`javascript
|
|
165
|
+
<COPY 10+ lines EXACTLY - preserve indentation, spacing, comments>
|
|
166
|
+
\`\`\`
|
|
167
|
+
REPLACE: \`\`\`javascript
|
|
168
|
+
<SAME lines but with necessary modifications>
|
|
169
|
+
\`\`\`
|
|
170
|
+
|
|
171
|
+
For creating new files:
|
|
172
|
+
CREATE: <relative path to new file>
|
|
173
|
+
CONTENT: \`\`\`javascript
|
|
174
|
+
<full content of new file>
|
|
175
|
+
\`\`\`
|
|
176
|
+
|
|
177
|
+
CRITICAL RULES - READ CAREFULLY:
|
|
178
|
+
1. If the file does NOT exist, use CREATE: format to create it
|
|
179
|
+
2. If the file DOES exist and you need to modify it, use FILE:/SEARCH:/REPLACE: format
|
|
180
|
+
3. For FILE: blocks, SEARCH block must be COPIED CHARACTER-BY-CHARACTER from CURRENT CODE CONTEXT above
|
|
181
|
+
4. Use the EXACT code as it appears NOW - do NOT use old/outdated code from memory
|
|
182
|
+
5. Include ALL property values EXACTLY as shown (e.g., if context shows 'type: "info"', use 'type: "info"', NOT 'type: "setting"')
|
|
183
|
+
6. Include indentation EXACTLY as shown (count the spaces!)
|
|
184
|
+
7. For modifications, include AT LEAST 20-30 LINES of context:
|
|
185
|
+
- Start 10-15 lines BEFORE the code you need to change
|
|
186
|
+
- End 10-15 lines AFTER the code you need to change
|
|
187
|
+
- MORE context is BETTER than less - include extra lines if unsure
|
|
188
|
+
8. Do NOT paraphrase or rewrite - COPY EXACTLY from CURRENT CODE CONTEXT
|
|
189
|
+
9. FILE path must match exactly what's after "---" in CURRENT CODE CONTEXT (DO NOT include the "---" itself)
|
|
190
|
+
10. All paths must be RELATIVE to repo root (e.g., "specs/005-beta-pricing/tasks.md" NOT "/Users/.../tasks.md")
|
|
191
|
+
11. Output ONLY the FILE/SEARCH/REPLACE or CREATE/CONTENT blocks
|
|
192
|
+
12. NO explanations, NO markdown outside the blocks, NO additional text
|
|
193
|
+
13. If you cannot find the exact code to modify, output: ERROR: CANNOT LOCATE CODE IN CONTEXT
|
|
194
|
+
14. IMPORTANT: Include ALL intermediate code between the before/after context - do NOT skip lines
|
|
195
|
+
15. DOUBLE-CHECK: Compare your SEARCH block line-by-line with CURRENT CODE CONTEXT to ensure they match
|
|
196
|
+
|
|
197
|
+
EXAMPLE (notice EXACT copying of indentation and spacing):
|
|
198
|
+
|
|
199
|
+
FILE: packages/cli/src/utils/interactive.js
|
|
200
|
+
SEARCH: \`\`\`javascript
|
|
201
|
+
// Add warning if no TODO requirements
|
|
202
|
+
if (counts.todoCount === 0) {
|
|
203
|
+
requirementsText += \` \${chalk.red('� No requirements to work on')}\`;
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
requirementsText += \`\${chalk.yellow('0 TODO')}, \${chalk.cyan('0 TO VERIFY')}, \${chalk.green('0 VERIFIED')} \${chalk.red('� No requirements')}\`;
|
|
207
|
+
}
|
|
208
|
+
\`\`\`
|
|
209
|
+
REPLACE: \`\`\`javascript
|
|
210
|
+
// Add warning if no TODO requirements
|
|
211
|
+
if (counts.todoCount === 0) {
|
|
212
|
+
requirementsText += \` \${chalk.red('� No requirements')}\`;
|
|
213
|
+
}
|
|
214
|
+
} else {
|
|
215
|
+
requirementsText += \`\${chalk.yellow('0 TODO')}, \${chalk.cyan('0 TO VERIFY')}, \${chalk.green('0 VERIFIED')} \${chalk.red('� No requirements')}\`;
|
|
216
|
+
}
|
|
217
|
+
\`\`\`
|
|
218
|
+
|
|
219
|
+
CREATE EXAMPLE (for new files):
|
|
220
|
+
|
|
221
|
+
CREATE: packages/web/src/utils/paypal-config.js
|
|
222
|
+
CONTENT: \`\`\`javascript
|
|
223
|
+
/**
|
|
224
|
+
* PayPal Configuration Utility
|
|
225
|
+
*/
|
|
226
|
+
|
|
227
|
+
export const getPayPalClientId = () => {
|
|
228
|
+
return import.meta.env.VITE_PAYPAL_CLIENT_ID;
|
|
229
|
+
};
|
|
230
|
+
|
|
231
|
+
export const getPayPalEnvironment = () => {
|
|
232
|
+
return import.meta.env.VITE_PAYPAL_ENVIRONMENT || 'sandbox';
|
|
233
|
+
};
|
|
234
|
+
\`\`\`
|
|
235
|
+
|
|
236
|
+
Now implement the requirement. Remember: For modifications, COPY THE SEARCH BLOCK EXACTLY! For new files, use CREATE: format.`;
|
|
237
|
+
|
|
238
|
+
let fullResponse = '';
|
|
239
|
+
let chunkCount = 0;
|
|
240
|
+
let totalChars = 0;
|
|
241
|
+
|
|
242
|
+
// Show spinner while waiting for first chunk
|
|
243
|
+
const spinnerFrames = ['⠋', '⠙', '⠹', '⠸', '⠼', '⠴', '⠦', '⠧', '⠇', '⠏'];
|
|
244
|
+
let spinnerIndex = 0;
|
|
245
|
+
let spinnerInterval = null;
|
|
246
|
+
let receivedFirstChunk = false;
|
|
247
|
+
|
|
248
|
+
const startSpinner = () => {
|
|
249
|
+
process.stdout.write(chalk.cyan('� Waiting for response'));
|
|
250
|
+
spinnerInterval = setInterval(() => {
|
|
251
|
+
process.stdout.write(`\r${chalk.cyan('� Waiting for response')} ${chalk.yellow(spinnerFrames[spinnerIndex])}`);
|
|
252
|
+
spinnerIndex = (spinnerIndex + 1) % spinnerFrames.length;
|
|
253
|
+
}, 100);
|
|
254
|
+
};
|
|
255
|
+
|
|
256
|
+
const stopSpinner = () => {
|
|
257
|
+
if (spinnerInterval) {
|
|
258
|
+
clearInterval(spinnerInterval);
|
|
259
|
+
spinnerInterval = null;
|
|
260
|
+
process.stdout.write('\r\x1b[K'); // Clear the line
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
|
|
264
|
+
startSpinner();
|
|
265
|
+
|
|
266
|
+
const result = await llm.call(providerConfig, prompt, {
|
|
267
|
+
temperature: 0.1,
|
|
268
|
+
maxTokens: 4096,
|
|
269
|
+
onChunk: (chunk) => {
|
|
270
|
+
chunkCount++;
|
|
271
|
+
totalChars += chunk.length;
|
|
272
|
+
// Show first chunk arrival to confirm streaming started
|
|
273
|
+
if (chunkCount === 1) {
|
|
274
|
+
stopSpinner();
|
|
275
|
+
receivedFirstChunk = true;
|
|
276
|
+
process.stdout.write(chalk.green(' Streaming started...\n'));
|
|
277
|
+
}
|
|
278
|
+
// Use white text for better visibility instead of gray
|
|
279
|
+
process.stdout.write(chalk.white(chunk));
|
|
280
|
+
fullResponse += chunk;
|
|
281
|
+
},
|
|
282
|
+
onComplete: () => {
|
|
283
|
+
stopSpinner();
|
|
284
|
+
if (chunkCount > 0) {
|
|
285
|
+
console.log(chalk.green(`\n Received ${totalChars} characters in ${chunkCount} chunks`));
|
|
286
|
+
} else {
|
|
287
|
+
console.log(chalk.yellow('\n� No streaming response received (using complete response)'));
|
|
288
|
+
}
|
|
289
|
+
console.log(chalk.gray(' '.repeat(80)));
|
|
290
|
+
console.log();
|
|
291
|
+
},
|
|
292
|
+
onError: (error) => {
|
|
293
|
+
stopSpinner();
|
|
294
|
+
console.error(chalk.red(`\n Error: ${error}`));
|
|
295
|
+
}
|
|
296
|
+
});
|
|
297
|
+
|
|
298
|
+
// Ensure spinner is stopped even if callbacks didn't fire
|
|
299
|
+
stopSpinner();
|
|
300
|
+
|
|
301
|
+
if (!result.success) {
|
|
302
|
+
const combinedError = [result.error, fullResponse].filter(Boolean).join('\n').trim() || 'Unknown error';
|
|
303
|
+
console.log(chalk.red(`\n LLM call failed: ${combinedError}`));
|
|
304
|
+
// CRITICAL: Mark provider as rate-limited for ANY error so acquireProviderConfig() will skip it
|
|
305
|
+
providerManager.markRateLimited(providerConfig.provider, providerConfig.model, combinedError);
|
|
306
|
+
|
|
307
|
+
// Track health metrics for failed direct providers
|
|
308
|
+
const providerType = providerConfig.provider;
|
|
309
|
+
const duration = Date.now() - startTime;
|
|
310
|
+
try {
|
|
311
|
+
// Detect quota/rate limit errors vs other failures
|
|
312
|
+
const quotaPattern = /(quota|rate.?limit|usage.?limit|spending.?cap|allowance|exceeded|overloaded)/i;
|
|
313
|
+
const isQuotaError = quotaPattern.test(combinedError);
|
|
314
|
+
|
|
315
|
+
if (isQuotaError) {
|
|
316
|
+
await sharedHealthTracker.recordQuota(providerType, combinedError, {
|
|
317
|
+
requirementId: requirement.id || requirement.text.substring(0, 50),
|
|
318
|
+
});
|
|
319
|
+
} else {
|
|
320
|
+
await sharedHealthTracker.recordFailure(providerType, combinedError, {
|
|
321
|
+
timeoutUsed: duration,
|
|
322
|
+
requirementId: requirement.id || requirement.text.substring(0, 50),
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
} catch (healthError) {
|
|
326
|
+
// Don't fail the iteration if health tracking fails
|
|
327
|
+
console.log(chalk.gray(`� Health tracking error: ${healthError.message}`));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
return { success: false, error: combinedError };
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
334
|
+
// CLEAN UP PHASE - APPLY CHANGES TO ACTUAL FILES
|
|
335
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
336
|
+
printStatusCard(requirement.text, 'CLEAN UP', 'active');
|
|
337
|
+
|
|
338
|
+
console.log(chalk.cyan('>� Parsing and applying changes...\n'));
|
|
339
|
+
|
|
340
|
+
// Check if LLM said it cannot locate code
|
|
341
|
+
if (fullResponse.includes('ERROR: CANNOT LOCATE CODE') || fullResponse.includes('CANNOT LOCATE CODE')) {
|
|
342
|
+
console.log(chalk.red('\n LLM could not locate the code to modify'));
|
|
343
|
+
console.log(chalk.yellow('The code context provided may not contain the relevant section\n'));
|
|
344
|
+
return { success: false, error: 'LLM could not locate code in context', changes: [] };
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
const changes = parseSearchReplaceBlocks(fullResponse);
|
|
348
|
+
|
|
349
|
+
if (changes.length === 0) {
|
|
350
|
+
if (fullResponse.includes('NO CHANGES NEEDED')) {
|
|
351
|
+
console.log(chalk.yellow('� LLM determined no code changes needed\n'));
|
|
352
|
+
return { success: false, error: 'No changes needed', changes: [] };
|
|
353
|
+
} else {
|
|
354
|
+
console.log(chalk.yellow('� Could not parse any search/replace blocks from LLM response\n'));
|
|
355
|
+
console.log(chalk.gray('This might be a documentation-only requirement or LLM formatting issue\n'));
|
|
356
|
+
return { success: false, error: 'No search/replace blocks found', changes: [] };
|
|
357
|
+
}
|
|
358
|
+
} else {
|
|
359
|
+
console.log(chalk.white(`Applying ${changes.length} change(s):\n`));
|
|
360
|
+
|
|
361
|
+
let appliedCount = 0;
|
|
362
|
+
let failedCount = 0;
|
|
363
|
+
|
|
364
|
+
for (let i = 0; i < changes.length; i++) {
|
|
365
|
+
const change = changes[i];
|
|
366
|
+
console.log(chalk.cyan(` ${i + 1}. ${change.file}...`));
|
|
367
|
+
|
|
368
|
+
const applyResult = await applyFileChange(change, repoPath);
|
|
369
|
+
|
|
370
|
+
if (applyResult.success) {
|
|
371
|
+
const methodInfo = applyResult.method === 'fuzzy'
|
|
372
|
+
? ` (fuzzy match at line ${applyResult.matchedAt})`
|
|
373
|
+
: '';
|
|
374
|
+
console.log(chalk.green(` Applied successfully${methodInfo}`));
|
|
375
|
+
appliedCount++;
|
|
376
|
+
} else {
|
|
377
|
+
console.log(chalk.red(` Failed: ${applyResult.error}`));
|
|
378
|
+
failedCount++;
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
console.log();
|
|
383
|
+
console.log(chalk.white(`Applied: ${chalk.green(appliedCount)}, Failed: ${chalk.red(failedCount)}`));
|
|
384
|
+
console.log();
|
|
385
|
+
|
|
386
|
+
// CRITICAL: Fail if no changes were applied successfully
|
|
387
|
+
if (appliedCount === 0 && failedCount > 0) {
|
|
388
|
+
console.log(chalk.bold.red('\nL ITERATION FAILED\n'));
|
|
389
|
+
console.log(chalk.red('No changes were successfully applied'));
|
|
390
|
+
console.log(chalk.yellow('Common causes:'));
|
|
391
|
+
console.log(chalk.gray(' - LLM provided incorrect search text'));
|
|
392
|
+
console.log(chalk.gray(' - Code has changed since context was provided'));
|
|
393
|
+
console.log(chalk.gray(' - File path is incorrect'));
|
|
394
|
+
console.log();
|
|
395
|
+
console.log(chalk.cyan('=� Tip: Check the search block matches the actual code in the file'));
|
|
396
|
+
console.log();
|
|
397
|
+
return { success: false, error: 'No changes applied', changes: [] };
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
402
|
+
|
|
403
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
404
|
+
// VERIFY PHASE - CONFIRM CHANGES WERE APPLIED
|
|
405
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
406
|
+
printStatusCard(requirement.text, 'VERIFY', 'active');
|
|
407
|
+
|
|
408
|
+
console.log(chalk.cyan(' Verifying changes...\n'));
|
|
409
|
+
|
|
410
|
+
if (changes.length > 0) {
|
|
411
|
+
console.log(chalk.white('Modified files:'));
|
|
412
|
+
for (const change of changes) {
|
|
413
|
+
const fullPath = path.join(repoPath, change.file);
|
|
414
|
+
if (await fs.pathExists(fullPath)) {
|
|
415
|
+
const content = await fs.readFile(fullPath, 'utf8');
|
|
416
|
+
|
|
417
|
+
// Handle both create and modify types
|
|
418
|
+
let hasChange = false;
|
|
419
|
+
if (change.type === 'create') {
|
|
420
|
+
hasChange = change.content && content.includes(change.content.trim());
|
|
421
|
+
} else {
|
|
422
|
+
hasChange = change.replace && content.includes(change.replace.trim());
|
|
423
|
+
}
|
|
424
|
+
|
|
425
|
+
if (hasChange) {
|
|
426
|
+
console.log(chalk.green(` ${change.file}`));
|
|
427
|
+
} else {
|
|
428
|
+
console.log(chalk.yellow(` � ${change.file} (change may not have applied)`));
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
console.log();
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
await new Promise(resolve => setTimeout(resolve, 500));
|
|
436
|
+
|
|
437
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
438
|
+
// DONE PHASE
|
|
439
|
+
// PPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPPP
|
|
440
|
+
printStatusCard(requirement.text, 'DONE', 'active');
|
|
441
|
+
|
|
442
|
+
const elapsed = ((Date.now() - startTime) / 1000).toFixed(1);
|
|
443
|
+
|
|
444
|
+
console.log(chalk.bold.green(` ${t('auto.direct.requirement.completed')}\n`));
|
|
445
|
+
console.log(chalk.white(`${t('auto.direct.requirement.title')}`), chalk.cyan(requirement.text));
|
|
446
|
+
console.log(chalk.white(t('auto.direct.summary.files.modified')), chalk.cyan(changes.length));
|
|
447
|
+
console.log(chalk.white(t('auto.direct.summary.status')), chalk.green(t('auto.direct.summary.moving.to.verify')));
|
|
448
|
+
console.log(chalk.white(t('auto.direct.summary.time')), chalk.gray(`${elapsed}s`));
|
|
449
|
+
console.log();
|
|
450
|
+
|
|
451
|
+
// Move requirement to TO VERIFY section
|
|
452
|
+
const moved = await moveRequirementToVerify(repoPath, requirement.text);
|
|
453
|
+
if (moved) {
|
|
454
|
+
console.log(chalk.green(` ${t('auto.direct.status.verification.pending')}`));
|
|
455
|
+
} else {
|
|
456
|
+
console.log(chalk.yellow('� Could not automatically move requirement'));
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
// Record performance metric
|
|
460
|
+
const duration = Date.now() - startTime;
|
|
461
|
+
providerManager.recordPerformance(providerConfig.provider, providerConfig.model, duration);
|
|
462
|
+
|
|
463
|
+
// Track health metrics for direct providers (IDE providers tracked in runIdeFallbackIteration)
|
|
464
|
+
const providerType = providerConfig.provider;
|
|
465
|
+
try {
|
|
466
|
+
await sharedHealthTracker.recordSuccess(providerType, duration, {
|
|
467
|
+
requirementId: requirement.id || requirement.text.substring(0, 50),
|
|
468
|
+
continuationPromptsDetected: 0,
|
|
469
|
+
});
|
|
470
|
+
} catch (healthError) {
|
|
471
|
+
// Don't fail the iteration if health tracking fails
|
|
472
|
+
console.log(chalk.gray(`� Health tracking error: ${healthError.message}`));
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
console.log();
|
|
476
|
+
console.log(chalk.gray(' '.repeat(80)));
|
|
477
|
+
console.log();
|
|
478
|
+
|
|
479
|
+
return { success: true, changes };
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
module.exports = {
|
|
483
|
+
initialize,
|
|
484
|
+
runIteration
|
|
485
|
+
};
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
* Extracted from auto-direct.js to reduce file size
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
|
-
const { getAutoConfig } = require('
|
|
6
|
+
const { getAutoConfig } = require('../../utils/config');
|
|
7
7
|
const { getProviderPreferences, getProviderDefinition, saveProviderPreferences } = require('../../utils/provider-registry');
|
|
8
8
|
const ProviderManager = require('vibecodingmachine-core/src/ide-integration/provider-manager.cjs');
|
|
9
9
|
const { checkAntigravityRateLimit, handleAntigravityRateLimit } = require('../../utils/antigravity-js-handler');
|
|
@@ -13,6 +13,22 @@ const { checkClineRateLimit, handleClineRateLimit } = require('../../utils/cline
|
|
|
13
13
|
// CRITICAL: Shared ProviderManager instance to track rate limits across all function calls
|
|
14
14
|
const sharedProviderManager = new ProviderManager();
|
|
15
15
|
|
|
16
|
+
/**
|
|
17
|
+
* Normalize config.providers to a {providerName: configObj} map.
|
|
18
|
+
* Handles both array format [{provider, model, ...}] and object format {name: {...}}.
|
|
19
|
+
*/
|
|
20
|
+
function normalizeProvidersMap(rawProviders) {
|
|
21
|
+
if (!rawProviders) return {};
|
|
22
|
+
if (Array.isArray(rawProviders)) {
|
|
23
|
+
const map = {};
|
|
24
|
+
for (const entry of rawProviders) {
|
|
25
|
+
if (entry && entry.provider) map[entry.provider] = entry;
|
|
26
|
+
}
|
|
27
|
+
return map;
|
|
28
|
+
}
|
|
29
|
+
return rawProviders;
|
|
30
|
+
}
|
|
31
|
+
|
|
16
32
|
/**
|
|
17
33
|
* Get all available provider configurations
|
|
18
34
|
*/
|
|
@@ -23,8 +39,10 @@ async function getAllAvailableProviders() {
|
|
|
23
39
|
const providers = [];
|
|
24
40
|
const skipped = [];
|
|
25
41
|
|
|
42
|
+
const providersMap = normalizeProvidersMap(config.providers);
|
|
43
|
+
|
|
26
44
|
// Check each provider in config
|
|
27
|
-
for (const [providerName, providerConfig] of Object.entries(
|
|
45
|
+
for (const [providerName, providerConfig] of Object.entries(providersMap)) {
|
|
28
46
|
// Skip if provider is disabled in preferences
|
|
29
47
|
if (prefs.disabled?.includes(providerName)) {
|
|
30
48
|
skipped.push(providerName);
|
|
@@ -130,8 +148,21 @@ async function acquireProviderConfig(excludeProvider = null, excludeModel = null
|
|
|
130
148
|
// If a specific provider is forced, bypass normal selection
|
|
131
149
|
if (forcedProvider) {
|
|
132
150
|
const { providers } = await getAllAvailableProviders();
|
|
133
|
-
|
|
134
|
-
|
|
151
|
+
let provider = providers.find(p => p.name === forcedProvider);
|
|
152
|
+
|
|
153
|
+
// Fall back to registry definition for credential-free providers (e.g. claude-code CLI)
|
|
154
|
+
if (!provider) {
|
|
155
|
+
const definition = getProviderDefinition(forcedProvider);
|
|
156
|
+
if (definition && !definition.credentials?.length) {
|
|
157
|
+
provider = {
|
|
158
|
+
name: forcedProvider,
|
|
159
|
+
displayName: definition.displayName || forcedProvider,
|
|
160
|
+
config: {},
|
|
161
|
+
definition
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
135
166
|
if (!provider) {
|
|
136
167
|
throw new Error(`Forced provider "${forcedProvider}" not available`);
|
|
137
168
|
}
|
|
@@ -146,16 +177,16 @@ async function acquireProviderConfig(excludeProvider = null, excludeModel = null
|
|
|
146
177
|
}
|
|
147
178
|
|
|
148
179
|
const config = await getProviderConfig(excludeProvider);
|
|
149
|
-
|
|
180
|
+
|
|
150
181
|
// Model selection logic
|
|
151
182
|
let selectedModel = config.config.model;
|
|
152
|
-
|
|
183
|
+
|
|
153
184
|
// Exclude specific model if requested
|
|
154
185
|
if (excludeModel && selectedModel === excludeModel) {
|
|
155
186
|
// Try alternative models
|
|
156
187
|
const alternativeModels = config.definition.models || [];
|
|
157
188
|
const availableModel = alternativeModels.find(m => m !== excludeModel && m !== selectedModel);
|
|
158
|
-
|
|
189
|
+
|
|
159
190
|
if (availableModel) {
|
|
160
191
|
selectedModel = availableModel;
|
|
161
192
|
} else {
|