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.
- package/.babelrc +13 -0
- package/README.md +28 -0
- package/__tests__/applescript-manager-claude-fix.test.js +286 -0
- package/__tests__/requirement-2-auto-start-looping.test.js +69 -0
- package/__tests__/requirement-3-auto-start-looping.test.js +69 -0
- package/__tests__/requirement-4-auto-start-looping.test.js +69 -0
- package/__tests__/requirement-6-auto-start-looping.test.js +73 -0
- package/__tests__/requirement-7-status-tracking.test.js +332 -0
- package/jest.config.js +18 -0
- package/jest.setup.js +12 -0
- package/package.json +46 -0
- package/src/auth/access-denied.html +119 -0
- package/src/auth/shared-auth-storage.js +230 -0
- package/src/autonomous-mode/feature-implementer.cjs +70 -0
- package/src/autonomous-mode/feature-implementer.js +425 -0
- package/src/chat-management/chat-manager.cjs +71 -0
- package/src/chat-management/chat-manager.js +342 -0
- package/src/ide-integration/__tests__/applescript-manager-thread-closure.test.js +227 -0
- package/src/ide-integration/aider-cli-manager.cjs +850 -0
- package/src/ide-integration/applescript-diagnostics.js +0 -0
- package/src/ide-integration/applescript-manager.cjs +1088 -0
- package/src/ide-integration/applescript-manager.js +2803 -0
- package/src/ide-integration/applescript-open-apps.js +0 -0
- package/src/ide-integration/applescript-read-response.js +0 -0
- package/src/ide-integration/applescript-send-text.js +0 -0
- package/src/ide-integration/applescript-thread-closure.js +0 -0
- package/src/ide-integration/applescript-utils.js +306 -0
- package/src/ide-integration/cdp-manager.cjs +221 -0
- package/src/ide-integration/cdp-manager.js +321 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +301 -0
- package/src/ide-integration/cline-cli-manager.cjs +2252 -0
- package/src/ide-integration/continue-cli-manager.js +431 -0
- package/src/ide-integration/provider-manager.cjs +354 -0
- package/src/ide-integration/quota-detector.cjs +34 -0
- package/src/ide-integration/quota-detector.js +349 -0
- package/src/ide-integration/windows-automation-manager.js +262 -0
- package/src/index.cjs +43 -0
- package/src/index.js +17 -0
- package/src/llm/direct-llm-manager.cjs +609 -0
- package/src/ui/ButtonComponents.js +247 -0
- package/src/ui/ChatInterface.js +499 -0
- package/src/ui/StateManager.js +259 -0
- package/src/ui/StateManager.test.js +0 -0
- package/src/utils/audit-logger.cjs +116 -0
- package/src/utils/config-helpers.cjs +94 -0
- package/src/utils/config-helpers.js +94 -0
- package/src/utils/electron-update-checker.js +78 -0
- package/src/utils/gcloud-auth.cjs +394 -0
- package/src/utils/logger.cjs +193 -0
- package/src/utils/logger.js +191 -0
- package/src/utils/repo-helpers.cjs +120 -0
- package/src/utils/repo-helpers.js +120 -0
- package/src/utils/requirement-helpers.js +432 -0
- package/src/utils/update-checker.js +167 -0
|
File without changes
|
|
File without changes
|
|
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 };
|