vibecodingmachine-core 1.0.0 → 1.0.1

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 (48) hide show
  1. package/.babelrc +13 -13
  2. package/README.md +28 -28
  3. package/__tests__/applescript-manager-claude-fix.test.js +286 -286
  4. package/__tests__/requirement-2-auto-start-looping.test.js +69 -69
  5. package/__tests__/requirement-3-auto-start-looping.test.js +69 -69
  6. package/__tests__/requirement-4-auto-start-looping.test.js +69 -69
  7. package/__tests__/requirement-6-auto-start-looping.test.js +73 -73
  8. package/__tests__/requirement-7-status-tracking.test.js +332 -332
  9. package/jest.config.js +18 -18
  10. package/jest.setup.js +12 -12
  11. package/package.json +47 -45
  12. package/src/auth/access-denied.html +119 -119
  13. package/src/auth/shared-auth-storage.js +230 -230
  14. package/src/autonomous-mode/feature-implementer.cjs +70 -70
  15. package/src/autonomous-mode/feature-implementer.js +425 -425
  16. package/src/chat-management/chat-manager.cjs +71 -71
  17. package/src/chat-management/chat-manager.js +342 -342
  18. package/src/ide-integration/__tests__/applescript-manager-thread-closure.test.js +227 -227
  19. package/src/ide-integration/aider-cli-manager.cjs +850 -850
  20. package/src/ide-integration/applescript-manager.cjs +1088 -1088
  21. package/src/ide-integration/applescript-manager.js +2802 -2802
  22. package/src/ide-integration/applescript-utils.js +306 -306
  23. package/src/ide-integration/cdp-manager.cjs +221 -221
  24. package/src/ide-integration/cdp-manager.js +321 -321
  25. package/src/ide-integration/claude-code-cli-manager.cjs +301 -301
  26. package/src/ide-integration/cline-cli-manager.cjs +2252 -2252
  27. package/src/ide-integration/continue-cli-manager.js +431 -431
  28. package/src/ide-integration/provider-manager.cjs +354 -354
  29. package/src/ide-integration/quota-detector.cjs +34 -34
  30. package/src/ide-integration/quota-detector.js +349 -349
  31. package/src/ide-integration/windows-automation-manager.js +262 -262
  32. package/src/index.cjs +43 -43
  33. package/src/index.js +17 -17
  34. package/src/llm/direct-llm-manager.cjs +609 -609
  35. package/src/ui/ButtonComponents.js +247 -247
  36. package/src/ui/ChatInterface.js +499 -499
  37. package/src/ui/StateManager.js +259 -259
  38. package/src/utils/audit-logger.cjs +116 -116
  39. package/src/utils/config-helpers.cjs +94 -94
  40. package/src/utils/config-helpers.js +94 -94
  41. package/src/utils/electron-update-checker.js +85 -78
  42. package/src/utils/gcloud-auth.cjs +394 -394
  43. package/src/utils/logger.cjs +193 -193
  44. package/src/utils/logger.js +191 -191
  45. package/src/utils/repo-helpers.cjs +120 -120
  46. package/src/utils/repo-helpers.js +120 -120
  47. package/src/utils/requirement-helpers.js +432 -432
  48. package/src/utils/update-checker.js +167 -167
