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.
Files changed (162) hide show
  1. package/bin/auth/auth-compliance.js +7 -7
  2. package/bin/commands/agent-commands.js +15 -15
  3. package/bin/commands/auto-commands.js +3 -3
  4. package/bin/commands/command-aliases.js +13 -4
  5. package/bin/config/cli-config.js +15 -5
  6. package/bin/update/update-checker.js +5 -5
  7. package/bin/vibecodingmachine.js +2 -2
  8. package/package.json +2 -2
  9. package/src/commands/agents/add.js +5 -5
  10. package/src/commands/agents/check.js +19 -19
  11. package/src/commands/agents/list.js +24 -24
  12. package/src/commands/agents/remove.js +4 -4
  13. package/src/commands/agents-check.js +1 -1
  14. package/src/commands/analyze-file-sizes.js +43 -43
  15. package/src/commands/auto-direct/auto-provider-manager.js +19 -19
  16. package/src/commands/auto-direct/auto-start-phases.js +493 -0
  17. package/src/commands/auto-direct/auto-status-display.js +35 -35
  18. package/src/commands/auto-direct/auto-utils.js +50 -50
  19. package/src/commands/auto-direct/cline-installer.js +56 -0
  20. package/src/commands/auto-direct/code-processor.js +27 -27
  21. package/src/commands/auto-direct/file-scanner.js +19 -19
  22. package/src/commands/auto-direct/ide-completion-waiter.js +485 -0
  23. package/src/commands/auto-direct/ide-fallback-runner.js +226 -0
  24. package/src/commands/auto-direct/ide-provider-runner.js +103 -0
  25. package/src/commands/auto-direct/iteration-handlers.js +189 -0
  26. package/src/commands/auto-direct/iteration-runner.js +485 -0
  27. package/src/commands/auto-direct/provider-config.js +38 -7
  28. package/src/commands/auto-direct/provider-manager.js +132 -6
  29. package/src/commands/auto-direct/requirement-manager.js +169 -104
  30. package/src/commands/auto-direct/requirement-mover.js +350 -0
  31. package/src/commands/auto-direct/spec-handlers.js +155 -0
  32. package/src/commands/auto-direct/spec-ide-runner.js +318 -0
  33. package/src/commands/auto-direct/spec-processing.js +203 -0
  34. package/src/commands/auto-direct/status-display.js +9 -9
  35. package/src/commands/auto-direct/utils.js +83 -1
  36. package/src/commands/auto-direct-refactored.js +1 -413
  37. package/src/commands/auto-direct.js +127 -4119
  38. package/src/commands/auto-execution.js +21 -21
  39. package/src/commands/auto-status-helpers.js +0 -2
  40. package/src/commands/auto.js +22 -22
  41. package/src/commands/check-compliance.js +65 -65
  42. package/src/commands/computers.js +39 -39
  43. package/src/commands/continuous-scan.js +19 -19
  44. package/src/commands/ide.js +4 -4
  45. package/src/commands/locale.js +7 -7
  46. package/src/commands/refactor-file.js +59 -59
  47. package/src/commands/requirements/commands.js +17 -17
  48. package/src/commands/requirements/default-handlers.js +30 -30
  49. package/src/commands/requirements/disable.js +3 -3
  50. package/src/commands/requirements/enable.js +3 -3
  51. package/src/commands/requirements/utils.js +6 -6
  52. package/src/commands/requirements-refactored.js +3 -3
  53. package/src/commands/requirements-remote.js +38 -38
  54. package/src/commands/requirements.js +3 -3
  55. package/src/commands/settings.js +111 -0
  56. package/src/commands/specs/count.js +60 -0
  57. package/src/commands/specs/disable.js +3 -3
  58. package/src/commands/specs/enable.js +3 -3
  59. package/src/commands/status.js +10 -10
  60. package/src/commands/sync.js +25 -25
  61. package/src/commands/timeout.js +35 -35
  62. package/src/trui/TruiInterface.js +2 -2
  63. package/src/trui/agents/AgentInterface.js +4 -4
  64. package/src/trui/agents/handlers/CommandHandler.js +4 -4
  65. package/src/trui/agents/handlers/ContextManager.js +1 -1
  66. package/src/trui/agents/handlers/DisplayHandler.js +11 -11
  67. package/src/trui/agents/handlers/HelpHandler.js +1 -1
  68. package/src/utils/agent-selector.js +6 -6
  69. package/src/utils/antigravity-installer.js +4 -4
  70. package/src/utils/asset-cleanup.js +1 -1
  71. package/src/utils/auth.js +9 -12
  72. package/src/utils/clarification-actions.js +4 -4
  73. package/src/utils/cline-js-handler.js +5 -5
  74. package/src/utils/compliance-check.js +6 -6
  75. package/src/utils/config.js +12 -12
  76. package/src/utils/display-formatters-complete.js +2 -2
  77. package/src/utils/display-formatters-extracted.js +2 -2
  78. package/src/utils/display-formatters.js +2 -2
  79. package/src/utils/feedback-handler.js +2 -2
  80. package/src/utils/first-run.js +7 -7
  81. package/src/utils/ide-detection.js +1 -1
  82. package/src/utils/ide-handlers.js +6 -6
  83. package/src/utils/interactive/clarification-actions.js +3 -3
  84. package/src/utils/interactive/core-ui.js +7 -7
  85. package/src/utils/interactive/file-backup.js +6 -6
  86. package/src/utils/interactive/file-import-export.js +49 -49
  87. package/src/utils/interactive/file-operations.js +3 -3
  88. package/src/utils/interactive/file-validation.js +41 -41
  89. package/src/utils/interactive/interactive-prompts.js +41 -41
  90. package/src/utils/interactive/requirement-actions.js +5 -5
  91. package/src/utils/interactive/requirement-crud.js +4 -4
  92. package/src/utils/interactive/requirements-navigation.js +10 -10
  93. package/src/utils/interactive-broken.js +6 -6
  94. package/src/utils/interactive.js +37 -37
  95. package/src/utils/keyboard-handler.js +4 -4
  96. package/src/utils/prompt-helper.js +6 -6
  97. package/src/utils/provider-checker/agent-checker.js +1 -1
  98. package/src/utils/provider-checker/agent-runner.js +203 -314
  99. package/src/utils/provider-checker/agents-file-lock.js +134 -0
  100. package/src/utils/provider-checker/agents-manager.js +224 -36
  101. package/src/utils/provider-checker/cli-installer.js +28 -28
  102. package/src/utils/provider-checker/cli-utils.js +2 -2
  103. package/src/utils/provider-checker/cursor-approval-clicker.js +108 -0
  104. package/src/utils/provider-checker/format-utils.js +4 -4
  105. package/src/utils/provider-checker/ide-installer-helper.js +96 -0
  106. package/src/utils/provider-checker/ide-manager.js +19 -8
  107. package/src/utils/provider-checker/ide-quota-checker.js +120 -0
  108. package/src/utils/provider-checker/ide-utils.js +2 -2
  109. package/src/utils/provider-checker/node-detector.js +4 -4
  110. package/src/utils/provider-checker/node-utils.js +5 -5
  111. package/src/utils/provider-checker/opencode-checker.js +107 -73
  112. package/src/utils/provider-checker/process-utils.js +1 -1
  113. package/src/utils/provider-checker/provider-validator.js +11 -11
  114. package/src/utils/provider-checker/quota-checker.js +5 -5
  115. package/src/utils/provider-checker/quota-detector.js +5 -5
  116. package/src/utils/provider-checker/requirements-manager.js +6 -6
  117. package/src/utils/provider-checker/test-requirements.js +1 -1
  118. package/src/utils/provider-checker/vscode-approval-clicker.js +328 -0
  119. package/src/utils/provider-checker-new.js +6 -6
  120. package/src/utils/provider-checker.js +6 -6
  121. package/src/utils/provider-checkers/ide-manager.js +13 -13
  122. package/src/utils/provider-checkers/node-executable-finder.js +4 -4
  123. package/src/utils/provider-checkers/provider-checker-core.js +5 -5
  124. package/src/utils/provider-checkers/provider-checker-main.js +17 -17
  125. package/src/utils/provider-registry.js +5 -6
  126. package/src/utils/provider-utils.js +12 -12
  127. package/src/utils/quota-detectors.js +32 -32
  128. package/src/utils/requirement-action-handlers.js +12 -12
  129. package/src/utils/requirement-actions/requirement-operations.js +3 -3
  130. package/src/utils/requirement-actions.js +1 -1
  131. package/src/utils/requirement-file-operations.js +5 -5
  132. package/src/utils/requirement-helpers.js +1 -1
  133. package/src/utils/requirement-management.js +5 -5
  134. package/src/utils/requirement-navigation.js +2 -2
  135. package/src/utils/requirement-organization.js +3 -3
  136. package/src/utils/rui-trui-adapter.js +14 -14
  137. package/src/utils/simple-trui.js +3 -3
  138. package/src/utils/status-helpers-extracted.js +3 -3
  139. package/src/utils/trui-clarifications.js +11 -11
  140. package/src/utils/trui-debug.js +3 -2
  141. package/src/utils/trui-devin.js +217 -0
  142. package/src/utils/trui-feedback.js +7 -7
  143. package/src/utils/trui-kiro-integration.js +34 -34
  144. package/src/utils/trui-main-handlers.js +20 -21
  145. package/src/utils/trui-main-menu.js +19 -19
  146. package/src/utils/trui-nav-agents.js +59 -8
  147. package/src/utils/trui-nav-requirements.js +3 -3
  148. package/src/utils/trui-nav-settings.js +10 -10
  149. package/src/utils/trui-nav-specifications.js +1 -1
  150. package/src/utils/trui-navigation-backup.js +11 -11
  151. package/src/utils/trui-navigation.js +9 -9
  152. package/src/utils/trui-provider-health.js +25 -25
  153. package/src/utils/trui-provider-manager.js +28 -28
  154. package/src/utils/trui-quick-menu.js +2 -2
  155. package/src/utils/trui-req-actions-backup.js +21 -21
  156. package/src/utils/trui-req-actions.js +20 -20
  157. package/src/utils/trui-req-editor.js +10 -10
  158. package/src/utils/trui-req-file-ops.js +3 -3
  159. package/src/utils/trui-req-tree.js +7 -7
  160. package/src/utils/trui-windsurf.js +103 -103
  161. package/src/utils/user-tracking.js +15 -15
  162. package/src/utils/trui-req-tree-old.js +0 -719
