vibecodingmachine-core 2026.2.20-438 → 2026.2.26-1739

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 (202) hide show
  1. package/README.md +240 -0
  2. package/package.json +10 -2
  3. package/src/agents/Agent.js +300 -0
  4. package/src/agents/AgentAdditionService.js +311 -0
  5. package/src/agents/AgentCheckService.js +690 -0
  6. package/src/agents/AgentInstallationService.js +140 -0
  7. package/src/agents/AgentSetupService.js +467 -0
  8. package/src/agents/AgentStatus.js +183 -0
  9. package/src/agents/AgentVerificationService.js +634 -0
  10. package/src/agents/ConfigurationSchemaValidator.js +543 -0
  11. package/src/agents/EnvironmentConfigurationManager.js +602 -0
  12. package/src/agents/InstallationErrorHandler.js +372 -0
  13. package/src/agents/InstallationLog.js +363 -0
  14. package/src/agents/InstallationMethod.js +510 -0
  15. package/src/agents/InstallationOrchestrator.js +352 -0
  16. package/src/agents/InstallationProgressReporter.js +372 -0
  17. package/src/agents/InstallationRetryManager.js +322 -0
  18. package/src/agents/InstallationType.js +254 -0
  19. package/src/agents/OperationTypes.js +310 -0
  20. package/src/agents/PerformanceMetricsCollector.js +493 -0
  21. package/src/agents/SecurityValidationService.js +534 -0
  22. package/src/agents/VerificationTest.js +354 -0
  23. package/src/agents/VerificationType.js +226 -0
  24. package/src/agents/WindowsPermissionHandler.js +518 -0
  25. package/src/agents/config/AgentConfigManager.js +393 -0
  26. package/src/agents/config/AgentDefaultsRegistry.js +373 -0
  27. package/src/agents/config/ConfigValidator.js +281 -0
  28. package/src/agents/discovery/AgentDiscoveryService.js +707 -0
  29. package/src/agents/logging/AgentLogger.js +511 -0
  30. package/src/agents/status/AgentStatusManager.js +481 -0
  31. package/src/agents/storage/FileManager.js +454 -0
  32. package/src/agents/verification/AgentCommunicationTester.js +474 -0
  33. package/src/agents/verification/BaseVerifier.js +430 -0
  34. package/src/agents/verification/CommandVerifier.js +480 -0
  35. package/src/agents/verification/FileOperationVerifier.js +453 -0
  36. package/src/agents/verification/ResultAnalyzer.js +707 -0
  37. package/src/agents/verification/TestRequirementManager.js +495 -0
  38. package/src/agents/verification/VerificationRunner.js +433 -0
  39. package/src/agents/windows/BaseWindowsInstaller.js +441 -0
  40. package/src/agents/windows/ChocolateyInstaller.js +509 -0
  41. package/src/agents/windows/DirectInstaller.js +443 -0
  42. package/src/agents/windows/InstallerFactory.js +391 -0
  43. package/src/agents/windows/NpmInstaller.js +505 -0
  44. package/src/agents/windows/PowerShellInstaller.js +458 -0
  45. package/src/agents/windows/WinGetInstaller.js +390 -0
  46. package/src/analysis/analysis-reporter.js +132 -0
  47. package/src/analysis/boundary-detector.js +712 -0
  48. package/src/analysis/categorizer.js +340 -0
  49. package/src/analysis/codebase-scanner.js +384 -0
  50. package/src/analysis/line-counter.js +513 -0
  51. package/src/analysis/priority-calculator.js +679 -0
  52. package/src/analysis/report/analysis-report.js +250 -0
  53. package/src/analysis/report/package-analyzer.js +278 -0
  54. package/src/analysis/report/recommendation-generator.js +382 -0
  55. package/src/analysis/report/statistics-generator.js +515 -0
  56. package/src/analysis/reports/analysis-report-model.js +101 -0
  57. package/src/analysis/reports/recommendation-generator.js +283 -0
  58. package/src/analysis/reports/report-generators.js +191 -0
  59. package/src/analysis/reports/statistics-calculator.js +231 -0
  60. package/src/analysis/reports/trend-analyzer.js +219 -0
  61. package/src/analysis/strategy-generator.js +814 -0
  62. package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
  63. package/src/config/refactoring-config.js +307 -0
  64. package/src/health-tracking/json-storage.js +38 -2
  65. package/src/ide-integration/applescript-manager-core.js +233 -0
  66. package/src/ide-integration/applescript-manager.cjs +357 -28
  67. package/src/ide-integration/applescript-manager.js +89 -3599
  68. package/src/ide-integration/cdp-manager.js +306 -0
  69. package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
  70. package/src/ide-integration/continuation-handler.js +337 -0
  71. package/src/ide-integration/ide-status-checker.js +292 -0
  72. package/src/ide-integration/macos-ide-manager.js +627 -0
  73. package/src/ide-integration/macos-text-sender.js +528 -0
  74. package/src/ide-integration/response-reader.js +548 -0
  75. package/src/ide-integration/windows-automation-manager.js +121 -0
  76. package/src/ide-integration/windows-ide-manager.js +373 -0
  77. package/src/index.cjs +25 -3
  78. package/src/index.js +15 -1
  79. package/src/llm/direct-llm-manager.cjs +90 -2
  80. package/src/models/compliance-report.js +538 -0
  81. package/src/models/file-analysis.js +681 -0
  82. package/src/models/refactoring-plan.js +770 -0
  83. package/src/monitoring/alert-system.js +834 -0
  84. package/src/monitoring/compliance-progress-tracker.js +437 -0
  85. package/src/monitoring/continuous-scan-notifications.js +661 -0
  86. package/src/monitoring/continuous-scanner.js +279 -0
  87. package/src/monitoring/file-monitor/file-analyzer.js +262 -0
  88. package/src/monitoring/file-monitor/file-monitor.js +237 -0
  89. package/src/monitoring/file-monitor/watcher.js +194 -0
  90. package/src/monitoring/file-monitor.js +17 -0
  91. package/src/monitoring/notification-manager.js +437 -0
  92. package/src/monitoring/scanner-core.js +368 -0
  93. package/src/monitoring/scanner-events.js +214 -0
  94. package/src/monitoring/violation-notification-system.js +515 -0
  95. package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
  96. package/src/refactoring/boundaries/extraction-result.js +285 -0
  97. package/src/refactoring/boundaries/extraction-strategies.js +392 -0
  98. package/src/refactoring/boundaries/module-boundary.js +209 -0
  99. package/src/refactoring/boundary/boundary-detector.js +741 -0
  100. package/src/refactoring/boundary/boundary-types.js +405 -0
  101. package/src/refactoring/boundary/extraction-strategies.js +554 -0
  102. package/src/refactoring/boundary-extraction-result.js +77 -0
  103. package/src/refactoring/boundary-extraction-strategies.js +330 -0
  104. package/src/refactoring/boundary-extractor.js +384 -0
  105. package/src/refactoring/boundary-types.js +46 -0
  106. package/src/refactoring/circular/circular-dependency.js +88 -0
  107. package/src/refactoring/circular/cycle-detection.js +147 -0
  108. package/src/refactoring/circular/dependency-node.js +82 -0
  109. package/src/refactoring/circular/dependency-result.js +107 -0
  110. package/src/refactoring/circular/dependency-types.js +58 -0
  111. package/src/refactoring/circular/graph-builder.js +213 -0
  112. package/src/refactoring/circular/resolution-strategy.js +72 -0
  113. package/src/refactoring/circular/strategy-generator.js +229 -0
  114. package/src/refactoring/circular-dependency-resolver-original.js +809 -0
  115. package/src/refactoring/circular-dependency-resolver.js +200 -0
  116. package/src/refactoring/code-mover.js +761 -0
  117. package/src/refactoring/file-splitter.js +696 -0
  118. package/src/refactoring/functionality-validator.js +816 -0
  119. package/src/refactoring/import-manager.js +774 -0
  120. package/src/refactoring/module-boundary.js +107 -0
  121. package/src/refactoring/refactoring-executor.js +672 -0
  122. package/src/refactoring/refactoring-rollback.js +614 -0
  123. package/src/refactoring/test-validator.js +631 -0
  124. package/src/requirement-management/default-requirement-manager.js +321 -0
  125. package/src/requirement-management/requirement-file-parser.js +159 -0
  126. package/src/requirement-management/requirement-sequencer.js +221 -0
  127. package/src/rui/commands/AgentCommandParser.js +600 -0
  128. package/src/rui/commands/AgentCommands.js +487 -0
  129. package/src/rui/commands/AgentResponseFormatter.js +832 -0
  130. package/src/scripts/verify-full-compliance.js +269 -0
  131. package/src/sync/sync-engine-core.js +1 -0
  132. package/src/sync/sync-engine-remote-handlers.js +135 -0
  133. package/src/task-generation/automated-task-generator.js +351 -0
  134. package/src/task-generation/prioritizer.js +287 -0
  135. package/src/task-generation/task-list-updater.js +215 -0
  136. package/src/task-generation/task-management-integration.js +480 -0
  137. package/src/task-generation/task-manager-integration.js +270 -0
  138. package/src/task-generation/violation-task-generator.js +474 -0
  139. package/src/task-management/continuous-scan-integration.js +342 -0
  140. package/src/timeout-management/index.js +12 -3
  141. package/src/timeout-management/response-time-tracker.js +167 -0
  142. package/src/timeout-management/timeout-calculator.js +159 -0
  143. package/src/timeout-management/timeout-config-manager.js +172 -0
  144. package/src/utils/ast-analyzer.js +417 -0
  145. package/src/utils/current-requirement-manager.js +276 -0
  146. package/src/utils/current-requirement-operations.js +472 -0
  147. package/src/utils/dependency-mapper.js +456 -0
  148. package/src/utils/download-with-progress.js +4 -2
  149. package/src/utils/electron-update-checker.js +4 -1
  150. package/src/utils/file-size-analyzer.js +272 -0
  151. package/src/utils/import-updater.js +280 -0
  152. package/src/utils/refactoring-tools.js +512 -0
  153. package/src/utils/report-generator.js +569 -0
  154. package/src/utils/reports/report-analysis.js +218 -0
  155. package/src/utils/reports/report-types.js +55 -0
  156. package/src/utils/reports/summary-generators.js +102 -0
  157. package/src/utils/requirement-file-management.js +157 -0
  158. package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
  159. package/src/utils/requirement-helpers/requirement-mover.js +414 -0
  160. package/src/utils/requirement-helpers/requirement-parser.js +326 -0
  161. package/src/utils/requirement-helpers/requirement-status.js +320 -0
  162. package/src/utils/requirement-helpers-new.js +55 -0
  163. package/src/utils/requirement-helpers-refactored.js +367 -0
  164. package/src/utils/requirement-helpers.js +291 -1191
  165. package/src/utils/requirement-movement-operations.js +450 -0
  166. package/src/utils/requirement-movement.js +312 -0
  167. package/src/utils/requirement-parsing-helpers.js +56 -0
  168. package/src/utils/requirement-statistics.js +200 -0
  169. package/src/utils/requirement-text-utils.js +58 -0
  170. package/src/utils/rollback/rollback-handlers.js +125 -0
  171. package/src/utils/rollback/rollback-operation.js +63 -0
  172. package/src/utils/rollback/rollback-recorder.js +166 -0
  173. package/src/utils/rollback/rollback-state-manager.js +175 -0
  174. package/src/utils/rollback/rollback-types.js +33 -0
  175. package/src/utils/rollback/rollback-utils.js +110 -0
  176. package/src/utils/rollback-manager-original.js +569 -0
  177. package/src/utils/rollback-manager.js +202 -0
  178. package/src/utils/smoke-test-cli.js +362 -0
  179. package/src/utils/smoke-test-gui.js +351 -0
  180. package/src/utils/smoke-test-orchestrator.js +321 -0
  181. package/src/utils/smoke-test-runner.js +60 -0
  182. package/src/utils/smoke-test-web.js +347 -0
  183. package/src/utils/specification-helpers.js +39 -13
  184. package/src/utils/specification-migration.js +97 -0
  185. package/src/utils/test-runner.js +579 -0
  186. package/src/utils/validation-framework.js +518 -0
  187. package/src/validation/compliance-analyzer.js +197 -0
  188. package/src/validation/compliance-report-generator.js +343 -0
  189. package/src/validation/compliance-reporter.js +711 -0
  190. package/src/validation/compliance-rules.js +127 -0
  191. package/src/validation/constitution-validator-new.js +196 -0
  192. package/src/validation/constitution-validator.js +17 -0
  193. package/src/validation/file-validators.js +170 -0
  194. package/src/validation/line-limit/file-analyzer.js +201 -0
  195. package/src/validation/line-limit/line-limit-validator.js +208 -0
  196. package/src/validation/line-limit/validation-result.js +144 -0
  197. package/src/validation/line-limit-core.js +225 -0
  198. package/src/validation/line-limit-reporter.js +134 -0
  199. package/src/validation/line-limit-result.js +125 -0
  200. package/src/validation/line-limit-validator.js +41 -0
  201. package/src/validation/metrics-calculator.js +660 -0
  202. package/src/sync/sync-engine-backup.js +0 -559