@@ -1,321 +1,321 @@
1
- import CDP from 'chrome-remote-interface';
2
-
3
- // Timeout utility function
4
- function timeout(ms, promise) {
5
- return Promise.race([
6
- promise,
7
- new Promise((_, reject) =>
8
- setTimeout(() => reject(new Error(`Operation timed out after ${ms}ms`)), ms)
9
- )
10
- ]);
11
- }
12
-
13
- export class CDPManager {
14
- constructor() {
15
- this.ports = {
16
- vscode: 9222,
17
- cursor: 9225,
18
- windsurf: 9224
19
- };
20
- }
21
-
22
- /**
23
- * Connect to an IDE via CDP
24
- * @param {string} ide - The IDE name (vscode, cursor, windsurf)
25
- * @param {number} port - The CDP port (optional, will use default if not provided)
26
- * @returns {Promise<Object>} CDP client and domains
27
- */
28
- async connectToIDE(ide, port = null) {
29
- const targetPort = port || this.ports[ide];
30
-
31
- if (!targetPort) {
32
- throw new Error(`No CDP port configured for IDE: ${ide}`);
33
- }
34
-
35
- try {
36
- console.log(`🔍 Connecting to ${ide} on port ${targetPort}...`);
37
-
38
- const targets = await timeout(5000, CDP.List({ port: targetPort }));
39
-
40
- if (!targets || targets.length === 0) {
41
- throw new Error(`Could not find ${ide}. Make sure ${ide} is running with --remote-debugging-port=${targetPort}`);
42
- }
43
-
44
- // Find the appropriate target
45
- let target;
46
- if (ide === 'vscode') {
47
- target = targets.find(t => t.url && t.url.includes('workbench')) || targets[0];
48
- } else {
49
- target = targets[0];
50
- }
51
-
52
- if (!target) {
53
- throw new Error(`No suitable target found for ${ide}`);
54
- }
55
-
56
- console.log(`Found ${targets.length} targets, using: ${target.title}`);
57
-
58
- const client = await CDP({ port: targetPort, target });
59
- const { Runtime, Input, Page, DOM } = client;
60
-
61
- await Runtime.enable();
62
- await DOM.enable();
63
-
64
- if (Page && Page.bringToFront) {
65
- try {
66
- await Page.bringToFront();
67
- } catch (error) {
68
- console.log('Could not bring page to front:', error.message);
69
- }
70
- }
71
-
72
- return {
73
- client,
74
- Runtime,
75
- Input,
76
- Page,
77
- DOM,
78
- target
79
- };
80
- } catch (error) {
81
- console.error(`CDP connection error for ${ide}:`, error);
82
- throw error;
83
- }
84
- }
85
-
86
- /**
87
- * Send text to an IDE via CDP
88
- * @param {string} text - The text to send
89
- * @param {string} ide - The IDE name
90
- * @returns {Promise<Object>} Result of the operation
91
- */
92
- async sendText(text, ide) {
93
- if (typeof text !== 'string') {
94
- return {
95
- success: false,
96
- error: `Invalid text type: ${typeof text}. Expected string.`
97
- };
98
- }
99
-
100
- const ideName = ide === 'windsurf' ? 'Windsurf' : ide === 'cursor' ? 'Cursor' : 'VS Code';
101
-
102
- console.log(`🔍 sendText: Starting debug session`);
103
- console.log(`📋 IDE: ${ideName} (${ide})`);
104
- console.log(`💬 Text: "${text.substring(0, 100)}${text.length > 100 ? '...' : ''}"`);
105
-
106
- try {
107
- const { client, Runtime, Input } = await this.connectToIDE(ide);
108
-
109
- // VS Code specific handling
110
- if (ide === 'vscode') {
111
- return await this.sendTextToVSCode(text, Runtime, Input);
112
- }
113
-
114
- // For other IDEs, use basic CDP approach
115
- return await this.sendTextBasic(text, Runtime, Input);
116
-
117
- } catch (error) {
118
- console.error(`${ideName} CDP error:`, error);
119
- return {
120
- success: false,
121
- error: `${ideName} CDP error: ${error.message}`
122
- };
123
- }
124
- }
125
-
126
- /**
127
- * Send text to VS Code using the working approach
128
- * @param {string} text - The text to send
129
- * @param {Object} Runtime - CDP Runtime domain
130
- * @param {Object} Input - CDP Input domain
131
- * @returns {Promise<Object>} Result of the operation
132
- */
133
- async sendTextToVSCode(text, Runtime, Input) {
134
- try {
135
- try {
136
- const isDarwin = process.platform === 'darwin';
137
- const modifiers = (isDarwin ? 4 /* Meta */ | 2 /* Ctrl */ : 2 /* Ctrl */);
138
- await Input.dispatchKeyEvent({ type: 'keyDown', key: 'I', text: 'I', modifiers });
139
- await Input.dispatchKeyEvent({ type: 'keyUp', key: 'I', text: 'I', modifiers });
140
- } catch (error) {
141
- console.log('Could not activate chat view:', error.message);
142
- }
143
-
144
- const textToSend = String(text).slice(0, 4000);
145
-
146
- // Use clipboard approach to avoid focus issues
147
- console.log('Copying text to clipboard:', textToSend);
148
-
149
- // Note: In VSCode extension context, we'll need to handle clipboard differently
150
- // For now, we'll use character-by-character typing
151
-
152
- // Type the text character by character
153
- console.log('Starting character-by-character typing...');
154
- for (let i = 0; i < textToSend.length; i++) {
155
- const char = textToSend[i];
156
- await Input.dispatchKeyEvent({ type: 'keyDown', key: char, text: char });
157
- await Input.dispatchKeyEvent({ type: 'keyUp', key: char, text: char });
158
- await new Promise(resolve => setTimeout(resolve, 20)); // Small delay between characters
159
- }
160
- console.log('Finished character-by-character typing');
161
-
162
- // Submit the message
163
- await this.submitMessage(Input, Runtime);
164
-
165
- return {
166
- success: true,
167
- method: 'cdp-character-typing',
168
- message: `Message sent to VS Code: ${text}`,
169
- note: 'Message sent via CDP with character-by-character typing'
170
- };
171
-
172
- } catch (error) {
173
- console.error('VS Code CDP error:', error);
174
- return { success: false, error: `VS Code CDP error: ${error.message}` };
175
- }
176
- }
177
-
178
- /**
179
- * Send text using basic CDP approach
180
- * @param {string} text - The text to send
181
- * @param {Object} Runtime - CDP Runtime domain
182
- * @param {Object} Input - CDP Input domain
183
- * @returns {Promise<Object>} Result of the operation
184
- */
185
- async sendTextBasic(text, Runtime, Input) {
186
- try {
187
- const textToSend = String(text).slice(0, 4000);
188
-
189
- // Type the text character by character
190
- console.log('Starting character-by-character typing...');
191
- for (let i = 0; i < textToSend.length; i++) {
192
- const char = textToSend[i];
193
- await Input.dispatchKeyEvent({ type: 'keyDown', key: char, text: char });
194
- await Input.dispatchKeyEvent({ type: 'keyUp', key: char, text: char });
195
- await new Promise(resolve => setTimeout(resolve, 20));
196
- }
197
- console.log('Finished character-by-character typing');
198
-
199
- // Submit the message
200
- await this.submitMessage(Input, Runtime);
201
-
202
- return {
203
- success: true,
204
- method: 'cdp-basic',
205
- message: `Message sent: ${text}`,
206
- note: 'Message sent via basic CDP approach'
207
- };
208
-
209
- } catch (error) {
210
- console.error('Basic CDP error:', error);
211
- return { success: false, error: `Basic CDP error: ${error.message}` };
212
- }
213
- }
214
-
215
- /**
216
- * Submit a message using multiple methods
217
- * @param {Object} Input - CDP Input domain
218
- * @param {Object} Runtime - CDP Runtime domain
219
- * @returns {Promise<void>}
220
- */
221
- async submitMessage(Input, Runtime) {
222
- // Wait a moment then try multiple ways to submit the message
223
- setTimeout(async () => {
224
- try {
225
- console.log('Attempting to submit message...');
226
-
227
- // Method 1: Press Enter
228
- console.log('Method 1: Pressing Enter...');
229
- await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Enter' });
230
- await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Enter' });
231
- await new Promise(resolve => setTimeout(resolve, 100));
232
-
233
- // Method 2: Try clicking the send button
234
- console.log('Method 2: Looking for send button...');
235
- const clickSendButton = `(() => {
236
- const sendButton = document.querySelector('[aria-label*="Send"]') ||
237
- document.querySelector('[title*="Send"]') ||
238
- document.querySelector('button[aria-label*="submit"]') ||
239
- document.querySelector('button[title*="submit"]') ||
240
- document.querySelector('[aria-label*="Send message"]') ||
241
- document.querySelector('[title*="Send message"]') ||
242
- document.querySelector('button[aria-label*="Send message"]') ||
243
- document.querySelector('button[title*="Send message"]') ||
244
- document.querySelector('button[aria-label*="Submit"]') ||
245
- document.querySelector('button[title*="Submit"]') ||
246
- document.querySelector('button[aria-label*="Send request"]') ||
247
- document.querySelector('button[title*="Send request"]') ||
248
- document.querySelector('button svg[data-icon*="send"]')?.closest('button') ||
249
- document.querySelector('button svg[data-icon*="play"]')?.closest('button') ||
250
- document.querySelector('button svg[data-icon*="arrow"]')?.closest('button') ||
251
- document.querySelector('button.send-button') ||
252
- document.querySelector('button.submit-button') ||
253
- document.querySelector('button[class*="send"]') ||
254
- document.querySelector('button[class*="submit"]');
255
-
256
- if (sendButton) {
257
- console.log('Found send button:', sendButton.getAttribute('aria-label') || sendButton.getAttribute('title') || sendButton.className);
258
- sendButton.click();
259
- return true;
260
- } else {
261
- console.log('No send button found');
262
- return false;
263
- }
264
- })()`;
265
-
266
- const { result: clickRes } = await Runtime.evaluate({ expression: clickSendButton, returnByValue: true });
267
- const clickResult = clickRes && (clickRes.value ?? clickRes.unserializableValue) ? (clickRes.value ?? clickRes.unserializableValue) : false;
268
- console.log('Send button click result:', clickResult);
269
-
270
- // Method 3: Try Cmd+Enter as alternative
271
- if (!clickResult) {
272
- console.log('Method 3: Trying Cmd+Enter...');
273
- const isDarwin = process.platform === 'darwin';
274
- const enterMods = isDarwin ? 4 /* Meta */ : 2 /* Ctrl */;
275
- await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Enter', text: 'Enter', modifiers: enterMods });
276
- await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Enter', text: 'Enter', modifiers: enterMods });
277
- }
278
-
279
- console.log('All submission methods attempted');
280
- } catch (error) {
281
- console.log('Submission failed:', error.message);
282
- }
283
- }, 300);
284
- }
285
-
286
- /**
287
- * Read chat text from an IDE
288
- * @param {string} ide - The IDE name
289
- * @returns {Promise<string>} The chat text
290
- */
291
- async readChatText(ide) {
292
- try {
293
- const { Runtime } = await this.connectToIDE(ide);
294
-
295
- const expression = `(() => {
296
- try {
297
- // Look for chat messages in various possible locations
298
- const chatMessages = document.querySelectorAll('[class*="message"], [class*="chat"], [class*="conversation"]');
299
- const messages = [];
300
-
301
- chatMessages.forEach(msg => {
302
- const text = msg.textContent || msg.innerText;
303
- if (text && text.trim()) {
304
- messages.push(text.trim());
305
- }
306
- });
307
-
308
- return messages.join('\\n\\n');
309
- } catch (error) {
310
- return 'Error reading chat: ' + error.message;
311
- }
312
- })()`;
313
-
314
- const { result } = await Runtime.evaluate({ expression, returnByValue: true });
315
- return result.value || '[]';
316
- } catch (error) {
317
- console.error(`Error reading chat from ${ide}:`, error);
318
- return `Error: ${error.message}`;
319
- }
320
- }
321
- }
1
+ import CDP from 'chrome-remote-interface';
2
+
3
+ // Timeout utility function
4
+ function timeout(ms, promise) {
5
+ return Promise.race([
6
+ promise,
7
+ new Promise((_, reject) =>
8
+ setTimeout(() => reject(new Error(`Operation timed out after ${ms}ms`)), ms)
9
+ )
10
+ ]);
11
+ }
12
+
13
+ export class CDPManager {
14
+ constructor() {
15
+ this.ports = {
16
+ vscode: 9222,
17
+ cursor: 9225,
18
+ windsurf: 9224
19
+ };
20
+ }
21
+
22
+ /**
23
+ * Connect to an IDE via CDP
24
+ * @param {string} ide - The IDE name (vscode, cursor, windsurf)
25
+ * @param {number} port - The CDP port (optional, will use default if not provided)
26
+ * @returns {Promise<Object>} CDP client and domains
27
+ */
28
+ async connectToIDE(ide, port = null) {
29
+ const targetPort = port || this.ports[ide];
30
+
31
+ if (!targetPort) {
32
+ throw new Error(`No CDP port configured for IDE: ${ide}`);
33
+ }
34
+
35
+ try {
36
+ console.log(`🔍 Connecting to ${ide} on port ${targetPort}...`);
37
+
38
+ const targets = await timeout(5000, CDP.List({ port: targetPort }));
39
+
40
+ if (!targets || targets.length === 0) {
41
+ throw new Error(`Could not find ${ide}. Make sure ${ide} is running with --remote-debugging-port=${targetPort}`);
42
+ }
43
+
44
+ // Find the appropriate target
45
+ let target;
46
+ if (ide === 'vscode') {
47
+ target = targets.find(t => t.url && t.url.includes('workbench')) || targets[0];
48
+ } else {
49
+ target = targets[0];
50
+ }
51
+
52
+ if (!target) {
53
+ throw new Error(`No suitable target found for ${ide}`);
54
+ }
55
+
56
+ console.log(`Found ${targets.length} targets, using: ${target.title}`);
57
+
58
+ const client = await CDP({ port: targetPort, target });
59
+ const { Runtime, Input, Page, DOM } = client;
60
+
61
+ await Runtime.enable();
62
+ await DOM.enable();
63
+
64
+ if (Page && Page.bringToFront) {
65
+ try {
66
+ await Page.bringToFront();
67
+ } catch (error) {
68
+ console.log('Could not bring page to front:', error.message);
69
+ }
70
+ }
71
+
72
+ return {
73
+ client,
74
+ Runtime,
75
+ Input,
76
+ Page,
77
+ DOM,
78
+ target
79
+ };
80
+ } catch (error) {
81
+ console.error(`CDP connection error for ${ide}:`, error);
82
+ throw error;
83
+ }
84
+ }
85
+
86
+ /**
87
+ * Send text to an IDE via CDP
88
+ * @param {string} text - The text to send
89
+ * @param {string} ide - The IDE name
90
+ * @returns {Promise<Object>} Result of the operation
91
+ */
92
+ async sendText(text, ide) {
93
+ if (typeof text !== 'string') {
94
+ return {
95
+ success: false,
96
+ error: `Invalid text type: ${typeof text}. Expected string.`
97
+ };
98
+ }
99
+
100
+ const ideName = ide === 'windsurf' ? 'Windsurf' : ide === 'cursor' ? 'Cursor' : 'VS Code';
101
+
102
+ console.log(`🔍 sendText: Starting debug session`);
103
+ console.log(`📋 IDE: ${ideName} (${ide})`);
104
+ console.log(`💬 Text: "${text.substring(0, 100)}${text.length > 100 ? '...' : ''}"`);
105
+
106
+ try {
107
+ const { client, Runtime, Input } = await this.connectToIDE(ide);
108
+
109
+ // VS Code specific handling
110
+ if (ide === 'vscode') {
111
+ return await this.sendTextToVSCode(text, Runtime, Input);
112
+ }
113
+
114
+ // For other IDEs, use basic CDP approach
115
+ return await this.sendTextBasic(text, Runtime, Input);
116
+
117
+ } catch (error) {
118
+ console.error(`${ideName} CDP error:`, error);
119
+ return {
120
+ success: false,
121
+ error: `${ideName} CDP error: ${error.message}`
122
+ };
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Send text to VS Code using the working approach
128
+ * @param {string} text - The text to send
129
+ * @param {Object} Runtime - CDP Runtime domain
130
+ * @param {Object} Input - CDP Input domain
131
+ * @returns {Promise<Object>} Result of the operation
132
+ */
133
+ async sendTextToVSCode(text, Runtime, Input) {
134
+ try {
135
+ try {
136
+ const isDarwin = process.platform === 'darwin';
137
+ const modifiers = (isDarwin ? 4 /* Meta */ | 2 /* Ctrl */ : 2 /* Ctrl */);
138
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: 'I', text: 'I', modifiers });
139
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: 'I', text: 'I', modifiers });
140
+ } catch (error) {
141
+ console.log('Could not activate chat view:', error.message);
142
+ }
143
+
144
+ const textToSend = String(text).slice(0, 4000);
145
+
146
+ // Use clipboard approach to avoid focus issues
147
+ console.log('Copying text to clipboard:', textToSend);
148
+
149
+ // Note: In VSCode extension context, we'll need to handle clipboard differently
150
+ // For now, we'll use character-by-character typing
151
+
152
+ // Type the text character by character
153
+ console.log('Starting character-by-character typing...');
154
+ for (let i = 0; i < textToSend.length; i++) {
155
+ const char = textToSend[i];
156
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: char, text: char });
157
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: char, text: char });
158
+ await new Promise(resolve => setTimeout(resolve, 20)); // Small delay between characters
159
+ }
160
+ console.log('Finished character-by-character typing');
161
+
162
+ // Submit the message
163
+ await this.submitMessage(Input, Runtime);
164
+
165
+ return {
166
+ success: true,
167
+ method: 'cdp-character-typing',
168
+ message: `Message sent to VS Code: ${text}`,
169
+ note: 'Message sent via CDP with character-by-character typing'
170
+ };
171
+
172
+ } catch (error) {
173
+ console.error('VS Code CDP error:', error);
174
+ return { success: false, error: `VS Code CDP error: ${error.message}` };
175
+ }
176
+ }
177
+
178
+ /**
179
+ * Send text using basic CDP approach
180
+ * @param {string} text - The text to send
181
+ * @param {Object} Runtime - CDP Runtime domain
182
+ * @param {Object} Input - CDP Input domain
183
+ * @returns {Promise<Object>} Result of the operation
184
+ */
185
+ async sendTextBasic(text, Runtime, Input) {
186
+ try {
187
+ const textToSend = String(text).slice(0, 4000);
188
+
189
+ // Type the text character by character
190
+ console.log('Starting character-by-character typing...');
191
+ for (let i = 0; i < textToSend.length; i++) {
192
+ const char = textToSend[i];
193
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: char, text: char });
194
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: char, text: char });
195
+ await new Promise(resolve => setTimeout(resolve, 20));
196
+ }
197
+ console.log('Finished character-by-character typing');
198
+
199
+ // Submit the message
200
+ await this.submitMessage(Input, Runtime);
201
+
202
+ return {
203
+ success: true,
204
+ method: 'cdp-basic',
205
+ message: `Message sent: ${text}`,
206
+ note: 'Message sent via basic CDP approach'
207
+ };
208
+
209
+ } catch (error) {
210
+ console.error('Basic CDP error:', error);
211
+ return { success: false, error: `Basic CDP error: ${error.message}` };
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Submit a message using multiple methods
217
+ * @param {Object} Input - CDP Input domain
218
+ * @param {Object} Runtime - CDP Runtime domain
219
+ * @returns {Promise<void>}
220
+ */
221
+ async submitMessage(Input, Runtime) {
222
+ // Wait a moment then try multiple ways to submit the message
223
+ setTimeout(async () => {
224
+ try {
225
+ console.log('Attempting to submit message...');
226
+
227
+ // Method 1: Press Enter
228
+ console.log('Method 1: Pressing Enter...');
229
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Enter' });
230
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Enter' });
231
+ await new Promise(resolve => setTimeout(resolve, 100));
232
+
233
+ // Method 2: Try clicking the send button
234
+ console.log('Method 2: Looking for send button...');
235
+ const clickSendButton = `(() => {
236
+ const sendButton = document.querySelector('[aria-label*="Send"]') ||
237
+ document.querySelector('[title*="Send"]') ||
238
+ document.querySelector('button[aria-label*="submit"]') ||
239
+ document.querySelector('button[title*="submit"]') ||
240
+ document.querySelector('[aria-label*="Send message"]') ||
241
+ document.querySelector('[title*="Send message"]') ||
242
+ document.querySelector('button[aria-label*="Send message"]') ||
243
+ document.querySelector('button[title*="Send message"]') ||
244
+ document.querySelector('button[aria-label*="Submit"]') ||
245
+ document.querySelector('button[title*="Submit"]') ||
246
+ document.querySelector('button[aria-label*="Send request"]') ||
247
+ document.querySelector('button[title*="Send request"]') ||
248
+ document.querySelector('button svg[data-icon*="send"]')?.closest('button') ||
249
+ document.querySelector('button svg[data-icon*="play"]')?.closest('button') ||
250
+ document.querySelector('button svg[data-icon*="arrow"]')?.closest('button') ||
251
+ document.querySelector('button.send-button') ||
252
+ document.querySelector('button.submit-button') ||
253
+ document.querySelector('button[class*="send"]') ||
254
+ document.querySelector('button[class*="submit"]');
255
+
256
+ if (sendButton) {
257
+ console.log('Found send button:', sendButton.getAttribute('aria-label') || sendButton.getAttribute('title') || sendButton.className);
258
+ sendButton.click();
259
+ return true;
260
+ } else {
261
+ console.log('No send button found');
262
+ return false;
263
+ }
264
+ })()`;
265
+
266
+ const { result: clickRes } = await Runtime.evaluate({ expression: clickSendButton, returnByValue: true });
267
+ const clickResult = clickRes && (clickRes.value ?? clickRes.unserializableValue) ? (clickRes.value ?? clickRes.unserializableValue) : false;
268
+ console.log('Send button click result:', clickResult);
269
+
270
+ // Method 3: Try Cmd+Enter as alternative
271
+ if (!clickResult) {
272
+ console.log('Method 3: Trying Cmd+Enter...');
273
+ const isDarwin = process.platform === 'darwin';
274
+ const enterMods = isDarwin ? 4 /* Meta */ : 2 /* Ctrl */;
275
+ await Input.dispatchKeyEvent({ type: 'keyDown', key: 'Enter', text: 'Enter', modifiers: enterMods });
276
+ await Input.dispatchKeyEvent({ type: 'keyUp', key: 'Enter', text: 'Enter', modifiers: enterMods });
277
+ }
278
+
279
+ console.log('All submission methods attempted');
280
+ } catch (error) {
281
+ console.log('Submission failed:', error.message);
282
+ }
283
+ }, 300);
284
+ }
285
+
286
+ /**
287
+ * Read chat text from an IDE
288
+ * @param {string} ide - The IDE name
289
+ * @returns {Promise<string>} The chat text
290
+ */
291
+ async readChatText(ide) {
292
+ try {
293
+ const { Runtime } = await this.connectToIDE(ide);
294
+
295
+ const expression = `(() => {
296
+ try {
297
+ // Look for chat messages in various possible locations
298
+ const chatMessages = document.querySelectorAll('[class*="message"], [class*="chat"], [class*="conversation"]');
299
+ const messages = [];
300
+
301
+ chatMessages.forEach(msg => {
302
+ const text = msg.textContent || msg.innerText;
303
+ if (text && text.trim()) {
304
+ messages.push(text.trim());
305
+ }
306
+ });
307
+
308
+ return messages.join('\\n\\n');
309
+ } catch (error) {
310
+ return 'Error reading chat: ' + error.message;
311
+ }
312
+ })()`;
313
+
314
+ const { result } = await Runtime.evaluate({ expression, returnByValue: true });
315
+ return result.value || '[]';
316
+ } catch (error) {
317
+ console.error(`Error reading chat from ${ide}:`, error);
318
+ return `Error: ${error.message}`;
319
+ }
320
+ }
321
+ }