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.
- package/README.md +240 -0
- package/package.json +10 -2
- package/src/agents/Agent.js +300 -0
- package/src/agents/AgentAdditionService.js +311 -0
- package/src/agents/AgentCheckService.js +690 -0
- package/src/agents/AgentInstallationService.js +140 -0
- package/src/agents/AgentSetupService.js +467 -0
- package/src/agents/AgentStatus.js +183 -0
- package/src/agents/AgentVerificationService.js +634 -0
- package/src/agents/ConfigurationSchemaValidator.js +543 -0
- package/src/agents/EnvironmentConfigurationManager.js +602 -0
- package/src/agents/InstallationErrorHandler.js +372 -0
- package/src/agents/InstallationLog.js +363 -0
- package/src/agents/InstallationMethod.js +510 -0
- package/src/agents/InstallationOrchestrator.js +352 -0
- package/src/agents/InstallationProgressReporter.js +372 -0
- package/src/agents/InstallationRetryManager.js +322 -0
- package/src/agents/InstallationType.js +254 -0
- package/src/agents/OperationTypes.js +310 -0
- package/src/agents/PerformanceMetricsCollector.js +493 -0
- package/src/agents/SecurityValidationService.js +534 -0
- package/src/agents/VerificationTest.js +354 -0
- package/src/agents/VerificationType.js +226 -0
- package/src/agents/WindowsPermissionHandler.js +518 -0
- package/src/agents/config/AgentConfigManager.js +393 -0
- package/src/agents/config/AgentDefaultsRegistry.js +373 -0
- package/src/agents/config/ConfigValidator.js +281 -0
- package/src/agents/discovery/AgentDiscoveryService.js +707 -0
- package/src/agents/logging/AgentLogger.js +511 -0
- package/src/agents/status/AgentStatusManager.js +481 -0
- package/src/agents/storage/FileManager.js +454 -0
- package/src/agents/verification/AgentCommunicationTester.js +474 -0
- package/src/agents/verification/BaseVerifier.js +430 -0
- package/src/agents/verification/CommandVerifier.js +480 -0
- package/src/agents/verification/FileOperationVerifier.js +453 -0
- package/src/agents/verification/ResultAnalyzer.js +707 -0
- package/src/agents/verification/TestRequirementManager.js +495 -0
- package/src/agents/verification/VerificationRunner.js +433 -0
- package/src/agents/windows/BaseWindowsInstaller.js +441 -0
- package/src/agents/windows/ChocolateyInstaller.js +509 -0
- package/src/agents/windows/DirectInstaller.js +443 -0
- package/src/agents/windows/InstallerFactory.js +391 -0
- package/src/agents/windows/NpmInstaller.js +505 -0
- package/src/agents/windows/PowerShellInstaller.js +458 -0
- package/src/agents/windows/WinGetInstaller.js +390 -0
- package/src/analysis/analysis-reporter.js +132 -0
- package/src/analysis/boundary-detector.js +712 -0
- package/src/analysis/categorizer.js +340 -0
- package/src/analysis/codebase-scanner.js +384 -0
- package/src/analysis/line-counter.js +513 -0
- package/src/analysis/priority-calculator.js +679 -0
- package/src/analysis/report/analysis-report.js +250 -0
- package/src/analysis/report/package-analyzer.js +278 -0
- package/src/analysis/report/recommendation-generator.js +382 -0
- package/src/analysis/report/statistics-generator.js +515 -0
- package/src/analysis/reports/analysis-report-model.js +101 -0
- package/src/analysis/reports/recommendation-generator.js +283 -0
- package/src/analysis/reports/report-generators.js +191 -0
- package/src/analysis/reports/statistics-calculator.js +231 -0
- package/src/analysis/reports/trend-analyzer.js +219 -0
- package/src/analysis/strategy-generator.js +814 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +836 -0
- package/src/config/refactoring-config.js +307 -0
- package/src/health-tracking/json-storage.js +38 -2
- package/src/ide-integration/applescript-manager-core.js +233 -0
- package/src/ide-integration/applescript-manager.cjs +357 -28
- package/src/ide-integration/applescript-manager.js +89 -3599
- package/src/ide-integration/cdp-manager.js +306 -0
- package/src/ide-integration/claude-code-cli-manager.cjs +1 -1
- package/src/ide-integration/continuation-handler.js +337 -0
- package/src/ide-integration/ide-status-checker.js +292 -0
- package/src/ide-integration/macos-ide-manager.js +627 -0
- package/src/ide-integration/macos-text-sender.js +528 -0
- package/src/ide-integration/response-reader.js +548 -0
- package/src/ide-integration/windows-automation-manager.js +121 -0
- package/src/ide-integration/windows-ide-manager.js +373 -0
- package/src/index.cjs +25 -3
- package/src/index.js +15 -1
- package/src/llm/direct-llm-manager.cjs +90 -2
- package/src/models/compliance-report.js +538 -0
- package/src/models/file-analysis.js +681 -0
- package/src/models/refactoring-plan.js +770 -0
- package/src/monitoring/alert-system.js +834 -0
- package/src/monitoring/compliance-progress-tracker.js +437 -0
- package/src/monitoring/continuous-scan-notifications.js +661 -0
- package/src/monitoring/continuous-scanner.js +279 -0
- package/src/monitoring/file-monitor/file-analyzer.js +262 -0
- package/src/monitoring/file-monitor/file-monitor.js +237 -0
- package/src/monitoring/file-monitor/watcher.js +194 -0
- package/src/monitoring/file-monitor.js +17 -0
- package/src/monitoring/notification-manager.js +437 -0
- package/src/monitoring/scanner-core.js +368 -0
- package/src/monitoring/scanner-events.js +214 -0
- package/src/monitoring/violation-notification-system.js +515 -0
- package/src/refactoring/boundaries/cohesion-analyzer.js +316 -0
- package/src/refactoring/boundaries/extraction-result.js +285 -0
- package/src/refactoring/boundaries/extraction-strategies.js +392 -0
- package/src/refactoring/boundaries/module-boundary.js +209 -0
- package/src/refactoring/boundary/boundary-detector.js +741 -0
- package/src/refactoring/boundary/boundary-types.js +405 -0
- package/src/refactoring/boundary/extraction-strategies.js +554 -0
- package/src/refactoring/boundary-extraction-result.js +77 -0
- package/src/refactoring/boundary-extraction-strategies.js +330 -0
- package/src/refactoring/boundary-extractor.js +384 -0
- package/src/refactoring/boundary-types.js +46 -0
- package/src/refactoring/circular/circular-dependency.js +88 -0
- package/src/refactoring/circular/cycle-detection.js +147 -0
- package/src/refactoring/circular/dependency-node.js +82 -0
- package/src/refactoring/circular/dependency-result.js +107 -0
- package/src/refactoring/circular/dependency-types.js +58 -0
- package/src/refactoring/circular/graph-builder.js +213 -0
- package/src/refactoring/circular/resolution-strategy.js +72 -0
- package/src/refactoring/circular/strategy-generator.js +229 -0
- package/src/refactoring/circular-dependency-resolver-original.js +809 -0
- package/src/refactoring/circular-dependency-resolver.js +200 -0
- package/src/refactoring/code-mover.js +761 -0
- package/src/refactoring/file-splitter.js +696 -0
- package/src/refactoring/functionality-validator.js +816 -0
- package/src/refactoring/import-manager.js +774 -0
- package/src/refactoring/module-boundary.js +107 -0
- package/src/refactoring/refactoring-executor.js +672 -0
- package/src/refactoring/refactoring-rollback.js +614 -0
- package/src/refactoring/test-validator.js +631 -0
- package/src/requirement-management/default-requirement-manager.js +321 -0
- package/src/requirement-management/requirement-file-parser.js +159 -0
- package/src/requirement-management/requirement-sequencer.js +221 -0
- package/src/rui/commands/AgentCommandParser.js +600 -0
- package/src/rui/commands/AgentCommands.js +487 -0
- package/src/rui/commands/AgentResponseFormatter.js +832 -0
- package/src/scripts/verify-full-compliance.js +269 -0
- package/src/sync/sync-engine-core.js +1 -0
- package/src/sync/sync-engine-remote-handlers.js +135 -0
- package/src/task-generation/automated-task-generator.js +351 -0
- package/src/task-generation/prioritizer.js +287 -0
- package/src/task-generation/task-list-updater.js +215 -0
- package/src/task-generation/task-management-integration.js +480 -0
- package/src/task-generation/task-manager-integration.js +270 -0
- package/src/task-generation/violation-task-generator.js +474 -0
- package/src/task-management/continuous-scan-integration.js +342 -0
- package/src/timeout-management/index.js +12 -3
- package/src/timeout-management/response-time-tracker.js +167 -0
- package/src/timeout-management/timeout-calculator.js +159 -0
- package/src/timeout-management/timeout-config-manager.js +172 -0
- package/src/utils/ast-analyzer.js +417 -0
- package/src/utils/current-requirement-manager.js +276 -0
- package/src/utils/current-requirement-operations.js +472 -0
- package/src/utils/dependency-mapper.js +456 -0
- package/src/utils/download-with-progress.js +4 -2
- package/src/utils/electron-update-checker.js +4 -1
- package/src/utils/file-size-analyzer.js +272 -0
- package/src/utils/import-updater.js +280 -0
- package/src/utils/refactoring-tools.js +512 -0
- package/src/utils/report-generator.js +569 -0
- package/src/utils/reports/report-analysis.js +218 -0
- package/src/utils/reports/report-types.js +55 -0
- package/src/utils/reports/summary-generators.js +102 -0
- package/src/utils/requirement-file-management.js +157 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +392 -0
- package/src/utils/requirement-helpers/requirement-mover.js +414 -0
- package/src/utils/requirement-helpers/requirement-parser.js +326 -0
- package/src/utils/requirement-helpers/requirement-status.js +320 -0
- package/src/utils/requirement-helpers-new.js +55 -0
- package/src/utils/requirement-helpers-refactored.js +367 -0
- package/src/utils/requirement-helpers.js +291 -1191
- package/src/utils/requirement-movement-operations.js +450 -0
- package/src/utils/requirement-movement.js +312 -0
- package/src/utils/requirement-parsing-helpers.js +56 -0
- package/src/utils/requirement-statistics.js +200 -0
- package/src/utils/requirement-text-utils.js +58 -0
- package/src/utils/rollback/rollback-handlers.js +125 -0
- package/src/utils/rollback/rollback-operation.js +63 -0
- package/src/utils/rollback/rollback-recorder.js +166 -0
- package/src/utils/rollback/rollback-state-manager.js +175 -0
- package/src/utils/rollback/rollback-types.js +33 -0
- package/src/utils/rollback/rollback-utils.js +110 -0
- package/src/utils/rollback-manager-original.js +569 -0
- package/src/utils/rollback-manager.js +202 -0
- package/src/utils/smoke-test-cli.js +362 -0
- package/src/utils/smoke-test-gui.js +351 -0
- package/src/utils/smoke-test-orchestrator.js +321 -0
- package/src/utils/smoke-test-runner.js +60 -0
- package/src/utils/smoke-test-web.js +347 -0
- package/src/utils/specification-helpers.js +39 -13
- package/src/utils/specification-migration.js +97 -0
- package/src/utils/test-runner.js +579 -0
- package/src/utils/validation-framework.js +518 -0
- package/src/validation/compliance-analyzer.js +197 -0
- package/src/validation/compliance-report-generator.js +343 -0
- package/src/validation/compliance-reporter.js +711 -0
- package/src/validation/compliance-rules.js +127 -0
- package/src/validation/constitution-validator-new.js +196 -0
- package/src/validation/constitution-validator.js +17 -0
- package/src/validation/file-validators.js +170 -0
- package/src/validation/line-limit/file-analyzer.js +201 -0
- package/src/validation/line-limit/line-limit-validator.js +208 -0
- package/src/validation/line-limit/validation-result.js +144 -0
- package/src/validation/line-limit-core.js +225 -0
- package/src/validation/line-limit-reporter.js +134 -0
- package/src/validation/line-limit-result.js +125 -0
- package/src/validation/line-limit-validator.js +41 -0
- package/src/validation/metrics-calculator.js +660 -0
- package/src/sync/sync-engine-backup.js +0 -559
|
@@ -0,0 +1,548 @@
|
|
|
1
|
+
// @vibecodingmachine/core - Response Reader
|
|
2
|
+
// Cross-platform chat response reading functionality
|
|
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
|
+
* Response Reader for cross-platform chat response reading
|
|
11
|
+
* Handles response reading for all supported IDEs
|
|
12
|
+
*/
|
|
13
|
+
class ResponseReader {
|
|
14
|
+
constructor(platform, windowsManager = null) {
|
|
15
|
+
this.logger = console;
|
|
16
|
+
this.platform = platform;
|
|
17
|
+
this.windowsManager = windowsManager;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Read chat response from IDE using platform-specific methods
|
|
22
|
+
* @param {string} ide - The IDE name ('cursor', 'windsurf', 'vscode')
|
|
23
|
+
* @returns {Promise<string>} The chat response text
|
|
24
|
+
*/
|
|
25
|
+
async readChatResponse(ide) {
|
|
26
|
+
if (ide !== 'windsurf' && ide !== 'cursor' && ide !== 'vscode') {
|
|
27
|
+
return 'Error: Response reading is only supported for Cursor, Windsurf, and VS Code';
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const ideName = ide === 'windsurf' ? 'Windsurf' : ide === 'cursor' ? 'Cursor' : ide === 'vscode' ? 'VS Code' : 'Unknown';
|
|
31
|
+
this.logger.log(`${ideName} detected - using platform-specific response reading`);
|
|
32
|
+
|
|
33
|
+
try {
|
|
34
|
+
// For Cursor, try CDP first if available
|
|
35
|
+
if (ide === 'cursor' && this.platform === 'darwin') {
|
|
36
|
+
try {
|
|
37
|
+
this.logger.log('🔧 Attempting CDP method for Cursor...');
|
|
38
|
+
const cdpResponse = await this._readCursorResponseViaCDP();
|
|
39
|
+
if (cdpResponse && cdpResponse.length > 20) {
|
|
40
|
+
this.logger.log('✅ Successfully read Cursor response via CDP');
|
|
41
|
+
return cdpResponse;
|
|
42
|
+
}
|
|
43
|
+
} catch (error) {
|
|
44
|
+
this.logger.log('⚠️ CDP method failed, falling back to AppleScript:', error.message);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Try clipboard-based response detection for Cursor
|
|
49
|
+
if (ide === 'cursor' && this.platform === 'darwin') {
|
|
50
|
+
try {
|
|
51
|
+
this.logger.log('🔧 Attempting clipboard-based response detection...');
|
|
52
|
+
const clipboardResponse = await this._readCursorResponseViaClipboard();
|
|
53
|
+
if (clipboardResponse && clipboardResponse.length > 20) {
|
|
54
|
+
this.logger.log('✅ Successfully read Cursor response via clipboard');
|
|
55
|
+
return clipboardResponse;
|
|
56
|
+
}
|
|
57
|
+
} catch (error) {
|
|
58
|
+
this.logger.log('⚠️ Clipboard method failed, falling back to AppleScript:', error.message);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Use platform-specific reading methods
|
|
63
|
+
if (this.platform === 'darwin') {
|
|
64
|
+
return await this._readResponseMacOS(ide);
|
|
65
|
+
} else if (this.platform === 'win32' && this.windowsManager) {
|
|
66
|
+
return await this.windowsManager.readChatResponse(ide);
|
|
67
|
+
} else {
|
|
68
|
+
return `Error: Platform ${this.platform} not supported for response reading`;
|
|
69
|
+
}
|
|
70
|
+
} catch (error) {
|
|
71
|
+
this.logger.log('Response reading failed:', error.message);
|
|
72
|
+
return 'Error: Could not read response via platform-specific methods';
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Read response using macOS AppleScript methods
|
|
78
|
+
* @param {string} ide - IDE name
|
|
79
|
+
* @returns {Promise<string>} Response text
|
|
80
|
+
*/
|
|
81
|
+
async _readResponseMacOS(ide) {
|
|
82
|
+
let appleScript;
|
|
83
|
+
|
|
84
|
+
if (ide === 'cursor') {
|
|
85
|
+
appleScript = this._generateCursorReaderScript();
|
|
86
|
+
} else if (ide === 'windsurf') {
|
|
87
|
+
appleScript = this._generateWindsurfReaderScript();
|
|
88
|
+
} else if (ide === 'vscode') {
|
|
89
|
+
appleScript = this._generateVSCodeReaderScript();
|
|
90
|
+
} else {
|
|
91
|
+
return `Error: AppleScript reading is not supported for IDE: ${ide}`;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
try {
|
|
95
|
+
const result = execSync(`osascript -e '${appleScript}'`, { stdio: 'pipe', encoding: 'utf8' });
|
|
96
|
+
this.logger.log(`Successfully read ${ide} response via AppleScript`);
|
|
97
|
+
this.logger.log('📖 AppleScript result:', result);
|
|
98
|
+
this.logger.log('📏 Result length:', result.length);
|
|
99
|
+
this.logger.log('🔍 Result preview:', result.substring(0, 200));
|
|
100
|
+
|
|
101
|
+
// Check if result is just diagnostic information
|
|
102
|
+
const isDiagnosticResult = result.includes('DEBUG:') ||
|
|
103
|
+
result.includes('diagnostic') ||
|
|
104
|
+
result.includes('No chat content found') ||
|
|
105
|
+
result.includes('Text areas found: 0') ||
|
|
106
|
+
result.includes('Static text found:') ||
|
|
107
|
+
result.includes('Window count:') ||
|
|
108
|
+
result.includes('Sample text:') ||
|
|
109
|
+
result.includes('Could not read') ||
|
|
110
|
+
result.includes('No readable text content detected');
|
|
111
|
+
|
|
112
|
+
if (isDiagnosticResult) {
|
|
113
|
+
this.logger.log('⚠️ AppleScript returned diagnostic info, all methods failed...');
|
|
114
|
+
return `Unable to read ${ide} response - all methods failed. AppleScript diagnostic: ${result.substring(0, 200)}...`;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
return result.trim();
|
|
118
|
+
} catch (error) {
|
|
119
|
+
this.logger.log('AppleScript reading failed:', error.message);
|
|
120
|
+
return 'Error: Could not read response via AppleScript';
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Generate AppleScript for reading Cursor responses
|
|
126
|
+
* @returns {string} AppleScript code
|
|
127
|
+
*/
|
|
128
|
+
_generateCursorReaderScript() {
|
|
129
|
+
return `
|
|
130
|
+
tell application "System Events"
|
|
131
|
+
tell process "Cursor"
|
|
132
|
+
set frontmost to true
|
|
133
|
+
delay 1
|
|
134
|
+
|
|
135
|
+
-- Method 1: Try to get text from web view content (most likely location)
|
|
136
|
+
try
|
|
137
|
+
set webViewGroups to group of window 1
|
|
138
|
+
set responseText to ""
|
|
139
|
+
repeat with grp in webViewGroups
|
|
140
|
+
try
|
|
141
|
+
-- Look for text areas within groups (web view content)
|
|
142
|
+
set textAreas to text area of grp
|
|
143
|
+
repeat with txtArea in textAreas
|
|
144
|
+
try
|
|
145
|
+
set textValue to value of txtArea
|
|
146
|
+
if textValue is not "" and textValue is not missing value then
|
|
147
|
+
set responseText to responseText & textValue & "\\n"
|
|
148
|
+
end if
|
|
149
|
+
on error
|
|
150
|
+
-- Continue to next text area
|
|
151
|
+
end try
|
|
152
|
+
end repeat
|
|
153
|
+
|
|
154
|
+
-- Look for static text within groups
|
|
155
|
+
set staticTexts to static text of grp
|
|
156
|
+
repeat with txt in staticTexts
|
|
157
|
+
try
|
|
158
|
+
set textValue to value of txt
|
|
159
|
+
if textValue is not "" and textValue is not missing value then
|
|
160
|
+
set responseText to responseText & textValue & "\\n"
|
|
161
|
+
end if
|
|
162
|
+
on error
|
|
163
|
+
-- Continue to next static text
|
|
164
|
+
end try
|
|
165
|
+
end repeat
|
|
166
|
+
on error
|
|
167
|
+
-- Continue to next group
|
|
168
|
+
end try
|
|
169
|
+
end repeat
|
|
170
|
+
if responseText is not "" then
|
|
171
|
+
return responseText
|
|
172
|
+
end if
|
|
173
|
+
on error
|
|
174
|
+
-- Continue to next method
|
|
175
|
+
end try
|
|
176
|
+
|
|
177
|
+
-- Method 2: Try to get text from all text areas in window
|
|
178
|
+
try
|
|
179
|
+
set allTextAreas to text area of window 1
|
|
180
|
+
set responseText to ""
|
|
181
|
+
repeat with txtArea in allTextAreas
|
|
182
|
+
try
|
|
183
|
+
set textValue to value of txtArea
|
|
184
|
+
if textValue is not "" and textValue is not missing value then
|
|
185
|
+
set responseText to responseText & textValue & "\\n"
|
|
186
|
+
end if
|
|
187
|
+
on error
|
|
188
|
+
-- Continue to next text area
|
|
189
|
+
end try
|
|
190
|
+
end repeat
|
|
191
|
+
if responseText is not "" then
|
|
192
|
+
return responseText
|
|
193
|
+
end if
|
|
194
|
+
on error
|
|
195
|
+
-- Continue to next method
|
|
196
|
+
end try
|
|
197
|
+
|
|
198
|
+
-- Method 3: Try to get text from all static text elements
|
|
199
|
+
try
|
|
200
|
+
set allTexts to static text of window 1
|
|
201
|
+
set responseText to ""
|
|
202
|
+
repeat with txt in allTexts
|
|
203
|
+
try
|
|
204
|
+
set textValue to value of txt
|
|
205
|
+
if textValue is not "" and textValue is not missing value then
|
|
206
|
+
set responseText to responseText & textValue & "\\n"
|
|
207
|
+
end if
|
|
208
|
+
on error
|
|
209
|
+
-- Continue to next text element
|
|
210
|
+
end try
|
|
211
|
+
end repeat
|
|
212
|
+
if responseText is not "" then
|
|
213
|
+
return responseText
|
|
214
|
+
end if
|
|
215
|
+
on error
|
|
216
|
+
-- Continue to next method
|
|
217
|
+
end try
|
|
218
|
+
|
|
219
|
+
-- Method 4: Try clipboard approach (select all and copy)
|
|
220
|
+
try
|
|
221
|
+
key code 0 using {command down}
|
|
222
|
+
delay 0.5
|
|
223
|
+
key code 8 using {command down}
|
|
224
|
+
delay 0.5
|
|
225
|
+
set clipboardText to (the clipboard)
|
|
226
|
+
if clipboardText is not "" then
|
|
227
|
+
return clipboardText
|
|
228
|
+
end if
|
|
229
|
+
on error
|
|
230
|
+
-- Continue to next method
|
|
231
|
+
end try
|
|
232
|
+
|
|
233
|
+
-- Method 5: Return diagnostic information
|
|
234
|
+
return "No chat content found in Cursor - diagnostic info: Window exists but no readable text content detected. This may be because Cursor's chat interface is in a web view that AppleScript cannot access directly."
|
|
235
|
+
end tell
|
|
236
|
+
end tell
|
|
237
|
+
`;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
/**
|
|
241
|
+
* Generate AppleScript for reading Windsurf responses
|
|
242
|
+
* @returns {string} AppleScript code
|
|
243
|
+
*/
|
|
244
|
+
_generateWindsurfReaderScript() {
|
|
245
|
+
return `
|
|
246
|
+
tell application "System Events"
|
|
247
|
+
tell process "Windsurf"
|
|
248
|
+
set frontmost to true
|
|
249
|
+
delay 1
|
|
250
|
+
|
|
251
|
+
-- Method 1: Try to get all static text from window
|
|
252
|
+
try
|
|
253
|
+
set allText to value of static text of window 1
|
|
254
|
+
if allText is not "" then
|
|
255
|
+
return allText
|
|
256
|
+
end if
|
|
257
|
+
on error
|
|
258
|
+
-- Continue to next method
|
|
259
|
+
end try
|
|
260
|
+
|
|
261
|
+
-- Method 2: Try to get text from groups
|
|
262
|
+
try
|
|
263
|
+
set groups to group of window 1
|
|
264
|
+
set responseText to ""
|
|
265
|
+
repeat with grp in groups
|
|
266
|
+
try
|
|
267
|
+
set groupText to value of static text of grp
|
|
268
|
+
if groupText is not "" then
|
|
269
|
+
set responseText to responseText & groupText & "\\n"
|
|
270
|
+
end if
|
|
271
|
+
on error
|
|
272
|
+
-- Continue to next group
|
|
273
|
+
end try
|
|
274
|
+
end repeat
|
|
275
|
+
if responseText is not "" then
|
|
276
|
+
return responseText
|
|
277
|
+
end if
|
|
278
|
+
on error
|
|
279
|
+
-- Continue to next method
|
|
280
|
+
end try
|
|
281
|
+
|
|
282
|
+
-- Method 3: Try clipboard approach
|
|
283
|
+
try
|
|
284
|
+
key code 0 using {command down}
|
|
285
|
+
delay 0.5
|
|
286
|
+
key code 8 using {command down}
|
|
287
|
+
delay 0.5
|
|
288
|
+
set clipboardText to (the clipboard)
|
|
289
|
+
if clipboardText is not "" then
|
|
290
|
+
return clipboardText
|
|
291
|
+
end if
|
|
292
|
+
on error
|
|
293
|
+
-- Continue to next method
|
|
294
|
+
end try
|
|
295
|
+
|
|
296
|
+
-- Method 4: Return placeholder
|
|
297
|
+
return "No chat content found in Windsurf"
|
|
298
|
+
end tell
|
|
299
|
+
end tell
|
|
300
|
+
`;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
/**
|
|
304
|
+
* Generate AppleScript for reading VS Code responses
|
|
305
|
+
* @returns {string} AppleScript code
|
|
306
|
+
*/
|
|
307
|
+
_generateVSCodeReaderScript() {
|
|
308
|
+
return `
|
|
309
|
+
tell application "System Events"
|
|
310
|
+
tell process "Visual Studio Code"
|
|
311
|
+
set frontmost to true
|
|
312
|
+
delay 1
|
|
313
|
+
|
|
314
|
+
-- Method 1: Try to get all static text from window (GitHub Copilot Chat)
|
|
315
|
+
try
|
|
316
|
+
set allText to value of static text of window 1
|
|
317
|
+
if allText is not "" then
|
|
318
|
+
return allText
|
|
319
|
+
end if
|
|
320
|
+
on error
|
|
321
|
+
-- Continue to next method
|
|
322
|
+
end try
|
|
323
|
+
|
|
324
|
+
-- Method 2: Try to get text from groups (chat panels)
|
|
325
|
+
try
|
|
326
|
+
set groups to group of window 1
|
|
327
|
+
set responseText to ""
|
|
328
|
+
repeat with grp in groups
|
|
329
|
+
try
|
|
330
|
+
set groupText to value of static text of grp
|
|
331
|
+
if groupText is not "" then
|
|
332
|
+
set responseText to responseText & groupText & "\\n"
|
|
333
|
+
end if
|
|
334
|
+
on error
|
|
335
|
+
-- Continue to next group
|
|
336
|
+
end try
|
|
337
|
+
end repeat
|
|
338
|
+
if responseText is not "" then
|
|
339
|
+
return responseText
|
|
340
|
+
end if
|
|
341
|
+
on error
|
|
342
|
+
-- Continue to next method
|
|
343
|
+
end try
|
|
344
|
+
|
|
345
|
+
-- Method 3: Try to get text from text areas (chat input/output areas)
|
|
346
|
+
try
|
|
347
|
+
set textAreas to text area of window 1
|
|
348
|
+
set responseText to ""
|
|
349
|
+
repeat with txtArea in textAreas
|
|
350
|
+
try
|
|
351
|
+
set textValue to value of txtArea
|
|
352
|
+
if textValue is not "" and textValue is not missing value then
|
|
353
|
+
set responseText to responseText & textValue & "\\n"
|
|
354
|
+
end if
|
|
355
|
+
on error
|
|
356
|
+
-- Continue to next text area
|
|
357
|
+
end try
|
|
358
|
+
end repeat
|
|
359
|
+
if responseText is not "" then
|
|
360
|
+
return responseText
|
|
361
|
+
end if
|
|
362
|
+
on error
|
|
363
|
+
-- Continue to next method
|
|
364
|
+
end try
|
|
365
|
+
|
|
366
|
+
-- Method 4: Try clipboard approach (select all chat content and copy)
|
|
367
|
+
try
|
|
368
|
+
key code 0 using {command down}
|
|
369
|
+
delay 0.5
|
|
370
|
+
key code 8 using {command down}
|
|
371
|
+
delay 0.5
|
|
372
|
+
set clipboardText to (the clipboard)
|
|
373
|
+
if clipboardText is not "" then
|
|
374
|
+
return clipboardText
|
|
375
|
+
end if
|
|
376
|
+
on error
|
|
377
|
+
-- Continue to next method
|
|
378
|
+
end try
|
|
379
|
+
|
|
380
|
+
-- Method 5: Return placeholder
|
|
381
|
+
return "No chat content found in VS Code - ensure GitHub Copilot Chat or Continue extension is active"
|
|
382
|
+
end tell
|
|
383
|
+
end tell
|
|
384
|
+
`;
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
/**
|
|
388
|
+
* Read Cursor response via Chrome DevTools Protocol (CDP)
|
|
389
|
+
* @returns {Promise<string>} The chat response text
|
|
390
|
+
*/
|
|
391
|
+
async _readCursorResponseViaCDP() {
|
|
392
|
+
try {
|
|
393
|
+
this.logger.log('🔧 Attempting CDP connection to Cursor on port 9225...');
|
|
394
|
+
|
|
395
|
+
// Import CDP dynamically to avoid issues in VSCode extension context
|
|
396
|
+
const CDP = require('chrome-remote-interface');
|
|
397
|
+
|
|
398
|
+
// List available targets
|
|
399
|
+
const targets = await CDP.List({ port: 9225 });
|
|
400
|
+
this.logger.log(`🔧 Found ${targets.length} CDP targets`);
|
|
401
|
+
|
|
402
|
+
// Find the main workbench target (not settings)
|
|
403
|
+
const workbench = targets.find(t =>
|
|
404
|
+
t.title !== 'Cursor Settings' &&
|
|
405
|
+
t.type === 'page' &&
|
|
406
|
+
t.url && t.url.includes('workbench')
|
|
407
|
+
) || targets[0];
|
|
408
|
+
|
|
409
|
+
if (!workbench) {
|
|
410
|
+
throw new Error('No suitable Cursor workbench target found');
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
this.logger.log(`🔧 Connecting to target: ${workbench.title}`);
|
|
414
|
+
|
|
415
|
+
// Connect to the target
|
|
416
|
+
const client = await CDP({ port: 9225, target: workbench });
|
|
417
|
+
const { Runtime, DOM } = client;
|
|
418
|
+
|
|
419
|
+
// Enable required domains
|
|
420
|
+
await Runtime.enable();
|
|
421
|
+
await DOM.enable();
|
|
422
|
+
|
|
423
|
+
this.logger.log('🔧 CDP connection established, searching for chat content...');
|
|
424
|
+
|
|
425
|
+
// Try multiple selectors to find chat content
|
|
426
|
+
const selectors = [
|
|
427
|
+
'.chat-content',
|
|
428
|
+
'.chat-messages',
|
|
429
|
+
'.response-content',
|
|
430
|
+
'.ai-response',
|
|
431
|
+
'.message-content',
|
|
432
|
+
'[data-testid="chat-message"]',
|
|
433
|
+
'.markdown-content',
|
|
434
|
+
'.prose',
|
|
435
|
+
'.chat-panel',
|
|
436
|
+
'.sidebar-panel'
|
|
437
|
+
];
|
|
438
|
+
|
|
439
|
+
for (const selector of selectors) {
|
|
440
|
+
try {
|
|
441
|
+
this.logger.log(`🔧 Trying selector: ${selector}`);
|
|
442
|
+
|
|
443
|
+
// Get document root
|
|
444
|
+
const { root } = await DOM.getDocument();
|
|
445
|
+
|
|
446
|
+
// Search for elements with selector
|
|
447
|
+
const { nodeIds } = await DOM.querySelectorAll({ nodeId: root.nodeId, selector });
|
|
448
|
+
|
|
449
|
+
if (nodeIds.length > 0) {
|
|
450
|
+
this.logger.log(`🔧 Found ${nodeIds.length} elements with selector: ${selector}`);
|
|
451
|
+
|
|
452
|
+
// Get text content from first matching element
|
|
453
|
+
const { nodeId } = await DOM.describeNode({ nodeId: nodeIds[0] });
|
|
454
|
+
const { outerHTML } = await DOM.getOuterHTML({ nodeId });
|
|
455
|
+
|
|
456
|
+
// Extract text content (remove HTML tags)
|
|
457
|
+
const textContent = outerHTML.replace(/<[^>]*>/g, ' ').replace(/\s+/g, ' ').trim();
|
|
458
|
+
|
|
459
|
+
if (textContent && textContent.length > 20) {
|
|
460
|
+
this.logger.log(`✅ Successfully extracted chat content via CDP: ${textContent.substring(0, 100)}...`);
|
|
461
|
+
await client.close();
|
|
462
|
+
return textContent;
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
} catch (error) {
|
|
466
|
+
this.logger.log(`⚠️ Selector ${selector} failed: ${error.message}`);
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
await client.close();
|
|
471
|
+
throw new Error('No chat content found via CDP');
|
|
472
|
+
} catch (error) {
|
|
473
|
+
this.logger.log(`❌ CDP method failed: ${error.message}`);
|
|
474
|
+
throw error;
|
|
475
|
+
}
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Read Cursor response via clipboard (select all and copy)
|
|
480
|
+
* @returns {Promise<string>} The chat response text
|
|
481
|
+
*/
|
|
482
|
+
async _readCursorResponseViaClipboard() {
|
|
483
|
+
try {
|
|
484
|
+
this.logger.log('🔧 Attempting clipboard-based response detection...');
|
|
485
|
+
|
|
486
|
+
// AppleScript to select all content in Cursor and copy to clipboard
|
|
487
|
+
const clipboardScript = `
|
|
488
|
+
tell application "System Events"
|
|
489
|
+
tell process "Cursor"
|
|
490
|
+
set frontmost to true
|
|
491
|
+
delay 1
|
|
492
|
+
|
|
493
|
+
-- Try to focus on the chat area first without selecting all content
|
|
494
|
+
try
|
|
495
|
+
-- Just try to copy without selecting all (safer approach)
|
|
496
|
+
key code 8 using {command down} -- Cmd+C to copy
|
|
497
|
+
delay 0.5
|
|
498
|
+
on error
|
|
499
|
+
-- If that fails, return empty response
|
|
500
|
+
return ""
|
|
501
|
+
end try
|
|
502
|
+
end tell
|
|
503
|
+
end tell
|
|
504
|
+
`;
|
|
505
|
+
|
|
506
|
+
const tempFile = join(tmpdir(), `clipboard_${Date.now()}.scpt`);
|
|
507
|
+
try {
|
|
508
|
+
writeFileSync(tempFile, clipboardScript, 'utf8');
|
|
509
|
+
execSync(`osascript "${tempFile}"`, { stdio: 'pipe' });
|
|
510
|
+
} finally {
|
|
511
|
+
try {
|
|
512
|
+
unlinkSync(tempFile);
|
|
513
|
+
} catch (cleanupError) {
|
|
514
|
+
this.logger.log(`⚠️ Failed to cleanup clipboard temp file: ${cleanupError.message}`);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
// Read from clipboard
|
|
519
|
+
const clipboardScript2 = `
|
|
520
|
+
clipboard
|
|
521
|
+
`;
|
|
522
|
+
|
|
523
|
+
const tempFile2 = join(tmpdir(), `clipboard_read_${Date.now()}.scpt`);
|
|
524
|
+
try {
|
|
525
|
+
writeFileSync(tempFile2, clipboardScript2, 'utf8');
|
|
526
|
+
const clipboardContent = execSync(`osascript "${tempFile2}"`, { stdio: 'pipe', encoding: 'utf8' });
|
|
527
|
+
|
|
528
|
+
if (clipboardContent && clipboardContent.trim().length > 20) {
|
|
529
|
+
this.logger.log(`✅ Successfully read clipboard content: ${clipboardContent.substring(0, 100)}...`);
|
|
530
|
+
return clipboardContent.trim();
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
throw new Error('Clipboard content is empty or too short');
|
|
534
|
+
} finally {
|
|
535
|
+
try {
|
|
536
|
+
unlinkSync(tempFile2);
|
|
537
|
+
} catch (cleanupError) {
|
|
538
|
+
this.logger.log(`⚠️ Failed to cleanup clipboard read temp file: ${cleanupError.message}`);
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
} catch (error) {
|
|
542
|
+
this.logger.log(`❌ Clipboard method failed: ${error.message}`);
|
|
543
|
+
throw error;
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
module.exports = ResponseReader;
|
|
@@ -257,6 +257,127 @@ try {
|
|
|
257
257
|
};
|
|
258
258
|
}
|
|
259
259
|
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Open VS Code on Windows
|
|
263
|
+
* @param {string} repoPath - Optional repository path to open
|
|
264
|
+
* @returns {Promise<Object>} Result object with success status and details
|
|
265
|
+
*/
|
|
266
|
+
async openVSCode(repoPath = null) {
|
|
267
|
+
try {
|
|
268
|
+
this.logger.log('🔧 Windows: Opening VS Code...');
|
|
269
|
+
|
|
270
|
+
let command = 'code';
|
|
271
|
+
if (repoPath) {
|
|
272
|
+
command += ` "${repoPath}"`;
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Try to open VS Code
|
|
276
|
+
execSync(command, { stdio: 'pipe' });
|
|
277
|
+
|
|
278
|
+
// Wait for VS Code to start
|
|
279
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
280
|
+
|
|
281
|
+
this.logger.log('✅ Windows: VS Code opened successfully');
|
|
282
|
+
return {
|
|
283
|
+
success: true,
|
|
284
|
+
message: repoPath ? `VS Code opened with repository: ${repoPath}` : 'VS Code opened successfully',
|
|
285
|
+
method: 'windows-command'
|
|
286
|
+
};
|
|
287
|
+
} catch (error) {
|
|
288
|
+
this.logger.error('❌ Windows: Error opening VS Code:', error.message);
|
|
289
|
+
return {
|
|
290
|
+
success: false,
|
|
291
|
+
error: error.message,
|
|
292
|
+
method: 'windows-command'
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
/**
|
|
298
|
+
* Open AWS Kiro IDE on Windows
|
|
299
|
+
* @param {string} repoPath - Optional repository path to open
|
|
300
|
+
* @returns {Promise<Object>} Result object with success status and details
|
|
301
|
+
*/
|
|
302
|
+
async openKiro(repoPath = null) {
|
|
303
|
+
try {
|
|
304
|
+
this.logger.log('🔧 Windows: Opening AWS Kiro...');
|
|
305
|
+
|
|
306
|
+
// Try different possible Kiro executable names/paths on Windows
|
|
307
|
+
const possibleCommands = [
|
|
308
|
+
'kiro',
|
|
309
|
+
'aws-kiro',
|
|
310
|
+
'"C:\\Program Files\\AWS\\Kiro\\kiro.exe"',
|
|
311
|
+
'"C:\\Program Files (x86)\\AWS\\Kiro\\kiro.exe"',
|
|
312
|
+
'"C:\\Users\\' + (require('os').userInfo().username) + '\\AppData\\Local\\Programs\\Kiro\\kiro.exe"'
|
|
313
|
+
];
|
|
314
|
+
|
|
315
|
+
let command = possibleCommands[0]; // Default to 'kiro'
|
|
316
|
+
if (repoPath) {
|
|
317
|
+
command += ` "${repoPath}"`;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
let lastError;
|
|
321
|
+
for (const cmd of possibleCommands) {
|
|
322
|
+
try {
|
|
323
|
+
const testCommand = repoPath ? `${cmd} "${repoPath}"` : cmd;
|
|
324
|
+
this.logger.log(`🔧 Windows: Trying command: ${testCommand}`);
|
|
325
|
+
|
|
326
|
+
// Test if the command exists by trying to run it with --version or similar
|
|
327
|
+
try {
|
|
328
|
+
execSync(`${cmd} --version`, { stdio: 'pipe', timeout: 5000 });
|
|
329
|
+
} catch (versionError) {
|
|
330
|
+
// If --version doesn't work, try just running the command
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
// Try to open Kiro
|
|
334
|
+
execSync(testCommand, { stdio: 'pipe', timeout: 10000 });
|
|
335
|
+
|
|
336
|
+
// Wait for Kiro to start
|
|
337
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
338
|
+
|
|
339
|
+
this.logger.log('✅ Windows: AWS Kiro opened successfully');
|
|
340
|
+
return {
|
|
341
|
+
success: true,
|
|
342
|
+
message: repoPath ? `AWS Kiro opened with repository: ${repoPath}` : 'AWS Kiro opened successfully',
|
|
343
|
+
method: 'windows-command',
|
|
344
|
+
command: testCommand
|
|
345
|
+
};
|
|
346
|
+
} catch (error) {
|
|
347
|
+
lastError = error;
|
|
348
|
+
this.logger.log(`⚠️ Windows: Failed to open Kiro with command: ${cmd} - ${error.message}`);
|
|
349
|
+
continue;
|
|
350
|
+
}
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// If all commands failed, try using 'start' command as fallback
|
|
354
|
+
try {
|
|
355
|
+
this.logger.log('🔧 Windows: Trying fallback with start command...');
|
|
356
|
+
const fallbackCommand = repoPath
|
|
357
|
+
? `start kiro "${repoPath}"`
|
|
358
|
+
: 'start kiro';
|
|
359
|
+
|
|
360
|
+
execSync(fallbackCommand, { stdio: 'pipe', timeout: 10000 });
|
|
361
|
+
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
362
|
+
|
|
363
|
+
this.logger.log('✅ Windows: AWS Kiro opened via start command');
|
|
364
|
+
return {
|
|
365
|
+
success: true,
|
|
366
|
+
message: repoPath ? `AWS Kiro opened with repository: ${repoPath}` : 'AWS Kiro opened successfully',
|
|
367
|
+
method: 'windows-start-command'
|
|
368
|
+
};
|
|
369
|
+
} catch (fallbackError) {
|
|
370
|
+
throw lastError || fallbackError;
|
|
371
|
+
}
|
|
372
|
+
} catch (error) {
|
|
373
|
+
this.logger.error('❌ Windows: Error opening AWS Kiro:', error.message);
|
|
374
|
+
return {
|
|
375
|
+
success: false,
|
|
376
|
+
error: `Windows automation error: ${error.message}`,
|
|
377
|
+
method: 'windows-command'
|
|
378
|
+
};
|
|
379
|
+
}
|
|
380
|
+
}
|
|
260
381
|
}
|
|
261
382
|
|
|
262
383
|
module.exports = WindowsAutomationManager;
|