@@ -0,0 +1,627 @@
1
+ // @vibecodingmachine/core - macOS IDE Manager
2
+ // macOS-specific IDE operations using AppleScript
3
+
4
+ const { execSync } = require('child_process');
5
+ const { writeFileSync, unlinkSync } = require('fs');
6
+ const { join } = require('path');
7
+ const { tmpdir } = require('os');
8
+
9
+ /**
10
+ * macOS IDE Manager for AppleScript-based interactions
11
+ * Handles all macOS-specific IDE operations
12
+ */
13
+ class MacOSIDEManager {
14
+ constructor(appleScriptUtils) {
15
+ this.logger = console;
16
+ this.appleScriptUtils = appleScriptUtils;
17
+ }
18
+
19
+ /**
20
+ * Open IDE on macOS using AppleScript
21
+ * @param {string} ide - The IDE name
22
+ * @param {string} repoPath - Optional repository path to open
23
+ * @returns {Promise<Object>} Result object with success status and details
24
+ */
25
+ async openIDE(ide, repoPath = null) {
26
+ const ideLower = (ide || '').toLowerCase();
27
+
28
+ switch (ideLower) {
29
+ case 'cursor':
30
+ return await this.openCursor(repoPath);
31
+ case 'windsurf':
32
+ return await this.openWindsurf(repoPath);
33
+ case 'antigravity':
34
+ return await this.openAntigravity(repoPath);
35
+ case 'vscode':
36
+ return await this.openVSCode(repoPath);
37
+ case 'github-copilot':
38
+ return await this.openVSCodeWithExtension('github-copilot', repoPath);
39
+ case 'amazon-q':
40
+ return await this.openVSCodeWithExtension('amazon-q', repoPath);
41
+ case 'replit':
42
+ return await this.openReplit(repoPath);
43
+ case 'kiro':
44
+ return await this.openKiro(repoPath);
45
+ case 'claude':
46
+ case 'claude-code':
47
+ return await this.openClaude(repoPath);
48
+ case 'gemini':
49
+ return await this.openGemini(repoPath);
50
+ default:
51
+ return {
52
+ success: false,
53
+ error: `Unknown IDE: ${ide}. Supported: cursor, windsurf, antigravity, vscode, github-copilot, amazon-q, replit, kiro, claude, claude-code, gemini`
54
+ };
55
+ }
56
+ }
57
+
58
+ /**
59
+ * Open Cursor IDE with optional repository path and remote debugging enabled
60
+ * @param {string} repoPath - Optional repository path to open
61
+ * @returns {Promise<Object>} Result object with success status and details
62
+ */
63
+ async openCursor(repoPath = null) {
64
+ try {
65
+ this.logger.log('Opening Cursor with remote debugging enabled...');
66
+
67
+ // Launch Cursor with remote debugging enabled
68
+ let command = 'open -a "Cursor" --args --remote-debugging-port=9225';
69
+ if (repoPath) {
70
+ command = `open -a "Cursor" "${repoPath}" --args --remote-debugging-port=9225`;
71
+ }
72
+
73
+ execSync(command, { stdio: 'pipe' });
74
+
75
+ // Wait for Cursor to start and bind the debugging port
76
+ await new Promise(resolve => setTimeout(resolve, 3000));
77
+
78
+ this.logger.log('Cursor opened successfully with remote debugging on port 9225');
79
+ return {
80
+ success: true,
81
+ message: repoPath ? `Cursor opened with repository: ${repoPath} and remote debugging` : 'Cursor opened successfully with remote debugging',
82
+ method: 'applescript',
83
+ debugPort: 9225
84
+ };
85
+ } catch (error) {
86
+ this.logger.log('Error opening Cursor:', error.message);
87
+ return {
88
+ success: false,
89
+ error: error.message,
90
+ method: 'applescript'
91
+ };
92
+ }
93
+ }
94
+
95
+ /**
96
+ * Open Gemini (in VS Code)
97
+ * @param {string} repoPath - Optional repository path to open
98
+ * @returns {Promise<Object>} Result object with success status and details
99
+ */
100
+ async openGemini(repoPath = null) {
101
+ this.logger.log('Opening Gemini, which runs in VS Code...');
102
+ return await this.openVSCode(repoPath);
103
+ }
104
+
105
+ /**
106
+ * Open Claude in a new terminal or bring existing instance to foreground
107
+ * @param {string} repoPath - Optional repository path to open (will cd to this directory before starting Claude)
108
+ * @returns {Promise<Object>} Result object with success status and details
109
+ */
110
+ async openClaude(repoPath = null) {
111
+ try {
112
+ this.logger.log('Opening Claude in terminal or bringing to foreground...');
113
+
114
+ // First, check if any Claude process is running using a simple shell command
115
+ try {
116
+ const claudeProcessCheck = execSync('ps aux | grep -i "claude" | grep -v grep | grep -v "Claude.app" | wc -l', { encoding: 'utf8' }).trim();
117
+ const claudeCount = parseInt(claudeProcessCheck);
118
+ this.logger.log(`🔍 [Claude] Found ${claudeCount} Claude processes running`);
119
+
120
+ if (claudeCount === 0) {
121
+ this.logger.log('No Claude process found, will create new terminal');
122
+ throw new Error('No Claude process running');
123
+ }
124
+ } catch (processCheckError) {
125
+ this.logger.log('No Claude process detected, will create new terminal');
126
+ // Jump to creating new terminal
127
+ const escapedPath = repoPath ? repoPath.replace(/'/g, "'\\''") : '';
128
+ const cdCommand = repoPath ? `cd '${escapedPath}' && ` : '';
129
+ const openClaudeScript = `
130
+ tell application "Terminal"
131
+ activate
132
+ set newWindow to do script "echo 'Starting Claude Code...' && ${cdCommand}claude --dangerously-skip-permissions"
133
+ delay 3
134
+ end tell
135
+ `;
136
+
137
+ const tempFile = join(tmpdir(), `claude_open_${Date.now()}.scpt`);
138
+ try {
139
+ writeFileSync(tempFile, openClaudeScript, 'utf8');
140
+ execSync(`osascript "${tempFile}"`, { stdio: 'pipe' });
141
+
142
+ this.logger.log('Claude opened in new terminal successfully');
143
+ return {
144
+ success: true,
145
+ message: repoPath ? `Claude opened in terminal with context: ${repoPath}` : 'Claude opened in new terminal',
146
+ method: 'applescript',
147
+ action: 'open'
148
+ };
149
+ } finally {
150
+ try {
151
+ unlinkSync(tempFile);
152
+ } catch (cleanupError) {
153
+ this.logger.log(`⚠️ Failed to cleanup temp file: ${cleanupError.message}`);
154
+ }
155
+ }
156
+ }
157
+
158
+ // If we get here, Claude process exists - find the specific Claude terminal window
159
+ // [Continued in next part due to size...]
160
+ return await this._findAndFocusClaudeTerminal(repoPath);
161
+ } catch (error) {
162
+ this.logger.log('Error opening Claude:', error.message);
163
+ return {
164
+ success: false,
165
+ error: error.message,
166
+ method: 'applescript'
167
+ };
168
+ }
169
+ }
170
+
171
+ /**
172
+ * Find and focus existing Claude terminal window
173
+ * @param {string} repoPath - Repository path for context
174
+ * @returns {Promise<Object>} Result object
175
+ */
176
+ async _findAndFocusClaudeTerminal(repoPath) {
177
+ try {
178
+ this.logger.log('🔍 [Claude] Claude process detected, searching for Claude terminal window...');
179
+ const escapedRepoPath = repoPath ? repoPath.replace(/'/g, "'\\''") : '';
180
+ const repoPathCheck = repoPath ? `and historyText contains "${escapedRepoPath}"` : '';
181
+
182
+ const findClaudeWindowScript = `
183
+ tell application "Terminal"
184
+ activate
185
+ delay 0.5
186
+
187
+ set claudeWindow to null
188
+ set windowCount to count of windows
189
+
190
+ -- Search through all terminal windows to find the one running Claude IN THE CORRECT DIRECTORY
191
+ repeat with i from 1 to windowCount
192
+ try
193
+ set currentWindow to window i
194
+ set currentTab to selected tab of currentWindow
195
+ set historyText to history of currentTab as text
196
+
197
+ -- Check for Claude AND optionally the correct repo path to avoid wrong terminal
198
+ if (historyText contains "Claude Code" or historyText contains "claude --dangerously-skip-permissions") ${repoPathCheck} then
199
+ set claudeWindow to currentWindow
200
+ exit repeat
201
+ end if
202
+ on error
203
+ -- Continue to next window
204
+ end try
205
+ end repeat
206
+
207
+ if claudeWindow is not null then
208
+ -- Found Claude window - bring it to front
209
+ set index of claudeWindow to 1
210
+ delay 0.5
211
+ return "claude-window-found"
212
+ else
213
+ return "claude-window-not-found"
214
+ end if
215
+ end tell
216
+ `;
217
+
218
+ const tempFile = join(tmpdir(), `claude_find_${Date.now()}.scpt`);
219
+ try {
220
+ writeFileSync(tempFile, findClaudeWindowScript, 'utf8');
221
+ const result = execSync(`osascript "${tempFile}"`, { stdio: 'pipe', encoding: 'utf8' }).trim();
222
+
223
+ if (result === 'claude-window-found') {
224
+ this.logger.log('✅ [Claude] Found and focused Claude terminal window');
225
+ return {
226
+ success: true,
227
+ message: 'Claude terminal window found and focused',
228
+ method: 'applescript',
229
+ action: 'focus'
230
+ };
231
+ } else {
232
+ this.logger.log('⚠️ [Claude] Claude window not found despite process running, will create new one');
233
+ }
234
+ } finally {
235
+ try {
236
+ unlinkSync(tempFile);
237
+ } catch (cleanupError) {
238
+ this.logger.log(`⚠️ Failed to cleanup temp file: ${cleanupError.message}`);
239
+ }
240
+ }
241
+
242
+ // No existing Claude found, open a new terminal with Claude
243
+ return await this._openNewClaudeTerminal(repoPath);
244
+ } catch (focusError) {
245
+ this.logger.log('⚠️ [Claude] Error finding Claude window, will create new one:', focusError.message);
246
+ return await this._openNewClaudeTerminal(repoPath);
247
+ }
248
+ }
249
+
250
+ /**
251
+ * Open new Claude terminal
252
+ * @param {string} repoPath - Repository path for context
253
+ * @returns {Promise<Object>} Result object
254
+ */
255
+ async _openNewClaudeTerminal(repoPath) {
256
+ const escapedPath = repoPath ? repoPath.replace(/'/g, "'\\''") : '';
257
+ const cdCommand = repoPath ? `cd '${escapedPath}' && ` : '';
258
+ const openClaudeScript = `
259
+ tell application "Terminal"
260
+ activate
261
+ set newWindow to do script "echo 'Starting Claude Code...' && ${cdCommand}claude --dangerously-skip-permissions"
262
+ delay 3
263
+ end tell
264
+ `;
265
+
266
+ const tempFile = join(tmpdir(), `claude_open_${Date.now()}.scpt`);
267
+ try {
268
+ writeFileSync(tempFile, openClaudeScript, 'utf8');
269
+ execSync(`osascript "${tempFile}"`, { stdio: 'pipe' });
270
+
271
+ this.logger.log('Claude opened in new terminal successfully');
272
+ return {
273
+ success: true,
274
+ message: repoPath ? `Claude opened in terminal with context: ${repoPath}` : 'Claude opened in new terminal',
275
+ method: 'applescript',
276
+ action: 'open'
277
+ };
278
+ } finally {
279
+ try {
280
+ unlinkSync(tempFile);
281
+ } catch (cleanupError) {
282
+ this.logger.log(`⚠️ Failed to cleanup temp file: ${cleanupError.message}`);
283
+ }
284
+ }
285
+ }
286
+
287
+ /**
288
+ * Open VS Code with optional repository path
289
+ * @param {string} repoPath - Optional repository path to open
290
+ * @returns {Promise<Object>} Result object with success status and details
291
+ */
292
+ async openVSCode(repoPath = null) {
293
+ try {
294
+ this.logger.log('Opening VS Code with remote debugging enabled...');
295
+
296
+ // First, check if VS Code is already running
297
+ try {
298
+ const isRunning = execSync('pgrep -x "Code"', { encoding: 'utf8', stdio: 'pipe' }).trim();
299
+ if (isRunning) {
300
+ this.logger.log('VS Code is already running - closing it to enable remote debugging...');
301
+ execSync('pkill -x "Code"', { stdio: 'pipe' });
302
+ await new Promise(resolve => setTimeout(resolve, 1000));
303
+ }
304
+ } catch (err) {
305
+ // VS Code not running, that's fine
306
+ }
307
+
308
+ // Launch VS Code with remote debugging enabled for quota detection
309
+ let command = 'open -a "Visual Studio Code" --args --remote-debugging-port=9222';
310
+ if (repoPath) {
311
+ command = `open -a "Visual Studio Code" "${repoPath}" --args --remote-debugging-port=9222`;
312
+ this.logger.log(`Opening VS Code with repository: ${repoPath}`);
313
+ }
314
+
315
+ execSync(command, { stdio: 'pipe' });
316
+
317
+ await new Promise(resolve => setTimeout(resolve, 3000));
318
+
319
+ // Verify remote debugging port is accessible
320
+ try {
321
+ const CDP = require('chrome-remote-interface');
322
+ await CDP.List({ port: 9222 });
323
+ this.logger.log('✅ VS Code remote debugging port 9222 is accessible');
324
+ } catch (cdpError) {
325
+ this.logger.log(`⚠️ Warning: VS Code remote debugging port not accessible: ${cdpError.message}`);
326
+ this.logger.log(' Waiting additional 2 seconds for VS Code to fully start...');
327
+ await new Promise(resolve => setTimeout(resolve, 2000));
328
+ }
329
+
330
+ this.logger.log('VS Code opened successfully with remote debugging');
331
+ return { success: true, message: `VS Code opened with repository: ${repoPath}`, method: 'applescript' };
332
+ } catch (error) {
333
+ this.logger.log('Error opening VS Code:', error.message);
334
+ return { success: false, error: error.message, method: 'applescript' };
335
+ }
336
+ }
337
+
338
+ /**
339
+ * Open VS Code with a specific extension installed
340
+ * @param {string} extension - Extension key (e.g., 'github-copilot', 'amazon-q')
341
+ * @param {string} repoPath - Optional repository path to open
342
+ * @returns {Promise<Object>} Result object with success status and details
343
+ */
344
+ async openVSCodeWithExtension(extension, repoPath = null) {
345
+ try {
346
+ this.logger.log(`Opening VS Code with ${extension} extension...`);
347
+
348
+ // Extension IDs mapping
349
+ const extensionIds = {
350
+ 'github-copilot': 'GitHub.copilot',
351
+ 'amazon-q': 'amazonwebservices.amazon-q-vscode',
352
+ 'continue': 'Continue.continue'
353
+ };
354
+
355
+ const extensionId = extensionIds[extension];
356
+ if (!extensionId) {
357
+ return { success: false, error: `Unknown extension: ${extension}`, method: 'applescript' };
358
+ }
359
+
360
+ // First, check if the extension is installed
361
+ try {
362
+ const checkCmd = `code --list-extensions | grep -i "${extensionId}"`;
363
+ execSync(checkCmd, { stdio: 'pipe' });
364
+ this.logger.log(`Extension ${extension} is already installed`);
365
+ } catch (checkError) {
366
+ // Extension not found, try to install it
367
+ this.logger.log(`Extension ${extension} not found, installing...`);
368
+ try {
369
+ execSync(`code --install-extension ${extensionId} --force`, { stdio: 'pipe', timeout: 60000 });
370
+ this.logger.log(`Extension ${extension} installed successfully`);
371
+ } catch (installError) {
372
+ this.logger.log(`Failed to install extension ${extension}:`, installError.message);
373
+ return { success: false, error: `Failed to install extension: ${installError.message}`, method: 'applescript' };
374
+ }
375
+ }
376
+
377
+ // First, check if VS Code is already running
378
+ try {
379
+ const isRunning = execSync('pgrep -x "Code"', { encoding: 'utf8', stdio: 'pipe' }).trim();
380
+ if (isRunning) {
381
+ this.logger.log('VS Code is already running - closing it to enable remote debugging...');
382
+ execSync('pkill -x "Code"', { stdio: 'pipe' });
383
+ await new Promise(resolve => setTimeout(resolve, 1000));
384
+ }
385
+ } catch (err) {
386
+ // VS Code not running, that's fine
387
+ }
388
+
389
+ // Open VS Code with the repository and remote debugging enabled
390
+ let command = 'open -a "Visual Studio Code" --args --remote-debugging-port=9222';
391
+ if (repoPath) {
392
+ command = `open -a "Visual Studio Code" "${repoPath}" --args --remote-debugging-port=9222`;
393
+ this.logger.log(`Opening VS Code with repository: ${repoPath}`);
394
+ }
395
+
396
+ execSync(command, { stdio: 'pipe' });
397
+ await new Promise(resolve => setTimeout(resolve, 3000));
398
+
399
+ // Verify remote debugging port is accessible
400
+ try {
401
+ const CDP = require('chrome-remote-interface');
402
+ await CDP.List({ port: 9222 });
403
+ this.logger.log('✅ VS Code remote debugging port 9222 is accessible');
404
+ } catch (cdpError) {
405
+ this.logger.log(`⚠️ Warning: VS Code remote debugging port not accessible: ${cdpError.message}`);
406
+ this.logger.log(' Waiting additional 2 seconds for VS Code to fully start...');
407
+ await new Promise(resolve => setTimeout(resolve, 2000));
408
+ }
409
+
410
+ this.logger.log(`VS Code opened successfully with ${extension} extension and remote debugging`);
411
+ return { success: true, message: `VS Code opened with ${extension} extension`, method: 'applescript' };
412
+ } catch (error) {
413
+ this.logger.log(`Error opening VS Code with ${extension}:`, error.message);
414
+ return { success: false, error: error.message, method: 'applescript' };
415
+ }
416
+ }
417
+
418
+ /**
419
+ * Open Replit Agent with optional repository path
420
+ * @param {string} repoPath - Optional repository path to open
421
+ * @returns {Promise<Object>} Result object with success status and details
422
+ */
423
+ async openReplit(repoPath = null) {
424
+ try {
425
+ this.logger.log('Opening Replit...');
426
+ this.logger.log(`Platform detected: ${process.platform}`);
427
+
428
+ // Replit typically uses web browser, so we'll open the Replit website
429
+ // If Replit has a desktop app or CLI, this can be updated
430
+ const replitUrl = repoPath
431
+ ? `https://replit.com/@replit/agent?path=${encodeURIComponent(repoPath)}`
432
+ : 'https://replit.com/@replit/agent';
433
+
434
+ const command = `open "${replitUrl}"`;
435
+ this.logger.log(`Using macOS command: ${command}`);
436
+
437
+ execSync(command, { stdio: 'pipe' });
438
+ await new Promise(resolve => setTimeout(resolve, 1000));
439
+
440
+ this.logger.log('Replit opened successfully');
441
+ return { success: true, message: 'Replit opened in browser', method: 'applescript' };
442
+ } catch (error) {
443
+ this.logger.log('Error opening Replit:', error.message);
444
+ return { success: false, error: error.message, method: 'applescript' };
445
+ }
446
+ }
447
+
448
+ /**
449
+ * Open Windsurf IDE with optional repository path
450
+ * @param {string} repoPath - Optional repository path to open
451
+ * @returns {Promise<Object>} Result object with success status and details
452
+ */
453
+ async openWindsurf(repoPath = null) {
454
+ try {
455
+ this.logger.log('Opening Windsurf...');
456
+
457
+ // Try to find Windsurf installation
458
+ const possiblePaths = [
459
+ '/Users/jesseolsen/.codeium/windsurf/bin/windsurf', // macOS - Codeium installation
460
+ '/Applications/Windsurf.app/Contents/MacOS/Windsurf', // macOS - App Store
461
+ '/usr/local/bin/windsurf', // Linux
462
+ '/opt/windsurf/windsurf' // Linux alternative
463
+ ];
464
+
465
+ let windsurfPath = possiblePaths.find(path => {
466
+ try {
467
+ const fs = require('fs');
468
+ fs.accessSync(path);
469
+ return true;
470
+ } catch {
471
+ return false;
472
+ }
473
+ });
474
+
475
+ if (!windsurfPath) {
476
+ // Try using the 'windsurf' command directly
477
+ windsurfPath = 'windsurf';
478
+ }
479
+
480
+ let command;
481
+ if (windsurfPath.includes('Windsurf.app')) {
482
+ // macOS app bundle
483
+ command = `open -a "Windsurf"`;
484
+ if (repoPath) {
485
+ command += ` "${repoPath}"`;
486
+ }
487
+ } else {
488
+ // Direct executable - use --reuse-window flag to avoid hanging when Windsurf is already running
489
+ command = `"${windsurfPath}" --reuse-window`;
490
+ if (repoPath) {
491
+ command += ` "${repoPath}"`;
492
+ }
493
+ }
494
+
495
+ this.logger.log(`Executing command: ${command}`);
496
+
497
+ // For Windsurf, we don't wait for the command to complete since it runs in background
498
+ if (windsurfPath.includes('windsurf')) {
499
+ // Use spawn to run in background
500
+ const { spawn } = require('child_process');
501
+ const windsurfProcess = spawn(windsurfPath, ['--reuse-window', repoPath], {
502
+ stdio: 'pipe',
503
+ detached: true
504
+ });
505
+
506
+ // Don't wait for completion, just give it a moment to start
507
+ await new Promise(resolve => setTimeout(resolve, 1000));
508
+ } else {
509
+ execSync(command, { stdio: 'pipe' });
510
+ // Wait a moment for Windsurf to start
511
+ await new Promise(resolve => setTimeout(resolve, 2000));
512
+ }
513
+
514
+ this.logger.log('Windsurf opened successfully');
515
+ return {
516
+ success: true,
517
+ message: repoPath ? `Windsurf opened with repository: ${repoPath}` : 'Windsurf opened successfully',
518
+ method: 'applescript'
519
+ };
520
+ } catch (error) {
521
+ this.logger.log('Error opening Windsurf:', error.message);
522
+ return {
523
+ success: false,
524
+ error: error.message,
525
+ method: 'applescript'
526
+ };
527
+ }
528
+ }
529
+
530
+ /**
531
+ * Open Google Antigravity with optional repository path
532
+ * @param {string} repoPath - Optional repository path to open
533
+ * @returns {Promise<Object>} Result object with success status and details
534
+ */
535
+ async openAntigravity(repoPath = null) {
536
+ try {
537
+ this.logger.log('Opening Google Antigravity...');
538
+
539
+ // Google Antigravity app path
540
+ const antigravityPath = '/Applications/Antigravity.app';
541
+
542
+ // Check if Antigravity is installed
543
+ try {
544
+ const fs = require('fs');
545
+ fs.accessSync(antigravityPath);
546
+ } catch {
547
+ throw new Error('Google Antigravity is not installed at /Applications/Antigravity.app');
548
+ }
549
+
550
+ let command = `open -a "Antigravity"`;
551
+ if (repoPath) {
552
+ command += ` "${repoPath}"`;
553
+ }
554
+
555
+ this.logger.log(`Executing command: ${command}`);
556
+ execSync(command, { stdio: 'pipe' });
557
+
558
+ // Wait a moment for Antigravity to start
559
+ await new Promise(resolve => setTimeout(resolve, 2000));
560
+
561
+ this.logger.log('Google Antigravity opened successfully');
562
+ return {
563
+ success: true,
564
+ message: repoPath ? `Google Antigravity opened with repository: ${repoPath}` : 'Google Antigravity opened successfully',
565
+ method: 'applescript'
566
+ };
567
+ } catch (error) {
568
+ this.logger.log('Error opening Google Antigravity:', error.message);
569
+ return {
570
+ success: false,
571
+ error: error.message,
572
+ method: 'applescript'
573
+ };
574
+ }
575
+ }
576
+
577
+ /**
578
+ * Open AWS Kiro IDE with optional repository path
579
+ * @param {string} repoPath - Optional repository path to open
580
+ * @returns {Promise<Object>} Result object with success status and details
581
+ */
582
+ async openKiro(repoPath = null) {
583
+ try {
584
+ this.logger.log('Opening AWS Kiro...');
585
+
586
+ let command = 'open -a "AWS Kiro"';
587
+ if (repoPath) {
588
+ command += ` "${repoPath}"`;
589
+ }
590
+
591
+ try {
592
+ this.logger.log(`Executing command: ${command}`);
593
+ execSync(command, { stdio: 'pipe' });
594
+ } catch (e) {
595
+ // Fallback to just "Kiro"
596
+ this.logger.log('Failed to open "AWS Kiro", trying "Kiro"...');
597
+ command = 'open -a "Kiro"';
598
+ if (repoPath) {
599
+ command += ` "${repoPath}"`;
600
+ }
601
+ execSync(command, { stdio: 'pipe' });
602
+ }
603
+
604
+ // Wait a moment for Kiro to start
605
+ await new Promise(resolve => setTimeout(resolve, 3000));
606
+
607
+ this.logger.log('AWS Kiro opened successfully');
608
+ return {
609
+ success: true,
610
+ message: repoPath ? `AWS Kiro opened with repository: ${repoPath}` : 'AWS Kiro opened successfully',
611
+ method: 'applescript'
612
+ };
613
+ } catch (error) {
614
+ this.logger.log('Error opening AWS Kiro:', error.message);
615
+ return {
616
+ success: false,
617
+ error: error.message,
618
+ method: 'applescript'
619
+ };
620
+ }
621
+ }
622
+
623
+ // Continue with sendText, closePreviousChatThread, and other methods...
624
+ // These will be split into additional files to stay under 555 lines
625
+ }
626
+
627
+ module.exports = MacOSIDEManager;