@@ -6,13 +6,17 @@ const path = require('path');
6
6
  const chokidar = require('chokidar');
7
7
 
8
8
  const { NODE_EXECUTABLE } = require('./node-detector');
9
- const { IDE_INFO, isIDERunning, openIDEApp } = require('./ide-manager');
9
+ const { IDE_INFO, isIDERunning } = require('./ide-manager');
10
10
  const { getResultFilePath, getAgentsFilePath, updateAgentStatus, getAgentStatus } = require('./agents-manager');
11
+ const { startVSCodeApprovalClicker } = require('./vscode-approval-clicker');
12
+ const { startCursorApprovalClicker } = require('./cursor-approval-clicker');
13
+ const { checkIDEQuotaLimitAndDone } = require('./ide-quota-checker');
14
+ const { ensureIDEReady } = require('./ide-installer-helper');
11
15
 
12
16
  // Timeout for direct LLM round-trips via auto:direct (ms)
13
17
  const DIRECT_TIMEOUT_MS = 60000;
14
- // Timeout for IDE automation round-trips via auto:start (ms)
15
- const IDE_TIMEOUT_MS = 90000;
18
+ // Timeout for IDE automation round-trips AI needs time to receive, process, and edit agents.json
19
+ const IDE_TIMEOUT_MS = 360000;
16
20
 
17
21
  const CLI_ENTRY_POINT = path.resolve(path.join(__dirname, '../../../bin/vibecodingmachine.js'));
18
22
 
