vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850
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/package.json +1 -1
- package/src/agents/AgentCheckDiscoveryService.js +180 -0
- package/src/agents/AgentCheckService.js +18 -261
- package/src/agents/AgentCheckStatisticsService.js +195 -0
- package/src/agents/EnvironmentConfigurationManager.js +31 -380
- package/src/agents/InstallationType.js +19 -6
- package/src/agents/SimpleAgentCheckService.js +472 -0
- package/src/agents/config-managers/ConfigUtils.js +72 -0
- package/src/agents/config-managers/DefaultConfig.js +58 -0
- package/src/agents/config-managers/EnvVarLoader.js +66 -0
- package/src/agents/config-managers/FileConfigLoader.js +124 -0
- package/src/agents/config-managers/TypeConverters.js +61 -0
- package/src/agents/config-managers/VariableMappings.js +92 -0
- package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
- package/src/agents/discovery/AgentDiscoveryService.js +29 -403
- package/src/agents/discovery/agent-validator.js +262 -0
- package/src/agents/discovery/discovery-results.js +176 -0
- package/src/agents/discovery/discovery-scanner.js +268 -0
- package/src/agents/discovery/discovery-utils.js +161 -0
- package/src/agents/discovery/executable-analyzer.js +290 -0
- package/src/agents/discovery/history-manager.js +310 -0
- package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
- package/src/agents/verification/ResultAnalyzer.js +30 -431
- package/src/agents/verification/analysis-utils.js +310 -0
- package/src/agents/verification/batch-analyzer.js +440 -0
- package/src/agents/verification/pattern-recognizer.js +369 -0
- package/src/agents/verification/report-generator.js +320 -0
- package/src/agents/verification/test-analyzer.js +290 -0
- package/src/agents/windows/InstallerFactory.js +4 -0
- package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
- package/src/analysis/analysis-engine.js +314 -0
- package/src/analysis/ast-analyzer.js +342 -0
- package/src/analysis/boundary-detector-refactored.js +378 -0
- package/src/analysis/boundary-detector.js +200 -603
- package/src/analysis/boundary-scanner.js +609 -0
- package/src/analysis/boundary-types.js +118 -0
- package/src/analysis/boundary-utils.js +293 -0
- package/src/analysis/deadline-priority-calculator.js +18 -0
- package/src/analysis/detection-methods.js +347 -0
- package/src/analysis/importance-priority-calculator.js +18 -0
- package/src/analysis/priority/factor-calculators.js +204 -0
- package/src/analysis/priority/factor-helpers.js +71 -0
- package/src/analysis/priority/priority-constants.js +73 -0
- package/src/analysis/priority/priority-factor-calculators.js +301 -0
- package/src/analysis/priority/reasons-generator.js +44 -0
- package/src/analysis/priority-calculator.js +15 -580
- package/src/analysis/strategy-generator.js +16 -66
- package/src/analysis/type-priority-calculator.js +18 -0
- package/src/analysis/urgency-priority-calculator.js +18 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
- package/src/commands/disable-requirement.js +60 -0
- package/src/commands/disable-spec.js +60 -0
- package/src/commands/enable-requirement.js +60 -0
- package/src/commands/enable-spec.js +60 -0
- package/src/commands/registry.js +1 -6
- package/src/commands/requirements.js +8 -2
- package/src/ide-integration/applescript-manager.cjs +9 -24
- package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
- package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
- package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
- package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
- package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
- package/src/ide-integration/cdp-manager.js +28 -573
- package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
- package/src/ide-integration/ide-openers/claude-opener.js +171 -0
- package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
- package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
- package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
- package/src/ide-integration/macos-ide-manager.js +20 -582
- package/src/ide-integration/macos-quota-checker.js +164 -0
- package/src/ide-integration/macos-text-sender.js +19 -38
- package/src/ide-integration/provider-manager.cjs +52 -7
- package/src/index.cjs +6 -0
- package/src/index.js +10 -0
- package/src/llm/direct-llm-manager.cjs +501 -0
- package/src/localization/translations/en-part1.js +363 -0
- package/src/localization/translations/en-part2.js +320 -0
- package/src/localization/translations/en.js +4 -687
- package/src/localization/translations/es-part1.js +363 -0
- package/src/localization/translations/es-part2.js +320 -0
- package/src/localization/translations/es.js +4 -688
- package/src/models/file-analysis-collection.js +139 -0
- package/src/models/file-analysis-metrics.js +50 -0
- package/src/models/file-analysis.js +15 -262
- package/src/models/plan-manager.js +410 -0
- package/src/models/refactoring-models.js +380 -0
- package/src/models/refactoring-plan-refactored.js +81 -0
- package/src/models/refactoring-plan.js +2 -663
- package/src/monitoring/alert-system.js +4 -45
- package/src/monitoring/continuous-scan-notifications.js +37 -191
- package/src/monitoring/notification-handlers/base-handler.js +58 -0
- package/src/monitoring/notification-handlers/error-handler.js +36 -0
- package/src/monitoring/notification-handlers/index.js +21 -0
- package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
- package/src/monitoring/notification-handlers/progress-handler.js +48 -0
- package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
- package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
- package/src/provider-registry.js +8 -0
- package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
- package/src/refactoring/boundary/boundary-detector.js +26 -596
- package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
- package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
- package/src/refactoring/boundary/detectors/class-detector.js +247 -0
- package/src/refactoring/boundary/detectors/config-detector.js +270 -0
- package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
- package/src/refactoring/boundary/detectors/function-detector.js +248 -0
- package/src/refactoring/boundary/detectors/module-detector.js +249 -0
- package/src/refactoring/boundary/detectors/object-detector.js +247 -0
- package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
- package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
- package/src/refactoring/circular-dependency-resolver-original.js +16 -76
- package/src/refactoring/code-mover-refactored.js +309 -0
- package/src/refactoring/code-mover.js +48 -355
- package/src/refactoring/execution-status.js +18 -0
- package/src/refactoring/execution-strategies.js +172 -0
- package/src/refactoring/file-splitter-core.js +568 -0
- package/src/refactoring/file-splitter-types.js +136 -0
- package/src/refactoring/file-splitter.js +2 -682
- package/src/refactoring/functionality-validator.js +11 -51
- package/src/refactoring/import-manager-refactored.js +385 -0
- package/src/refactoring/import-manager.js +112 -487
- package/src/refactoring/import-models.js +189 -0
- package/src/refactoring/import-parser.js +306 -0
- package/src/refactoring/move-executor.js +431 -0
- package/src/refactoring/move-utils.js +368 -0
- package/src/refactoring/operation-executor.js +76 -0
- package/src/refactoring/plan-creator.js +36 -0
- package/src/refactoring/plan-executor.js +143 -0
- package/src/refactoring/plan-validator.js +68 -0
- package/src/refactoring/refactoring-executor-result.js +70 -0
- package/src/refactoring/refactoring-executor.js +34 -569
- package/src/refactoring/refactoring-operation.js +94 -0
- package/src/refactoring/refactoring-plan.js +69 -0
- package/src/refactoring/refactoring-rollback.js +22 -527
- package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
- package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
- package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
- package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
- package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
- package/src/refactoring/test-validator.js +32 -448
- package/src/refactoring/validation/baseline-runner.js +71 -0
- package/src/refactoring/validation/report-generator.js +136 -0
- package/src/refactoring/validation/result-comparator.js +92 -0
- package/src/refactoring/validation/test-suite.js +59 -0
- package/src/refactoring/validation/test-validation-result.js +83 -0
- package/src/refactoring/validation/validation-runner.js +95 -0
- package/src/refactoring/validation/validation-status.js +18 -0
- package/src/rui/commands/AgentCommandParser.js +60 -369
- package/src/rui/commands/AgentResponseFormatter.js +7 -47
- package/src/rui/commands/parsers/CommandMapper.js +148 -0
- package/src/rui/commands/parsers/CommandValidator.js +228 -0
- package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
- package/src/rui/commands/parsers/TokenParser.js +69 -0
- package/src/rui/commands/parsers/tokenizer.js +153 -0
- package/src/utils/current-requirement-operations.js +50 -1
- package/src/utils/report-generator.js +18 -514
- package/src/utils/report-generators/analysis-generator.js +115 -0
- package/src/utils/report-generators/base-generator.js +141 -0
- package/src/utils/report-generators/compliance-generator.js +41 -0
- package/src/utils/report-generators/format-handlers.js +185 -0
- package/src/utils/report-generators/refactoring-generator.js +46 -0
- package/src/utils/report-generators/validation-generator.js +63 -0
- package/src/utils/requirement-enable-disable.js +265 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
- package/src/utils/requirement-helpers/requirement-mover.js +88 -1
- package/src/utils/requirement-helpers.js +5 -2
- package/src/utils/smoke-test-cli.js +45 -8
- package/src/utils/specification-enable-disable.js +122 -0
- package/src/utils/specification-helpers.js +30 -4
- package/src/utils/specification-migration.js +5 -5
- package/src/utils/test-comparator.js +118 -0
- package/src/utils/test-config.js +54 -0
- package/src/utils/test-executor.js +133 -0
- package/src/utils/test-parser.js +215 -0
- package/src/utils/test-runner-baseline.js +63 -0
- package/src/utils/test-runner-core.js +98 -0
- package/src/utils/test-runner-report.js +39 -0
- package/src/utils/test-runner-validation.js +71 -0
- package/src/utils/test-runner.js +11 -535
- package/src/validation/comparison-analyzer.js +333 -0
- package/src/validation/compliance-reporter-new.js +282 -0
- package/src/validation/compliance-reporter-refactored.js +344 -0
- package/src/validation/compliance-reporter.js +278 -591
- package/src/validation/compliance-utils.js +278 -0
- package/src/validation/html-generator.js +446 -0
- package/src/validation/metrics/category-calculator.js +137 -0
- package/src/validation/metrics/metrics-helpers.js +155 -0
- package/src/validation/metrics/overview-calculator.js +85 -0
- package/src/validation/metrics/overview-metrics.js +41 -0
- package/src/validation/metrics/quality-calculator.js +166 -0
- package/src/validation/metrics/size-calculator.js +69 -0
- package/src/validation/metrics-calculator.js +27 -551
|
@@ -632,6 +632,504 @@ class DirectLLMManager {
|
|
|
632
632
|
});
|
|
633
633
|
}
|
|
634
634
|
|
|
635
|
+
/**
|
|
636
|
+
* Call the VS Code Copilot CLI with a prompt
|
|
637
|
+
*/
|
|
638
|
+
async callVSCodeCopilotCLI(model, prompt, options = {}) {
|
|
639
|
+
const { onChunk, onComplete, onError } = options;
|
|
640
|
+
const { spawn } = require('child_process');
|
|
641
|
+
const os = require('os');
|
|
642
|
+
|
|
643
|
+
// Safe logging function to prevent EPIPE errors
|
|
644
|
+
const safeLog = (message) => {
|
|
645
|
+
try {
|
|
646
|
+
console.log(message);
|
|
647
|
+
} catch (err) {
|
|
648
|
+
// Ignore EPIPE errors that occur when stdout is closed
|
|
649
|
+
if (err.code === 'EPIPE') {
|
|
650
|
+
// Silently ignore - this happens during process shutdown
|
|
651
|
+
} else {
|
|
652
|
+
// Re-throw other errors
|
|
653
|
+
throw err;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
};
|
|
657
|
+
|
|
658
|
+
safeLog(`[VS CODE COPILOT CLI] Starting call with model: ${model}`);
|
|
659
|
+
safeLog(`[VS CODE COPILOT CLI] Prompt: ${prompt.substring(0, 100)}...`);
|
|
660
|
+
|
|
661
|
+
// Set up environment with authentication if available
|
|
662
|
+
const env = { ...process.env };
|
|
663
|
+
if (!env.HOME) env.HOME = os.homedir();
|
|
664
|
+
|
|
665
|
+
return new Promise((resolve) => {
|
|
666
|
+
let fullResponse = '';
|
|
667
|
+
let errorOutput = '';
|
|
668
|
+
|
|
669
|
+
// Non-interactive prompt invocation
|
|
670
|
+
// `copilot` uses `-p/--prompt` for non-interactive mode.
|
|
671
|
+
const args = ['-p', String(prompt), '-s', '--no-ask-user'];
|
|
672
|
+
const copilot = spawn('copilot', args, {
|
|
673
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
674
|
+
cwd: process.cwd(),
|
|
675
|
+
env
|
|
676
|
+
});
|
|
677
|
+
|
|
678
|
+
safeLog(`[VS CODE COPILOT CLI] Spawned process with PID: ${copilot.pid}`);
|
|
679
|
+
|
|
680
|
+
copilot.stdout.on('data', (data) => {
|
|
681
|
+
const text = data.toString();
|
|
682
|
+
fullResponse += text;
|
|
683
|
+
safeLog(`[VS CODE COPILOT CLI] STDOUT: ${text.substring(0, 200)}...`);
|
|
684
|
+
if (onChunk) onChunk(text);
|
|
685
|
+
});
|
|
686
|
+
|
|
687
|
+
copilot.stderr.on('data', (data) => {
|
|
688
|
+
const text = data.toString();
|
|
689
|
+
errorOutput += text;
|
|
690
|
+
safeLog(`[VS CODE COPILOT CLI] STDERR: ${text.substring(0, 200)}...`);
|
|
691
|
+
});
|
|
692
|
+
|
|
693
|
+
copilot.on('close', (code) => {
|
|
694
|
+
safeLog(`[VS CODE COPILOT CLI] Process closed with code: ${code}`);
|
|
695
|
+
safeLog(`[VS CODE COPILOT CLI] Full response length: ${fullResponse.length}`);
|
|
696
|
+
safeLog(`[VS CODE COPILOT CLI] Error output length: ${errorOutput.length}`);
|
|
697
|
+
safeLog(`[VS CODE COPILOT CLI] Error output: ${errorOutput}`);
|
|
698
|
+
|
|
699
|
+
if (code === 0) {
|
|
700
|
+
if (onComplete) onComplete(fullResponse);
|
|
701
|
+
resolve({ success: true, response: fullResponse });
|
|
702
|
+
} else {
|
|
703
|
+
// Check if this is an authentication error and provide a helpful message
|
|
704
|
+
const isAuthError = this.checkForAuthenticationError(errorOutput);
|
|
705
|
+
let error = `VS Code Copilot CLI exited with code ${code}: ${errorOutput}`;
|
|
706
|
+
|
|
707
|
+
if (isAuthError) {
|
|
708
|
+
error = `VS Code Copilot CLI requires authentication. Run 'copilot login' to authenticate with GitHub, or set COPILOT_GITHUB_TOKEN environment variable.`;
|
|
709
|
+
safeLog(`[VS CODE COPILOT CLI] Authentication error detected: ${error}`);
|
|
710
|
+
|
|
711
|
+
// If we had previously marked this provider as rate limited, clear that stale state.
|
|
712
|
+
// Auth/setup failures should never surface as rate limit in the GUI.
|
|
713
|
+
try {
|
|
714
|
+
if (this.providerManager && typeof this.providerManager.clearProviderRateLimits === 'function') {
|
|
715
|
+
this.providerManager.clearProviderRateLimits('vscode-copilot-cli');
|
|
716
|
+
}
|
|
717
|
+
} catch (_) { }
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
safeLog(`[VS CODE COPILOT CLI] Error: ${error}`);
|
|
721
|
+
if (onError) onError(error);
|
|
722
|
+
|
|
723
|
+
// Check if this is actually a rate limit error before calling detectAndSaveRateLimit
|
|
724
|
+
const isRateLimitError = this.checkForRateLimitError(errorOutput);
|
|
725
|
+
safeLog(`[VS CODE COPILOT CLI] Is rate limit error: ${isRateLimitError}`);
|
|
726
|
+
|
|
727
|
+
if (isRateLimitError) {
|
|
728
|
+
this.detectAndSaveRateLimit('vscode-copilot-cli', 'copilot-cli', errorOutput);
|
|
729
|
+
}
|
|
730
|
+
|
|
731
|
+
resolve({ success: false, error });
|
|
732
|
+
}
|
|
733
|
+
});
|
|
734
|
+
|
|
735
|
+
copilot.on('error', (err) => {
|
|
736
|
+
const error = `Failed to start VS Code Copilot CLI: ${err.message}`;
|
|
737
|
+
safeLog(`[VS CODE COPILOT CLI] Spawn error: ${error}`);
|
|
738
|
+
if (onError) onError(error);
|
|
739
|
+
resolve({ success: false, error });
|
|
740
|
+
});
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
/**
|
|
745
|
+
* Check if error output indicates an authentication error
|
|
746
|
+
*/
|
|
747
|
+
checkForAuthenticationError(errorOutput) {
|
|
748
|
+
const authIndicators = [
|
|
749
|
+
'No authentication information found',
|
|
750
|
+
'authentication information found',
|
|
751
|
+
'not authenticated',
|
|
752
|
+
'COPILOT_GITHUB_TOKEN',
|
|
753
|
+
'GH_TOKEN',
|
|
754
|
+
'GITHUB_TOKEN',
|
|
755
|
+
'/login',
|
|
756
|
+
'gh auth login',
|
|
757
|
+
'OAuth Token',
|
|
758
|
+
'Personal Access Token'
|
|
759
|
+
];
|
|
760
|
+
|
|
761
|
+
const isAuthError = authIndicators.some(indicator =>
|
|
762
|
+
errorOutput.includes(indicator)
|
|
763
|
+
);
|
|
764
|
+
|
|
765
|
+
console.log(`[AUTH CHECK] Error output: "${errorOutput}"`);
|
|
766
|
+
console.log(`[AUTH CHECK] Is authentication error: ${isAuthError}`);
|
|
767
|
+
|
|
768
|
+
return isAuthError;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
/**
|
|
772
|
+
* Check if error output indicates a genuine rate limit error
|
|
773
|
+
*/
|
|
774
|
+
checkForRateLimitError(errorOutput) {
|
|
775
|
+
// VS Code Copilot CLI specific rate limit indicators
|
|
776
|
+
const rateLimitIndicators = [
|
|
777
|
+
'rate limit',
|
|
778
|
+
'Rate limit',
|
|
779
|
+
'too many requests',
|
|
780
|
+
'Too many requests',
|
|
781
|
+
'429',
|
|
782
|
+
'quota exceeded',
|
|
783
|
+
'Quota exceeded',
|
|
784
|
+
'usage limit',
|
|
785
|
+
'Usage limit',
|
|
786
|
+
'limit reached',
|
|
787
|
+
'Limit reached',
|
|
788
|
+
'weekly limit',
|
|
789
|
+
'Weekly limit',
|
|
790
|
+
'daily limit',
|
|
791
|
+
'Daily limit'
|
|
792
|
+
];
|
|
793
|
+
|
|
794
|
+
// Exclude common authentication and setup errors that are NOT rate limits
|
|
795
|
+
const nonRateLimitIndicators = [
|
|
796
|
+
'authentication information found',
|
|
797
|
+
'Authentication information found',
|
|
798
|
+
'No authentication',
|
|
799
|
+
'not authenticated',
|
|
800
|
+
'COPILOT_GITHUB_TOKEN',
|
|
801
|
+
'GH_TOKEN',
|
|
802
|
+
'GITHUB_TOKEN',
|
|
803
|
+
'/login',
|
|
804
|
+
'gh auth login',
|
|
805
|
+
'OAuth Token',
|
|
806
|
+
'Personal Access Token',
|
|
807
|
+
'GitHub CLI'
|
|
808
|
+
];
|
|
809
|
+
|
|
810
|
+
// First check if it contains non-rate-limit indicators
|
|
811
|
+
const isNonRateLimit = nonRateLimitIndicators.some(indicator =>
|
|
812
|
+
errorOutput.includes(indicator)
|
|
813
|
+
);
|
|
814
|
+
|
|
815
|
+
if (isNonRateLimit) {
|
|
816
|
+
console.log(`[RATE LIMIT CHECK] Contains non-rate-limit indicators, not a rate limit`);
|
|
817
|
+
return false;
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
// Only consider it a rate limit if it contains specific rate limit indicators
|
|
821
|
+
const isRateLimit = rateLimitIndicators.some(indicator =>
|
|
822
|
+
errorOutput.includes(indicator)
|
|
823
|
+
);
|
|
824
|
+
|
|
825
|
+
console.log(`[RATE LIMIT CHECK] Error output: "${errorOutput}"`);
|
|
826
|
+
console.log(`[RATE LIMIT CHECK] Is rate limit: ${isRateLimit}`);
|
|
827
|
+
|
|
828
|
+
return isRateLimit;
|
|
829
|
+
}
|
|
830
|
+
|
|
831
|
+
/**
|
|
832
|
+
* Check if VS Code Copilot CLI is available AND authenticated
|
|
833
|
+
* @returns {Promise<{available: boolean, needsAuth: boolean, authMethod?: string}>}
|
|
834
|
+
*/
|
|
835
|
+
async isVSCodeCopilotCLIAvailable() {
|
|
836
|
+
const { spawn } = require('child_process');
|
|
837
|
+
const os = require('os');
|
|
838
|
+
|
|
839
|
+
// Safe logging function to prevent EPIPE errors
|
|
840
|
+
const safeLog = (message) => {
|
|
841
|
+
try {
|
|
842
|
+
console.log(message);
|
|
843
|
+
} catch (err) {
|
|
844
|
+
// Ignore EPIPE errors that occur when stdout is closed
|
|
845
|
+
if (err.code === 'EPIPE') {
|
|
846
|
+
// Silently ignore - this happens during process shutdown
|
|
847
|
+
} else {
|
|
848
|
+
// Re-throw other errors
|
|
849
|
+
throw err;
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
};
|
|
853
|
+
|
|
854
|
+
safeLog(`[VS CODE COPILOT CLI] Checking availability and authentication...`);
|
|
855
|
+
|
|
856
|
+
return new Promise((resolve) => {
|
|
857
|
+
// First check if the CLI is installed
|
|
858
|
+
const baseEnv = { ...process.env };
|
|
859
|
+
if (!baseEnv.HOME) baseEnv.HOME = os.homedir();
|
|
860
|
+
|
|
861
|
+
const versionProc = spawn('copilot', ['--version'], { stdio: ['ignore', 'pipe', 'pipe'], env: baseEnv });
|
|
862
|
+
|
|
863
|
+
let versionStdout = '';
|
|
864
|
+
let versionStderr = '';
|
|
865
|
+
let versionTimeout;
|
|
866
|
+
|
|
867
|
+
versionProc.stdout.on('data', (data) => {
|
|
868
|
+
versionStdout += data.toString();
|
|
869
|
+
safeLog(`[VS CODE COPILOT CLI] Version check STDOUT: ${data.toString().trim()}`);
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
versionProc.stderr.on('data', (data) => {
|
|
873
|
+
versionStderr += data.toString();
|
|
874
|
+
safeLog(`[VS CODE COPILOT CLI] Version check STDERR: ${data.toString().trim()}`);
|
|
875
|
+
});
|
|
876
|
+
|
|
877
|
+
versionProc.on('close', (versionCode) => {
|
|
878
|
+
clearTimeout(versionTimeout);
|
|
879
|
+
safeLog(`[VS CODE COPILOT CLI] Version check exited with code: ${versionCode}`);
|
|
880
|
+
|
|
881
|
+
if (versionCode !== 0) {
|
|
882
|
+
safeLog(`[VS CODE COPILOT CLI] Not installed or not in PATH`);
|
|
883
|
+
resolve({ available: false, needsAuth: false });
|
|
884
|
+
return;
|
|
885
|
+
}
|
|
886
|
+
|
|
887
|
+
// CLI is installed, now check if it's authenticated using a short non-interactive prompt.
|
|
888
|
+
// Note: This CLI does not support `copilot whoami`, and GitHub CLI (`gh`) may not be installed.
|
|
889
|
+
// We keep this probe short and interpret device-flow output as needsAuth.
|
|
890
|
+
safeLog(`[VS CODE COPILOT CLI] CLI is installed, checking authentication (non-interactive probe)...`);
|
|
891
|
+
|
|
892
|
+
const probeArgs = ['-p', 'Reply with OK', '-s', '--no-ask-user'];
|
|
893
|
+
const probeProc = spawn('copilot', probeArgs, { stdio: ['ignore', 'pipe', 'pipe'], env: baseEnv });
|
|
894
|
+
|
|
895
|
+
let probeStdout = '';
|
|
896
|
+
let probeStderr = '';
|
|
897
|
+
let probeFinished = false;
|
|
898
|
+
const finishProbe = (code) => {
|
|
899
|
+
if (probeFinished) return;
|
|
900
|
+
probeFinished = true;
|
|
901
|
+
const out = (probeStdout || '').trim();
|
|
902
|
+
const err = (probeStderr || '').trim();
|
|
903
|
+
safeLog(`[VS CODE COPILOT CLI] Probe exited with code: ${code}`);
|
|
904
|
+
if (out) safeLog(`[VS CODE COPILOT CLI] Probe STDOUT: ${out.substring(0, 200)}`);
|
|
905
|
+
if (err) safeLog(`[VS CODE COPILOT CLI] Probe STDERR: ${err.substring(0, 200)}`);
|
|
906
|
+
|
|
907
|
+
// For copilot CLI, we consider it working if we get "OK" output even with exit code 1
|
|
908
|
+
// The --no-ask-user flag seems to cause exit code 1 but still provides the response
|
|
909
|
+
const isWorking = (code === 0 && out) || (code === 1 && out.trim() === 'OK');
|
|
910
|
+
|
|
911
|
+
if (isWorking) {
|
|
912
|
+
resolve({ available: true, needsAuth: false, authMethod: 'existing' });
|
|
913
|
+
return;
|
|
914
|
+
}
|
|
915
|
+
|
|
916
|
+
const combined = `${out}\n${err}`;
|
|
917
|
+
|
|
918
|
+
// Check for rate limit first
|
|
919
|
+
const isRateLimited =
|
|
920
|
+
combined.includes('402 You have no quota') ||
|
|
921
|
+
combined.includes('quota') ||
|
|
922
|
+
combined.includes('rate limit') ||
|
|
923
|
+
combined.includes('Rate limit');
|
|
924
|
+
|
|
925
|
+
if (isRateLimited) {
|
|
926
|
+
safeLog(`[VS CODE COPILOT CLI] Detected rate limit error`);
|
|
927
|
+
resolve({ available: true, needsAuth: false, authMethod: 'existing', rateLimited: true });
|
|
928
|
+
return;
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
const needsAuth =
|
|
932
|
+
combined.includes('copilot login') ||
|
|
933
|
+
combined.includes('Authenticate with Copilot') ||
|
|
934
|
+
combined.includes('github.com/login/device') ||
|
|
935
|
+
combined.includes('To authenticate') ||
|
|
936
|
+
combined.includes('Waiting for authorization');
|
|
937
|
+
|
|
938
|
+
resolve({ available: true, needsAuth: Boolean(needsAuth), authMethod: needsAuth ? 'manual' : 'unknown' });
|
|
939
|
+
};
|
|
940
|
+
|
|
941
|
+
probeProc.stdout.on('data', (data) => { probeStdout += data.toString(); });
|
|
942
|
+
probeProc.stderr.on('data', (data) => { probeStderr += data.toString(); });
|
|
943
|
+
probeProc.on('close', (code) => finishProbe(code));
|
|
944
|
+
probeProc.on('error', () => finishProbe(1));
|
|
945
|
+
setTimeout(() => {
|
|
946
|
+
try { probeProc.kill(); } catch (_) { }
|
|
947
|
+
finishProbe(1);
|
|
948
|
+
}, 8000);
|
|
949
|
+
});
|
|
950
|
+
|
|
951
|
+
versionProc.on('error', (err) => {
|
|
952
|
+
clearTimeout(versionTimeout);
|
|
953
|
+
safeLog(`[VS CODE COPILOT CLI] Version check error: ${err.message}`);
|
|
954
|
+
resolve({ available: false, needsAuth: false });
|
|
955
|
+
});
|
|
956
|
+
|
|
957
|
+
versionTimeout = setTimeout(() => {
|
|
958
|
+
safeLog(`[VS CODE COPILOT CLI] Version check timeout, killing process`);
|
|
959
|
+
versionProc.kill();
|
|
960
|
+
resolve({ available: false, needsAuth: false });
|
|
961
|
+
}, 5000);
|
|
962
|
+
});
|
|
963
|
+
}
|
|
964
|
+
|
|
965
|
+
/**
|
|
966
|
+
* Attempt to authenticate VS Code Copilot CLI automatically
|
|
967
|
+
* @returns {Promise<{success: boolean, method: string, reason?: string}>}
|
|
968
|
+
*/
|
|
969
|
+
async attemptAutoAuthentication() {
|
|
970
|
+
const { spawn } = require('child_process');
|
|
971
|
+
|
|
972
|
+
// Safe logging function to prevent EPIPE errors
|
|
973
|
+
const safeLog = (message) => {
|
|
974
|
+
try {
|
|
975
|
+
console.log(message);
|
|
976
|
+
} catch (err) {
|
|
977
|
+
// Ignore EPIPE errors that occur when stdout is closed
|
|
978
|
+
if (err.code === 'EPIPE') {
|
|
979
|
+
// Silently ignore - this happens during process shutdown
|
|
980
|
+
} else {
|
|
981
|
+
// Re-throw other errors
|
|
982
|
+
throw err;
|
|
983
|
+
}
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
|
|
987
|
+
safeLog(`[VS CODE COPILOT CLI] Attempting auto-authentication...`);
|
|
988
|
+
|
|
989
|
+
// Method 1: Check if GitHub CLI is authenticated and get token
|
|
990
|
+
try {
|
|
991
|
+
safeLog(`[VS CODE COPILOT CLI] Method 1: Checking GitHub CLI authentication...`);
|
|
992
|
+
const ghAuth = spawn('gh', ['auth', 'status'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
993
|
+
|
|
994
|
+
let ghStdout = '';
|
|
995
|
+
let ghStderr = '';
|
|
996
|
+
|
|
997
|
+
ghAuth.stdout.on('data', (data) => {
|
|
998
|
+
ghStdout += data.toString();
|
|
999
|
+
});
|
|
1000
|
+
|
|
1001
|
+
ghAuth.stderr.on('data', (data) => {
|
|
1002
|
+
ghStderr += data.toString();
|
|
1003
|
+
});
|
|
1004
|
+
|
|
1005
|
+
const ghResult = await new Promise((resolve) => {
|
|
1006
|
+
ghAuth.on('close', (code) => {
|
|
1007
|
+
resolve({ code, stdout: ghStdout, stderr: ghStderr });
|
|
1008
|
+
});
|
|
1009
|
+
|
|
1010
|
+
ghAuth.on('error', () => {
|
|
1011
|
+
resolve({ code: -1, stdout: '', stderr: 'gh command not found' });
|
|
1012
|
+
});
|
|
1013
|
+
|
|
1014
|
+
setTimeout(() => { ghAuth.kill(); resolve({ code: -1, stdout: '', stderr: 'timeout' }); }, 5000);
|
|
1015
|
+
});
|
|
1016
|
+
|
|
1017
|
+
if (ghResult.code === 0 && ghResult.stdout.includes('Logged in to')) {
|
|
1018
|
+
safeLog(`[VS CODE COPILOT CLI] GitHub CLI is authenticated, getting token...`);
|
|
1019
|
+
|
|
1020
|
+
// Get token from GitHub CLI
|
|
1021
|
+
const ghToken = spawn('gh', ['auth', 'token'], { stdio: ['ignore', 'pipe', 'pipe'] });
|
|
1022
|
+
|
|
1023
|
+
let tokenStdout = '';
|
|
1024
|
+
let tokenStderr = '';
|
|
1025
|
+
|
|
1026
|
+
ghToken.stdout.on('data', (data) => {
|
|
1027
|
+
tokenStdout += data.toString();
|
|
1028
|
+
});
|
|
1029
|
+
|
|
1030
|
+
ghToken.stderr.on('data', (data) => {
|
|
1031
|
+
tokenStderr += data.toString();
|
|
1032
|
+
});
|
|
1033
|
+
|
|
1034
|
+
const tokenResult = await new Promise((resolve) => {
|
|
1035
|
+
ghToken.on('close', (code) => {
|
|
1036
|
+
resolve({ code, stdout: tokenStdout, stderr: tokenStderr });
|
|
1037
|
+
});
|
|
1038
|
+
|
|
1039
|
+
ghToken.on('error', () => {
|
|
1040
|
+
resolve({ code: 1, stdout: '', stderr: 'Failed to spawn gh auth token' });
|
|
1041
|
+
});
|
|
1042
|
+
|
|
1043
|
+
setTimeout(() => {
|
|
1044
|
+
try { ghToken.kill(); } catch (_) { }
|
|
1045
|
+
resolve({ code: 1, stdout: '', stderr: 'Timeout getting token' });
|
|
1046
|
+
}, 5000);
|
|
1047
|
+
});
|
|
1048
|
+
|
|
1049
|
+
if (tokenResult.code === 0 && tokenResult.stdout) {
|
|
1050
|
+
safeLog(`[VS CODE COPILOT CLI] Got token from GitHub CLI, testing with Copilot CLI...`);
|
|
1051
|
+
|
|
1052
|
+
// Test the token with Copilot CLI
|
|
1053
|
+
const testResult = await this.testTokenWithCopilot(tokenResult.stdout);
|
|
1054
|
+
if (testResult.success) {
|
|
1055
|
+
return { success: true, method: 'github-cli' };
|
|
1056
|
+
} else {
|
|
1057
|
+
safeLog(`[VS CODE COPILOT CLI] GitHub CLI token failed with Copilot: ${testResult.reason}`);
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
}
|
|
1061
|
+
} catch (error) {
|
|
1062
|
+
safeLog(`[VS CODE COPILOT CLI] GitHub CLI method failed: ${error.message}`);
|
|
1063
|
+
}
|
|
1064
|
+
|
|
1065
|
+
// Method 2: Check environment variables
|
|
1066
|
+
safeLog(`[VS CODE COPILOT CLI] Method 2: Checking environment variables...`);
|
|
1067
|
+
const envVars = ['COPILOT_GITHUB_TOKEN', 'GH_TOKEN', 'GITHUB_TOKEN'];
|
|
1068
|
+
|
|
1069
|
+
for (const envVar of envVars) {
|
|
1070
|
+
const token = process.env[envVar];
|
|
1071
|
+
if (token) {
|
|
1072
|
+
safeLog(`[VS CODE COPILOT CLI] Found ${envVar}, testing with Copilot CLI...`);
|
|
1073
|
+
|
|
1074
|
+
const testResult = await this.testTokenWithCopilot(token);
|
|
1075
|
+
if (testResult.success) {
|
|
1076
|
+
return { success: true, method: `env-${envVar}` };
|
|
1077
|
+
} else {
|
|
1078
|
+
safeLog(`[VS CODE COPILOT CLI] ${envVar} token failed with Copilot: ${testResult.reason}`);
|
|
1079
|
+
}
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
|
|
1083
|
+
safeLog(`[VS CODE COPILOT CLI] All auto-authentication methods failed`);
|
|
1084
|
+
return { success: false, method: 'none', reason: 'No valid authentication found' };
|
|
1085
|
+
}
|
|
1086
|
+
|
|
1087
|
+
/**
|
|
1088
|
+
* Test if a token works with VS Code Copilot CLI
|
|
1089
|
+
* @param {string} token - GitHub token to test
|
|
1090
|
+
* @returns {Promise<{success: boolean, reason?: string}>}
|
|
1091
|
+
*/
|
|
1092
|
+
async testTokenWithCopilot(token) {
|
|
1093
|
+
const { spawn } = require('child_process');
|
|
1094
|
+
|
|
1095
|
+
return new Promise((resolve) => {
|
|
1096
|
+
const env = { ...process.env, COPILOT_GITHUB_TOKEN: token };
|
|
1097
|
+
|
|
1098
|
+
const testProc = spawn('copilot', ['-p', 'test', '-s'], {
|
|
1099
|
+
stdio: ['ignore', 'pipe', 'pipe'],
|
|
1100
|
+
env,
|
|
1101
|
+
timeout: 5000
|
|
1102
|
+
});
|
|
1103
|
+
|
|
1104
|
+
let stderr = '';
|
|
1105
|
+
|
|
1106
|
+
testProc.stderr.on('data', (data) => {
|
|
1107
|
+
stderr += data.toString();
|
|
1108
|
+
});
|
|
1109
|
+
|
|
1110
|
+
testProc.on('close', (code) => {
|
|
1111
|
+
const needsAuth = stderr.includes('No authentication information found') ||
|
|
1112
|
+
stderr.includes('authentication information found') ||
|
|
1113
|
+
stderr.includes('not authenticated');
|
|
1114
|
+
|
|
1115
|
+
if (needsAuth) {
|
|
1116
|
+
resolve({ success: false, reason: 'Token not valid for Copilot CLI' });
|
|
1117
|
+
} else {
|
|
1118
|
+
resolve({ success: true });
|
|
1119
|
+
}
|
|
1120
|
+
});
|
|
1121
|
+
|
|
1122
|
+
testProc.on('error', (err) => {
|
|
1123
|
+
resolve({ success: false, reason: err.message });
|
|
1124
|
+
});
|
|
1125
|
+
|
|
1126
|
+
setTimeout(() => {
|
|
1127
|
+
testProc.kill();
|
|
1128
|
+
resolve({ success: false, reason: 'timeout' });
|
|
1129
|
+
}, 5000);
|
|
1130
|
+
});
|
|
1131
|
+
}
|
|
1132
|
+
|
|
635
1133
|
/**
|
|
636
1134
|
* Call any LLM provider
|
|
637
1135
|
* @param {Object} config - Provider configuration
|
|
@@ -686,6 +1184,9 @@ class DirectLLMManager {
|
|
|
686
1184
|
case 'opencode':
|
|
687
1185
|
result = await this.callOpenCode(currentModel, prompt, options);
|
|
688
1186
|
break;
|
|
1187
|
+
case 'vscode-copilot-cli':
|
|
1188
|
+
result = await this.callVSCodeCopilotCLI(currentModel, prompt, options);
|
|
1189
|
+
break;
|
|
689
1190
|
default:
|
|
690
1191
|
return { success: false, error: `Unknown provider: ${provider}` };
|
|
691
1192
|
}
|