vibecodingmachine-core 1.0.0

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 (54) hide show
  1. package/.babelrc +13 -0
  2. package/README.md +28 -0
  3. package/__tests__/applescript-manager-claude-fix.test.js +286 -0
  4. package/__tests__/requirement-2-auto-start-looping.test.js +69 -0
  5. package/__tests__/requirement-3-auto-start-looping.test.js +69 -0
  6. package/__tests__/requirement-4-auto-start-looping.test.js +69 -0
  7. package/__tests__/requirement-6-auto-start-looping.test.js +73 -0
  8. package/__tests__/requirement-7-status-tracking.test.js +332 -0
  9. package/jest.config.js +18 -0
  10. package/jest.setup.js +12 -0
  11. package/package.json +46 -0
  12. package/src/auth/access-denied.html +119 -0
  13. package/src/auth/shared-auth-storage.js +230 -0
  14. package/src/autonomous-mode/feature-implementer.cjs +70 -0
  15. package/src/autonomous-mode/feature-implementer.js +425 -0
  16. package/src/chat-management/chat-manager.cjs +71 -0
  17. package/src/chat-management/chat-manager.js +342 -0
  18. package/src/ide-integration/__tests__/applescript-manager-thread-closure.test.js +227 -0
  19. package/src/ide-integration/aider-cli-manager.cjs +850 -0
  20. package/src/ide-integration/applescript-diagnostics.js +0 -0
  21. package/src/ide-integration/applescript-manager.cjs +1088 -0
  22. package/src/ide-integration/applescript-manager.js +2803 -0
  23. package/src/ide-integration/applescript-open-apps.js +0 -0
  24. package/src/ide-integration/applescript-read-response.js +0 -0
  25. package/src/ide-integration/applescript-send-text.js +0 -0
  26. package/src/ide-integration/applescript-thread-closure.js +0 -0
  27. package/src/ide-integration/applescript-utils.js +306 -0
  28. package/src/ide-integration/cdp-manager.cjs +221 -0
  29. package/src/ide-integration/cdp-manager.js +321 -0
  30. package/src/ide-integration/claude-code-cli-manager.cjs +301 -0
  31. package/src/ide-integration/cline-cli-manager.cjs +2252 -0
  32. package/src/ide-integration/continue-cli-manager.js +431 -0
  33. package/src/ide-integration/provider-manager.cjs +354 -0
  34. package/src/ide-integration/quota-detector.cjs +34 -0
  35. package/src/ide-integration/quota-detector.js +349 -0
  36. package/src/ide-integration/windows-automation-manager.js +262 -0
  37. package/src/index.cjs +43 -0
  38. package/src/index.js +17 -0
  39. package/src/llm/direct-llm-manager.cjs +609 -0
  40. package/src/ui/ButtonComponents.js +247 -0
  41. package/src/ui/ChatInterface.js +499 -0
  42. package/src/ui/StateManager.js +259 -0
  43. package/src/ui/StateManager.test.js +0 -0
  44. package/src/utils/audit-logger.cjs +116 -0
  45. package/src/utils/config-helpers.cjs +94 -0
  46. package/src/utils/config-helpers.js +94 -0
  47. package/src/utils/electron-update-checker.js +78 -0
  48. package/src/utils/gcloud-auth.cjs +394 -0
  49. package/src/utils/logger.cjs +193 -0
  50. package/src/utils/logger.js +191 -0
  51. package/src/utils/repo-helpers.cjs +120 -0
  52. package/src/utils/repo-helpers.js +120 -0
  53. package/src/utils/requirement-helpers.js +432 -0
  54. package/src/utils/update-checker.js +167 -0
