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
File without changes
File without changes
@@ -0,0 +1,306 @@
1
+ /**
2
+ * Shared AppleScript utilities for IDE integration
3
+ * Consolidates common AppleScript patterns to follow DRY principles
4
+ */
5
+
6
+ class AppleScriptUtils {
7
+ constructor() {
8
+ this.logger = console;
9
+ }
10
+
11
+ /**
12
+ * Generate AppleScript for focusing AI panel with multiple fallback strategies
13
+ * @param {string} text - The text to send to the AI panel
14
+ * @param {string} ide - The IDE name (e.g., 'cursor')
15
+ * @returns {string} Complete AppleScript code
16
+ */
17
+ generateAIPanelFocusScript(text, ide = 'cursor') {
18
+ const escapedText = text.replace(/"/g, '\\"');
19
+
20
+ return `
21
+ tell application "System Events"
22
+ tell process "${ide}"
23
+ -- Check if the process is running before attempting to interact
24
+ try
25
+ set frontmost to true
26
+ delay 1
27
+
28
+ -- PRE-CHECK: Ensure we're not in an editor
29
+ try
30
+ -- Press Escape to ensure we're not in any input mode
31
+ key code 53 -- Escape
32
+ delay 0.5
33
+ on error
34
+ -- Continue if escape fails
35
+ end try
36
+
37
+ ${this.generateFocusStrategies(escapedText)}
38
+ on error
39
+ -- Process not running or not accessible
40
+ error "Process '${ide}' is not running or not accessible. VibeCodingMachine does not open IDEs - please open ${ide} manually first."
41
+ end try
42
+ end tell
43
+ end tell`;
44
+ }
45
+
46
+ /**
47
+ * Generate multiple focus strategies with fallbacks
48
+ * @param {string} escapedText - The escaped text to send
49
+ * @returns {string} AppleScript focus strategies
50
+ */
51
+ generateFocusStrategies(escapedText) {
52
+ return `
53
+ -- STRATEGY 1: Direct AI Panel Focus via Keyboard Shortcut (Cmd+L) - Primary
54
+ try
55
+ -- Use Cmd+L to focus AI panel (faster and more reliable)
56
+ key code 37 using {command down} -- Cmd+L
57
+ delay 1.5
58
+
59
+ -- Open new chat session with Cmd+T to prevent crashes
60
+ key code 17 using {command down} -- Cmd+T
61
+ delay 2.5
62
+
63
+ -- Skip clearing text to avoid selecting file content
64
+ -- The chat input should be empty when opening new chat session
65
+
66
+ -- Wait additional time for chat input field to be fully ready
67
+ delay 1.0
68
+
69
+ -- Type the message
70
+ keystroke "${escapedText}"
71
+ delay 1.5
72
+
73
+ -- Send with Cmd+Enter (standard for chat interfaces)
74
+ key code 36 using {command down}
75
+ delay 0.5
76
+
77
+ -- Fallback: Press Enter to ensure submission
78
+ key code 36
79
+ delay 0.5
80
+
81
+ -- Additional fallback: Press Enter again to be absolutely sure
82
+ key code 36
83
+ delay 1.0
84
+
85
+ return "Message sent via AppleScript to AI Panel using Cmd+L shortcut with new chat session (Cmd+T)"
86
+ on error
87
+ -- STRATEGY 2: Command Palette Approach (Fallback 1) - NO AI PANEL TOGGLE
88
+ try
89
+ -- Step 1: Open Command Palette (Cmd+Shift+P)
90
+ key code 35 using {command down, shift down} -- Cmd+Shift+P
91
+ delay 0.8
92
+
93
+ -- Step 2: Type "View: Focus into Secondary Side Bar" to focus AI panel
94
+ keystroke "View: Focus into Secondary Side Bar"
95
+ delay 0.8
96
+
97
+ -- Step 3: Press Enter to focus AI Panel
98
+ key code 36 -- Enter
99
+ delay 2.0
100
+
101
+ -- Step 4: Open new chat session with Cmd+T to prevent crashes
102
+ key code 17 using {command down} -- Cmd+T
103
+ delay 2.5
104
+
105
+ -- Step 5: Skip clearing text to avoid selecting file content
106
+ -- The chat input should be empty when opening new chat session
107
+
108
+ -- Step 6: Wait additional time for chat input field to be fully ready
109
+ delay 1.0
110
+
111
+ -- Step 7: Type the message
112
+ keystroke "${escapedText}"
113
+ delay 1.5
114
+
115
+ -- Step 8: Send with Cmd+Enter (standard for chat interfaces)
116
+ key code 36 using {command down}
117
+ delay 0.5
118
+
119
+ -- Fallback: Press Enter to ensure submission
120
+ key code 36
121
+ delay 0.5
122
+
123
+ -- Additional fallback: Press Enter again to be absolutely sure
124
+ key code 36
125
+ delay 1.0
126
+
127
+ return "Message sent via AppleScript to AI Panel using command palette fallback with new chat session (Cmd+T)"
128
+ on error
129
+ -- STRATEGY 3: Direct Element Targeting (Last Resort)
130
+ try
131
+ -- Look for AI panel elements and click them
132
+ set aiPanelFound to false
133
+
134
+ -- Try to find text fields that might be chat inputs
135
+ set allTextFields to text field of window 1
136
+ repeat with textField in allTextFields
137
+ try
138
+ -- Click on the text field (likely chat input)
139
+ click textField
140
+ delay 0.5
141
+
142
+ -- Open new chat session with Cmd+T to prevent crashes
143
+ key code 17 using {command down} -- Cmd+T
144
+ delay 2.5
145
+
146
+ -- Skip clearing text to avoid selecting file content
147
+ -- The chat input should be empty when opening new chat session
148
+
149
+ -- Wait additional time for chat input field to be fully ready
150
+ delay 1.0
151
+
152
+ -- Type the message
153
+ keystroke "${escapedText}"
154
+ delay 1.5
155
+
156
+ -- Send with Cmd+Enter
157
+ key code 36 using {command down}
158
+ delay 0.5
159
+
160
+ -- Fallback: Press Enter to ensure submission
161
+ key code 36
162
+ delay 0.5
163
+
164
+ -- Additional fallback: Press Enter again to be absolutely sure
165
+ key code 36
166
+ delay 1.0
167
+
168
+ set aiPanelFound to true
169
+ exit repeat
170
+ on error
171
+ -- Continue to next text field
172
+ end try
173
+ end repeat
174
+
175
+ if aiPanelFound then
176
+ return "Message sent via AppleScript to AI Panel using direct element targeting"
177
+ end if
178
+ on error
179
+ -- STRATEGY 4: Emergency fallback - ensure we're not in editor
180
+ try
181
+ -- First escape any terminal focus
182
+ key code 53 -- Escape key
183
+ delay 1
184
+
185
+ -- Click in editor area to escape terminal
186
+ do shell script "/usr/local/bin/cliclick c:400,300"
187
+ delay 1
188
+
189
+ -- Try Tab navigation to find chat input
190
+ repeat 3 times
191
+ key code 48 -- Tab key
192
+ delay 0.5
193
+ end repeat
194
+
195
+ -- Open new chat session with Cmd+T to prevent crashes
196
+ key code 17 using {command down} -- Cmd+T
197
+ delay 2.5
198
+
199
+ -- Wait additional time for chat input field to be fully ready
200
+ delay 1.0
201
+
202
+ -- Type the message
203
+ keystroke "${escapedText}"
204
+ delay 1.5
205
+
206
+ -- Send with Cmd+Enter
207
+ key code 36 using {command down}
208
+ delay 0.5
209
+
210
+ -- Fallback: Press Enter to ensure submission
211
+ key code 36
212
+ delay 0.5
213
+
214
+ -- Additional fallback: Press Enter again to be absolutely sure
215
+ key code 36
216
+ delay 1.0
217
+
218
+ return "Message sent via AppleScript to AI Panel using emergency fallback with new chat session (Cmd+T)"
219
+ on error
220
+ return "ERROR: All AI panel focus strategies failed"
221
+ end try
222
+ end try
223
+ end try
224
+ end try`;
225
+ }
226
+
227
+ /**
228
+ * Generate Windows PowerShell script for AI panel focus
229
+ * @param {string} text - The text to send to the AI panel
230
+ * @returns {string} Complete PowerShell script
231
+ */
232
+ generateWindowsAIPanelScript(text) {
233
+ const escapedText = text.replace(/"/g, '""');
234
+
235
+ return `
236
+ # Windows AI Panel Focus Script - Consolidated
237
+ Add-Type -AssemblyName System.Windows.Forms
238
+ Add-Type -AssemblyName System.Drawing
239
+
240
+ # Function to find Cursor window
241
+ function Find-CursorWindow {
242
+ $processes = Get-Process | Where-Object { $_.ProcessName -like "*cursor*" -or $_.MainWindowTitle -like "*cursor*" }
243
+ foreach ($proc in $processes) {
244
+ if ($proc.MainWindowHandle -ne [IntPtr]::Zero) {
245
+ return $proc
246
+ }
247
+ }
248
+ return $null
249
+ }
250
+
251
+ # Function to focus AI Panel and send text
252
+ function Send-ToAIPanel {
253
+ param($windowHandle, $text)
254
+
255
+ # Focus the Cursor window
256
+ [Microsoft.VisualBasic.Interaction]::AppActivate($windowHandle)
257
+ Start-Sleep -Milliseconds 500
258
+
259
+ # Step 1: Try Cmd+L equivalent (Ctrl+L on Windows) to focus AI panel
260
+ [System.Windows.Forms.SendKeys]::SendWait("^l")
261
+ Start-Sleep -Milliseconds 1500
262
+
263
+ # Step 2: Open new chat session with Ctrl+T to prevent crashes
264
+ [System.Windows.Forms.SendKeys]::SendWait("^t")
265
+ Start-Sleep -Milliseconds 1000
266
+
267
+ # Step 3: Clear any existing text in the chat input (Ctrl+A, Delete)
268
+ [System.Windows.Forms.SendKeys]::SendWait("^a")
269
+ Start-Sleep -Milliseconds 200
270
+ [System.Windows.Forms.SendKeys]::SendWait("{DELETE}")
271
+ Start-Sleep -Milliseconds 200
272
+
273
+ # Step 4: Type the message
274
+ [System.Windows.Forms.SendKeys]::SendWait("$text")
275
+ Start-Sleep -Milliseconds 500
276
+
277
+ # Step 5: Send with Ctrl+Enter (standard for chat interfaces)
278
+ [System.Windows.Forms.SendKeys]::SendWait("^{ENTER}")
279
+ Start-Sleep -Milliseconds 1000
280
+ }
281
+
282
+ try {
283
+ # Find Cursor window
284
+ $cursorProcess = Find-CursorWindow
285
+ if ($cursorProcess -eq $null) {
286
+ Write-Output "ERROR: Cursor window not found"
287
+ exit 1
288
+ }
289
+
290
+ Write-Output "Found Cursor process: $($cursorProcess.ProcessName) (PID: $($cursorProcess.Id))"
291
+
292
+ # Send the text to AI Panel
293
+ Send-ToAIPanel -windowHandle $cursorProcess.MainWindowHandle -text "${escapedText}"
294
+
295
+ Write-Output "SUCCESS: Message sent to Cursor AI Panel using Ctrl+L shortcut with new chat session (Ctrl+T)"
296
+ exit 0
297
+
298
+ } catch {
299
+ Write-Output "ERROR: $($_.Exception.Message)"
300
+ exit 1
301
+ }`;
302
+ }
303
+ }
304
+
305
+ module.exports = AppleScriptUtils;
306
+
@@ -0,0 +1,221 @@
1
+ // @vibecodingmachine/core - CDP Manager (CommonJS)
2
+ // Handles Chrome DevTools Protocol interactions with IDEs
3
+
4
+ const CDP = require('chrome-remote-interface');
5
+
6
+ /**
7
+ * CDP Manager for IDE interactions
8
+ * Handles Chrome DevTools Protocol-based text sending for IDEs like VS Code and Cursor
9
+ */
10
+ class CDPManager {
11
+ constructor() {
12
+ this.logger = console;
13
+ }
14
+
15
+ /**
16
+ * Timeout utility function
17
+ * @param {number} ms - Timeout in milliseconds
18
+ * @param {Promise} promise - Promise to timeout
19
+ * @returns {Promise} Promise with timeout
20
+ */
21
+ timeout(ms, promise) {
22
+ return Promise.race([
23
+ promise,
24
+ new Promise((_, reject) =>
25
+ setTimeout(() => reject(new Error(`Operation timed out after ${ms}ms`)), ms)
26
+ )
27
+ ]);
28
+ }
29
+
30
+ /**
31
+ * Send text to an IDE via CDP
32
+ * @param {string} text - The text to send
33
+ * @param {string} ide - The IDE name ('vscode', 'cursor')
34
+ * @returns {Promise<Object>} Result object with success status and details
35
+ */
36
+ async sendText(text, ide) {
37
+ if (typeof text !== 'string') {
38
+ return {
39
+ success: false,
40
+ error: `Invalid text type: ${typeof text}. Expected string.`,
41
+ debug: { textType: typeof text, textValue: text }
42
+ };
43
+ }
44
+
45
+ const ideName = ide === 'cursor' ? 'Cursor' : ide === 'vscode' ? 'VS Code' : 'Unknown IDE';
46
+ const port = ide === 'cursor' ? 9225 : 9222;
47
+
48
+ this.logger.log(`🔍 sendText: Starting debug session`);
49
+ this.logger.log(`📋 IDE: ${ideName} (${ide})`);
50
+ this.logger.log(`🔌 Port: ${port}`);
51
+ this.logger.log(`💬 Text: "${text.substring(0, 100)}${text.length > 100 ? '...' : ''}"`);
52
+
53
+ try {
54
+ // For VS Code, use the working approach from commit 6235f46b
55
+ if (ide === 'vscode') {
56
+ return await this.sendTextToVSCode(text);
57
+ }
58
+
59
+ // For other IDEs, use basic CDP approach
60
+ return await this.sendTextBasic(text, ide);
61
+ } catch (error) {
62
+ this.logger.error('CDP error:', error);
63
+ return {
64
+ success: false,
65
+ error: `CDP error: ${error.message}`,
66
+ debug: { ide, port, textLength: text.length }
67
+ };
68
+ }
69
+ }
70
+
71
+ /**
72
+ * Send text to VS Code using the working approach
73
+ * @param {string} text - The text to send
74
+ * @returns {Promise<Object>} Result object
75
+ */
76
+ async sendTextToVSCode(text) {
77
+ try {
78
+ const targets = await CDP.List({ port: 9222 });
79
+ if (!targets || targets.length === 0) {
80
+ return { success: false, error: 'Could not find VS Code. Make sure VS Code is running with --remote-debugging-port=9222' };
81
+ }
82
+
83
+ const workbench = targets.find(t => t.url && t.url.includes('workbench')) || targets[0];
84
+ if (!workbench) return { success: false, error: 'No VS Code workbench target found.' };
85
+
86
+ this.logger.log(`Found ${targets.length} targets, using workbench: ${workbench.title}`);
87
+ const client = await CDP({ port: 9222, target: workbench });
88
+ const { Runtime, Input, Page, DOM } = client;
89
+ await Runtime.enable();
90
+ await DOM.enable();
91
+ if (Page && Page.bringToFront) { try { await Page.bringToFront(); } catch (_) {} }
92
+
93
+ // Use clipboard approach to avoid focus issues
94
+ const clipboardText = String(text).slice(0, 4000);
95
+ this.logger.log('Copying text to clipboard:', clipboardText);
96
+
97
+ // Try to paste the text after a short delay
98
+ setTimeout(async () => {
99
+ try {
100
+ const isDarwin = process.platform === 'darwin';
101
+ const pasteMods = isDarwin ? 4 /* Meta */ : 2 /* Ctrl */;
102
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: 'v', text: 'v', modifiers: pasteMods });
103
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: 'v', text: 'v', modifiers: pasteMods });
104
+ this.logger.log('Pasted text via Cmd+V');
105
+ } catch (e) {
106
+ this.logger.log('Paste failed:', e.message);
107
+ }
108
+ }, 200);
109
+
110
+ // Also try typing the text character by character
111
+ setTimeout(async () => {
112
+ try {
113
+ this.logger.log('Starting character-by-character typing...');
114
+ for (let i = 0; i < clipboardText.length; i++) {
115
+ const char = clipboardText[i];
116
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: char, text: char });
117
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: char, text: char });
118
+ await new Promise(resolve => setTimeout(resolve, 20));
119
+ }
120
+ this.logger.log('Finished character-by-character typing');
121
+
122
+ // Try multiple submission methods
123
+ setTimeout(async () => {
124
+ try {
125
+ this.logger.log('Attempting to submit message...');
126
+
127
+ // Method 1: Press Enter
128
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Enter' });
129
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Enter' });
130
+ await new Promise(resolve => setTimeout(resolve, 100));
131
+
132
+ // Method 2: Try Cmd+Enter
133
+ const isDarwin = process.platform === 'darwin';
134
+ const enterMods = isDarwin ? 4 /* Meta */ : 2 /* Ctrl */;
135
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Enter', text: 'Enter', modifiers: enterMods });
136
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Enter', text: 'Enter', modifiers: enterMods });
137
+
138
+ } catch (e) {
139
+ this.logger.log('Submission failed:', e.message);
140
+ }
141
+ }, 300);
142
+
143
+ } catch (e) {
144
+ this.logger.log('Character typing failed:', e.message);
145
+ }
146
+ }, 500);
147
+
148
+ this.logger.log(`Successfully sent message to VS Code via CDP`);
149
+ return {
150
+ success: true,
151
+ method: 'cdp-clipboard',
152
+ message: `Message sent to VS Code: ${text}`,
153
+ note: 'Message sent via CDP with clipboard approach'
154
+ };
155
+
156
+ } catch (error) {
157
+ this.logger.error('VS Code CDP error:', error);
158
+ return { success: false, error: `VS Code CDP error: ${error.message}` };
159
+ }
160
+ }
161
+
162
+ /**
163
+ * Send text using basic CDP approach
164
+ * @param {string} text - The text to send
165
+ * @param {string} ide - The IDE name
166
+ * @returns {Promise<Object>} Result object
167
+ */
168
+ async sendTextBasic(text, ide) {
169
+ const textToSend = String(text).slice(0, 4000);
170
+ const port = ide === 'cursor' ? 9225 : 9222;
171
+
172
+ try {
173
+ const targets = await this.timeout(5000, CDP.List({ port }));
174
+ if (!targets || targets.length === 0) {
175
+ return { success: false, error: `Could not find ${ide}. Make sure ${ide} is running with --remote-debugging-port=${port}` };
176
+ }
177
+
178
+ const workbench = targets.find(t => t.url && t.url.includes('workbench')) || targets[0];
179
+ if (!workbench) return { success: false, error: `No ${ide} workbench target found.` };
180
+
181
+ const client = await this.timeout(10000, CDP({ port, target: workbench }));
182
+ const { Runtime, Input, Page } = client;
183
+
184
+ await this.timeout(5000, Runtime.enable());
185
+ await this.timeout(5000, Page.enable());
186
+
187
+ if (Page && Page.bringToFront) {
188
+ try {
189
+ await this.timeout(3000, Page.bringToFront());
190
+ } catch (error) {
191
+ this.logger.log(`Bring to front failed: ${error.message}`);
192
+ }
193
+ }
194
+
195
+ // Type the text character by character
196
+ for (let i = 0; i < textToSend.length; i++) {
197
+ const char = textToSend[i];
198
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: char, text: char });
199
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: char, text: char });
200
+ await new Promise(resolve => setTimeout(resolve, 20));
201
+ }
202
+
203
+ // Press Enter to submit
204
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Enter' });
205
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Enter' });
206
+
207
+ return {
208
+ success: true,
209
+ method: 'cdp-basic',
210
+ message: `Message sent to ${ide}: ${text}`,
211
+ note: 'Message sent via basic CDP approach'
212
+ };
213
+
214
+ } catch (error) {
215
+ this.logger.error(`${ide} CDP error:`, error);
216
+ return { success: false, error: `${ide} CDP error: ${error.message}` };
217
+ }
218
+ }
219
+ }
220
+
221
+ module.exports = { CDPManager };