@@ -30,113 +34,21 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
30
34
 
31
35
  // Ensure temp dir exists
32
36
  fs.mkdirSync(path.dirname(resultFile), { recursive: true });
33
- // Remove stale result file so we detect a fresh write
37
+ // Remove stale result files so we detect a fresh write
34
38
  try { fs.unlinkSync(resultFile); } catch { }
39
+ const _homeResultFile = path.join(require('os').homedir(), '.vibecodingmachine', 'temp', 'TEMP_agent_check.txt');
40
+ try { fs.mkdirSync(path.dirname(_homeResultFile), { recursive: true }); } catch { }
41
+ try { fs.unlinkSync(_homeResultFile); } catch { }
35
42
 
36
43
  // For IDE providers: verify the IDE is running/installed, install if needed
37
44
  let ideLaunchNote = '';
38
45
  if (def.type === 'ide') {
39
46
  const info = IDE_INFO[providerId] || IDE_INFO[def.ide] || null;
40
- if (info && info.process) {
41
- if (!isIDERunning(info.process)) {
42
- // macOS: launch the app if not running
43
- if (process.platform === 'darwin' && info.app) {
44
- const launchSuccess = await openIDEApp(info.app, repoPath);
45
- if (launchSuccess) {
46
- ideLaunchNote = ` (VCM launched ${info.app})`;
47
- } else {
48
- // Failed to launch on macOS - check if installed
49
- const { IDEInstaller } = require('../../../../electron-app/src/main/ide-installer');
50
- const installer = new IDEInstaller();
51
- const ideKey = def.ide || providerId;
52
- const checkResult = await installer.checkIDEInstallation(ideKey);
53
- if (!checkResult.installed) {
54
- return {
55
- status: 'error',
56
- message: `${info.app} is not installed. Please download from ${IDEInstaller.IDE_CONFIG[ideKey]?.downloadBrowserUrl || 'its official website'}`,
57
- checkedAt
58
- };
59
- }
60
- }
61
- }
62
- // Windows: check if installed, install if possible, launch if installed
63
- else if (process.platform === 'win32') {
64
- const { IDEInstaller } = require('../../../../electron-app/src/main/ide-installer');
65
- const installer = new IDEInstaller();
66
- const ideKey = def.ide || providerId;
67
- const ideConfig = IDEInstaller.IDE_CONFIG[ideKey];
68
-
69
- // Check if IDE is installed
70
- let checkResult = await installer.checkIDEInstallation(ideKey);
71
-
72
- if (!checkResult.installed) {
73
- // IDE is not installed - try to install if we have a download URL
74
- const downloadUrl = ideConfig?.downloadUrl?.[process.platform];
75
-
76
- if (downloadUrl) {
77
- // Has a direct download URL - auto-install
78
- console.log(`[AGENT CHECK] ${info.app || ideKey} not installed, installing...`);
79
- if (onProgress) onProgress(providerId, 'installing');
80
-
81
- try {
82
- const installResult = await installer.installIDE(ideKey, (progress) => {
83
- console.log(`[AGENT CHECK] Installation progress for ${ideKey}: ${progress.progress}% - ${progress.message}`);
84
- });
85
-
86
- if (!installResult || !installResult.success) {
87
- console.error(`[AGENT CHECK] Installation failed for ${info.app || ideKey}`);
88
- return {
89
- status: 'error',
90
- message: `Failed to install ${info.app || ideKey}: ${installResult?.error || 'Installation failed'}. Please install manually and try again.`,
91
- checkedAt
92
- };
93
- }
94
-
95
- console.log(`[AGENT CHECK] ${info.app || ideKey} installed successfully`);
96
- ideLaunchNote = ` (VCM installed ${info.app || ideKey})`;
97
- // Re-check that installation succeeded
98
- await new Promise(r => setTimeout(r, 3000));
99
- checkResult = await installer.checkIDEInstallation(ideKey);
100
- } catch (installError) {
101
- console.error(`[AGENT CHECK] Installation error for ${info.app || ideKey}:`, installError.message);
102
- return {
103
- status: 'error',
104
- message: `Installation failed for ${info.app || ideKey}: ${installError.message}. Please install manually and try again.`,
105
- checkedAt
106
- };
107
- }
108
- } else {
109
- // No direct download URL - provide browser download link
110
- const browserUrl = ideConfig?.downloadBrowserUrl || `${ideKey}'s official website`;
111
- return {
112
- status: 'error',
113
- message: `${info.app || ideKey} is not installed. Please download from: ${browserUrl}`,
114
- checkedAt
115
- };
116
- }
117
- }
118
-
119
- // IDE is now installed (either was already or we just installed it) - launch it if not already running
120
- if (checkResult.installed) {
121
- // Check if IDE is already running before attempting to launch
122
- const isRunning = isIDERunning(info.process);
123
- if (!isRunning) {
124
- console.log(`🪟 [AGENT CHECK] ${info.app} not running, attempting to launch...`);
125
- // Use openIDEApp which will use WindowsAutomationManager
126
- const launchSuccess = await openIDEApp(info.app, repoPath);
127
- if (launchSuccess) {
128
- ideLaunchNote = ideLaunchNote || ` (VCM launched ${info.app})`;
129
- console.log(`🪟 [AGENT CHECK] Successfully launched ${info.app}`);
130
- } else {
131
- console.warn(`🪟 [AGENT CHECK] Could not launch ${info.app}, continuing anyway...`);
132
- }
133
- } else {
134
- console.log(`[AGENT CHECK] ${info.app} is already running, skipping launch`);
135
- // Give running IDE a moment to be ready
136
- await new Promise(r => setTimeout(r, 2000));
137
- }
138
- }
139
- }
47
+ if (info && (info.process || info.appPath) && !isIDERunning(info.process, info.appPath)) {
48
+ const ideResult = await ensureIDEReady(providerId, def, repoPath, info, onProgress);
49
+ ideLaunchNote = ideResult.ideLaunchNote;
50
+ if (ideResult.error) {
51
+ return { status: 'error', message: ideResult.error, checkedAt };
140
52
  }
141
53
  }
142
54
  }
@@ -148,9 +60,13 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
148
60
  let watcher;
149
61
  let requirementsWatcher;
150
62
 
63
+ // Shared resolved-state object so clicker modules can check it
64
+ const resolvedRef = { resolved: false };
65
+
151
66
  async function done(result) {
152
67
  if (resolved) return;
153
68
  resolved = true;
69
+ resolvedRef.resolved = true;
154
70
  try { if (watcher) watcher.close(); } catch { }
155
71
  try { if (requirementsWatcher) requirementsWatcher.close(); } catch { }
156
72
  clearTimeout(timeout);
@@ -160,15 +76,14 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
160
76
  // Update agent status based on result
161
77
  try {
162
78
  if (result.status === 'success') {
163
- // Status already set to 'operational' by the IDE agent
164
79
  console.log(`[AGENT CHECK] ${providerId} check passed - status is 'operational'`);
165
80
  } else if (result.rateLimited) {
166
- updateAgentStatus(providerId, 'rate_limited', {
81
+ await updateAgentStatus(providerId, 'rate_limited', {
167
82
  rateLimitResume: result.rateLimitResume
168
83
  });
169
84
  console.log(`[AGENT CHECK] Set ${providerId} status to 'rate_limited'`);
170
85
  } else {
171
- updateAgentStatus(providerId, 'error', {
86
+ await updateAgentStatus(providerId, 'error', {
172
87
  error: result.message
173
88
  });
174
89
  console.log(`[AGENT CHECK] Set ${providerId} status to 'error'`);
@@ -177,7 +92,6 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
177
92
  console.warn(`[AGENT CHECK] Could not update agent status: ${err.message}`);
178
93
  }
179
94
 
180
- // Notify UI that check is done
181
95
  if (onProgress) {
182
96
  const statusMessage = result.status === 'success'
183
97
  ? 'Check completed successfully'
@@ -188,68 +102,90 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
188
102
  resolve(result);
189
103
  }
190
104
 
105
+ // Also watch home-dir fallback path (some IDEs resolve relative paths to ~ not repoPath)
106
+ const homeResultFile = path.join(require('os').homedir(), '.vibecodingmachine', 'temp', 'TEMP_agent_check.txt');
107
+
191
108
  function checkResult() {
192
- if (!resolved && fs.existsSync(resultFile)) {
193
- try {
194
- const content = fs.readFileSync(resultFile, 'utf8');
195
- if (content.includes('VCM_CHECK_OK')) {
196
- if (onProgress) onProgress(providerId, 'response_detected', null, 'Response detected.');
197
- done({ status: 'success', message: 'End-to-end check passed', checkedAt });
198
- }
199
- } catch { }
109
+ for (const f of [resultFile, homeResultFile]) {
110
+ if (!resolved && fs.existsSync(f)) {
111
+ try {
112
+ const content = fs.readFileSync(f, 'utf8');
113
+ if (content.includes('VCM_CHECK_OK')) {
114
+ console.log(`[AGENT CHECK] ${providerId}: VCM_CHECK_OK found in ${f}`);
115
+ if (onProgress) onProgress(providerId, 'response_detected', null, 'Response detected.');
116
+ done({ status: 'success', message: 'End-to-end check passed', checkedAt });
117
+ return;
118
+ }
119
+ } catch { }
120
+ }
200
121
  }
201
122
  }
202
123
 
203
- // Watch for result file creation
204
- watcher = chokidar.watch(resultFile, { persistent: true, ignoreInitial: false, disableGlobbing: true });
124
+ // Watch for result file creation (both repo-path and home-dir fallback)
125
+ watcher = chokidar.watch([resultFile, homeResultFile], { persistent: true, ignoreInitial: false, disableGlobbing: true });
205
126
  watcher.on('add', checkResult);
206
127
  watcher.on('change', checkResult);
207
128
 
208
- // Watch agents.json for status changes to 'operational'
209
- // Use debouncing to prevent multiple rapid status checks
129
+ // Watch agents.json for status changes to 'operational' written AFTER this test started.
130
+ // Guard against stale 'operational' status from a previous test run for this or another agent.
210
131
  let debounceTimer = null;
211
132
  const agentsFilePath = getAgentsFilePath();
212
133
  requirementsWatcher = chokidar.watch(agentsFilePath, { persistent: true, ignoreInitial: true });
213
134
  requirementsWatcher.on('change', () => {
214
- // Clear existing debounce timer
215
135
  if (debounceTimer) clearTimeout(debounceTimer);
216
-
217
- // Set new timer (50ms debounce - fast response while avoiding duplicate reads)
218
136
  debounceTimer = setTimeout(() => {
219
- try {
220
- const agentStatus = getAgentStatus(providerId);
221
- console.log(`[AGENT CHECK] Current status for ${providerId}: ${agentStatus.status}`);
222
-
223
- // Check if agent status is 'operational'
224
- if (agentStatus.status === 'operational') {
225
- console.log(`[AGENT CHECK] Detected 'operational' status in agents.json for ${providerId}`);
226
- if (onProgress) onProgress(providerId, 'response_detected', null, 'Status updated to operational.');
227
- done({ status: 'success', message: 'Agent updated status to operational', checkedAt });
137
+ try {
138
+ const agentStatus = getAgentStatus(providerId);
139
+ console.log(`[AGENT CHECK] Current status for ${providerId}: ${agentStatus.status}`);
140
+ const writtenAfterTestStart = agentStatus.lastChecked && new Date(agentStatus.lastChecked) > new Date(checkedAt);
141
+ if (agentStatus.status === 'operational' && writtenAfterTestStart) {
142
+ console.log(`[AGENT CHECK] Detected fresh 'operational' status for ${providerId} (written at ${agentStatus.lastChecked})`);
143
+ if (onProgress) onProgress(providerId, 'response_detected', null, 'Status updated to operational.');
144
+ done({ status: 'success', message: 'Agent updated status to operational', checkedAt });
145
+ } else if (agentStatus.status === 'operational' && !writtenAfterTestStart) {
146
+ console.log(`[AGENT CHECK] Ignoring stale 'operational' for ${providerId} — was set before this test started`);
147
+ }
148
+ } catch (err) {
149
+ console.warn(`[AGENT CHECK] Error reading agents.json: ${err.message}`);
228
150
  }
229
- } catch (err) {
230
- console.warn(`[AGENT CHECK] Error reading agents.json: ${err.message}`);
231
- }
232
- }, 50); // End of debounce setTimeout - reduced from 300ms to 50ms for faster response
151
+ }, 50);
233
152
  });
234
153
 
235
154
  const timeout = setTimeout(() => {
236
- // Diagnose: is the IDE process still running?
237
155
  let diagnosis = '';
238
156
  if (def.type === 'ide') {
239
157
  const info = IDE_INFO[providerId] || IDE_INFO[def.ide] || null;
240
- if (info && info.process) {
241
- diagnosis = isIDERunning(info.process)
158
+ if (info && (info.process || info.appPath)) {
159
+ diagnosis = isIDERunning(info.process, info.appPath)
242
160
  ? ` — ${info.app || info.process} is running but did not respond`
243
161
  : ` — ${info.app || info.process} is not running`;
244
162
  }
245
163
  }
246
164
  console.warn(`[AGENT CHECK] Timeout for ${providerId} after ${timeoutMs / 1000}s${diagnosis}`);
247
165
 
248
- const timeoutResult = { status: 'error', message: `Timeout${ideLaunchNote}${diagnosis}`, checkedAt };
166
+ const ideNotRunning = def.type === 'ide' && diagnosis.includes('is not running');
167
+ const failureReason = ideNotRunning
168
+ ? `${def.name || providerId} is not running`
169
+ : `${def.name || providerId} did not complete the test file write within ${timeoutMs / 1000}s${diagnosis}`;
170
+ const userAction = ideNotRunning
171
+ ? `Open ${def.name || providerId} and try again`
172
+ : `Check that ${def.name || providerId} is logged in, has no quota errors, and can run shell commands`;
173
+ const timeoutResult = { status: 'error', message: `Timeout${ideLaunchNote}${diagnosis}`, checkedAt, failureReason, userAction };
249
174
 
250
- // For IDE timeout, also check for quota limit (in output + UI)
251
175
  if (def.type === 'ide') {
252
- checkIDEQuotaLimitAndDone(providerId, timeoutResult).catch(err => {
176
+ try {
177
+ const { getAgentStatus } = require('./agents-manager');
178
+ const currentStatus = getAgentStatus(providerId);
179
+ if (currentStatus && currentStatus.status === 'operational' &&
180
+ currentStatus.lastChecked && new Date(currentStatus.lastChecked) > new Date(checkedAt)) {
181
+ console.log(`[AGENT CHECK] ${providerId} succeeded after timeout — status is operational`);
182
+ done({ status: 'success', message: 'Agent updated status to operational (post-timeout)', checkedAt });
183
+ return;
184
+ }
185
+ } catch (e) {
186
+ // ignore
187
+ }
188
+ checkIDEQuotaLimitAndDone(providerId, timeoutResult, output, done).catch(err => {
253
189
  console.error('[AGENT CHECK] Error in quota check:', err);
254
190
  done(timeoutResult);
255
191
  });
@@ -263,38 +199,70 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
263
199
  if (signal && signal.cancelled) {
264
200
  done({ status: 'error', message: 'Check cancelled by user', checkedAt });
265
201
  }
266
- }, 1000); // Check every second
202
+ }, 1000);
267
203
 
268
- // Send initial checking status
269
204
  if (onProgress) {
270
205
  onProgress(providerId, 'awaiting', null, 'Awaiting response...');
271
206
  }
272
207
 
273
- // For IDE providers: send connectivity test directly using Windows automation
274
- // Don't spawn auto:start since it expects requirements files (which we removed)
208
+ // For IDE providers: send connectivity test directly using platform-specific automation
275
209
  if (def.type === 'ide') {
276
210
  try {
277
211
  const { generateConnectivityTestMessage } = require('./agents-manager');
278
- const { WindowsAutomationManager } = require('vibecodingmachine-core');
279
212
 
280
- console.log(`[AGENT CHECK] Sending connectivity test directly to ${providerId}`);
213
+ let automation;
214
+ if (process.platform === 'darwin') {
215
+ const { AppleScriptManager } = require('vibecodingmachine-core');
216
+ automation = new AppleScriptManager();
217
+ } else if (process.platform === 'win32') {
218
+ const { WindowsAutomationManager } = require('vibecodingmachine-core');
219
+ automation = new WindowsAutomationManager();
220
+ } else {
221
+ return {
222
+ status: 'error',
223
+ message: `Platform ${process.platform} not supported for IDE automation`,
224
+ checkedAt
225
+ };
226
+ }
281
227
 
282
- // Get the test message
283
- const testMessage = generateConnectivityTestMessage(def.name || providerId, providerId);
228
+ console.log(`[AGENT CHECK] Sending connectivity test directly to ${providerId}`);
229
+ console.log(`[AGENT CHECK] Setting ${providerId} status to 'checking' in agents.json`);
230
+ try {
231
+ await updateAgentStatus(providerId, 'checking');
232
+ console.log(`[AGENT CHECK] Set ${providerId} status to 'checking'`);
233
+ } catch (err) {
234
+ console.warn(`[AGENT CHECK] Could not set agent status: ${err.message}`);
235
+ }
284
236
 
285
- // Send directly to IDE using Windows automation
286
- const automation = new WindowsAutomationManager();
237
+ const testMessage = generateConnectivityTestMessage(def.name || providerId, providerId, repoPath);
238
+ console.log(`[AGENT CHECK] ${providerId}: test message = "${testMessage}"`);
287
239
 
288
- // Call the appropriate method based on provider
289
240
  let sendResult;
290
241
  try {
291
242
  switch(providerId.toLowerCase()) {
292
- case 'windsurf':
293
- sendResult = await automation.sendTextToWindsurf(testMessage);
294
- break;
243
+ case 'devin':
244
+ // Devin is web-based — not automatable via desktop automation
245
+ done({ status: 'error', message: 'Devin is web-based and cannot be tested via desktop automation', checkedAt });
246
+ return;
295
247
  case 'cursor':
296
248
  sendResult = await automation.sendTextToCursor(testMessage);
297
249
  break;
250
+ case 'antigravity':
251
+ sendResult = await automation.sendTextToAntigravity(testMessage);
252
+ break;
253
+ case 'kiro':
254
+ sendResult = await automation.sendTextToKiro(testMessage);
255
+ break;
256
+ case 'vscode':
257
+ case 'github-copilot':
258
+ case 'vscode-copilot-cli':
259
+ case 'amazon-q':
260
+ sendResult = await automation.sendTextToVSCode(testMessage);
261
+ break;
262
+ case 'replit':
263
+ // Replit is browser-based — not automatable via desktop AppleScript
264
+ done({ status: 'error', message: 'Replit is browser-based and cannot be tested via desktop automation', checkedAt });
265
+ return;
298
266
  default:
299
267
  sendResult = { success: false, error: `No automation method for ${providerId}` };
300
268
  }
@@ -314,7 +282,63 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
314
282
  console.log(`[AGENT CHECK] Successfully sent connectivity test to ${providerId}`);
315
283
  console.log(`[AGENT CHECK] Waiting for IDE to update agents.json status to 'operational'...`);
316
284
 
317
- // Don't spawn child process - just wait for file watcher to detect status change
285
+ // Antigravity shows "Allow running this command?" approval dialog auto-approve with "1" + Enter
286
+ if (process.platform === 'darwin' && providerId === 'antigravity') {
287
+ const { spawn: spawnApproval } = require('child_process');
288
+ const tryApproveAntigravity = (attempt) => {
289
+ if (resolved) return;
290
+ console.log(`[AGENT CHECK] Antigravity: pressing "1" to approve command (attempt ${attempt})`);
291
+ const approveScript = `
292
+ tell application "Antigravity" to activate
293
+ delay 0.5
294
+ tell application "System Events"
295
+ tell process "Antigravity"
296
+ keystroke "1"
297
+ delay 0.3
298
+ key code 36
299
+ end tell
300
+ end tell
301
+ `;
302
+ const tmpFile = require('os').tmpdir() + '/antigravity_approve.scpt';
303
+ require('fs').writeFileSync(tmpFile, approveScript);
304
+ const approveChild = spawnApproval('osascript', [tmpFile], { detached: true, stdio: 'ignore' });
305
+ approveChild.unref();
306
+ };
307
+ for (let i = 0; i < 20; i++) {
308
+ setTimeout(() => tryApproveAntigravity(i + 1), 20000 + i * 15000);
309
+ }
310
+ }
311
+
312
+ // VS Code-based IDEs show "Allow"/"Run" buttons in WebViews — use CGEvent clicker
313
+ if (process.platform === 'darwin' && (providerId === 'github-copilot' || providerId === 'amazon-q' || providerId === 'kiro')) {
314
+ startVSCodeApprovalClicker(providerId, resolvedRef, testMessage);
315
+ }
316
+
317
+ // Cursor shows a "Run" button for terminal commands in agentic mode
318
+ if (process.platform === 'darwin' && providerId === 'cursor') {
319
+ startCursorApprovalClicker(resolvedRef);
320
+ }
321
+
322
+ // Early quota check for cursor
323
+ if (process.platform === 'darwin' && providerId === 'cursor') {
324
+ const earlyCheckDelay = 30000;
325
+ setTimeout(async () => {
326
+ if (resolved) return;
327
+ try {
328
+ let quotaCheck = null;
329
+ if (providerId === 'cursor') {
330
+ quotaCheck = await automation.checkCursorQuotaLimit();
331
+ }
332
+ if (quotaCheck && (quotaCheck.isRateLimited || quotaCheck.hasQuotaWarning)) {
333
+ console.log(`[AGENT CHECK] ${providerId} rate limit detected early`);
334
+ done({ status: 'error', message: `Rate limited: ${quotaCheck.matchedText || quotaCheck.message || 'quota exceeded'}`, checkedAt, rateLimited: true });
335
+ }
336
+ } catch (e) {
337
+ console.log(`[AGENT CHECK] Early rate limit check error for ${providerId}: ${e.message}`);
338
+ }
339
+ }, earlyCheckDelay);
340
+ }
341
+
318
342
  return;
319
343
 
320
344
  } catch (err) {
@@ -324,17 +348,15 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
324
348
  }
325
349
  }
326
350
 
327
- // For direct LLM providers: still use auto:direct
351
+ // For direct LLM providers: use auto:direct
328
352
  let args;
329
353
  if (def.type !== 'ide') {
330
354
  args = [CLI_ENTRY_POINT, 'auto:direct', '--provider', providerId, '--max-chats', '1'];
331
355
  } else {
332
- // IDE handling moved above - this shouldn't be reached
333
356
  done({ status: 'error', message: 'IDE handling logic error', checkedAt });
334
357
  return;
335
358
  }
336
359
 
337
- // Verify CLI entry point exists and is readable
338
360
  if (!fs.existsSync(CLI_ENTRY_POINT)) {
339
361
  console.error(`[AGENT CHECK] CLI entry point not found: ${CLI_ENTRY_POINT}`);
340
362
  done({ status: 'error', message: `CLI entry point not found: ${CLI_ENTRY_POINT}`, checkedAt });
@@ -349,7 +371,6 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
349
371
  return;
350
372
  }
351
373
 
352
- // Verify repo path exists and is accessible
353
374
  if (!fs.existsSync(repoPath)) {
354
375
  console.error(`[AGENT CHECK] Repository path not found: ${repoPath}`);
355
376
  done({ status: 'error', message: `Repository path not found: ${repoPath}`, checkedAt });
@@ -364,29 +385,24 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
364
385
  return;
365
386
  }
366
387
 
367
- // Log the command being executed
368
388
  console.log(`[AGENT CHECK] Starting check for ${providerId}`);
369
389
  console.log(`[AGENT CHECK] Node Executable: ${NODE_EXECUTABLE}`);
370
390
  console.log(`[AGENT CHECK] Args: ${args.join(' ')}`);
371
391
  console.log(`[AGENT CHECK] CWD: ${repoPath}`);
372
392
  console.log(`[AGENT CHECK] Result file: ${resultFile}`);
373
393
 
374
- // Set agent status to 'checking' in agents.json before sending test
375
394
  console.log(`[AGENT CHECK] Setting ${providerId} status to 'checking' in agents.json`);
376
395
  try {
377
- updateAgentStatus(providerId, 'checking');
396
+ await updateAgentStatus(providerId, 'checking');
378
397
  console.log(`[AGENT CHECK] Set ${providerId} status to 'checking'`);
379
398
  } catch (err) {
380
399
  console.warn(`[AGENT CHECK] Could not set agent status: ${err.message}`);
381
400
  }
382
401
 
383
- // Prepare environment - inherit all process.env and add NODE_PATH if needed
384
402
  const spawnEnv = {
385
403
  ...process.env,
386
- // Set IDE check mode flag so auto-execution knows to use --ide option instead of configured providers
387
404
  VCM_IDE_CHECK_MODE: 'true',
388
405
  VCM_SKIP_AUTH: 'true',
389
- // Ensure NODE_PATH includes the monorepo node_modules if it exists
390
406
  NODE_PATH: [
391
407
  path.join(__dirname, '../../node_modules'),
392
408
  path.join(__dirname, '../../../node_modules'),
@@ -394,13 +410,6 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
394
410
  ].filter(Boolean).join(path.delimiter)
395
411
  };
396
412
 
397
- // Log the command being executed
398
- console.log(`[AGENT CHECK] Starting check for ${providerId}`);
399
- console.log(`[AGENT CHECK] Node Executable: ${NODE_EXECUTABLE}`);
400
- console.log(`[AGENT CHECK] Args: ${args.join(' ')}`);
401
- console.log(`[AGENT CHECK] CWD: ${repoPath}`);
402
- console.log(`[AGENT CHECK] Result file: ${resultFile}`);
403
-
404
413
  child = spawn(NODE_EXECUTABLE, args, {
405
414
  cwd: repoPath,
406
415
  env: spawnEnv,
@@ -435,13 +444,11 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
435
444
  console.log(`[AGENT CHECK] ${providerId} process exited with code ${code}`);
436
445
  console.log(`[AGENT CHECK] ${providerId} process output: ${output.slice(-500)}`);
437
446
 
438
- // Additional debugging for Windsurf authentication issues
439
- if (providerId === 'windsurf' && code === 8) {
440
- console.log(`[AGENT CHECK] Windsurf specific debugging - code 8 often indicates authentication or startup issues`);
441
- console.log(`[AGENT CHECK] Windsurf output analysis:`, output.split('\n').slice(-10));
447
+ if (providerId === 'devin' && code === 8) {
448
+ console.log(`[AGENT CHECK] Devin specific debugging - code 8 often indicates authentication or startup issues`);
449
+ console.log(`[AGENT CHECK] Devin output analysis:`, output.split('\n').slice(-10));
442
450
  }
443
451
 
444
- // Check for DONE status in output (indicates successful completion)
445
452
  if (code === 0 && output.includes('Status: ✅ DONE') && output.includes('Requirement complete')) {
446
453
  console.log(`[AGENT CHECK] Detected DONE in console output for ${providerId}`);
447
454
  console.log(`[AGENT CHECK] ✅ Test PASSED: Agent reached DONE status - communication verified`);
@@ -450,9 +457,24 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
450
457
  return;
451
458
  }
452
459
 
453
- // Check one more time after process exits
460
+ if (code === 0 && def.type === 'direct' && (output.includes('No requirements') || output.includes('No more TODO'))) {
461
+ console.log(`[AGENT CHECK] ${providerId} CLI exited cleanly — marking operational`);
462
+ if (onProgress) onProgress(providerId, 'response_detected', null, 'CLI verified operational.');
463
+ done({ status: 'success', message: `${providerId} CLI is operational`, checkedAt });
464
+ return;
465
+ }
466
+
454
467
  checkResult();
455
468
  if (!resolved) {
469
+ // Detect rate-limit / credit-balance conditions — treat as rateLimited, not a config error
470
+ const isRateLimited = /credit balance is too low/i.test(output) ||
471
+ (/rate.?limit/i.test(output) && /no providers available/i.test(output));
472
+ if (isRateLimited) {
473
+ console.log(`[AGENT CHECK] ${providerId} detected as rate-limited via output scan`);
474
+ done({ status: 'error', rateLimited: true, message: 'Rate limited (credit balance low or quota exceeded)', checkedAt });
475
+ return;
476
+ }
477
+
456
478
  const tail = output.slice(-300).trim().replace(/\n/g, ' ');
457
479
  let codeInfo = '';
458
480
  if (code === 4294967295 || code === -1) {
@@ -468,9 +490,8 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
468
490
 
469
491
  const errorResult = { status: 'error', message: `Automation exited (code ${code})${codeInfo}${tail ? ': ' + tail : ''}`, checkedAt };
470
492
 
471
- // For IDE providers, check for quota limit (UI + process output)
472
493
  if (def.type === 'ide') {
473
- checkIDEQuotaLimitAndDone(providerId, errorResult).catch(err => {
494
+ checkIDEQuotaLimitAndDone(providerId, errorResult, output, done).catch(err => {
474
495
  console.error('[AGENT CHECK] Error in quota check:', err);
475
496
  done(errorResult);
476
497
  });
@@ -479,138 +500,6 @@ async function runAgentCheck(providerId, def, repoPath, resultFile, timeoutMs, s
479
500
  }
480
501
  }
481
502
  });
482
-
483
- // Helper function to check IDE quota limits and call done with enriched result
484
- async function checkIDEQuotaLimitAndDone(providerId, errorResult) {
485
- const debugLog = (msg) => {
486
- const timestamp = new Date().toISOString();
487
- const logLine = `[${timestamp}] ${msg}\n`;
488
- try {
489
- fs.appendFileSync(`/tmp/vibe-${providerId}-quota-debug.log`, logLine);
490
- } catch (_) { }
491
- console.log(`[AGENT CHECK] ${msg}`);
492
- };
493
-
494
- debugLog(`Starting checkIDEQuotaLimitAndDone for ${providerId}`);
495
- debugLog('errorResult.message: ' + JSON.stringify(errorResult.message).substring(0, 200));
496
-
497
- try {
498
- debugLog(`Checking for ${providerId} quota limit...`);
499
-
500
- // Check process output first for quota error keywords
501
- const lowerOutput = output.toLowerCase();
502
- const lowerErrorMsg = errorResult.message.toLowerCase();
503
- debugLog('Checking process output length: ' + output.length);
504
- debugLog('Process output sample: ' + output.substring(0, 300));
505
-
506
- // Check both output and error message for quota keywords
507
- const quotaKeywords = ['quota', 'rate limit', 'resource_exhausted', 'usage limit', 'model quota', 'limit exceeded', 'spending cap', 'usage cap', 'you\'ve reached your monthly chat messages quota', 'upgrade to copilot pro', 'wait for your allowance to renew'];
508
- const hasQuotaKeyword = quotaKeywords.some(kw => lowerOutput.includes(kw) || lowerErrorMsg.includes(kw));
509
-
510
- if (hasQuotaKeyword) {
511
- debugLog(`🚨 Quota keywords found in process output or message for ${providerId}`);
512
- errorResult.rateLimited = true;
513
- errorResult.rateLimitMessage = output || errorResult.message;
514
- // Set provider-specific rate limit flags for compatibility
515
- switch (providerId) {
516
- case 'antigravity':
517
- errorResult.antigravityRateLimited = true;
518
- break;
519
- case 'windsurf':
520
- errorResult.windsurfRateLimited = true;
521
- break;
522
- case 'cursor':
523
- errorResult.cursorRateLimited = true;
524
- break;
525
- case 'github-copilot':
526
- errorResult.githubCopilotRateLimited = true;
527
- break;
528
- }
529
- debugLog('Set rateLimited to true, calling done()');
530
- done(errorResult);
531
- return;
532
- }
533
-
534
- debugLog(`No quota keywords in process output or message, checking platform-specific UI fallback for ${providerId}`);
535
-
536
- // Get quota manager based on platform
537
- let quotaManager = null;
538
- if (process.platform === 'darwin') {
539
- const { AppleScriptManager } = require('vibecodingmachine-core');
540
- quotaManager = new AppleScriptManager();
541
- } else if (process.platform === 'win32') {
542
- const { WindowsAutomationManager } = require('vibecodingmachine-core');
543
- quotaManager = new WindowsAutomationManager();
544
- }
545
-
546
- // Check platform-specific UI scraping as fallback for IDEs that support it
547
- if (quotaManager) {
548
- try {
549
- let quotaCheck = null;
550
-
551
- // Use specific quota detection methods for each IDE
552
- switch (providerId) {
553
- case 'antigravity':
554
- quotaCheck = await quotaManager.checkAntigravityQuotaLimit();
555
- break;
556
- case 'windsurf':
557
- quotaCheck = await quotaManager.checkWindsurfQuotaLimit();
558
- break;
559
- case 'cursor':
560
- quotaCheck = await quotaManager.checkCursorQuotaLimit();
561
- break;
562
- case 'github-copilot':
563
- // GitHub Copilot uses the same detection as Cursor (both are VS Code extensions)
564
- quotaCheck = await quotaManager.checkCursorQuotaLimit();
565
- break;
566
- default:
567
- debugLog(`No specific quota detection method available for ${providerId}`);
568
- break;
569
- }
570
-
571
- debugLog(`${providerId} quota check result: ` + JSON.stringify(quotaCheck));
572
-
573
- if (quotaCheck && (quotaCheck.isRateLimited || quotaCheck.hasQuotaWarning)) {
574
- debugLog(`🚨 ${providerId} quota limit detected via platform UI check`);
575
- errorResult.rateLimited = true;
576
- errorResult.rateLimitMessage = quotaCheck.message || quotaCheck.matchedText || `${providerId} quota limit detected`;
577
- if (quotaCheck.resumeAt) {
578
- errorResult.rateLimitResume = quotaCheck.resumeAt;
579
- }
580
- // Set provider-specific rate limit flags for compatibility
581
- switch (providerId) {
582
- case 'antigravity':
583
- errorResult.antigravityRateLimited = true;
584
- break;
585
- case 'windsurf':
586
- errorResult.windsurfRateLimited = true;
587
- break;
588
- case 'cursor':
589
- errorResult.cursorRateLimited = true;
590
- break;
591
- case 'github-copilot':
592
- errorResult.githubCopilotRateLimited = true;
593
- break;
594
- }
595
- debugLog('Enriched error result with quota limit');
596
- } else {
597
- debugLog(`No rate limit detected for ${providerId}`);
598
- }
599
- } catch (appleScriptError) {
600
- debugLog(`AppleScript quota detection failed for ${providerId}: ${appleScriptError.message}`);
601
- }
602
- } else {
603
- debugLog(`Skipping AppleScript quota detection for ${providerId} on non-macOS platform`);
604
- }
605
- } catch (err) {
606
- debugLog(`Error checking ${providerId} quota: ${err.message}`);
607
- } finally {
608
- debugLog('Calling done() with final errorResult');
609
- debugLog('Final errorResult.rateLimited: ' + errorResult.rateLimited);
610
- debugLog('Final errorResult.rateLimitMessage: ' + (errorResult.rateLimitMessage ? errorResult.rateLimitMessage.substring(0, 100) : 'none'));
611
- done(errorResult);
612
- }
613
- }
614
503
  });
615
504
  }
616
505