@@ -0,0 +1,425 @@
1
+ // @vibecodingmachine/core - Feature Implementer
2
+ // Handles autonomous mode feature implementation and development workflow
3
+
4
+ import { QuotaDetector } from '../ide-integration/quota-detector.js';
5
+ import { ChatManager } from '../chat-management/chat-manager.js';
6
+
7
+ /**
8
+ * Feature Implementer for autonomous development
9
+ * Manages autonomous mode workflow, quota checking, and feature implementation
10
+ */
11
+ export class FeatureImplementer {
12
+ constructor(options = {}) {
13
+ this.logger = options.logger || console;
14
+ this.electronAPI = options.electronAPI || null;
15
+ this.onStatusUpdate = options.onStatusUpdate || (() => {});
16
+ this.onProgressUpdate = options.onProgressUpdate || (() => {});
17
+ this.onMessageUpdate = options.onMessageUpdate || (() => {});
18
+ this.onErrorUpdate = options.onErrorUpdate || (() => {});
19
+ this.onCompleteUpdate = options.onCompleteUpdate || (() => {});
20
+
21
+ // Managers
22
+ this.quotaDetector = new QuotaDetector();
23
+ this.chatManager = new ChatManager({
24
+ logger: this.logger,
25
+ electronAPI: this.electronAPI,
26
+ onMessageUpdate: this.onMessageUpdate,
27
+ onStatusUpdate: this.onStatusUpdate,
28
+ onProgressUpdate: this.onProgressUpdate
29
+ });
30
+
31
+ // State
32
+ this.isAutonomousMode = false;
33
+ this.isPaused = false;
34
+ this.isStopped = false;
35
+ this.currentProgress = 0;
36
+ this.taskCount = 0;
37
+ this.maxTasks = 10;
38
+ this.completedFeatures = [];
39
+ this.errorLog = [];
40
+ }
41
+
42
+ /**
43
+ * Start autonomous mode with recovery capabilities
44
+ * @param {string} ide - The IDE to use for autonomous mode
45
+ * @param {string} tabId - The tab ID for tracking
46
+ * @returns {Promise<Object>} Result of autonomous mode execution
47
+ */
48
+ async startAutonomousMode(ide, tabId) {
49
+ this.logger.log('🤖 ===== AUTONOMOUS MODE START =====');
50
+ this.logger.log('🤖 startAutonomousMode called for:', ide);
51
+
52
+ this.isAutonomousMode = true;
53
+ this.isStopped = false;
54
+ this.currentProgress = 0;
55
+ this.taskCount = 0;
56
+ this.completedFeatures = [];
57
+ this.errorLog = [];
58
+
59
+ this.onStatusUpdate(tabId, '🤖 Starting enhanced autonomous mode with backend integration...');
60
+
61
+ try {
62
+ // Check if this is a Windsurf tab for enhanced functionality
63
+ const isWindsurfTab = ide === 'windsurf';
64
+ this.logger.log('🤖 Is Windsurf tab:', isWindsurfTab);
65
+
66
+ if (isWindsurfTab) {
67
+ this.onStatusUpdate(tabId, '🚀 Starting Windsurf-specific autonomous development...');
68
+ this.logger.log('🤖 Windsurf tab detected - using enhanced autonomous mode');
69
+ } else {
70
+ this.onStatusUpdate(tabId, '🤖 Starting standard autonomous mode...');
71
+ this.logger.log('🤖 Standard IDE tab detected - using standard autonomous mode');
72
+ }
73
+
74
+ // Enhanced autonomous mode for Windsurf
75
+ if (isWindsurfTab) {
76
+ this.logger.log('🤖 Using enhanced Windsurf autonomous mode...');
77
+ this.onStatusUpdate(tabId, '🤖 Starting enhanced Windsurf autonomous mode...');
78
+
79
+ // Check for quota warning in Windsurf first
80
+ this.logger.log('🤖 Checking Windsurf quota before starting autonomous mode...');
81
+ this.onStatusUpdate(tabId, '🤖 Checking Windsurf quota...');
82
+
83
+ const quotaCheck = await this.checkQuotaAndSwitch('windsurf');
84
+
85
+ if (quotaCheck.switched) {
86
+ this.logger.log('🤖 ✅ Switched from Windsurf to another IDE due to quota warning');
87
+ this.onStatusUpdate(tabId, `🤖 Switched to ${quotaCheck.newIde} due to Windsurf quota warning`);
88
+
89
+ // Continue with autonomous mode using the new IDE
90
+ this.logger.log('🤖 Continuing autonomous mode with new IDE...');
91
+ this.onStatusUpdate(tabId, `🤖 Continuing autonomous mode with ${quotaCheck.newIde}...`);
92
+
93
+ // Reset states for the new IDE
94
+ this.isStopped = false;
95
+ this.currentProgress = 0;
96
+
97
+ // Use the new IDE for autonomous mode
98
+ const newIde = quotaCheck.newIde;
99
+ this.logger.log(`🤖 Using ${newIde} for autonomous mode instead of Windsurf`);
100
+
101
+ return await this.runAutonomousLoop(newIde, tabId);
102
+ } else if (quotaCheck.error) {
103
+ this.logger.log('🤖 ⚠️ Quota check failed:', quotaCheck.error);
104
+ // Continue with Windsurf even if quota check failed
105
+ } else {
106
+ this.logger.log('🤖 ✅ No quota warning in Windsurf, proceeding with Windsurf autonomous mode');
107
+ this.onStatusUpdate(tabId, '🤖 Windsurf quota OK, starting autonomous mode...');
108
+ }
109
+ }
110
+
111
+ // Run autonomous loop with the specified IDE
112
+ return await this.runAutonomousLoop(ide, tabId);
113
+
114
+ } catch (error) {
115
+ this.logger.error('❌ Error starting autonomous mode:', error);
116
+ this.onErrorUpdate(tabId, `Error starting autonomous mode: ${error.message}`);
117
+ this.stopAutonomousMode();
118
+
119
+ return {
120
+ success: false,
121
+ error: error.message
122
+ };
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Run the autonomous development loop
128
+ * @param {string} ide - The IDE to use
129
+ * @param {string} tabId - The tab ID for tracking
130
+ * @returns {Promise<Object>} Result of autonomous loop execution
131
+ */
132
+ async runAutonomousLoop(ide, tabId) {
133
+ this.logger.log(`🤖 Starting ${ide} autonomous loop...`);
134
+
135
+ // Send initial command to start autonomous development
136
+ const initialCommand = 'Follow the instructions in the INSTRUCTIONS.md file in the root of the repo. Please implement the features and report progress percentage after each task.';
137
+
138
+ let currentProgress = 0;
139
+ let taskCount = 0;
140
+
141
+ this.logger.log('🤖 Initial conditions:', { currentProgress, taskCount, maxTasks: this.maxTasks, isStopped: this.isStopped, isAutonomousMode: this.isAutonomousMode });
142
+
143
+ // Main autonomous loop
144
+ while (currentProgress < 100 && taskCount < this.maxTasks && !this.isStopped && this.isAutonomousMode) {
145
+ // Check if paused
146
+ while (this.isPaused && this.isAutonomousMode && !this.isStopped) {
147
+ this.logger.log('⏸️ Autonomous mode paused, waiting...');
148
+ await new Promise(resolve => setTimeout(resolve, 1000));
149
+ }
150
+
151
+ // Check if stopped
152
+ if (this.isStopped || !this.isAutonomousMode) {
153
+ this.logger.log('🛑 Autonomous mode stopped, exiting...');
154
+ break;
155
+ }
156
+
157
+ taskCount++;
158
+ this.taskCount = taskCount;
159
+ this.onStatusUpdate(tabId, `🤖 Task ${taskCount}: Implementing features (${currentProgress}% complete)...`);
160
+
161
+ // Send command and wait for response
162
+ const commandResult = await this.sendAutonomousCommand(initialCommand, ide, tabId);
163
+
164
+ if (commandResult.success) {
165
+ if (commandResult.progress !== undefined) {
166
+ currentProgress = commandResult.progress;
167
+ this.currentProgress = currentProgress;
168
+ this.onProgressUpdate(currentProgress);
169
+ }
170
+
171
+ if (commandResult.completed) {
172
+ this.onStatusUpdate(tabId, '🎉 All features implemented! Autonomous development complete!');
173
+ this.onCompleteUpdate(tabId, true);
174
+ this.stopAutonomousMode();
175
+
176
+ return {
177
+ success: true,
178
+ progress: 100,
179
+ completed: true,
180
+ taskCount: taskCount
181
+ };
182
+ }
183
+
184
+ // Wait before next task
185
+ await new Promise(resolve => setTimeout(resolve, 2000));
186
+ } else {
187
+ this.logger.log('❌ Command failed:', commandResult.error);
188
+ this.onErrorUpdate(tabId, `Task ${taskCount} failed: ${commandResult.error}`);
189
+
190
+ // Add to error log
191
+ this.errorLog.push({
192
+ task: taskCount,
193
+ error: commandResult.error,
194
+ timestamp: Date.now()
195
+ });
196
+
197
+ // Continue with next task
198
+ await new Promise(resolve => setTimeout(resolve, 3000));
199
+ }
200
+ }
201
+
202
+ // Check why we exited the loop
203
+ if (taskCount >= this.maxTasks) {
204
+ this.onStatusUpdate(tabId, '⚠️ Maximum tasks reached, autonomous mode stopping...');
205
+ } else if (this.isStopped) {
206
+ this.onStatusUpdate(tabId, '🛑 Autonomous mode stopped by user');
207
+ } else if (currentProgress >= 100) {
208
+ this.onStatusUpdate(tabId, '🎉 100% completion reached!');
209
+ this.onCompleteUpdate(tabId, true);
210
+ }
211
+
212
+ this.stopAutonomousMode();
213
+
214
+ return {
215
+ success: true,
216
+ progress: currentProgress,
217
+ completed: currentProgress >= 100,
218
+ taskCount: taskCount,
219
+ errorLog: this.errorLog
220
+ };
221
+ }
222
+
223
+ /**
224
+ * Send an autonomous command to an IDE
225
+ * @param {string} command - The command to send
226
+ * @param {string} ide - The IDE to send to
227
+ * @param {string} tabId - The tab ID for tracking
228
+ * @returns {Promise<Object>} Result of the command execution
229
+ */
230
+ async sendAutonomousCommand(command, ide, tabId) {
231
+ this.logger.log(`🤖 Sending autonomous command: ${command.substring(0, 100)}...`);
232
+
233
+ try {
234
+ // Check for quota warnings before sending command
235
+ const quotaCheck = await this.checkQuotaAndSwitch(ide);
236
+
237
+ if (quotaCheck.switched) {
238
+ this.logger.log('🤖 Switched from', ide, 'to', quotaCheck.newIde);
239
+ this.onStatusUpdate(tabId, `🤖 Switched to ${quotaCheck.newIde} due to quota warning`);
240
+
241
+ // Send the command to the new IDE instead
242
+ return await this.sendAutonomousCommand(command, quotaCheck.newIde, tabId);
243
+ } else if (quotaCheck.error) {
244
+ this.logger.log('🤖 ⚠️ Quota check failed:', quotaCheck.error);
245
+ // Continue with sending command even if quota check failed
246
+ } else {
247
+ this.logger.log('🤖 ✅ No quota warnings detected, proceeding with command');
248
+ }
249
+
250
+ // Add auto-sent message to chat display
251
+ this.onMessageUpdate(tabId, {
252
+ role: 'auto',
253
+ text: command,
254
+ timestamp: Date.now()
255
+ });
256
+
257
+ // Send the command using chat manager
258
+ const sendResult = await this.chatManager.sendMessage(command, ide, tabId);
259
+
260
+ if (sendResult && sendResult.success) {
261
+ this.logger.log('✅ Command sent successfully');
262
+
263
+ // Wait for response completion
264
+ const responseResult = await this.chatManager.detectResponseCompletion(ide, '');
265
+
266
+ if (responseResult.completed) {
267
+ this.logger.log('✅ Response completed successfully');
268
+
269
+ // If we're at 100%, don't send another command
270
+ if (responseResult.progress === 100) {
271
+ this.logger.log('🎉 100% completion reached - stopping autonomous mode');
272
+ return { success: true, progress: 100, completed: true };
273
+ }
274
+
275
+ return { success: true, progress: responseResult.progress || 0 };
276
+ } else {
277
+ this.logger.log('⚠️ Response detection failed or incomplete');
278
+ return { success: false, reason: 'response_incomplete' };
279
+ }
280
+ } else {
281
+ this.logger.log('❌ Failed to send command:', sendResult?.error);
282
+ return { success: false, error: sendResult?.error };
283
+ }
284
+ } catch (error) {
285
+ this.logger.log('❌ Error in autonomous command:', error.message);
286
+ return { success: false, error: error.message };
287
+ }
288
+ }
289
+
290
+ /**
291
+ * Check quota and switch to available IDE if needed
292
+ * @param {string} ide - The IDE to check
293
+ * @returns {Promise<Object>} Quota check result
294
+ */
295
+ async checkQuotaAndSwitch(ide) {
296
+ try {
297
+ this.logger.log(`🔍 Checking quota for ${ide}...`);
298
+
299
+ const quotaResult = await this.quotaDetector.detectQuotaWarning(ide);
300
+
301
+ if (quotaResult.hasQuotaWarning) {
302
+ this.logger.log(`❌ Quota warning detected in ${ide}:`, quotaResult.note);
303
+
304
+ // Get available IDEs without quota warnings
305
+ const availableIdes = await this.quotaDetector.getAvailableIdes(['vscode', 'cursor', 'windsurf']);
306
+
307
+ // Remove the current IDE from available options
308
+ const otherIdes = availableIdes.filter(availableIde => availableIde !== ide);
309
+
310
+ if (otherIdes.length > 0) {
311
+ const newIde = otherIdes[0]; // Use the first available IDE
312
+ this.logger.log(`🔄 Switching from ${ide} to ${newIde} due to quota warning`);
313
+
314
+ return {
315
+ switched: true,
316
+ newIde: newIde,
317
+ reason: 'quota_warning',
318
+ originalIde: ide
319
+ };
320
+ } else {
321
+ this.logger.log('❌ No available IDEs found, cannot switch');
322
+ return {
323
+ switched: false,
324
+ error: 'No available IDEs without quota warnings'
325
+ };
326
+ }
327
+ } else {
328
+ this.logger.log(`✅ No quota warnings detected in ${ide}`);
329
+ return {
330
+ switched: false,
331
+ ide: ide
332
+ };
333
+ }
334
+ } catch (error) {
335
+ this.logger.log(`❌ Error checking quota for ${ide}:`, error.message);
336
+ return {
337
+ switched: false,
338
+ error: error.message
339
+ };
340
+ }
341
+ }
342
+
343
+ /**
344
+ * Stop autonomous mode
345
+ */
346
+ stopAutonomousMode() {
347
+ this.isAutonomousMode = false;
348
+ this.isStopped = true;
349
+ this.chatManager.stop();
350
+ this.logger.log('🛑 Autonomous mode stopped');
351
+ }
352
+
353
+ /**
354
+ * Pause autonomous mode
355
+ */
356
+ pauseAutonomousMode() {
357
+ this.isPaused = true;
358
+ this.chatManager.pause();
359
+ this.logger.log('⏸️ Autonomous mode paused');
360
+ }
361
+
362
+ /**
363
+ * Resume autonomous mode
364
+ */
365
+ resumeAutonomousMode() {
366
+ this.isPaused = false;
367
+ this.chatManager.resume();
368
+ this.logger.log('▶️ Autonomous mode resumed');
369
+ }
370
+
371
+ /**
372
+ * Get current autonomous mode state
373
+ * @returns {Object} Current state
374
+ */
375
+ getState() {
376
+ return {
377
+ isAutonomousMode: this.isAutonomousMode,
378
+ isPaused: this.isPaused,
379
+ isStopped: this.isStopped,
380
+ currentProgress: this.currentProgress,
381
+ taskCount: this.taskCount,
382
+ maxTasks: this.maxTasks,
383
+ completedFeatures: this.completedFeatures,
384
+ errorLog: this.errorLog
385
+ };
386
+ }
387
+
388
+ /**
389
+ * Set electron API for Electron environment
390
+ * @param {Object} electronAPI - The electron API object
391
+ */
392
+ setElectronAPI(electronAPI) {
393
+ this.electronAPI = electronAPI;
394
+ this.chatManager.setElectronAPI(electronAPI);
395
+ }
396
+
397
+ /**
398
+ * Set callback functions
399
+ * @param {Object} callbacks - Object containing callback functions
400
+ */
401
+ setCallbacks(callbacks) {
402
+ if (callbacks.onStatusUpdate) {
403
+ this.onStatusUpdate = callbacks.onStatusUpdate;
404
+ }
405
+ if (callbacks.onProgressUpdate) {
406
+ this.onProgressUpdate = callbacks.onProgressUpdate;
407
+ }
408
+ if (callbacks.onMessageUpdate) {
409
+ this.onMessageUpdate = callbacks.onMessageUpdate;
410
+ }
411
+ if (callbacks.onErrorUpdate) {
412
+ this.onErrorUpdate = callbacks.onErrorUpdate;
413
+ }
414
+ if (callbacks.onCompleteUpdate) {
415
+ this.onCompleteUpdate = callbacks.onCompleteUpdate;
416
+ }
417
+
418
+ // Update chat manager callbacks
419
+ this.chatManager.setCallbacks({
420
+ onMessageUpdate: this.onMessageUpdate,
421
+ onStatusUpdate: this.onStatusUpdate,
422
+ onProgressUpdate: this.onProgressUpdate
423
+ });
424
+ }
425
+ }
@@ -0,0 +1,71 @@
1
+ // @vibecodingmachine/core - Chat Manager (CommonJS) - Stub
2
+ // Handles chat message management, polling, and response detection
3
+
4
+ class ChatManager {
5
+ constructor(options = {}) {
6
+ this.logger = options.logger || console;
7
+ this.electronAPI = options.electronAPI || null;
8
+ this.onMessageUpdate = options.onMessageUpdate || (() => {});
9
+ this.onStatusUpdate = options.onStatusUpdate || (() => {});
10
+ this.onProgressUpdate = options.onProgressUpdate || (() => {});
11
+ }
12
+
13
+ async sendMessage(message, ide, tabId) {
14
+ this.logger.log('sendMessage stub called with:', { message: message.substring(0, 50) + '...', ide, tabId });
15
+ return {
16
+ success: true,
17
+ method: 'stub',
18
+ message: 'Message sent via stub'
19
+ };
20
+ }
21
+
22
+ startPolling(ide, tabId) {
23
+ this.logger.log('startPolling stub for:', ide, tabId);
24
+ }
25
+
26
+ stopPolling() {
27
+ this.logger.log('stopPolling stub');
28
+ }
29
+
30
+ pause() {
31
+ this.logger.log('pause stub');
32
+ }
33
+
34
+ resume() {
35
+ this.logger.log('resume stub');
36
+ }
37
+
38
+ stop() {
39
+ this.logger.log('stop stub');
40
+ }
41
+
42
+ reset() {
43
+ this.logger.log('reset stub');
44
+ }
45
+
46
+ getState() {
47
+ return {
48
+ isPolling: false,
49
+ isPaused: false,
50
+ isStopped: false
51
+ };
52
+ }
53
+
54
+ setElectronAPI(electronAPI) {
55
+ this.electronAPI = electronAPI;
56
+ }
57
+
58
+ setCallbacks(callbacks) {
59
+ if (callbacks.onMessageUpdate) {
60
+ this.onMessageUpdate = callbacks.onMessageUpdate;
61
+ }
62
+ if (callbacks.onStatusUpdate) {
63
+ this.onStatusUpdate = callbacks.onStatusUpdate;
64
+ }
65
+ if (callbacks.onProgressUpdate) {
66
+ this.onProgressUpdate = callbacks.onProgressUpdate;
67
+ }
68
+ }
69
+ }
70
+
71
+ module.exports = { ChatManager };